Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit efc3f16b authored by Brian C. Young's avatar Brian C. Young
Browse files

Add "Unlocked device required" parameter to keys

Add a keymaster parameter for keys that should be inaccessible when
the device screen is locked. "Locked" here is a state where the device
can be used or accessed without any further trust factor such as a
PIN, password, fingerprint, or trusted face or voice.

This parameter is added to the Java keystore interface for key
creation and import, as well as enums specified by and for the native
keystore process.

Test: CTS tests in I8a5affd1eaed176756175158e3057e44934fffed

Bug: 67752510

Change-Id: I314b848f6971d1849a7a6347d52e41d9604639ae
parent 5f76688c
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -38445,6 +38445,7 @@ package android.security.keystore {
    method public boolean isRandomizedEncryptionRequired();
    method public boolean isStrongBoxBacked();
    method public boolean isTrustedUserPresenceRequired();
    method public boolean isUnlockedDeviceRequired();
    method public boolean isUserAuthenticationRequired();
    method public boolean isUserAuthenticationValidWhileOnBody();
    method public boolean isUserConfirmationRequired();
@@ -38472,6 +38473,7 @@ package android.security.keystore {
    method public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean);
    method public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...);
    method public android.security.keystore.KeyGenParameterSpec.Builder setTrustedUserPresenceRequired(boolean);
    method public android.security.keystore.KeyGenParameterSpec.Builder setUnlockedDeviceRequired(boolean);
    method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationRequired(boolean);
    method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidWhileOnBody(boolean);
    method public android.security.keystore.KeyGenParameterSpec.Builder setUserAuthenticationValidityDurationSeconds(int);
@@ -38563,6 +38565,8 @@ package android.security.keystore {
    method public boolean isDigestsSpecified();
    method public boolean isInvalidatedByBiometricEnrollment();
    method public boolean isRandomizedEncryptionRequired();
    method public boolean isTrustedUserPresenceRequired();
    method public boolean isUnlockedDeviceRequired();
    method public boolean isUserAuthenticationRequired();
    method public boolean isUserAuthenticationValidWhileOnBody();
    method public boolean isUserConfirmationRequired();
@@ -38581,6 +38585,8 @@ package android.security.keystore {
    method public android.security.keystore.KeyProtection.Builder setKeyValidityStart(java.util.Date);
    method public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean);
    method public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...);
    method public android.security.keystore.KeyProtection.Builder setTrustedUserPresenceRequired(boolean);
    method public android.security.keystore.KeyProtection.Builder setUnlockedDeviceRequired(boolean);
    method public android.security.keystore.KeyProtection.Builder setUserAuthenticationRequired(boolean);
    method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidWhileOnBody(boolean);
    method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(int);
