Skip to content

Commit edbc986

Browse files
committed
Expand OpenSSL Version granularity
Additional granularity for tracking versions is needed in Native code to make better branching decisions based upon the library versions. Currently, there is differentiation only between <=1.0.x and >=1.1.0. Version 1.1.1 will be supported until 2023-09-11, versions including 1.1.0, 1.0.2, 1.0.1, 1.0.0, and 0.9.8 are no longer supported. We need to add support for separate versions to deprecate/add features in the future. Signed-off-by: Jinhang Zhang <[email protected]>
1 parent ed76bf1 commit edbc986

File tree

3 files changed

+70
-34
lines changed

3 files changed

+70
-34
lines changed

closed/src/java.base/share/classes/jdk/crypto/jniprovider/NativeCrypto.java

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,10 @@ public class NativeCrypto {
4848
public static final int SHA5_384 = 3;
4949
public static final int SHA5_512 = 4;
5050

51+
public static final long OPENSSL_VERSION_1_0_0 = 0x1_00_00_000L;
52+
public static final long OPENSSL_VERSION_1_1_0 = 0x1_01_00_000L;
53+
public static final long OPENSSL_VERSION_3_0_0 = 0x3_00_00_000L;
54+
5155
private static final Cleaner ECKeyCleaner = CleanerFactory.cleaner();
5256

5357
private static final boolean useNativeCrypto = Boolean.parseBoolean(
@@ -60,14 +64,13 @@ private static final class InstanceHolder {
6064
private static final NativeCrypto instance = new NativeCrypto();
6165
}
6266

63-
//ossl_vers:
67+
//ossl_vers will be either:
6468
// -1 : library load failed
65-
// 0 : openssl 1.0.x
66-
// 1 : openssl 1.1.x or newer
67-
private final int ossl_ver;
69+
// or one of the OPENSSL_VERSION_x_x_x constants
70+
private final long ossl_ver;
6871

69-
private static int loadCryptoLibraries() {
70-
int osslVersion;
72+
private static long loadCryptoLibraries() {
73+
long osslVersion;
7174

7275
try {
7376
// load jncrypto JNI library
@@ -91,7 +94,7 @@ private static int loadCryptoLibraries() {
9194

9295
@SuppressWarnings("removal")
9396
private NativeCrypto() {
94-
ossl_ver = AccessController.doPrivileged((PrivilegedAction<Integer>) () -> loadCryptoLibraries()).intValue();
97+
ossl_ver = AccessController.doPrivileged((PrivilegedAction<Long>) () -> loadCryptoLibraries()).longValue();
9598
}
9699

97100
/**
@@ -112,7 +115,7 @@ public static final boolean isAllowedAndLoaded() {
112115
*
113116
* @return the OpenSSL library version if it is available
114117
*/
115-
public static final int getVersionIfAvailable() {
118+
public static final long getVersionIfAvailable() {
116119
/*[IF CRIU_SUPPORT]*/
117120
if (InternalCRIUSupport.isCheckpointAllowed()) {
118121
return -1;
@@ -185,7 +188,8 @@ public void run() {
185188
}
186189

187190
/* Native digest interfaces */
188-
private static final native int loadCrypto(boolean traceEnabled);
191+
192+
private static final native long loadCrypto(boolean trace);
189193

190194
public final native long DigestCreateContext(long nativeBuffer,
191195
int algoIndex);

closed/src/java.base/share/native/libjncrypto/NativeCrypto.c

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/*
22
* ===========================================================================
3-
* (c) Copyright IBM Corp. 2018, 2022 All Rights Reserved
3+
* (c) Copyright IBM Corp. 2018, 2023 All Rights Reserved
44
* ===========================================================================
55
*
66
* This code is free software; you can redistribute it and/or modify it
@@ -29,6 +29,7 @@
2929
#include <openssl/ecdh.h>
3030
#include <openssl/pkcs12.h>
3131

32+
#include <ctype.h>
3233
#include <jni.h>
3334
#include <stdio.h>
3435
#include <stdint.h>
@@ -38,10 +39,15 @@
3839
#include "jdk_crypto_jniprovider_NativeCrypto.h"
3940
#include "NativeCrypto_md.h"
4041

41-
#define OPENSSL_VERSION_1_0 "OpenSSL 1.0."
42-
#define OPENSSL_VERSION_1_1 "OpenSSL 1.1."
42+
#define OPENSSL_VERSION_CODE(major, minor, fix, patch) \
43+
((((jlong)(major)) << 28) | ((minor) << 20) | ((fix) << 12) | (patch))
44+
45+
#define OPENSSL_VERSION_1_0_0 OPENSSL_VERSION_CODE(1, 0, 0, 0)
46+
#define OPENSSL_VERSION_1_1_0 OPENSSL_VERSION_CODE(1, 1, 0, 0)
47+
#define OPENSSL_VERSION_2_0_0 OPENSSL_VERSION_CODE(2, 0, 0, 0)
4348
/* Per new OpenSSL naming convention starting from OpenSSL 3, all major versions are ABI and API compatible. */
44-
#define OPENSSL_VERSION_3_X "OpenSSL 3."
49+
#define OPENSSL_VERSION_3_0_0 OPENSSL_VERSION_CODE(3, 0, 0, 0)
50+
#define OPENSSL_VERSION_4_0_0 OPENSSL_VERSION_CODE(4, 0, 0, 0)
4551

4652
/* needed for OpenSSL 1.0.2 Thread handling routines */
4753
#define CRYPTO_LOCK 1
@@ -261,13 +267,39 @@ static void printErrors(void)
261267
fflush(stderr);
262268
}
263269

270+
/*
271+
* We use a 8 digit map (ABBCCDDD) to represent the version of openssl.
272+
* A is the major version,
273+
* BB is the minor version,
274+
* CC is the fix,
275+
* DDD is the patch that could be present in any version.
276+
* For example, if an openssl version is in this scheme 1.2.3.d
277+
* where major is 1, minor is 2, fix is 3 and patch is d -> 4.
278+
* So the result would be 0x10203004, where A is 1, BB is 02, CC is 03, DDD is 004.
279+
*/
280+
static jlong extractVersionToJlong(const char *astring)
281+
{
282+
long major = 0;
283+
long minor = 0;
284+
long fix = 0;
285+
long patch = 0;
286+
char patch_char = 0;
287+
if (sscanf(astring, "OpenSSL %ld.%ld.%ld%c", &major, &minor, &fix, &patch_char) < 3) {
288+
return -1;
289+
}
290+
if (isalpha(patch_char)) {
291+
patch = tolower(patch_char) - 'a' + 1;
292+
}
293+
return (jlong)OPENSSL_VERSION_CODE(major, minor, fix, patch);
294+
}
295+
264296
static void *crypto_library = NULL;
265297
/*
266298
* Class: jdk_crypto_jniprovider_NativeCrypto
267299
* Method: loadCrypto
268-
* Signature: (Z)I
300+
* Signature: (Z)J
269301
*/
270-
JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto
302+
JNIEXPORT jlong JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto
271303
(JNIEnv *env, jclass thisObj, jboolean trace)
272304
{
273305
char *error;
@@ -276,7 +308,7 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto
276308
/* Determine the version of OpenSSL. */
277309
OSSL_version_t* OSSL_version;
278310
const char * openssl_version;
279-
int ossl_ver;
311+
jlong ossl_ver = 0;
280312

281313
/* Load OpenSSL Crypto library */
282314
crypto_library = load_crypto_library(trace);
@@ -310,7 +342,8 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto
310342
} else {
311343
openssl_version = (*OSSL_version)(0); /* get OPENSSL_VERSION */
312344
/* Ensure the OpenSSL version is "OpenSSL 1.0.x" */
313-
if (0 != strncmp(openssl_version, OPENSSL_VERSION_1_0, strlen(OPENSSL_VERSION_1_0))) {
345+
ossl_ver = extractVersionToJlong(openssl_version);
346+
if (!((OPENSSL_VERSION_1_0_0 <= ossl_ver) && (ossl_ver < OPENSSL_VERSION_1_1_0))) {
314347
if (trace) {
315348
fprintf(stderr, "Error loading OpenSSL: Incompatible OpenSSL version found: %s\n", openssl_version);
316349
fflush(stderr);
@@ -319,13 +352,13 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto
319352
crypto_library = NULL;
320353
return -1;
321354
}
322-
ossl_ver = 0;
323355
}
324356
} else {
325357
openssl_version = (*OSSL_version)(0); /* get OPENSSL_VERSION */
326358
/* Ensure the OpenSSL version is "OpenSSL 1.1.x" or "OpenSSL 3.x.x". */
327-
if ((0 != strncmp(openssl_version, OPENSSL_VERSION_1_1, strlen(OPENSSL_VERSION_1_1)))
328-
&& (0 != strncmp(openssl_version, OPENSSL_VERSION_3_X, strlen(OPENSSL_VERSION_3_X)))
359+
ossl_ver = extractVersionToJlong(openssl_version);
360+
if (!((OPENSSL_VERSION_1_1_0 <= ossl_ver) && (ossl_ver < OPENSSL_VERSION_2_0_0))
361+
&& !((OPENSSL_VERSION_3_0_0 <= ossl_ver) && (ossl_ver < OPENSSL_VERSION_4_0_0))
329362
) {
330363
if (trace) {
331364
fprintf(stderr, "Error loading OpenSSL: Incompatible OpenSSL version found: %s\n", openssl_version);
@@ -335,7 +368,6 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto
335368
crypto_library = NULL;
336369
return -1;
337370
}
338-
ossl_ver = 1;
339371
}
340372

341373
/* Load the function symbols for OpenSSL errors. */
@@ -344,7 +376,7 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto
344376
OSSL_get_error = (OSSL_get_error_t*)find_crypto_symbol(crypto_library, "ERR_get_error");
345377

346378
/* Load Threading routines for OpenSSL 1.0.2 */
347-
if (0 == ossl_ver) {
379+
if (ossl_ver < OPENSSL_VERSION_1_1_0) {
348380
OSSL_CRYPTO_num_locks = (OSSL_CRYPTO_num_locks_t*)find_crypto_symbol(crypto_library, "CRYPTO_num_locks");
349381
OSSL_CRYPTO_THREADID_set_numeric = (OSSL_CRYPTO_THREADID_set_numeric_t*)find_crypto_symbol(crypto_library, "CRYPTO_THREADID_set_numeric");
350382
OSSL_OPENSSL_malloc = (OSSL_OPENSSL_malloc_t*)find_crypto_symbol(crypto_library, "CRYPTO_malloc");
@@ -360,7 +392,7 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto
360392
OSSL_sha384 = (OSSL_sha_t*)find_crypto_symbol(crypto_library, "EVP_sha384");
361393
OSSL_sha512 = (OSSL_sha_t*)find_crypto_symbol(crypto_library, "EVP_sha512");
362394

363-
if (1 == ossl_ver) {
395+
if (ossl_ver >= OPENSSL_VERSION_1_1_0) {
364396
OSSL_MD_CTX_new = (OSSL_MD_CTX_new_t*)find_crypto_symbol(crypto_library, "EVP_MD_CTX_new");
365397
OSSL_MD_CTX_reset = (OSSL_MD_CTX_reset_t*)find_crypto_symbol(crypto_library, "EVP_MD_CTX_reset");
366398
OSSL_MD_CTX_free = (OSSL_MD_CTX_free_t*)find_crypto_symbol(crypto_library, "EVP_MD_CTX_free");
@@ -394,7 +426,7 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto
394426
OSSL_DecryptFinal = (OSSL_DecryptFinal_t*)find_crypto_symbol(crypto_library, "EVP_DecryptFinal");
395427

396428
/* Load the functions symbols for OpenSSL ChaCha20 algorithms. (Need OpenSSL 1.1.x or above) */
397-
if (1 == ossl_ver) {
429+
if (ossl_ver >= OPENSSL_VERSION_1_1_0) {
398430
OSSL_chacha20 = (OSSL_cipher_t*)find_crypto_symbol(crypto_library, "EVP_chacha20");
399431
OSSL_chacha20_poly1305 = (OSSL_cipher_t*)find_crypto_symbol(crypto_library, "EVP_chacha20_poly1305");
400432
} else {
@@ -405,7 +437,7 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto
405437
/* Load the functions symbols for OpenSSL RSA algorithm. */
406438
OSSL_RSA_new = (OSSL_RSA_new_t*)find_crypto_symbol(crypto_library, "RSA_new");
407439

408-
if (1 == ossl_ver) {
440+
if (ossl_ver >= OPENSSL_VERSION_1_1_0) {
409441
OSSL_RSA_set0_key = (OSSL_RSA_set0_key_t*)find_crypto_symbol(crypto_library, "RSA_set0_key");
410442
OSSL_RSA_set0_factors = (OSSL_RSA_set0_factors_t*)find_crypto_symbol(crypto_library, "RSA_set0_factors");
411443
OSSL_RSA_set0_crt_params = (OSSL_RSA_set0_key_t*)find_crypto_symbol(crypto_library, "RSA_set0_crt_params");
@@ -524,14 +556,14 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto
524556
(NULL == OSSL_EC_KEY_check_key) ||
525557
(NULL == OSSL_PKCS12_key_gen) ||
526558
/* Check symbols that are only available in OpenSSL 1.1.x and above */
527-
((1 == ossl_ver) && ((NULL == OSSL_chacha20) || (NULL == OSSL_chacha20_poly1305))) ||
559+
((ossl_ver >= OPENSSL_VERSION_1_1_0) && ((NULL == OSSL_chacha20) || (NULL == OSSL_chacha20_poly1305))) ||
528560
/* Check symbols that are only available in OpenSSL 1.0.x and above */
529-
((NULL == OSSL_CRYPTO_num_locks) && (0 == ossl_ver)) ||
530-
((NULL == OSSL_CRYPTO_THREADID_set_numeric) && (0 == ossl_ver)) ||
531-
((NULL == OSSL_OPENSSL_malloc) && (0 == ossl_ver)) ||
532-
((NULL == OSSL_OPENSSL_free) && (0 == ossl_ver)) ||
533-
((NULL == OSSL_CRYPTO_THREADID_set_callback) && (0 == ossl_ver)) ||
534-
((NULL == OSSL_CRYPTO_set_locking_callback) && (0 == ossl_ver))) {
561+
((NULL == OSSL_CRYPTO_num_locks) && (ossl_ver < OPENSSL_VERSION_1_1_0)) ||
562+
((NULL == OSSL_CRYPTO_THREADID_set_numeric) && (ossl_ver < OPENSSL_VERSION_1_1_0)) ||
563+
((NULL == OSSL_OPENSSL_malloc) && (ossl_ver < OPENSSL_VERSION_1_1_0)) ||
564+
((NULL == OSSL_OPENSSL_free) && (ossl_ver < OPENSSL_VERSION_1_1_0)) ||
565+
((NULL == OSSL_CRYPTO_THREADID_set_callback) && (ossl_ver < OPENSSL_VERSION_1_1_0)) ||
566+
((NULL == OSSL_CRYPTO_set_locking_callback) && (ossl_ver < OPENSSL_VERSION_1_1_0))) {
535567
if (trace) {
536568
fprintf(stderr, "Error loading OpenSSL: One or more of the required symbols are missing in the crypto library: %s\n", openssl_version);
537569
}
@@ -549,7 +581,7 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto
549581
free(library_path);
550582
}
551583
}
552-
if (0 == ossl_ver) {
584+
if (ossl_ver < OPENSSL_VERSION_1_1_0) {
553585
if (0 != thread_setup()) {
554586
unload_crypto_library(crypto_library);
555587
crypto_library = NULL;

src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -336,7 +336,7 @@ void putEntries() {
336336
attrs.clear();
337337
attrs.put("SupportedKeyFormats", "RAW");
338338

339-
if (useNativeChaCha20Cipher && (NativeCrypto.getVersionIfAvailable() >= 1)) {
339+
if (useNativeChaCha20Cipher && (NativeCrypto.getVersionIfAvailable() >= NativeCrypto.OPENSSL_VERSION_1_1_0)) {
340340
ps("Cipher", "ChaCha20",
341341
"com.sun.crypto.provider.NativeChaCha20Cipher$ChaCha20Only",
342342
null, attrs);

0 commit comments

Comments
 (0)