Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What Is the Difference Between isInsideSecureHardware() and isUserAuthenticationRequirementEnforcedBySecureHardware()?

Android 6.0+ has a KeyInfo class to get info on a key saved in the AndroidKeyStore. On the KeyInfo class, we have isInsideSecureHardware() and isUserAuthenticationRequirementEnforcedBySecureHardware() methods. We also have isUserAuthenticationRequired(). The documentation, as usual, sucks.

Based on method names and the (limited) documentation, it would seem as though isUserAuthenticationRequirementEnforcedBySecureHardware() is simply a logical AND of isInsideSecureHardware() and isUserAuthenticationRequired().

Is there something more to it than that? If so, what does it mean for the user authentication requirement to be enforced by secure hardware, beyond just the key being in secure hardware?

like image 475
CommonsWare Avatar asked Jan 29 '18 23:01

CommonsWare


People also ask

What is Keymaster Hal?

The Android Keystore API and the underlying Keymaster HAL provide a basic but adequate set of cryptographic primitives to allow the implementation of protocols using access-controlled, hardware-backed keys.

What is Android StrongBox?

StrongBox is an implementation of the Keymaster HAL that resides in a hardware security module. It is an important security enhancement for Android devices and paved the way for us to consider features that were previously not possible.

What is hardware-backed storage?

Most of the latest devices now have a secure hardware storage which stores encryption keys which can be used by apps, Providing more security by making the keys unavailable for extraction. That is, once keys are in a hardware-backed even the OS kernel cannot access this key.


2 Answers

The method isUserAuthenticationRequirementEnforcedBySecureHardware() is not a logical AND of isInsideSecureHardware() and isUserAuthenticationRequired().

But if you dig into the code, you can see that it is a logical AND of 3 things:

  1. isUserAuthenticationRequired()
  2. 0 SW Enforced User Authenticators
  3. 1 or more HW Enforced User Authenticators

Snippet of code:

boolean userAuthenticationRequirementEnforcedBySecureHardware = (userAuthenticationRequired)
                && (keymasterHwEnforcedUserAuthenticators != 0)
                && (keymasterSwEnforcedUserAuthenticators == 0);

The difference is not whether the key is secure in hardware, but if user authentication is backed by hardware, not software. For most, if not all devices with fingerprint readers, user authentication in secure hardware means the TEE would contain two things that interact with the Keymaster Trusted App:

  1. Gatekeeper Trusted App for pin/password/pattern
  2. Fingerprint Trusted App for fingerprint authentication

Example scenarios:

  • isUserAuthenticationRequirementEnforcedBySecureHardware() could return false if both isInsideSecureHardware() and isUserAuthenticationRequired() return true, but the user authentication is done in SW and not in the TEE. (not likely)
  • isUserAuthenticationRequirementEnforcedBySecureHardware() could return true if isInsideSecureHardware() returns false (key is not supported in device's secure hardware) and isUserAuthenticationRequired() returns true with the user authentication done in HW. (possible)
like image 168
Steve Miskovetz Avatar answered Oct 12 '22 20:10

Steve Miskovetz


isUserAuthenticationRequirementEnforcedBySecureHardware() is simply a logical AND of isInsideSecureHardware() and isUserAuthenticationRequired().

I think that's not true (see methods below) it comes via the key from KeyChain.

Is there something more to it than that?

KeyInfo.java is a container class for key info from a KeyChain. Whether the key is bound to the secure hardware is known only once the key has been imported.

To find out, use:

{
    PrivateKey key = ...; // private key from KeyChain

    KeyFactory keyFactory =
        KeyFactory.getInstance(key.getAlgorithm(), "AndroidKeyStore");
    KeyInfo keyInfo = keyFactory.getKeySpec(key, KeyInfo.class);
    if (keyInfo.isInsideSecureHardware()) 
    {
        // The key is bound to the secure hardware of this Android
    }
}

From KeyInfo.java:

/**
 * Returns {@code true} if the key resides inside secure hardware (e.g., Trusted Execution
 * Environment (TEE) or Secure Element (SE)). Key material of such keys is available in
 * plaintext only inside the secure hardware and is not exposed outside of it.
 */
public boolean isInsideSecureHardware() 
{
    return mInsideSecureHardware;
}

/**
 * Returns {@code true} if the requirement that this key can only be used if the user has been
 * authenticated is enforced by secure hardware (e.g., Trusted Execution Environment (TEE) or
 * Secure Element (SE)).
 *
 * @see #isUserAuthenticationRequired()
 */
public boolean isUserAuthenticationRequirementEnforcedBySecureHardware() 
{
    return mUserAuthenticationRequirementEnforcedBySecureHardware;
}

/**
 * Returns {@code true} if the key is authorized to be used only if the user has been
 * authenticated.
 *
 * <p>This authorization applies only to secret key and private key operations. Public key
 * operations are not restricted.
 *
 * @see #getUserAuthenticationValidityDurationSeconds()
 * @see KeyGenParameterSpec.Builder#setUserAuthenticationRequired(boolean)
 * @see KeyProtection.Builder#setUserAuthenticationRequired(boolean)
 */
public boolean isUserAuthenticationRequired() 
{
    return mUserAuthenticationRequired;
}

See also: KeyStore.java

like image 32
Jon Goodwin Avatar answered Oct 12 '22 19:10

Jon Goodwin