Skip to content

Commit

Permalink
TKSS-1020: Not re-create NativeSM4 instance after doFinal
Browse files Browse the repository at this point in the history
  • Loading branch information
johnshajiang committed Dec 30, 2024
1 parent b7bd1d3 commit 51bf1a0
Show file tree
Hide file tree
Showing 10 changed files with 155 additions and 66 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public class SM4DecrypterPerfTest {
@State(Scope.Benchmark)
public static class DecrypterHolder {

@Param({"KonaCrypto", "KonaCrypto-Native"})
@Param({"KonaCrypto-Native"})
String provider;

@Param({"Small", "Mid", "Big"})
Expand All @@ -84,7 +84,7 @@ public static class DecrypterHolder {
Cipher decrypterCTRNoPadding;
Cipher decrypterGCMNoPadding;

@Setup(Level.Invocation)
@Setup(Level.Trial)
public void setup() throws Exception {
setupCiphertexts();
setupDecrypters();
Expand Down Expand Up @@ -138,8 +138,6 @@ private void setupDecrypters() throws Exception {

decrypterGCMNoPadding = Cipher.getInstance(
"SM4/GCM/NoPadding", provider);
decrypterGCMNoPadding.init(
Cipher.DECRYPT_MODE, SECRET_KEY, GCM_PARAM_SPEC);
}
}

Expand All @@ -154,12 +152,7 @@ private static byte[] data(String dataType) {
}

@Benchmark
public byte[] cbcPadding(DecrypterHolder holder) throws Exception {
return holder.decrypterCBCPadding.doFinal(holder.ciphertextCBCPadding);
}

@Benchmark
public byte[] cbcNoPadding(DecrypterHolder holder) throws Exception {
public byte[] cbc(DecrypterHolder holder) throws Exception {
return holder.decrypterCBCNoPadding.doFinal(holder.ciphertextCBCNoPadding);
}

Expand All @@ -175,6 +168,8 @@ public byte[] ctr(DecrypterHolder holder) throws Exception {

@Benchmark
public byte[] gcm(DecrypterHolder holder) throws Exception {
holder.decrypterGCMNoPadding.init(
Cipher.DECRYPT_MODE, SECRET_KEY, GCM_PARAM_SPEC);
return holder.decrypterGCMNoPadding.doFinal(holder.ciphertextGCMNoPadding);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import java.math.BigInteger;
import java.util.concurrent.TimeUnit;

import static com.tencent.kona.crypto.CryptoUtils.toBytes;
Expand All @@ -45,13 +46,10 @@
public class SM4EncrypterPerfTest {

private static final byte[] KEY = toBytes("0123456789abcdef0123456789abcdef");
private static final byte[] IV = toBytes("00000000000000000000000000000000");
private static final byte[] GCM_IV = toBytes("000000000000000000000000");
private static final byte[] IV = toBytes("10000000000000000000000000000000");

private static final SecretKey SECRET_KEY = new SecretKeySpec(KEY, "SM4");
private static final IvParameterSpec IV_PARAM_SPEC = new IvParameterSpec(IV);
private static final GCMParameterSpec GCM_PARAM_SPEC
= new GCMParameterSpec(Constants.SM4_GCM_TAG_LEN * 8, GCM_IV);

private final static byte[] SMALL_DATA = TestUtils.data(128);
private final static byte[] MEDIUM_DATA = TestUtils.dataKB(1);
Expand All @@ -64,6 +62,8 @@ public class SM4EncrypterPerfTest {
@State(Scope.Benchmark)
public static class EncrypterHolder {

private BigInteger gcmIvValue = BigInteger.ZERO;

@Param({"KonaCrypto", "KonaCrypto-Native"})
String provider;

Expand All @@ -72,21 +72,15 @@ public static class EncrypterHolder {

byte[] data;

Cipher encrypterCBCPadding;
Cipher encrypterCBCNoPadding;
Cipher encrypterECBNoPadding;
Cipher encrypterCTRNoPadding;
Cipher encrypterGCMNoPadding;

@Setup(Level.Invocation)
@Setup(Level.Trial)
public void setup() throws Exception {
data = data(dataType);

encrypterCBCPadding = Cipher.getInstance(
"SM4/CBC/PKCS7Padding", provider);
encrypterCBCPadding.init(
Cipher.ENCRYPT_MODE, SECRET_KEY, IV_PARAM_SPEC);

encrypterCBCNoPadding = Cipher.getInstance(
"SM4/CBC/NoPadding", provider);
encrypterCBCNoPadding.init(
Expand All @@ -104,8 +98,6 @@ public void setup() throws Exception {

encrypterGCMNoPadding = Cipher.getInstance(
"SM4/GCM/NoPadding", provider);
encrypterGCMNoPadding.init(
Cipher.ENCRYPT_MODE, SECRET_KEY, GCM_PARAM_SPEC);
}
}

Expand All @@ -120,12 +112,7 @@ private static byte[] data(String dataType) {
}

@Benchmark
public byte[] cbcPadding(EncrypterHolder holder) throws Exception {
return holder.encrypterCBCPadding.doFinal(holder.data);
}

@Benchmark
public byte[] cbcNoPadding(EncrypterHolder holder) throws Exception {
public byte[] cbc(EncrypterHolder holder) throws Exception {
return holder.encrypterCBCNoPadding.doFinal(holder.data);
}

Expand All @@ -141,6 +128,24 @@ public byte[] ecb(EncrypterHolder holder) throws Exception {

@Benchmark
public byte[] gcm(EncrypterHolder holder) throws Exception {
holder.gcmIvValue = holder.gcmIvValue.add(BigInteger.ONE);
GCMParameterSpec GCM_PARAM_SPEC = new GCMParameterSpec(
Constants.SM4_GCM_TAG_LEN * 8, toByte12(holder.gcmIvValue));
holder.encrypterGCMNoPadding.init(
Cipher.ENCRYPT_MODE, SECRET_KEY, GCM_PARAM_SPEC);
return holder.encrypterGCMNoPadding.doFinal(holder.data);
}

private static byte[] toByte12(BigInteger ivValue) {
byte[] result = new byte[12];

byte[] iv = ivValue.toByteArray();
if (iv.length >= 12) {
System.arraycopy(iv, iv.length - 12, result, 0, 12);
} else {
System.arraycopy(iv, 0, result, 12 - iv.length, iv.length);
}

return result;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -184,7 +184,8 @@ private static void copyNativeLib(String libName, Path libPath)
native long sm4CreateCtx(boolean encrypt, String mode, boolean padding, byte[] key, byte[] iv);
native void sm4FreeCtx(long pointer);
native byte[] sm4Update(long pointer, byte[] in);
native byte[] sm4Final(long pointer);
native byte[] sm4Final(long pointer, byte[] key, byte[] iv);
native int sm4GCMSetIV(long pointer, byte[] iv);
native int sm4GCMUpdateAAD(long pointer, byte[] aad);
native int sm4GCMProcTag(long pointer, byte[] tag);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,20 @@
*/
abstract class NativeSM4 extends NativeRef {

final boolean encrypt;
final Mode mode;
final boolean padding;
final byte[] key;
byte[] iv;

NativeSM4(boolean encrypt, Mode mode, boolean padding, byte[] key, byte[] iv) {
super(createCtx(encrypt, mode, padding, key, iv));

this.encrypt = encrypt;
this.mode = mode;
this.padding = padding;
this.key = key;
this.iv = iv;
}

private static long createCtx(boolean encrypt, Mode mode, boolean padding,
Expand Down Expand Up @@ -69,10 +81,6 @@ private static long createCtx(boolean encrypt, Mode mode, boolean padding,
return nativeCrypto().sm4CreateCtx(encrypt, mode.name, padding, key, iv);
}

NativeSM4(long pointer) {
super(pointer);
}

byte[] update(byte[] data) {
Objects.requireNonNull(data);

Expand All @@ -88,7 +96,7 @@ byte[] update(byte[] data) {
byte[] doFinal() {
byte[] result = pointer == 0
? null
: nativeCrypto().sm4Final(pointer);
: nativeCrypto().sm4Final(pointer, key, iv);
if (result == null) {
throw new IllegalStateException("SM4 final operation failed");
}
Expand Down Expand Up @@ -119,21 +127,13 @@ final static class SM4CBC extends NativeSM4 {
SM4CBC(boolean encrypt, boolean padding, byte[] key, byte[] iv) {
super(encrypt, Mode.CBC, padding, key, iv);
}

SM4CBC(long pointer) {
super(pointer);
}
}

final static class SM4CTR extends NativeSM4 {

SM4CTR(boolean encrypt, byte[] key, byte[] iv) {
super(encrypt, Mode.CTR, false, key, iv);
}

SM4CTR(long pointer) {
super(pointer);
}
}

final static class SM4ECB extends NativeSM4 {
Expand All @@ -142,10 +142,6 @@ final static class SM4ECB extends NativeSM4 {
super(encrypt, Mode.ECB, padding, key, null);
}

SM4ECB(long pointer) {
super(pointer);
}

void processBlock(byte[] in, int inOff, byte[] out, int outOff) {
byte[] inBlock = new byte[SM4_BLOCK_SIZE];
System.arraycopy(in, inOff, inBlock, 0, SM4_BLOCK_SIZE);
Expand All @@ -167,21 +163,32 @@ static class SM4GCM extends NativeSM4 {
void updateAAD(byte[] aad) {
Objects.requireNonNull(aad);

if (pointer != 0) {
nativeCrypto().sm4GCMUpdateAAD(pointer, aad);
} else {
if (pointer == 0
|| nativeCrypto().sm4GCMUpdateAAD(pointer, aad) != OPENSSL_SUCCESS){
throw new IllegalStateException("SM4 updateAAD operation failed");
}
}

@Override
byte[] doFinal() {
try {
return super.doFinal();
} catch (IllegalStateException e) {
byte[] result = pointer == 0
? null
: nativeCrypto().sm4Final(pointer, null, null);
if (result == null) {
throw new IllegalStateException(
new AEADBadTagException("Tag is incorrect"));
}
return result;
}

void setIV(byte[] iv) {
Objects.requireNonNull(iv);

if (pointer == 0
|| nativeCrypto().sm4GCMSetIV(pointer, iv) != OPENSSL_SUCCESS) {
throw new IllegalStateException("SM4 re-init context operation failed");
}

this.iv = iv;
}

byte[] getTag() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,22 +77,28 @@ private void init() {
switch (mode) {
case ECB:
sm4 = new NativeSM4.SM4ECB(!decrypting, padding, key);
SWEEPER.register(this, new SweepNativeRef(sm4));
break;
case CBC:
sm4 = new NativeSM4.SM4CBC(!decrypting, padding, key, iv);
SWEEPER.register(this, new SweepNativeRef(sm4));
break;
case GCM:
gcmLastCipherBlock = new DataWindow(SM4_GCM_TAG_LEN);
sm4 = new NativeSM4.SM4GCM(!decrypting, key, iv);
if (sm4 == null) {
sm4 = new NativeSM4.SM4GCM(!decrypting, key, iv);
SWEEPER.register(this, new SweepNativeRef(sm4));
} else {
((NativeSM4.SM4GCM) sm4).setIV (iv);
}
break;
case CTR:
sm4 = new NativeSM4.SM4CTR(!decrypting, key, iv);
SWEEPER.register(this, new SweepNativeRef(sm4));
break;
default:
throw new IllegalStateException("Unexpected mode: " + mode);
}

SWEEPER.register(this, new SweepNativeRef(sm4));
}

@Override
Expand Down Expand Up @@ -207,9 +213,6 @@ private byte[] doFinal(byte[] input, int offset, int length) {
"Unexpected SM4: " + sm4.getClass());
}

// re-init
init();

return CryptoUtils.concat(updateOut, finalOut);
}

Expand Down
12 changes: 10 additions & 2 deletions kona-crypto/src/main/jni/include/kona/kona_jni.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

39 changes: 38 additions & 1 deletion kona-crypto/src/main/jni/kona_sm4.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ JNIEXPORT jbyteArray JNICALL Java_com_tencent_kona_crypto_provider_nativeImpl_Na
}

JNIEXPORT jbyteArray JNICALL Java_com_tencent_kona_crypto_provider_nativeImpl_NativeCrypto_sm4Final
(JNIEnv* env, jobject thisObj, jlong pointer) {
(JNIEnv* env, jobject thisObj, jlong pointer, jbyteArray key, jbyteArray iv) {
EVP_CIPHER_CTX* ctx = (EVP_CIPHER_CTX*)pointer;
if (ctx == NULL) {
return NULL;
Expand All @@ -164,9 +164,46 @@ JNIEXPORT jbyteArray JNICALL Java_com_tencent_kona_crypto_provider_nativeImpl_Na

OPENSSL_free(out_buf);

// Re-init with the original parameters for the next operations.
jbyte* key_bytes = key ? (*env)->GetByteArrayElements(env, key, NULL) : NULL;
jbyte* iv_bytes = iv ? (*env)->GetByteArrayElements(env, iv, NULL) : NULL;
if (!EVP_CipherInit_ex(ctx, NULL, NULL, (uint8_t*)key_bytes, (uint8_t*)iv_bytes, EVP_CIPHER_CTX_encrypting(ctx))) {
OPENSSL_print_err();
}
if (key != NULL) {
(*env)->ReleaseByteArrayElements(env, key, key_bytes, JNI_ABORT);
}
if (iv_bytes != NULL) {
(*env)->ReleaseByteArrayElements(env, iv, iv_bytes, JNI_ABORT);
}

return out_bytes;
}

JNIEXPORT jint JNICALL Java_com_tencent_kona_crypto_provider_nativeImpl_NativeCrypto_sm4GCMSetIV
(JNIEnv* env, jobject thisObj, jlong pointer, jbyteArray iv) {
EVP_CIPHER_CTX* ctx = (EVP_CIPHER_CTX*)pointer;
if (ctx == NULL) {
return OPENSSL_FAILURE;
}

if (iv == NULL) {
return OPENSSL_FAILURE;
}

jbyte* iv_bytes = (*env)->GetByteArrayElements(env, iv, NULL);

jlong result = OPENSSL_SUCCESS;
if (!EVP_CipherInit_ex(ctx, NULL, NULL, NULL, (uint8_t*)iv_bytes, EVP_CIPHER_CTX_encrypting(ctx))) {
OPENSSL_print_err();
result = OPENSSL_FAILURE;
}

(*env)->ReleaseByteArrayElements(env, iv, iv_bytes, JNI_ABORT);

return (jint)result;
}

JNIEXPORT jint JNICALL Java_com_tencent_kona_crypto_provider_nativeImpl_NativeCrypto_sm4GCMUpdateAAD
(JNIEnv* env, jobject thisObj, jlong pointer, jbyteArray aad) {
EVP_CIPHER_CTX* ctx = (EVP_CIPHER_CTX*)pointer;
Expand Down
Binary file modified kona-crypto/src/main/resources/libKonaCrypto-linux-aarch64.so
Binary file not shown.
Binary file modified kona-crypto/src/main/resources/libKonaCrypto-linux-x86_64.so
Binary file not shown.
Loading

0 comments on commit 51bf1a0

Please sign in to comment.