+3 −0
Original line number Diff line number Diff line
@@ -75,6 +75,7 @@ public final class KeymasterDefs {
    public static final int KM_TAG_ALLOW_WHILE_ON_BODY = KM_BOOL | 506;
    public static final int KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED = KM_BOOL | 507;
    public static final int KM_TAG_TRUSTED_CONFIRMATION_REQUIRED = KM_BOOL | 508;
    public static final int KM_TAG_UNLOCKED_DEVICE_REQUIRED = KM_BOOL | 509;

    public static final int KM_TAG_ALL_APPLICATIONS = KM_BOOL | 600;
    public static final int KM_TAG_APPLICATION_ID = KM_BYTES | 601;
@@ -216,6 +217,7 @@ public final class KeymasterDefs {
    public static final int KM_ERROR_MISSING_MIN_MAC_LENGTH = -58;
    public static final int KM_ERROR_UNSUPPORTED_MIN_MAC_LENGTH = -59;
    public static final int KM_ERROR_CANNOT_ATTEST_IDS = -66;
    public static final int KM_ERROR_DEVICE_LOCKED = -72;
    public static final int KM_ERROR_UNIMPLEMENTED = -100;
    public static final int KM_ERROR_VERSION_MISMATCH = -101;
    public static final int KM_ERROR_UNKNOWN_ERROR = -1000;
@@ -262,6 +264,7 @@ public final class KeymasterDefs {
        sErrorCodeToString.put(KM_ERROR_INVALID_MAC_LENGTH,
                "Invalid MAC or authentication tag length");
        sErrorCodeToString.put(KM_ERROR_CANNOT_ATTEST_IDS, "Unable to attest device ids");
        sErrorCodeToString.put(KM_ERROR_DEVICE_LOCKED, "Device locked");
        sErrorCodeToString.put(KM_ERROR_UNIMPLEMENTED, "Not implemented");
        sErrorCodeToString.put(KM_ERROR_UNKNOWN_ERROR, "Unknown error");
    }
+13 −10
Original line number Diff line number Diff line
@@ -545,7 +545,9 @@ public class KeyStore {
        try {
            args = args != null ? args : new KeymasterArguments();
            entropy = entropy != null ? entropy : new byte[0];
            return mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
            OperationResult res = mBinder.begin(getToken(), alias, purpose, pruneable, args, entropy, uid);
            // This result is -26 (KEY_USER_NOT_AUTHENTICATED) but why??
            return res;
        } catch (RemoteException e) {
            Log.w(TAG, "Cannot connect to keystore", e);
            return null;
@@ -563,7 +565,8 @@ public class KeyStore {
        try {
            arguments = arguments != null ? arguments : new KeymasterArguments();
            input = input != null ? input : new byte[0];
            return mBinder.update(token, arguments, input);
            OperationResult res = mBinder.update(token, arguments, input);
            return res;
        } catch (RemoteException e) {
            Log.w(TAG, "Cannot connect to keystore", e);
            return null;
@@ -618,9 +621,9 @@ public class KeyStore {
     * @return {@code KeyStore.NO_ERROR} on success, otherwise an error value corresponding to
     * a {@code KeymasterDefs.KM_ERROR_} value or {@code KeyStore} ResponseCode.
     */
    public int addAuthToken(byte[] authToken) {
    public int addAuthToken(byte[] authToken, int userId) {
        try {
            return mBinder.addAuthToken(authToken);
            return mBinder.addAuthToken(authToken, userId);
        } catch (RemoteException e) {
            Log.w(TAG, "Cannot connect to keystore", e);
            return SYSTEM_ERROR;
@@ -832,14 +835,14 @@ public class KeyStore {
    public InvalidKeyException getInvalidKeyException(
            String keystoreKeyAlias, int uid, KeyStoreException e) {
        switch (e.getErrorCode()) {
            case LOCKED:
            case LOCKED: // 2
                return new UserNotAuthenticatedException();
            case KeymasterDefs.KM_ERROR_KEY_EXPIRED:
            case KeymasterDefs.KM_ERROR_KEY_EXPIRED: // -25
                return new KeyExpiredException();
            case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID:
            case KeymasterDefs.KM_ERROR_KEY_NOT_YET_VALID: // -2
                return new KeyNotYetValidException();
            case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED:
            case OP_AUTH_NEEDED:
            case KeymasterDefs.KM_ERROR_KEY_USER_NOT_AUTHENTICATED: // -26
            case OP_AUTH_NEEDED: // 15
            {
                // We now need to determine whether the key/operation can become usable if user
                // authentication is performed, or whether it can never become usable again.
@@ -879,7 +882,7 @@ public class KeyStore {
                // None of the key's SIDs can ever be authenticated
                return new KeyPermanentlyInvalidatedException();
            }
            case UNINITIALIZED:
            case UNINITIALIZED: // 3
                return new KeyPermanentlyInvalidatedException();
            default:
                return new InvalidKeyException("Keystore operation failed", e);
+2 −17
Original line number Diff line number Diff line
@@ -243,13 +243,7 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
                // Check that user authentication related parameters are acceptable. This method
                // will throw an IllegalStateException if there are issues (e.g., secure lock screen
                // not set up).
                KeymasterUtils.addUserAuthArgs(new KeymasterArguments(),
                        spec.isUserAuthenticationRequired(),
                        spec.getUserAuthenticationValidityDurationSeconds(),
                        spec.isUserAuthenticationValidWhileOnBody(),
                        spec.isInvalidatedByBiometricEnrollment(),
                        GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
                        spec.isUserConfirmationRequired());
                KeymasterUtils.addUserAuthArgs(new KeymasterArguments(), spec);
            } catch (IllegalStateException | IllegalArgumentException e) {
                throw new InvalidAlgorithmParameterException(e);
            }
@@ -285,16 +279,7 @@ public abstract class AndroidKeyStoreKeyGeneratorSpi extends KeyGeneratorSpi {
        args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes);
        args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterPaddings);
        args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
        KeymasterUtils.addUserAuthArgs(args,
                spec.isUserAuthenticationRequired(),
                spec.getUserAuthenticationValidityDurationSeconds(),
                spec.isUserAuthenticationValidWhileOnBody(),
                spec.isInvalidatedByBiometricEnrollment(),
                GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
                spec.isUserConfirmationRequired());
        if (spec.isTrustedUserPresenceRequired()) {
            args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED);
        }
        KeymasterUtils.addUserAuthArgs(args, spec);
        KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(
                args,
                mKeymasterAlgorithm,
+2 −14
Original line number Diff line number Diff line
@@ -344,13 +344,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
                // Check that user authentication related parameters are acceptable. This method
                // will throw an IllegalStateException if there are issues (e.g., secure lock screen
                // not set up).
                KeymasterUtils.addUserAuthArgs(new KeymasterArguments(),
                        mSpec.isUserAuthenticationRequired(),
                        mSpec.getUserAuthenticationValidityDurationSeconds(),
                        mSpec.isUserAuthenticationValidWhileOnBody(),
                        mSpec.isInvalidatedByBiometricEnrollment(),
                        GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
                        mSpec.isUserConfirmationRequired());
                KeymasterUtils.addUserAuthArgs(new KeymasterArguments(), mSpec);
            } catch (IllegalArgumentException | IllegalStateException e) {
                throw new InvalidAlgorithmParameterException(e);
            }
@@ -541,13 +535,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
        args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterSignaturePaddings);
        args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);

        KeymasterUtils.addUserAuthArgs(args,
                mSpec.isUserAuthenticationRequired(),
                mSpec.getUserAuthenticationValidityDurationSeconds(),
                mSpec.isUserAuthenticationValidWhileOnBody(),
                mSpec.isInvalidatedByBiometricEnrollment(),
                GateKeeper.INVALID_SECURE_USER_ID /* boundToSpecificSecureUserId */,
                mSpec.isUserConfirmationRequired());
        KeymasterUtils.addUserAuthArgs(args, mSpec);
        args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, mSpec.getKeyValidityStart());
        args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME,
                mSpec.getKeyValidityForOriginationEnd());
Loading