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

Commit 34945b1f authored by Eric Biggers's avatar Eric Biggers
Browse files

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
parent cd671e38
Loading
Loading
Loading
Loading
+33 −2
Original line number Diff line number Diff line
@@ -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);
        }
    }
}
+6 −0
Original line number Diff line number Diff line
@@ -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);
        }