use of java.security.ProviderException in project android_frameworks_base by AOSPA.
the class KeyStoreCryptoOperationChunkedStreamer method flush.
public byte[] flush() throws KeyStoreException {
if (mBufferedLength <= 0) {
return EmptyArray.BYTE;
}
// Keep invoking the update operation with remaining buffered data until either all of the
// buffered data is consumed or until update fails to consume anything.
ByteArrayOutputStream bufferedOutput = null;
while (mBufferedLength > 0) {
byte[] chunk = ArrayUtils.subarray(mBuffered, mBufferedOffset, mBufferedLength);
OperationResult opResult = mKeyStoreStream.update(chunk);
if (opResult == null) {
throw new KeyStoreConnectException();
} else if (opResult.resultCode != KeyStore.NO_ERROR) {
throw KeyStore.getKeyStoreException(opResult.resultCode);
}
if (opResult.inputConsumed <= 0) {
// Nothing was consumed. Break out of the loop to avoid an infinite loop.
break;
}
if (opResult.inputConsumed >= chunk.length) {
// All of the input was consumed
mBuffered = EmptyArray.BYTE;
mBufferedOffset = 0;
mBufferedLength = 0;
} else {
// Some of the input was not consumed
mBuffered = chunk;
mBufferedOffset = opResult.inputConsumed;
mBufferedLength = chunk.length - opResult.inputConsumed;
}
if (opResult.inputConsumed > chunk.length) {
throw new KeyStoreException(KeymasterDefs.KM_ERROR_UNKNOWN_ERROR, "Keystore consumed more input than provided. Provided: " + chunk.length + ", consumed: " + opResult.inputConsumed);
}
if ((opResult.output != null) && (opResult.output.length > 0)) {
// Some output was produced by this update operation
if (bufferedOutput == null) {
// No output buffered yet.
if (mBufferedLength == 0) {
// No more output will be produced by this flush operation
mProducedOutputSizeBytes += opResult.output.length;
return opResult.output;
} else {
// More output might be produced by this flush operation -- buffer output.
bufferedOutput = new ByteArrayOutputStream();
}
}
// Buffer the output from this update operation
try {
bufferedOutput.write(opResult.output);
} catch (IOException e) {
throw new ProviderException("Failed to buffer output", e);
}
}
}
if (mBufferedLength > 0) {
throw new KeyStoreException(KeymasterDefs.KM_ERROR_INVALID_INPUT_LENGTH, "Keystore failed to consume last " + ((mBufferedLength != 1) ? (mBufferedLength + " bytes") : "byte") + " of input");
}
byte[] result = (bufferedOutput != null) ? bufferedOutput.toByteArray() : EmptyArray.BYTE;
mProducedOutputSizeBytes += result.length;
return result;
}
use of java.security.ProviderException in project android_frameworks_base by AOSPA.
the class KeymasterUtils method addUserAuthArgs.
/**
* Adds keymaster arguments to express the key's authorization policy supported by user
* authentication.
*
* @param userAuthenticationRequired whether user authentication is required to authorize the
* use of the key.
* @param userAuthenticationValidityDurationSeconds duration of time (seconds) for which user
* authentication is valid as authorization for using the key or {@code -1} if every
* use of the key needs authorization.
*
* @throws IllegalStateException if user authentication is required but the system is in a wrong
* state (e.g., secure lock screen not set up) for generating or importing keys that
* require user authentication.
*/
public static void addUserAuthArgs(KeymasterArguments args, boolean userAuthenticationRequired, int userAuthenticationValidityDurationSeconds, boolean userAuthenticationValidWhileOnBody, boolean invalidatedByBiometricEnrollment) {
if (!userAuthenticationRequired) {
args.addBoolean(KeymasterDefs.KM_TAG_NO_AUTH_REQUIRED);
return;
}
if (userAuthenticationValidityDurationSeconds == -1) {
// Every use of this key needs to be authorized by the user. This currently means
// fingerprint-only auth.
FingerprintManager fingerprintManager = KeyStore.getApplicationContext().getSystemService(FingerprintManager.class);
// TODO: Restore USE_FINGERPRINT permission check in
// FingerprintManager.getAuthenticatorId once the ID is no longer needed here.
long fingerprintOnlySid = (fingerprintManager != null) ? fingerprintManager.getAuthenticatorId() : 0;
if (fingerprintOnlySid == 0) {
throw new IllegalStateException("At least one fingerprint must be enrolled to create keys requiring user" + " authentication for every use");
}
long sid;
if (invalidatedByBiometricEnrollment) {
// The fingerprint-only SID will change on fingerprint enrollment or removal of all,
// enrolled fingerprints, invalidating the key.
sid = fingerprintOnlySid;
} else {
// The root SID will *not* change on fingerprint enrollment, or removal of all
// enrolled fingerprints, allowing the key to remain valid.
sid = getRootSid();
}
args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, KeymasterArguments.toUint64(sid));
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_FINGERPRINT);
if (userAuthenticationValidWhileOnBody) {
throw new ProviderException("Key validity extension while device is on-body is not " + "supported for keys requiring fingerprint authentication");
}
} else {
// The key is authorized for use for the specified amount of time after the user has
// authenticated. Whatever unlocks the secure lock screen should authorize this key.
long rootSid = getRootSid();
args.addUnsignedLong(KeymasterDefs.KM_TAG_USER_SECURE_ID, KeymasterArguments.toUint64(rootSid));
args.addEnum(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, KeymasterDefs.HW_AUTH_PASSWORD | KeymasterDefs.HW_AUTH_FINGERPRINT);
args.addUnsignedInt(KeymasterDefs.KM_TAG_AUTH_TIMEOUT, userAuthenticationValidityDurationSeconds);
if (userAuthenticationValidWhileOnBody) {
args.addBoolean(KeymasterDefs.KM_TAG_ALLOW_WHILE_ON_BODY);
}
}
}
use of java.security.ProviderException in project android_frameworks_base by AOSPA.
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);
if (spec.isUseSecureProcessor())
args.addBoolean(KeymasterDefs.KM_TAG_USE_SECURE_PROCESSOR);
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 java.security.ProviderException in project android_frameworks_base by AOSPA.
the class AndroidKeyStoreKeyPairGeneratorSpi method generateSelfSignedCertificateWithFakeSignature.
@SuppressWarnings("deprecation")
private X509Certificate generateSelfSignedCertificateWithFakeSignature(PublicKey publicKey) throws IOException, CertificateParsingException {
V3TBSCertificateGenerator tbsGenerator = new V3TBSCertificateGenerator();
ASN1ObjectIdentifier sigAlgOid;
AlgorithmIdentifier sigAlgId;
byte[] signature;
switch(mKeymasterAlgorithm) {
case KeymasterDefs.KM_ALGORITHM_EC:
sigAlgOid = X9ObjectIdentifiers.ecdsa_with_SHA256;
sigAlgId = new AlgorithmIdentifier(sigAlgOid);
ASN1EncodableVector v = new ASN1EncodableVector();
v.add(new DERInteger(0));
v.add(new DERInteger(0));
signature = new DERSequence().getEncoded();
break;
case KeymasterDefs.KM_ALGORITHM_RSA:
sigAlgOid = PKCSObjectIdentifiers.sha256WithRSAEncryption;
sigAlgId = new AlgorithmIdentifier(sigAlgOid, DERNull.INSTANCE);
signature = new byte[1];
break;
default:
throw new ProviderException("Unsupported key algorithm: " + mKeymasterAlgorithm);
}
try (ASN1InputStream publicKeyInfoIn = new ASN1InputStream(publicKey.getEncoded())) {
tbsGenerator.setSubjectPublicKeyInfo(SubjectPublicKeyInfo.getInstance(publicKeyInfoIn.readObject()));
}
tbsGenerator.setSerialNumber(new ASN1Integer(mSpec.getCertificateSerialNumber()));
X509Principal subject = new X509Principal(mSpec.getCertificateSubject().getEncoded());
tbsGenerator.setSubject(subject);
tbsGenerator.setIssuer(subject);
tbsGenerator.setStartDate(new Time(mSpec.getCertificateNotBefore()));
tbsGenerator.setEndDate(new Time(mSpec.getCertificateNotAfter()));
tbsGenerator.setSignature(sigAlgId);
TBSCertificate tbsCertificate = tbsGenerator.generateTBSCertificate();
ASN1EncodableVector result = new ASN1EncodableVector();
result.add(tbsCertificate);
result.add(sigAlgId);
result.add(new DERBitString(signature));
return new X509CertificateObject(Certificate.getInstance(new DERSequence(result)));
}
use of java.security.ProviderException in project android_frameworks_base by AOSPA.
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.isUseSecureProcessor()) {
checkSecureProcessorValidKeySize(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();
}
}
}
Aggregations