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

Expand OpenSSL Version granularity #77

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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