use of android.security.keymaster.KeyCharacteristics in project platform_frameworks_base by android.
the class AndroidKeyStoreProvider method loadAndroidKeyStorePublicKeyFromKeystore.
@NonNull
public static AndroidKeyStorePublicKey loadAndroidKeyStorePublicKeyFromKeystore(@NonNull KeyStore keyStore, @NonNull String privateKeyAlias, int uid) throws UnrecoverableKeyException {
KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
int errorCode = keyStore.getKeyCharacteristics(privateKeyAlias, null, null, uid, keyCharacteristics);
if (errorCode != KeyStore.NO_ERROR) {
throw (UnrecoverableKeyException) new UnrecoverableKeyException("Failed to obtain information about private key").initCause(KeyStore.getKeyStoreException(errorCode));
}
ExportResult exportResult = keyStore.exportKey(privateKeyAlias, KeymasterDefs.KM_KEY_FORMAT_X509, null, null, uid);
if (exportResult.resultCode != KeyStore.NO_ERROR) {
throw (UnrecoverableKeyException) new UnrecoverableKeyException("Failed to obtain X.509 form of public key").initCause(KeyStore.getKeyStoreException(exportResult.resultCode));
}
final byte[] x509EncodedPublicKey = exportResult.exportData;
Integer keymasterAlgorithm = keyCharacteristics.getEnum(KeymasterDefs.KM_TAG_ALGORITHM);
if (keymasterAlgorithm == null) {
throw new UnrecoverableKeyException("Key algorithm unknown");
}
String jcaKeyAlgorithm;
try {
jcaKeyAlgorithm = KeyProperties.KeyAlgorithm.fromKeymasterAsymmetricKeyAlgorithm(keymasterAlgorithm);
} catch (IllegalArgumentException e) {
throw (UnrecoverableKeyException) new UnrecoverableKeyException("Failed to load private key").initCause(e);
}
return AndroidKeyStoreProvider.getAndroidKeyStorePublicKey(privateKeyAlias, uid, jcaKeyAlgorithm, x509EncodedPublicKey);
}
use of android.security.keymaster.KeyCharacteristics in project platform_frameworks_base by android.
the class AndroidKeyStoreRSACipherSpi method initKey.
@Override
protected final void initKey(int opmode, Key key) throws InvalidKeyException {
if (key == null) {
throw new InvalidKeyException("Unsupported key: null");
}
if (!KeyProperties.KEY_ALGORITHM_RSA.equalsIgnoreCase(key.getAlgorithm())) {
throw new InvalidKeyException("Unsupported key algorithm: " + key.getAlgorithm() + ". Only " + KeyProperties.KEY_ALGORITHM_RSA + " supported");
}
AndroidKeyStoreKey keystoreKey;
if (key instanceof AndroidKeyStorePrivateKey) {
keystoreKey = (AndroidKeyStoreKey) key;
} else if (key instanceof AndroidKeyStorePublicKey) {
keystoreKey = (AndroidKeyStoreKey) key;
} else {
throw new InvalidKeyException("Unsupported key type: " + key);
}
if (keystoreKey instanceof PrivateKey) {
// Private key
switch(opmode) {
case Cipher.DECRYPT_MODE:
case Cipher.UNWRAP_MODE:
// Permitted
break;
case Cipher.ENCRYPT_MODE:
case Cipher.WRAP_MODE:
if (!adjustConfigForEncryptingWithPrivateKey()) {
throw new InvalidKeyException("RSA private keys cannot be used with " + opmodeToString(opmode) + " and padding " + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding) + ". Only RSA public keys supported for this mode");
}
break;
default:
throw new InvalidKeyException("RSA private keys cannot be used with opmode: " + opmode);
}
} else {
// Public key
switch(opmode) {
case Cipher.ENCRYPT_MODE:
case Cipher.WRAP_MODE:
// Permitted
break;
case Cipher.DECRYPT_MODE:
case Cipher.UNWRAP_MODE:
throw new InvalidKeyException("RSA public keys cannot be used with " + opmodeToString(opmode) + " and padding " + KeyProperties.EncryptionPadding.fromKeymaster(mKeymasterPadding) + ". Only RSA private keys supported for this opmode.");
// break;
default:
throw new InvalidKeyException("RSA public keys cannot be used with " + opmodeToString(opmode));
}
}
KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
int errorCode = getKeyStore().getKeyCharacteristics(keystoreKey.getAlias(), null, null, keystoreKey.getUid(), keyCharacteristics);
if (errorCode != KeyStore.NO_ERROR) {
throw getKeyStore().getInvalidKeyException(keystoreKey.getAlias(), keystoreKey.getUid(), errorCode);
}
long keySizeBits = keyCharacteristics.getUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, -1);
if (keySizeBits == -1) {
throw new InvalidKeyException("Size of key not known");
} else if (keySizeBits > Integer.MAX_VALUE) {
throw new InvalidKeyException("Key too large: " + keySizeBits + " bits");
}
mModulusSizeBytes = (int) ((keySizeBits + 7) / 8);
setKey(keystoreKey);
}
use of android.security.keymaster.KeyCharacteristics in project platform_frameworks_base by android.
the class AndroidKeyStoreSecretKeyFactorySpi method getKeyInfo.
static KeyInfo getKeyInfo(KeyStore keyStore, String entryAlias, String keyAliasInKeystore, int keyUid) {
KeyCharacteristics keyCharacteristics = new KeyCharacteristics();
int errorCode = keyStore.getKeyCharacteristics(keyAliasInKeystore, null, null, keyUid, keyCharacteristics);
if (errorCode != KeyStore.NO_ERROR) {
throw new ProviderException("Failed to obtain information about key." + " Keystore error: " + errorCode);
}
boolean insideSecureHardware;
@KeyProperties.OriginEnum int origin;
int keySize;
@KeyProperties.PurposeEnum int purposes;
String[] encryptionPaddings;
String[] signaturePaddings;
@KeyProperties.DigestEnum String[] digests;
@KeyProperties.BlockModeEnum String[] blockModes;
int keymasterSwEnforcedUserAuthenticators;
int keymasterHwEnforcedUserAuthenticators;
List<BigInteger> keymasterSecureUserIds;
try {
if (keyCharacteristics.hwEnforced.containsTag(KeymasterDefs.KM_TAG_ORIGIN)) {
insideSecureHardware = true;
origin = KeyProperties.Origin.fromKeymaster(keyCharacteristics.hwEnforced.getEnum(KeymasterDefs.KM_TAG_ORIGIN, -1));
} else if (keyCharacteristics.swEnforced.containsTag(KeymasterDefs.KM_TAG_ORIGIN)) {
insideSecureHardware = false;
origin = KeyProperties.Origin.fromKeymaster(keyCharacteristics.swEnforced.getEnum(KeymasterDefs.KM_TAG_ORIGIN, -1));
} else {
throw new ProviderException("Key origin not available");
}
long keySizeUnsigned = keyCharacteristics.getUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, -1);
if (keySizeUnsigned == -1) {
throw new ProviderException("Key size not available");
} else if (keySizeUnsigned > Integer.MAX_VALUE) {
throw new ProviderException("Key too large: " + keySizeUnsigned + " bits");
}
keySize = (int) keySizeUnsigned;
purposes = KeyProperties.Purpose.allFromKeymaster(keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_PURPOSE));
List<String> encryptionPaddingsList = new ArrayList<String>();
List<String> signaturePaddingsList = new ArrayList<String>();
// Keymaster stores both types of paddings in the same array -- we split it into two.
for (int keymasterPadding : keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_PADDING)) {
try {
@KeyProperties.EncryptionPaddingEnum String jcaPadding = KeyProperties.EncryptionPadding.fromKeymaster(keymasterPadding);
encryptionPaddingsList.add(jcaPadding);
} catch (IllegalArgumentException e) {
try {
@KeyProperties.SignaturePaddingEnum String padding = KeyProperties.SignaturePadding.fromKeymaster(keymasterPadding);
signaturePaddingsList.add(padding);
} catch (IllegalArgumentException e2) {
throw new ProviderException("Unsupported encryption padding: " + keymasterPadding);
}
}
}
encryptionPaddings = encryptionPaddingsList.toArray(new String[encryptionPaddingsList.size()]);
signaturePaddings = signaturePaddingsList.toArray(new String[signaturePaddingsList.size()]);
digests = KeyProperties.Digest.allFromKeymaster(keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_DIGEST));
blockModes = KeyProperties.BlockMode.allFromKeymaster(keyCharacteristics.getEnums(KeymasterDefs.KM_TAG_BLOCK_MODE));
keymasterSwEnforcedUserAuthenticators = keyCharacteristics.swEnforced.getEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0);
keymasterHwEnforcedUserAuthenticators = keyCharacteristics.hwEnforced.getEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0);
keymasterSecureUserIds = keyCharacteristics.getUnsignedLongs(KeymasterDefs.KM_TAG_USER_SECURE_ID);
} catch (IllegalArgumentException e) {
throw new ProviderException("Unsupported key characteristic", e);
}
Date keyValidityStart = keyCharacteristics.getDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME);
Date keyValidityForOriginationEnd = keyCharacteristics.getDate(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME);
Date keyValidityForConsumptionEnd = keyCharacteristics.getDate(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME);
boolean userAuthenticationRequired = !keyCharacteristics.getBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
long userAuthenticationValidityDurationSeconds = keyCharacteristics.getUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, -1);
if (userAuthenticationValidityDurationSeconds > Integer.MAX_VALUE) {
throw new ProviderException("User authentication timeout validity too long: " + userAuthenticationValidityDurationSeconds + " seconds");
}
boolean userAuthenticationRequirementEnforcedBySecureHardware = (userAuthenticationRequired) && (keymasterHwEnforcedUserAuthenticators != 0) && (keymasterSwEnforcedUserAuthenticators == 0);
boolean userAuthenticationValidWhileOnBody = keyCharacteristics.hwEnforced.getBoolean(KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY);
boolean invalidatedByBiometricEnrollment = false;
if (keymasterSwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_FINGERPRINT || keymasterHwEnforcedUserAuthenticators == KeymasterDefs.HW_AUTH_FINGERPRINT) {
// Fingerprint-only key; will be invalidated if the root SID isn't in the SID list.
invalidatedByBiometricEnrollment = keymasterSecureUserIds != null && !keymasterSecureUserIds.isEmpty() && !keymasterSecureUserIds.contains(getGateKeeperSecureUserId());
}
return new KeyInfo(entryAlias, insideSecureHardware, origin, keySize, keyValidityStart, keyValidityForOriginationEnd, keyValidityForConsumptionEnd, purposes, encryptionPaddings, signaturePaddings, digests, blockModes, userAuthenticationRequired, (int) userAuthenticationValidityDurationSeconds, userAuthenticationRequirementEnforcedBySecureHardware, userAuthenticationValidWhileOnBody, invalidatedByBiometricEnrollment);
}
use of android.security.keymaster.KeyCharacteristics in project platform_frameworks_base by android.
the class AndroidKeyStoreKeyGeneratorSpi method engineGenerateKey.
@Override
protected SecretKey engineGenerateKey() {
KeyGenParameterSpec spec = mSpec;
if (spec == null) {
throw new IllegalStateException("Not initialized");
}
KeymasterArguments args = new KeymasterArguments();
args.addUnsignedInt(KeymasterDefs.KM_TAG_KEY_SIZE, mKeySizeBits);
args.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, mKeymasterAlgorithm);
args.addEnums(KeymasterDefs.KM_TAG_PURPOSE, mKeymasterPurposes);
args.addEnums(KeymasterDefs.KM_TAG_BLOCK_MODE, mKeymasterBlockModes);
args.addEnums(KeymasterDefs.KM_TAG_PADDING, mKeymasterPaddings);
args.addEnums(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigests);
KeymasterUtils.addUserAuthArgs(args, spec.isUserAuthenticationRequired(), spec.getUserAuthenticationValidityDurationSeconds(), spec.isUserAuthenticationValidWhileOnBody(), spec.isInvalidatedByBiometricEnrollment());
KeymasterUtils.addMinMacLengthAuthorizationIfNecessary(args, mKeymasterAlgorithm, mKeymasterBlockModes, mKeymasterDigests);
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ACTIVE_DATETIME, spec.getKeyValidityStart());
args.addDateIfNotNull(KeymasterDefs.KM_TAG_ORIGINATION_EXPIRE_DATETIME, spec.getKeyValidityForOriginationEnd());
args.addDateIfNotNull(KeymasterDefs.KM_TAG_USAGE_EXPIRE_DATETIME, spec.getKeyValidityForConsumptionEnd());
if (((spec.getPurposes() & KeyProperties.PURPOSE_ENCRYPT) != 0) && (!spec.isRandomizedEncryptionRequired())) {
// Permit caller-provided IV when encrypting with this key
args.addBoolean(KeymasterDefs.KM_TAG_CALLER_NONCE);
}
byte[] additionalEntropy = KeyStoreCryptoOperationUtils.getRandomBytesToMixIntoKeystoreRng(mRng, (mKeySizeBits + 7) / 8);
int flags = 0;
String keyAliasInKeystore = Credentials.USER_SECRET_KEY + spec.getKeystoreAlias();
KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics();
boolean success = false;
try {
Credentials.deleteAllTypesForAlias(mKeyStore, spec.getKeystoreAlias(), spec.getUid());
int errorCode = mKeyStore.generateKey(keyAliasInKeystore, args, additionalEntropy, spec.getUid(), flags, resultingKeyCharacteristics);
if (errorCode != KeyStore.NO_ERROR) {
throw new ProviderException("Keystore operation failed", KeyStore.getKeyStoreException(errorCode));
}
@KeyProperties.KeyAlgorithmEnum String keyAlgorithmJCA;
try {
keyAlgorithmJCA = KeyProperties.KeyAlgorithm.fromKeymasterSecretKeyAlgorithm(mKeymasterAlgorithm, mKeymasterDigest);
} catch (IllegalArgumentException e) {
throw new ProviderException("Failed to obtain JCA secret key algorithm name", e);
}
SecretKey result = new AndroidKeyStoreSecretKey(keyAliasInKeystore, spec.getUid(), keyAlgorithmJCA);
success = true;
return result;
} finally {
if (!success) {
Credentials.deleteAllTypesForAlias(mKeyStore, spec.getKeystoreAlias(), spec.getUid());
}
}
}
use of android.security.keymaster.KeyCharacteristics in project platform_frameworks_base by android.
the class AndroidKeyStoreKeyPairGeneratorSpi method generateKeystoreKeyPair.
private void generateKeystoreKeyPair(final String privateKeyAlias, KeymasterArguments args, byte[] additionalEntropy, final int flags) throws ProviderException {
KeyCharacteristics resultingKeyCharacteristics = new KeyCharacteristics();
int errorCode = mKeyStore.generateKey(privateKeyAlias, args, additionalEntropy, mEntryUid, flags, resultingKeyCharacteristics);
if (errorCode != KeyStore.NO_ERROR) {
throw new ProviderException("Failed to generate key pair", KeyStore.getKeyStoreException(errorCode));
}
}
Aggregations