Merge "Add support for app-generated attestation keys." am: 50a66e39cd am: 2da3a280d2 am: bbdb4d9ee5

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

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I0e4b2bcfa54953e37452a7533a89b49586596502
This commit is contained in:
Shawn Willden
2021-02-17 20:49:09 +00:00
committed by Automerger Merge Worker
8 changed files with 241 additions and 84 deletions

View File

@@ -12429,6 +12429,7 @@ package android.content.pm {
field public static final String FEATURE_INPUT_METHODS = "android.software.input_methods";
field public static final String FEATURE_IPSEC_TUNNELS = "android.software.ipsec_tunnels";
field public static final String FEATURE_IRIS = "android.hardware.biometrics.iris";
field public static final String FEATURE_KEYSTORE_APP_ATTEST_KEY = "android.hardware.keystore.app_attest_key";
field public static final String FEATURE_KEYSTORE_LIMITED_USE_KEY = "android.hardware.keystore.limited_use_key";
field public static final String FEATURE_KEYSTORE_SINGLE_USE_KEY = "android.hardware.keystore.single_use_key";
field public static final String FEATURE_LEANBACK = "android.software.leanback";
@@ -37090,6 +37091,7 @@ package android.security.keystore {
public final class KeyGenParameterSpec implements java.security.spec.AlgorithmParameterSpec {
method @Nullable public java.security.spec.AlgorithmParameterSpec getAlgorithmParameterSpec();
method @Nullable public String getAttestKeyAlias();
method public byte[] getAttestationChallenge();
method @NonNull public String[] getBlockModes();
method @NonNull public java.util.Date getCertificateNotAfter();
@@ -37124,6 +37126,7 @@ package android.security.keystore {
ctor public KeyGenParameterSpec.Builder(@NonNull String, int);
method @NonNull public android.security.keystore.KeyGenParameterSpec build();
method public android.security.keystore.KeyGenParameterSpec.Builder setAlgorithmParameterSpec(@NonNull java.security.spec.AlgorithmParameterSpec);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setAttestKeyAlias(@Nullable String);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setAttestationChallenge(byte[]);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setBlockModes(java.lang.String...);
method @NonNull public android.security.keystore.KeyGenParameterSpec.Builder setCertificateNotAfter(@NonNull java.util.Date);
@@ -37221,6 +37224,7 @@ package android.security.keystore {
field public static final int ORIGIN_SECURELY_IMPORTED = 8; // 0x8
field public static final int ORIGIN_UNKNOWN = 4; // 0x4
field public static final int PURPOSE_AGREE_KEY = 64; // 0x40
field public static final int PURPOSE_ATTEST_KEY = 128; // 0x80
field public static final int PURPOSE_DECRYPT = 2; // 0x2
field public static final int PURPOSE_ENCRYPT = 1; // 0x1
field public static final int PURPOSE_SIGN = 4; // 0x4

View File

@@ -3669,6 +3669,15 @@ public abstract class PackageManager {
public static final String FEATURE_KEYSTORE_LIMITED_USE_KEY =
"android.hardware.keystore.limited_use_key";
/**
* Feature for {@link #getSystemAvailableFeatures} and {@link #hasSystemFeature}: The device has
* a Keystore implementation that can create application-specific attestation keys.
* See {@link android.security.keystore.KeyGenParameterSpec.Builder#setAttestKeyAlias}.
*/
@SdkConstant(SdkConstantType.FEATURE)
public static final String FEATURE_KEYSTORE_APP_ATTEST_KEY =
"android.hardware.keystore.app_attest_key";
/** @hide */
public static final boolean APP_ENUMERATION_ENABLED_BY_DEFAULT = true;

View File

@@ -188,6 +188,7 @@ public final class KeymasterDefs {
public static final int KM_PURPOSE_VERIFY = KeyPurpose.VERIFY;
public static final int KM_PURPOSE_WRAP = KeyPurpose.WRAP_KEY;
public static final int KM_PURPOSE_AGREE_KEY = KeyPurpose.AGREE_KEY;
public static final int KM_PURPOSE_ATTEST_KEY = KeyPurpose.ATTEST_KEY;
// Key formats.
public static final int KM_KEY_FORMAT_X509 = KeyFormat.X509;

View File

@@ -279,8 +279,8 @@ import javax.security.auth.x500.X500Principal;
* }
*/
public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAuthArgs {
private static final X500Principal DEFAULT_CERT_SUBJECT = new X500Principal("CN=fake");
private static final X500Principal DEFAULT_CERT_SUBJECT =
new X500Principal("CN=Android Keystore Key");
private static final BigInteger DEFAULT_CERT_SERIAL_NUMBER = new BigInteger("1");
private static final Date DEFAULT_CERT_NOT_BEFORE = new Date(0L); // Jan 1 1970
private static final Date DEFAULT_CERT_NOT_AFTER = new Date(2461449600000L); // Jan 1 2048
@@ -317,6 +317,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
private final boolean mUnlockedDeviceRequired;
private final boolean mCriticalToDeviceEncryption;
private final int mMaxUsageCount;
private final String mAttestKeyAlias;
/*
* ***NOTE***: All new fields MUST also be added to the following:
* ParcelableKeyGenParameterSpec class.
@@ -358,7 +359,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
boolean userConfirmationRequired,
boolean unlockedDeviceRequired,
boolean criticalToDeviceEncryption,
int maxUsageCount) {
int maxUsageCount,
String attestKeyAlias) {
if (TextUtils.isEmpty(keyStoreAlias)) {
throw new IllegalArgumentException("keyStoreAlias must not be empty");
}
@@ -413,6 +415,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
mUnlockedDeviceRequired = unlockedDeviceRequired;
mCriticalToDeviceEncryption = criticalToDeviceEncryption;
mMaxUsageCount = maxUsageCount;
mAttestKeyAlias = attestKeyAlias;
}
/**
@@ -868,6 +871,18 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
return mMaxUsageCount;
}
/**
* Returns the alias of the attestation key that will be used to sign the attestation
* certificate of the generated key. Note that an attestation certificate will only be
* generated if an attestation challenge is set.
*
* @see Builder#setAttestKeyAlias(String)
*/
@Nullable
public String getAttestKeyAlias() {
return mAttestKeyAlias;
}
/**
* Builder of {@link KeyGenParameterSpec} instances.
*/
@@ -906,6 +921,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
private boolean mUnlockedDeviceRequired = false;
private boolean mCriticalToDeviceEncryption = false;
private int mMaxUsageCount = KeyProperties.UNRESTRICTED_USAGE_COUNT;
private String mAttestKeyAlias = null;
/**
* Creates a new instance of the {@code Builder}.
@@ -975,6 +991,7 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
mUnlockedDeviceRequired = sourceSpec.isUnlockedDeviceRequired();
mCriticalToDeviceEncryption = sourceSpec.isCriticalToDeviceEncryption();
mMaxUsageCount = sourceSpec.getMaxUsageCount();
mAttestKeyAlias = sourceSpec.getAttestKeyAlias();
}
/**
@@ -1694,6 +1711,28 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
throw new IllegalArgumentException("maxUsageCount is not valid");
}
/**
* Sets the alias of the attestation key that will be used to sign the attestation
* certificate for the generated key pair, if an attestation challenge is set with {@link
* #setAttestationChallenge}. If an attestKeyAlias is set but no challenge, {@link
* java.security.KeyPairGenerator#initialize} will throw {@link
* java.security.InvalidAlgorithmParameterException}.
*
* <p>If the attestKeyAlias is set to null (the default), Android Keystore will select an
* appropriate system-provided attestation signing key. If not null, the alias must
* reference an Android Keystore Key that was created with {@link
* android.security.keystore.KeyProperties#PURPOSE_ATTEST_KEY}, or key generation will throw
* {@link java.security.InvalidAlgorithmParameterException}.
*
* @param attestKeyAlias the alias of the attestation key to be used to sign the
* attestation certificate.
*/
@NonNull
public Builder setAttestKeyAlias(@Nullable String attestKeyAlias) {
mAttestKeyAlias = attestKeyAlias;
return this;
}
/**
* Builds an instance of {@code KeyGenParameterSpec}.
*/
@@ -1731,7 +1770,8 @@ public final class KeyGenParameterSpec implements AlgorithmParameterSpec, UserAu
mUserConfirmationRequired,
mUnlockedDeviceRequired,
mCriticalToDeviceEncryption,
mMaxUsageCount);
mMaxUsageCount,
mAttestKeyAlias);
}
}
}

View File

@@ -70,6 +70,7 @@ public abstract class KeyProperties {
PURPOSE_VERIFY,
PURPOSE_WRAP_KEY,
PURPOSE_AGREE_KEY,
PURPOSE_ATTEST_KEY,
})
public @interface PurposeEnum {}
@@ -112,6 +113,13 @@ public abstract class KeyProperties {
*/
public static final int PURPOSE_AGREE_KEY = 1 << 6;
/**
* Purpose of key: Signing attestaions. This purpose is incompatible with all others, meaning
* that when generating a key with PURPOSE_ATTEST_KEY, no other purposes may be specified. In
* addition, PURPOSE_ATTEST_KEY may not be specified for imported keys.
*/
public static final int PURPOSE_ATTEST_KEY = 1 << 7;
/**
* @hide
*/
@@ -132,6 +140,8 @@ public abstract class KeyProperties {
return KeymasterDefs.KM_PURPOSE_WRAP;
case PURPOSE_AGREE_KEY:
return KeymasterDefs.KM_PURPOSE_AGREE_KEY;
case PURPOSE_ATTEST_KEY:
return KeymasterDefs.KM_PURPOSE_ATTEST_KEY;
default:
throw new IllegalArgumentException("Unknown purpose: " + purpose);
}
@@ -151,6 +161,8 @@ public abstract class KeyProperties {
return PURPOSE_WRAP_KEY;
case KeymasterDefs.KM_PURPOSE_AGREE_KEY:
return PURPOSE_AGREE_KEY;
case KeymasterDefs.KM_PURPOSE_ATTEST_KEY:
return PURPOSE_ATTEST_KEY;
default:
throw new IllegalArgumentException("Unknown purpose: " + purpose);
}

View File

@@ -588,7 +588,8 @@ public final class KeyProtection implements ProtectionParameter, UserAuthArgs {
private long mBoundToSecureUserId = GateKeeper.INVALID_SECURE_USER_ID;
private boolean mCriticalToDeviceEncryption = false;
private boolean mIsStrongBoxBacked = false;
private int mMaxUsageCount = KeyProperties.UNRESTRICTED_USAGE_COUNT;
private int mMaxUsageCount = KeyProperties.UNRESTRICTED_USAGE_COUNT;
private String mAttestKeyAlias = null;
/**
* Creates a new instance of the {@code Builder}.

View File

@@ -110,6 +110,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable {
out.writeBoolean(mSpec.isUnlockedDeviceRequired());
out.writeBoolean(mSpec.isCriticalToDeviceEncryption());
out.writeInt(mSpec.getMaxUsageCount());
out.writeString(mSpec.getAttestKeyAlias());
}
private static Date readDateOrNull(Parcel in) {
@@ -170,6 +171,7 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable {
final boolean unlockedDeviceRequired = in.readBoolean();
final boolean criticalToDeviceEncryption = in.readBoolean();
final int maxUsageCount = in.readInt();
final String attestKeyAlias = in.readString();
// The KeyGenParameterSpec is intentionally not constructed using a Builder here:
// The intention is for this class to break if new parameters are added to the
// KeyGenParameterSpec constructor (whereas using a builder would silently drop them).
@@ -205,7 +207,8 @@ public final class ParcelableKeyGenParameterSpec implements Parcelable {
userConfirmationRequired,
unlockedDeviceRequired,
criticalToDeviceEncryption,
maxUsageCount);
maxUsageCount,
attestKeyAlias);
}
public static final @android.annotation.NonNull Creator<ParcelableKeyGenParameterSpec> CREATOR = new Creator<ParcelableKeyGenParameterSpec>() {

View File

@@ -20,7 +20,9 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.Context;
import android.hardware.security.keymint.KeyParameter;
import android.hardware.security.keymint.KeyPurpose;
import android.hardware.security.keymint.SecurityLevel;
import android.hardware.security.keymint.Tag;
import android.os.Build;
import android.security.KeyPairGeneratorSpec;
import android.security.KeyStore;
@@ -37,9 +39,11 @@ import android.security.keystore.KeyProperties;
import android.security.keystore.KeymasterUtils;
import android.security.keystore.SecureKeyImportUnavailableException;
import android.security.keystore.StrongBoxUnavailableException;
import android.system.keystore2.Authorization;
import android.system.keystore2.Domain;
import android.system.keystore2.IKeystoreSecurityLevel;
import android.system.keystore2.KeyDescriptor;
import android.system.keystore2.KeyEntryResponse;
import android.system.keystore2.KeyMetadata;
import android.system.keystore2.ResponseCode;
import android.telephony.TelephonyManager;
@@ -61,6 +65,7 @@ import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.ECGenParameterSpec;
import java.security.spec.RSAKeyGenParameterSpec;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
@@ -69,6 +74,7 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.function.Predicate;
/**
* Provides a way to create instances of a KeyPair which will be placed in the
@@ -153,6 +159,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
private int mKeymasterAlgorithm = -1;
private int mKeySizeBits;
private SecureRandom mRng;
private KeyDescriptor mAttestKeyDescriptor;
private int[] mKeymasterPurposes;
private int[] mKeymasterBlockModes;
@@ -197,83 +204,9 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
// Legacy/deprecated spec
KeyPairGeneratorSpec legacySpec = (KeyPairGeneratorSpec) params;
try {
KeyGenParameterSpec.Builder specBuilder;
String specKeyAlgorithm = legacySpec.getKeyType();
if (specKeyAlgorithm != null) {
// Spec overrides the generator's default key algorithm
try {
keymasterAlgorithm =
KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(
specKeyAlgorithm);
} catch (IllegalArgumentException e) {
throw new InvalidAlgorithmParameterException(
"Invalid key type in parameters", e);
}
}
switch (keymasterAlgorithm) {
case KeymasterDefs.KM_ALGORITHM_EC:
specBuilder = new KeyGenParameterSpec.Builder(
legacySpec.getKeystoreAlias(),
KeyProperties.PURPOSE_SIGN
| KeyProperties.PURPOSE_VERIFY);
// Authorized to be used with any digest (including no digest).
// MD5 was never offered for Android Keystore for ECDSA.
specBuilder.setDigests(
KeyProperties.DIGEST_NONE,
KeyProperties.DIGEST_SHA1,
KeyProperties.DIGEST_SHA224,
KeyProperties.DIGEST_SHA256,
KeyProperties.DIGEST_SHA384,
KeyProperties.DIGEST_SHA512);
break;
case KeymasterDefs.KM_ALGORITHM_RSA:
specBuilder = new KeyGenParameterSpec.Builder(
legacySpec.getKeystoreAlias(),
KeyProperties.PURPOSE_ENCRYPT
| KeyProperties.PURPOSE_DECRYPT
| KeyProperties.PURPOSE_SIGN
| KeyProperties.PURPOSE_VERIFY);
// Authorized to be used with any digest (including no digest).
specBuilder.setDigests(
KeyProperties.DIGEST_NONE,
KeyProperties.DIGEST_MD5,
KeyProperties.DIGEST_SHA1,
KeyProperties.DIGEST_SHA224,
KeyProperties.DIGEST_SHA256,
KeyProperties.DIGEST_SHA384,
KeyProperties.DIGEST_SHA512);
// Authorized to be used with any encryption and signature padding
// schemes (including no padding).
specBuilder.setEncryptionPaddings(
KeyProperties.ENCRYPTION_PADDING_NONE,
KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1,
KeyProperties.ENCRYPTION_PADDING_RSA_OAEP);
specBuilder.setSignaturePaddings(
KeyProperties.SIGNATURE_PADDING_RSA_PKCS1,
KeyProperties.SIGNATURE_PADDING_RSA_PSS);
// Disable randomized encryption requirement to support encryption
// padding NONE above.
specBuilder.setRandomizedEncryptionRequired(false);
break;
default:
throw new ProviderException(
"Unsupported algorithm: " + mKeymasterAlgorithm);
}
if (legacySpec.getKeySize() != -1) {
specBuilder.setKeySize(legacySpec.getKeySize());
}
if (legacySpec.getAlgorithmParameterSpec() != null) {
specBuilder.setAlgorithmParameterSpec(
legacySpec.getAlgorithmParameterSpec());
}
specBuilder.setCertificateSubject(legacySpec.getSubjectDN());
specBuilder.setCertificateSerialNumber(legacySpec.getSerialNumber());
specBuilder.setCertificateNotBefore(legacySpec.getStartDate());
specBuilder.setCertificateNotAfter(legacySpec.getEndDate());
specBuilder.setUserAuthenticationRequired(false);
spec = specBuilder.build();
keymasterAlgorithm = getKeymasterAlgorithmFromLegacy(keymasterAlgorithm,
legacySpec);
spec = buildKeyGenParameterSpecFromLegacy(legacySpec, keymasterAlgorithm);
} catch (NullPointerException | IllegalArgumentException e) {
throw new InvalidAlgorithmParameterException(e);
}
@@ -342,6 +275,10 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
mJcaKeyAlgorithm = jcaKeyAlgorithm;
mRng = random;
mKeyStore = KeyStore2.getInstance();
mAttestKeyDescriptor = buildAndCheckAttestKeyDescriptor(spec);
checkAttestKeyPurpose(spec);
success = true;
} finally {
if (!success) {
@@ -350,6 +287,156 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
}
}
private void checkAttestKeyPurpose(KeyGenParameterSpec spec)
throws InvalidAlgorithmParameterException {
if ((spec.getPurposes() & KeyProperties.PURPOSE_ATTEST_KEY) != 0
&& spec.getPurposes() != KeyProperties.PURPOSE_ATTEST_KEY) {
throw new InvalidAlgorithmParameterException(
"PURPOSE_ATTEST_KEY may not be specified with any other purposes");
}
}
private KeyDescriptor buildAndCheckAttestKeyDescriptor(KeyGenParameterSpec spec)
throws InvalidAlgorithmParameterException {
if (spec.getAttestKeyAlias() != null) {
KeyDescriptor attestKeyDescriptor = new KeyDescriptor();
attestKeyDescriptor.domain = Domain.APP;
attestKeyDescriptor.alias = spec.getAttestKeyAlias();
try {
KeyEntryResponse attestKey = mKeyStore.getKeyEntry(attestKeyDescriptor);
checkAttestKeyChallenge(spec);
checkAttestKeyPurpose(attestKey.metadata.authorizations);
checkAttestKeySecurityLevel(spec, attestKey);
} catch (KeyStoreException e) {
throw new InvalidAlgorithmParameterException("Invalid attestKeyAlias", e);
}
return attestKeyDescriptor;
}
return null;
}
private void checkAttestKeyChallenge(KeyGenParameterSpec spec)
throws InvalidAlgorithmParameterException {
if (spec.getAttestationChallenge() == null) {
throw new InvalidAlgorithmParameterException(
"AttestKey specified but no attestation challenge provided");
}
}
private void checkAttestKeyPurpose(Authorization[] keyAuths)
throws InvalidAlgorithmParameterException {
Predicate<Authorization> isAttestKeyPurpose = x -> x.keyParameter.tag == Tag.PURPOSE
&& x.keyParameter.value.getKeyPurpose() == KeyPurpose.ATTEST_KEY;
if (Arrays.stream(keyAuths).noneMatch(isAttestKeyPurpose)) {
throw new InvalidAlgorithmParameterException(
("Invalid attestKey, does not have PURPOSE_ATTEST_KEY"));
}
}
private void checkAttestKeySecurityLevel(KeyGenParameterSpec spec, KeyEntryResponse key)
throws InvalidAlgorithmParameterException {
boolean attestKeyInStrongBox = key.metadata.keySecurityLevel == SecurityLevel.STRONGBOX;
if (spec.isStrongBoxBacked() != attestKeyInStrongBox) {
if (attestKeyInStrongBox) {
throw new InvalidAlgorithmParameterException(
"Invalid security level: Cannot sign non-StrongBox key with "
+ "StrongBox attestKey");
} else {
throw new InvalidAlgorithmParameterException(
"Invalid security level: Cannot sign StrongBox key with "
+ "non-StrongBox attestKey");
}
}
}
private int getKeymasterAlgorithmFromLegacy(int keymasterAlgorithm,
KeyPairGeneratorSpec legacySpec) throws InvalidAlgorithmParameterException {
String specKeyAlgorithm = legacySpec.getKeyType();
if (specKeyAlgorithm != null) {
// Spec overrides the generator's default key algorithm
try {
keymasterAlgorithm =
KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(
specKeyAlgorithm);
} catch (IllegalArgumentException e) {
throw new InvalidAlgorithmParameterException(
"Invalid key type in parameters", e);
}
}
return keymasterAlgorithm;
}
private KeyGenParameterSpec buildKeyGenParameterSpecFromLegacy(KeyPairGeneratorSpec legacySpec,
int keymasterAlgorithm) {
KeyGenParameterSpec.Builder specBuilder;
switch (keymasterAlgorithm) {
case KeymasterDefs.KM_ALGORITHM_EC:
specBuilder = new KeyGenParameterSpec.Builder(
legacySpec.getKeystoreAlias(),
KeyProperties.PURPOSE_SIGN
| KeyProperties.PURPOSE_VERIFY);
// Authorized to be used with any digest (including no digest).
// MD5 was never offered for Android Keystore for ECDSA.
specBuilder.setDigests(
KeyProperties.DIGEST_NONE,
KeyProperties.DIGEST_SHA1,
KeyProperties.DIGEST_SHA224,
KeyProperties.DIGEST_SHA256,
KeyProperties.DIGEST_SHA384,
KeyProperties.DIGEST_SHA512);
break;
case KeymasterDefs.KM_ALGORITHM_RSA:
specBuilder = new KeyGenParameterSpec.Builder(
legacySpec.getKeystoreAlias(),
KeyProperties.PURPOSE_ENCRYPT
| KeyProperties.PURPOSE_DECRYPT
| KeyProperties.PURPOSE_SIGN
| KeyProperties.PURPOSE_VERIFY);
// Authorized to be used with any digest (including no digest).
specBuilder.setDigests(
KeyProperties.DIGEST_NONE,
KeyProperties.DIGEST_MD5,
KeyProperties.DIGEST_SHA1,
KeyProperties.DIGEST_SHA224,
KeyProperties.DIGEST_SHA256,
KeyProperties.DIGEST_SHA384,
KeyProperties.DIGEST_SHA512);
// Authorized to be used with any encryption and signature padding
// schemes (including no padding).
specBuilder.setEncryptionPaddings(
KeyProperties.ENCRYPTION_PADDING_NONE,
KeyProperties.ENCRYPTION_PADDING_RSA_PKCS1,
KeyProperties.ENCRYPTION_PADDING_RSA_OAEP);
specBuilder.setSignaturePaddings(
KeyProperties.SIGNATURE_PADDING_RSA_PKCS1,
KeyProperties.SIGNATURE_PADDING_RSA_PSS);
// Disable randomized encryption requirement to support encryption
// padding NONE above.
specBuilder.setRandomizedEncryptionRequired(false);
break;
default:
throw new ProviderException(
"Unsupported algorithm: " + mKeymasterAlgorithm);
}
if (legacySpec.getKeySize() != -1) {
specBuilder.setKeySize(legacySpec.getKeySize());
}
if (legacySpec.getAlgorithmParameterSpec() != null) {
specBuilder.setAlgorithmParameterSpec(
legacySpec.getAlgorithmParameterSpec());
}
specBuilder.setCertificateSubject(legacySpec.getSubjectDN());
specBuilder.setCertificateSerialNumber(legacySpec.getSerialNumber());
specBuilder.setCertificateNotBefore(legacySpec.getStartDate());
specBuilder.setCertificateNotAfter(legacySpec.getEndDate());
specBuilder.setUserAuthenticationRequired(false);
return specBuilder.build();
}
private void resetAll() {
mEntryAlias = null;
mEntryUid = KeyProperties.NAMESPACE_APPLICATION;
@@ -464,7 +551,7 @@ public abstract class AndroidKeyStoreKeyPairGeneratorSpi extends KeyPairGenerato
try {
KeyStoreSecurityLevel iSecurityLevel = mKeyStore.getSecurityLevel(securityLevel);
KeyMetadata metadata = iSecurityLevel.generateKey(descriptor, null,
KeyMetadata metadata = iSecurityLevel.generateKey(descriptor, mAttestKeyDescriptor,
constructKeyGenerationArguments(), flags, additionalEntropy);
AndroidKeyStorePublicKey publicKey =