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

Optimize ChaCha20-Poly1305 initialization #249

Merged
merged 1 commit into from
Sep 6, 2023
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 @@ -24,7 +24,7 @@
*/
/*
* ===========================================================================
* (c) Copyright IBM Corp. 2018, 2021 All Rights Reserved
* (c) Copyright IBM Corp. 2018, 2023 All Rights Reserved
* ===========================================================================
*/
package com.sun.crypto.provider;
Expand Down Expand Up @@ -93,6 +93,9 @@ abstract class NativeChaCha20Cipher extends CipherSpi {
private static final Cleaner contextCleaner;
private final long context;

// The previous mode, initialized to an illegal value.
private int prevMode = Cipher.WRAP_MODE;

private final ByteArrayOutputStream aadBuf;

static {
Expand Down Expand Up @@ -600,7 +603,18 @@ private void init(int opmode, Key key, byte[] newNonce)
aadDone = false;
initialized = true;

int ret = nativeCrypto.ChaCha20Init(context, ossl_mode, openssl_iv, openssl_iv.length, keyBytes, keyBytes.length);
// Optimize the initialization of chacha20-poly1305 when they have the same ossl_mode
// otherwise, we have to reinitialize based upon the ossl_mode.
int ret;
if (prevMode == ossl_mode) {
ret = nativeCrypto.ChaCha20Init(context, ossl_mode, openssl_iv, openssl_iv.length, keyBytes, keyBytes.length, true);
} else {
ret = nativeCrypto.ChaCha20Init(context, ossl_mode, openssl_iv, openssl_iv.length, keyBytes, keyBytes.length, false);
prevMode = ossl_mode;
}
if (ret == -1) {
throw new ProviderException("Error in Native ChaCha20Cipher");
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -321,7 +321,8 @@ public final native int ChaCha20Init(long context,
byte[] iv,
int ivlen,
byte[] key,
int keylen);
int keylen,
boolean doReset);

public final native int ChaCha20Update(long context,
byte[] input,
Expand Down
28 changes: 18 additions & 10 deletions closed/src/java.base/share/native/libjncrypto/NativeCrypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -2153,11 +2153,11 @@ int OSSL102_RSA_set0_crt_params(RSA *r2, BIGNUM *dmp1, BIGNUM *dmq1, BIGNUM *iqm
/*
* Class: jdk_crypto_jniprovider_NativeCrypto
* Method: ChaCha20Init
* Signature: (JI[BI[BI)I
* Signature: (JI[BI[BIZ)I
*/
JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_ChaCha20Init
(JNIEnv *env, jobject thisObj, jlong c, jint mode, jbyteArray iv, jint ivLen,
jbyteArray key, jint key_len)
jbyteArray key, jint key_len, jboolean doReset)
{
EVP_CIPHER_CTX *ctx = (EVP_CIPHER_CTX*)(intptr_t) c;
unsigned char *ivNative = NULL;
Expand All @@ -2170,12 +2170,18 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_ChaCha20Init
}

if ((0 == mode) || (1 == mode)) {
evp_cipher1 = (*OSSL_chacha20_poly1305)();
/* Use the existing evp_cipher? */
if (JNI_FALSE == doReset) {
evp_cipher1 = (*OSSL_chacha20_poly1305)();
}
encrypt = mode;
} else if (2 == mode) {
/* Use the existing evp_cipher? */
if (JNI_FALSE == doReset) {
evp_cipher1 = (*OSSL_chacha20)();
}
/* encrypt or decrypt does not matter */
encrypt = 1;
evp_cipher1 = (*OSSL_chacha20)();
} else {
return -1;
}
Expand All @@ -2200,12 +2206,14 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_ChaCha20Init
}

/* if using Poly1305 */
if (2 != mode) {
if (1 != (*OSSL_CIPHER_CTX_ctrl)(ctx, EVP_CTRL_AEAD_SET_IVLEN, ivLen, NULL)) {
printErrors();
(*env)->ReleaseByteArrayElements(env, iv, (jbyte*)ivNative, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, key, (jbyte*)keyNative, JNI_ABORT);
return -1;
if (JNI_FALSE == doReset) {
if (2 != mode) {
if (1 != (*OSSL_CIPHER_CTX_ctrl)(ctx, EVP_CTRL_AEAD_SET_IVLEN, ivLen, NULL)) {
printErrors();
(*env)->ReleaseByteArrayElements(env, iv, (jbyte*)ivNative, JNI_ABORT);
(*env)->ReleaseByteArrayElements(env, key, (jbyte*)keyNative, JNI_ABORT);
return -1;
}
}
}

Expand Down