Skip to content
This repository has been archived by the owner on Dec 13, 2024. It is now read-only.

Commit

Permalink
Merge pull request #77 from WilburZjh/ExpandOpenSSLVersionGranularity
Browse files Browse the repository at this point in the history
Expand OpenSSL Version granularity
  • Loading branch information
keithc-ca authored Mar 10, 2023
2 parents 9d52294 + 996b79a commit faa8bad
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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
Expand All @@ -91,7 +94,7 @@ private static int loadCryptoLibraries() {

@SuppressWarnings("removal")
private NativeCrypto() {
ossl_ver = AccessController.doPrivileged((PrivilegedAction<Integer>) () -> loadCryptoLibraries()).intValue();
ossl_ver = AccessController.doPrivileged((PrivilegedAction<Long>) () -> loadCryptoLibraries()).longValue();
}

/**
Expand All @@ -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;
Expand Down Expand Up @@ -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);
Expand Down
80 changes: 56 additions & 24 deletions closed/src/java.base/share/native/libjncrypto/NativeCrypto.c
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -29,6 +29,7 @@
#include <openssl/ecdh.h>
#include <openssl/pkcs12.h>

#include <ctype.h>
#include <jni.h>
#include <stdio.h>
#include <stdint.h>
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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);
Expand Down Expand Up @@ -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);
Expand All @@ -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);
Expand All @@ -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. */
Expand All @@ -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");
Expand All @@ -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");
Expand Down Expand Up @@ -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 {
Expand All @@ -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");
Expand Down Expand Up @@ -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);
}
Expand All @@ -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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit faa8bad

Please sign in to comment.