Skip to content

Commit f415407

Browse files
authored
Merge branch 'master' into unwrap_preconditions
2 parents c4e3225 + dd9fb60 commit f415407

15 files changed

Lines changed: 1416 additions & 194 deletions

File tree

.github/workflows/ci.yml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ jobs:
6969
- name: Set up JDK 11 for toolchains
7070
uses: actions/setup-java@v4
7171
with:
72-
distribution: 'zulu'
72+
distribution: 'temurin'
7373
java-version: 11
7474

7575
- name: Set runner-specific environment variables
@@ -313,22 +313,25 @@ jobs:
313313
strategy:
314314
fail-fast: false
315315
matrix:
316-
platform: [ubuntu-latest, macos-13, macos-latest, windows-latest]
316+
platform: [ubuntu-latest, macos-14, macos-latest, windows-latest]
317317
java: [8, 11, 17, 21]
318318
dist: ['temurin', 'zulu']
319319
include:
320320
- platform: ubuntu-latest
321321
separator: ':'
322322
- platform: macos-latest
323323
separator: ':'
324-
- platform: macos-13
324+
- platform: macos-14
325325
separator: ':'
326326
- platform: windows-latest
327327
separator: ';'
328328
exclude: # Not available on Github runners
329329
- platform: macos-latest
330330
java: 8
331331
dist: 'temurin'
332+
- platform: macos-14
333+
java: 8
334+
dist: 'temurin'
332335

333336

334337
runs-on: ${{ matrix.platform }}

common/src/jni/main/cpp/conscrypt/native_crypto.cc

Lines changed: 278 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1233,6 +1233,273 @@ static jlong NativeCrypto_EVP_parse_private_key(JNIEnv* env, jclass, jbyteArray
12331233
return reinterpret_cast<uintptr_t>(pkey.release());
12341234
}
12351235

