diff options
Diffstat (limited to 'keystore')
3 files changed, 60 insertions, 12 deletions
diff --git a/keystore/java/android/security/IKeyChainService.aidl b/keystore/java/android/security/IKeyChainService.aidl index f708298a2cbd..d00f5f669594 100644 --- a/keystore/java/android/security/IKeyChainService.aidl +++ b/keystore/java/android/security/IKeyChainService.aidl @@ -37,8 +37,6 @@ interface IKeyChainService { void setUserSelectable(String alias, boolean isUserSelectable); int generateKeyPair(in String algorithm, in ParcelableKeyGenParameterSpec spec); - int attestKey(in String alias, in byte[] challenge, in int[] idAttestationFlags, - out KeymasterCertificateChain chain); boolean setKeyPairCertificate(String alias, in byte[] userCert, in byte[] certChain); // APIs used by CertInstaller and DevicePolicyManager diff --git a/keystore/java/android/security/KeyChain.java b/keystore/java/android/security/KeyChain.java index 63690d3c1567..d59ca98433a9 100644 --- a/keystore/java/android/security/KeyChain.java +++ b/keystore/java/android/security/KeyChain.java @@ -40,6 +40,8 @@ import android.os.UserManager; import android.security.keystore.AndroidKeyStoreProvider; import android.security.keystore.KeyPermanentlyInvalidatedException; import android.security.keystore.KeyProperties; +import android.system.keystore2.Domain; +import android.system.keystore2.KeyDescriptor; import com.android.org.conscrypt.TrustedCertificateStore; @@ -622,6 +624,33 @@ public final class KeyChain { return null; } + /** + * This prefix is used to disambiguate grant aliase strings from normal key alias strings. + * Technically, a key alias string can use the same prefix. However, a collision does not + * lead to privilege escalation, because grants are access controlled in the Keystore daemon. + * @hide + */ + public static final String GRANT_ALIAS_PREFIX = "ks2_keychain_grant_id:"; + + private static KeyDescriptor getGrantDescriptor(String keyid) { + KeyDescriptor result = new KeyDescriptor(); + result.domain = Domain.GRANT; + result.blob = null; + result.alias = null; + try { + result.nspace = Long.parseUnsignedLong( + keyid.substring(GRANT_ALIAS_PREFIX.length()), 16 /* radix */); + } catch (NumberFormatException e) { + return null; + } + return result; + } + + /** @hide */ + public static String getGrantString(KeyDescriptor key) { + return String.format(GRANT_ALIAS_PREFIX + "%016X", key.nspace); + } + /** @hide */ @Nullable @WorkerThread public static KeyPair getKeyPair(@NonNull Context context, @NonNull String alias) @@ -645,11 +674,23 @@ public final class KeyChain { if (keyId == null) { return null; + } + + if (AndroidKeyStoreProvider.isKeystore2Enabled()) { + try { + return android.security.keystore2.AndroidKeyStoreProvider + .loadAndroidKeyStoreKeyPairFromKeystore( + KeyStore2.getInstance(), + getGrantDescriptor(keyId)); + } catch (UnrecoverableKeyException | KeyPermanentlyInvalidatedException e) { + throw new KeyChainException(e); + } } else { try { return AndroidKeyStoreProvider.loadAndroidKeyStoreKeyPairFromKeystore( KeyStore.getInstance(), keyId, KeyStore.UID_SELF); - } catch (RuntimeException | UnrecoverableKeyException | KeyPermanentlyInvalidatedException e) { + } catch (RuntimeException | UnrecoverableKeyException + | KeyPermanentlyInvalidatedException e) { throw new KeyChainException(e); } } @@ -767,11 +808,8 @@ public final class KeyChain { @Deprecated public static boolean isBoundKeyAlgorithm( @NonNull @KeyProperties.KeyAlgorithmEnum String algorithm) { - if (!isKeyAlgorithmSupported(algorithm)) { - return false; - } - - return KeyStore.getInstance().isHardwareBacked(algorithm); + // All supported algorithms are hardware backed. Individual keys may not be. + return true; } /** @hide */ diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java index e1011155248e..35059ac929c3 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreProvider.java @@ -273,10 +273,10 @@ public class AndroidKeyStoreProvider extends Provider { /** @hide **/ @NonNull public static KeyPair loadAndroidKeyStoreKeyPairFromKeystore( - @NonNull KeyStore2 keyStore, @NonNull String privateKeyAlias, int namespace) + @NonNull KeyStore2 keyStore, @NonNull KeyDescriptor descriptor) throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException { AndroidKeyStoreKey key = - loadAndroidKeyStoreKeyFromKeystore(keyStore, privateKeyAlias, namespace); + loadAndroidKeyStoreKeyFromKeystore(keyStore, descriptor); if (key instanceof AndroidKeyStorePublicKey) { AndroidKeyStorePublicKey publicKey = (AndroidKeyStorePublicKey) key; return new KeyPair(publicKey, publicKey.getPrivateKey()); @@ -336,7 +336,7 @@ public class AndroidKeyStoreProvider extends Provider { @NonNull public static AndroidKeyStoreKey loadAndroidKeyStoreKeyFromKeystore( @NonNull KeyStore2 keyStore, @NonNull String alias, int namespace) - throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException { + throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException { KeyDescriptor descriptor = new KeyDescriptor(); if (namespace == KeyProperties.NAMESPACE_APPLICATION) { @@ -348,6 +348,18 @@ public class AndroidKeyStoreProvider extends Provider { } descriptor.alias = alias; descriptor.blob = null; + + final AndroidKeyStoreKey key = loadAndroidKeyStoreKeyFromKeystore(keyStore, descriptor); + if (key instanceof AndroidKeyStorePublicKey) { + return ((AndroidKeyStorePublicKey) key).getPrivateKey(); + } else { + return key; + } + } + + private static AndroidKeyStoreKey loadAndroidKeyStoreKeyFromKeystore( + @NonNull KeyStore2 keyStore, @NonNull KeyDescriptor descriptor) + throws UnrecoverableKeyException, KeyPermanentlyInvalidatedException { KeyEntryResponse response = null; try { response = keyStore.getKeyEntry(descriptor); @@ -397,7 +409,7 @@ public class AndroidKeyStoreProvider extends Provider { keymasterAlgorithm == KeymasterDefs.KM_ALGORITHM_EC) { return makeAndroidKeyStorePublicKeyFromKeyEntryResponse(descriptor, response.metadata, new KeyStoreSecurityLevel(response.iSecurityLevel), - keymasterAlgorithm).getPrivateKey(); + keymasterAlgorithm); } else { throw new UnrecoverableKeyException("Key algorithm unknown"); } |