diff options
author | Alex Klyubin <klyubin@google.com> | 2015-04-01 18:57:31 +0000 |
---|---|---|
committer | Android Git Automerger <android-git-automerger@android.com> | 2015-04-01 18:57:31 +0000 |
commit | ef17b73c6abb9f50d79b00beafa9b1babcbcc1f0 (patch) | |
tree | 0b870f7f98507fc9e8210b2b4ef3eb9d6a9fa6df | |
parent | 16a6279e5f1dde063707adc852f8de1e14206905 (diff) | |
parent | 93e029e0066737f9f09f6dfef95dc664dc236b15 (diff) | |
download | frameworks_base-ef17b73c6abb9f50d79b00beafa9b1babcbcc1f0.zip frameworks_base-ef17b73c6abb9f50d79b00beafa9b1babcbcc1f0.tar.gz frameworks_base-ef17b73c6abb9f50d79b00beafa9b1babcbcc1f0.tar.bz2 |
am 93e029e0: am f00cdf68: am c6cc9d82: Merge "A way to obtain KeyStore operation handle from crypto primitives."
* commit '93e029e0066737f9f09f6dfef95dc664dc236b15':
A way to obtain KeyStore operation handle from crypto primitives.
4 files changed, 103 insertions, 3 deletions
diff --git a/keystore/java/android/security/AndroidKeyStoreProvider.java b/keystore/java/android/security/AndroidKeyStoreProvider.java index 39f9d9c..a7c2ddb 100644 --- a/keystore/java/android/security/AndroidKeyStoreProvider.java +++ b/keystore/java/android/security/AndroidKeyStoreProvider.java @@ -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(); + } } diff --git a/keystore/java/android/security/KeyStoreCipherSpi.java b/keystore/java/android/security/KeyStoreCipherSpi.java index 87f0d8e..bdaa812 100644 --- a/keystore/java/android/security/KeyStoreCipherSpi.java +++ b/keystore/java/android/security/KeyStoreCipherSpi.java @@ -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. diff --git a/keystore/java/android/security/KeyStoreCryptoOperation.java b/keystore/java/android/security/KeyStoreCryptoOperation.java new file mode 100644 index 0000000..19abd05 --- /dev/null +++ b/keystore/java/android/security/KeyStoreCryptoOperation.java @@ -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(); +} diff --git a/keystore/java/android/security/KeyStoreHmacSpi.java b/keystore/java/android/security/KeyStoreHmacSpi.java index 939b41c..841b90d 100644 --- a/keystore/java/android/security/KeyStoreHmacSpi.java +++ b/keystore/java/android/security/KeyStoreHmacSpi.java @@ -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; + } } |