Merge changes I316fdb8b,I99c1bd49 am: 572416b317

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1519116

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: Id4fa3e795e428d0c2240cc1072d1daf819287a0a
This commit is contained in:
Treehugger Robot
2020-12-19 04:05:57 +00:00
committed by Automerger Merge Worker
12 changed files with 301 additions and 84 deletions

View File

@@ -41,7 +41,7 @@ import javax.crypto.spec.IvParameterSpec;
* *
* @hide * @hide
*/ */
public class AndroidKeyStore3DESCipherSpi extends AndroidKeyStoreCipherSpiBase { public abstract class AndroidKeyStore3DESCipherSpi extends AndroidKeyStoreCipherSpiBase {
private static final int BLOCK_SIZE_BYTES = 8; private static final int BLOCK_SIZE_BYTES = 8;
@@ -73,12 +73,22 @@ public class AndroidKeyStore3DESCipherSpi extends AndroidKeyStoreCipherSpiBase {
public NoPadding() { public NoPadding() {
super(KeymasterDefs.KM_PAD_NONE); super(KeymasterDefs.KM_PAD_NONE);
} }
@Override
protected final String getTransform() {
return "DESede/ECB/NoPadding";
}
} }
public static class PKCS7Padding extends ECB { public static class PKCS7Padding extends ECB {
public PKCS7Padding() { public PKCS7Padding() {
super(KeymasterDefs.KM_PAD_PKCS7); 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() { public NoPadding() {
super(KeymasterDefs.KM_PAD_NONE); super(KeymasterDefs.KM_PAD_NONE);
} }
@Override
protected final String getTransform() {
return "DESede/CBC/NoPadding";
}
} }
public static class PKCS7Padding extends CBC { public static class PKCS7Padding extends CBC {
public PKCS7Padding() { public PKCS7Padding() {
super(KeymasterDefs.KM_PAD_PKCS7); super(KeymasterDefs.KM_PAD_PKCS7);
} }
@Override
protected final String getTransform() {
return "DESede/CBC/PKCS7Padding";
}
} }
} }

View File

@@ -63,6 +63,11 @@ abstract class AndroidKeyStoreAuthenticatedAESCipherSpi extends AndroidKeyStoreC
super(KeymasterDefs.KM_MODE_GCM, keymasterPadding); super(KeymasterDefs.KM_MODE_GCM, keymasterPadding);
} }
@Override
protected final String getTransform() {
return "AES/GCM/NoPadding";
}
@Override @Override
protected final void resetAll() { protected final void resetAll() {
mTagLengthBits = DEFAULT_TAG_LENGTH_BITS; mTagLengthBits = DEFAULT_TAG_LENGTH_BITS;

View File

@@ -254,13 +254,13 @@ class AndroidKeyStoreBCWorkaroundProvider extends Provider {
private void putAsymmetricCipherImpl(String transformation, String implClass) { private void putAsymmetricCipherImpl(String transformation, String implClass) {
put("Cipher." + transformation, implClass); put("Cipher." + transformation, implClass);
put("Cipher." + transformation + " SupportedKeyClasses", 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) { private void putSignatureImpl(String algorithm, String implClass) {
put("Signature." + algorithm, implClass); put("Signature." + algorithm, implClass);
put("Signature." + algorithm + " SupportedKeyClasses", put("Signature." + algorithm + " SupportedKeyClasses",
KEYSTORE_PRIVATE_KEY_CLASS_NAME + "|" + KEYSTORE_PUBLIC_KEY_CLASS_NAME); KEYSTORE_PRIVATE_KEY_CLASS_NAME);
} }
public static String[] getSupportedEcdsaSignatureDigests() { public static String[] getSupportedEcdsaSignatureDigests() {

View File

@@ -43,6 +43,7 @@ import java.security.PublicKey;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec; import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec; import java.security.spec.X509EncodedKeySpec;
import java.util.ArrayList; import java.util.ArrayList;
@@ -57,6 +58,8 @@ import javax.crypto.NoSuchPaddingException;
import javax.crypto.SecretKey; import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory; import javax.crypto.SecretKeyFactory;
import javax.crypto.ShortBufferException; import javax.crypto.ShortBufferException;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import javax.crypto.spec.SecretKeySpec; import javax.crypto.spec.SecretKeySpec;
/** /**
@@ -99,6 +102,8 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
*/ */
private Exception mCachedException; private Exception mCachedException;
private Cipher mCipher;
AndroidKeyStoreCipherSpiBase() { AndroidKeyStoreCipherSpiBase() {
mOperation = null; mOperation = null;
mEncrypting = false; mEncrypting = false;
@@ -110,6 +115,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
mAdditionalAuthenticationDataStreamer = null; mAdditionalAuthenticationDataStreamer = null;
mAdditionalAuthenticationDataStreamerClosed = false; mAdditionalAuthenticationDataStreamerClosed = false;
mCachedException = null; mCachedException = null;
mCipher = null;
} }
@Override @Override
@@ -117,6 +123,45 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
throws InvalidKeyException { throws InvalidKeyException {
resetAll(); 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; boolean success = false;
try { try {
init(opmode, key, random); init(opmode, key, random);
@@ -139,6 +184,17 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
resetAll(); 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; boolean success = false;
try { try {
init(opmode, key, random); init(opmode, key, random);
@@ -157,6 +213,17 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException { SecureRandom random) throws InvalidKeyException, InvalidAlgorithmParameterException {
resetAll(); 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; boolean success = false;
try { try {
init(opmode, key, random); init(opmode, key, random);
@@ -214,6 +281,7 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
mAdditionalAuthenticationDataStreamer = null; mAdditionalAuthenticationDataStreamer = null;
mAdditionalAuthenticationDataStreamerClosed = false; mAdditionalAuthenticationDataStreamerClosed = false;
mCachedException = null; mCachedException = null;
mCipher = null;
} }
/** /**
@@ -320,6 +388,10 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override @Override
protected final byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) { protected final byte[] engineUpdate(byte[] input, int inputOffset, int inputLen) {
if (mCipher != null) {
return mCipher.update(input, inputOffset, inputLen);
}
if (mCachedException != null) { if (mCachedException != null) {
return null; return null;
} }
@@ -371,6 +443,9 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override @Override
protected final int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output, protected final int engineUpdate(byte[] input, int inputOffset, int inputLen, byte[] output,
int outputOffset) throws ShortBufferException { int outputOffset) throws ShortBufferException {
if (mCipher != null) {
return mCipher.update(input, inputOffset, inputLen, output);
}
byte[] outputCopy = engineUpdate(input, inputOffset, inputLen); byte[] outputCopy = engineUpdate(input, inputOffset, inputLen);
if (outputCopy == null) { if (outputCopy == null) {
return 0; return 0;
@@ -387,6 +462,10 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override @Override
protected final int engineUpdate(ByteBuffer input, ByteBuffer output) protected final int engineUpdate(ByteBuffer input, ByteBuffer output)
throws ShortBufferException { throws ShortBufferException {
if (mCipher != null) {
return mCipher.update(input, output);
}
if (input == null) { if (input == null) {
throw new NullPointerException("input == null"); throw new NullPointerException("input == null");
} }
@@ -423,6 +502,11 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override @Override
protected final void engineUpdateAAD(byte[] input, int inputOffset, int inputLen) { protected final void engineUpdateAAD(byte[] input, int inputOffset, int inputLen) {
if (mCipher != null) {
mCipher.updateAAD(input, inputOffset, inputLen);
return;
}
if (mCachedException != null) { if (mCachedException != null) {
return; return;
} }
@@ -459,6 +543,11 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override @Override
protected final void engineUpdateAAD(ByteBuffer src) { protected final void engineUpdateAAD(ByteBuffer src) {
if (mCipher != null) {
mCipher.updateAAD(src);
return;
}
if (src == null) { if (src == null) {
throw new IllegalArgumentException("src == null"); throw new IllegalArgumentException("src == null");
} }
@@ -486,6 +575,10 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override @Override
protected final byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen) protected final byte[] engineDoFinal(byte[] input, int inputOffset, int inputLen)
throws IllegalBlockSizeException, BadPaddingException { throws IllegalBlockSizeException, BadPaddingException {
if (mCipher != null) {
return mCipher.doFinal(input, inputOffset, inputLen);
}
if (mCachedException != null) { if (mCachedException != null) {
throw (IllegalBlockSizeException) throw (IllegalBlockSizeException)
new IllegalBlockSizeException().initCause(mCachedException); 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, protected final int engineDoFinal(byte[] input, int inputOffset, int inputLen, byte[] output,
int outputOffset) throws ShortBufferException, IllegalBlockSizeException, int outputOffset) throws ShortBufferException, IllegalBlockSizeException,
BadPaddingException { BadPaddingException {
if (mCipher != null) {
return mCipher.doFinal(input, inputOffset, inputLen, output);
}
byte[] outputCopy = engineDoFinal(input, inputOffset, inputLen); byte[] outputCopy = engineDoFinal(input, inputOffset, inputLen);
if (outputCopy == null) { if (outputCopy == null) {
return 0; return 0;
@@ -538,6 +635,10 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override @Override
protected final int engineDoFinal(ByteBuffer input, ByteBuffer output) protected final int engineDoFinal(ByteBuffer input, ByteBuffer output)
throws ShortBufferException, IllegalBlockSizeException, BadPaddingException { throws ShortBufferException, IllegalBlockSizeException, BadPaddingException {
if (mCipher != null) {
return mCipher.doFinal(input, output);
}
if (input == null) { if (input == null) {
throw new NullPointerException("input == null"); throw new NullPointerException("input == null");
} }
@@ -575,6 +676,10 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override @Override
protected final byte[] engineWrap(Key key) protected final byte[] engineWrap(Key key)
throws IllegalBlockSizeException, InvalidKeyException { throws IllegalBlockSizeException, InvalidKeyException {
if (mCipher != null) {
return mCipher.wrap(key);
}
if (mKey == null) { if (mKey == null) {
throw new IllegalStateException("Not initilized"); throw new IllegalStateException("Not initilized");
} }
@@ -656,6 +761,10 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
@Override @Override
protected final Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm, protected final Key engineUnwrap(byte[] wrappedKey, String wrappedKeyAlgorithm,
int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException { int wrappedKeyType) throws InvalidKeyException, NoSuchAlgorithmException {
if (mCipher != null) {
return mCipher.unwrap(wrappedKey, wrappedKeyAlgorithm, wrappedKeyType);
}
if (mKey == null) { if (mKey == null) {
throw new IllegalStateException("Not initilized"); throw new IllegalStateException("Not initilized");
} }
@@ -902,4 +1011,6 @@ abstract class AndroidKeyStoreCipherSpiBase extends CipherSpi implements KeyStor
*/ */
protected abstract void loadAlgorithmSpecificParametersFromBeginResult( protected abstract void loadAlgorithmSpecificParametersFromBeginResult(
KeyParameter[] parameters); KeyParameter[] parameters);
protected abstract String getTransform();
} }

View File

@@ -43,6 +43,11 @@ abstract class AndroidKeyStoreECDSASignatureSpi extends AndroidKeyStoreSignature
super(KeymasterDefs.KM_DIGEST_NONE); super(KeymasterDefs.KM_DIGEST_NONE);
} }
@Override
protected String getAlgorithm() {
return "NONEwithECDSA";
}
@Override @Override
protected KeyStoreCryptoOperationStreamer createMainDataStreamer( protected KeyStoreCryptoOperationStreamer createMainDataStreamer(
KeyStoreOperation operation) { KeyStoreOperation operation) {
@@ -113,30 +118,50 @@ abstract class AndroidKeyStoreECDSASignatureSpi extends AndroidKeyStoreSignature
public SHA1() { public SHA1() {
super(KeymasterDefs.KM_DIGEST_SHA1); super(KeymasterDefs.KM_DIGEST_SHA1);
} }
@Override
protected String getAlgorithm() {
return "SHA1withECDSA";
}
} }
public final static class SHA224 extends AndroidKeyStoreECDSASignatureSpi { public final static class SHA224 extends AndroidKeyStoreECDSASignatureSpi {
public SHA224() { public SHA224() {
super(KeymasterDefs.KM_DIGEST_SHA_2_224); super(KeymasterDefs.KM_DIGEST_SHA_2_224);
} }
@Override
protected String getAlgorithm() {
return "SHA224withECDSA";
}
} }
public final static class SHA256 extends AndroidKeyStoreECDSASignatureSpi { public final static class SHA256 extends AndroidKeyStoreECDSASignatureSpi {
public SHA256() { public SHA256() {
super(KeymasterDefs.KM_DIGEST_SHA_2_256); super(KeymasterDefs.KM_DIGEST_SHA_2_256);
} }
@Override
protected String getAlgorithm() {
return "SHA256withECDSA";
}
} }
public final static class SHA384 extends AndroidKeyStoreECDSASignatureSpi { public final static class SHA384 extends AndroidKeyStoreECDSASignatureSpi {
public SHA384() { public SHA384() {
super(KeymasterDefs.KM_DIGEST_SHA_2_384); super(KeymasterDefs.KM_DIGEST_SHA_2_384);
} }
@Override
protected String getAlgorithm() {
return "SHA384withECDSA";
}
} }
public final static class SHA512 extends AndroidKeyStoreECDSASignatureSpi { public final static class SHA512 extends AndroidKeyStoreECDSASignatureSpi {
public SHA512() { public SHA512() {
super(KeymasterDefs.KM_DIGEST_SHA_2_512); super(KeymasterDefs.KM_DIGEST_SHA_2_512);
} }
@Override
protected String getAlgorithm() {
return "SHA512withECDSA";
}
} }
private final int mKeymasterDigest; private final int mKeymasterDigest;

View File

@@ -31,9 +31,7 @@ import android.system.keystore2.KeyEntryResponse;
import android.system.keystore2.KeyMetadata; import android.system.keystore2.KeyMetadata;
import android.system.keystore2.ResponseCode; import android.system.keystore2.ResponseCode;
import java.security.KeyFactory;
import java.security.KeyPair; import java.security.KeyPair;
import java.security.NoSuchAlgorithmException;
import java.security.Provider; import java.security.Provider;
import java.security.ProviderException; import java.security.ProviderException;
import java.security.PublicKey; import java.security.PublicKey;
@@ -42,8 +40,6 @@ import java.security.Signature;
import java.security.UnrecoverableKeyException; import java.security.UnrecoverableKeyException;
import java.security.interfaces.ECPublicKey; import java.security.interfaces.ECPublicKey;
import java.security.interfaces.RSAPublicKey; import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.X509EncodedKeySpec;
import javax.crypto.Cipher; import javax.crypto.Cipher;
import javax.crypto.Mac; 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." throw new UnrecoverableKeyException("Failed to obtain X.509 form of public key."
+ " Keystore has no public certificate stored."); + " Keystore has no public certificate stored.");
} }
final byte[] x509EncodedPublicKey = metadata.certificate; final byte[] x509PublicCert = metadata.certificate;
String jcaKeyAlgorithm; PublicKey publicKey = AndroidKeyStoreSpi.toCertificate(x509PublicCert).getPublicKey();
try {
jcaKeyAlgorithm = KeyProperties.KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm(
algorithm);
} catch (IllegalArgumentException e) {
throw (UnrecoverableKeyException)
new UnrecoverableKeyException("Failed to load private key")
.initCause(e);
}
PublicKey publicKey; String jcaKeyAlgorithm = publicKey.getAlgorithm();
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);
}
KeyStoreSecurityLevel securityLevel = iSecurityLevel; KeyStoreSecurityLevel securityLevel = iSecurityLevel;
if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(jcaKeyAlgorithm)) { if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(jcaKeyAlgorithm)) {
@@ -358,7 +337,7 @@ public class AndroidKeyStoreProvider extends Provider {
KeyDescriptor descriptor = new KeyDescriptor(); KeyDescriptor descriptor = new KeyDescriptor();
if (namespace == KeyProperties.NAMESPACE_APPLICATION) { if (namespace == KeyProperties.NAMESPACE_APPLICATION) {
descriptor.nspace = 0; // ignored; descriptor.nspace = KeyProperties.NAMESPACE_APPLICATION; // ignored;
descriptor.domain = Domain.APP; descriptor.domain = Domain.APP;
} else { } else {
descriptor.nspace = namespace; descriptor.nspace = namespace;
@@ -407,7 +386,7 @@ public class AndroidKeyStoreProvider extends Provider {
keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_EC) { keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_EC) {
return makeAndroidKeyStorePublicKeyFromKeyEntryResponse(descriptor, response.metadata, return makeAndroidKeyStorePublicKeyFromKeyEntryResponse(descriptor, response.metadata,
new KeyStoreSecurityLevel(response.iSecurityLevel), new KeyStoreSecurityLevel(response.iSecurityLevel),
keymasterAlgorithm); keymasterAlgorithm).getPrivateKey();
} else { } else {
throw new UnrecoverableKeyException("Key algorithm unknown"); throw new UnrecoverableKeyException("Key algorithm unknown");
} }

View File

@@ -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 { abstract static class OAEPWithMGF1Padding extends AndroidKeyStoreRSACipherSpi {
@@ -316,6 +316,25 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
protected final int getAdditionalEntropyAmountForFinish() { protected final int getAdditionalEntropyAmountForFinish() {
return (isEncrypting()) ? mDigestOutputSizeBytes : 0; 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 { public static class OAEPWithSHA1AndMGF1Padding extends OAEPWithMGF1Padding {
@@ -357,6 +376,11 @@ abstract class AndroidKeyStoreRSACipherSpi extends AndroidKeyStoreCipherSpiBase
mKeymasterPadding = keymasterPadding; mKeymasterPadding = keymasterPadding;
} }
@Override
protected String getTransform() {
return "RSA/ECB/" + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding);
}
@Override @Override
protected final void initKey(int opmode, Key key) throws InvalidKeyException { protected final void initKey(int opmode, Key key) throws InvalidKeyException {
if (key == null) { if (key == null) {

View File

@@ -48,42 +48,70 @@ abstract class AndroidKeyStoreRSASignatureSpi extends AndroidKeyStoreSignatureSp
public NONEWithPKCS1Padding() { public NONEWithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_NONE); super(KeymasterDefs.KM_DIGEST_NONE);
} }
@Override
protected String getAlgorithm() {
return "NONEwithRSA";
}
} }
public static final class MD5WithPKCS1Padding extends PKCS1Padding { public static final class MD5WithPKCS1Padding extends PKCS1Padding {
public MD5WithPKCS1Padding() { public MD5WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_MD5); super(KeymasterDefs.KM_DIGEST_MD5);
} }
@Override
protected String getAlgorithm() {
return "MD5withRSA";
}
} }
public static final class SHA1WithPKCS1Padding extends PKCS1Padding { public static final class SHA1WithPKCS1Padding extends PKCS1Padding {
public SHA1WithPKCS1Padding() { public SHA1WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_SHA1); super(KeymasterDefs.KM_DIGEST_SHA1);
} }
@Override
protected String getAlgorithm() {
return "SHA1withRSA";
}
} }
public static final class SHA224WithPKCS1Padding extends PKCS1Padding { public static final class SHA224WithPKCS1Padding extends PKCS1Padding {
public SHA224WithPKCS1Padding() { public SHA224WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_224); super(KeymasterDefs.KM_DIGEST_SHA_2_224);
} }
@Override
protected String getAlgorithm() {
return "SHA224withRSA";
}
} }
public static final class SHA256WithPKCS1Padding extends PKCS1Padding { public static final class SHA256WithPKCS1Padding extends PKCS1Padding {
public SHA256WithPKCS1Padding() { public SHA256WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_256); super(KeymasterDefs.KM_DIGEST_SHA_2_256);
} }
@Override
protected String getAlgorithm() {
return "SHA256withRSA";
}
} }
public static final class SHA384WithPKCS1Padding extends PKCS1Padding { public static final class SHA384WithPKCS1Padding extends PKCS1Padding {
public SHA384WithPKCS1Padding() { public SHA384WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_384); super(KeymasterDefs.KM_DIGEST_SHA_2_384);
} }
@Override
protected String getAlgorithm() {
return "SHA384withRSA";
}
} }
public static final class SHA512WithPKCS1Padding extends PKCS1Padding { public static final class SHA512WithPKCS1Padding extends PKCS1Padding {
public SHA512WithPKCS1Padding() { public SHA512WithPKCS1Padding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_512); super(KeymasterDefs.KM_DIGEST_SHA_2_512);
} }
@Override
protected String getAlgorithm() {
return "SHA512withRSA";
}
} }
abstract static class PSSPadding extends AndroidKeyStoreRSASignatureSpi { abstract static class PSSPadding extends AndroidKeyStoreRSASignatureSpi {
@@ -103,30 +131,50 @@ abstract class AndroidKeyStoreRSASignatureSpi extends AndroidKeyStoreSignatureSp
public SHA1WithPSSPadding() { public SHA1WithPSSPadding() {
super(KeymasterDefs.KM_DIGEST_SHA1); super(KeymasterDefs.KM_DIGEST_SHA1);
} }
@Override
protected String getAlgorithm() {
return "SHA1withRSA/PSS";
}
} }
public static final class SHA224WithPSSPadding extends PSSPadding { public static final class SHA224WithPSSPadding extends PSSPadding {
public SHA224WithPSSPadding() { public SHA224WithPSSPadding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_224); super(KeymasterDefs.KM_DIGEST_SHA_2_224);
} }
@Override
protected String getAlgorithm() {
return "SHA224withRSA/PSS";
}
} }
public static final class SHA256WithPSSPadding extends PSSPadding { public static final class SHA256WithPSSPadding extends PSSPadding {
public SHA256WithPSSPadding() { public SHA256WithPSSPadding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_256); super(KeymasterDefs.KM_DIGEST_SHA_2_256);
} }
@Override
protected String getAlgorithm() {
return "SHA256withRSA/PSS";
}
} }
public static final class SHA384WithPSSPadding extends PSSPadding { public static final class SHA384WithPSSPadding extends PSSPadding {
public SHA384WithPSSPadding() { public SHA384WithPSSPadding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_384); super(KeymasterDefs.KM_DIGEST_SHA_2_384);
} }
@Override
protected String getAlgorithm() {
return "SHA384withRSA/PSS";
}
} }
public static final class SHA512WithPSSPadding extends PSSPadding { public static final class SHA512WithPSSPadding extends PSSPadding {
public SHA512WithPSSPadding() { public SHA512WithPSSPadding() {
super(KeymasterDefs.KM_DIGEST_SHA_2_512); super(KeymasterDefs.KM_DIGEST_SHA_2_512);
} }
@Override
protected String getAlgorithm() {
return "SHA512withRSA/PSS";
}
} }
private final int mKeymasterDigest; private final int mKeymasterDigest;