1236+
static const EVP_PKEY_ALG* GetAlg(int pkeyType) {
1237+
switch (pkeyType) {
1238+
case EVP_PKEY_ED25519:
1239+
return EVP_pkey_ed25519();
1240+
case EVP_PKEY_X25519:
1241+
return EVP_pkey_x25519();
1242+
case EVP_PKEY_ML_DSA_65:
1243+
return EVP_pkey_ml_dsa_65();
1244+
case EVP_PKEY_ML_DSA_87:
1245+
return EVP_pkey_ml_dsa_87();
1246+
default:
1247+
return nullptr;
1248+
}
1249+
}
1250+
1251+
static jlong NativeCrypto_EVP_PKEY_from_private_key_info(JNIEnv* env, jclass,
1252+
jbyteArray key_java_bytes,
1253+
jintArray algs) {
1254+
CHECK_ERROR_QUEUE_ON_RETURN;
1255+
JNI_TRACE("EVP_PKEY_from_private_key_info(_, %p)", algs);
1256+
1257+
if (key_java_bytes == nullptr) {
1258+
conscrypt::jniutil::throwNullPointerException(env, "key_java_bytes == null");
1259+
return 0;
1260+
}
1261+
1262+
ScopedByteArrayRO bytes(env, key_java_bytes);
1263+
if (bytes.get() == nullptr) {
1264+
JNI_TRACE("EVP_PKEY_from_private_key_info => threw exception");
1265+
conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for bytes");
1266+
return 0;
1267+
}
1268+
1269+
size_t num_algs = static_cast<size_t>(env->GetArrayLength(algs));
1270+
if (num_algs == 0) {
1271+
conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
1272+
"algs.length == 0");
1273+
return 0;
1274+
}
1275+
ScopedIntArrayRO algs_ro(env, algs);
1276+
std::vector<const EVP_PKEY_ALG*> alg_pointers(num_algs);
1277+
for (size_t i = 0; i < num_algs; ++i) {
1278+
const EVP_PKEY_ALG* alg = GetAlg(algs_ro.get()[i]);
1279+
if (alg == nullptr) {
1280+
conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
1281+
"unsupported pkeyType");
1282+
return 0;
1283+
}
1284+
alg_pointers[i] = alg;
1285+
}
1286+
1287+
bssl::UniquePtr<EVP_PKEY> pkey(
1288+
EVP_PKEY_from_private_key_info(reinterpret_cast<const uint8_t*>(bytes.get()),
1289+
bytes.size(), alg_pointers.data(), alg_pointers.size()));
1290+
if (pkey.get() == nullptr) {
1291+
conscrypt::jniutil::throwParsingException(env, "Error parsing private key");
1292+
ERR_clear_error();
1293+
JNI_TRACE("EVP_PKEY_from_private_key_info => threw exception");
1294+
return 0;
1295+
}
1296+
1297+
return reinterpret_cast<uintptr_t>(pkey.release());
1298+
}
1299+
1300+
static jlong NativeCrypto_EVP_PKEY_from_subject_public_key_info(JNIEnv* env, jclass,
1301+
jbyteArray key_java_bytes,
1302+
jintArray algs) {
1303+
CHECK_ERROR_QUEUE_ON_RETURN;
1304+
JNI_TRACE("EVP_PKEY_from_subject_public_key_info(%p, %p)", key_java_bytes, algs);
1305+
1306+
if (key_java_bytes == nullptr) {
1307+
conscrypt::jniutil::throwNullPointerException(env, "key_java_bytes == null");
1308+
return 0;
1309+
}
1310+
1311+
ScopedByteArrayRO bytes(env, key_java_bytes);
1312+
if (bytes.get() == nullptr) {
1313+
JNI_TRACE("bytes=%p EVP_PKEY_from_subject_public_key_info => threw exception",
1314+
key_java_bytes);
1315+
conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for bytes");
1316+
return 0;
1317+
}
1318+
1319+
size_t num_algs = static_cast<size_t>(env->GetArrayLength(algs));
1320+
if (num_algs == 0) {
1321+
conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
1322+
"algs.length == 0");
1323+
return 0;
1324+
}
1325+
ScopedIntArrayRO algs_ro(env, algs);
1326+
std::vector<const EVP_PKEY_ALG*> alg_pointers(num_algs);
1327+
for (size_t i = 0; i < num_algs; ++i) {
1328+
const EVP_PKEY_ALG* alg = GetAlg(algs_ro.get()[i]);
1329+
if (alg == nullptr) {
1330+
conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
1331+
"unsupported pkeyType");
1332+
return 0;
1333+
}
1334+
alg_pointers[i] = alg;
1335+
}
1336+
1337+
bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_from_subject_public_key_info(
1338+
reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size(), alg_pointers.data(),
1339+
alg_pointers.size()));
1340+
if (pkey.get() == nullptr) {
1341+
conscrypt::jniutil::throwParsingException(env, "Error parsing public key");
1342+
ERR_clear_error();
1343+
JNI_TRACE("bytes=%p EVP_PKEY_from_subject_public_key_info => threw exception",
1344+
key_java_bytes);
1345+
return 0;
1346+
}
1347+
1348+
JNI_TRACE("bytes=%p EVP_PKEY_from_subject_public_key_info => %p", key_java_bytes, pkey.get());
1349+
return reinterpret_cast<uintptr_t>(pkey.release());
1350+
}
1351+
1352+
static jlong NativeCrypto_EVP_PKEY_from_raw_public_key(JNIEnv* env, jclass, jint pkey_type,
1353+
jbyteArray key_java_bytes) {
1354+
CHECK_ERROR_QUEUE_ON_RETURN;
1355+
JNI_TRACE("EVP_PKEY_from_raw_public_key(%p)", key_java_bytes);
1356+
1357+
if (key_java_bytes == nullptr) {
1358+
conscrypt::jniutil::throwNullPointerException(env, "key_java_bytes == null");
1359+
return 0;
1360+
}
1361+
1362+
ScopedByteArrayRO bytes(env, key_java_bytes);
1363+
if (bytes.get() == nullptr) {
1364+
JNI_TRACE("bytes=%p EVP_PKEY_from_raw_public_key => threw exception", key_java_bytes);
1365+
conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for key_java_bytes");
1366+
return 0;
1367+
}
1368+
1369+
const EVP_PKEY_ALG* alg = GetAlg(pkey_type);
1370+
if (alg == nullptr) {
1371+
conscrypt::jniutil::throwException(env, "java/lang/IllegalArgumentException",
1372+
"unsupported pkeyType");
1373+
return 0;
1374+
}
1375+
1376+
bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_from_raw_public_key(
1377+
alg, reinterpret_cast<const uint8_t*>(bytes.get()), bytes.size()));
1378+
if (!pkey) {
1379+
conscrypt::jniutil::throwParsingException(env, "Error parsing public key");
1380+
ERR_clear_error();
1381+
JNI_TRACE("bytes=%p EVP_PKEY_from_raw_public_key => threw exception", key_java_bytes);
1382+
return 0;
1383+
}
1384+
1385+
JNI_TRACE("bytes=%p EVP_PKEY_from_raw_public_key => %p", key_java_bytes, pkey.get());
1386+
return reinterpret_cast<uintptr_t>(pkey.release());
1387+
}
1388+
1389+
static jbyteArray NativeCrypto_EVP_PKEY_get_raw_public_key(JNIEnv* env, jclass, jobject pkey_ref) {
1390+
CHECK_ERROR_QUEUE_ON_RETURN;
1391+
JNI_TRACE("EVP_PKEY_get_raw_public_key(%p)", pkey_ref);
1392+
1393+
EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkey_ref);
1394+
if (pkey == nullptr) {
1395+
return nullptr;
1396+
}
1397+
1398+
size_t key_length = 0;
1399+
if (EVP_PKEY_get_raw_public_key(pkey, nullptr, &key_length) == 0) {
1400+
conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get_raw_public_key");
1401+
return nullptr;
1402+
}
1403+
1404+
ScopedLocalRef<jbyteArray> raw_key_array(env,
1405+
env->NewByteArray(static_cast<jsize>(key_length)));
1406+
if (raw_key_array.get() == nullptr) {
1407+
JNI_TRACE("EVP_PKEY_get_raw_public_key: creating byte array failed");
1408+
conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for raw_key_array");
1409+
return nullptr;
1410+
}
1411+
ScopedByteArrayRW raw_key(env, raw_key_array.get());
1412+
if (raw_key.get() == nullptr) {
1413+
JNI_TRACE("EVP_PKEY_get_raw_public_key: using byte array failed");
1414+
conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for raw_key");
1415+
return nullptr;
1416+
}
1417+
1418+
if (EVP_PKEY_get_raw_public_key(pkey, reinterpret_cast<uint8_t*>(raw_key.get()), &key_length) ==
1419+
0) {
1420+
conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get_raw_public_key");
1421+
return nullptr;
1422+
}
1423+
return raw_key_array.release();
1424+
}
1425+
1426+
static jlong NativeCrypto_EVP_PKEY_from_private_seed(JNIEnv* env, jclass, jint pkeyType,
1427+
jbyteArray javaSeedBytes) {
1428+
CHECK_ERROR_QUEUE_ON_RETURN;
1429+
JNI_TRACE("EVP_PKEY_from_private_seed(%p)", javaSeedBytes);
1430+
1431+
if (javaSeedBytes == nullptr) {
1432+
JNI_TRACE("EVP_PKEY_from_private_seed => threw exception");
1433+
conscrypt::jniutil::throwNullPointerException(env, "javaSeedBytes == null");
1434+
return 0;
1435+
}
1436+
1437+
ScopedByteArrayRO seed(env, javaSeedBytes);
1438+
if (seed.get() == nullptr) {
1439+
JNI_TRACE("bytes=%p EVP_PKEY_from_private_seed => threw exception", javaSeedBytes);
1440+
conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for seed");
1441+
return 0;
1442+
}
1443+
1444+
const EVP_PKEY_ALG* alg;
1445+
if (pkeyType == EVP_PKEY_ML_DSA_65) {
1446+
alg = EVP_pkey_ml_dsa_65();
1447+
} else if (pkeyType == EVP_PKEY_ML_DSA_87) {
1448+
alg = EVP_pkey_ml_dsa_87();
1449+
} else {
1450+
conscrypt::jniutil::throwInvalidKeyException(env, "unsupported pkeyType");
1451+
return 0;
1452+
}
1453+
1454+
bssl::UniquePtr<EVP_PKEY> pkey(EVP_PKEY_from_private_seed(
1455+
alg, reinterpret_cast<const uint8_t*>(seed.get()), seed.size()));
1456+
1457+
if (!pkey) {
1458+
conscrypt::jniutil::throwParsingException(env, "Error parsing private key");
1459+
ERR_clear_error();
1460+
JNI_TRACE("bytes=%p EVP_PKEY_from_private_seed => threw exception", javaSeedBytes);
1461+
return 0;
1462+
}
1463+
1464+
JNI_TRACE("bytes=%p EVP_PKEY_from_private_seed => %p", javaSeedBytes, pkey.get());
1465+
return reinterpret_cast<uintptr_t>(pkey.release());
1466+
}
1467+
1468+
static jbyteArray NativeCrypto_EVP_PKEY_get_private_seed(JNIEnv* env, jclass cls, jobject pkeyRef) {
1469+
CHECK_ERROR_QUEUE_ON_RETURN;
1470+
JNI_TRACE("EVP_PKEY_get_private_seed(%p)", pkeyRef);
1471+
1472+
EVP_PKEY* pkey = fromContextObject<EVP_PKEY>(env, pkeyRef);
1473+
if (pkey == nullptr) {
1474+
return nullptr;
1475+
}
1476+
1477+
size_t seed_length = 0;
1478+
if (EVP_PKEY_get_private_seed(pkey, nullptr, &seed_length) == 0) {
1479+
conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get_private_seed");
1480+
return nullptr;
1481+
}
1482+
1483+
ScopedLocalRef<jbyteArray> seedArray(env, env->NewByteArray(static_cast<jsize>(seed_length)));
1484+
if (seedArray.get() == nullptr) {
1485+
JNI_TRACE("EVP_PKEY_get_raw_private_key: creating byte array failed");
1486+
conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for seedArray");
1487+
return nullptr;
1488+
}
1489+
ScopedByteArrayRW seed(env, seedArray.get());
1490+
if (seed.get() == nullptr) {
1491+
JNI_TRACE("EVP_PKEY_get_raw_private_key: using byte array failed");
1492+
conscrypt::jniutil::throwOutOfMemory(env, "Unable to allocate buffer for seed");
1493+
return nullptr;
1494+
}
1495+
1496+
if (EVP_PKEY_get_private_seed(pkey, reinterpret_cast<uint8_t*>(seed.get()), &seed_length) ==
1497+
0) {
1498+
conscrypt::jniutil::throwExceptionFromBoringSSLError(env, "EVP_PKEY_get_private_seed");
1499+
return nullptr;
1500+
}
1501+
return seedArray.release();
1502+
}
12361503

