Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 5 additions & 90 deletions common/src/jni/main/cpp/conscrypt/native_crypto.cc
Original file line number Diff line number Diff line change
Expand Up @@ -428,10 +428,7 @@ static jobjectArray CryptoBuffersToObjectArray(JNIEnv* env,
* Converts ASN.1 BIT STRING to a jbooleanArray.
*/
jbooleanArray ASN1BitStringToBooleanArray(JNIEnv* env, const ASN1_BIT_STRING* bitStr) {
int size = ASN1_STRING_length(bitStr) * 8;
if (bitStr->flags & ASN1_STRING_FLAG_BITS_LEFT) {
size -= bitStr->flags & 0x07;
}
int size = ASN1_STRING_length(bitStr) * 8 - ASN1_BIT_STRING_unused_bits(bitStr);

ScopedLocalRef<jbooleanArray> bitsRef(env, env->NewBooleanArray(size));
if (bitsRef.get() == nullptr) {
Expand Down Expand Up @@ -846,7 +843,6 @@ static jlong NativeCrypto_EVP_PKEY_new_RSA(JNIEnv* env, jclass, jbyteArray n, jb
return 0;
}

#if BORINGSSL_API_VERSION >= 20
bssl::UniquePtr<BIGNUM> nBN, eBN, dBN, pBN, qBN, dmp1BN, dmq1BN, iqmpBN;
nBN = arrayToBignum(env, n);
if (!nBN) {
Expand Down Expand Up @@ -917,70 +913,6 @@ static jlong NativeCrypto_EVP_PKEY_new_RSA(JNIEnv* env, jclass, jbyteArray n, jb
conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_new_RSA");
return 0;
}
#else
bssl::UniquePtr<RSA> rsa(RSA_new());
if (rsa.get() == nullptr) {
conscrypt::jniutil::throwRuntimeException(env, "RSA_new failed");
return 0;
}

if (!arrayToBignum(env, n, &rsa->n)) {
return 0;
}

if (e != nullptr && !arrayToBignum(env, e, &rsa->e)) {
return 0;
}

if (d != nullptr && !arrayToBignum(env, d, &rsa->d)) {
return 0;
}

if (p != nullptr && !arrayToBignum(env, p, &rsa->p)) {
return 0;
}

if (q != nullptr && !arrayToBignum(env, q, &rsa->q)) {
return 0;
}

if (dmp1 != nullptr && !arrayToBignum(env, dmp1, &rsa->dmp1)) {
return 0;
}

if (dmq1 != nullptr && !arrayToBignum(env, dmq1, &rsa->dmq1)) {
return 0;
}

if (iqmp != nullptr && !arrayToBignum(env, iqmp, &rsa->iqmp)) {
return 0;
}

if (conscrypt::trace::kWithJniTrace) {
if (p != nullptr && q != nullptr) {
int check = RSA_check_key(rsa.get());
JNI_TRACE("EVP_PKEY_new_RSA(...) RSA_check_key returns %d", check);
}
}

if (rsa->n == nullptr || (rsa->e == nullptr && rsa->d == nullptr)) {
conscrypt::jniutil::throwRuntimeException(env, "Unable to convert BigInteger to BIGNUM");
return 0;
}

/*
* If the private exponent is available, there is the potential to do signing
* operations. However, we can only do blinding if the public exponent is also
* available. Disable blinding if the public exponent isn't available.
*
* TODO[kroot]: We should try to recover the public exponent by trying
* some common ones such 3, 17, or 65537.
*/
if (rsa->d != nullptr && rsa->e == nullptr) {
JNI_TRACE("EVP_PKEY_new_RSA(...) disabling RSA blinding => %p", rsa.get());
rsa->flags |= RSA_FLAG_NO_BLINDING;
}
#endif

bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_new());
if (pkey.get() == nullptr) {
Expand Down Expand Up @@ -1690,7 +1622,6 @@ static jlong NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv* env, jclass, jobject j

ensure_engine_globals();

#if BORINGSSL_API_VERSION >= 20
// The PSS padding code needs access to the actual n, so set it even though we
// don't set any other parts of the key
bssl::UniquePtr<BIGNUM> n = arrayToBignum(env, modulusBytes);
Expand All @@ -1705,19 +1636,6 @@ static jlong NativeCrypto_getRSAPrivateKeyWrapper(JNIEnv* env, jclass, jobject j
conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
return 0;
}
#else
bssl::UniquePtr<RSA> rsa(RSA_new_method(g_engine));
if (rsa == nullptr) {
conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate RSA key");
return 0;
}

// The PSS padding code needs access to the actual n, so set it even though we
// don't set any other parts of the key
if (!arrayToBignum(env, modulusBytes, &rsa->n)) {
return 0;
}
#endif

auto ex_data = new KeyExData;
ex_data->private_key = env->NewGlobalRef(javaKey);
Expand Down Expand Up @@ -5788,12 +5706,9 @@ static jobject GENERAL_NAME_to_jobject(JNIEnv* env, GENERAL_NAME* gen) {
/* Write in RFC 2253 format */
return X509_NAME_to_jstring(env, gen->d.directoryName, XN_FLAG_RFC2253);
case GEN_IPADD: {
#ifdef _WIN32
void* ip = reinterpret_cast<void*>(gen->d.ip->data);
#else
const void* ip = reinterpret_cast<const void*>(gen->d.ip->data);
#endif
if (gen->d.ip->length == 4) {
const uint8_t* ip = ASN1_STRING_get0_data(gen->d.ip);
int ip_len = ASN1_STRING_length(gen->d.ip);
if (ip_len == 4) {
// IPv4
std::unique_ptr<char[]> buffer(new char[INET_ADDRSTRLEN]);
if (inet_ntop(AF_INET, ip, buffer.get(), INET_ADDRSTRLEN) != nullptr) {
Expand All @@ -5803,7 +5718,7 @@ static jobject GENERAL_NAME_to_jobject(JNIEnv* env, GENERAL_NAME* gen) {
JNI_TRACE("GENERAL_NAME_to_jobject(%p) => IPv4 failed %s", gen,
strerror(errno));
}
} else if (gen->d.ip->length == 16) {
} else if (ip_len == 16) {
// IPv6
std::unique_ptr<char[]> buffer(new char[INET6_ADDRSTRLEN]);
if (inet_ntop(AF_INET6, ip, buffer.get(), INET6_ADDRSTRLEN) != nullptr) {
Expand Down
116 changes: 102 additions & 14 deletions common/src/main/java/org/conscrypt/OpenSslSlhDsaKeyFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,34 +26,105 @@
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Arrays;

/** An implementation of a {@link KeyFactorySpi} for SLH-DSL keys based on BoringSSL. */
@Internal
public final class OpenSslSlhDsaKeyFactory extends KeyFactorySpi {
// X.509 format preamble for SLH-DSA-SHA2-128S.
static final byte[] x509Preamble = new byte[] {
(byte) 0x30, (byte) 0x30, (byte) 0x30, (byte) 0x0b, (byte) 0x06, (byte) 0x09,
(byte) 0x60, (byte) 0x86, (byte) 0x48, (byte) 0x01, (byte) 0x65, (byte) 0x03,
(byte) 0x04, (byte) 0x03, (byte) 0x14, (byte) 0x03, (byte) 0x21, (byte) 0x00};

// PKCS#8 format preamble for SLH-DSA-SHA2-128S.
static final byte[] pkcs8Preamble =
new byte[] {(byte) 0x30, (byte) 0x52, (byte) 0x02, (byte) 0x01, (byte) 0x00,
(byte) 0x30, (byte) 0x0b, (byte) 0x06, (byte) 0x09, (byte) 0x60,
(byte) 0x86, (byte) 0x48, (byte) 0x01, (byte) 0x65, (byte) 0x03,
(byte) 0x04, (byte) 0x03, (byte) 0x14, (byte) 0x04, (byte) 0x40};

public OpenSslSlhDsaKeyFactory() {}

private OpenSslSlhDsaPublicKey makePublicKeyFromRaw(byte[] raw) throws InvalidKeySpecException {
if (raw.length != OpenSslSlhDsaPublicKey.PUBLIC_KEY_SIZE_BYTES) {
throw new InvalidKeySpecException("Invalid raw public key length: " + raw.length
+ " != "
+ OpenSslSlhDsaPublicKey.PUBLIC_KEY_SIZE_BYTES);
}
try {
return new OpenSslSlhDsaPublicKey(raw);
} catch (IllegalArgumentException e) {
throw new InvalidKeySpecException("Invalid raw public key", e);
}
}

@Override
protected PublicKey engineGeneratePublic(KeySpec keySpec) throws InvalidKeySpecException {
if (keySpec == null) {
throw new InvalidKeySpecException("keySpec == null");
}
if (keySpec instanceof EncodedKeySpec) {
return new OpenSslSlhDsaPublicKey((EncodedKeySpec) keySpec);
if (!(keySpec instanceof EncodedKeySpec)) {
throw new InvalidKeySpecException("Currently only EncodedKeySpec is supported; was "
+ keySpec.getClass().getName());
}
EncodedKeySpec encodedKeySpec = (EncodedKeySpec) keySpec;
if ("raw".equalsIgnoreCase(encodedKeySpec.getFormat())) {
byte[] raw = encodedKeySpec.getEncoded();
return makePublicKeyFromRaw(raw);
}
if (!encodedKeySpec.getFormat().equals("X.509")) {
throw new InvalidKeySpecException("Encoding must be in X.509 format");
}
byte[] encoded = encodedKeySpec.getEncoded();
if (ArrayUtils.startsWith(encoded, x509Preamble)) {
byte[] raw = Arrays.copyOfRange(encoded, x509Preamble.length, encoded.length);
return makePublicKeyFromRaw(raw);
} else {
throw new InvalidKeySpecException(
"Only X.509 format for SLH-DSA-SHA2-128S is supported");
}
}

private OpenSslSlhDsaPrivateKey makePrivateKeyFromRaw(byte[] raw)
throws InvalidKeySpecException {
if (raw.length != OpenSslSlhDsaPrivateKey.PRIVATE_KEY_SIZE_BYTES) {
throw new InvalidKeySpecException("Invalid raw private key length: " + raw.length
+ " != "
+ OpenSslSlhDsaPrivateKey.PRIVATE_KEY_SIZE_BYTES);
}
try {
return new OpenSslSlhDsaPrivateKey(raw);
} catch (IllegalArgumentException e) {
throw new InvalidKeySpecException("Invalid raw private key", e);
}
throw new InvalidKeySpecException("Currently only EncodedKeySpec is supported; was "
+ keySpec.getClass().getName());
}

@Override
protected PrivateKey engineGeneratePrivate(KeySpec keySpec) throws InvalidKeySpecException {
if (keySpec == null) {
throw new InvalidKeySpecException("keySpec == null");
}
if (keySpec instanceof EncodedKeySpec) {
return new OpenSslSlhDsaPrivateKey((EncodedKeySpec) keySpec);
if (!(keySpec instanceof EncodedKeySpec)) {
throw new InvalidKeySpecException("Currently only EncodedKeySpec is supported; was "
+ keySpec.getClass().getName());
}
EncodedKeySpec encodedKeySpec = (EncodedKeySpec) keySpec;
if ("raw".equalsIgnoreCase(encodedKeySpec.getFormat())) {
byte[] raw = encodedKeySpec.getEncoded();
return makePrivateKeyFromRaw(raw);
}
if (!encodedKeySpec.getFormat().equals("PKCS#8")) {
throw new InvalidKeySpecException("Encoding must be in PKCS#8 format");
}
byte[] encoded = encodedKeySpec.getEncoded();
if (ArrayUtils.startsWith(encoded, pkcs8Preamble)) {
byte[] raw = Arrays.copyOfRange(encoded, pkcs8Preamble.length, encoded.length);
return makePrivateKeyFromRaw(raw);
} else {
throw new InvalidKeySpecException(
"Only PKCS#8 format for SLH-DSA-SHA2-128S is supported");
}
throw new InvalidKeySpecException("Currently only EncodedKeySpec is supported; was "
+ keySpec.getClass().getName());
}

@Override
Expand All @@ -68,16 +139,18 @@ protected <T extends KeySpec> T engineGetKeySpec(Key key, Class<T> keySpec)
if (key instanceof OpenSslSlhDsaPublicKey) {
OpenSslSlhDsaPublicKey conscryptKey = (OpenSslSlhDsaPublicKey) key;
if (X509EncodedKeySpec.class.isAssignableFrom(keySpec)) {
throw new UnsupportedOperationException(
"X509EncodedKeySpec is currently not supported");
@SuppressWarnings("unchecked")
T result = (T) new X509EncodedKeySpec(key.getEncoded());
return result;
} else if (EncodedKeySpec.class.isAssignableFrom(keySpec)) {
return KeySpecUtil.makeRawKeySpec(conscryptKey.getRaw(), keySpec);
}
} else if (key instanceof OpenSslSlhDsaPrivateKey) {
OpenSslSlhDsaPrivateKey conscryptKey = (OpenSslSlhDsaPrivateKey) key;
if (PKCS8EncodedKeySpec.class.isAssignableFrom(keySpec)) {
throw new UnsupportedOperationException(
"PKCS8EncodedKeySpec is currently not supported");
@SuppressWarnings("unchecked")
T result = (T) new PKCS8EncodedKeySpec(key.getEncoded());
return result;
} else if (EncodedKeySpec.class.isAssignableFrom(keySpec)) {
return KeySpecUtil.makeRawKeySpec(conscryptKey.getRaw(), keySpec);
}
Expand All @@ -95,7 +168,22 @@ protected Key engineTranslateKey(Key key) throws InvalidKeyException {
if ((key instanceof OpenSslSlhDsaPublicKey) || (key instanceof OpenSslSlhDsaPrivateKey)) {
return key;
}
throw new InvalidKeyException(
"Key must be OpenSslSlhDsaPublicKey or OpenSslSlhDsaPrivateKey");
if ((key instanceof PrivateKey) && key.getFormat().equals("PKCS#8")) {
byte[] encoded = key.getEncoded();
try {
return engineGeneratePrivate(new PKCS8EncodedKeySpec(encoded));
} catch (InvalidKeySpecException e) {
throw new InvalidKeyException(e);
}
} else if ((key instanceof PublicKey) && key.getFormat().equals("X.509")) {
byte[] encoded = key.getEncoded();
try {
return engineGeneratePublic(new X509EncodedKeySpec(encoded));
} catch (InvalidKeySpecException e) {
throw new InvalidKeyException(e);
}
} else {
throw new InvalidKeyException("Unable to translate key into SLH-DSA key");
}
}
}
18 changes: 2 additions & 16 deletions common/src/main/java/org/conscrypt/OpenSslSlhDsaPrivateKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.PrivateKey;
import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;

/** A SLH-DSA private key. */
Expand All @@ -32,18 +30,6 @@ public class OpenSslSlhDsaPrivateKey implements PrivateKey {

private byte[] raw;

public OpenSslSlhDsaPrivateKey(EncodedKeySpec keySpec) throws InvalidKeySpecException {
byte[] encoded = keySpec.getEncoded();
if ("raw".equalsIgnoreCase(keySpec.getFormat())) {
if (encoded.length != PRIVATE_KEY_SIZE_BYTES) {
throw new InvalidKeySpecException("Invalid key size");
}
raw = encoded;
} else {
throw new InvalidKeySpecException("Encoding must be in raw format");
}
}

public OpenSslSlhDsaPrivateKey(byte[] raw) {
if (raw.length != PRIVATE_KEY_SIZE_BYTES) {
throw new IllegalArgumentException("Invalid key size");
Expand All @@ -58,12 +44,12 @@ public String getAlgorithm() {

@Override
public String getFormat() {
throw new UnsupportedOperationException("getFormat() not yet supported");
return "PKCS#8";
}

@Override
public byte[] getEncoded() {
throw new UnsupportedOperationException("getEncoded() not yet supported");
return ArrayUtils.concat(OpenSslSlhDsaKeyFactory.pkcs8Preamble, raw);
}

byte[] getRaw() {
Expand Down
18 changes: 2 additions & 16 deletions common/src/main/java/org/conscrypt/OpenSslSlhDsaPublicKey.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.security.PublicKey;
import java.security.spec.EncodedKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.util.Arrays;

/** An SLH-DSA public key. */
Expand All @@ -32,18 +30,6 @@ public class OpenSslSlhDsaPublicKey implements PublicKey {

private final byte[] raw;

public OpenSslSlhDsaPublicKey(EncodedKeySpec keySpec) throws InvalidKeySpecException {
byte[] encoded = keySpec.getEncoded();
if ("raw".equalsIgnoreCase(keySpec.getFormat())) {
if (encoded.length != PUBLIC_KEY_SIZE_BYTES) {
throw new InvalidKeySpecException("Invalid key size");
}
raw = encoded;
} else {
throw new InvalidKeySpecException("Encoding must be in raw format");
}
}

public OpenSslSlhDsaPublicKey(byte[] raw) {
if (raw.length != PUBLIC_KEY_SIZE_BYTES) {
throw new IllegalArgumentException("Invalid key size");
Expand All @@ -58,12 +44,12 @@ public String getAlgorithm() {

@Override
public String getFormat() {
throw new UnsupportedOperationException("getFormat() not yet supported");
return "X.509";
}

@Override
public byte[] getEncoded() {
throw new UnsupportedOperationException("getEncoded() not yet supported");
return ArrayUtils.concat(OpenSslSlhDsaKeyFactory.x509Preamble, raw);
}

byte[] getRaw() {
Expand Down
Loading
Loading