diff --git a/src/main/java/org/apache/commons/crypto/cipher/OpenSsl.java b/src/main/java/org/apache/commons/crypto/cipher/OpenSsl.java index c8f3d98ab..922085a29 100644 --- a/src/main/java/org/apache/commons/crypto/cipher/OpenSsl.java +++ b/src/main/java/org/apache/commons/crypto/cipher/OpenSsl.java @@ -45,7 +45,7 @@ final class OpenSsl { /** Currently only support AES/CTR/NoPadding. */ private enum AlgorithmMode { - AES_CTR, AES_CBC, AES_GCM; + AES_CTR, AES_CBC, AES_GCM, SM4_CTR, SM4_CBC; /** * Gets the mode. diff --git a/src/main/native/org/apache/commons/crypto/cipher/OpenSslNative.c b/src/main/native/org/apache/commons/crypto/cipher/OpenSslNative.c index 2204d0a19..3d12b1cea 100644 --- a/src/main/native/org/apache/commons/crypto/cipher/OpenSslNative.c +++ b/src/main/native/org/apache/commons/crypto/cipher/OpenSslNative.c @@ -52,6 +52,8 @@ static EVP_CIPHER * (*dlsym_EVP_aes_128_cbc)(void); static EVP_CIPHER * (*dlsym_EVP_aes_256_gcm)(void); static EVP_CIPHER * (*dlsym_EVP_aes_192_gcm)(void); static EVP_CIPHER * (*dlsym_EVP_aes_128_gcm)(void); +static EVP_CIPHER * (*dlsym_EVP_sm4_ctr)(void); +static EVP_CIPHER * (*dlsym_EVP_sm4_cbc)(void); #endif #ifdef WINDOWS @@ -79,6 +81,8 @@ typedef EVP_CIPHER * (__cdecl *__dlsym_EVP_aes_128_cbc)(void); typedef EVP_CIPHER * (__cdecl *__dlsym_EVP_aes_256_gcm)(void); typedef EVP_CIPHER * (__cdecl *__dlsym_EVP_aes_192_gcm)(void); typedef EVP_CIPHER * (__cdecl *__dlsym_EVP_aes_128_gcm)(void); +typedef EVP_CIPHER * (__cdecl *__dlsym_EVP_sm4_ctr)(void); +typedef EVP_CIPHER * (__cdecl *__dlsym_EVP_sm4_cbc)(void); static __dlsym_EVP_CIPHER_CTX_new dlsym_EVP_CIPHER_CTX_new; static __dlsym_EVP_CIPHER_CTX_free dlsym_EVP_CIPHER_CTX_free; static __dlsym_EVP_CIPHER_CTX_set_padding dlsym_EVP_CIPHER_CTX_set_padding; @@ -99,6 +103,8 @@ static __dlsym_EVP_aes_128_cbc dlsym_EVP_aes_128_cbc; static __dlsym_EVP_aes_256_gcm dlsym_EVP_aes_256_gcm; static __dlsym_EVP_aes_192_gcm dlsym_EVP_aes_192_gcm; static __dlsym_EVP_aes_128_gcm dlsym_EVP_aes_128_gcm; +static __dlsym_EVP_sm4_ctr dlsym_EVP_sm4_ctr; +static __dlsym_EVP_sm4_cbc dlsym_EVP_sm4_cbc; #endif #ifdef UNIX @@ -119,6 +125,8 @@ static void loadAes(JNIEnv *env, HMODULE openssl) LOAD_DYNAMIC_SYMBOL(dlsym_EVP_aes_256_gcm, env, openssl, "EVP_aes_256_gcm"); LOAD_DYNAMIC_SYMBOL(dlsym_EVP_aes_192_gcm, env, openssl, "EVP_aes_192_gcm"); LOAD_DYNAMIC_SYMBOL(dlsym_EVP_aes_128_gcm, env, openssl, "EVP_aes_128_gcm"); + LOAD_DYNAMIC_SYMBOL(dlsym_EVP_sm4_ctr, env, openssl, "EVP_sm4_ctr"); + LOAD_DYNAMIC_SYMBOL(dlsym_EVP_sm4_cbc, env, openssl, "EVP_sm4_cbc"); #endif #ifdef WINDOWS @@ -140,6 +148,10 @@ static void loadAes(JNIEnv *env, HMODULE openssl) env, openssl, "EVP_aes_192_gcm"); LOAD_DYNAMIC_SYMBOL(__dlsym_EVP_aes_128_gcm, dlsym_EVP_aes_128_gcm, \ env, openssl, "EVP_aes_128_gcm"); + LOAD_DYNAMIC_SYMBOL(__dlsym_EVP_sm4_ctr, dlsym_EVP_sm4_ctr, \ + env, openssl, "EVP_sm4_ctr"); + LOAD_DYNAMIC_SYMBOL(__dlsym_EVP_sm4_cbc, dlsym_EVP_sm4_cbc, \ + env, openssl, "EVP_sm4_cbc"); #endif } @@ -276,13 +288,16 @@ static EVP_CIPHER_CTX * get_context(JNIEnv *env, jlong addr) { JNIEXPORT jlong JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_initContext (JNIEnv *env, jclass clazz, jint alg, jint padding) { - if (alg != AES_CTR && alg != AES_CBC && alg != AES_GCM) { + if (alg != AES_CTR && alg != AES_CBC && alg != AES_GCM + && alg != SM4_CTR && alg != SM4_CBC) { THROW(env, "java/security/NoSuchAlgorithmException", NULL); return (jlong)0; } if (!(alg == AES_CTR && padding == NOPADDING) && !(alg == AES_CBC && (padding == NOPADDING|| padding == PKCS5PADDING)) - && !(alg == AES_GCM && padding == NOPADDING)) { + && !(alg == AES_GCM && padding == NOPADDING) + && !(alg == SM4_CTR && (padding == NOPADDING || padding == PKCS5PADDING)) + && !(alg == SM4_CBC && (padding == NOPADDING || padding == PKCS5PADDING))) { THROW(env, "javax/crypto/NoSuchPaddingException", NULL); return (jlong)0; } @@ -308,6 +323,18 @@ JNIEXPORT jlong JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_init return (jlong)0; } + if (dlsym_EVP_sm4_ctr == NULL) { + THROW(env, "java/security/NoSuchAlgorithmException", \ + "Doesn't support SM4 CTR."); + return (jlong)0; + } + + if (dlsym_EVP_sm4_cbc == NULL) { + THROW(env, "java/security/NoSuchAlgorithmException", \ + "Doesn't support SM4 CBC."); + return (jlong)0; + } + EVP_CTX_Wrapper *wrapper = new_context_wrapper(env); return JLONG(wrapper); } @@ -340,6 +367,14 @@ static EVP_CIPHER * getEvpCipher(int alg, int keyLen) } else if (keyLen == KEY_LENGTH_128) { cipher = dlsym_EVP_aes_128_gcm(); } + } else if (alg == SM4_CTR) { + if (keyLen == KEY_LENGTH_128) { + cipher = dlsym_EVP_sm4_ctr(); + } + } else if (alg == SM4_CBC) { + if (keyLen == KEY_LENGTH_128) { + cipher = dlsym_EVP_sm4_cbc(); + } } return cipher; } @@ -386,7 +421,7 @@ JNIEXPORT jlong JNICALL Java_org_apache_commons_crypto_cipher_OpenSslNative_init goto cleanup; } - if (!(alg == AES_CTR || alg == AES_CBC || alg == AES_GCM)) { + if (!(alg == AES_CTR || alg == AES_CBC || alg == AES_GCM || alg == SM4_CTR || alg == SM4_CBC)) { THROW(env, "java/security/NoSuchAlgorithmException", "The algorithm is not supported."); goto cleanup; } diff --git a/src/main/native/org/apache/commons/crypto/org_apache_commons_crypto.h b/src/main/native/org/apache/commons/crypto/org_apache_commons_crypto.h index 4f8561b5a..25b9a6f5a 100644 --- a/src/main/native/org/apache/commons/crypto/org_apache_commons_crypto.h +++ b/src/main/native/org/apache/commons/crypto/org_apache_commons_crypto.h @@ -259,6 +259,8 @@ static FARPROC WINAPI do_version_dlsym(JNIEnv *env, HMODULE handle) { #define AES_CTR 0 #define AES_CBC 1 #define AES_GCM 2 +#define SM4_CTR 3 +#define SM4_CBC 4 #define NOPADDING 0 #define PKCS5PADDING 1