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
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>
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+
264296static 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 ;
0 commit comments