use of android.security.keymaster.KeymasterArguments in project platform_frameworks_base by android.
the class AndroidKeyStoreKeyPairGeneratorSpi method initialize.
@SuppressWarnings("deprecation")
@Override
public void initialize(AlgorithmParameterSpec params, SecureRandom random) throws InvalidAlgorithmParameterException {
resetAll();
boolean success = false;
try {
if (params == null) {
throw new InvalidAlgorithmParameterException("Must supply params of type " + KeyGenParameterSpec.class.getName() + " or " + KeyPairGeneratorSpec.class.getName());
}
KeyGenParameterSpec spec;
boolean encryptionAtRestRequired = false;
int keymasterAlgorithm = mOriginalKeymasterAlgorithm;
if (params instanceof KeyGenParameterSpec) {
spec = (KeyGenParameterSpec) params;
} else if (params instanceof KeyPairGeneratorSpec) {
// 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());
encryptionAtRestRequired = legacySpec.isEncryptionRequired();
specBuilder.setUserAuthenticationRequired(false);
spec = specBuilder.build();
} catch (NullPointerException | IllegalArgumentException e) {
throw new InvalidAlgorithmParameterException(e);
}
} else {
throw new InvalidAlgorithmParameterException("Unsupported params class: " + params.getClass().getName() + ". Supported: " + KeyGenParameterSpec.class.getName() + ", " + KeyPairGeneratorSpec.class.getName());
}
mEntryAlias = spec.getKeystoreAlias();
mEntryUid = spec.getUid();
mSpec = spec;
mKeymasterAlgorithm = keymasterAlgorithm;
mEncryptionAtRestRequired = encryptionAtRestRequired;
mKeySizeBits = spec.getKeySize();
initAlgorithmSpecificParameters();
if (mKeySizeBits == -1) {
mKeySizeBits = getDefaultKeySize(keymasterAlgorithm);
}
checkValidKeySize(keymasterAlgorithm, mKeySizeBits);
if (spec.getKeystoreAlias() == null) {
throw new InvalidAlgorithmParameterException("KeyStore entry alias not provided");
}
String jcaKeyAlgorithm;
try {
jcaKeyAlgorithm = KeyProperties.KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm(keymasterAlgorithm);
mKeymasterPurposes = KeyProperties.Purpose.allToKeymaster(spec.getPurposes());
mKeymasterBlockModes = KeyProperties.BlockMode.allToKeymaster(spec.getBlockModes());
mKeymasterEncryptionPaddings = KeyProperties.EncryptionPadding.allToKeymaster(spec.getEncryptionPaddings());
if (((spec.getPurposes() & KeyProperties.PURPOSE_ENCRYPT) != 0) && (spec.isRandomizedEncryptionRequired())) {
for (int keymasterPadding : mKeymasterEncryptionPaddings) {
if (!KeymasterUtils.isKeymasterPaddingSchemeIndCpaCompatibleWithAsymmetricCrypto(keymasterPadding)) {
throw new InvalidAlgorithmParameterException("Randomized encryption (IND-CPA) required but may be violated" + " by padding scheme: " + KeyProperties.EncryptionPadding.fromKeymaster(keymasterPadding) + ". See " + KeyGenParameterSpec.class.getName() + " documentation.");
}
}
}
mKeymasterSignaturePaddings = KeyProperties.SignaturePadding.allToKeymaster(spec.getSignaturePaddings());
if (spec.isDigestsSpecified()) {
mKeymasterDigests = KeyProperties.Digest.allToKeymaster(spec.getDigests());
} else {
mKeymasterDigests = EmptyArray.INT;
}
// Check that user authentication related parameters are acceptable. This method
// will throw an IllegalStateException if there are issues (e.g., secure lock screen
// not set up).
KeymasterUtils.addUserAuthArgs(new KeymasterArguments(), mSpec.isUserAuthenticationRequired(), mSpec.getUserAuthenticationValidityDurationSeconds(), mSpec.isUserAuthenticationValidWhileOnBody(), mSpec.isInvalidatedByBiometricEnrollment());
} catch (IllegalArgumentException | IllegalStateException e) {
throw new InvalidAlgorithmParameterException(e);
}
mJcaKeyAlgorithm = jcaKeyAlgorithm;
mRng = random;
mKeyStore = KeyStore.getInstance();
success = true;
} finally {
if (!success) {
resetAll();
}
}
}
use of android.security.keymaster.KeymasterArguments in project platform_frameworks_base by android.
the class AndroidKeyStoreKeyPairGeneratorSpi method createCertificateChain.
private Iterable<byte[]> createCertificateChain(final String privateKeyAlias, KeyPair keyPair) throws ProviderException {
byte[] challenge = mSpec.getAttestationChallenge();
if (challenge != null) {
KeymasterArguments args = new KeymasterArguments();
args.addBytes(KeymasterDefs.KM_TAG_ATTESTATION_CHALLENGE, challenge);
return getAttestationChain(privateKeyAlias, keyPair, args);
}
// Very short certificate chain in the non-attestation case.
return Collections.singleton(generateSelfSignedCertificateBytes(keyPair));
}
use of android.security.keymaster.KeymasterArguments in project platform_frameworks_base by android.
the class AndroidKeyStoreSignatureSpiBase method ensureKeystoreOperationInitialized.
private void ensureKeystoreOperationInitialized() throws InvalidKeyException {
if (mMessageStreamer != null) {
return;
}
if (mCachedException != null) {
return;
}
if (mKey == null) {
throw new IllegalStateException("Not initialized");
}
KeymasterArguments keymasterInputArgs = new KeymasterArguments();
addAlgorithmSpecificParametersToBegin(keymasterInputArgs);
OperationResult opResult = mKeyStore.begin(mKey.getAlias(), mSigning ? KeymasterDefs.KM_PURPOSE_SIGN : KeymasterDefs.KM_PURPOSE_VERIFY, // permit aborting this operation if keystore runs out of resources
true, keymasterInputArgs, // no additional entropy for begin -- only finish might need some
null, mKey.getUid());
if (opResult == null) {
throw new KeyStoreConnectException();
}
// Store operation token and handle regardless of the error code returned by KeyStore to
// ensure that the operation gets aborted immediately if the code below throws an exception.
mOperationToken = opResult.token;
mOperationHandle = opResult.operationHandle;
// If necessary, throw an exception due to KeyStore operation having failed.
InvalidKeyException e = KeyStoreCryptoOperationUtils.getInvalidKeyExceptionForInit(mKeyStore, mKey, opResult.resultCode);
if (e != null) {
throw e;
}
if (mOperationToken == null) {
throw new ProviderException("Keystore returned null operation token");
}
if (mOperationHandle == 0) {
throw new ProviderException("Keystore returned invalid operation handle");
}
mMessageStreamer = createMainDataStreamer(mKeyStore, opResult.token);
}
use of android.security.keymaster.KeymasterArguments in project platform_frameworks_base by android.
the class AndroidKeyStoreSpi method setSecretKeyEntry.
private void setSecretKeyEntry(String entryAlias, SecretKey key, java.security.KeyStore.ProtectionParameter param) throws KeyStoreException {
if ((param != null) && (!(param instanceof KeyProtection))) {
throw new KeyStoreException("Unsupported protection parameter class: " + param.getClass().getName() + ". Supported: " + KeyProtection.class.getName());
}
KeyProtection params = (KeyProtection) param;
if (key instanceof AndroidKeyStoreSecretKey) {
// KeyStore-backed secret key. It cannot be duplicated into another entry and cannot
// overwrite its own entry.
String keyAliasInKeystore = ((AndroidKeyStoreSecretKey) key).getAlias();
if (keyAliasInKeystore == null) {
throw new KeyStoreException("KeyStore-backed secret key does not have an alias");
}
if (!keyAliasInKeystore.startsWith(Credentials.USER_SECRET_KEY)) {
throw new KeyStoreException("KeyStore-backed secret key has invalid alias: " + keyAliasInKeystore);
}
String keyEntryAlias = keyAliasInKeystore.substring(Credentials.USER_SECRET_KEY.length());
if (!entryAlias.equals(keyEntryAlias)) {
throw new KeyStoreException("Can only replace KeyStore-backed keys with same" + " alias: " + entryAlias + " != " + keyEntryAlias);
}
// This is the entry where this key is already stored. No need to do anything.
if (params != null) {
throw new KeyStoreException("Modifying KeyStore-backed key using protection" + " parameters not supported");
}
return;
}
if (params == null) {
throw new KeyStoreException("Protection parameters must be specified when importing a symmetric key");
}
// Not a KeyStore-backed secret key -- import its key material into keystore.
String keyExportFormat = key.getFormat();
if (keyExportFormat == null) {
throw new KeyStoreException("Only secret keys that export their key material are supported");
} else if (!"RAW".equals(keyExportFormat)) {
throw new KeyStoreException("Unsupported secret key material export format: " + keyExportFormat);
}
byte[] keyMaterial = key.getEncoded();
if (keyMaterial == null) {
throw new KeyStoreException("Key did not export its key material despite supporting" + " RAW format export");
}
KeymasterArguments args = new KeymasterArguments();
try {
int keymasterAlgorithm = KeyProperties.KeyAlgorithm.toKeymasterSecretKeyAlgorithm(key.getAlgorithm());
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, keymasterAlgorithm);
int[] keymasterDigests;
if (keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_HMAC) {
// JCA HMAC key algorithm implies a digest (e.g., HmacSHA256 key algorithm
// implies SHA-256 digest). Because keymaster HMAC key is authorized only for one
// digest, we don't let import parameters override the digest implied by the key.
// If the parameters specify digests at all, they must specify only one digest, the
// only implied by key algorithm.
int keymasterImpliedDigest = KeyProperties.KeyAlgorithm.toKeymasterDigest(key.getAlgorithm());
if (keymasterImpliedDigest == -1) {
throw new ProviderException("HMAC key algorithm digest unknown for key algorithm " + key.getAlgorithm());
}
keymasterDigests = new int[] { keymasterImpliedDigest };
if (params.isDigestsSpecified()) {
// Digest(s) explicitly specified in params -- check that the list consists of
// exactly one digest, the one implied by key algorithm.
int[] keymasterDigestsFromParams = KeyProperties.Digest.allToKeymaster(params.getDigests());
if ((keymasterDigestsFromParams.length != 1) || (keymasterDigestsFromParams[0] != keymasterImpliedDigest)) {
throw new KeyStoreException("Unsupported digests specification: " + Arrays.asList(params.getDigests()) + ". Only " + KeyProperties.Digest.fromKeymaster(keymasterImpliedDigest) + " supported for HMAC key algorithm " + key.getAlgorithm());
}
}
} else {
// Key algorithm does not imply a digest.
if (params.isDigestsSpecified()) {
keymasterDigests = KeyProperties.Digest.allToKeymaster(params.getDigests());
} else {
keymasterDigests = EmptyArray.INT;
}
}
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, keymasterDigests);
@KeyProperties.PurposeEnum int purposes = params.getPurposes();
int[] keymasterBlockModes = KeyProperties.BlockMode.allToKeymaster(params.getBlockModes());
if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0) && (params.isRandomizedEncryptionRequired())) {
for (int keymasterBlockMode : keymasterBlockModes) {
if (!KeymasterUtils.isKeymasterBlockModeIndCpaCompatibleWithSymmetricCrypto(keymasterBlockMode)) {
throw new KeyStoreException("Randomized encryption (IND-CPA) required but may be violated by" + " block mode: " + KeyProperties.BlockMode.fromKeymaster(keymasterBlockMode) + ". See KeyProtection documentation.");
}
}
}
args.addEnums(KeymasterDefs.KM_TAG_PURPOSE, KeyProperties.Purpose.allToKeymaster(purposes));
args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, keymasterBlockModes);
if (params.getSignaturePaddings().length > 0) {
throw new KeyStoreException("Signature paddings not supported for symmetric keys");
}
int[] keymasterPaddings = KeyProperties.EncryptionPadding.allToKeymaster(params.getEncryptionPaddings());
args.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterPaddings);
KeymasterUtils.addUserAuthArgs(args, params.isUserAuthenticationRequired(), params.getUserAuthenticationValidityDurationSeconds(), params.isUserAuthenticationValidWhileOnBody(), params.isInvalidatedByBiometricEnrollment());
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(args, keymasterAlgorithm, keymasterBlockModes, keymasterDigests);
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, params.getKeyValidityStart());
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, params.getKeyValidityForOriginationEnd());
args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME, params.getKeyValidityForConsumptionEnd());
if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0) && (!params.isRandomizedEncryptionRequired())) {
// Permit caller-provided IV when encrypting with this key
args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE);
}
} catch (IllegalArgumentException | IllegalStateException e) {
throw new KeyStoreException(e);
}
Credentials.deleteAllTypesForAlias(mKeyStore, entryAlias, mUid);
String keyAliasInKeystore = Credentials.USER_SECRET_KEY + entryAlias;
int errorCode = mKeyStore.importKey(keyAliasInKeystore, args, KeymasterDefs.KM_KEY_FORMAT_RAW, keyMaterial, mUid, // flags
0, new KeyCharacteristics());
if (errorCode != KeyStore.NO_ERROR) {
throw new KeyStoreException("Failed to import secret key. Keystore error code: " + errorCode);
}
}
use of android.security.keymaster.KeymasterArguments in project platform_frameworks_base by android.
the class AndroidKeyStoreSpi method setPrivateKeyEntry.
private void setPrivateKeyEntry(String alias, PrivateKey key, Certificate[] chain, java.security.KeyStore.ProtectionParameter param) throws KeyStoreException {
int flags = 0;
KeyProtection spec;
if (param == null) {
spec = getLegacyKeyProtectionParameter(key);
} else if (param instanceof KeyStoreParameter) {
spec = getLegacyKeyProtectionParameter(key);
KeyStoreParameter legacySpec = (KeyStoreParameter) param;
if (legacySpec.isEncryptionRequired()) {
flags = KeyStore.FLAG_ENCRYPTED;
}
} else if (param instanceof KeyProtection) {
spec = (KeyProtection) param;
} else {
throw new KeyStoreException("Unsupported protection parameter class:" + param.getClass().getName() + ". Supported: " + KeyProtection.class.getName() + ", " + KeyStoreParameter.class.getName());
}
// Make sure the chain exists since this is a PrivateKey
if ((chain == null) || (chain.length == 0)) {
throw new KeyStoreException("Must supply at least one Certificate with PrivateKey");
}
// Do chain type checking.
X509Certificate[] x509chain = new X509Certificate[chain.length];
for (int i = 0; i < chain.length; i++) {
if (!"X.509".equals(chain[i].getType())) {
throw new KeyStoreException("Certificates must be in X.509 format: invalid cert #" + i);
}
if (!(chain[i] instanceof X509Certificate)) {
throw new KeyStoreException("Certificates must be in X.509 format: invalid cert #" + i);
}
x509chain[i] = (X509Certificate) chain[i];
}
final byte[] userCertBytes;
try {
userCertBytes = x509chain[0].getEncoded();
} catch (CertificateEncodingException e) {
throw new KeyStoreException("Failed to encode certificate #0", e);
}
/*
* If we have a chain, store it in the CA certificate slot for this
* alias as concatenated DER-encoded certificates. These can be
* deserialized by {@link CertificateFactory#generateCertificates}.
*/
final byte[] chainBytes;
if (chain.length > 1) {
/*
* The chain is passed in as {user_cert, ca_cert_1, ca_cert_2, ...}
* so we only need the certificates starting at index 1.
*/
final byte[][] certsBytes = new byte[x509chain.length - 1][];
int totalCertLength = 0;
for (int i = 0; i < certsBytes.length; i++) {
try {
certsBytes[i] = x509chain[i + 1].getEncoded();
totalCertLength += certsBytes[i].length;
} catch (CertificateEncodingException e) {
throw new KeyStoreException("Failed to encode certificate #" + i, e);
}
}
/*
* Serialize this into one byte array so we can later call
* CertificateFactory#generateCertificates to recover them.
*/
chainBytes = new byte[totalCertLength];
int outputOffset = 0;
for (int i = 0; i < certsBytes.length; i++) {
final int certLength = certsBytes[i].length;
System.arraycopy(certsBytes[i], 0, chainBytes, outputOffset, certLength);
outputOffset += certLength;
certsBytes[i] = null;
}
} else {
chainBytes = null;
}
final String pkeyAlias;
if (key instanceof AndroidKeyStorePrivateKey) {
pkeyAlias = ((AndroidKeyStoreKey) key).getAlias();
} else {
pkeyAlias = null;
}
byte[] pkcs8EncodedPrivateKeyBytes;
KeymasterArguments importArgs;
final boolean shouldReplacePrivateKey;
if (pkeyAlias != null && pkeyAlias.startsWith(Credentials.USER_PRIVATE_KEY)) {
final String keySubalias = pkeyAlias.substring(Credentials.USER_PRIVATE_KEY.length());
if (!alias.equals(keySubalias)) {
throw new KeyStoreException("Can only replace keys with same alias: " + alias + " != " + keySubalias);
}
shouldReplacePrivateKey = false;
importArgs = null;
pkcs8EncodedPrivateKeyBytes = null;
} else {
shouldReplacePrivateKey = true;
// Make sure the PrivateKey format is the one we support.
final String keyFormat = key.getFormat();
if ((keyFormat == null) || (!"PKCS#8".equals(keyFormat))) {
throw new KeyStoreException("Unsupported private key export format: " + keyFormat + ". Only private keys which export their key material in PKCS#8 format are" + " supported.");
}
// Make sure we can actually encode the key.
pkcs8EncodedPrivateKeyBytes = key.getEncoded();
if (pkcs8EncodedPrivateKeyBytes == null) {
throw new KeyStoreException("Private key did not export any key material");
}
importArgs = new KeymasterArguments();
try {
importArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm(key.getAlgorithm()));
@KeyProperties.PurposeEnum int purposes = spec.getPurposes();
importArgs.addEnums(KeymasterDefs.KM_TAG_PURPOSE, KeyProperties.Purpose.allToKeymaster(purposes));
if (spec.isDigestsSpecified()) {
importArgs.addEnums(KeymasterDefs.KM_TAG_DIGEST, KeyProperties.Digest.allToKeymaster(spec.getDigests()));
}
importArgs.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, KeyProperties.BlockMode.allToKeymaster(spec.getBlockModes()));
int[] keymasterEncryptionPaddings = KeyProperties.EncryptionPadding.allToKeymaster(spec.getEncryptionPaddings());
if (((purposes & KeyProperties.PURPOSE_ENCRYPT) != 0) && (spec.isRandomizedEncryptionRequired())) {
for (int keymasterPadding : keymasterEncryptionPaddings) {
if (!KeymasterUtils.isKeymasterPaddingSchemeIndCpaCompatibleWithAsymmetricCrypto(keymasterPadding)) {
throw new KeyStoreException("Randomized encryption (IND-CPA) required but is violated by" + " encryption padding mode: " + KeyProperties.EncryptionPadding.fromKeymaster(keymasterPadding) + ". See KeyProtection documentation.");
}
}
}
importArgs.addEnums(KeymasterDefs.KM_TAG_PADDING, keymasterEncryptionPaddings);
importArgs.addEnums(KeymasterDefs.KM_TAG_PADDING, KeyProperties.SignaturePadding.allToKeymaster(spec.getSignaturePaddings()));
KeymasterUtils.addUserAuthArgs(importArgs, spec.isUserAuthenticationRequired(), spec.getUserAuthenticationValidityDurationSeconds(), spec.isUserAuthenticationValidWhileOnBody(), spec.isInvalidatedByBiometricEnrollment());
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, spec.getKeyValidityStart());
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, spec.getKeyValidityForOriginationEnd());
importArgs.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME, spec.getKeyValidityForConsumptionEnd());
} catch (IllegalArgumentException | IllegalStateException e) {
throw new KeyStoreException(e);
}
}
boolean success = false;
try {
// Store the private key, if necessary
if (shouldReplacePrivateKey) {
// Delete the stored private key and any related entries before importing the
// provided key
Credentials.deleteAllTypesForAlias(mKeyStore, alias, mUid);
KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics();
int errorCode = mKeyStore.importKey(Credentials.USER_PRIVATE_KEY + alias, importArgs, KeymasterDefs.KM_KEY_FORMAT_PKCS8, pkcs8EncodedPrivateKeyBytes, mUid, flags, resultingKeyCharacteristics);
if (errorCode != KeyStore.NO_ERROR) {
throw new KeyStoreException("Failed to store private key", KeyStore.getKeyStoreException(errorCode));
}
} else {
// Keep the stored private key around -- delete all other entry types
Credentials.deleteCertificateTypesForAlias(mKeyStore, alias, mUid);
Credentials.deleteSecretKeyTypeForAlias(mKeyStore, alias, mUid);
}
// Store the leaf certificate
int errorCode = mKeyStore.insert(Credentials.USER_CERTIFICATE + alias, userCertBytes, mUid, flags);
if (errorCode != KeyStore.NO_ERROR) {
throw new KeyStoreException("Failed to store certificate #0", KeyStore.getKeyStoreException(errorCode));
}
// Store the certificate chain
errorCode = mKeyStore.insert(Credentials.CA_CERTIFICATE + alias, chainBytes, mUid, flags);
if (errorCode != KeyStore.NO_ERROR) {
throw new KeyStoreException("Failed to store certificate chain", KeyStore.getKeyStoreException(errorCode));
}
success = true;
} finally {
if (!success) {
if (shouldReplacePrivateKey) {
Credentials.deleteAllTypesForAlias(mKeyStore, alias, mUid);
} else {
Credentials.deleteCertificateTypesForAlias(mKeyStore, alias, mUid);
Credentials.deleteSecretKeyTypeForAlias(mKeyStore, alias, mUid);
}
}
}
}
Aggregations