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

Commit fcb4e8ee authored by Qi Wu's avatar Qi Wu
Browse files

Add limited use keys related API into Keystore 2.0 SPI.

Bug: b/174140443
Test: atest CtsKeystoreTestCases

The new CTS tests for this feature is introduced in aosp/1556464

Change-Id: I9620c4a3e5d2c10ed8a50d494e63eb2fb19dabef
parent e8af7795
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -36869,6 +36869,7 @@ package android.security.keystore {
    method @Nullable public java.util.Date getKeyValidityForOriginationEnd();
    method @Nullable public java.util.Date getKeyValidityStart();
    method @NonNull public String getKeystoreAlias();
    method public int getMaxUsageCount();
    method public int getPurposes();
    method @NonNull public String[] getSignaturePaddings();
    method public int getUserAuthenticationType();
@@ -36905,6 +36906,7 @@ package android.security.keystore {
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityForConsumptionEnd(java.util.Date);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityForOriginationEnd(java.util.Date);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setKeyValidityStart(java.util.Date);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMaxUsageCount(int);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setRandomizedEncryptionRequired(boolean);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setSignaturePaddings(java.lang.String...);
    method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setUnlockedDeviceRequired(boolean);
@@ -36927,6 +36929,7 @@ package android.security.keystore {
    method public String getKeystoreAlias();
    method public int getOrigin();
    method public int getPurposes();
    method public int getRemainingUsageCount();
    method public int getSecurityLevel();
    method @NonNull public String[] getSignaturePaddings();
    method public int getUserAuthenticationType();
@@ -36996,6 +36999,7 @@ package android.security.keystore {
    field public static final int SECURITY_LEVEL_UNKNOWN_SECURE = -1; // 0xffffffff
    field public static final String SIGNATURE_PADDING_RSA_PKCS1 = "PKCS1";
    field public static final String SIGNATURE_PADDING_RSA_PSS = "PSS";
    field public static final int UNRESTRICTED_USAGE_COUNT = -1; // 0xffffffff
  }
  public final class KeyProtection implements java.security.KeyStore.ProtectionParameter {
@@ -37005,6 +37009,7 @@ package android.security.keystore {
    method @Nullable public java.util.Date getKeyValidityForConsumptionEnd();
    method @Nullable public java.util.Date getKeyValidityForOriginationEnd();
    method @Nullable public java.util.Date getKeyValidityStart();
    method public int getMaxUsageCount();
    method public int getPurposes();
    method @NonNull public String[] getSignaturePaddings();
    method public int getUserAuthenticationType();
@@ -37031,6 +37036,7 @@ package android.security.keystore {
    method @NonNull public android.security.keystore.KeyProtection.Builder setKeyValidityForConsumptionEnd(java.util.Date);
    method @NonNull public android.security.keystore.KeyProtection.Builder setKeyValidityForOriginationEnd(java.util.Date);
    method @NonNull public android.security.keystore.KeyProtection.Builder setKeyValidityStart(java.util.Date);
    method @NonNull public android.security.keystore.KeyProtection.Builder setMaxUsageCount(int);
    method @NonNull public android.security.keystore.KeyProtection.Builder setRandomizedEncryptionRequired(boolean);
    method @NonNull public android.security.keystore.KeyProtection.Builder setSignaturePaddings(java.lang.String...);
    method @NonNull public android.security.keystore.KeyProtection.Builder setUnlockedDeviceRequired(boolean);
+1 −0
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@ public final class KeymasterDefs {
    public static final int KM_TAG_MIN_SECONDS_BETWEEN_OPS =
            Tag.MIN_SECONDS_BETWEEN_OPS; // KM_UINT | 403;
    public static final int KM_TAG_MAX_USES_PER_BOOT = Tag.MAX_USES_PER_BOOT; // KM_UINT | 404;
    public static final int KM_TAG_USAGE_COUNT_LIMIT = Tag.USAGE_COUNT_LIMIT; // KM_UINT | 405;

    public static final int KM_TAG_USER_ID = Tag.USER_ID; // KM_UINT | 501;
    public static final int KM_TAG_USER_SECURE_ID = Tag.USER_SECURE_ID; // KM_ULONG_REP | 502;
+2 −1
Original line number Diff line number Diff line
@@ -215,7 +215,8 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
                // Keystore 1.0 does not tell us the exact security level of the key
                // so we report an unknown but secure security level.
                insideSecureHardware ? KeyProperties.SECURITY_LEVEL_UNKNOWN_SECURE
                        : KeyProperties.SECURITY_LEVEL_SOFTWARE);
                        : KeyProperties.SECURITY_LEVEL_SOFTWARE,
                KeyProperties.UNRESTRICTED_USAGE_COUNT);
    }

    private static BigInteger getGateKeeperSecureUserId() throws ProviderException {
+61 −3
Original line number Diff line number Diff line
@@ -274,6 +274,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
    private final boolean mUserConfirmationRequired;
    private final boolean mUnlockedDeviceRequired;
    private final boolean mCriticalToDeviceEncryption;
    private final int mMaxUsageCount;
    /*
     * ***NOTE***: All new fields MUST also be added to the following:
     * ParcelableKeyGenParameterSpec class.
@@ -313,7 +314,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
            boolean isStrongBoxBacked,
            boolean userConfirmationRequired,
            boolean unlockedDeviceRequired,
            boolean criticalToDeviceEncryption) {
            boolean criticalToDeviceEncryption,
            int maxUsageCount) {
        if (TextUtils.isEmpty(keyStoreAlias)) {
            throw new IllegalArgumentException("keyStoreAlias must not be empty");
        }
@@ -366,6 +368,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
        mUserConfirmationRequired = userConfirmationRequired;
        mUnlockedDeviceRequired = unlockedDeviceRequired;
        mCriticalToDeviceEncryption = criticalToDeviceEncryption;
        mMaxUsageCount = maxUsageCount;
    }

    /**
@@ -782,7 +785,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
    }

    /**
     * Return whether this key is critical to the device encryption flow.
     * Returns whether this key is critical to the device encryption flow.
     *
     * @see android.security.KeyStore#FLAG_CRITICAL_TO_DEVICE_ENCRYPTION
     * @hide
@@ -791,6 +794,17 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
        return mCriticalToDeviceEncryption;
    }

    /**
     * Returns the maximum number of times the limited use key is allowed to be used or
     * {@link KeyProperties#UNRESTRICTED_USAGE_COUNT} if there’s no restriction on the number of
     * times the key can be used.
     *
     * @see Builder#setMaxUsageCount(int)
     */
    public int getMaxUsageCount() {
        return mMaxUsageCount;
    }

    /**
     * Builder of {@link KeyGenParameterSpec} instances.
     */
@@ -827,6 +841,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
        private boolean mUserConfirmationRequired;
        private boolean mUnlockedDeviceRequired = false;
        private boolean mCriticalToDeviceEncryption = false;
        private int mMaxUsageCount = KeyProperties.UNRESTRICTED_USAGE_COUNT;

        /**
         * Creates a new instance of the {@code Builder}.
@@ -894,6 +909,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
            mUserConfirmationRequired = sourceSpec.isUserConfirmationRequired();
            mUnlockedDeviceRequired = sourceSpec.isUnlockedDeviceRequired();
            mCriticalToDeviceEncryption = sourceSpec.isCriticalToDeviceEncryption();
            mMaxUsageCount = sourceSpec.getMaxUsageCount();
        }

        /**
@@ -1552,6 +1568,47 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
            return this;
        }

        /**
         * Sets the maximum number of times the key is allowed to be used. After every use of the
         * key, the use counter will decrease. This authorization applies only to secret key and
         * private key operations. Public key operations are not restricted. For example, after
         * successfully encrypting and decrypting data using methods such as
         * {@link Cipher#doFinal()}, the use counter of the secret key will decrease. After
         * successfully signing data using methods such as {@link Signature#sign()}, the use
         * counter of the private key will decrease.
         *
         * When the use counter is depleted, the key will be marked for deletion by Android
         * Keystore and any subsequent attempt to use the key will throw
         * {@link KeyPermanentlyInvalidatedException}. There is no key to be loaded from the
         * Android Keystore once the exhausted key is permanently deleted, as if the key never
         * existed before.
         *
         * <p>By default, there is no restriction on the usage of key.
         *
         * <p>Some secure hardware may not support this feature at all, in which case it will
         * be enforced in software, some secure hardware may support it but only with
         * maxUsageCount = 1, and some secure hardware may support it with larger value
         * of maxUsageCount.
         *
         * <p>The PackageManger feature flags:
         * {@link android.content.pm.PackageManager#FEATURE_KEYSTORE_SINGLE_USE_KEY} and
         * {@link android.content.pm.PackageManager#FEATURE_KEYSTORE_LIMITED_USE_KEY} can be used
         * to check whether the secure hardware cannot enforce this feature, can only enforce it
         * with maxUsageCount = 1, or can enforce it with larger value of maxUsageCount.
         *
         * @param maxUsageCount maximum number of times the key is allowed to be used or
         *        {@link KeyProperties#UNRESTRICTED_USAGE_COUNT} if there is no restriction on the
         *        usage.
         */
        @NonNull
        public Builder setMaxUsageCount(int maxUsageCount) {
            if (maxUsageCount == KeyProperties.UNRESTRICTED_USAGE_COUNT || maxUsageCount > 0) {
                mMaxUsageCount = maxUsageCount;
                return this;
            }
            throw new IllegalArgumentException("maxUsageCount is not valid");
        }

        /**
         * Builds an instance of {@code KeyGenParameterSpec}.
         */
@@ -1587,7 +1644,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
                    mIsStrongBoxBacked,
                    mUserConfirmationRequired,
                    mUnlockedDeviceRequired,
                    mCriticalToDeviceEncryption);
                    mCriticalToDeviceEncryption,
                    mMaxUsageCount);
        }
    }
}
+15 −1
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ public class KeyInfo implements KeySpec {
    private final boolean mInvalidatedByBiometricEnrollment;
    private final boolean mUserConfirmationRequired;
    private final @KeyProperties.SecurityLevelEnum int mSecurityLevel;
    private final int mRemainingUsageCount;

    /**
     * @hide
@@ -109,7 +110,8 @@ public class KeyInfo implements KeySpec {
            boolean trustedUserPresenceRequired,
            boolean invalidatedByBiometricEnrollment,
            boolean userConfirmationRequired,
            @KeyProperties.SecurityLevelEnum int securityLevel) {
            @KeyProperties.SecurityLevelEnum int securityLevel,
            int remainingUsageCount) {
        mKeystoreAlias = keystoreKeyAlias;
        mInsideSecureHardware = insideSecureHardware;
        mOrigin = origin;
@@ -134,6 +136,7 @@ public class KeyInfo implements KeySpec {
        mInvalidatedByBiometricEnrollment = invalidatedByBiometricEnrollment;
        mUserConfirmationRequired = userConfirmationRequired;
        mSecurityLevel = securityLevel;
        mRemainingUsageCount = remainingUsageCount;
    }

    /**
@@ -374,4 +377,15 @@ public class KeyInfo implements KeySpec {
    public @KeyProperties.SecurityLevelEnum int getSecurityLevel() {
        return mSecurityLevel;
    }

    /**
     * Returns the remaining number of times the key is allowed to be used or
     * {@link KeyProperties#UNRESTRICTED_USAGE_COUNT} if there's no restriction on the number of
     * times the key can be used. Note that this gives a best effort count and need not be
     * accurate (as there might be usages happening in parallel and the count maintained here need
     * not be in sync with the usage).
     */
    public int getRemainingUsageCount() {
        return mRemainingUsageCount;
    }
}
Loading