use of java.security.ProviderException in project android_frameworks_base by DirtyUnicorns.
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 DirtyUnicorns.
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 DirtyUnicorns.
the class AndroidKeyStoreKeyPairGeneratorSpi method getAttestationChain.
private Iterable<byte[]> getAttestationChain(String privateKeyAlias, KeyPair keyPair, KeymasterArguments args) throws ProviderException {
KeymasterCertificateChain outChain = new KeymasterCertificateChain();
int errorCode = mKeyStore.attestKey(privateKeyAlias, args, outChain);
if (errorCode != KeyStore.NO_ERROR) {
throw new ProviderException("Failed to generate attestation certificate chain", KeyStore.getKeyStoreException(errorCode));
}
Collection<byte[]> chain = outChain.getCertificates();
if (chain.size() < 2) {
throw new ProviderException("Attestation certificate chain contained " + chain.size() + " entries. At least two are required.");
}
return chain;
}
use of java.security.ProviderException in project android_frameworks_base by DirtyUnicorns.
the class AndroidKeyStoreKeyPairGeneratorSpi method initAlgorithmSpecificParameters.
private void initAlgorithmSpecificParameters() throws InvalidAlgorithmParameterException {
AlgorithmParameterSpec algSpecificSpec = mSpec.getAlgorithmParameterSpec();
switch(mKeymasterAlgorithm) {
case KeymasterDefs.KM_ALGORITHM_RSA:
{
BigInteger publicExponent = null;
if (algSpecificSpec instanceof RSAKeyGenParameterSpec) {
RSAKeyGenParameterSpec rsaSpec = (RSAKeyGenParameterSpec) algSpecificSpec;
if (mKeySizeBits == -1) {
mKeySizeBits = rsaSpec.getKeysize();
} else if (mKeySizeBits != rsaSpec.getKeysize()) {
throw new InvalidAlgorithmParameterException("RSA key size must match " + " between " + mSpec + " and " + algSpecificSpec + ": " + mKeySizeBits + " vs " + rsaSpec.getKeysize());
}
publicExponent = rsaSpec.getPublicExponent();
} else if (algSpecificSpec != null) {
throw new InvalidAlgorithmParameterException("RSA may only use RSAKeyGenParameterSpec");
}
if (publicExponent == null) {
publicExponent = RSAKeyGenParameterSpec.F4;
}
if (publicExponent.compareTo(BigInteger.ZERO) < 1) {
throw new InvalidAlgorithmParameterException("RSA public exponent must be positive: " + publicExponent);
}
if (publicExponent.compareTo(KeymasterArguments.UINT64_MAX_VALUE) > 0) {
throw new InvalidAlgorithmParameterException("Unsupported RSA public exponent: " + publicExponent + ". Maximum supported value: " + KeymasterArguments.UINT64_MAX_VALUE);
}
mRSAPublicExponent = publicExponent;
break;
}
case KeymasterDefs.KM_ALGORITHM_EC:
if (algSpecificSpec instanceof ECGenParameterSpec) {
ECGenParameterSpec ecSpec = (ECGenParameterSpec) algSpecificSpec;
String curveName = ecSpec.getName();
Integer ecSpecKeySizeBits = SUPPORTED_EC_NIST_CURVE_NAME_TO_SIZE.get(curveName.toLowerCase(Locale.US));
if (ecSpecKeySizeBits == null) {
throw new InvalidAlgorithmParameterException("Unsupported EC curve name: " + curveName + ". Supported: " + SUPPORTED_EC_NIST_CURVE_NAMES);
}
if (mKeySizeBits == -1) {
mKeySizeBits = ecSpecKeySizeBits;
} else if (mKeySizeBits != ecSpecKeySizeBits) {
throw new InvalidAlgorithmParameterException("EC key size must match " + " between " + mSpec + " and " + algSpecificSpec + ": " + mKeySizeBits + " vs " + ecSpecKeySizeBits);
}
} else if (algSpecificSpec != null) {
throw new InvalidAlgorithmParameterException("EC may only use ECGenParameterSpec");
}
break;
default:
throw new ProviderException("Unsupported algorithm: " + mKeymasterAlgorithm);
}
}
use of java.security.ProviderException in project android_frameworks_base by DirtyUnicorns.
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