use of android.security.keymaster.OperationResult in project android_frameworks_base by AOSPA.
the class AndroidKeyStoreHmacSpi method ensureKeystoreOperationInitialized.
private void ensureKeystoreOperationInitialized() throws InvalidKeyException {
if (mChunkedStreamer != null) {
return;
}
if (mKey == null) {
throw new IllegalStateException("Not initialized");
}
KeymasterArguments keymasterArgs = new KeymasterArguments();
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_ALGORITHM, KeymasterDefs.KM_ALGORITHM_HMAC);
keymasterArgs.addEnum(KeymasterDefs.KM_TAG_DIGEST, mKeymasterDigest);
keymasterArgs.addUnsignedInt(KeymasterDefs.KM_TAG_MAC_LENGTH, mMacSizeBits);
OperationResult opResult = mKeyStore.begin(mKey.getAlias(), KeymasterDefs.KM_PURPOSE_SIGN, true, keymasterArgs, // no additional entropy needed for HMAC because it's deterministic
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");
}
mChunkedStreamer = new KeyStoreCryptoOperationChunkedStreamer(new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(mKeyStore, mOperationToken));
}
use of android.security.keymaster.OperationResult in project android_frameworks_base by DirtyUnicorns.
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.OperationResult 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 android.security.keymaster.OperationResult in project android_frameworks_base by DirtyUnicorns.
the class KeyStoreCryptoOperationChunkedStreamer method doFinal.
@Override
public byte[] doFinal(byte[] input, int inputOffset, int inputLength, byte[] signature, byte[] additionalEntropy) throws KeyStoreException {
if (inputLength == 0) {
// No input provided -- simplify the rest of the code
input = EmptyArray.BYTE;
inputOffset = 0;
}
// Flush all buffered input and provided input into keystore/keymaster.
byte[] output = update(input, inputOffset, inputLength);
output = ArrayUtils.concat(output, flush());
OperationResult opResult = mKeyStoreStream.finish(signature, additionalEntropy);
if (opResult == null) {
throw new KeyStoreConnectException();
} else if (opResult.resultCode != KeyStore.NO_ERROR) {
throw KeyStore.getKeyStoreException(opResult.resultCode);
}
mProducedOutputSizeBytes += opResult.output.length;
return ArrayUtils.concat(output, opResult.output);
}
use of android.security.keymaster.OperationResult in project android_frameworks_base by DirtyUnicorns.
the class KeyStoreTest method testBadToken.
public void testBadToken() throws Exception {
IBinder token = new Binder();
OperationResult result = mKeyStore.update(token, null, new byte[] { 0x01 });
assertEquals("Update with invalid token should fail", KeymasterDefs.KM_ERROR_INVALID_OPERATION_HANDLE, result.resultCode);
}
Aggregations