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); }