diff --git a/common/src/jni/main/cpp/conscrypt/native_crypto.cc b/common/src/jni/main/cpp/conscrypt/native_crypto.cc index 8a8a5f17b..f6cde6c99 100644 --- a/common/src/jni/main/cpp/conscrypt/native_crypto.cc +++ b/common/src/jni/main/cpp/conscrypt/native_crypto.cc @@ -1584,46 +1584,6 @@ static jbyteArray NativeCrypto_EVP_PKEY_get_private_seed(JNIEnv* env, jclass cls return seedArray.release(); } -static jbyteArray NativeCrypto_EVP_raw_X25519_private_key( - JNIEnv* env, jclass cls, jbyteArray keyJavaBytes) { - CHECK_ERROR_QUEUE_ON_RETURN; - JNI_TRACE("NativeCrypto_EVP_raw_X25519_private_key(%p)", keyJavaBytes); - - jlong key_ptr = NativeCrypto_EVP_parse_private_key(env, cls, keyJavaBytes); - if (key_ptr == 0) { - return nullptr; - } - bssl::UniquePtr pkey(reinterpret_cast(key_ptr)); - if (EVP_PKEY_id(pkey.get()) != EVP_PKEY_X25519) { - conscrypt::jniutil::throwInvalidKeyException(env, "Invalid key type"); - return nullptr; - } - - size_t key_length = X25519_PRIVATE_KEY_LEN; - ScopedLocalRef byteArray(env, env->NewByteArray(static_cast(key_length))); - if (byteArray.get() == nullptr) { - conscrypt::jniutil::throwOutOfMemory(env, "Allocating byte[]"); - JNI_TRACE("NativeCrypto_EVP_raw_X25519_private_key: byte array creation failed"); - return nullptr; - } - - ScopedByteArrayRW bytes(env, byteArray.get()); - if (bytes.get() == nullptr) { - conscrypt::jniutil::throwOutOfMemory(env, "Allocating scoped byte array"); - JNI_TRACE("NativeCrypto_EVP_raw_X25519_private_key: scoped byte array failed"); - return nullptr; - } - - if (EVP_PKEY_get_raw_private_key( - pkey.get(), reinterpret_cast(bytes.get()), &key_length) == 0) { - conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get_raw_private_key"); - return nullptr; - } - jbyteArray result = byteArray.release(); - JNI_TRACE("bytes=%p NativeCrypto_EVP_raw_X25519_private_key => %p", keyJavaBytes, result); - return result; -} - /* * static native byte[] EVP_marshal_public_key(long) */ @@ -12238,7 +12198,6 @@ static JNINativeMethod sNativeCryptoMethods[] = { CONSCRYPT_NATIVE_METHOD(EVP_PKEY_get_raw_public_key, "(" REF_EVP_PKEY ")[B"), CONSCRYPT_NATIVE_METHOD(EVP_PKEY_from_private_seed, "(I[B)J"), CONSCRYPT_NATIVE_METHOD(EVP_PKEY_get_private_seed, "(" REF_EVP_PKEY ")[B"), - CONSCRYPT_NATIVE_METHOD(EVP_raw_X25519_private_key, "([B)[B"), CONSCRYPT_NATIVE_METHOD(EVP_marshal_public_key, "(" REF_EVP_PKEY ")[B"), CONSCRYPT_NATIVE_METHOD(EVP_parse_public_key, "([B)J"), CONSCRYPT_NATIVE_METHOD(PEM_read_bio_PUBKEY, "(J)J"), diff --git a/common/src/main/java/org/conscrypt/NativeCrypto.java b/common/src/main/java/org/conscrypt/NativeCrypto.java index 24afc900d..2badbc641 100644 --- a/common/src/main/java/org/conscrypt/NativeCrypto.java +++ b/common/src/main/java/org/conscrypt/NativeCrypto.java @@ -123,9 +123,6 @@ static native long EVP_PKEY_from_subject_public_key_info(byte[] data, int[] algs static native byte[] EVP_PKEY_get_private_seed(NativeRef.EVP_PKEY pkey); - static native byte[] EVP_raw_X25519_private_key(byte[] data) - throws ParsingException, InvalidKeyException; - static native long EVP_parse_public_key(byte[] data) throws ParsingException; static native long PEM_read_bio_PUBKEY(long bioCtx); diff --git a/common/src/main/java/org/conscrypt/OpenSSLX25519PrivateKey.java b/common/src/main/java/org/conscrypt/OpenSSLX25519PrivateKey.java index e816d2df0..b94c7ac6c 100644 --- a/common/src/main/java/org/conscrypt/OpenSSLX25519PrivateKey.java +++ b/common/src/main/java/org/conscrypt/OpenSSLX25519PrivateKey.java @@ -21,7 +21,6 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.security.InvalidKeyException; import java.security.PrivateKey; import java.security.spec.EncodedKeySpec; import java.security.spec.InvalidKeySpecException; @@ -29,14 +28,6 @@ public class OpenSSLX25519PrivateKey implements OpenSSLX25519Key, PrivateKey { private static final long serialVersionUID = -3136201500221850916L; - private static final byte[] PKCS8_PREAMBLE = new byte[]{ - 0x30, 0x2e, // Sequence: 46 bytes - 0x02, 0x01, 0x00, // Integer: 0 (version) - 0x30, 0x05, // Sequence: 5 bytes - 0x06, 0x03, 0x2b, 0x65, 0x6e, // OID: 1.3.101.110 (X25519) - 0x04, 0x22, 0x04, 0x20, // Octet string: 32 bytes - // Key bytes follow directly - }; private byte[] uCoordinate; @@ -45,8 +36,10 @@ public OpenSSLX25519PrivateKey(EncodedKeySpec keySpec) byte[] encoded = keySpec.getEncoded(); if ("PKCS#8".equals(keySpec.getFormat())) { try { - uCoordinate = NativeCrypto.EVP_raw_X25519_private_key(encoded); - } catch (InvalidKeyException | ParsingException e) { + OpenSSLKey key = new OpenSSLKey(NativeCrypto.EVP_PKEY_from_private_key_info( + encoded, new int[] {NativeConstants.EVP_PKEY_X25519})); + uCoordinate = NativeCrypto.EVP_PKEY_get_raw_private_key(key.getNativeRef()); + } catch (ParsingException e) { throw new InvalidKeySpecException(e); } } else if ("raw".equalsIgnoreCase(keySpec.getFormat())) { @@ -81,7 +74,13 @@ public byte[] getEncoded() { if (uCoordinate == null) { throw new IllegalStateException("key is destroyed"); } - return ArrayUtils.concat(PKCS8_PREAMBLE, uCoordinate); + try { + OpenSSLKey key = new OpenSSLKey(NativeCrypto.EVP_PKEY_from_raw_private_key( + NativeConstants.EVP_PKEY_X25519, uCoordinate)); + return NativeCrypto.EVP_marshal_private_key(key.getNativeRef()); + } catch (ParsingException e) { + throw new IllegalStateException("unable to create key", e); + } } @Override diff --git a/common/src/main/java/org/conscrypt/OpenSSLX25519PublicKey.java b/common/src/main/java/org/conscrypt/OpenSSLX25519PublicKey.java index 246ff64f0..ef733d29d 100644 --- a/common/src/main/java/org/conscrypt/OpenSSLX25519PublicKey.java +++ b/common/src/main/java/org/conscrypt/OpenSSLX25519PublicKey.java @@ -16,6 +16,8 @@ package org.conscrypt; +import org.conscrypt.OpenSSLX509CertificateFactory.ParsingException; + import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; @@ -27,27 +29,18 @@ public class OpenSSLX25519PublicKey implements OpenSSLX25519Key, PublicKey { private static final long serialVersionUID = 453861992373478445L; - private static final byte[] X509_PREAMBLE = new byte[] { - 0x30, 0x2a, // Sequence: 42 bytes - 0x30, 0x05, // Sequence: 5 bytes - 0x06, 0x03, 0x2b, 0x65, 0x6e, // OID: 1.3.101.110 (X25519) - 0x03, 0x21, 0x00, // Bit string: 256 bits - // Key bytes follow directly - }; - private final byte[] uCoordinate; public OpenSSLX25519PublicKey(EncodedKeySpec keySpec) throws InvalidKeySpecException { byte[] encoded = keySpec.getEncoded(); if ("X.509".equals(keySpec.getFormat())) { - if (!ArrayUtils.startsWith(encoded, X509_PREAMBLE)) { - throw new InvalidKeySpecException("Invalid format"); - } - int totalLength = X509_PREAMBLE.length + X25519_KEY_SIZE_BYTES; - if (encoded.length < totalLength) { - throw new InvalidKeySpecException("Invalid key size"); + try { + OpenSSLKey key = new OpenSSLKey(NativeCrypto.EVP_PKEY_from_subject_public_key_info( + encoded, new int[] {NativeConstants.EVP_PKEY_X25519})); + uCoordinate = NativeCrypto.EVP_PKEY_get_raw_public_key(key.getNativeRef()); + } catch (ParsingException e) { + throw new InvalidKeySpecException("Invalid format", e); } - uCoordinate = Arrays.copyOfRange(encoded, X509_PREAMBLE.length, totalLength); } else if ("raw".equalsIgnoreCase(keySpec.getFormat())) { if (encoded.length != X25519_KEY_SIZE_BYTES) { throw new InvalidKeySpecException("Invalid key size"); @@ -80,8 +73,13 @@ public byte[] getEncoded() { if (uCoordinate == null) { throw new IllegalStateException("key is destroyed"); } - - return ArrayUtils.concat(X509_PREAMBLE, uCoordinate); + try { + OpenSSLKey key = new OpenSSLKey(NativeCrypto.EVP_PKEY_from_raw_public_key( + NativeConstants.EVP_PKEY_X25519, uCoordinate)); + return NativeCrypto.EVP_marshal_public_key(key.getNativeRef()); + } catch (ParsingException e) { + throw new IllegalStateException("unable to create key", e); + } } @Override