View File

@@ -30,10 +30,12 @@ import libcore.util.EmptyArray;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.InvalidParameterException; import java.security.InvalidParameterException;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey; import java.security.PrivateKey;
import java.security.ProviderException; import java.security.ProviderException;
import java.security.PublicKey; import java.security.PublicKey;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.Signature;
import java.security.SignatureException; import java.security.SignatureException;
import java.security.SignatureSpi; import java.security.SignatureSpi;
import java.util.ArrayList; import java.util.ArrayList;
@@ -76,6 +78,13 @@ abstract class AndroidKeyStoreSignatureSpiBase extends SignatureSpi
*/ */
private Exception mCachedException; 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() { AndroidKeyStoreSignatureSpiBase() {
mOperation = null; mOperation = null;
mOperationChallenge = 0; mOperationChallenge = 0;
@@ -84,6 +93,7 @@ abstract class AndroidKeyStoreSignatureSpiBase extends SignatureSpi
appRandom = null; appRandom = null;
mMessageStreamer = null; mMessageStreamer = null;
mCachedException = null; mCachedException = null;
mSignature = null;
} }
@Override @Override
@@ -123,27 +133,13 @@ abstract class AndroidKeyStoreSignatureSpiBase extends SignatureSpi
protected final void engineInitVerify(PublicKey publicKey) throws InvalidKeyException { protected final void engineInitVerify(PublicKey publicKey) throws InvalidKeyException {
resetAll(); resetAll();
boolean success = false;
try { try {
if (publicKey == null) { mSignature = Signature.getInstance(getAlgorithm());
throw new InvalidKeyException("Unsupported key: null"); } catch (NoSuchAlgorithmException e) {
} throw new InvalidKeyException(e);
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.initVerify(publicKey);
} }
/** /**
@@ -251,6 +247,11 @@ abstract class AndroidKeyStoreSignatureSpiBase extends SignatureSpi
@Override @Override
protected final void engineUpdate(byte[] b, int off, int len) throws SignatureException { protected final void engineUpdate(byte[] b, int off, int len) throws SignatureException {
if (mSignature != null) {
mSignature.update(b, off, len);
return;
}
if (mCachedException != null) { if (mCachedException != null) {
throw new SignatureException(mCachedException); throw new SignatureException(mCachedException);
} }
@@ -337,39 +338,10 @@ abstract class AndroidKeyStoreSignatureSpiBase extends SignatureSpi
@Override @Override
protected final boolean engineVerify(byte[] signature) throws SignatureException { protected final boolean engineVerify(byte[] signature) throws SignatureException {
if (mCachedException != null) { if (mSignature != null) {
throw new SignatureException(mCachedException); return mSignature.verify(signature);
} }
throw new IllegalStateException("Not initialised.");
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);
}
}
resetWhilePreservingInitState();
return verified;
} }
@Override @Override
@@ -391,6 +363,13 @@ abstract class AndroidKeyStoreSignatureSpiBase extends SignatureSpi
throw new InvalidParameterException(); throw new InvalidParameterException();
} }
/**
* 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 * Returns {@code true} if this signature is initialized for signing, {@code false} if this
* signature is initialized for verification. * signature is initialized for verification.

View File

@@ -219,7 +219,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
return null; return null;
} }
private static X509Certificate toCertificate(byte[] bytes) { static X509Certificate toCertificate(byte[] bytes) {
try { try {
final CertificateFactory certFactory = CertificateFactory.getInstance("X.509"); final CertificateFactory certFactory = CertificateFactory.getInstance("X.509");
return (X509Certificate) certFactory.generateCertificate( return (X509Certificate) certFactory.generateCertificate(

View File

@@ -42,7 +42,7 @@ import javax.crypto.spec.IvParameterSpec;
* *
* @hide * @hide
*/ */
class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSpiBase { abstract class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSpiBase {
abstract static class ECB extends AndroidKeyStoreUnauthenticatedAESCipherSpi { abstract static class ECB extends AndroidKeyStoreUnauthenticatedAESCipherSpi {
protected ECB(int keymasterPadding) { protected ECB(int keymasterPadding) {
@@ -53,12 +53,22 @@ class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSp
public NoPadding() { public NoPadding() {
super(KeymasterDefs.KM_PAD_NONE); super(KeymasterDefs.KM_PAD_NONE);
} }
@Override
protected final String getTransform() {
return "AES/ECB/NoPadding";
}
} }
public static class PKCS7Padding extends ECB { public static class PKCS7Padding extends ECB {
public PKCS7Padding() { public PKCS7Padding() {
super(KeymasterDefs.KM_PAD_PKCS7); super(KeymasterDefs.KM_PAD_PKCS7);
} }
@Override
protected final String getTransform() {
return "AES/ECB/PKCS7Padding";
}
} }
} }
@@ -71,12 +81,22 @@ class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSp
public NoPadding() { public NoPadding() {
super(KeymasterDefs.KM_PAD_NONE); super(KeymasterDefs.KM_PAD_NONE);
} }
@Override
protected final String getTransform() {
return "AES/CBC/NoPadding";
}
} }
public static class PKCS7Padding extends CBC { public static class PKCS7Padding extends CBC {
public PKCS7Padding() { public PKCS7Padding() {
super(KeymasterDefs.KM_PAD_PKCS7); super(KeymasterDefs.KM_PAD_PKCS7);
} }
@Override
protected final String getTransform() {
return "AES/CBC/PKCS7Padding";
}
} }
} }
@@ -89,6 +109,11 @@ class AndroidKeyStoreUnauthenticatedAESCipherSpi extends AndroidKeyStoreCipherSp
public NoPadding() { public NoPadding() {
super(KeymasterDefs.KM_PAD_NONE); super(KeymasterDefs.KM_PAD_NONE);
} }
@Override
protected final String getTransform() {
return "AES/CTR/NoPadding";
}
} }
} }

View File

@@ -177,7 +177,7 @@ public abstract class KeyStore2ParameterUtils {
static void forEachSetFlag(int flags, Consumer<Integer> consumer) { static void forEachSetFlag(int flags, Consumer<Integer> consumer) {
int offset = 0; int offset = 0;
while (flags != 0) { while (flags != 0) {
if ((flags & 1) == 0) { if ((flags & 1) == 1) {
consumer.accept(1 << offset); consumer.accept(1 << offset);
} }
offset += 1; offset += 1;