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; 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();
}
} }

View File

@@ -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.

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 * @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;
}
} }