diff options
6 files changed, 76 insertions, 12 deletions
| diff --git a/core/api/current.txt b/core/api/current.txt index b44ff6c8e0ea..c600df19a379 100644 --- a/core/api/current.txt +++ b/core/api/current.txt @@ -39579,7 +39579,7 @@ package android.security.keystore {      method @Nullable public java.util.Date getKeyValidityStart();      method @NonNull public String getKeystoreAlias();      method public int getMaxUsageCount(); -    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public java.util.Set<java.lang.String> getMgf1Digests(); +    method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();      method public int getPurposes();      method @NonNull public String[] getSignaturePaddings();      method public int getUserAuthenticationType(); @@ -39587,7 +39587,7 @@ package android.security.keystore {      method public boolean isDevicePropertiesAttestationIncluded();      method @NonNull public boolean isDigestsSpecified();      method public boolean isInvalidatedByBiometricEnrollment(); -    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public boolean isMgf1DigestsSpecified(); +    method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public boolean isMgf1DigestsSpecified();      method public boolean isRandomizedEncryptionRequired();      method public boolean isStrongBoxBacked();      method public boolean isUnlockedDeviceRequired(); @@ -39619,7 +39619,7 @@ package android.security.keystore {      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 @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMgf1Digests(@NonNull java.lang.String...); +    method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setMgf1Digests(@NonNull java.lang.String...);      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); @@ -39724,14 +39724,14 @@ package android.security.keystore {      method @Nullable public java.util.Date getKeyValidityForOriginationEnd();      method @Nullable public java.util.Date getKeyValidityStart();      method public int getMaxUsageCount(); -    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public java.util.Set<java.lang.String> getMgf1Digests(); +    method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public java.util.Set<java.lang.String> getMgf1Digests();      method public int getPurposes();      method @NonNull public String[] getSignaturePaddings();      method public int getUserAuthenticationType();      method public int getUserAuthenticationValidityDurationSeconds();      method public boolean isDigestsSpecified();      method public boolean isInvalidatedByBiometricEnrollment(); -    method @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public boolean isMgf1DigestsSpecified(); +    method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public boolean isMgf1DigestsSpecified();      method public boolean isRandomizedEncryptionRequired();      method public boolean isUnlockedDeviceRequired();      method public boolean isUserAuthenticationRequired(); @@ -39753,7 +39753,7 @@ package android.security.keystore {      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 @FlaggedApi("MGF1_DIGEST_SETTER") @NonNull public android.security.keystore.KeyProtection.Builder setMgf1Digests(@Nullable java.lang.String...); +    method @FlaggedApi("android.security.mgf1_digest_setter") @NonNull public android.security.keystore.KeyProtection.Builder setMgf1Digests(@Nullable java.lang.String...);      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); diff --git a/core/java/android/security/flags.aconfig b/core/java/android/security/flags.aconfig index ef1d682ee786..17f750410316 100644 --- a/core/java/android/security/flags.aconfig +++ b/core/java/android/security/flags.aconfig @@ -15,6 +15,13 @@ flag {  }  flag { +    name: "mgf1_digest_setter" +    namespace: "hardware_backed_security" +    description: "Feature flag for mgf1 digest setter in key generation and import parameters." +    bug: "308378912" +} + +flag {      name: "fix_unlocked_device_required_keys_v2"      namespace: "hardware_backed_security"      description: "Fix bugs in behavior of UnlockedDeviceRequired keystore keys" diff --git a/keystore/java/android/security/keystore/KeyGenParameterSpec.java b/keystore/java/android/security/keystore/KeyGenParameterSpec.java index 231fa4837441..4982f3732089 100644 --- a/keystore/java/android/security/keystore/KeyGenParameterSpec.java +++ b/keystore/java/android/security/keystore/KeyGenParameterSpec.java @@ -618,7 +618,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu       * @see #isMgf1DigestsSpecified()       */      @NonNull -    @FlaggedApi("MGF1_DIGEST_SETTER") +    @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)      public @KeyProperties.DigestEnum Set<String> getMgf1Digests() {          if (mMgf1Digests.isEmpty()) {              throw new IllegalStateException("Mask generation function (MGF) not specified"); @@ -633,7 +633,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu       * @see #getMgf1Digests()       */      @NonNull -    @FlaggedApi("MGF1_DIGEST_SETTER") +    @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)      public boolean isMgf1DigestsSpecified() {          return !mMgf1Digests.isEmpty();      } @@ -1292,7 +1292,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu           * <p>See {@link KeyProperties}.{@code DIGEST} constants.           */          @NonNull -        @FlaggedApi("MGF1_DIGEST_SETTER") +        @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)          public Builder setMgf1Digests(@NonNull @KeyProperties.DigestEnum String... mgf1Digests) {              mMgf1Digests = Set.of(mgf1Digests);              return this; diff --git a/keystore/java/android/security/keystore/KeyProtection.java b/keystore/java/android/security/keystore/KeyProtection.java index c1e3bab5d37c..7b6b2d142f95 100644 --- a/keystore/java/android/security/keystore/KeyProtection.java +++ b/keystore/java/android/security/keystore/KeyProtection.java @@ -401,7 +401,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {       * @see #isMgf1DigestsSpecified()       */      @NonNull -    @FlaggedApi("MGF1_DIGEST_SETTER") +    @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)      public @KeyProperties.DigestEnum Set<String> getMgf1Digests() {          if (mMgf1Digests.isEmpty()) {              throw new IllegalStateException("Mask generation function (MGF) not specified"); @@ -416,7 +416,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {       * @see #getMgf1Digests()       */      @NonNull -    @FlaggedApi("MGF1_DIGEST_SETTER") +    @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)      public boolean isMgf1DigestsSpecified() {          return !mMgf1Digests.isEmpty();      } @@ -799,7 +799,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {           * <p>See {@link KeyProperties}.{@code DIGEST} constants.           */          @NonNull -        @FlaggedApi("MGF1_DIGEST_SETTER") +        @FlaggedApi(android.security.Flags.FLAG_MGF1_DIGEST_SETTER)          public Builder setMgf1Digests(@Nullable @KeyProperties.DigestEnum String... mgf1Digests) {              mMgf1Digests = Set.of(mgf1Digests);              return this; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java index ed4b485f3927..9c05a3a768a0 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -28,6 +28,7 @@ import android.hardware.security.keymint.SecurityLevel;  import android.hardware.security.keymint.Tag;  import android.os.Build;  import android.os.StrictMode; +import android.security.Flags;  import android.security.KeyPairGeneratorSpec;  import android.security.KeyStore2;  import android.security.KeyStoreException; @@ -853,6 +854,22 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato                              KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, mgf1Digest                      ));                  }); + +                /* If the MGF1 Digest setter is not set, fall back to the previous behaviour: +                 * Add, as MGF1 Digest function, all the primary digests. +                 * Avoid adding the default MGF1 digest as it will have been included in the +                 * mKeymasterMgf1Digests field. +                 */ +                if (!getMgf1DigestSetterFlag()) { +                    final int defaultMgf1Digest = KeyProperties.Digest.toKeymaster( +                            DEFAULT_MGF1_DIGEST); +                    ArrayUtils.forEach(mKeymasterDigests, (digest) -> { +                        if (digest != defaultMgf1Digest) { +                            params.add(KeyStore2ParameterUtils.makeEnum( +                                    KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, digest)); +                        } +                    }); +                }              }          });          ArrayUtils.forEach(mKeymasterSignaturePaddings, (padding) -> { @@ -928,6 +945,16 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato          return params;      } +    private static boolean getMgf1DigestSetterFlag() { +        try { +            return Flags.mgf1DigestSetter(); +        } catch (SecurityException e) { +            Log.w(TAG, "Cannot read MGF1 Digest setter flag value", e); +            return false; +        } +    } + +      private void addAlgorithmSpecificParameters(List<KeyParameter> params) {          switch (mKeymasterAlgorithm) {              case KeymasterDefs.KM_ALGORITHM_RSA: diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java index ddbd93e458fd..2d8c5a380c6b 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java @@ -25,6 +25,7 @@ import android.hardware.security.keymint.HardwareAuthenticatorType;  import android.hardware.security.keymint.KeyParameter;  import android.hardware.security.keymint.SecurityLevel;  import android.os.StrictMode; +import android.security.Flags;  import android.security.GateKeeper;  import android.security.KeyStore2;  import android.security.KeyStoreParameter; @@ -256,6 +257,15 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {          }      } +    private static boolean getMgf1DigestSetterFlag() { +        try { +            return Flags.mgf1DigestSetter(); +        } catch (SecurityException e) { +            Log.w(NAME, "Cannot read MGF1 Digest setter flag value", e); +            return false; +        } +    } +      @Override      public Date engineGetCreationDate(String alias) {          KeyEntryResponse response = getKeyMetadata(alias); @@ -537,11 +547,31 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {                          /* Because of default MGF1 digest is SHA-1. It has to be added in Key                           * characteristics. Otherwise, crypto operations will fail with Incompatible                           * MGF1 digest. +                         * If the MGF1 Digest setter flag isn't set, then the condition in the +                         * if clause above must be false (cannot have MGF1 digests specified if the +                         * flag was off). In that case, in addition to adding the default MGF1 +                         * digest, we have to add all the other digests as MGF1 Digests. +                         *                           */                          importArgs.add(KeyStore2ParameterUtils.makeEnum(                                  KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST,                                  KeyProperties.Digest.toKeymaster(DEFAULT_MGF1_DIGEST)                          )); +                        if (!getMgf1DigestSetterFlag()) { +                            final int defaultMgf1Digest = KeyProperties.Digest.toKeymaster( +                                    DEFAULT_MGF1_DIGEST); +                            for (String digest : spec.getDigests()) { +                                int digestToAddAsMgf1Digest = KeyProperties.Digest.toKeymaster( +                                        digest); +                                // Do not add the default MGF1 digest as it has been added above. +                                if (digestToAddAsMgf1Digest != defaultMgf1Digest) { +                                    importArgs.add(KeyStore2ParameterUtils.makeEnum( +                                            KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, +                                            digestToAddAsMgf1Digest +                                    )); +                                } +                            } +                        }                      }                  }              } |