am c6cc9d82: Merge "A way to obtain KeyStore operation handle from crypto primitives."

* commit 'c6cc9d820d007a6b11df2bb3274d40743e1f1d87':
  A way to obtain KeyStore operation handle from crypto primitives.
This commit is contained in:
Alex Klyubin
2015-04-01 17:57:00 +00:00
committed by Android Git Automerger
4 changed files with 103 additions and 3 deletions

View File

@@ -16,8 +16,12 @@
package android.security;
import java.lang.reflect.Method;
import java.security.Provider;
import javax.crypto.Cipher;
import javax.crypto.Mac;
/**
* A provider focused on providing JCA interfaces for the Android KeyStore.
*
@@ -71,4 +75,42 @@ public class AndroidKeyStoreProvider extends Provider {
put("Cipher." + transformation, implClass);
put("Cipher." + transformation + " SupportedKeyClasses", KeyStoreSecretKey.class.getName());
}
/**
* Gets the {@link KeyStore} operation handle corresponding to the provided JCA crypto
* primitive.
*
* <p>The following primitives are supported: {@link Cipher} and {@link Mac}.
*
* @return KeyStore operation handle or {@code null} if the provided primitive's KeyStore
* operation is not in progress.
*
* @throws IllegalArgumentException if the provided primitive is not supported or is not backed
* by AndroidKeyStore provider.
*/
public static Long getKeyStoreOperationHandle(Object cryptoPrimitive) {
if (cryptoPrimitive == null) {
throw new NullPointerException();
}
if ((!(cryptoPrimitive instanceof Mac)) && (!(cryptoPrimitive instanceof Cipher))) {
throw new IllegalArgumentException("Unsupported crypto primitive: " + cryptoPrimitive);
}
Object spi;
// TODO: Replace this Reflection based codewith direct invocations once the libcore changes
// are in.
try {
Method getSpiMethod = cryptoPrimitive.getClass().getDeclaredMethod("getSpi");
getSpiMethod.setAccessible(true);
spi = getSpiMethod.invoke(cryptoPrimitive);
} catch (ReflectiveOperationException e) {
throw new IllegalArgumentException(
"Unsupported crypto primitive: " + cryptoPrimitive, e);
}
if (!(spi instanceof KeyStoreCryptoOperation)) {
throw new IllegalArgumentException(
"Crypto primitive not backed by Android KeyStore: " + cryptoPrimitive
+ ", spi: " + spi);
}
return ((KeyStoreCryptoOperation) spi).getOperationHandle();
}
}

View File

@@ -45,7 +45,7 @@ import javax.crypto.spec.IvParameterSpec;
*
* @hide
*/
public abstract class KeyStoreCipherSpi extends CipherSpi {
public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCryptoOperation {
public abstract static class AES extends KeyStoreCipherSpi {
protected AES(@KeyStoreKeyConstraints.BlockModeEnum int blockMode,
@@ -129,6 +129,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi {
* error conditions in between.
*/
private IBinder mOperationToken;
private Long mOperationHandle;
private KeyStoreCryptoOperationChunkedStreamer mMainDataStreamer;
protected KeyStoreCipherSpi(
@@ -192,6 +193,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi {
mOperationToken = null;
mKeyStore.abort(operationToken);
}
mOperationHandle = null;
mMainDataStreamer = null;
mAdditionalEntropyForBegin = null;
}
@@ -230,6 +232,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi {
throw new CryptoOperationException("Keystore returned null operation token");
}
mOperationToken = opResult.token;
mOperationHandle = opResult.operationHandle;
loadAlgorithmSpecificParametersFromBeginResult(keymasterOutputArgs);
mFirstOperationInitiated = true;
mMainDataStreamer = new KeyStoreCryptoOperationChunkedStreamer(
@@ -348,6 +351,23 @@ public abstract class KeyStoreCipherSpi extends CipherSpi {
throw new UnsupportedOperationException();
}
@Override
public void finalize() throws Throwable {
try {
IBinder operationToken = mOperationToken;
if (operationToken != null) {
mKeyStore.abort(operationToken);
}
} finally {
super.finalize();
}
}
@Override
public Long getOperationHandle() {
return mOperationHandle;
}
// The methods below may need to be overridden by subclasses that use algorithm-specific
// parameters.

View File

@@ -0,0 +1,31 @@
/*
* Copyright (C) 2015 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.security;
/**
* Cryptographic operation backed by {@link KeyStore}.
*
* @hide
*/
public interface KeyStoreCryptoOperation {
/**
* Gets the KeyStore operation handle of this crypto operation.
*
* @return handle or {@code null} if the KeyStore operation is not in progress.
*/
Long getOperationHandle();
}

View File

@@ -33,7 +33,7 @@ import javax.crypto.MacSpi;
*
* @hide
*/
public abstract class KeyStoreHmacSpi extends MacSpi {
public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOperation {
public static class HmacSHA256 extends KeyStoreHmacSpi {
public HmacSHA256() {
@@ -50,6 +50,7 @@ public abstract class KeyStoreHmacSpi extends MacSpi {
// The fields below are reset by the engineReset operation.
private KeyStoreCryptoOperationChunkedStreamer mChunkedStreamer;
private IBinder mOperationToken;
private Long mOperationHandle;
protected KeyStoreHmacSpi(@KeyStoreKeyConstraints.DigestEnum int digest, int macSizeBytes) {
mDigest = digest;
@@ -87,6 +88,7 @@ public abstract class KeyStoreHmacSpi extends MacSpi {
mOperationToken = null;
mKeyStore.abort(operationToken);
}
mOperationHandle = null;
mChunkedStreamer = null;
KeymasterArguments keymasterArgs = new KeymasterArguments();
@@ -108,6 +110,7 @@ public abstract class KeyStoreHmacSpi extends MacSpi {
if (mOperationToken == null) {
throw new CryptoOperationException("Keystore returned null operation token");
}
mOperationHandle = opResult.operationHandle;
mChunkedStreamer = new KeyStoreCryptoOperationChunkedStreamer(
new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
mKeyStore, mOperationToken));
@@ -157,11 +160,15 @@ public abstract class KeyStoreHmacSpi extends MacSpi {
try {
IBinder operationToken = mOperationToken;
if (operationToken != null) {
mOperationToken = null;
mKeyStore.abort(operationToken);
}
} finally {
super.finalize();
}
}
@Override
public Long getOperationHandle() {
return mOperationHandle;
}
}