Merge "KeyStore: X25519 key import" am: 9db6ee342b
Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/2183495 Change-Id: I6ebaecda61d701e06bc5a58bcf7443bb754d3b38 Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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())) {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -88,7 +88,7 @@ public class AndroidKeyStoreXDHPublicKey extends AndroidKeyStorePublicKey implem
|
||||
getUserKeyDescriptor(),
|
||||
getKeyIdDescriptor().nspace,
|
||||
getAuthorizations(),
|
||||
"x25519",
|
||||
"XDH",
|
||||
getSecurityLevel());
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user