diff --git a/api/current.txt b/api/current.txt index 375bee7c0c501..4d7fc92a356a8 100644 --- a/api/current.txt +++ b/api/current.txt @@ -28742,6 +28742,53 @@ package android.security { public abstract class KeyStoreKeyProperties { } + public static abstract class KeyStoreKeyProperties.Algorithm { + field public static final java.lang.String AES = "AES"; + field public static final java.lang.String EC = "EC"; + field public static final java.lang.String HMAC_SHA1 = "HmacSHA1"; + field public static final java.lang.String HMAC_SHA224 = "HmacSHA224"; + field public static final java.lang.String HMAC_SHA256 = "HmacSHA256"; + field public static final java.lang.String HMAC_SHA384 = "HmacSHA384"; + field public static final java.lang.String HMAC_SHA512 = "HmacSHA512"; + field public static final java.lang.String RSA = "RSA"; + } + + public static abstract class KeyStoreKeyProperties.AlgorithmEnum implements java.lang.annotation.Annotation { + } + + public static abstract class KeyStoreKeyProperties.BlockMode { + field public static final java.lang.String CBC = "CBC"; + field public static final java.lang.String CTR = "CTR"; + field public static final java.lang.String ECB = "ECB"; + field public static final java.lang.String GCM = "GCM"; + } + + public static abstract class KeyStoreKeyProperties.BlockModeEnum implements java.lang.annotation.Annotation { + } + + public static abstract class KeyStoreKeyProperties.Digest { + field public static final java.lang.String MD5 = "MD5"; + field public static final java.lang.String NONE = "NONE"; + field public static final java.lang.String SHA1 = "SHA-1"; + field public static final java.lang.String SHA224 = "SHA-224"; + field public static final java.lang.String SHA256 = "SHA-256"; + field public static final java.lang.String SHA384 = "SHA-384"; + field public static final java.lang.String SHA512 = "SHA-512"; + } + + public static abstract class KeyStoreKeyProperties.DigestEnum implements java.lang.annotation.Annotation { + } + + public static abstract class KeyStoreKeyProperties.EncryptionPadding { + field public static final java.lang.String NONE = "NoPadding"; + field public static final java.lang.String PKCS7 = "PKCS7Padding"; + field public static final java.lang.String RSA_OAEP = "OAEPPadding"; + field public static final java.lang.String RSA_PKCS1 = "PKCS1Padding"; + } + + public static abstract class KeyStoreKeyProperties.EncryptionPaddingEnum implements java.lang.annotation.Annotation { + } + public static abstract class KeyStoreKeyProperties.Origin { field public static final int GENERATED = 1; // 0x1 field public static final int IMPORTED = 2; // 0x2 @@ -28761,6 +28808,14 @@ package android.security { public static abstract class KeyStoreKeyProperties.PurposeEnum implements java.lang.annotation.Annotation { } + public static abstract class KeyStoreKeyProperties.SignaturePadding { + field public static final java.lang.String RSA_PKCS1 = "PKCS1"; + field public static final java.lang.String RSA_PSS = "PSS"; + } + + public static abstract class KeyStoreKeyProperties.SignaturePaddingEnum implements java.lang.annotation.Annotation { + } + public class KeyStoreKeySpec implements java.security.spec.KeySpec { method public java.lang.String[] getBlockModes(); method public java.lang.String[] getDigests(); diff --git a/api/system-current.txt b/api/system-current.txt index 63ba05fd76a30..431dcd37752ba 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -30756,6 +30756,53 @@ package android.security { public abstract class KeyStoreKeyProperties { } + public static abstract class KeyStoreKeyProperties.Algorithm { + field public static final java.lang.String AES = "AES"; + field public static final java.lang.String EC = "EC"; + field public static final java.lang.String HMAC_SHA1 = "HmacSHA1"; + field public static final java.lang.String HMAC_SHA224 = "HmacSHA224"; + field public static final java.lang.String HMAC_SHA256 = "HmacSHA256"; + field public static final java.lang.String HMAC_SHA384 = "HmacSHA384"; + field public static final java.lang.String HMAC_SHA512 = "HmacSHA512"; + field public static final java.lang.String RSA = "RSA"; + } + + public static abstract class KeyStoreKeyProperties.AlgorithmEnum implements java.lang.annotation.Annotation { + } + + public static abstract class KeyStoreKeyProperties.BlockMode { + field public static final java.lang.String CBC = "CBC"; + field public static final java.lang.String CTR = "CTR"; + field public static final java.lang.String ECB = "ECB"; + field public static final java.lang.String GCM = "GCM"; + } + + public static abstract class KeyStoreKeyProperties.BlockModeEnum implements java.lang.annotation.Annotation { + } + + public static abstract class KeyStoreKeyProperties.Digest { + field public static final java.lang.String MD5 = "MD5"; + field public static final java.lang.String NONE = "NONE"; + field public static final java.lang.String SHA1 = "SHA-1"; + field public static final java.lang.String SHA224 = "SHA-224"; + field public static final java.lang.String SHA256 = "SHA-256"; + field public static final java.lang.String SHA384 = "SHA-384"; + field public static final java.lang.String SHA512 = "SHA-512"; + } + + public static abstract class KeyStoreKeyProperties.DigestEnum implements java.lang.annotation.Annotation { + } + + public static abstract class KeyStoreKeyProperties.EncryptionPadding { + field public static final java.lang.String NONE = "NoPadding"; + field public static final java.lang.String PKCS7 = "PKCS7Padding"; + field public static final java.lang.String RSA_OAEP = "OAEPPadding"; + field public static final java.lang.String RSA_PKCS1 = "PKCS1Padding"; + } + + public static abstract class KeyStoreKeyProperties.EncryptionPaddingEnum implements java.lang.annotation.Annotation { + } + public static abstract class KeyStoreKeyProperties.Origin { field public static final int GENERATED = 1; // 0x1 field public static final int IMPORTED = 2; // 0x2 @@ -30775,6 +30822,14 @@ package android.security { public static abstract class KeyStoreKeyProperties.PurposeEnum implements java.lang.annotation.Annotation { } + public static abstract class KeyStoreKeyProperties.SignaturePadding { + field public static final java.lang.String RSA_PKCS1 = "PKCS1"; + field public static final java.lang.String RSA_PSS = "PSS"; + } + + public static abstract class KeyStoreKeyProperties.SignaturePaddingEnum implements java.lang.annotation.Annotation { + } + public class KeyStoreKeySpec implements java.security.spec.KeySpec { method public java.lang.String[] getBlockModes(); method public java.lang.String[] getDigests(); diff --git a/keystore/java/android/security/AndroidKeyPairGenerator.java b/keystore/java/android/security/AndroidKeyPairGenerator.java index 3b25ba66b9c31..3f29c6ab83b6a 100644 --- a/keystore/java/android/security/AndroidKeyPairGenerator.java +++ b/keystore/java/android/security/AndroidKeyPairGenerator.java @@ -54,13 +54,13 @@ public abstract class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { public static class RSA extends AndroidKeyPairGenerator { public RSA() { - super("RSA"); + super(KeyStoreKeyProperties.Algorithm.RSA); } } public static class EC extends AndroidKeyPairGenerator { public EC() { - super("EC"); + super(KeyStoreKeyProperties.Algorithm.EC); } } @@ -83,15 +83,15 @@ public abstract class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { private android.security.KeyStore mKeyStore; private KeyPairGeneratorSpec mSpec; - private String mKeyAlgorithm; + private @KeyStoreKeyProperties.AlgorithmEnum String mKeyAlgorithm; private int mKeyType; private int mKeySize; - protected AndroidKeyPairGenerator(String algorithm) { + protected AndroidKeyPairGenerator(@KeyStoreKeyProperties.AlgorithmEnum String algorithm) { mAlgorithm = algorithm; } - public String getAlgorithm() { + public @KeyStoreKeyProperties.AlgorithmEnum String getAlgorithm() { return mAlgorithm; } @@ -197,7 +197,7 @@ public abstract class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { return certGen.generate(privateKey); } - private String getKeyAlgorithm(KeyPairGeneratorSpec spec) { + private @KeyStoreKeyProperties.AlgorithmEnum String getKeyAlgorithm(KeyPairGeneratorSpec spec) { String result = spec.getKeyType(); if (result != null) { return result; @@ -248,10 +248,11 @@ public abstract class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { } } - private static String getDefaultSignatureAlgorithmForKeyAlgorithm(String algorithm) { - if ("RSA".equalsIgnoreCase(algorithm)) { + private static String getDefaultSignatureAlgorithmForKeyAlgorithm( + @KeyStoreKeyProperties.AlgorithmEnum String algorithm) { + if (KeyStoreKeyProperties.Algorithm.RSA.equalsIgnoreCase(algorithm)) { return "sha256WithRSA"; - } else if ("EC".equalsIgnoreCase(algorithm)) { + } else if (KeyStoreKeyProperties.Algorithm.EC.equalsIgnoreCase(algorithm)) { return "sha256WithECDSA"; } else { throw new IllegalArgumentException("Unsupported key type " + algorithm); @@ -287,7 +288,7 @@ public abstract class AndroidKeyPairGenerator extends KeyPairGeneratorSpi { } KeyPairGeneratorSpec spec = (KeyPairGeneratorSpec) params; - String keyAlgorithm = getKeyAlgorithm(spec); + @KeyStoreKeyProperties.AlgorithmEnum String keyAlgorithm = getKeyAlgorithm(spec); int keyType = KeyStore.getKeyTypeForAlgorithm(keyAlgorithm); if (keyType == -1) { throw new InvalidAlgorithmParameterException( diff --git a/keystore/java/android/security/AndroidKeyStore.java b/keystore/java/android/security/AndroidKeyStore.java index 72cb062c8bf43..e82ff6a70acd6 100644 --- a/keystore/java/android/security/AndroidKeyStore.java +++ b/keystore/java/android/security/AndroidKeyStore.java @@ -128,10 +128,11 @@ public class AndroidKeyStore extends KeyStoreSpi { keymasterDigest = keymasterDigests.get(0); } - String keyAlgorithmString; + @KeyStoreKeyProperties.AlgorithmEnum String keyAlgorithmString; try { - keyAlgorithmString = KeymasterUtils.getJcaSecretKeyAlgorithm( - keymasterAlgorithm, keymasterDigest); + keyAlgorithmString = + KeyStoreKeyProperties.Algorithm.fromKeymasterSecretKeyAlgorithm( + keymasterAlgorithm, keymasterDigest); } catch (IllegalArgumentException e) { throw (UnrecoverableKeyException) new UnrecoverableKeyException("Unsupported secret key type").initCause(e); @@ -451,10 +452,10 @@ public class AndroidKeyStore extends KeyStoreSpi { int keymasterAlgorithm; int keymasterDigest; try { - keymasterAlgorithm = KeymasterUtils.getKeymasterAlgorithmFromJcaSecretKeyAlgorithm( + keymasterAlgorithm = KeyStoreKeyProperties.Algorithm.toKeymasterSecretKeyAlgorithm( keyAlgorithmString); keymasterDigest = - KeymasterUtils.getKeymasterDigestfromJcaSecretKeyAlgorithm(keyAlgorithmString); + KeyStoreKeyProperties.Algorithm.toKeymasterDigest(keyAlgorithmString); } catch (IllegalArgumentException e) { throw new KeyStoreException("Unsupported secret key algorithm: " + keyAlgorithmString); } @@ -465,8 +466,7 @@ public class AndroidKeyStore extends KeyStoreSpi { int[] keymasterDigests; if (params.isDigestsSpecified()) { // Digest(s) specified in parameters - keymasterDigests = - KeymasterUtils.getKeymasterDigestsFromJcaDigestAlgorithms(params.getDigests()); + keymasterDigests = KeyStoreKeyProperties.Digest.allToKeymaster(params.getDigests()); if (keymasterDigest != -1) { // Digest also specified in the JCA key algorithm name. if (!com.android.internal.util.ArrayUtils.contains( @@ -494,8 +494,8 @@ public class AndroidKeyStore extends KeyStoreSpi { } @KeyStoreKeyProperties.PurposeEnum int purposes = params.getPurposes(); - int[] keymasterBlockModes = KeymasterUtils.getKeymasterBlockModesFromJcaBlockModes( - params.getBlockModes()); + int[] keymasterBlockModes = + KeyStoreKeyProperties.BlockMode.allToKeymaster(params.getBlockModes()); if (((purposes & KeyStoreKeyProperties.Purpose.ENCRYPT) != 0) && (params.isRandomizedEncryptionRequired())) { for (int keymasterBlockMode : keymasterBlockModes) { @@ -503,8 +503,7 @@ public class AndroidKeyStore extends KeyStoreSpi { throw new KeyStoreException( "Randomized encryption (IND-CPA) required but may be violated by block" + " mode: " - + KeymasterUtils.getJcaBlockModeFromKeymasterBlockMode( - keymasterBlockMode) + + KeyStoreKeyProperties.BlockMode.fromKeymaster(keymasterBlockMode) + ". See KeyStoreParameter documentation."); } } @@ -513,11 +512,11 @@ public class AndroidKeyStore extends KeyStoreSpi { args.addInt(KeymasterDefs.KM_TAG_PURPOSE, keymasterPurpose); } args.addInts(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockModes); - int[] keymasterPaddings = ArrayUtils.concat( - KeymasterUtils.getKeymasterPaddingsFromJcaEncryptionPaddings( - params.getEncryptionPaddings()), - KeymasterUtils.getKeymasterPaddingsFromJcaSignaturePaddings( - params.getSignaturePaddings())); + if (params.getSignaturePaddings().length > 0) { + throw new KeyStoreException("Signature paddings not supported for symmetric keys"); + } + int[] keymasterPaddings = KeyStoreKeyProperties.EncryptionPadding.allToKeymaster( + params.getEncryptionPaddings()); args.addInts(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings); KeymasterUtils.addUserAuthArgs(args, params.getContext(), diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java index e9c24ddc7afb8..8e27dc39ae985 100644 --- a/keystore/java/android/security/KeyChain.java +++ b/keystore/java/android/security/KeyChain.java @@ -262,7 +262,8 @@ public final class KeyChain { * unavailable. */ public static void choosePrivateKeyAlias(Activity activity, KeyChainAliasCallback response, - String[] keyTypes, Principal[] issuers, String host, int port, String alias) { + @KeyStoreKeyProperties.AlgorithmEnum String[] keyTypes, Principal[] issuers, + String host, int port, String alias) { choosePrivateKeyAlias(activity, response, keyTypes, issuers, host, port, null, alias); } @@ -306,9 +307,8 @@ public final class KeyChain { * unavailable. */ public static void choosePrivateKeyAlias(Activity activity, KeyChainAliasCallback response, - String[] keyTypes, Principal[] issuers, - String host, int port, String url, - String alias) { + @KeyStoreKeyProperties.AlgorithmEnum String[] keyTypes, Principal[] issuers, + String host, int port, String url, String alias) { /* * TODO currently keyTypes, issuers are unused. They are meant * to follow the semantics and purpose of X509KeyManager @@ -431,9 +431,11 @@ public final class KeyChain { * specific {@code PrivateKey} type indicated by {@code algorithm} (e.g., * "RSA"). */ - public static boolean isKeyAlgorithmSupported(String algorithm) { + public static boolean isKeyAlgorithmSupported( + @KeyStoreKeyProperties.AlgorithmEnum String algorithm) { final String algUpper = algorithm.toUpperCase(Locale.US); - return "EC".equals(algUpper) || "RSA".equals(algUpper); + return KeyStoreKeyProperties.Algorithm.EC.equals(algUpper) + || KeyStoreKeyProperties.Algorithm.RSA.equals(algUpper); } /** @@ -443,7 +445,8 @@ public final class KeyChain { * hardware support that can be used to bind keys to the device in a way * that makes it non-exportable. */ - public static boolean isBoundKeyAlgorithm(String algorithm) { + public static boolean isBoundKeyAlgorithm( + @KeyStoreKeyProperties.AlgorithmEnum String algorithm) { if (!isKeyAlgorithmSupported(algorithm)) { return false; } diff --git a/keystore/java/android/security/KeyGeneratorSpec.java b/keystore/java/android/security/KeyGeneratorSpec.java index 8f135a6f4b7b1..875cbd5f4f007 100644 --- a/keystore/java/android/security/KeyGeneratorSpec.java +++ b/keystore/java/android/security/KeyGeneratorSpec.java @@ -48,8 +48,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { private final Date mKeyValidityForOriginationEnd; private final Date mKeyValidityForConsumptionEnd; private final @KeyStoreKeyProperties.PurposeEnum int mPurposes; - private final String[] mEncryptionPaddings; - private final String[] mBlockModes; + private final @KeyStoreKeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings; + private final @KeyStoreKeyProperties.BlockModeEnum String[] mBlockModes; private final boolean mRandomizedEncryptionRequired; private final boolean mUserAuthenticationRequired; private final int mUserAuthenticationValidityDurationSeconds; @@ -63,8 +63,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { Date keyValidityForOriginationEnd, Date keyValidityForConsumptionEnd, @KeyStoreKeyProperties.PurposeEnum int purposes, - String[] encryptionPaddings, - String[] blockModes, + @KeyStoreKeyProperties.EncryptionPaddingEnum String[] encryptionPaddings, + @KeyStoreKeyProperties.BlockModeEnum String[] blockModes, boolean randomizedEncryptionRequired, boolean userAuthenticationRequired, int userAuthenticationValidityDurationSeconds) { @@ -160,14 +160,14 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { /** * Gets the set of padding schemes with which the key can be used when encrypting/decrypting. */ - public String[] getEncryptionPaddings() { + public @KeyStoreKeyProperties.EncryptionPaddingEnum String[] getEncryptionPaddings() { return ArrayUtils.cloneIfNotEmpty(mEncryptionPaddings); } /** * Gets the set of block modes with which the key can be used. */ - public String[] getBlockModes() { + public @KeyStoreKeyProperties.BlockModeEnum String[] getBlockModes() { return ArrayUtils.cloneIfNotEmpty(mBlockModes); } @@ -220,8 +220,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { private Date mKeyValidityForOriginationEnd; private Date mKeyValidityForConsumptionEnd; private @KeyStoreKeyProperties.PurposeEnum int mPurposes; - private String[] mEncryptionPaddings; - private String[] mBlockModes; + private @KeyStoreKeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings; + private @KeyStoreKeyProperties.BlockModeEnum String[] mBlockModes; private boolean mRandomizedEncryptionRequired = true; private boolean mUserAuthenticationRequired; private int mUserAuthenticationValidityDurationSeconds = -1; @@ -346,7 +346,8 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { * *
This must be specified for keys which are used for encryption/decryption. */ - public Builder setEncryptionPaddings(String... paddings) { + public Builder setEncryptionPaddings( + @KeyStoreKeyProperties.EncryptionPaddingEnum String... paddings) { mEncryptionPaddings = ArrayUtils.cloneIfNotEmpty(paddings); return this; } @@ -357,7 +358,7 @@ public class KeyGeneratorSpec implements AlgorithmParameterSpec { * *
This must be specified for encryption/decryption keys. */ - public Builder setBlockModes(String... blockModes) { + public Builder setBlockModes(@KeyStoreKeyProperties.BlockModeEnum String... blockModes) { mBlockModes = ArrayUtils.cloneIfNotEmpty(blockModes); return this; } diff --git a/keystore/java/android/security/KeyPairGeneratorSpec.java b/keystore/java/android/security/KeyPairGeneratorSpec.java index d6d37897eee4c..0e341103322e7 100644 --- a/keystore/java/android/security/KeyPairGeneratorSpec.java +++ b/keystore/java/android/security/KeyPairGeneratorSpec.java @@ -85,13 +85,13 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { private final @KeyStoreKeyProperties.PurposeEnum int mPurposes; - private final String[] mDigests; + private final @KeyStoreKeyProperties.DigestEnum String[] mDigests; - private final String[] mEncryptionPaddings; + private final @KeyStoreKeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings; - private final String[] mSignaturePaddings; + private final @KeyStoreKeyProperties.SignaturePaddingEnum String[] mSignaturePaddings; - private final String[] mBlockModes; + private final @KeyStoreKeyProperties.BlockModeEnum String[] mBlockModes; private final boolean mRandomizedEncryptionRequired; @@ -138,10 +138,10 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { Date keyValidityForOriginationEnd, Date keyValidityForConsumptionEnd, @KeyStoreKeyProperties.PurposeEnum int purposes, - String[] digests, - String[] encryptionPaddings, - String[] signaturePaddings, - String[] blockModes, + @KeyStoreKeyProperties.DigestEnum String[] digests, + @KeyStoreKeyProperties.EncryptionPaddingEnum String[] encryptionPaddings, + @KeyStoreKeyProperties.SignaturePaddingEnum String[] signaturePaddings, + @KeyStoreKeyProperties.BlockModeEnum String[] blockModes, boolean randomizedEncryptionRequired, boolean userAuthenticationRequired, int userAuthenticationValidityDurationSeconds) { @@ -246,7 +246,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { /** * Returns the key type (e.g., "EC", "RSA") specified by this parameter. */ - public String getKeyType() { + public @KeyStoreKeyProperties.AlgorithmEnum String getKeyType() { return mKeyType; } @@ -352,28 +352,28 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { /** * Gets the set of digest algorithms with which the key can be used. */ - public String[] getDigests() { + public @KeyStoreKeyProperties.DigestEnum String[] getDigests() { return ArrayUtils.cloneIfNotEmpty(mDigests); } /** * Gets the set of padding schemes with which the key can be used when encrypting/decrypting. */ - public String[] getEncryptionPaddings() { + public @KeyStoreKeyProperties.EncryptionPaddingEnum String[] getEncryptionPaddings() { return ArrayUtils.cloneIfNotEmpty(mEncryptionPaddings); } /** * Gets the set of padding schemes with which the key can be used when signing/verifying. */ - public String[] getSignaturePaddings() { + public @KeyStoreKeyProperties.SignaturePaddingEnum String[] getSignaturePaddings() { return ArrayUtils.cloneIfNotEmpty(mSignaturePaddings); } /** * Gets the set of block modes with which the key can be used. */ - public String[] getBlockModes() { + public @KeyStoreKeyProperties.BlockModeEnum String[] getBlockModes() { return ArrayUtils.cloneIfNotEmpty(mBlockModes); } @@ -468,13 +468,13 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { private @KeyStoreKeyProperties.PurposeEnum int mPurposes; - private String[] mDigests; + private @KeyStoreKeyProperties.DigestEnum String[] mDigests; - private String[] mEncryptionPaddings; + private @KeyStoreKeyProperties.EncryptionPaddingEnum String[] mEncryptionPaddings; - private String[] mSignaturePaddings; + private @KeyStoreKeyProperties.SignaturePaddingEnum String[] mSignaturePaddings; - private String[] mBlockModes; + private @KeyStoreKeyProperties.BlockModeEnum String[] mBlockModes; private boolean mRandomizedEncryptionRequired = true; @@ -511,7 +511,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { /** * Sets the key type (e.g., EC, RSA) of the keypair to be created. */ - public Builder setKeyType(String keyType) throws NoSuchAlgorithmException { + public Builder setKeyType(@KeyStoreKeyProperties.AlgorithmEnum String keyType) + throws NoSuchAlgorithmException { if (keyType == null) { throw new NullPointerException("keyType == null"); } else { @@ -691,7 +692,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * *
This must be specified for keys which are used for signing/verification. */ - public Builder setDigests(String... digests) { + public Builder setDigests(@KeyStoreKeyProperties.DigestEnum String... digests) { mDigests = ArrayUtils.cloneIfNotEmpty(digests); return this; } @@ -703,7 +704,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * *
This must be specified for keys which are used for encryption/decryption. */ - public Builder setEncryptionPaddings(String... paddings) { + public Builder setEncryptionPaddings( + @KeyStoreKeyProperties.EncryptionPaddingEnum String... paddings) { mEncryptionPaddings = ArrayUtils.cloneIfNotEmpty(paddings); return this; } @@ -715,7 +717,8 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * *
This must be specified for RSA keys which are used for signing/verification. */ - public Builder setSignaturePaddings(String... paddings) { + public Builder setSignaturePaddings( + @KeyStoreKeyProperties.SignaturePaddingEnum String... paddings) { mSignaturePaddings = ArrayUtils.cloneIfNotEmpty(paddings); return this; } @@ -726,7 +729,7 @@ public final class KeyPairGeneratorSpec implements AlgorithmParameterSpec { * *
This must be specified for encryption/decryption keys. */ - public Builder setBlockModes(String... blockModes) { + public Builder setBlockModes(@KeyStoreKeyProperties.BlockModeEnum String... blockModes) { mBlockModes = ArrayUtils.cloneIfNotEmpty(blockModes); return this; } diff --git a/keystore/java/android/security/KeyStore.java b/keystore/java/android/security/KeyStore.java index 82d328b0b71ff..304d2772312a7 100644 --- a/keystore/java/android/security/KeyStore.java +++ b/keystore/java/android/security/KeyStore.java @@ -115,10 +115,10 @@ public class KeyStore { return mToken; } - static int getKeyTypeForAlgorithm(String keyType) { - if ("RSA".equalsIgnoreCase(keyType)) { + static int getKeyTypeForAlgorithm(@KeyStoreKeyProperties.AlgorithmEnum String keyType) { + if (KeyStoreKeyProperties.Algorithm.RSA.equalsIgnoreCase(keyType)) { return NativeConstants.EVP_PKEY_RSA; - } else if ("EC".equalsIgnoreCase(keyType)) { + } else if (KeyStoreKeyProperties.Algorithm.EC.equalsIgnoreCase(keyType)) { return NativeConstants.EVP_PKEY_EC; } else { return -1; diff --git a/keystore/java/android/security/KeyStoreCipherSpi.java b/keystore/java/android/security/KeyStoreCipherSpi.java index 094aa75bf4b23..28bc3d20650de 100644 --- a/keystore/java/android/security/KeyStoreCipherSpi.java +++ b/keystore/java/android/security/KeyStoreCipherSpi.java @@ -494,7 +494,8 @@ public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCry } if ((mIv != null) && (mIv.length > 0)) { try { - AlgorithmParameters params = AlgorithmParameters.getInstance("AES"); + AlgorithmParameters params = + AlgorithmParameters.getInstance(KeyStoreKeyProperties.Algorithm.AES); params.init(new IvParameterSpec(mIv)); return params; } catch (NoSuchAlgorithmException e) { diff --git a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java index 68b57518ae703..e69648c6d98e4 100644 --- a/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java +++ b/keystore/java/android/security/KeyStoreKeyGeneratorSpi.java @@ -129,8 +129,8 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { int keySizeBits = (spec.getKeySize() != -1) ? spec.getKeySize() : mDefaultKeySizeBits; args.addInt(KeymasterDefs.KM_TAG_KEY_SIZE, keySizeBits); @KeyStoreKeyProperties.PurposeEnum int purposes = spec.getPurposes(); - int[] keymasterBlockModes = KeymasterUtils.getKeymasterBlockModesFromJcaBlockModes( - spec.getBlockModes()); + int[] keymasterBlockModes = + KeyStoreKeyProperties.BlockMode.allToKeymaster(spec.getBlockModes()); if (((purposes & KeyStoreKeyProperties.Purpose.ENCRYPT) != 0) && (spec.isRandomizedEncryptionRequired())) { for (int keymasterBlockMode : keymasterBlockModes) { @@ -138,8 +138,7 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { throw new IllegalStateException( "Randomized encryption (IND-CPA) required but may be violated by block" + " mode: " - + KeymasterUtils.getJcaBlockModeFromKeymasterBlockMode( - keymasterBlockMode) + + KeyStoreKeyProperties.BlockMode.fromKeymaster(keymasterBlockMode) + ". See KeyGeneratorSpec documentation."); } } @@ -152,7 +151,7 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { args.addInts(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockModes); args.addInts( KeymasterDefs.KM_TAG_PADDING, - KeymasterUtils.getKeymasterPaddingsFromJcaEncryptionPaddings( + KeyStoreKeyProperties.EncryptionPadding.allToKeymaster( spec.getEncryptionPaddings())); KeymasterUtils.addUserAuthArgs(args, spec.getContext(), @@ -189,8 +188,9 @@ public abstract class KeyStoreKeyGeneratorSpi extends KeyGeneratorSpi { throw new IllegalStateException( "Keystore operation failed", KeyStore.getKeyStoreException(errorCode)); } - String keyAlgorithmJCA = - KeymasterUtils.getJcaSecretKeyAlgorithm(mKeymasterAlgorithm, mKeymasterDigest); + @KeyStoreKeyProperties.AlgorithmEnum String keyAlgorithmJCA = + KeyStoreKeyProperties.Algorithm.fromKeymasterSecretKeyAlgorithm( + mKeymasterAlgorithm, mKeymasterDigest); return new KeyStoreSecretKey(keyAliasInKeystore, keyAlgorithmJCA); } diff --git a/keystore/java/android/security/KeyStoreKeyProperties.java b/keystore/java/android/security/KeyStoreKeyProperties.java index b85ec531f245c..1c3e3005acffb 100644 --- a/keystore/java/android/security/KeyStoreKeyProperties.java +++ b/keystore/java/android/security/KeyStoreKeyProperties.java @@ -17,13 +17,23 @@ package android.security; import android.annotation.IntDef; +import android.annotation.StringDef; import android.security.keymaster.KeymasterDefs; import libcore.util.EmptyArray; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.security.Key; +import java.security.KeyFactory; +import java.security.KeyPairGenerator; import java.util.Collection; +import java.util.Locale; + +import javax.crypto.Cipher; +import javax.crypto.KeyGenerator; +import javax.crypto.Mac; +import javax.crypto.SecretKeyFactory; /** * Properties of {@code AndroidKeyStore} keys. @@ -37,7 +47,7 @@ public abstract class KeyStoreKeyProperties { public @interface PurposeEnum {} /** - * Purpose of key. + * Purposes of key. */ public static abstract class Purpose { private Purpose() {} @@ -121,6 +131,514 @@ public abstract class KeyStoreKeyProperties { } } + @Retention(RetentionPolicy.SOURCE) + @StringDef({ + Algorithm.RSA, + Algorithm.EC, + Algorithm.AES, + Algorithm.HMAC_SHA1, + Algorithm.HMAC_SHA224, + Algorithm.HMAC_SHA256, + Algorithm.HMAC_SHA384, + Algorithm.HMAC_SHA512, + }) + public @interface AlgorithmEnum {} + + /** + * Key algorithms. + * + *
These are standard names which can be used to obtain instances of {@link KeyGenerator},
+ * {@link KeyPairGenerator}, {@link Cipher} (as part of the transformation string), {@link Mac},
+ * {@link KeyFactory}, {@link SecretKeyFactory}. These are also the names used by
+ * {@link Key#getAlgorithm()}.
+ */
+ public static abstract class Algorithm {
+ private Algorithm() {}
+
+ /** Rivest Shamir Adleman (RSA) key. */
+ public static final String RSA = "RSA";
+
+ /** Elliptic Curve (EC) key. */
+ public static final String EC = "EC";
+
+ /** Advanced Encryption Standard (AES) key. */
+ public static final String AES = "AES";
+
+ /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-1 as the hash. */
+ public static final String HMAC_SHA1 = "HmacSHA1";
+
+ /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-224 as the hash. */
+ public static final String HMAC_SHA224 = "HmacSHA224";
+
+ /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-256 as the hash. */
+ public static final String HMAC_SHA256 = "HmacSHA256";
+
+ /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-384 as the hash. */
+ public static final String HMAC_SHA384 = "HmacSHA384";
+
+ /** Keyed-Hash Message Authentication Code (HMAC) key using SHA-512 as the hash. */
+ public static final String HMAC_SHA512 = "HmacSHA512";
+
+ /**
+ * @hide
+ */
+ static int toKeymasterSecretKeyAlgorithm(@AlgorithmEnum String algorithm) {
+ if (AES.equalsIgnoreCase(algorithm)) {
+ return KeymasterDefs.KM_ALGORITHM_AES;
+ } else if (algorithm.toUpperCase(Locale.US).startsWith("HMAC")) {
+ return KeymasterDefs.KM_ALGORITHM_HMAC;
+ } else {
+ throw new IllegalArgumentException(
+ "Unsupported secret key algorithm: " + algorithm);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ static @AlgorithmEnum String fromKeymasterSecretKeyAlgorithm(
+ int keymasterAlgorithm, int keymasterDigest) {
+ switch (keymasterAlgorithm) {
+ case KeymasterDefs.KM_ALGORITHM_AES:
+ if (keymasterDigest != -1) {
+ throw new IllegalArgumentException("Digest not supported for AES key: "
+ + Digest.fromKeymaster(keymasterDigest));
+ }
+ return AES;
+ case KeymasterDefs.KM_ALGORITHM_HMAC:
+ switch (keymasterDigest) {
+ case KeymasterDefs.KM_DIGEST_SHA1:
+ return HMAC_SHA1;
+ case KeymasterDefs.KM_DIGEST_SHA_2_224:
+ return HMAC_SHA224;
+ case KeymasterDefs.KM_DIGEST_SHA_2_256:
+ return HMAC_SHA256;
+ case KeymasterDefs.KM_DIGEST_SHA_2_384:
+ return HMAC_SHA384;
+ case KeymasterDefs.KM_DIGEST_SHA_2_512:
+ return HMAC_SHA512;
+ default:
+ throw new IllegalArgumentException("Unsupported HMAC digest: "
+ + Digest.fromKeymaster(keymasterDigest));
+ }
+ default:
+ throw new IllegalArgumentException(
+ "Unsupported algorithm: " + keymasterAlgorithm);
+ }
+ }
+
+ /**
+ * @hide
+ *
+ * @return keymaster digest or {@code -1} if the algorithm does not involve a digest.
+ */
+ static int toKeymasterDigest(@AlgorithmEnum String algorithm) {
+ String algorithmUpper = algorithm.toUpperCase(Locale.US);
+ if (algorithmUpper.startsWith("HMAC")) {
+ String digestUpper = algorithmUpper.substring("HMAC".length());
+ switch (digestUpper) {
+ case "SHA1":
+ return KeymasterDefs.KM_DIGEST_SHA1;
+ case "SHA224":
+ return KeymasterDefs.KM_DIGEST_SHA_2_224;
+ case "SHA256":
+ return KeymasterDefs.KM_DIGEST_SHA_2_256;
+ case "SHA384":
+ return KeymasterDefs.KM_DIGEST_SHA_2_384;
+ case "SHA512":
+ return KeymasterDefs.KM_DIGEST_SHA_2_512;
+ default:
+ throw new IllegalArgumentException(
+ "Unsupported HMAC digest: " + digestUpper);
+ }
+ } else {
+ return -1;
+ }
+ }
+ }
+
+ @Retention(RetentionPolicy.SOURCE)
+ @StringDef({
+ BlockMode.ECB,
+ BlockMode.CBC,
+ BlockMode.CTR,
+ BlockMode.GCM,
+ })
+ public @interface BlockModeEnum {}
+
+ /**
+ * Block modes that can be used when encrypting/decrypting using a key.
+ */
+ public static abstract class BlockMode {
+ private BlockMode() {}
+
+ /** Electronic Codebook (ECB) block mode. */
+ public static final String ECB = "ECB";
+
+ /** Cipher Block Chaining (CBC) block mode. */
+ public static final String CBC = "CBC";
+
+ /** Counter (CTR) block mode. */
+ public static final String CTR = "CTR";
+
+ /** Galois/Counter Mode (GCM) block mode. */
+ public static final String GCM = "GCM";
+
+ /**
+ * @hide
+ */
+ static int toKeymaster(@BlockModeEnum String blockMode) {
+ if (ECB.equalsIgnoreCase(blockMode)) {
+ return KeymasterDefs.KM_MODE_ECB;
+ } else if (CBC.equalsIgnoreCase(blockMode)) {
+ return KeymasterDefs.KM_MODE_CBC;
+ } else if (CTR.equalsIgnoreCase(blockMode)) {
+ return KeymasterDefs.KM_MODE_CTR;
+ } else if (GCM.equalsIgnoreCase(blockMode)) {
+ return KeymasterDefs.KM_MODE_GCM;
+ } else {
+ throw new IllegalArgumentException("Unsupported block mode: " + blockMode);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ static @BlockModeEnum String fromKeymaster(int blockMode) {
+ switch (blockMode) {
+ case KeymasterDefs.KM_MODE_ECB:
+ return ECB;
+ case KeymasterDefs.KM_MODE_CBC:
+ return CBC;
+ case KeymasterDefs.KM_MODE_CTR:
+ return CTR;
+ case KeymasterDefs.KM_MODE_GCM:
+ return GCM;
+ default:
+ throw new IllegalArgumentException("Unsupported block mode: " + blockMode);
+ }
+ }
+
+ /**
+ * @hide
+ */
+ static @BlockModeEnum String[] allFromKeymaster(Collection This must be specified for keys which are used for encryption/decryption.
*/
- public Builder setEncryptionPaddings(String... paddings) {
+ public Builder setEncryptionPaddings(
+ @KeyStoreKeyProperties.EncryptionPaddingEnum String... paddings) {
mEncryptionPaddings = ArrayUtils.cloneIfNotEmpty(paddings);
return this;
}
@@ -368,7 +369,8 @@ public final class KeyStoreParameter implements ProtectionParameter {
*
* This must be specified for RSA keys which are used for signing/verification.
*/
- public Builder setSignaturePaddings(String... paddings) {
+ public Builder setSignaturePaddings(
+ @KeyStoreKeyProperties.SignaturePaddingEnum String... paddings) {
mSignaturePaddings = ArrayUtils.cloneIfNotEmpty(paddings);
return this;
}
@@ -381,7 +383,7 @@ public final class KeyStoreParameter implements ProtectionParameter {
* For HMAC keys, the default is the digest specified in {@link Key#getAlgorithm()}. For
* asymmetric signing keys this constraint must be specified.
*/
- public Builder setDigests(String... digests) {
+ public Builder setDigests(@KeyStoreKeyProperties.DigestEnum String... digests) {
mDigests = ArrayUtils.cloneIfNotEmpty(digests);
return this;
}
@@ -392,7 +394,7 @@ public final class KeyStoreParameter implements ProtectionParameter {
*
* This must be specified for encryption/decryption keys.
*/
- public Builder setBlockModes(String... blockModes) {
+ public Builder setBlockModes(@KeyStoreKeyProperties.BlockModeEnum String... blockModes) {
mBlockModes = ArrayUtils.cloneIfNotEmpty(blockModes);
return this;
}
diff --git a/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java b/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java
index bfe09e3e1b734..ff79b7a4a4ff5 100644
--- a/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java
+++ b/keystore/java/android/security/KeyStoreSecretKeyFactorySpi.java
@@ -79,8 +79,8 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
int keySize;
@KeyStoreKeyProperties.PurposeEnum int purposes;
String[] encryptionPaddings;
- String[] digests;
- String[] blockModes;
+ @KeyStoreKeyProperties.DigestEnum String[] digests;
+ @KeyStoreKeyProperties.BlockModeEnum String[] blockModes;
int keymasterSwEnforcedUserAuthenticators;
int keymasterHwEnforcedUserAuthenticators;
try {
@@ -105,10 +105,10 @@ public class KeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi {
List