Merge "A way to obtain KeyStore operation handle from crypto primitives."
This commit is contained in:
@@ -16,8 +16,12 @@
|
|||||||
|
|
||||||
package android.security;
|
package android.security;
|
||||||
|
|
||||||
|
import java.lang.reflect.Method;
|
||||||
import java.security.Provider;
|
import java.security.Provider;
|
||||||
|
|
||||||
|
import javax.crypto.Cipher;
|
||||||
|
import javax.crypto.Mac;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A provider focused on providing JCA interfaces for the Android KeyStore.
|
* 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, implClass);
|
||||||
put("Cipher." + transformation + " SupportedKeyClasses", KeyStoreSecretKey.class.getName());
|
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
|
* @hide
|
||||||
*/
|
*/
|
||||||
public abstract class KeyStoreCipherSpi extends CipherSpi {
|
public abstract class KeyStoreCipherSpi extends CipherSpi implements KeyStoreCryptoOperation {
|
||||||
|
|
||||||
public abstract static class AES extends KeyStoreCipherSpi {
|
public abstract static class AES extends KeyStoreCipherSpi {
|
||||||
protected AES(@KeyStoreKeyConstraints.BlockModeEnum int blockMode,
|
protected AES(@KeyStoreKeyConstraints.BlockModeEnum int blockMode,
|
||||||
@@ -129,6 +129,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi {
|
|||||||
* error conditions in between.
|
* error conditions in between.
|
||||||
*/
|
*/
|
||||||
private IBinder mOperationToken;
|
private IBinder mOperationToken;
|
||||||
|
private Long mOperationHandle;
|
||||||
private KeyStoreCryptoOperationChunkedStreamer mMainDataStreamer;
|
private KeyStoreCryptoOperationChunkedStreamer mMainDataStreamer;
|
||||||
|
|
||||||
protected KeyStoreCipherSpi(
|
protected KeyStoreCipherSpi(
|
||||||
@@ -192,6 +193,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi {
|
|||||||
mOperationToken = null;
|
mOperationToken = null;
|
||||||
mKeyStore.abort(operationToken);
|
mKeyStore.abort(operationToken);
|
||||||
}
|
}
|
||||||
|
mOperationHandle = null;
|
||||||
mMainDataStreamer = null;
|
mMainDataStreamer = null;
|
||||||
mAdditionalEntropyForBegin = null;
|
mAdditionalEntropyForBegin = null;
|
||||||
}
|
}
|
||||||
@@ -230,6 +232,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi {
|
|||||||
throw new CryptoOperationException("Keystore returned null operation token");
|
throw new CryptoOperationException("Keystore returned null operation token");
|
||||||
}
|
}
|
||||||
mOperationToken = opResult.token;
|
mOperationToken = opResult.token;
|
||||||
|
mOperationHandle = opResult.operationHandle;
|
||||||
loadAlgorithmSpecificParametersFromBeginResult(keymasterOutputArgs);
|
loadAlgorithmSpecificParametersFromBeginResult(keymasterOutputArgs);
|
||||||
mFirstOperationInitiated = true;
|
mFirstOperationInitiated = true;
|
||||||
mMainDataStreamer = new KeyStoreCryptoOperationChunkedStreamer(
|
mMainDataStreamer = new KeyStoreCryptoOperationChunkedStreamer(
|
||||||
@@ -348,6 +351,23 @@ public abstract class KeyStoreCipherSpi extends CipherSpi {
|
|||||||
throw new UnsupportedOperationException();
|
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
|
// The methods below may need to be overridden by subclasses that use algorithm-specific
|
||||||
// parameters.
|
// 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
|
* @hide
|
||||||
*/
|
*/
|
||||||
public abstract class KeyStoreHmacSpi extends MacSpi {
|
public abstract class KeyStoreHmacSpi extends MacSpi implements KeyStoreCryptoOperation {
|
||||||
|
|
||||||
public static class HmacSHA256 extends KeyStoreHmacSpi {
|
public static class HmacSHA256 extends KeyStoreHmacSpi {
|
||||||
public HmacSHA256() {
|
public HmacSHA256() {
|
||||||
@@ -50,6 +50,7 @@ public abstract class KeyStoreHmacSpi extends MacSpi {
|
|||||||
// The fields below are reset by the engineReset operation.
|
// The fields below are reset by the engineReset operation.
|
||||||
private KeyStoreCryptoOperationChunkedStreamer mChunkedStreamer;
|
private KeyStoreCryptoOperationChunkedStreamer mChunkedStreamer;
|
||||||
private IBinder mOperationToken;
|
private IBinder mOperationToken;
|
||||||
|
private Long mOperationHandle;
|
||||||
|
|
||||||
protected KeyStoreHmacSpi(@KeyStoreKeyConstraints.DigestEnum int digest, int macSizeBytes) {
|
protected KeyStoreHmacSpi(@KeyStoreKeyConstraints.DigestEnum int digest, int macSizeBytes) {
|
||||||
mDigest = digest;
|
mDigest = digest;
|
||||||
@@ -87,6 +88,7 @@ public abstract class KeyStoreHmacSpi extends MacSpi {
|
|||||||
mOperationToken = null;
|
mOperationToken = null;
|
||||||
mKeyStore.abort(operationToken);
|
mKeyStore.abort(operationToken);
|
||||||
}
|
}
|
||||||
|
mOperationHandle = null;
|
||||||
mChunkedStreamer = null;
|
mChunkedStreamer = null;
|
||||||
|
|
||||||
KeymasterArguments keymasterArgs = new KeymasterArguments();
|
KeymasterArguments keymasterArgs = new KeymasterArguments();
|
||||||
@@ -108,6 +110,7 @@ public abstract class KeyStoreHmacSpi extends MacSpi {
|
|||||||
if (mOperationToken == null) {
|
if (mOperationToken == null) {
|
||||||
throw new CryptoOperationException("Keystore returned null operation token");
|
throw new CryptoOperationException("Keystore returned null operation token");
|
||||||
}
|
}
|
||||||
|
mOperationHandle = opResult.operationHandle;
|
||||||
mChunkedStreamer = new KeyStoreCryptoOperationChunkedStreamer(
|
mChunkedStreamer = new KeyStoreCryptoOperationChunkedStreamer(
|
||||||
new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
|
new KeyStoreCryptoOperationChunkedStreamer.MainDataStream(
|
||||||
mKeyStore, mOperationToken));
|
mKeyStore, mOperationToken));
|
||||||
@@ -157,11 +160,15 @@ public abstract class KeyStoreHmacSpi extends MacSpi {
|
|||||||
try {
|
try {
|
||||||
IBinder operationToken = mOperationToken;
|
IBinder operationToken = mOperationToken;
|
||||||
if (operationToken != null) {
|
if (operationToken != null) {
|
||||||
mOperationToken = null;
|
|
||||||
mKeyStore.abort(operationToken);
|
mKeyStore.abort(operationToken);
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
super.finalize();
|
super.finalize();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Long getOperationHandle() {
|
||||||
|
return mOperationHandle;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user