Skip to content

Commit 403fa14

Browse files
committed
Cache openssl message digest contexts
It has been identified that when using `OpenSSL` version `3.x` the message digest context initialization is much more expensive than using `OpenSSL` version `1.x`. This update optimizes the use of `OpenSSL` contexts by making use of a simple cache. We will create a second initialized openssl digest context when the message digest cipher is initialized. This second context, defined as `context->cachedInitalizedDigestContext`, will be copied over the working context, `context->ctx`, using the `EVP_MD_CTX_copy_ex` API whenever we wish to re-initalize this cipher. The restoration of a context occurs whenever a cipher is explictly reset or whenever a final digest is computed. Backported from: ibmruntimes/openj9-openjdk-jdk#643 Signed-off by: Jason Katonica <[email protected]>
1 parent 31de43f commit 403fa14

File tree

3 files changed

+81
-24
lines changed

3 files changed

+81
-24
lines changed

closed/src/java.base/share/classes/jdk/crypto/jniprovider/NativeCrypto.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ public final native int DigestComputeAndReset(long context,
218218
int digestOffset,
219219
int digestLen);
220220

221-
public final native void DigestReset(long context);
221+
public final native int DigestReset(long context);
222222

223223
/* Native interfaces shared by CBC and ChaCha20 */
224224

closed/src/java.base/share/classes/sun/security/provider/NativeDigest.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,10 @@
2424
*/
2525
/*
2626
* ===========================================================================
27-
* (c) Copyright IBM Corp. 2018, 2019 All Rights Reserved
27+
* (c) Copyright IBM Corp. 2018, 2023 All Rights Reserved
2828
* ===========================================================================
2929
*/
3030

31-
3231
package sun.security.provider;
3332

3433
import java.security.MessageDigestSpi;
@@ -136,7 +135,10 @@ synchronized protected final void engineReset() {
136135
return;
137136
}
138137

139-
nativeCrypto.DigestReset(context);
138+
int ret = nativeCrypto.DigestReset(context);
139+
if (ret == -1) {
140+
throw new ProviderException("Error in Native Digest Reset");
141+
}
140142
bytesProcessed = 0;
141143
}
142144

closed/src/java.base/share/native/libjncrypto/NativeCrypto.c

Lines changed: 75 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -298,6 +298,7 @@ OSSL_PKCS12_key_gen_t* OSSL_PKCS12_key_gen;
298298
typedef struct OpenSSLMDContext {
299299
EVP_MD_CTX *ctx;
300300
const EVP_MD *digestAlg;
301+
EVP_MD_CTX *cachedInitializedDigestContext;
301302
} OpenSSLMDContext;
302303

303304
/* Handle errors from OpenSSL calls. */
@@ -901,22 +902,38 @@ JNIEXPORT jlong JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_DigestCreateCon
901902
context->ctx = ctx;
902903
context->digestAlg = digestAlg;
903904

905+
/*
906+
* Create a second initialized openssl digest context. This is being done for performance reasons since
907+
* creating and or re-initializing digest contexts later during processing is found to be expensive.
908+
* This second context, context->cachedInitializedDigestContext, will be copied over the working context,
909+
* context->ctx, using the EVP_MD_CTX_copy_ex API whenever we wish to re-initalize this cipher. This occurs
910+
* during an explicit reset of the cipher or whenever a final digest is computed.
911+
*/
912+
context->cachedInitializedDigestContext = (*OSSL_MD_CTX_new)();
913+
if (NULL == context->cachedInitializedDigestContext) {
914+
goto releaseContexts;
915+
}
916+
917+
if (1 != (*OSSL_MD_CTX_copy_ex)(context->cachedInitializedDigestContext, context->ctx)) {
918+
goto releaseContexts;
919+
}
920+
904921
if (0 != copyContext) {
905922
EVP_MD_CTX *contextToCopy = ((OpenSSLMDContext*)(intptr_t)copyContext)->ctx;
906923
if (NULL == contextToCopy) {
907-
(*OSSL_MD_CTX_free)(ctx);
908-
free(context);
909-
return -1;
924+
goto releaseContexts;
910925
}
911926
if (0 == (*OSSL_MD_CTX_copy_ex)(ctx, contextToCopy)) {
912-
printErrors();
913-
(*OSSL_MD_CTX_free)(ctx);
914-
free(context);
915-
return -1;
927+
goto releaseContexts;
916928
}
917929
}
918930

919931
return (jlong)(intptr_t)context;
932+
933+
releaseContexts:
934+
printErrors();
935+
Java_jdk_crypto_jniprovider_NativeCrypto_DigestDestroyContext(env, thisObj, (jlong)(intptr_t)context);
936+
return -1;
920937
}
921938

