Loading keystore/java/android/security/keystore/AndroidKeyStoreKeyFactorySpi.java 0 → 100644 +91 −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.keystore; import android.security.Credentials; import android.security.KeyStore; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyFactorySpi; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; /** * {@link KeyFactorySpi} backed by Android KeyStore. * * @hide */ public class AndroidKeyStoreKeyFactorySpi extends KeyFactorySpi { private final KeyStore mKeyStore = KeyStore.getInstance(); @Override protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpecClass) throws InvalidKeySpecException { if (keySpecClass == null) { throw new InvalidKeySpecException("keySpecClass == null"); } if (!(key instanceof AndroidKeyStorePrivateKey)) { throw new InvalidKeySpecException("Only Android KeyStore private keys supported: " + ((key != null) ? key.getClass().getName() : "null")); } if (PKCS8EncodedKeySpec.class.isAssignableFrom(keySpecClass)) { throw new InvalidKeySpecException( "Key material export of Android KeyStore keys is not supported"); } if (!KeyInfo.class.equals(keySpecClass)) { throw new InvalidKeySpecException("Unsupported key spec: " + keySpecClass.getName()); } String keyAliasInKeystore = ((AndroidKeyStoreKey) key).getAlias(); String entryAlias; if (keyAliasInKeystore.startsWith(Credentials.USER_PRIVATE_KEY)) { entryAlias = keyAliasInKeystore.substring(Credentials.USER_PRIVATE_KEY.length()); } else { throw new InvalidKeySpecException("Invalid key alias: " + keyAliasInKeystore); } @SuppressWarnings("unchecked") T result = (T) AndroidKeyStoreSecretKeyFactorySpi.getKeyInfo( mKeyStore, entryAlias, keyAliasInKeystore); return result; } @Override protected PrivateKey engineGeneratePrivate(KeySpec spec) throws InvalidKeySpecException { throw new UnsupportedOperationException( "To generate a key pair in Android KeyStore, use KeyPairGenerator initialized with" + " " + KeyGenParameterSpec.class.getName()); } @Override protected PublicKey engineGeneratePublic(KeySpec spec) throws InvalidKeySpecException { throw new UnsupportedOperationException( "To generate a key pair in Android KeyStore, use KeyPairGenerator initialized with" + " " + KeyGenParameterSpec.class.getName()); } @Override protected Key engineTranslateKey(Key arg0) throws InvalidKeyException { throw new UnsupportedOperationException( "To import a key into Android KeyStore, use KeyStore.setEntry with " + KeyProtection.class.getName()); } } keystore/java/android/security/keystore/AndroidKeyStoreProvider.java +8 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,10 @@ public class AndroidKeyStoreProvider extends Provider { put("KeyPairGenerator.EC", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$EC"); put("KeyPairGenerator.RSA", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$RSA"); // java.security.KeyFactory putKeyFactoryImpl("EC"); putKeyFactoryImpl("RSA"); // javax.crypto.KeyGenerator put("KeyGenerator.AES", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$AES"); put("KeyGenerator.HmacSHA1", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA1"); Loading Loading @@ -101,6 +105,10 @@ public class AndroidKeyStoreProvider extends Provider { put("SecretKeyFactory." + algorithm, PACKAGE_NAME + ".AndroidKeyStoreSecretKeyFactorySpi"); } private void putKeyFactoryImpl(String algorithm) { put("KeyFactory." + algorithm, PACKAGE_NAME + ".AndroidKeyStoreKeyFactorySpi"); } /** * Gets the {@link KeyStore} operation handle corresponding to the provided JCA crypto * primitive. Loading keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java +34 −17 Original line number Diff line number Diff line Loading @@ -21,9 +21,8 @@ import android.security.KeyStore; import android.security.keymaster.KeyCharacteristics; import android.security.keymaster.KeymasterDefs; import libcore.util.EmptyArray; import java.security.InvalidKeyException; import java.security.ProviderException; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.util.ArrayList; Loading @@ -35,7 +34,7 @@ import javax.crypto.SecretKeyFactorySpi; import javax.crypto.spec.SecretKeySpec; /** * {@link SecretKeyFactorySpi} backed by Android KeyStore. * {@link SecretKeyFactorySpi} backed by Android Keystore. * * @hide */ Loading @@ -60,7 +59,7 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { if (!KeyInfo.class.equals(keySpecClass)) { throw new InvalidKeySpecException("Unsupported key spec: " + keySpecClass.getName()); } String keyAliasInKeystore = ((AndroidKeyStoreSecretKey) key).getAlias(); String keyAliasInKeystore = ((AndroidKeyStoreKey) key).getAlias(); String entryAlias; if (keyAliasInKeystore.startsWith(Credentials.USER_SECRET_KEY)) { entryAlias = keyAliasInKeystore.substring(Credentials.USER_SECRET_KEY.length()); Loading @@ -68,11 +67,15 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { throw new InvalidKeySpecException("Invalid key alias: " + keyAliasInKeystore); } return getKeyInfo(mKeyStore, entryAlias, keyAliasInKeystore); } static KeyInfo getKeyInfo(KeyStore keyStore, String entryAlias, String keyAliasInKeystore) { KeyCharacteristics keyCharacteristics = new KeyCharacteristics(); int errorCode = mKeyStore.getKeyCharacteristics(keyAliasInKeystore, null, null, keyCharacteristics); keyStore.getKeyCharacteristics(keyAliasInKeystore, null, null, keyCharacteristics); if (errorCode != KeyStore.NO_ERROR) { throw new InvalidKeySpecException("Failed to obtain information about key." throw new ProviderException("Failed to obtain information about key." + " Keystore error: " + errorCode); } Loading @@ -81,6 +84,7 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { int keySize; @KeyProperties.PurposeEnum int purposes; String[] encryptionPaddings; String[] signaturePaddings; @KeyProperties.DigestEnum String[] digests; @KeyProperties.BlockModeEnum String[] blockModes; int keymasterSwEnforcedUserAuthenticators; Loading @@ -95,29 +99,40 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { origin = KeyProperties.Origin.fromKeymaster( keyCharacteristics.swEnforced.getInt(KeymasterDefs.KM_TAG_ORIGIN, -1)); } else { throw new InvalidKeySpecException("Key origin not available"); throw new ProviderException("Key origin not available"); } Integer keySizeInteger = keyCharacteristics.getInteger(KeymasterDefs.KM_TAG_KEY_SIZE); if (keySizeInteger == null) { throw new InvalidKeySpecException("Key size not available"); throw new ProviderException("Key size not available"); } keySize = keySizeInteger; purposes = KeyProperties.Purpose.allFromKeymaster( keyCharacteristics.getInts(KeymasterDefs.KM_TAG_PURPOSE)); List<String> encryptionPaddingsList = new ArrayList<String>(); List<String> signaturePaddingsList = new ArrayList<String>(); // Keymaster stores both types of paddings in the same array -- we split it into two. for (int keymasterPadding : keyCharacteristics.getInts(KeymasterDefs.KM_TAG_PADDING)) { @KeyProperties.EncryptionPaddingEnum String jcaPadding; try { jcaPadding = KeyProperties.EncryptionPadding.fromKeymaster(keymasterPadding); @KeyProperties.EncryptionPaddingEnum String jcaPadding = KeyProperties.EncryptionPadding.fromKeymaster(keymasterPadding); encryptionPaddingsList.add(jcaPadding); } catch (IllegalArgumentException e) { throw new InvalidKeySpecException( try { @KeyProperties.SignaturePaddingEnum String padding = KeyProperties.SignaturePadding.fromKeymaster(keymasterPadding); signaturePaddingsList.add(padding); } catch (IllegalArgumentException e2) { throw new ProviderException( "Unsupported encryption padding: " + keymasterPadding); } encryptionPaddingsList.add(jcaPadding); } } encryptionPaddings = encryptionPaddingsList.toArray(new String[encryptionPaddingsList.size()]); signaturePaddings = signaturePaddingsList.toArray(new String[signaturePaddingsList.size()]); digests = KeyProperties.Digest.allFromKeymaster( keyCharacteristics.getInts(KeymasterDefs.KM_TAG_DIGEST)); Loading @@ -128,7 +143,7 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { keymasterHwEnforcedUserAuthenticators = keyCharacteristics.hwEnforced.getInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0); } catch (IllegalArgumentException e) { throw new InvalidKeySpecException("Unsupported key characteristic", e); throw new ProviderException("Unsupported key characteristic", e); } Date keyValidityStart = keyCharacteristics.getDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME); Loading Loading @@ -164,7 +179,7 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { keyValidityForConsumptionEnd, purposes, encryptionPaddings, EmptyArray.STRING, // no signature paddings -- this is symmetric crypto signaturePaddings, digests, blockModes, userAuthenticationRequired, Loading @@ -175,12 +190,14 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { @Override protected SecretKey engineGenerateSecret(KeySpec keySpec) throws InvalidKeySpecException { throw new UnsupportedOperationException( "Key import into Android KeyStore is not supported"); "To generate secret key in Android KeyStore, use KeyGenerator initialized with " + KeyGenParameterSpec.class.getName()); } @Override protected SecretKey engineTranslateKey(SecretKey key) throws InvalidKeyException { throw new UnsupportedOperationException( "Key import into Android KeyStore is not supported"); "To import a secret key into Android KeyStore, use KeyStore.setEntry with " + KeyProtection.class.getName()); } } Loading
keystore/java/android/security/keystore/AndroidKeyStoreKeyFactorySpi.java 0 → 100644 +91 −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.keystore; import android.security.Credentials; import android.security.KeyStore; import java.security.InvalidKeyException; import java.security.Key; import java.security.KeyFactorySpi; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.security.spec.PKCS8EncodedKeySpec; /** * {@link KeyFactorySpi} backed by Android KeyStore. * * @hide */ public class AndroidKeyStoreKeyFactorySpi extends KeyFactorySpi { private final KeyStore mKeyStore = KeyStore.getInstance(); @Override protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpecClass) throws InvalidKeySpecException { if (keySpecClass == null) { throw new InvalidKeySpecException("keySpecClass == null"); } if (!(key instanceof AndroidKeyStorePrivateKey)) { throw new InvalidKeySpecException("Only Android KeyStore private keys supported: " + ((key != null) ? key.getClass().getName() : "null")); } if (PKCS8EncodedKeySpec.class.isAssignableFrom(keySpecClass)) { throw new InvalidKeySpecException( "Key material export of Android KeyStore keys is not supported"); } if (!KeyInfo.class.equals(keySpecClass)) { throw new InvalidKeySpecException("Unsupported key spec: " + keySpecClass.getName()); } String keyAliasInKeystore = ((AndroidKeyStoreKey) key).getAlias(); String entryAlias; if (keyAliasInKeystore.startsWith(Credentials.USER_PRIVATE_KEY)) { entryAlias = keyAliasInKeystore.substring(Credentials.USER_PRIVATE_KEY.length()); } else { throw new InvalidKeySpecException("Invalid key alias: " + keyAliasInKeystore); } @SuppressWarnings("unchecked") T result = (T) AndroidKeyStoreSecretKeyFactorySpi.getKeyInfo( mKeyStore, entryAlias, keyAliasInKeystore); return result; } @Override protected PrivateKey engineGeneratePrivate(KeySpec spec) throws InvalidKeySpecException { throw new UnsupportedOperationException( "To generate a key pair in Android KeyStore, use KeyPairGenerator initialized with" + " " + KeyGenParameterSpec.class.getName()); } @Override protected PublicKey engineGeneratePublic(KeySpec spec) throws InvalidKeySpecException { throw new UnsupportedOperationException( "To generate a key pair in Android KeyStore, use KeyPairGenerator initialized with" + " " + KeyGenParameterSpec.class.getName()); } @Override protected Key engineTranslateKey(Key arg0) throws InvalidKeyException { throw new UnsupportedOperationException( "To import a key into Android KeyStore, use KeyStore.setEntry with " + KeyProtection.class.getName()); } }
keystore/java/android/security/keystore/AndroidKeyStoreProvider.java +8 −0 Original line number Diff line number Diff line Loading @@ -53,6 +53,10 @@ public class AndroidKeyStoreProvider extends Provider { put("KeyPairGenerator.EC", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$EC"); put("KeyPairGenerator.RSA", PACKAGE_NAME + ".AndroidKeyStoreKeyPairGeneratorSpi$RSA"); // java.security.KeyFactory putKeyFactoryImpl("EC"); putKeyFactoryImpl("RSA"); // javax.crypto.KeyGenerator put("KeyGenerator.AES", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$AES"); put("KeyGenerator.HmacSHA1", PACKAGE_NAME + ".AndroidKeyStoreKeyGeneratorSpi$HmacSHA1"); Loading Loading @@ -101,6 +105,10 @@ public class AndroidKeyStoreProvider extends Provider { put("SecretKeyFactory." + algorithm, PACKAGE_NAME + ".AndroidKeyStoreSecretKeyFactorySpi"); } private void putKeyFactoryImpl(String algorithm) { put("KeyFactory." + algorithm, PACKAGE_NAME + ".AndroidKeyStoreKeyFactorySpi"); } /** * Gets the {@link KeyStore} operation handle corresponding to the provided JCA crypto * primitive. Loading
keystore/java/android/security/keystore/AndroidKeyStoreSecretKeyFactorySpi.java +34 −17 Original line number Diff line number Diff line Loading @@ -21,9 +21,8 @@ import android.security.KeyStore; import android.security.keymaster.KeyCharacteristics; import android.security.keymaster.KeymasterDefs; import libcore.util.EmptyArray; import java.security.InvalidKeyException; import java.security.ProviderException; import java.security.spec.InvalidKeySpecException; import java.security.spec.KeySpec; import java.util.ArrayList; Loading @@ -35,7 +34,7 @@ import javax.crypto.SecretKeyFactorySpi; import javax.crypto.spec.SecretKeySpec; /** * {@link SecretKeyFactorySpi} backed by Android KeyStore. * {@link SecretKeyFactorySpi} backed by Android Keystore. * * @hide */ Loading @@ -60,7 +59,7 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { if (!KeyInfo.class.equals(keySpecClass)) { throw new InvalidKeySpecException("Unsupported key spec: " + keySpecClass.getName()); } String keyAliasInKeystore = ((AndroidKeyStoreSecretKey) key).getAlias(); String keyAliasInKeystore = ((AndroidKeyStoreKey) key).getAlias(); String entryAlias; if (keyAliasInKeystore.startsWith(Credentials.USER_SECRET_KEY)) { entryAlias = keyAliasInKeystore.substring(Credentials.USER_SECRET_KEY.length()); Loading @@ -68,11 +67,15 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { throw new InvalidKeySpecException("Invalid key alias: " + keyAliasInKeystore); } return getKeyInfo(mKeyStore, entryAlias, keyAliasInKeystore); } static KeyInfo getKeyInfo(KeyStore keyStore, String entryAlias, String keyAliasInKeystore) { KeyCharacteristics keyCharacteristics = new KeyCharacteristics(); int errorCode = mKeyStore.getKeyCharacteristics(keyAliasInKeystore, null, null, keyCharacteristics); keyStore.getKeyCharacteristics(keyAliasInKeystore, null, null, keyCharacteristics); if (errorCode != KeyStore.NO_ERROR) { throw new InvalidKeySpecException("Failed to obtain information about key." throw new ProviderException("Failed to obtain information about key." + " Keystore error: " + errorCode); } Loading @@ -81,6 +84,7 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { int keySize; @KeyProperties.PurposeEnum int purposes; String[] encryptionPaddings; String[] signaturePaddings; @KeyProperties.DigestEnum String[] digests; @KeyProperties.BlockModeEnum String[] blockModes; int keymasterSwEnforcedUserAuthenticators; Loading @@ -95,29 +99,40 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { origin = KeyProperties.Origin.fromKeymaster( keyCharacteristics.swEnforced.getInt(KeymasterDefs.KM_TAG_ORIGIN, -1)); } else { throw new InvalidKeySpecException("Key origin not available"); throw new ProviderException("Key origin not available"); } Integer keySizeInteger = keyCharacteristics.getInteger(KeymasterDefs.KM_TAG_KEY_SIZE); if (keySizeInteger == null) { throw new InvalidKeySpecException("Key size not available"); throw new ProviderException("Key size not available"); } keySize = keySizeInteger; purposes = KeyProperties.Purpose.allFromKeymaster( keyCharacteristics.getInts(KeymasterDefs.KM_TAG_PURPOSE)); List<String> encryptionPaddingsList = new ArrayList<String>(); List<String> signaturePaddingsList = new ArrayList<String>(); // Keymaster stores both types of paddings in the same array -- we split it into two. for (int keymasterPadding : keyCharacteristics.getInts(KeymasterDefs.KM_TAG_PADDING)) { @KeyProperties.EncryptionPaddingEnum String jcaPadding; try { jcaPadding = KeyProperties.EncryptionPadding.fromKeymaster(keymasterPadding); @KeyProperties.EncryptionPaddingEnum String jcaPadding = KeyProperties.EncryptionPadding.fromKeymaster(keymasterPadding); encryptionPaddingsList.add(jcaPadding); } catch (IllegalArgumentException e) { throw new InvalidKeySpecException( try { @KeyProperties.SignaturePaddingEnum String padding = KeyProperties.SignaturePadding.fromKeymaster(keymasterPadding); signaturePaddingsList.add(padding); } catch (IllegalArgumentException e2) { throw new ProviderException( "Unsupported encryption padding: " + keymasterPadding); } encryptionPaddingsList.add(jcaPadding); } } encryptionPaddings = encryptionPaddingsList.toArray(new String[encryptionPaddingsList.size()]); signaturePaddings = signaturePaddingsList.toArray(new String[signaturePaddingsList.size()]); digests = KeyProperties.Digest.allFromKeymaster( keyCharacteristics.getInts(KeymasterDefs.KM_TAG_DIGEST)); Loading @@ -128,7 +143,7 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { keymasterHwEnforcedUserAuthenticators = keyCharacteristics.hwEnforced.getInt(KeymasterDefs.KM_TAG_USER_AUTH_TYPE, 0); } catch (IllegalArgumentException e) { throw new InvalidKeySpecException("Unsupported key characteristic", e); throw new ProviderException("Unsupported key characteristic", e); } Date keyValidityStart = keyCharacteristics.getDate(KeymasterDefs.KM_TAG_ACTIVE_DATETIME); Loading Loading @@ -164,7 +179,7 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { keyValidityForConsumptionEnd, purposes, encryptionPaddings, EmptyArray.STRING, // no signature paddings -- this is symmetric crypto signaturePaddings, digests, blockModes, userAuthenticationRequired, Loading @@ -175,12 +190,14 @@ public class AndroidKeyStoreSecretKeyFactorySpi extends SecretKeyFactorySpi { @Override protected SecretKey engineGenerateSecret(KeySpec keySpec) throws InvalidKeySpecException { throw new UnsupportedOperationException( "Key import into Android KeyStore is not supported"); "To generate secret key in Android KeyStore, use KeyGenerator initialized with " + KeyGenParameterSpec.class.getName()); } @Override protected SecretKey engineTranslateKey(SecretKey key) throws InvalidKeyException { throw new UnsupportedOperationException( "Key import into Android KeyStore is not supported"); "To import a secret key into Android KeyStore, use KeyStore.setEntry with " + KeyProtection.class.getName()); } }