diff options
8 files changed, 95 insertions, 64 deletions
diff --git a/api/current.txt b/api/current.txt index 69d9a9e4c73c..f41a92094faa 100644 --- a/api/current.txt +++ b/api/current.txt @@ -39384,6 +39384,7 @@ package android.security.keystore { method public boolean isDigestsSpecified(); method public boolean isInvalidatedByBiometricEnrollment(); method public boolean isRandomizedEncryptionRequired(); + method public boolean isTrustedUserPresenceRequired(); method public boolean isUserAuthenticationRequired(); method public boolean isUserAuthenticationValidWhileOnBody(); method public boolean isUserConfirmationRequired(); @@ -39402,6 +39403,7 @@ 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 setUserAuthenticationRequired(boolean); method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidWhileOnBody(boolean); method public android.security.keystore.KeyProtection.Builder setUserAuthenticationValidityDurationSeconds(int); diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java index 09b3b9b523b4..419eb24e1cc1 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyGeneratorSpi.java @@ -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, diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java index e33e3cd4e92b..d68a33de2c61 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -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()); diff --git a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java index 05cc74a0bec9..fc86ca0443b0 100644 --- a/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore/AndroidKeyStoreSpi.java @@ -497,13 +497,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { importArgs.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterEncryptionPaddings); importArgs.addEnums(KeymasterDefs.KM_TAG_PADDING, KeyProperties.SignaturePadding.allToKeymaster(spec.getSignaturePaddings())); - KeymasterUtils.addUserAuthArgs(importArgs, - spec.isUserAuthenticationRequired(), - spec.getUserAuthenticationValidityDurationSeconds(), - spec.isUserAuthenticationValidWhileOnBody(), - spec.isInvalidatedByBiometricEnrollment(), - spec.getBoundToSpecificSecureUserId(), - spec.isUserConfirmationRequired()); + KeymasterUtils.addUserAuthArgs(importArgs, spec); importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, spec.getKeyValidityStart()); importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, @@ -700,13 +694,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { int[] keymasterPaddings = KeyProperties.EncryptionPadding.allToKeymaster( params.getEncryptionPaddings()); args.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings); - KeymasterUtils.addUserAuthArgs(args, - params.isUserAuthenticationRequired(), - params.getUserAuthenticationValidityDurationSeconds(), - params.isUserAuthenticationValidWhileOnBody(), - params.isInvalidatedByBiometricEnrollment(), - params.getBoundToSpecificSecureUserId(), - params.isUserConfirmationRequired()); + KeymasterUtils.addUserAuthArgs(args, params); KeymasterUtils.addMinMacLengthAuthorizationIfNecessary( args, keymasterAlgorithm, diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java index da23c70f58bb..4b9f3c803481 100644 --- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.KeyguardManager; import android.hardware.fingerprint.FingerprintManager; +import android.security.GateKeeper; import android.security.KeyStore; import android.text.TextUtils; @@ -232,7 +233,7 @@ import javax.security.auth.x500.X500Principal; * key = (SecretKey) keyStore.getKey("key2", null); * }</pre> */ -public final class KeyGenParameterSpec implements AlgorithmParameterSpec { +public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAuthArgs { private static final X500Principal DEFAULT_CERT_SUBJECT = new X500Principal("CN=fake"); private static final BigInteger DEFAULT_CERT_SERIAL_NUMBER = new BigInteger("1"); @@ -669,6 +670,13 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec { } /** + * @hide + */ + public long getBoundToSpecificSecureUserId() { + return GateKeeper.INVALID_SECURE_USER_ID; + } + + /** * Builder of {@link KeyGenParameterSpec} instances. */ public final static class Builder { diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java index b5b328192f21..95eeec704847 100644 --- a/keystore/java/android/security/keystore/KeyProtection.java +++ b/keystore/java/android/security/keystore/KeyProtection.java @@ -212,7 +212,7 @@ import javax.crypto.Mac; * ... * }</pre> */ -public final class KeyProtection implements ProtectionParameter { +public final class KeyProtection implements ProtectionParameter, UserAuthArgs { private final Date mKeyValidityStart; private final Date mKeyValidityForOriginationEnd; private final Date mKeyValidityForConsumptionEnd; @@ -224,6 +224,7 @@ public final class KeyProtection implements ProtectionParameter { private final boolean mRandomizedEncryptionRequired; private final boolean mUserAuthenticationRequired; private final int mUserAuthenticationValidityDurationSeconds; + private final boolean mTrustedUserPresenceRequred; private final boolean mUserAuthenticationValidWhileOnBody; private final boolean mInvalidatedByBiometricEnrollment; private final long mBoundToSecureUserId; @@ -242,6 +243,7 @@ public final class KeyProtection implements ProtectionParameter { boolean randomizedEncryptionRequired, boolean userAuthenticationRequired, int userAuthenticationValidityDurationSeconds, + boolean trustedUserPresenceRequred, boolean userAuthenticationValidWhileOnBody, boolean invalidatedByBiometricEnrollment, long boundToSecureUserId, @@ -260,6 +262,7 @@ public final class KeyProtection implements ProtectionParameter { mRandomizedEncryptionRequired = randomizedEncryptionRequired; mUserAuthenticationRequired = userAuthenticationRequired; mUserAuthenticationValidityDurationSeconds = userAuthenticationValidityDurationSeconds; + mTrustedUserPresenceRequred = trustedUserPresenceRequred; mUserAuthenticationValidWhileOnBody = userAuthenticationValidWhileOnBody; mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment; mBoundToSecureUserId = boundToSecureUserId; @@ -437,6 +440,14 @@ public final class KeyProtection implements ProtectionParameter { } /** + * Returns {@code true} if the key is authorized to be used only if a test of user presence has + * been performed between the {@code Signature.initSign()} and {@code Signature.sign()} calls. + */ + public boolean isTrustedUserPresenceRequired() { + return mTrustedUserPresenceRequred; + } + + /** * Returns {@code true} if the key will be de-authorized when the device is removed from the * user's body. This option has no effect on keys that don't have an authentication validity * duration, and has no effect if the device lacks an on-body sensor. @@ -509,6 +520,7 @@ public final class KeyProtection implements ProtectionParameter { private boolean mRandomizedEncryptionRequired = true; private boolean mUserAuthenticationRequired; private int mUserAuthenticationValidityDurationSeconds = -1; + private boolean mTrustedUserPresenceRequired = false; private boolean mUserAuthenticationValidWhileOnBody; private boolean mInvalidatedByBiometricEnrollment = true; private boolean mUserConfirmationRequired; @@ -811,6 +823,16 @@ public final class KeyProtection implements ProtectionParameter { } /** + * Sets whether a test of user presence is required to be performed between the + * {@code Signature.initSign()} and {@code Signature.sign()} method calls. + */ + @NonNull + public Builder setTrustedUserPresenceRequired(boolean required) { + mTrustedUserPresenceRequired = required; + return this; + } + + /** * Sets whether the key will remain authorized only until the device is removed from the * user's body up to the limit of the authentication validity period (see * {@link #setUserAuthenticationValidityDurationSeconds} and @@ -910,6 +932,7 @@ public final class KeyProtection implements ProtectionParameter { mRandomizedEncryptionRequired, mUserAuthenticationRequired, mUserAuthenticationValidityDurationSeconds, + mTrustedUserPresenceRequired, mUserAuthenticationValidWhileOnBody, mInvalidatedByBiometricEnrollment, mBoundToSecureUserId, diff --git a/keystore/java/android/security/keystore/KeymasterUtils.java b/keystore/java/android/security/keystore/KeymasterUtils.java index 4e28601f17a1..0ef08f237b4e 100644 --- a/keystore/java/android/security/keystore/KeymasterUtils.java +++ b/keystore/java/android/security/keystore/KeymasterUtils.java @@ -18,6 +18,7 @@ package android.security.keystore; import android.util.Log; import android.hardware.fingerprint.FingerprintManager; +import android.os.UserHandle; import android.security.GateKeeper; import android.security.KeyStore; import android.security.keymaster.KeymasterArguments; @@ -101,22 +102,21 @@ public abstract class KeymasterUtils { * require user authentication. */ public static void addUserAuthArgs(KeymasterArguments args, - boolean userAuthenticationRequired, - int userAuthenticationValidityDurationSeconds, - boolean userAuthenticationValidWhileOnBody, - boolean invalidatedByBiometricEnrollment, - long boundToSpecificSecureUserId, - boolean userConfirmationRequired) { - if (userConfirmationRequired) { + UserAuthArgs spec) { + if (spec.isUserConfirmationRequired()) { args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_CONFIRMATION_REQUIRED); } - if (!userAuthenticationRequired) { + if (spec.isTrustedUserPresenceRequired()) { + args.addBoolean(KeymasterDefs.KM_TAG_TRUSTED_USER_PRESENCE_REQUIRED); + } + + if (!spec.isUserAuthenticationRequired()) { args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED); return; } - if (userAuthenticationValidityDurationSeconds == -1) { + if (spec.getUserAuthenticationValidityDurationSeconds() == -1) { // Every use of this key needs to be authorized by the user. This currently means // fingerprint-only auth. FingerprintManager fingerprintManager = @@ -132,9 +132,9 @@ public abstract class KeymasterUtils { } long sid; - if (boundToSpecificSecureUserId != GateKeeper.INVALID_SECURE_USER_ID) { - sid = boundToSpecificSecureUserId; - } else if (invalidatedByBiometricEnrollment) { + if (spec.getBoundToSpecificSecureUserId() != GateKeeper.INVALID_SECURE_USER_ID) { + sid = spec.getBoundToSpecificSecureUserId(); + } else if (spec.isInvalidatedByBiometricEnrollment()) { // The fingerprint-only SID will change on fingerprint enrollment or removal of all, // enrolled fingerprints, invalidating the key. sid = fingerprintOnlySid; @@ -147,14 +147,14 @@ public abstract class KeymasterUtils { args.addUnsignedLong( KeymasterDefs.KM_TAG_USER_SECURE_ID, KeymasterArguments.toUint64(sid)); args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_FINGERPRINT); - if (userAuthenticationValidWhileOnBody) { + if (spec.isUserAuthenticationValidWhileOnBody()) { throw new ProviderException("Key validity extension while device is on-body is not " + "supported for keys requiring fingerprint authentication"); } } else { long sid; - if (boundToSpecificSecureUserId != GateKeeper.INVALID_SECURE_USER_ID) { - sid = boundToSpecificSecureUserId; + if (spec.getBoundToSpecificSecureUserId() != GateKeeper.INVALID_SECURE_USER_ID) { + sid = spec.getBoundToSpecificSecureUserId(); } else { // The key is authorized for use for the specified amount of time after the user has // authenticated. Whatever unlocks the secure lock screen should authorize this key. @@ -165,8 +165,8 @@ public abstract class KeymasterUtils { args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_FINGERPRINT); args.addUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, - userAuthenticationValidityDurationSeconds); - if (userAuthenticationValidWhileOnBody) { + spec.getUserAuthenticationValidityDurationSeconds()); + if (spec.isUserAuthenticationValidWhileOnBody()) { args.addBoolean(KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY); } } diff --git a/keystore/java/android/security/keystore/UserAuthArgs.java b/keystore/java/android/security/keystore/UserAuthArgs.java new file mode 100644 index 000000000000..1949592e7240 --- /dev/null +++ b/keystore/java/android/security/keystore/UserAuthArgs.java @@ -0,0 +1,37 @@ +/* + * Copyright (C) 2017 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.keystore; + +/** + * @hide + * + * This is an interface to encapsulate the user authentication arguments that + * are passed to KeymasterUtils.addUserAuthArgs. Classes that represent + * authorization characteristics for new or imported keys can implement this + * interface to be passed to that method. + */ +public interface UserAuthArgs { + + boolean isUserAuthenticationRequired(); + int getUserAuthenticationValidityDurationSeconds(); + boolean isUserAuthenticationValidWhileOnBody(); + boolean isInvalidatedByBiometricEnrollment(); + boolean isUserConfirmationRequired(); + long getBoundToSpecificSecureUserId(); + boolean isTrustedUserPresenceRequired(); + +} |