From 66014df847ce76992658ded3c8c9055577fd41e1 Mon Sep 17 00:00:00 2001 From: Jinhang-Zhang Date: Wed, 20 Apr 2022 13:58:12 -0400 Subject: [PATCH] Add openssl version 3+ support for Linux platforms Signed-off-by: Jinhang Zhang --- .../jdk/crypto/jniprovider/NativeCrypto.java | 16 ++++- .../jdk/crypto/jniprovider/NativeCrypto.c | 62 +++++++++++-------- .../jdk/crypto/jniprovider/NativeCrypto_md.h | 6 +- .../jdk/crypto/jniprovider/NativeCrypto_md.c | 21 ++++++- .../jdk/crypto/jniprovider/NativeCrypto_md.c | 4 +- .../Cipher/AEAD/GCMParameterSpecTest.java | 16 ++++- 6 files changed, 89 insertions(+), 36 deletions(-) diff --git a/closed/adds/jdk/src/share/classes/jdk/crypto/jniprovider/NativeCrypto.java b/closed/adds/jdk/src/share/classes/jdk/crypto/jniprovider/NativeCrypto.java index 94a2d0605f9..96d1c1b521b 100644 --- a/closed/adds/jdk/src/share/classes/jdk/crypto/jniprovider/NativeCrypto.java +++ b/closed/adds/jdk/src/share/classes/jdk/crypto/jniprovider/NativeCrypto.java @@ -1,6 +1,6 @@ /* * =========================================================================== - * (c) Copyright IBM Corp. 2018, 2019 All Rights Reserved + * (c) Copyright IBM Corp. 2018, 2022 All Rights Reserved * =========================================================================== * * This code is free software; you can redistribute it and/or modify it @@ -34,16 +34,26 @@ public class NativeCrypto { + //ossl_ver: + // -1 : library load failed + // 0 : openssl 1.0.x + // 1 : openssl 1.1.x or newer private static final boolean loaded = AccessController.doPrivileged( (PrivilegedAction) () -> { Boolean isLoaded = Boolean.FALSE; + + boolean traceEnabled = Boolean.getBoolean("jdk.nativeCryptoTrace"); try { System.loadLibrary("jncrypto"); // check for native library // load OpenSSL crypto library dynamically. - if (loadCrypto() == 0) { + int ossl_ver = loadCrypto(traceEnabled); + if (ossl_ver != -1) { isLoaded = Boolean.TRUE; } } catch (UnsatisfiedLinkError usle) { + if (traceEnabled) { + System.err.println("UnsatisfiedLinkError: Failure attempting to load jncrypto JNI library"); + } // Return that isLoaded is false (default set above) } @@ -70,7 +80,7 @@ public static NativeCrypto getNativeCrypto() { } /* Native digest interfaces */ - static final native int loadCrypto(); + private static final native int loadCrypto(boolean traceEnabled); public final native long DigestCreateContext(long nativeBuffer, int algoIndex); diff --git a/closed/adds/jdk/src/share/native/jdk/crypto/jniprovider/NativeCrypto.c b/closed/adds/jdk/src/share/native/jdk/crypto/jniprovider/NativeCrypto.c index 6da9e7f0c2c..d705afce4b3 100644 --- a/closed/adds/jdk/src/share/native/jdk/crypto/jniprovider/NativeCrypto.c +++ b/closed/adds/jdk/src/share/native/jdk/crypto/jniprovider/NativeCrypto.c @@ -1,6 +1,6 @@ /* * =========================================================================== - * (c) Copyright IBM Corp. 2018, 2021 All Rights Reserved + * (c) Copyright IBM Corp. 2018, 2022 All Rights Reserved * =========================================================================== * * This code is free software; you can redistribute it and/or modify it @@ -38,6 +38,9 @@ #define OPENSSL_VERSION_1_0 "OpenSSL 1.0." #define OPENSSL_VERSION_1_1 "OpenSSL 1.1." +/* Per new OpenSSL naming convention starting from OpenSSL 3, all major versions are ABI and API compatible. */ +#define OPENSSL_VERSION_3_X "OpenSSL 3." + /* needed for OpenSSL 1.0.2 Thread handling routines */ # define CRYPTO_LOCK 1 @@ -188,10 +191,11 @@ static void *crypto_library = NULL; /* * Class: jdk_crypto_jniprovider_NativeCrypto * Method: loadCrypto - * Signature: ()I + * Signature: (Z)I */ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto - (JNIEnv *env, jclass thisObj){ + (JNIEnv *env, jclass thisObj, jboolean traceEnabled) +{ typedef const char* OSSL_version_t(int); @@ -201,19 +205,20 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto int ossl_ver; /* Load OpenSSL Crypto library */ - crypto_library = load_crypto_library(); + crypto_library = load_crypto_library(traceEnabled); if (NULL == crypto_library) { -#if 0 - fprintf(stderr, " :FAILED TO LOAD OPENSSL CRYPTO LIBRARY\n"); - fflush(stderr); -#endif /* 0 */ + if (traceEnabled) { + fprintf(stderr, " :FAILED TO LOAD OPENSSL CRYPTO LIBRARY\n"); + fflush(stderr); + } return -1; } - /* Different symbols are used by OpenSSL with 1.0 and 1.1. - * The symbol 'OpenSSL_version' is used by OpenSSL 1.1 where as + /* + * Different symbols are used by OpenSSL with 1.0 and 1.1 and later. + * The symbol 'OpenSSL_version' is used by OpenSSL 1.1 and later where as * the symbol "SSLeay_version" is used by OpenSSL 1.0. - * Currently only openssl 1.0.x and 1.1.x are supported. + * Currently only openssl 1.0.x, 1.1.x and 3.x.x are supported. */ OSSL_version = (OSSL_version_t*)find_crypto_symbol(crypto_library, "OpenSSL_version"); @@ -221,10 +226,10 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto OSSL_version = (OSSL_version_t*)find_crypto_symbol(crypto_library, "SSLeay_version"); if (NULL == OSSL_version) { -#if 0 - fprintf(stderr, "Only openssl 1.0.x and 1.1.x are supported\n"); - fflush(stderr); -#endif /* 0 */ + if (traceEnabled) { + fprintf(stderr, "Only OpenSSL 1.0.x, 1.1.x and 3.x are supported\n"); + fflush(stderr); + } unload_crypto_library(crypto_library); crypto_library = NULL; return -1; @@ -232,10 +237,10 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto 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))) { -#if 0 - fprintf(stderr, "Incompatable OpenSSL version: %s\n", openssl_version); - fflush(stderr); -#endif /* 0 */ + if (traceEnabled) { + fprintf(stderr, "Incompatable OpenSSL version: %s\n", openssl_version); + fflush(stderr); + } unload_crypto_library(crypto_library); crypto_library = NULL; return -1; @@ -244,12 +249,14 @@ 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.1.x". */ - if (0 != strncmp(openssl_version,OPENSSL_VERSION_1_1, strlen(OPENSSL_VERSION_1_1))) { -#if 0 - fprintf(stderr, "Incompatable OpenSSL version: %s\n", openssl_version); - fflush(stderr); -#endif /* 0 */ + /* 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))) + ) { + if (traceEnabled) { + fprintf(stderr, "Incompatable OpenSSL version: %s\n", openssl_version); + fflush(stderr); + } unload_crypto_library(crypto_library); crypto_library = NULL; return -1; @@ -257,6 +264,11 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto ossl_ver = 1; } + if (traceEnabled) { + fprintf(stderr, "Supported OpenSSL version: %s\n", openssl_version); + fflush(stderr); + } + /* Load the function symbols for OpenSSL errors. */ OSSL_error_string_n = (OSSL_error_string_n_t*)find_crypto_symbol(crypto_library, "ERR_error_string_n"); OSSL_error_string = (OSSL_error_string_t*)find_crypto_symbol(crypto_library, "ERR_error_string"); diff --git a/closed/adds/jdk/src/share/native/jdk/crypto/jniprovider/NativeCrypto_md.h b/closed/adds/jdk/src/share/native/jdk/crypto/jniprovider/NativeCrypto_md.h index a532a3022fe..4cf9edc0da4 100644 --- a/closed/adds/jdk/src/share/native/jdk/crypto/jniprovider/NativeCrypto_md.h +++ b/closed/adds/jdk/src/share/native/jdk/crypto/jniprovider/NativeCrypto_md.h @@ -1,6 +1,6 @@ /* * =========================================================================== - * (c) Copyright IBM Corp. 2019, 2019 All Rights Reserved + * (c) Copyright IBM Corp. 2019, 2022 All Rights Reserved * =========================================================================== * * This code is free software; you can redistribute it and/or modify it @@ -25,7 +25,9 @@ #ifndef NATIVECRYPTO_MD_H #define NATIVECRYPTO_MD_H -void * load_crypto_library(); +#include + +void * load_crypto_library(jboolean traceEnabled); void unload_crypto_library(void *handle); void * find_crypto_symbol(void *handle, const char *symname); diff --git a/closed/adds/jdk/src/solaris/native/jdk/crypto/jniprovider/NativeCrypto_md.c b/closed/adds/jdk/src/solaris/native/jdk/crypto/jniprovider/NativeCrypto_md.c index be4db98b656..febf7b773de 100644 --- a/closed/adds/jdk/src/solaris/native/jdk/crypto/jniprovider/NativeCrypto_md.c +++ b/closed/adds/jdk/src/solaris/native/jdk/crypto/jniprovider/NativeCrypto_md.c @@ -1,6 +1,6 @@ /* * =========================================================================== - * (c) Copyright IBM Corp. 2019, 2019 All Rights Reserved + * (c) Copyright IBM Corp. 2019, 2022 All Rights Reserved * =========================================================================== * * This code is free software; you can redistribute it and/or modify it @@ -29,13 +29,18 @@ #include #include "NativeCrypto_md.h" +#if defined(__linux__) +#include +#endif /* defined(__linux__) */ + /* Load the crypto library (return NULL on error) */ -void * load_crypto_library() { +void * load_crypto_library(jboolean traceEnabled) +{ void * result = NULL; int flags = RTLD_NOW; size_t i = 0; - // Library names for OpenSSL 1.1.1, 1.1.0, 1.0.2 and symbolic links + // Library names for OpenSSL 3.x, 1.1.1, 1.1.0, 1.0.2 and symbolic links static const char * const libNames[] = { #if defined(_AIX) "libcrypto.a(libcrypto64.so.1.1)", @@ -47,6 +52,7 @@ void * load_crypto_library() { "libcrypto.1.0.0.dylib", "libcrypto.dylib" #else + "libcrypto.so.3", // 3.x library name "libcrypto.so.1.1", "libcrypto.so.1.0.0", "libcrypto.so.10", @@ -67,6 +73,15 @@ void * load_crypto_library() { result = dlopen (libName, flags); } +#if defined(__linux__) + if (traceEnabled && (NULL != result)) { + struct link_map *map = NULL; + dlinfo(result, RTLD_DI_LINKMAP, &map); + fprintf(stderr, "Attempt to load OpenSSL %s\n", map->l_name); + fflush(stderr); + } +#endif /* defined(__linux__) */ + return result; } diff --git a/closed/adds/jdk/src/windows/native/jdk/crypto/jniprovider/NativeCrypto_md.c b/closed/adds/jdk/src/windows/native/jdk/crypto/jniprovider/NativeCrypto_md.c index 1876ac42196..67c2a9df208 100644 --- a/closed/adds/jdk/src/windows/native/jdk/crypto/jniprovider/NativeCrypto_md.c +++ b/closed/adds/jdk/src/windows/native/jdk/crypto/jniprovider/NativeCrypto_md.c @@ -1,6 +1,6 @@ /* * =========================================================================== - * (c) Copyright IBM Corp. 2019, 2019 All Rights Reserved + * (c) Copyright IBM Corp. 2019, 2022 All Rights Reserved * =========================================================================== * * This code is free software; you can redistribute it and/or modify it @@ -37,7 +37,7 @@ static jboolean GetApplicationHome(char *buf, jint bufsize); static int JLI_Snprintf(char* buffer, size_t size, const char* format, ...); /* Load the crypto library (return NULL on error) */ -void * load_crypto_library() { +void * load_crypto_library(jboolean traceEnabled) { void * result = NULL; const char *libname; const char *oldname = "libeay32.dll"; diff --git a/jdk/test/com/sun/crypto/provider/Cipher/AEAD/GCMParameterSpecTest.java b/jdk/test/com/sun/crypto/provider/Cipher/AEAD/GCMParameterSpecTest.java index 7250c4d7f0f..eea64ee77dc 100644 --- a/jdk/test/com/sun/crypto/provider/Cipher/AEAD/GCMParameterSpecTest.java +++ b/jdk/test/com/sun/crypto/provider/Cipher/AEAD/GCMParameterSpecTest.java @@ -21,6 +21,12 @@ * questions. */ +/* + * =========================================================================== + * (c) Copyright IBM Corp. 2022, 2022 All Rights Reserved + * =========================================================================== + */ + import java.security.NoSuchAlgorithmException; import java.security.NoSuchProviderException; import java.util.Arrays; @@ -36,7 +42,15 @@ */ public class GCMParameterSpecTest { - private static final int[] IV_LENGTHS = { 96, 8, 1024 }; + /* + * OpenSSL3 only supports IV lengths up to 16 bytes. + * When the IV length is set to be larger than 16 bytes, an error is thrown. + * According to the OpenSSL docs([1]), in OpenSSL1.1.1 and older, there is + * no error thrown but unpredictable behavior will happen for large IV sizes. + * + * [1] https://www.openssl.org/docs/man1.1.1/man3/EVP_CIPHER_CTX_block_size.html + */ + private static final int[] IV_LENGTHS = { 96, 8 }; private static final int[] KEY_LENGTHS = { 128, 192, 256 }; private static final int[] DATA_LENGTHS = { 0, 128, 1024 }; private static final int[] AAD_LENGTHS = { 0, 128, 1024 };