Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Expand OpenSSL Version granularity #652

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
@@ -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 @@ -44,24 +44,27 @@ 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 boolean useNativeCrypto = Boolean.parseBoolean(
GetPropertyAction.privilegedGetProperty("jdk.nativeCrypto", "true"));

private static final boolean traceEnabled = Boolean.parseBoolean(
GetPropertyAction.privilegedGetProperty("jdk.nativeCryptoTrace", "false"));

//ossl_ver:
//ossl_vers will be either:
// -1 : library load failed
// 0 : openssl 1.0.x
// 1 : openssl 1.1.x or newer
// or one of the OPENSSL_VERSION_x_x_x constants
keithc-ca marked this conversation as resolved.
Show resolved Hide resolved
private static final boolean loaded = AccessController.doPrivileged(
(PrivilegedAction<Boolean>) () -> {
Boolean isLoaded = Boolean.FALSE;

try {
System.loadLibrary("jncrypto"); // check for native library
// load OpenSSL crypto library dynamically.
int ossl_ver = loadCrypto(traceEnabled);
long ossl_ver = loadCrypto(traceEnabled);
if (ossl_ver != -1) {
isLoaded = Boolean.TRUE;
}
Expand Down Expand Up @@ -190,7 +193,8 @@ public void run() {
}

/* Native digest interfaces */
private static final native int loadCrypto(boolean traceEnabled);

private static final native long loadCrypto(boolean trace);

public final native long DigestCreateContext(long nativeBuffer,
int algoIndex);
Expand All @@ -213,6 +217,7 @@ public final native int DigestComputeAndReset(long context,
public final native void DigestReset(long context);

/* Native CBC interfaces */

public final native long CBCCreateContext();

public final native int CBCDestroyContext(long context);
Expand All @@ -239,6 +244,7 @@ public final native int CBCFinalEncrypt(long context,
int outputOffset);

/* Native GCM interfaces */

public final native int GCMEncrypt(byte[] key,
int keylen,
byte[] iv,
Expand Down
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 @@ -244,13 +250,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 traceEnabled)
{

Expand All @@ -259,7 +291,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(traceEnabled);
Expand Down Expand Up @@ -293,7 +325,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 (traceEnabled) {
fprintf(stderr, "Incompatable OpenSSL version: %s\n", openssl_version);
fflush(stderr);
Expand All @@ -302,13 +335,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 (traceEnabled) {
fprintf(stderr, "Incompatable OpenSSL version: %s\n", openssl_version);
Expand All @@ -318,7 +351,6 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto
crypto_library = NULL;
return -1;
}
ossl_ver = 1;
}

if (traceEnabled) {
Expand All @@ -332,7 +364,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 @@ -348,7 +380,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 @@ -384,7 +416,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 @@ -502,12 +534,12 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto
(NULL == OSSL_EC_KEY_set_public_key) ||
(NULL == OSSL_EC_KEY_check_key) ||
(NULL == OSSL_PKCS12_key_gen) ||
((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 0
fprintf(stderr, "One or more of the required symbols are missing in the crypto library\n");
fflush(stderr);
Expand All @@ -516,7 +548,7 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto
crypto_library = NULL;
return -1;
} else {
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