Make ImportWrappedKey work with real hardware:
Get unwrapping params from WrappedKeyEntry Add @hide API for StrongBox-backed imported keys (as opposed to wrapped or generated) Enable 3DES conditionally based on a system property. Bug: b/79986479 Bug: b/79986680 Test: CTS Change-Id: If6beedc203337027576ecd3555d11ed2874f9768
This commit is contained in:
@ -48,6 +48,8 @@ class AndroidKeyStoreBCWorkaroundProvider extends Provider {
|
||||
private static final String KEYSTORE_PUBLIC_KEY_CLASS_NAME =
|
||||
PACKAGE_NAME + ".AndroidKeyStorePublicKey";
|
||||
|
||||
private static final String DESEDE_SYSTEM_PROPERTY = "ro.hardware.keystore_desede";
|
||||
|
||||
AndroidKeyStoreBCWorkaroundProvider() {
|
||||
super("AndroidKeyStoreBCWorkaround",
|
||||
1.0,
|
||||
@ -93,7 +95,7 @@ class AndroidKeyStoreBCWorkaroundProvider extends Provider {
|
||||
putSymmetricCipherImpl("AES/CTR/NoPadding",
|
||||
PACKAGE_NAME + ".AndroidKeyStoreUnauthenticatedAESCipherSpi$CTR$NoPadding");
|
||||
|
||||
if ("true".equals(System.getProperty("supports3DES"))) {
|
||||
if ("true".equals(android.os.SystemProperties.get(DESEDE_SYSTEM_PROPERTY))) {
|
||||
putSymmetricCipherImpl("DESede/CBC/NoPadding",
|
||||
PACKAGE_NAME + ".AndroidKeyStore3DESCipherSpi$CBC$NoPadding");
|
||||
putSymmetricCipherImpl("DESede/CBC/PKCS7Padding",
|
||||
|
@ -64,10 +64,13 @@ public class AndroidKeyStoreProvider extends Provider {
|
||||
|
||||
private static final String PACKAGE_NAME = "android.security.keystore";
|
||||
|
||||
private static final String DESEDE_SYSTEM_PROPERTY =
|
||||
"ro.hardware.keystore_desede";
|
||||
|
||||
public AndroidKeyStoreProvider() {
|
||||
super(PROVIDER_NAME, 1.0, "Android KeyStore security provider");
|
||||
|
||||
boolean supports3DES = "true".equals(System.getProperty("supports3DES"));
|
||||
boolean supports3DES = "true".equals(android.os.SystemProperties.get(DESEDE_SYSTEM_PROPERTY));
|
||||
|
||||
// java.security.KeyStore
|
||||
put("KeyStore.AndroidKeyStore", PACKAGE_NAME + ".AndroidKeyStoreSpi");
|
||||
|
@ -353,6 +353,10 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
||||
if (spec.isCriticalToDeviceEncryption()) {
|
||||
flags |= KeyStore.FLAG_CRITICAL_TO_DEVICE_ENCRYPTION;
|
||||
}
|
||||
|
||||
if (spec.isStrongBoxBacked()) {
|
||||
flags |= KeyStore.FLAG_STRONGBOX;
|
||||
}
|
||||
} else {
|
||||
throw new KeyStoreException(
|
||||
"Unsupported protection parameter class:" + param.getClass().getName()
|
||||
@ -720,6 +724,9 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
||||
if (params.isCriticalToDeviceEncryption()) {
|
||||
flags |= KeyStore.FLAG_CRITICAL_TO_DEVICE_ENCRYPTION;
|
||||
}
|
||||
if (params.isStrongBoxBacked()) {
|
||||
flags |= KeyStore.FLAG_STRONGBOX;
|
||||
}
|
||||
|
||||
Credentials.deleteAllTypesForAlias(mKeyStore, entryAlias, mUid);
|
||||
String keyAliasInKeystore = Credentials.USER_PRIVATE_KEY + entryAlias;
|
||||
@ -737,19 +744,76 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
||||
}
|
||||
}
|
||||
|
||||
private void setWrappedKeyEntry(String alias, byte[] wrappedKeyBytes, String wrappingKeyAlias,
|
||||
private void setWrappedKeyEntry(String alias, WrappedKeyEntry entry,
|
||||
java.security.KeyStore.ProtectionParameter param) throws KeyStoreException {
|
||||
if (param != null) {
|
||||
throw new KeyStoreException("Protection parameters are specified inside wrapped keys");
|
||||
}
|
||||
|
||||
byte[] maskingKey = new byte[32];
|
||||
KeymasterArguments args = new KeymasterArguments(); // TODO: populate wrapping key args.
|
||||
|
||||
|
||||
KeymasterArguments args = new KeymasterArguments();
|
||||
String[] parts = entry.getTransformation().split("/");
|
||||
|
||||
String algorithm = parts[0];
|
||||
if (KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(algorithm)) {
|
||||
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
|
||||
} else if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(algorithm)) {
|
||||
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_RSA);
|
||||
}
|
||||
|
||||
if (parts.length > 1) {
|
||||
String mode = parts[1];
|
||||
if (KeyProperties.BLOCK_MODE_ECB.equalsIgnoreCase(mode)) {
|
||||
args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_ECB);
|
||||
} else if (KeyProperties.BLOCK_MODE_CBC.equalsIgnoreCase(mode)) {
|
||||
args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_CBC);
|
||||
} else if (KeyProperties.BLOCK_MODE_CTR.equalsIgnoreCase(mode)) {
|
||||
args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_CTR);
|
||||
} else if (KeyProperties.BLOCK_MODE_GCM.equalsIgnoreCase(mode)) {
|
||||
args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, KeymasterDefs.KM_MODE_GCM);
|
||||
}
|
||||
}
|
||||
|
||||
if (parts.length > 2) {
|
||||
String padding = parts[2];
|
||||
if (KeyProperties.ENCRYPTION_PADDING_NONE.equalsIgnoreCase(padding)) {
|
||||
// Noop
|
||||
} else if (KeyProperties.ENCRYPTION_PADDING_PKCS7.equalsIgnoreCase(padding)) {
|
||||
args.addEnums(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_PKCS7);
|
||||
} else if (KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1.equalsIgnoreCase(padding)) {
|
||||
args.addEnums(KeymasterDefs.KM_TAG_PADDING,
|
||||
KeymasterDefs.KM_PAD_RSA_PKCS1_1_5_ENCRYPT);
|
||||
} else if (KeyProperties.ENCRYPTION_PADDING_RSA_OAEP.equalsIgnoreCase(padding)) {
|
||||
args.addEnums(KeymasterDefs.KM_TAG_PADDING, KeymasterDefs.KM_PAD_RSA_OAEP);
|
||||
}
|
||||
}
|
||||
|
||||
KeyGenParameterSpec spec = (KeyGenParameterSpec) entry.getAlgorithmParameterSpec();
|
||||
if (spec.isDigestsSpecified()) {
|
||||
String digest = spec.getDigests()[0];
|
||||
if (KeyProperties.DIGEST_NONE.equalsIgnoreCase(digest)) {
|
||||
// Noop
|
||||
} else if (KeyProperties.DIGEST_MD5.equalsIgnoreCase(digest)) {
|
||||
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_MD5);
|
||||
} else if (KeyProperties.DIGEST_SHA1.equalsIgnoreCase(digest)) {
|
||||
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA1);
|
||||
} else if (KeyProperties.DIGEST_SHA224.equalsIgnoreCase(digest)) {
|
||||
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_224);
|
||||
} else if (KeyProperties.DIGEST_SHA256.equalsIgnoreCase(digest)) {
|
||||
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_256);
|
||||
} else if (KeyProperties.DIGEST_SHA384.equalsIgnoreCase(digest)) {
|
||||
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_384);
|
||||
} else if (KeyProperties.DIGEST_SHA512.equalsIgnoreCase(digest)) {
|
||||
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeymasterDefs.KM_DIGEST_SHA_2_512);
|
||||
}
|
||||
}
|
||||
|
||||
int errorCode = mKeyStore.importWrappedKey(
|
||||
Credentials.USER_SECRET_KEY + alias,
|
||||
wrappedKeyBytes,
|
||||
Credentials.USER_PRIVATE_KEY + wrappingKeyAlias,
|
||||
entry.getWrappedKeyBytes(),
|
||||
Credentials.USER_PRIVATE_KEY + entry.getWrappingKeyAlias(),
|
||||
maskingKey,
|
||||
args,
|
||||
GateKeeper.getSecureUserId(),
|
||||
@ -996,7 +1060,7 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi {
|
||||
setSecretKeyEntry(alias, secE.getSecretKey(), param);
|
||||
} else if (entry instanceof WrappedKeyEntry) {
|
||||
WrappedKeyEntry wke = (WrappedKeyEntry) entry;
|
||||
setWrappedKeyEntry(alias, wke.getWrappedKeyBytes(), wke.getWrappingKeyAlias(), param);
|
||||
setWrappedKeyEntry(alias, wke, param);
|
||||
} else {
|
||||
throw new KeyStoreException(
|
||||
"Entry must be a PrivateKeyEntry, SecretKeyEntry or TrustedCertificateEntry"
|
||||
|
@ -232,6 +232,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
|
||||
private final boolean mCriticalToDeviceEncryption;
|
||||
private final boolean mUserConfirmationRequired;
|
||||
private final boolean mUnlockedDeviceRequired;
|
||||
private final boolean mIsStrongBoxBacked;
|
||||
|
||||
private KeyProtection(
|
||||
Date keyValidityStart,
|
||||
@ -251,7 +252,8 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
|
||||
long boundToSecureUserId,
|
||||
boolean criticalToDeviceEncryption,
|
||||
boolean userConfirmationRequired,
|
||||
boolean unlockedDeviceRequired) {
|
||||
boolean unlockedDeviceRequired,
|
||||
boolean isStrongBoxBacked) {
|
||||
mKeyValidityStart = Utils.cloneIfNotNull(keyValidityStart);
|
||||
mKeyValidityForOriginationEnd = Utils.cloneIfNotNull(keyValidityForOriginationEnd);
|
||||
mKeyValidityForConsumptionEnd = Utils.cloneIfNotNull(keyValidityForConsumptionEnd);
|
||||
@ -272,6 +274,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
|
||||
mCriticalToDeviceEncryption = criticalToDeviceEncryption;
|
||||
mUserConfirmationRequired = userConfirmationRequired;
|
||||
mUnlockedDeviceRequired = unlockedDeviceRequired;
|
||||
mIsStrongBoxBacked = isStrongBoxBacked;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -528,6 +531,14 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
|
||||
return mUnlockedDeviceRequired;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if the key is protected by a Strongbox security chip.
|
||||
* @hide
|
||||
*/
|
||||
public boolean isStrongBoxBacked() {
|
||||
return mIsStrongBoxBacked;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builder of {@link KeyProtection} instances.
|
||||
*/
|
||||
@ -552,6 +563,7 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
|
||||
|
||||
private long mBoundToSecureUserId = GateKeeper.INVALID_SECURE_USER_ID;
|
||||
private boolean mCriticalToDeviceEncryption = false;
|
||||
private boolean mIsStrongBoxBacked = false;
|
||||
|
||||
/**
|
||||
* Creates a new instance of the {@code Builder}.
|
||||
@ -961,6 +973,16 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether this key should be protected by a StrongBox security chip.
|
||||
* @hide
|
||||
*/
|
||||
@NonNull
|
||||
public Builder setIsStrongBoxBacked(boolean isStrongBoxBacked) {
|
||||
mIsStrongBoxBacked = isStrongBoxBacked;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds an instance of {@link KeyProtection}.
|
||||
*
|
||||
@ -986,7 +1008,8 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
|
||||
mBoundToSecureUserId,
|
||||
mCriticalToDeviceEncryption,
|
||||
mUserConfirmationRequired,
|
||||
mUnlockedDeviceRequired);
|
||||
mUnlockedDeviceRequired,
|
||||
mIsStrongBoxBacked);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user