diff options
author | Eran Messeri <eranm@google.com> | 2022-11-25 15:42:46 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2022-11-25 15:42:46 +0000 |
commit | a9e03a249893b46a600ee72f6dcd87e954cf19aa (patch) | |
tree | b12b70d3e3e9345e49378d41290b083fbadb9222 | |
parent | 3e58b78907146a22f3340e3a072d51edd9068191 (diff) | |
parent | 9db6ee342b7c2748477e7b8c46add353087b8204 (diff) | |
download | base-a9e03a249893b46a600ee72f6dcd87e954cf19aa.tar.gz |
Merge "KeyStore: X25519 key import" am: 9db6ee342b
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2183495
Change-Id: I7aa4360491ef7b0ad71ac45ebf15003c39e39dfe
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
6 files changed, 125 insertions, 47 deletions
diff --git a/keystore/java/android/security/keystore/KeyProperties.java b/keystore/java/android/security/keystore/KeyProperties.java index 62455988db34..8c42547caea6 100644 --- a/keystore/java/android/security/keystore/KeyProperties.java +++ b/keystore/java/android/security/keystore/KeyProperties.java @@ -196,6 +196,7 @@ public abstract class KeyProperties { @StringDef(prefix = { "KEY_" }, value = { KEY_ALGORITHM_RSA, KEY_ALGORITHM_EC, + KEY_ALGORITHM_XDH, KEY_ALGORITHM_AES, KEY_ALGORITHM_HMAC_SHA1, KEY_ALGORITHM_HMAC_SHA224, @@ -211,6 +212,11 @@ public abstract class KeyProperties { /** Elliptic Curve (EC) Cryptography key. */ public static final String KEY_ALGORITHM_EC = "EC"; + /** Curve 25519 based Agreement key. + * @hide + */ + public static final String KEY_ALGORITHM_XDH = "XDH"; + /** Advanced Encryption Standard (AES) key. */ public static final String KEY_ALGORITHM_AES = "AES"; @@ -246,7 +252,8 @@ public abstract class KeyProperties { public static int toKeymasterAsymmetricKeyAlgorithm( @NonNull @KeyAlgorithmEnum String algorithm) { - if (KEY_ALGORITHM_EC.equalsIgnoreCase(algorithm)) { + if (KEY_ALGORITHM_EC.equalsIgnoreCase(algorithm) + || KEY_ALGORITHM_XDH.equalsIgnoreCase(algorithm)) { return KeymasterDefs.KM_ALGORITHM_EC; } else if (KEY_ALGORITHM_RSA.equalsIgnoreCase(algorithm)) { return KeymasterDefs.KM_ALGORITHM_RSA; diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreECPublicKey.java b/keystore/java/android/security/keystore2/AndroidKeyStoreECPublicKey.java index 4e73bd9d3c82..4505eaf0c862 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreECPublicKey.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreECPublicKey.java @@ -24,13 +24,9 @@ import android.system.keystore2.Authorization; import android.system.keystore2.KeyDescriptor; import android.system.keystore2.KeyMetadata; -import java.security.AlgorithmParameters; -import java.security.NoSuchAlgorithmException; import java.security.interfaces.ECPublicKey; -import java.security.spec.ECGenParameterSpec; import java.security.spec.ECParameterSpec; import java.security.spec.ECPoint; -import java.security.spec.InvalidParameterSpecException; /** * {@link ECPublicKey} backed by keystore. @@ -62,34 +58,13 @@ public class AndroidKeyStoreECPublicKey extends AndroidKeyStorePublicKey impleme } } - private static String getEcCurveFromKeymaster(int ecCurve) { - switch (ecCurve) { - case android.hardware.security.keymint.EcCurve.P_224: - return "secp224r1"; - case android.hardware.security.keymint.EcCurve.P_256: - return "secp256r1"; - case android.hardware.security.keymint.EcCurve.P_384: - return "secp384r1"; - case android.hardware.security.keymint.EcCurve.P_521: - return "secp521r1"; - } - return ""; - } - - private ECParameterSpec getCurveSpec(String name) - throws NoSuchAlgorithmException, InvalidParameterSpecException { - AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC"); - parameters.init(new ECGenParameterSpec(name)); - return parameters.getParameterSpec(ECParameterSpec.class); - } - @Override public AndroidKeyStorePrivateKey getPrivateKey() { ECParameterSpec params = mParams; for (Authorization a : getAuthorizations()) { try { if (a.keyParameter.tag == KeymasterDefs.KM_TAG_EC_CURVE) { - params = getCurveSpec(getEcCurveFromKeymaster( + params = KeymasterUtils.getCurveSpec(KeymasterUtils.getEcCurveFromKeymaster( a.keyParameter.value.getEcCurve())); break; } diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyAgreementSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyAgreementSpi.java index 4caa47f2078b..7292cd3c5fb1 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreKeyAgreementSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreKeyAgreementSpi.java @@ -32,7 +32,6 @@ import java.security.ProviderException; import java.security.PublicKey; import java.security.SecureRandom; import java.security.interfaces.ECKey; -import java.security.interfaces.XECKey; import java.security.spec.AlgorithmParameterSpec; import java.util.ArrayList; import java.util.List; @@ -134,10 +133,15 @@ public class AndroidKeyStoreKeyAgreementSpi extends KeyAgreementSpi throw new InvalidKeyException("key == null"); } else if (!(key instanceof PublicKey)) { throw new InvalidKeyException("Only public keys supported. Key: " + key); - } else if (!(mKey instanceof ECKey && key instanceof ECKey) - && !(mKey instanceof XECKey && key instanceof XECKey)) { + } else if (mKey instanceof ECKey && !(key instanceof ECKey) + /*&& !(mKey instanceof XECKey && key instanceof XECKey)*/) { + /** TODO This condition is temporary modified, because OpenSSL implementation does not + * implement OpenSSLX25519PublicKey from XECKey interface (b/214203951). + * This change has to revert once conscrypt implements OpenSSLX25519PublicKey from + * XECKey interface. + */ throw new InvalidKeyException( - "Public and Private key should be of the same type:"); + "Public and Private key should be of the same type."); } else if (mKey instanceof ECKey && !((ECKey) key).getParams().getCurve() .equals(((ECKey) mKey).getParams().getCurve())) { diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java index f05cdc57fb70..91f216f1320a 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreSpi.java @@ -20,6 +20,7 @@ import static android.security.keystore2.AndroidKeyStoreCipherSpiBase.DEFAULT_MG import android.annotation.NonNull; import android.hardware.biometrics.BiometricManager; +import android.hardware.security.keymint.EcCurve; import android.hardware.security.keymint.HardwareAuthenticatorType; import android.hardware.security.keymint.KeyParameter; import android.hardware.security.keymint.SecurityLevel; @@ -67,6 +68,14 @@ import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.interfaces.ECKey; +import java.security.interfaces.ECPrivateKey; +import java.security.interfaces.EdECKey; +import java.security.interfaces.EdECPrivateKey; +import java.security.interfaces.XECKey; +import java.security.interfaces.XECPrivateKey; +import java.security.spec.AlgorithmParameterSpec; +import java.security.spec.ECParameterSpec; +import java.security.spec.NamedParameterSpec; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -567,22 +576,14 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { spec.getMaxUsageCount() )); } - if (KeyProperties.KEY_ALGORITHM_EC.equalsIgnoreCase(key.getAlgorithm())) { - if (key instanceof ECKey) { - ECKey ecKey = (ECKey) key; - importArgs.add(KeyStore2ParameterUtils.makeEnum( - KeymasterDefs.KM_TAG_EC_CURVE, - KeyProperties.EcCurve.toKeymasterCurve(ecKey.getParams()) - )); - } + if (KeymasterDefs.KM_ALGORITHM_EC + == KeyProperties.KeyAlgorithm.toKeymasterAsymmetricKeyAlgorithm( + key.getAlgorithm())) { + importArgs.add(KeyStore2ParameterUtils.makeEnum( + KeymasterDefs.KM_TAG_EC_CURVE, + getKeymasterEcCurve(key) + )); } - /* TODO: check for Ed25519(EdDSA) or X25519(XDH) key algorithm and - * add import args for KM_TAG_EC_CURVE as EcCurve.CURVE_25519. - * Currently conscrypt does not support EdDSA key import and XDH keys are not an - * instance of XECKey, hence these conditions are not added, once it is fully - * implemented by conscrypt, we can add CURVE_25519 argument for EdDSA and XDH - * algorithms. - */ } catch (IllegalArgumentException | IllegalStateException e) { throw new KeyStoreException(e); } @@ -608,6 +609,31 @@ public class AndroidKeyStoreSpi extends KeyStoreSpi { } } + private int getKeymasterEcCurve(PrivateKey key) { + if (key instanceof ECKey) { + ECParameterSpec param = ((ECPrivateKey) key).getParams(); + int kmECCurve = KeymasterUtils.getKeymasterEcCurve(KeymasterUtils.getCurveName(param)); + if (kmECCurve >= 0) { + return kmECCurve; + } + } else if (key instanceof XECKey) { + AlgorithmParameterSpec param = ((XECPrivateKey) key).getParams(); + if (param.equals(NamedParameterSpec.X25519)) { + return EcCurve.CURVE_25519; + } + } else if (key.getAlgorithm().equals("XDH")) { + // TODO com.android.org.conscrypt.OpenSSLX25519PrivateKey does not implement XECKey, + // this case is not required once it implements XECKey interface(b/214203951). + return EcCurve.CURVE_25519; + } else if (key instanceof EdECKey) { + AlgorithmParameterSpec param = ((EdECPrivateKey) key).getParams(); + if (param.equals(NamedParameterSpec.ED25519)) { + return EcCurve.CURVE_25519; + } + } + throw new IllegalArgumentException("Unexpected Key " + key.getClass().getName()); + } + private static void assertCanReplace(String alias, @Domain int targetDomain, int targetNamespace, KeyDescriptor descriptor) throws KeyStoreException { diff --git a/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPublicKey.java b/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPublicKey.java index 9f3df3d72d86..69138340f653 100644 --- a/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPublicKey.java +++ b/keystore/java/android/security/keystore2/AndroidKeyStoreXDHPublicKey.java @@ -88,7 +88,7 @@ public class AndroidKeyStoreXDHPublicKey extends AndroidKeyStorePublicKey implem getUserKeyDescriptor(), getKeyIdDescriptor().nspace, getAuthorizations(), - "x25519", + "XDH", getSecurityLevel()); } diff --git a/keystore/java/android/security/keystore2/KeymasterUtils.java b/keystore/java/android/security/keystore2/KeymasterUtils.java index de4696cea3ac..614e3684c417 100644 --- a/keystore/java/android/security/keystore2/KeymasterUtils.java +++ b/keystore/java/android/security/keystore2/KeymasterUtils.java @@ -20,7 +20,12 @@ import android.security.keymaster.KeymasterArguments; import android.security.keymaster.KeymasterDefs; import android.security.keystore.KeyProperties; +import java.security.AlgorithmParameters; +import java.security.NoSuchAlgorithmException; import java.security.ProviderException; +import java.security.spec.ECGenParameterSpec; +import java.security.spec.ECParameterSpec; +import java.security.spec.InvalidParameterSpecException; /** * @hide @@ -121,4 +126,65 @@ public abstract class KeymasterUtils { break; } } + + static String getEcCurveFromKeymaster(int ecCurve) { + switch (ecCurve) { + case android.hardware.security.keymint.EcCurve.P_224: + return "secp224r1"; + case android.hardware.security.keymint.EcCurve.P_256: + return "secp256r1"; + case android.hardware.security.keymint.EcCurve.P_384: + return "secp384r1"; + case android.hardware.security.keymint.EcCurve.P_521: + return "secp521r1"; + } + return ""; + } + + static int getKeymasterEcCurve(String ecCurveName) { + if (ecCurveName.equals("secp224r1")) { + return android.hardware.security.keymint.EcCurve.P_224; + } else if (ecCurveName.equals("secp256r1")) { + return android.hardware.security.keymint.EcCurve.P_256; + } else if (ecCurveName.equals("secp384r1")) { + return android.hardware.security.keymint.EcCurve.P_384; + } else if (ecCurveName.equals("secp521r1")) { + return android.hardware.security.keymint.EcCurve.P_521; + } + return -1; + } + + static ECParameterSpec getCurveSpec(String name) + throws NoSuchAlgorithmException, InvalidParameterSpecException { + AlgorithmParameters parameters = AlgorithmParameters.getInstance("EC"); + parameters.init(new ECGenParameterSpec(name)); + return parameters.getParameterSpec(ECParameterSpec.class); + } + + static String getCurveName(ECParameterSpec spec) { + if (KeymasterUtils.isECParameterSpecOfCurve(spec, "secp224r1")) { + return "secp224r1"; + } else if (KeymasterUtils.isECParameterSpecOfCurve(spec, "secp256r1")) { + return "secp256r1"; + } else if (KeymasterUtils.isECParameterSpecOfCurve(spec, "secp384r1")) { + return "secp384r1"; + } else if (KeymasterUtils.isECParameterSpecOfCurve(spec, "secp521r1")) { + return "secp521r1"; + } + return null; + } + + private static boolean isECParameterSpecOfCurve(ECParameterSpec spec, String curveName) { + try { + ECParameterSpec curveSpec = KeymasterUtils.getCurveSpec(curveName); + if (curveSpec.getCurve().equals(spec.getCurve()) + && curveSpec.getOrder().equals(spec.getOrder()) + && curveSpec.getGenerator().equals(spec.getGenerator())) { + return true; + } + } catch (NoSuchAlgorithmException | InvalidParameterSpecException e) { + return false; + } + return false; + } } |