diff options
7 files changed, 92 insertions, 16 deletions
diff --git a/core/java/android/security/keymaster/KeymasterDefs.java b/core/java/android/security/keymaster/KeymasterDefs.java index f90055829b89..8efc5eb6b6ff 100644 --- a/core/java/android/security/keymaster/KeymasterDefs.java +++ b/core/java/android/security/keymaster/KeymasterDefs.java @@ -68,6 +68,8 @@ public final class KeymasterDefs { public static final int KM_TAG_RSA_PUBLIC_EXPONENT = Tag.RSA_PUBLIC_EXPONENT; // KM_ULONG | 200; public static final int KM_TAG_INCLUDE_UNIQUE_ID = Tag.INCLUDE_UNIQUE_ID; // KM_BOOL | 202; + public static final int KM_TAG_RSA_OAEP_MGF_DIGEST = Tag.RSA_OAEP_MGF_DIGEST; + // KM_ENUM_REP | 203; public static final int KM_TAG_ACTIVE_DATETIME = Tag.ACTIVE_DATETIME; // KM_DATE | 400; public static final int KM_TAG_ORIGINATION_EXPIRE_DATETIME = diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java index d9a7994d6c4a..dbd918e35d70 100644 --- a/keystore/java/android/security/keystore/KeyProperties.java +++ b/keystore/java/android/security/keystore/KeyProperties.java @@ -29,6 +29,8 @@ import libcore.util.EmptyArray; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.MGF1ParameterSpec; import java.util.Collection; import java.util.Locale; @@ -675,6 +677,26 @@ public abstract class KeyProperties { } } + /** + * @hide + */ + @NonNull public static @DigestEnum + AlgorithmParameterSpec fromKeymasterToMGF1ParameterSpec(int digest) { + switch (digest) { + default: + case KeymasterDefs.KM_DIGEST_SHA1: + return MGF1ParameterSpec.SHA1; + case KeymasterDefs.KM_DIGEST_SHA_2_224: + return MGF1ParameterSpec.SHA224; + case KeymasterDefs.KM_DIGEST_SHA_2_256: + return MGF1ParameterSpec.SHA256; + case KeymasterDefs.KM_DIGEST_SHA_2_384: + return MGF1ParameterSpec.SHA384; + case KeymasterDefs.KM_DIGEST_SHA_2_512: + return MGF1ParameterSpec.SHA512; + } + } + @NonNull public static @DigestEnum String fromKeymasterToSignatureAlgorithmDigest(int digest) { switch (digest) { diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java index e808c5cc51bd..7571e44a7713 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java @@ -69,6 +69,7 @@ import javax.crypto.spec.SecretKeySpec; */ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStoreCryptoOperation { private static final String TAG = "AndroidKeyStoreCipherSpiBase"; + public static final String DEFAULT_MGF1_DIGEST = "SHA-1"; // Fields below are populated by Cipher.init and KeyStore.begin and should be preserved after // doFinal finishes. @@ -133,24 +134,28 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor if ("RSA/ECB/OAEPWithSHA-224AndMGF1Padding".equals(transform)) { OAEPParameterSpec spec = new OAEPParameterSpec("SHA-224", "MGF1", - new MGF1ParameterSpec("SHA1"), PSource.PSpecified.DEFAULT); + new MGF1ParameterSpec(DEFAULT_MGF1_DIGEST), + PSource.PSpecified.DEFAULT); mCipher.init(opmode, key, spec, random); } else if ("RSA/ECB/OAEPWithSHA-256AndMGF1Padding".equals(transform)) { OAEPParameterSpec spec = new OAEPParameterSpec("SHA-256", "MGF1", - new MGF1ParameterSpec("SHA1"), PSource.PSpecified.DEFAULT); + new MGF1ParameterSpec(DEFAULT_MGF1_DIGEST), + PSource.PSpecified.DEFAULT); mCipher.init(opmode, key, spec, random); } else if ("RSA/ECB/OAEPWithSHA-384AndMGF1Padding".equals(transform)) { OAEPParameterSpec spec = new OAEPParameterSpec("SHA-384", "MGF1", - new MGF1ParameterSpec("SHA1"), PSource.PSpecified.DEFAULT); + new MGF1ParameterSpec(DEFAULT_MGF1_DIGEST), + PSource.PSpecified.DEFAULT); mCipher.init(opmode, key, spec, random); } else if ("RSA/ECB/OAEPWithSHA-512AndMGF1Padding".equals(transform)) { OAEPParameterSpec spec = new OAEPParameterSpec("SHA-512", "MGF1", - new MGF1ParameterSpec("SHA1"), PSource.PSpecified.DEFAULT); + new MGF1ParameterSpec(DEFAULT_MGF1_DIGEST), + PSource.PSpecified.DEFAULT); mCipher.init(opmode, key, spec, random); } else { mCipher.init(opmode, key, random); diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java index cdc1085a5015..acc0005154b4 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyPairGeneratorSpi.java @@ -16,6 +16,8 @@ package android.security.keystore2; +import static android.security.keystore2.AndroidKeyStoreCipherSpiBase.DEFAULT_MGF1_DIGEST; + import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityThread; @@ -908,6 +910,26 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato params.add(KeyStore2ParameterUtils.makeEnum( KeymasterDefs.KM_TAG_PADDING, padding )); + if (padding == KeymasterDefs.KM_PAD_RSA_OAEP) { + final boolean[] hasDefaultMgf1DigestBeenAdded = {false}; + ArrayUtils.forEach(mKeymasterDigests, (digest) -> { + params.add(KeyStore2ParameterUtils.makeEnum( + KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, digest + )); + hasDefaultMgf1DigestBeenAdded[0] |= + digest.equals(KeyProperties.Digest.toKeymaster(DEFAULT_MGF1_DIGEST)); + }); + /* 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 (!hasDefaultMgf1DigestBeenAdded[0]) { + params.add(KeyStore2ParameterUtils.makeEnum( + KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, + KeyProperties.Digest.toKeymaster(DEFAULT_MGF1_DIGEST) + )); + } + } }); ArrayUtils.forEach(mKeymasterSignaturePaddings, (padding) -> { params.add(KeyStore2ParameterUtils.makeEnum( diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java index 5848247809e7..e9b66aafc262 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java @@ -161,10 +161,11 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase */ abstract static class OAEPWithMGF1Padding extends AndroidKeyStoreRSACipherSpi { - private static final String MGF_ALGORITGM_MGF1 = "MGF1"; + private static final String MGF_ALGORITHM_MGF1 = "MGF1"; private int mKeymasterDigest = -1; private int mDigestOutputSizeBytes; + private int mKeymasterMgf1Digest = KeymasterDefs.KM_DIGEST_SHA1; // Default MGF1 digest OAEPWithMGF1Padding(int keymasterDigest) { super(KeymasterDefs.KM_PAD_RSA_OAEP); @@ -189,10 +190,10 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase + ". Only OAEPParameterSpec supported"); } OAEPParameterSpec spec = (OAEPParameterSpec) params; - if (!MGF_ALGORITGM_MGF1.equalsIgnoreCase(spec.getMGFAlgorithm())) { + if (!MGF_ALGORITHM_MGF1.equalsIgnoreCase(spec.getMGFAlgorithm())) { throw new InvalidAlgorithmParameterException( "Unsupported MGF: " + spec.getMGFAlgorithm() - + ". Only " + MGF_ALGORITGM_MGF1 + " supported"); + + ". Only " + MGF_ALGORITHM_MGF1 + " supported"); } String jcaDigest = spec.getDigestAlgorithm(); int keymasterDigest; @@ -225,11 +226,6 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase } MGF1ParameterSpec mgfSpec = (MGF1ParameterSpec) mgfParams; String mgf1JcaDigest = mgfSpec.getDigestAlgorithm(); - if (!KeyProperties.DIGEST_SHA1.equalsIgnoreCase(mgf1JcaDigest)) { - throw new InvalidAlgorithmParameterException( - "Unsupported MGF1 digest: " + mgf1JcaDigest - + ". Only " + KeyProperties.DIGEST_SHA1 + " supported"); - } PSource pSource = spec.getPSource(); if (!(pSource instanceof PSource.PSpecified)) { throw new InvalidAlgorithmParameterException( @@ -244,6 +240,7 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase + ". Only pSpecifiedEmpty (PSource.PSpecified.DEFAULT) supported"); } mKeymasterDigest = keymasterDigest; + mKeymasterMgf1Digest = KeyProperties.Digest.toKeymaster(mgf1JcaDigest); mDigestOutputSizeBytes = (KeymasterUtils.getDigestOutputSizeBits(keymasterDigest) + 7) / 8; } @@ -273,10 +270,10 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase protected final AlgorithmParameters engineGetParameters() { OAEPParameterSpec spec = new OAEPParameterSpec( - KeyProperties.Digest.fromKeymaster(mKeymasterDigest), - MGF_ALGORITGM_MGF1, - MGF1ParameterSpec.SHA1, - PSource.PSpecified.DEFAULT); + KeyProperties.Digest.fromKeymaster(mKeymasterDigest), + MGF_ALGORITHM_MGF1, + KeyProperties.Digest.fromKeymasterToMGF1ParameterSpec(mKeymasterMgf1Digest), + PSource.PSpecified.DEFAULT); try { AlgorithmParameters params = AlgorithmParameters.getInstance("OAEP"); params.init(spec); @@ -298,6 +295,9 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase parameters.add(KeyStore2ParameterUtils.makeEnum( KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest )); + parameters.add(KeyStore2ParameterUtils.makeEnum( + KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, mKeymasterMgf1Digest + )); } @Override diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java index dfda356ec35b..94bf122877bd 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java @@ -16,6 +16,8 @@ package android.security.keystore2; +import static android.security.keystore2.AndroidKeyStoreCipherSpiBase.DEFAULT_MGF1_DIGEST; + import android.annotation.NonNull; import android.hardware.biometrics.BiometricManager; import android.hardware.security.keymint.HardwareAuthenticatorType; @@ -511,6 +513,28 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { KeymasterDefs.KM_TAG_PADDING, padding )); + if (padding == KeymasterDefs.KM_PAD_RSA_OAEP) { + if (spec.isDigestsSpecified()) { + boolean hasDefaultMgf1DigestBeenAdded = false; + for (String digest : spec.getDigests()) { + importArgs.add(KeyStore2ParameterUtils.makeEnum( + KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, + KeyProperties.Digest.toKeymaster(digest) + )); + hasDefaultMgf1DigestBeenAdded |= digest.equals(DEFAULT_MGF1_DIGEST); + } + /* 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 (!hasDefaultMgf1DigestBeenAdded) { + importArgs.add(KeyStore2ParameterUtils.makeEnum( + KeymasterDefs.KM_TAG_RSA_OAEP_MGF_DIGEST, + KeyProperties.Digest.toKeymaster(DEFAULT_MGF1_DIGEST) + )); + } + } + } } for (String padding : spec.getSignaturePaddings()) { importArgs.add(KeyStore2ParameterUtils.makeEnum( diff --git a/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java b/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java index dcdd7defd752..54955c6b7fab 100644 --- a/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java +++ b/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java @@ -78,6 +78,7 @@ public abstract class KeyStore2ParameterUtils { kp.value = KeyParameterValue.blockMode(v); break; case Tag.DIGEST: + case Tag.RSA_OAEP_MGF_DIGEST: kp.value = KeyParameterValue.digest(v); break; case Tag.EC_CURVE: |