Switch OpenSSLECDHKeyAgreement to KeyFactory.translateKey.
OpenSSL KeyFactory.translateKey encapsulates all the functionality
for translating arbitrary Key instances to OpenSSL-backed Key
instances. Thus, there's no need to replicate that functionality
elsewhere.
(cherry picked from commit 0469e3a6a9b5e854b8b985039de8ba4f6e6037bd)
Change-Id: I4caa0021e51a83be6932617117275fd033b6d5f7
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
index b24ad0e..dfc512f 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/NativeCrypto.java
@@ -206,6 +206,8 @@
public static native byte[] EC_GROUP_get_order(long groupCtx);
+ public static native int EC_GROUP_get_degree(long groupCtx);
+
public static native byte[] EC_GROUP_get_cofactor(long groupCtx);
public static native long EC_POINT_new(long groupRef);
diff --git a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECDHKeyAgreement.java b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECDHKeyAgreement.java
index 096e300..5146156 100644
--- a/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECDHKeyAgreement.java
+++ b/luni/src/main/java/org/apache/harmony/xnet/provider/jsse/OpenSSLECDHKeyAgreement.java
@@ -19,9 +19,10 @@
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Key;
+import java.security.KeyFactory;
+import java.security.PrivateKey;
+import java.security.PublicKey;
import java.security.SecureRandom;
-import java.security.interfaces.ECPrivateKey;
-import java.security.interfaces.ECPublicKey;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.KeyAgreementSpi;
@@ -54,36 +55,14 @@
if (!lastPhase) {
throw new IllegalStateException("ECDH only has one phase");
}
+
if (key == null) {
throw new InvalidKeyException("key == null");
}
- if (!(key instanceof ECPublicKey)) {
- throw new InvalidKeyException("This phase requires an ECPublicKey. Actual key type: "
- + key.getClass());
+ if (!(key instanceof PublicKey)) {
+ throw new InvalidKeyException("Not a public key: " + key.getClass());
}
- ECPublicKey publicKey = (ECPublicKey) key;
-
- OpenSSLKey openSslPublicKey;
- if (publicKey instanceof OpenSSLECPublicKey) {
- // OpenSSL-backed key
- openSslPublicKey = ((OpenSSLECPublicKey) publicKey).getOpenSSLKey();
- } else {
- // Not an OpenSSL-backed key -- create an OpenSSL-backed key from its X.509 encoding
- if (!"X.509".equals(publicKey.getFormat())) {
- throw new InvalidKeyException("Non-OpenSSL public key (" + publicKey.getClass()
- + ") offers unsupported encoding format: " + publicKey.getFormat());
- }
- byte[] encoded = publicKey.getEncoded();
- if (encoded == null) {
- throw new InvalidKeyException("Non-OpenSSL public key (" + publicKey.getClass()
- + ") does not provide encoded form");
- }
- try {
- openSslPublicKey = new OpenSSLKey(NativeCrypto.d2i_PUBKEY(encoded));
- } catch (Exception e) {
- throw new InvalidKeyException("Failed to decode X.509 encoded public key", e);
- }
- }
+ OpenSSLKey openSslPublicKey = translateKeyToEcOpenSSLKey(key);
byte[] buffer = new byte[mExpectedResultLength];
int actualResultLength = NativeCrypto.ECDH_compute_key(
@@ -142,35 +121,15 @@
if (key == null) {
throw new InvalidKeyException("key == null");
}
- if (!(key instanceof ECPrivateKey)) {
- throw new InvalidKeyException("Not an EC private key: " + key.getClass());
+ if (!(key instanceof PrivateKey)) {
+ throw new InvalidKeyException("Not a private key: " + key.getClass());
}
- ECPrivateKey privateKey = (ECPrivateKey) key;
- mExpectedResultLength =
- (privateKey.getParams().getCurve().getField().getFieldSize() + 7) / 8;
- OpenSSLKey openSslPrivateKey;
- if (privateKey instanceof OpenSSLECPrivateKey) {
- // OpenSSL-backed key
- openSslPrivateKey = ((OpenSSLECPrivateKey) privateKey).getOpenSSLKey();
- } else {
- // Not an OpenSSL-backed key -- create an OpenSSL-backed key from its PKCS#8 encoding
- if (!"PKCS#8".equals(privateKey.getFormat())) {
- throw new InvalidKeyException("Non-OpenSSL private key (" + privateKey.getClass()
- + ") offers unsupported encoding format: " + privateKey.getFormat());
- }
- byte[] encoded = privateKey.getEncoded();
- if (encoded == null) {
- throw new InvalidKeyException("Non-OpenSSL private key (" + privateKey.getClass()
- + ") does not provide encoded form");
- }
- try {
- openSslPrivateKey = new OpenSSLKey(NativeCrypto.d2i_PKCS8_PRIV_KEY_INFO(encoded));
- } catch (Exception e) {
- throw new InvalidKeyException("Failed to decode PKCS#8 encoded private key", e);
- }
- }
- mOpenSslPrivateKey = openSslPrivateKey;
+ OpenSSLKey openSslKey = translateKeyToEcOpenSSLKey(key);
+ int fieldSizeBits = NativeCrypto.EC_GROUP_get_degree(NativeCrypto.EC_KEY_get0_group(
+ openSslKey.getPkeyContext()));
+ mExpectedResultLength = (fieldSizeBits + 7) / 8;
+ mOpenSslPrivateKey = openSslKey;
}
@Override
@@ -188,4 +147,13 @@
throw new IllegalStateException("Key agreement not completed");
}
}
+
+ private static OpenSSLKey translateKeyToEcOpenSSLKey(Key key) throws InvalidKeyException {
+ try {
+ return ((OpenSSLKeyHolder) KeyFactory.getInstance(
+ "EC", OpenSSLProvider.PROVIDER_NAME).translateKey(key)).getOpenSSLKey();
+ } catch (Exception e) {
+ throw new InvalidKeyException("Failed to translate key to OpenSSL EC key", e);
+ }
+ }
}
diff --git a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
index ee6a57e..0921d8b 100644
--- a/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
+++ b/luni/src/main/native/org_apache_harmony_xnet_provider_jsse_NativeCrypto.cpp
@@ -2360,6 +2360,22 @@
return orderArray;
}
+static jint NativeCrypto_EC_GROUP_get_degree(JNIEnv* env, jclass, jlong groupRef)
+{
+ const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
+ JNI_TRACE("EC_GROUP_get_degree(%p)", group);
+
+ jint degree = EC_GROUP_get_degree(group);
+ if (degree == 0) {
+ JNI_TRACE("EC_GROUP_get_degree(%p) => unsupported", group);
+ jniThrowRuntimeException(env, "not supported");
+ return 0;
+ }
+
+ JNI_TRACE("EC_GROUP_get_degree(%p) => %d", group, degree);
+ return degree;
+}
+
static jbyteArray NativeCrypto_EC_GROUP_get_cofactor(JNIEnv* env, jclass, jlong groupRef)
{
const EC_GROUP* group = reinterpret_cast<const EC_GROUP*>(groupRef);
@@ -7821,6 +7837,7 @@
NATIVE_METHOD(NativeCrypto, EC_GROUP_get_curve_name, "(J)Ljava/lang/String;"),
NATIVE_METHOD(NativeCrypto, EC_GROUP_get_curve, "(J)[[B"),
NATIVE_METHOD(NativeCrypto, EC_GROUP_get_order, "(J)[B"),
+ NATIVE_METHOD(NativeCrypto, EC_GROUP_get_degree, "(J)I"),
NATIVE_METHOD(NativeCrypto, EC_GROUP_get_cofactor, "(J)[B"),
NATIVE_METHOD(NativeCrypto, EC_GROUP_clear_free, "(J)V"),
NATIVE_METHOD(NativeCrypto, EC_GROUP_cmp, "(JJ)Z"),