922939
/*
@@ -928,11 +945,20 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_DigestDestroyCon
928945
(JNIEnv *env, jclass thisObj, jlong c)
929946
{
930947
OpenSSLMDContext *context = (OpenSSLMDContext*)(intptr_t) c;
931-
if ((NULL == context) || (NULL == context->ctx)) {
948+
if (NULL == context) {
932949
return -1;
933950
}
934951

935-
(*OSSL_MD_CTX_free)(context->ctx);
952+
if (NULL != context->ctx) {
953+
(*OSSL_MD_CTX_free)(context->ctx);
954+
context->ctx = NULL;
955+
}
956+
957+
if (NULL != context->cachedInitializedDigestContext) {
958+
(*OSSL_MD_CTX_free)(context->cachedInitializedDigestContext);
959+
context->cachedInitializedDigestContext = NULL;
960+
}
961+
936962
free(context);
937963
return 0;
938964
}
@@ -989,7 +1015,7 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_DigestComputeAnd
9891015
unsigned char* messageNative = NULL;
9901016
unsigned char* digestNative = NULL;
9911017

992-
if ((NULL == context) || (NULL == context->ctx)) {
1018+
if ((NULL == context) || (NULL == context->ctx) || (NULL == context->cachedInitializedDigestContext)) {
9931019
return -1;
9941020
}
9951021

@@ -1021,10 +1047,23 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_DigestComputeAnd
10211047

10221048
(*env)->ReleasePrimitiveArrayCritical(env, digest, digestNative, 0);
10231049

1024-
(*OSSL_MD_CTX_reset)(context->ctx);
1025-
1026-
if (1 != (*OSSL_DigestInit_ex)(context->ctx, context->digestAlg, NULL)) {
1050+
/*
1051+
* Reset the message digest context to the original context. We are then ready to perform
1052+
* digest operations again using a copy of this cached context.
1053+
*/
1054+
if (1 != (*OSSL_MD_CTX_copy_ex)(context->ctx, context->cachedInitializedDigestContext)) {
10271055
printErrors();
1056+
1057+
if (NULL != context->ctx) {
1058+
(*OSSL_MD_CTX_free)(context->ctx);
1059+
context->ctx = NULL;
1060+
}
1061+
1062+
if (NULL != context->cachedInitializedDigestContext) {
1063+
(*OSSL_MD_CTX_free)(context->cachedInitializedDigestContext);
1064+
context->cachedInitializedDigestContext = NULL;
1065+
}
1066+
10281067
return -1;
10291068
}
10301069

@@ -1035,22 +1074,38 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_DigestComputeAnd
10351074
*
10361075
* Class: jdk_crypto_jniprovider_NativeCrypto
10371076
* Method: DigestReset
1038-
* Signature: (J)V
1077+
* Signature: (J)I
10391078
*/
1040-
JNIEXPORT void JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_DigestReset
1079+
JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_DigestReset
10411080
(JNIEnv *env, jclass thisObj, jlong c)
10421081
{
10431082
OpenSSLMDContext *context = (OpenSSLMDContext*)(intptr_t) c;
10441083

1045-
if ((NULL == context) || (NULL == context->ctx)) {
1046-
return;
1084+
if ((NULL == context) || (NULL == context->ctx) || (NULL == context->cachedInitializedDigestContext)) {
1085+
return -1;
10471086
}
10481087

1049-
(*OSSL_MD_CTX_reset)(context->ctx);
1050-
1051-
if (1 != (*OSSL_DigestInit_ex)(context->ctx, context->digestAlg, NULL)) {
1088+
/*
1089+
* Reset the message digest context to the original context. We are then ready to perform
1090+
* digest operations again using a copy of this cached context.
1091+
*/
1092+
if (1 != (*OSSL_MD_CTX_copy_ex)(context->ctx, context->cachedInitializedDigestContext)) {
10521093
printErrors();
1094+
1095+
if (NULL != context->ctx) {
1096+
(*OSSL_MD_CTX_free)(context->ctx);
1097+
context->ctx = NULL;
1098+
}
1099+
1100+
if (NULL != context->cachedInitializedDigestContext) {
1101+
(*OSSL_MD_CTX_free)(context->cachedInitializedDigestContext);
1102+
context->cachedInitializedDigestContext = NULL;
1103+
}
1104+
1105+
return -1;
10531106
}
1107+
1108+
return 0;
10541109
}
10551110

10561111
/*

0 commit comments

Comments
 (0)