Loading keystore/java/android/security/AndroidKeyStoreProvider.java +42 −0 Original line number Diff line number Diff line Loading @@ -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. * Loading Loading @@ -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(); } } keystore/java/android/security/KeyStoreCipherSpi.java +21 −1 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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( Loading Loading @@ -192,6 +193,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi { mOperationToken = null; mKeyStore.abort(operationToken); } mOperationHandle = null; mMainDataStreamer = null; mAdditionalEntropyForBegin = null; } Loading Loading @@ -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( Loading Loading @@ -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. Loading keystore/java/android/security/KeyStoreCryptoOperation.java 0 → 100644 +31 −0 Original line number Diff line number Diff line /* * 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(); } keystore/java/android/security/KeyStoreHmacSpi.java +9 −2 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -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; Loading Loading @@ -87,6 +88,7 @@ public abstract class KeyStoreHmacSpi extends MacSpi { mOperationToken = null; mKeyStore.abort(operationToken); } mOperationHandle = null; mChunkedStreamer = null; KeymasterArguments keymasterArgs = new KeymasterArguments(); Loading @@ -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)); Loading Loading @@ -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; } } Loading
keystore/java/android/security/AndroidKeyStoreProvider.java +42 −0 Original line number Diff line number Diff line Loading @@ -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. * Loading Loading @@ -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(); } }
keystore/java/android/security/KeyStoreCipherSpi.java +21 −1 Original line number Diff line number Diff line Loading @@ -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, Loading Loading @@ -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( Loading Loading @@ -192,6 +193,7 @@ public abstract class KeyStoreCipherSpi extends CipherSpi { mOperationToken = null; mKeyStore.abort(operationToken); } mOperationHandle = null; mMainDataStreamer = null; mAdditionalEntropyForBegin = null; } Loading Loading @@ -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( Loading Loading @@ -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. Loading
keystore/java/android/security/KeyStoreCryptoOperation.java 0 → 100644 +31 −0 Original line number Diff line number Diff line /* * 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(); }
keystore/java/android/security/KeyStoreHmacSpi.java +9 −2 Original line number Diff line number Diff line Loading @@ -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() { Loading @@ -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; Loading Loading @@ -87,6 +88,7 @@ public abstract class KeyStoreHmacSpi extends MacSpi { mOperationToken = null; mKeyStore.abort(operationToken); } mOperationHandle = null; mChunkedStreamer = null; KeymasterArguments keymasterArgs = new KeymasterArguments(); Loading @@ -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)); Loading Loading @@ -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; } }