summaryrefslogtreecommitdiff
path: root/keystore
diff options
context:
space:
mode:
Diffstat (limited to 'keystore')
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java23
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java5
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java4
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java111
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java25
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreLoadStoreParameter.java4
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java31
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java26
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java48
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java81
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java13
-rw-r--r--keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java27
-rw-r--r--keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java2
13 files changed, 307 insertions, 93 deletions
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java
index 21ae5d2ae6b4..56f7ea8725ee 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStore3DESCipherSpi.java
@@ -41,7 +41,7 @@ import javax.crypto.spec.IvParameterSpec;
*
* @hide
*/
-public class AndroidKeyStore3DESCipherSpi extends AndroidKeyStoreCipherSpiBase {
+public abstract class AndroidKeyStore3DESCipherSpi extends AndroidKeyStoreCipherSpiBase {
private static final int BLOCK_SIZE_BYTES = 8;
@@ -73,12 +73,22 @@ public class AndroidKeyStore3DESCipherSpi extends AndroidKeyStoreCipherSpiBase {
public NoPadding() {
super(KeymasterDefs.KM_PAD_NONE);
}
+
+ @Override
+ protected final String getTransform() {
+ return "DESede/ECB/NoPadding";
+ }
}
public static class PKCS7Padding extends ECB {
public PKCS7Padding() {
super(KeymasterDefs.KM_PAD_PKCS7);
}
+
+ @Override
+ protected final String getTransform() {
+ return "DESede/ECB/PKCS7Padding";
+ }
}
}
@@ -91,12 +101,23 @@ public class AndroidKeyStore3DESCipherSpi extends AndroidKeyStoreCipherSpiBase {
public NoPadding() {
super(KeymasterDefs.KM_PAD_NONE);
}
+
+ @Override
+ protected final String getTransform() {
+ return "DESede/CBC/NoPadding";
+ }
+
}
public static class PKCS7Padding extends CBC {
public PKCS7Padding() {
super(KeymasterDefs.KM_PAD_PKCS7);
}
+
+ @Override
+ protected final String getTransform() {
+ return "DESede/CBC/PKCS7Padding";
+ }
}
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java
index efb4208ed8be..64da83778a45 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreAuthenticatedAESCipherSpi.java
@@ -64,6 +64,11 @@ abstract class AndroidKeyStoreAuthenticatedAESCipherSpi extends AndroidKeyStoreC
}
@Override
+ protected final String getTransform() {
+ return "AES/GCM/NoPadding";
+ }
+
+ @Override
protected final void resetAll() {
mTagLengthBits = DEFAULT_TAG_LENGTH_BITS;
super.resetAll();
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java
index dd943d422e62..9ad6f3adbd33 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreBCWorkaroundProvider.java
@@ -254,13 +254,13 @@ class AndroidKeyStoreBCWorkaroundProvider extends Provider {
private void putAsymmetricCipherImpl(String transformation, String implClass) {
put("Cipher." + transformation, implClass);
put("Cipher." + transformation + " SupportedKeyClasses",
- KEYSTORE_PRIVATE_KEY_CLASS_NAME + "|" + KEYSTORE_PUBLIC_KEY_CLASS_NAME);
+ KEYSTORE_PRIVATE_KEY_CLASS_NAME);
}
private void putSignatureImpl(String algorithm, String implClass) {
put("Signature." + algorithm, implClass);
put("Signature." + algorithm + " SupportedKeyClasses",
- KEYSTORE_PRIVATE_KEY_CLASS_NAME + "|" + KEYSTORE_PUBLIC_KEY_CLASS_NAME);
+ KEYSTORE_PRIVATE_KEY_CLASS_NAME);
}
public static String[] getSupportedEcdsaSignatureDigests() {
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
index a3b04abfba3f..2ee952cbc5fb 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreCipherSpiBase.java
@@ -43,6 +43,7 @@ import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException;
+import java.security.spec.MGF1ParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList;
@@ -57,6 +58,8 @@ import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.ShortBufferException;
+import javax.crypto.spec.OAEPParameterSpec;
+import javax.crypto.spec.PSource;
import javax.crypto.spec.SecretKeySpec;
/**
@@ -99,6 +102,8 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
*/
private Exception mCachedException;
+ private Cipher mCipher;
+
AndroidKeyStoreCipherSpiBase() {
mOperation = null;
mEncrypting = false;
@@ -110,6 +115,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
mAdditionalAuthenticationDataStreamer = null;
mAdditionalAuthenticationDataStreamerClosed = false;
mCachedException = null;
+ mCipher = null;
}
@Override
@@ -117,6 +123,45 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
throws InvalidKeyException {
resetAll();
+ if (!(key instanceof AndroidKeyStorePrivateKey
+ || key instanceof AndroidKeyStoreSecretKey)) {
+ try {
+ mCipher = Cipher.getInstance(getTransform());
+ String transform = getTransform();
+
+ if ("RSA/ECB/OAEPWithSHA-224AndMGF1Padding".equals(transform)) {
+ OAEPParameterSpec spec =
+ new OAEPParameterSpec("SHA-224", "MGF1",
+ new MGF1ParameterSpec("SHA1"), 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);
+ 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);
+ 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);
+ mCipher.init(opmode, key, spec, random);
+ } else {
+ mCipher.init(opmode, key, random);
+ }
+ return;
+ } catch (NoSuchAlgorithmException
+ | NoSuchPaddingException
+ | InvalidAlgorithmParameterException e) {
+ throw new InvalidKeyException(e);
+ }
+ }
+
boolean success = false;
try {
init(opmode, key, random);
@@ -139,6 +184,17 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
resetAll();
+ if (!(key instanceof AndroidKeyStorePrivateKey
+ || key instanceof AndroidKeyStoreSecretKey)) {
+ try {
+ mCipher = Cipher.getInstance(getTransform());
+ mCipher.init(opmode, key, params, random);
+ return;
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+ throw new InvalidKeyException(e);
+ }
+ }
+
boolean success = false;
try {
init(opmode, key, random);
@@ -157,6 +213,17 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
resetAll();
+ if (!(key instanceof AndroidKeyStorePrivateKey
+ || key instanceof AndroidKeyStoreSecretKey)) {
+ try {
+ mCipher = Cipher.getInstance(getTransform());
+ mCipher.init(opmode, key, params, random);
+ return;
+ } catch (NoSuchAlgorithmException | NoSuchPaddingException e) {
+ throw new InvalidKeyException(e);
+ }
+ }
+
boolean success = false;
try {
init(opmode, key, random);
@@ -214,6 +281,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
mAdditionalAuthenticationDataStreamer = null;
mAdditionalAuthenticationDataStreamerClosed = false;
mCachedException = null;
+ mCipher = null;
}
/**
@@ -320,6 +388,10 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override
protected final byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
+ if (mCipher != null) {
+ return mCipher.update(input, inputOffset, inputLen);
+ }
+
if (mCachedException != null) {
return null;
}
@@ -371,6 +443,9 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override
protected final int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output,
int outputOffset) throws ShortBufferException {
+ if (mCipher != null) {
+ return mCipher.update(input, inputOffset, inputLen, output);
+ }
byte[] outputCopy = engineUpdate(input, inputOffset, inputLen);
if (outputCopy == null) {
return 0;
@@ -387,6 +462,10 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override
protected final int engineUpdate(ByteBuffer input, ByteBuffer output)
throws ShortBufferException {
+ if (mCipher != null) {
+ return mCipher.update(input, output);
+ }
+
if (input == null) {
throw new NullPointerException("input == null");
}
@@ -423,6 +502,11 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override
protected final void engineUpdateAAD(byte[] input, int inputOffset, int inputLen) {
+ if (mCipher != null) {
+ mCipher.updateAAD(input, inputOffset, inputLen);
+ return;
+ }
+
if (mCachedException != null) {
return;
}
@@ -459,6 +543,11 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override
protected final void engineUpdateAAD(ByteBuffer src) {
+ if (mCipher != null) {
+ mCipher.updateAAD(src);
+ return;
+ }
+
if (src == null) {
throw new IllegalArgumentException("src == null");
}
@@ -486,6 +575,10 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override
protected final byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
throws IllegalBlockSizeException, BadPaddingException {
+ if (mCipher != null) {
+ return mCipher.doFinal(input, inputOffset, inputLen);
+ }
+
if (mCachedException != null) {
throw (IllegalBlockSizeException)
new IllegalBlockSizeException().initCause(mCachedException);
@@ -522,6 +615,10 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
protected final int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
int outputOffset) throws ShortBufferException, IllegalBlockSizeException,
BadPaddingException {
+ if (mCipher != null) {
+ return mCipher.doFinal(input, inputOffset, inputLen, output);
+ }
+
byte[] outputCopy = engineDoFinal(input, inputOffset, inputLen);
if (outputCopy == null) {
return 0;
@@ -538,6 +635,10 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override
protected final int engineDoFinal(ByteBuffer input, ByteBuffer output)
throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
+ if (mCipher != null) {
+ return mCipher.doFinal(input, output);
+ }
+
if (input == null) {
throw new NullPointerException("input == null");
}
@@ -575,6 +676,10 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override
protected final byte[] engineWrap(Key key)
throws IllegalBlockSizeException, InvalidKeyException {
+ if (mCipher != null) {
+ return mCipher.wrap(key);
+ }
+
if (mKey == null) {
throw new IllegalStateException("Not initilized");
}
@@ -656,6 +761,10 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override
protected final Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException {
+ if (mCipher != null) {
+ return mCipher.unwrap(wrappedKey, wrappedKeyAlgorithm, wrappedKeyType);
+ }
+
if (mKey == null) {
throw new IllegalStateException("Not initilized");
}
@@ -902,4 +1011,6 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
*/
protected abstract void loadAlgorithmSpecificParametersFromBeginResult(
KeyParameter[] parameters);
+
+ protected abstract String getTransform();
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
index d1ef1df817e6..8289671de212 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreECDSASignatureSpi.java
@@ -44,6 +44,11 @@ abstract class AndroidKeyStoreECDSASignatureSpi extends AndroidKeyStoreSignature
}
@Override
+ protected String getAlgorithm() {
+ return "NONEwithECDSA";
+ }
+
+ @Override
protected KeyStoreCryptoOperationStreamer createMainDataStreamer(
KeyStoreOperation operation) {
return new TruncateToFieldSizeMessageStreamer(
@@ -113,30 +118,50 @@ abstract class AndroidKeyStoreECDSASignatureSpi extends AndroidKeyStoreSignature
public SHA1() {
super(KeymasterDefs.KM_DIGEST_SHA1);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA1withECDSA";
+ }
}
public final static class SHA224 extends AndroidKeyStoreECDSASignatureSpi {
public SHA224() {
super(KeymasterDefs.KM_DIGEST_SHA_2_224);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA224withECDSA";
+ }
}
public final static class SHA256 extends AndroidKeyStoreECDSASignatureSpi {
public SHA256() {
super(KeymasterDefs.KM_DIGEST_SHA_2_256);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA256withECDSA";
+ }
}
public final static class SHA384 extends AndroidKeyStoreECDSASignatureSpi {
public SHA384() {
super(KeymasterDefs.KM_DIGEST_SHA_2_384);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA384withECDSA";
+ }
}
public final static class SHA512 extends AndroidKeyStoreECDSASignatureSpi {
public SHA512() {
super(KeymasterDefs.KM_DIGEST_SHA_2_512);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA512withECDSA";
+ }
}
private final int mKeymasterDigest;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreLoadStoreParameter.java b/keystore/java/android/security/keystore2/AndroidKeyStoreLoadStoreParameter.java
index afb10547411b..0c6744f9822c 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreLoadStoreParameter.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreLoadStoreParameter.java
@@ -22,11 +22,11 @@ import java.security.KeyStore.ProtectionParameter;
/**
* @hide
*/
-class AndroidKeyStoreLoadStoreParameter implements KeyStore.LoadStoreParameter {
+public class AndroidKeyStoreLoadStoreParameter implements KeyStore.LoadStoreParameter {
private final int mNamespace;
- AndroidKeyStoreLoadStoreParameter(int namespace) {
+ public AndroidKeyStoreLoadStoreParameter(int namespace) {
mNamespace = namespace;
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
index c0cd96853957..403da189262d 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java
@@ -31,9 +31,7 @@ import android.system.keystore2.KeyEntryResponse;
import android.system.keystore2.KeyMetadata;
import android.system.keystore2.ResponseCode;
-import java.security.KeyFactory;
import java.security.KeyPair;
-import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.ProviderException;
import java.security.PublicKey;
@@ -42,8 +40,6 @@ import java.security.Signature;
import java.security.UnrecoverableKeyException;
import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPublicKey;
-import java.security.spec.InvalidKeySpecException;
-import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher;
import javax.crypto.Mac;
@@ -237,28 +233,11 @@ public class AndroidKeyStoreProvider extends Provider {
throw new UnrecoverableKeyException("Failed to obtain X.509 form of public key."
+ " Keystore has no public certificate stored.");
}
- final byte[] x509EncodedPublicKey = metadata.certificate;
+ final byte[] x509PublicCert = metadata.certificate;
- String jcaKeyAlgorithm;
- try {
- jcaKeyAlgorithm = KeyProperties.KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm(
- algorithm);
- } catch (IllegalArgumentException e) {
- throw (UnrecoverableKeyException)
- new UnrecoverableKeyException("Failed to load private key")
- .initCause(e);
- }
+ PublicKey publicKey = AndroidKeyStoreSpi.toCertificate(x509PublicCert).getPublicKey();
- PublicKey publicKey;
- try {
- KeyFactory keyFactory = KeyFactory.getInstance(jcaKeyAlgorithm);
- publicKey = keyFactory.generatePublic(new X509EncodedKeySpec(x509EncodedPublicKey));
- } catch (NoSuchAlgorithmException e) {
- throw new ProviderException(
- "Failed to obtain " + jcaKeyAlgorithm + " KeyFactory", e);
- } catch (InvalidKeySpecException e) {
- throw new ProviderException("Invalid X.509 encoding of public key", e);
- }
+ String jcaKeyAlgorithm = publicKey.getAlgorithm();
KeyStoreSecurityLevel securityLevel = iSecurityLevel;
if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(jcaKeyAlgorithm)) {
@@ -358,7 +337,7 @@ public class AndroidKeyStoreProvider extends Provider {
KeyDescriptor descriptor = new KeyDescriptor();
if (namespace == KeyProperties.NAMESPACE_APPLICATION) {
- descriptor.nspace = 0; // ignored;
+ descriptor.nspace = KeyProperties.NAMESPACE_APPLICATION; // ignored;
descriptor.domain = Domain.APP;
} else {
descriptor.nspace = namespace;
@@ -407,7 +386,7 @@ public class AndroidKeyStoreProvider extends Provider {
keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_EC) {
return makeAndroidKeyStorePublicKeyFromKeyEntryResponse(descriptor, response.metadata,
new KeyStoreSecurityLevel(response.iSecurityLevel),
- keymasterAlgorithm);
+ keymasterAlgorithm).getPrivateKey();
} else {
throw new UnrecoverableKeyException("Key algorithm unknown");
}
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
index 951f91887894..6ff9432905ed 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreRSACipherSpi.java
@@ -158,7 +158,7 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
}
/**
- * RSA cipher with OAEP encryption padding. Only SHA-1 based MGF1 is supported as MGF.
+ * RSA cipher with OAEP encryption padding.
*/
abstract static class OAEPWithMGF1Padding extends AndroidKeyStoreRSACipherSpi {
@@ -316,6 +316,25 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
protected final int getAdditionalEntropyAmountForFinish() {
return (isEncrypting()) ? mDigestOutputSizeBytes : 0;
}
+
+ @Override
+ protected final String getTransform() {
+ switch (mKeymasterDigest) {
+ case KeymasterDefs.KM_DIGEST_SHA1:
+ return "RSA/ECB/OAEPWithSHA-1AndMGF1Padding";
+ case KeymasterDefs.KM_DIGEST_SHA_2_224:
+ return "RSA/ECB/OAEPWithSHA-224AndMGF1Padding";
+ case KeymasterDefs.KM_DIGEST_SHA_2_256:
+ return "RSA/ECB/OAEPWithSHA-256AndMGF1Padding";
+ case KeymasterDefs.KM_DIGEST_SHA_2_384:
+ return "RSA/ECB/OAEPWithSHA-384AndMGF1Padding";
+ case KeymasterDefs.KM_DIGEST_SHA_2_512:
+ return "RSA/ECB/OAEPWithSHA-512AndMGF1Padding";
+ default:
+ return "RSA/ECB/OAEPPadding";
+ }
+ }
+
}
public static class OAEPWithSHA1AndMGF1Padding extends OAEPWithMGF1Padding {
@@ -358,6 +377,11 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
}
@Override
+ protected String getTransform() {
+ return "RSA/ECB/" + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding);
+ }
+
+ @Override
protected final void initKey(int opmode, Key key) throws InvalidKeyException {
if (key == null) {
throw new InvalidKeyException("Unsupported key: null");
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java
index ab7559116a41..931c2f864eba 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreRSASignatureSpi.java
@@ -48,42 +48,70 @@ abstract class AndroidKeyStoreRSASignatureSpi extends AndroidKeyStoreSignatureSp
public NONEWithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_NONE);
}
+ @Override
+ protected String getAlgorithm() {
+ return "NONEwithRSA";
+ }
}
public static final class MD5WithPKCS1Padding extends PKCS1Padding {
public MD5WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_MD5);
}
+ @Override
+ protected String getAlgorithm() {
+ return "MD5withRSA";
+ }
}
public static final class SHA1WithPKCS1Padding extends PKCS1Padding {
public SHA1WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_SHA1);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA1withRSA";
+ }
}
public static final class SHA224WithPKCS1Padding extends PKCS1Padding {
public SHA224WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_224);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA224withRSA";
+ }
}
public static final class SHA256WithPKCS1Padding extends PKCS1Padding {
public SHA256WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_256);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA256withRSA";
+ }
}
public static final class SHA384WithPKCS1Padding extends PKCS1Padding {
public SHA384WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_384);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA384withRSA";
+ }
}
public static final class SHA512WithPKCS1Padding extends PKCS1Padding {
public SHA512WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_512);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA512withRSA";
+ }
}
abstract static class PSSPadding extends AndroidKeyStoreRSASignatureSpi {
@@ -103,30 +131,50 @@ abstract class AndroidKeyStoreRSASignatureSpi extends AndroidKeyStoreSignatureSp
public SHA1WithPSSPadding() {
super(KeymasterDefs.KM_DIGEST_SHA1);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA1withRSA/PSS";
+ }
}
public static final class SHA224WithPSSPadding extends PSSPadding {
public SHA224WithPSSPadding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_224);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA224withRSA/PSS";
+ }
}
public static final class SHA256WithPSSPadding extends PSSPadding {
public SHA256WithPSSPadding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_256);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA256withRSA/PSS";
+ }
}
public static final class SHA384WithPSSPadding extends PSSPadding {
public SHA384WithPSSPadding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_384);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA384withRSA/PSS";
+ }
}
public static final class SHA512WithPSSPadding extends PSSPadding {
public SHA512WithPSSPadding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_512);
}
+ @Override
+ protected String getAlgorithm() {
+ return "SHA512withRSA/PSS";
+ }
}
private final int mKeymasterDigest;
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java
index 9b4f01e744f7..96da1e00ade8 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSignatureSpiBase.java
@@ -30,10 +30,12 @@ import libcore.util.EmptyArray;
import java.nio.ByteBuffer;
import java.security.InvalidKeyException;
import java.security.InvalidParameterException;
+import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.ProviderException;
import java.security.PublicKey;
import java.security.SecureRandom;
+import java.security.Signature;
import java.security.SignatureException;
import java.security.SignatureSpi;
import java.util.ArrayList;
@@ -76,6 +78,13 @@ abstract class AndroidKeyStoreSignatureSpiBase extends SignatureSpi
*/
private Exception mCachedException;
+ /**
+ * This signature object is used for public key operations, i.e, signatrue verification.
+ * The Android Keystore backend does not perform public key operations and defers to the
+ * Highest priority provider.
+ */
+ private Signature mSignature;
+
AndroidKeyStoreSignatureSpiBase() {
mOperation = null;
mOperationChallenge = 0;
@@ -84,6 +93,7 @@ abstract class AndroidKeyStoreSignatureSpiBase extends SignatureSpi
appRandom = null;
mMessageStreamer = null;
mCachedException = null;
+ mSignature = null;
}
@Override
@@ -123,27 +133,13 @@ abstract class AndroidKeyStoreSignatureSpiBase extends SignatureSpi
protected final void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
resetAll();
- boolean success = false;
try {
- if (publicKey == null) {
- throw new InvalidKeyException("Unsupported key: null");
- }
- AndroidKeyStoreKey keystoreKey;
- if (publicKey instanceof AndroidKeyStorePublicKey) {
- keystoreKey = (AndroidKeyStorePublicKey) publicKey;
- } else {
- throw new InvalidKeyException("Unsupported public key type: " + publicKey);
- }
- mSigning = false;
- initKey(keystoreKey);
- appRandom = null;
- ensureKeystoreOperationInitialized();
- success = true;
- } finally {
- if (!success) {
- resetAll();
- }
+ mSignature = Signature.getInstance(getAlgorithm());
+ } catch (NoSuchAlgorithmException e) {
+ throw new InvalidKeyException(e);
}
+
+ mSignature.initVerify(publicKey);
}
/**
@@ -251,6 +247,11 @@ abstract class AndroidKeyStoreSignatureSpiBase extends SignatureSpi
@Override
protected final void engineUpdate(byte[] b, int off, int len) throws SignatureException {
+ if (mSignature != null) {
+ mSignature.update(b, off, len);
+ return;
+ }
+
if (mCachedException != null) {
throw new SignatureException(mCachedException);
}
@@ -337,39 +338,10 @@ abstract class AndroidKeyStoreSignatureSpiBase extends SignatureSpi
@Override
protected final boolean engineVerify(byte[] signature) throws SignatureException {
- if (mCachedException != null) {
- throw new SignatureException(mCachedException);
- }
-
- try {
- ensureKeystoreOperationInitialized();
- } catch (InvalidKeyException e) {
- throw new SignatureException(e);
- }
-
- boolean verified;
- try {
- byte[] output = mMessageStreamer.doFinal(
- EmptyArray.BYTE, 0, 0,
- signature);
- if (output.length != 0) {
- throw new ProviderException(
- "Signature verification unexpected produced output: " + output.length
- + " bytes");
- }
- verified = true;
- } catch (KeyStoreException e) {
- switch (e.getErrorCode()) {
- case KeymasterDefs.KM_ERROR_VERIFICATION_FAILED:
- verified = false;
- break;
- default:
- throw new SignatureException(e);
- }
+ if (mSignature != null) {
+ return mSignature.verify(signature);
}
-
- resetWhilePreservingInitState();
- return verified;
+ throw new IllegalStateException("Not initialised.");
}
@Override
@@ -392,6 +364,13 @@ abstract class AndroidKeyStoreSignatureSpiBase extends SignatureSpi
}
/**
+ * Implementations need to report the algorithm they implement so that we can delegate to the
+ * highest priority provider.
+ * @return Algorithm string.
+ */
+ protected abstract String getAlgorithm();
+
+ /**
* Returns {@code true} if this signature is initialized for signing, {@code false} if this
* signature is initialized for verification.
*/
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
index aca531458382..5e7f6482ebed 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java
@@ -219,7 +219,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
return null;
}
- private static X509Certificate toCertificate(byte[] bytes) {
+ static X509Certificate toCertificate(byte[] bytes) {
try {
final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
return (X509Certificate) certFactory.generateCertificate(
@@ -250,13 +250,10 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
return null;
}
-
- // TODO add modification time to key metadata.
- return null;
- // if (response.metadata.modificationTime == -1) {
- // return null;
- // }
- // return new Date(response.metadata.modificationTime);
+ if (response.metadata.modificationTimeMs == -1) {
+ return null;
+ }
+ return new Date(response.metadata.modificationTimeMs);
}
@Override
diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
index 02e231ea990f..5c048a127cb3 100644
--- a/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
+++ b/keystore/java/android/security/keystore2/AndroidKeyStoreUnauthenticatedAESCipherSpi.java
@@ -42,7 +42,7 @@ import javax.crypto.spec.IvParameterSpec;
*
* @hide
*/
-class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSpiBase {
+abstract class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSpiBase {
abstract static class ECB extends AndroidKeyStoreUnauthenticatedAESCipherSpi {
protected ECB(int keymasterPadding) {
@@ -53,12 +53,22 @@ class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSp
public NoPadding() {
super(KeymasterDefs.KM_PAD_NONE);
}
+
+ @Override
+ protected final String getTransform() {
+ return "AES/ECB/NoPadding";
+ }
}
public static class PKCS7Padding extends ECB {
public PKCS7Padding() {
super(KeymasterDefs.KM_PAD_PKCS7);
}
+
+ @Override
+ protected final String getTransform() {
+ return "AES/ECB/PKCS7Padding";
+ }
}
}
@@ -71,12 +81,22 @@ class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSp
public NoPadding() {
super(KeymasterDefs.KM_PAD_NONE);
}
+
+ @Override
+ protected final String getTransform() {
+ return "AES/CBC/NoPadding";
+ }
}
public static class PKCS7Padding extends CBC {
public PKCS7Padding() {
super(KeymasterDefs.KM_PAD_PKCS7);
}
+
+ @Override
+ protected final String getTransform() {
+ return "AES/CBC/PKCS7Padding";
+ }
}
}
@@ -89,6 +109,11 @@ class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSp
public NoPadding() {
super(KeymasterDefs.KM_PAD_NONE);
}
+
+ @Override
+ protected final String getTransform() {
+ return "AES/CTR/NoPadding";
+ }
}
}
diff --git a/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java b/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java
index 32dfd6e7050c..4c8ab8d6c713 100644
--- a/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java
+++ b/keystore/java/android/security/keystore2/KeyStore2ParameterUtils.java
@@ -206,7 +206,7 @@ public abstract class KeyStore2ParameterUtils {
static void forEachSetFlag(int flags, Consumer<Integer> consumer) {
int offset = 0;
while (flags != 0) {
- if ((flags & 1) == 0) {
+ if ((flags & 1) == 1) {
consumer.accept(1 << offset);
}
offset += 1;