12371504
static jbyteArray NativeCrypto_EVP_raw_X25519_private_key(
12381505
JNIEnv* env, jclass cls, jbyteArray keyJavaBytes) {
@@ -3285,9 +3552,11 @@ static jlong evpDigestSignVerifyInit(JNIEnv* env,
32853552
}
32863553
JNI_TRACE("%s(%p, %p, %p) <- ptr", jniName, mdCtx, md, pkey);
32873554

3288-
// For ED25519, md must be null, see
3555+
// Allow md to be null for ED25519, ML_DSA_65, and ML_DSA_87. See
32893556
// https://github.com/google/boringssl/blob/main/include/openssl/evp.h
3290-
if (md == nullptr && (EVP_PKEY_id(pkey) != EVP_PKEY_ED25519)) {
3557+
int pkey_id = EVP_PKEY_id(pkey);
3558+
if (md == nullptr && (pkey_id != EVP_PKEY_ED25519 && pkey_id != EVP_PKEY_ML_DSA_65 &&
3559+
pkey_id != EVP_PKEY_ML_DSA_87)) {
32913560
JNI_TRACE("ctx=%p %s => md == null", mdCtx, jniName);
32923561
conscrypt::jniutil::throwNullPointerException(env, "md == null");
32933562
return 0;
@@ -3985,7 +4254,7 @@ static void NativeCrypto_EVP_CipherInit_ex(JNIEnv* env, jclass, jobject ctxRef,
39854254
encrypting ? 1 : 0);
39864255

39874256
if (ctx == nullptr) {
3988-
JNI_TRACE("EVP_CipherUpdate => ctx == null");
4257+
JNI_TRACE("EVP_CipherInit_ex => ctx == null");
39894258
return;
39904259
}
39914260

@@ -12070,6 +12339,12 @@ static JNINativeMethod sNativeCryptoMethods[] = {
1207012339
CONSCRYPT_NATIVE_METHOD(EVP_PKEY_cmp, "(" REF_EVP_PKEY REF_EVP_PKEY ")I"),
1207112340
CONSCRYPT_NATIVE_METHOD(EVP_marshal_private_key, "(" REF_EVP_PKEY ")[B"),
1207212341
CONSCRYPT_NATIVE_METHOD(EVP_parse_private_key, "([B)J"),
12342+
CONSCRYPT_NATIVE_METHOD(EVP_PKEY_from_private_key_info, "([B[I)J"),
12343+
CONSCRYPT_NATIVE_METHOD(EVP_PKEY_from_subject_public_key_info, "([B[I)J"),
12344+
CONSCRYPT_NATIVE_METHOD(EVP_PKEY_from_raw_public_key, "(I[B)J"),
12345+
CONSCRYPT_NATIVE_METHOD(EVP_PKEY_get_raw_public_key, "(" REF_EVP_PKEY ")[B"),
12346+
CONSCRYPT_NATIVE_METHOD(EVP_PKEY_from_private_seed, "(I[B)J"),
12347+
CONSCRYPT_NATIVE_METHOD(EVP_PKEY_get_private_seed, "(" REF_EVP_PKEY ")[B"),
1207312348
CONSCRYPT_NATIVE_METHOD(EVP_raw_X25519_private_key, "([B)[B"),
1207412349
CONSCRYPT_NATIVE_METHOD(EVP_marshal_public_key, "(" REF_EVP_PKEY ")[B"),
1207512350
CONSCRYPT_NATIVE_METHOD(EVP_parse_public_key, "([B)J"),

common/src/main/java/org/conscrypt/NativeCrypto.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,20 @@ static native long EVP_PKEY_new_RSA(byte[] n, byte[] e, byte[] d, byte[] p, byte
105105

106106
static native byte[] EVP_marshal_public_key(NativeRef.EVP_PKEY pkey);
107107

108+
static native long EVP_PKEY_from_private_key_info(byte[] data, int[] algs)
109+
throws ParsingException;
110+
111+
static native long EVP_PKEY_from_subject_public_key_info(byte[] data, int[] algs)
112+
throws ParsingException;
113+
114+
static native long EVP_PKEY_from_raw_public_key(int type, byte[] data) throws ParsingException;
115+
116+
static native byte[] EVP_PKEY_get_raw_public_key(NativeRef.EVP_PKEY pkey);
117+
118+
static native long EVP_PKEY_from_private_seed(int type, byte[] seed) throws ParsingException;
119+
120+
static native byte[] EVP_PKEY_get_private_seed(NativeRef.EVP_PKEY pkey);
121+
108122
static native byte[] EVP_raw_X25519_private_key(byte[] data)
109123
throws ParsingException, InvalidKeyException;
110124

0 commit comments

Comments
 (0)