From 996b79a305e49c27b400be692e6aa1ac4f286310 Mon Sep 17 00:00:00 2001 From: WilburZjh Date: Mon, 27 Feb 2023 10:54:27 -0500 Subject: [PATCH] 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 --- .../jdk/crypto/jniprovider/NativeCrypto.java | 21 ++--- .../share/native/libjncrypto/NativeCrypto.c | 80 +++++++++++++------ .../com/sun/crypto/provider/SunJCE.java | 2 +- 3 files changed, 69 insertions(+), 34 deletions(-) diff --git a/closed/src/java.base/share/classes/jdk/crypto/jniprovider/NativeCrypto.java b/closed/src/java.base/share/classes/jdk/crypto/jniprovider/NativeCrypto.java index 37513820d64..635d3225d88 100644 --- a/closed/src/java.base/share/classes/jdk/crypto/jniprovider/NativeCrypto.java +++ b/closed/src/java.base/share/classes/jdk/crypto/jniprovider/NativeCrypto.java @@ -48,6 +48,10 @@ public class NativeCrypto { public static final int SHA5_384 = 3; public static final int SHA5_512 = 4; + public static final long OPENSSL_VERSION_1_0_0 = 0x1_00_00_000L; + public static final long OPENSSL_VERSION_1_1_0 = 0x1_01_00_000L; + public static final long OPENSSL_VERSION_3_0_0 = 0x3_00_00_000L; + private static final Cleaner ECKeyCleaner = CleanerFactory.cleaner(); private static final boolean useNativeCrypto = Boolean.parseBoolean( @@ -60,14 +64,13 @@ private static final class InstanceHolder { private static final NativeCrypto instance = new NativeCrypto(); } - //ossl_vers: + //ossl_vers will be either: // -1 : library load failed - // 0 : openssl 1.0.x - // 1 : openssl 1.1.x or newer - private final int ossl_ver; + // or one of the OPENSSL_VERSION_x_x_x constants + private final long ossl_ver; - private static int loadCryptoLibraries() { - int osslVersion; + private static long loadCryptoLibraries() { + long osslVersion; try { // load jncrypto JNI library @@ -91,7 +94,7 @@ private static int loadCryptoLibraries() { @SuppressWarnings("removal") private NativeCrypto() { - ossl_ver = AccessController.doPrivileged((PrivilegedAction) () -> loadCryptoLibraries()).intValue(); + ossl_ver = AccessController.doPrivileged((PrivilegedAction) () -> loadCryptoLibraries()).longValue(); } /** @@ -112,7 +115,7 @@ public static final boolean isAllowedAndLoaded() { * * @return the OpenSSL library version if it is available */ - public static final int getVersionIfAvailable() { + public static final long getVersionIfAvailable() { /*[IF CRIU_SUPPORT]*/ if (InternalCRIUSupport.isCheckpointAllowed()) { return -1; @@ -186,7 +189,7 @@ public void run() { /* Native digest interfaces */ - private static final native int loadCrypto(boolean trace); + private static final native long loadCrypto(boolean trace); public final native long DigestCreateContext(long nativeBuffer, int algoIndex); diff --git a/closed/src/java.base/share/native/libjncrypto/NativeCrypto.c b/closed/src/java.base/share/native/libjncrypto/NativeCrypto.c index 7c3bbec9db0..c592dac9f46 100644 --- a/closed/src/java.base/share/native/libjncrypto/NativeCrypto.c +++ b/closed/src/java.base/share/native/libjncrypto/NativeCrypto.c @@ -1,6 +1,6 @@ /* * =========================================================================== - * (c) Copyright IBM Corp. 2018, 2022 All Rights Reserved + * (c) Copyright IBM Corp. 2018, 2023 All Rights Reserved * =========================================================================== * * This code is free software; you can redistribute it and/or modify it @@ -29,6 +29,7 @@ #include #include +#include #include #include #include @@ -38,10 +39,15 @@ #include "jdk_crypto_jniprovider_NativeCrypto.h" #include "NativeCrypto_md.h" -#define OPENSSL_VERSION_1_0 "OpenSSL 1.0." -#define OPENSSL_VERSION_1_1 "OpenSSL 1.1." +#define OPENSSL_VERSION_CODE(major, minor, fix, patch) \ + ((((jlong)(major)) << 28) | ((minor) << 20) | ((fix) << 12) | (patch)) + +#define OPENSSL_VERSION_1_0_0 OPENSSL_VERSION_CODE(1, 0, 0, 0) +#define OPENSSL_VERSION_1_1_0 OPENSSL_VERSION_CODE(1, 1, 0, 0) +#define OPENSSL_VERSION_2_0_0 OPENSSL_VERSION_CODE(2, 0, 0, 0) /* Per new OpenSSL naming convention starting from OpenSSL 3, all major versions are ABI and API compatible. */ -#define OPENSSL_VERSION_3_X "OpenSSL 3." +#define OPENSSL_VERSION_3_0_0 OPENSSL_VERSION_CODE(3, 0, 0, 0) +#define OPENSSL_VERSION_4_0_0 OPENSSL_VERSION_CODE(4, 0, 0, 0) /* needed for OpenSSL 1.0.2 Thread handling routines */ #define CRYPTO_LOCK 1 @@ -261,13 +267,39 @@ static void printErrors(void) fflush(stderr); } +/* + * We use a 8 digit map (ABBCCDDD) to represent the version of openssl. + * A is the major version, + * BB is the minor version, + * CC is the fix, + * DDD is the patch that could be present in any version. + * For example, if an openssl version is in this scheme 1.2.3.d + * where major is 1, minor is 2, fix is 3 and patch is d -> 4. + * So the result would be 0x10203004, where A is 1, BB is 02, CC is 03, DDD is 004. + */ +static jlong extractVersionToJlong(const char *astring) +{ + long major = 0; + long minor = 0; + long fix = 0; + long patch = 0; + char patch_char = 0; + if (sscanf(astring, "OpenSSL %ld.%ld.%ld%c", &major, &minor, &fix, &patch_char) < 3) { + return -1; + } + if (isalpha(patch_char)) { + patch = tolower(patch_char) - 'a' + 1; + } + return (jlong)OPENSSL_VERSION_CODE(major, minor, fix, patch); +} + static void *crypto_library = NULL; /* * Class: jdk_crypto_jniprovider_NativeCrypto * Method: loadCrypto - * Signature: (Z)I + * Signature: (Z)J */ -JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto +JNIEXPORT jlong JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto (JNIEnv *env, jclass thisObj, jboolean trace) { char *error; @@ -276,7 +308,7 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto /* Determine the version of OpenSSL. */ OSSL_version_t* OSSL_version; const char * openssl_version; - int ossl_ver; + jlong ossl_ver = 0; /* Load OpenSSL Crypto library */ crypto_library = load_crypto_library(trace); @@ -310,7 +342,8 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto } else { openssl_version = (*OSSL_version)(0); /* get OPENSSL_VERSION */ /* Ensure the OpenSSL version is "OpenSSL 1.0.x" */ - if (0 != strncmp(openssl_version, OPENSSL_VERSION_1_0, strlen(OPENSSL_VERSION_1_0))) { + ossl_ver = extractVersionToJlong(openssl_version); + if (!((OPENSSL_VERSION_1_0_0 <= ossl_ver) && (ossl_ver < OPENSSL_VERSION_1_1_0))) { if (trace) { fprintf(stderr, "Error loading OpenSSL: Incompatible OpenSSL version found: %s\n", openssl_version); fflush(stderr); @@ -319,13 +352,13 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto crypto_library = NULL; return -1; } - ossl_ver = 0; } } else { openssl_version = (*OSSL_version)(0); /* get OPENSSL_VERSION */ /* Ensure the OpenSSL version is "OpenSSL 1.1.x" or "OpenSSL 3.x.x". */ - if ((0 != strncmp(openssl_version, OPENSSL_VERSION_1_1, strlen(OPENSSL_VERSION_1_1))) - && (0 != strncmp(openssl_version, OPENSSL_VERSION_3_X, strlen(OPENSSL_VERSION_3_X))) + ossl_ver = extractVersionToJlong(openssl_version); + if (!((OPENSSL_VERSION_1_1_0 <= ossl_ver) && (ossl_ver < OPENSSL_VERSION_2_0_0)) + && !((OPENSSL_VERSION_3_0_0 <= ossl_ver) && (ossl_ver < OPENSSL_VERSION_4_0_0)) ) { if (trace) { 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 crypto_library = NULL; return -1; } - ossl_ver = 1; } /* Load the function symbols for OpenSSL errors. */ @@ -344,7 +376,7 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto OSSL_get_error = (OSSL_get_error_t*)find_crypto_symbol(crypto_library, "ERR_get_error"); /* Load Threading routines for OpenSSL 1.0.2 */ - if (0 == ossl_ver) { + if (ossl_ver < OPENSSL_VERSION_1_1_0) { OSSL_CRYPTO_num_locks = (OSSL_CRYPTO_num_locks_t*)find_crypto_symbol(crypto_library, "CRYPTO_num_locks"); OSSL_CRYPTO_THREADID_set_numeric = (OSSL_CRYPTO_THREADID_set_numeric_t*)find_crypto_symbol(crypto_library, "CRYPTO_THREADID_set_numeric"); 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 OSSL_sha384 = (OSSL_sha_t*)find_crypto_symbol(crypto_library, "EVP_sha384"); OSSL_sha512 = (OSSL_sha_t*)find_crypto_symbol(crypto_library, "EVP_sha512"); - if (1 == ossl_ver) { + if (ossl_ver >= OPENSSL_VERSION_1_1_0) { OSSL_MD_CTX_new = (OSSL_MD_CTX_new_t*)find_crypto_symbol(crypto_library, "EVP_MD_CTX_new"); OSSL_MD_CTX_reset = (OSSL_MD_CTX_reset_t*)find_crypto_symbol(crypto_library, "EVP_MD_CTX_reset"); 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 OSSL_DecryptFinal = (OSSL_DecryptFinal_t*)find_crypto_symbol(crypto_library, "EVP_DecryptFinal"); /* Load the functions symbols for OpenSSL ChaCha20 algorithms. (Need OpenSSL 1.1.x or above) */ - if (1 == ossl_ver) { + if (ossl_ver >= OPENSSL_VERSION_1_1_0) { OSSL_chacha20 = (OSSL_cipher_t*)find_crypto_symbol(crypto_library, "EVP_chacha20"); OSSL_chacha20_poly1305 = (OSSL_cipher_t*)find_crypto_symbol(crypto_library, "EVP_chacha20_poly1305"); } else { @@ -405,7 +437,7 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto /* Load the functions symbols for OpenSSL RSA algorithm. */ OSSL_RSA_new = (OSSL_RSA_new_t*)find_crypto_symbol(crypto_library, "RSA_new"); - if (1 == ossl_ver) { + if (ossl_ver >= OPENSSL_VERSION_1_1_0) { OSSL_RSA_set0_key = (OSSL_RSA_set0_key_t*)find_crypto_symbol(crypto_library, "RSA_set0_key"); OSSL_RSA_set0_factors = (OSSL_RSA_set0_factors_t*)find_crypto_symbol(crypto_library, "RSA_set0_factors"); 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 (NULL == OSSL_EC_KEY_check_key) || (NULL == OSSL_PKCS12_key_gen) || /* Check symbols that are only available in OpenSSL 1.1.x and above */ - ((1 == ossl_ver) && ((NULL == OSSL_chacha20) || (NULL == OSSL_chacha20_poly1305))) || + ((ossl_ver >= OPENSSL_VERSION_1_1_0) && ((NULL == OSSL_chacha20) || (NULL == OSSL_chacha20_poly1305))) || /* Check symbols that are only available in OpenSSL 1.0.x and above */ - ((NULL == OSSL_CRYPTO_num_locks) && (0 == ossl_ver)) || - ((NULL == OSSL_CRYPTO_THREADID_set_numeric) && (0 == ossl_ver)) || - ((NULL == OSSL_OPENSSL_malloc) && (0 == ossl_ver)) || - ((NULL == OSSL_OPENSSL_free) && (0 == ossl_ver)) || - ((NULL == OSSL_CRYPTO_THREADID_set_callback) && (0 == ossl_ver)) || - ((NULL == OSSL_CRYPTO_set_locking_callback) && (0 == ossl_ver))) { + ((NULL == OSSL_CRYPTO_num_locks) && (ossl_ver < OPENSSL_VERSION_1_1_0)) || + ((NULL == OSSL_CRYPTO_THREADID_set_numeric) && (ossl_ver < OPENSSL_VERSION_1_1_0)) || + ((NULL == OSSL_OPENSSL_malloc) && (ossl_ver < OPENSSL_VERSION_1_1_0)) || + ((NULL == OSSL_OPENSSL_free) && (ossl_ver < OPENSSL_VERSION_1_1_0)) || + ((NULL == OSSL_CRYPTO_THREADID_set_callback) && (ossl_ver < OPENSSL_VERSION_1_1_0)) || + ((NULL == OSSL_CRYPTO_set_locking_callback) && (ossl_ver < OPENSSL_VERSION_1_1_0))) { if (trace) { fprintf(stderr, "Error loading OpenSSL: One or more of the required symbols are missing in the crypto library: %s\n", openssl_version); } @@ -549,7 +581,7 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto free(library_path); } } - if (0 == ossl_ver) { + if (ossl_ver < OPENSSL_VERSION_1_1_0) { if (0 != thread_setup()) { unload_crypto_library(crypto_library); crypto_library = NULL; diff --git a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java index 744f0e559f2..601bade315c 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/SunJCE.java @@ -336,7 +336,7 @@ void putEntries() { attrs.clear(); attrs.put("SupportedKeyFormats", "RAW"); - if (useNativeChaCha20Cipher && (NativeCrypto.getVersionIfAvailable() >= 1)) { + if (useNativeChaCha20Cipher && (NativeCrypto.getVersionIfAvailable() >= NativeCrypto.OPENSSL_VERSION_1_1_0)) { ps("Cipher", "ChaCha20", "com.sun.crypto.provider.NativeChaCha20Cipher$ChaCha20Only", null, attrs);