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:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
31
keystore/java/android/security/KeyStoreCryptoOperation.java
Normal file
31
keystore/java/android/security/KeyStoreCryptoOperation.java
Normal 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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user