From 34945b1fd2d8f9201c7db1b7ff915eaea78d33ac Mon Sep 17 00:00:00 2001 From: Eric Biggers Date: Sat, 23 Jul 2022 00:28:01 +0000 Subject: [PATCH] AndroidKeyStore: support platform use of rollback-resistant keys The keystore2 binder API supports rollback resistance when KeyMint supports it, but until now this wasn't exposed to Java code that uses AndroidKeyStore. Add support for rollback-resistant keys to KeyProtection and AndroidKeyStoreSpi.setSecretKeyEntry() so that LockSettingsService can request it for SP protector keys. This CL does *not* do any of the following: - Add any non-hidden APIs. KeyMint implementations only support a limited number of rollback-resistant keys; currently the available space is reserved for platform use only. Note that other examples of "hidden", platform-only key properties are isCriticalToDeviceEncryption() and getBoundToSpecificSecureUserId(). - Support rollback resistance with keys directly generated by Keystore. This isn't currently needed. Note that this would require changes KeyGenParameterSpec and AndroidKeyStoreKeyGeneratorSpi. - Allow querying the rollback resistance property of keys. This isn't currently needed. Note that this would require changes to KeyInfo and AndroidKeyStoreSecretKeyFactorySpi. Bug: 239632930 Test: see I05f3b7e5c139471febe5c266a39e3dc3bca4831f Change-Id: Ifcfd0b8f1bf440ef1ac80a9ac2b0e9c7f62106dd --- .../security/keystore/KeyProtection.java | 35 +++++++++++++++++-- .../keystore2/AndroidKeyStoreSpi.java | 6 ++++ 2 files changed, 39 insertions(+), 2 deletions(-) diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java index c14c3c534cf42..5ab21bc5f4897 100644 --- a/keystore/java/android/security/keystore/KeyProtection.java +++ b/keystore/java/android/security/keystore/KeyProtection.java @@ -237,6 +237,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { private final boolean mUnlockedDeviceRequired; private final boolean mIsStrongBoxBacked; private final int mMaxUsageCount; + private final boolean mRollbackResistant; private KeyProtection( Date keyValidityStart, @@ -259,7 +260,8 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { boolean userConfirmationRequired, boolean unlockedDeviceRequired, boolean isStrongBoxBacked, - int maxUsageCount) { + int maxUsageCount, + boolean rollbackResistant) { mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart); mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd); mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd); @@ -283,6 +285,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { mUnlockedDeviceRequired = unlockedDeviceRequired; mIsStrongBoxBacked = isStrongBoxBacked; mMaxUsageCount = maxUsageCount; + mRollbackResistant = rollbackResistant; } /** @@ -562,6 +565,17 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { return mMaxUsageCount; } + /** + * Returns {@code true} if the key is rollback-resistant, meaning that when deleted it is + * guaranteed to be permanently deleted and unusable. + * + * @see Builder#setRollbackResistant(boolean) + * @hide + */ + public boolean isRollbackResistant() { + return mRollbackResistant; + } + /** * Builder of {@link KeyProtection} instances. */ @@ -591,6 +605,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { private boolean mIsStrongBoxBacked = false; private int mMaxUsageCount = KeyProperties.UNRESTRICTED_USAGE_COUNT; private String mAttestKeyAlias = null; + private boolean mRollbackResistant = false; /** * Creates a new instance of the {@code Builder}. @@ -1096,6 +1111,21 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { throw new IllegalArgumentException("maxUsageCount is not valid"); } + /** + * Sets whether the key should be rollback-resistant, meaning that when deleted it is + * guaranteed to be permanently deleted and unusable. Not all implementations support + * rollback-resistant keys. This method is hidden because implementations only support a + * limited number of rollback-resistant keys; currently the available space is reserved for + * critical system keys. + * + * @hide + */ + @NonNull + public Builder setRollbackResistant(boolean rollbackResistant) { + mRollbackResistant = rollbackResistant; + return this; + } + /** * Builds an instance of {@link KeyProtection}. * @@ -1124,7 +1154,8 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs { mUserConfirmationRequired, mUnlockedDeviceRequired, mIsStrongBoxBacked, - mMaxUsageCount); + mMaxUsageCount, + mRollbackResistant); } } } diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java index 33411e1ec5b97..dfda356ec35bc 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java @@ -783,6 +783,12 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { params.getMaxUsageCount() )); } + + if (params.isRollbackResistant()) { + importArgs.add(KeyStore2ParameterUtils.makeBool( + KeymasterDefs.KM_TAG_ROLLBACK_RESISTANT + )); + } } catch (IllegalArgumentException | IllegalStateException e) { throw new KeyStoreException(e); }