Skip to content

Commit

Permalink
HADOOP-17609. Make SM4 support optional for OpenSSL native code. (#3019)
Browse files Browse the repository at this point in the history
Reviewed-by: Steve Loughran <[email protected]>
Reviewed-by: Wei-Chiu Chuang <[email protected]>
  • Loading branch information
iwasakims authored Aug 8, 2024
1 parent b189ef8 commit 2a50911
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,20 @@ private static Transform tokenizeTransformation(String transformation)
}
return new Transform(parts[0], parts[1], parts[2]);
}

public static boolean isSupported(CipherSuite suite) {
Transform transform;
int algMode;
int padding;
try {
transform = tokenizeTransformation(suite.getName());
algMode = AlgMode.get(transform.alg, transform.mode);
padding = Padding.get(transform.padding);
} catch (NoSuchAlgorithmException|NoSuchPaddingException e) {
return false;
}
return isSupportedSuite(algMode, padding);
}

/**
* Initialize this cipher with a key and IV.
Expand Down Expand Up @@ -298,5 +312,7 @@ private native int doFinal(long context, ByteBuffer output, int offset,

private native void clean(long ctx, long engineNum);

private native static boolean isSupportedSuite(int alg, int padding);

public native static String getLibraryName();
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ public OpensslSm4CtrCryptoCodec() {
if (loadingFailureReason != null) {
throw new RuntimeException(loadingFailureReason);
}

if (!OpensslCipher.isSupported(CipherSuite.SM4_CTR_NOPADDING)) {
throw new RuntimeException("The OpenSSL native library is built without SM4 CTR support");
}
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,10 @@ JNIEXPORT void JNICALL Java_org_apache_hadoop_crypto_OpensslCipher_initIDs
#endif

loadAesCtr(env);
#if !defined(OPENSSL_NO_SM4)
loadSm4Ctr(env);
#endif

#if OPENSSL_VERSION_NUMBER >= 0x10101001L
int ret = dlsym_OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
if(!ret) {
Expand All @@ -245,7 +248,7 @@ JNIEXPORT void JNICALL Java_org_apache_hadoop_crypto_OpensslCipher_initIDs
if (jthr) {
(*env)->DeleteLocalRef(env, jthr);
THROW(env, "java/lang/UnsatisfiedLinkError", \
"Cannot find AES-CTR/SM4-CTR support, is your version of Openssl new enough?");
"Cannot find AES-CTR support, is your version of OpenSSL new enough?");
return;
}
}
Expand Down Expand Up @@ -554,3 +557,24 @@ JNIEXPORT jstring JNICALL Java_org_apache_hadoop_crypto_OpensslCipher_getLibrary
}
#endif
}

JNIEXPORT jboolean JNICALL Java_org_apache_hadoop_crypto_OpensslCipher_isSupportedSuite
(JNIEnv *env, jclass clazz, jint alg, jint padding)
{
if (padding != NOPADDING) {
return JNI_FALSE;
}

if (alg == AES_CTR && (dlsym_EVP_aes_256_ctr != NULL && dlsym_EVP_aes_128_ctr != NULL)) {
return JNI_TRUE;
}

if (alg == SM4_CTR) {
#if OPENSSL_VERSION_NUMBER >= 0x10101001L && !defined(OPENSSL_NO_SM4)
if (dlsym_EVP_sm4_ctr != NULL) {
return JNI_TRUE;
}
#endif
}
return JNI_FALSE;
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,31 +106,21 @@ public void testJceAesCtrCryptoCodec() throws Exception {

@Test(timeout=120000)
public void testJceSm4CtrCryptoCodec() throws Exception {
GenericTestUtils.assumeInNativeProfile();
if (!NativeCodeLoader.buildSupportsOpenssl()) {
LOG.warn("Skipping test since openSSL library not loaded");
Assume.assumeTrue(false);
}
conf.set(HADOOP_SECURITY_CRYPTO_CIPHER_SUITE_KEY, "SM4/CTR/NoPadding");
conf.set(HADOOP_SECURITY_CRYPTO_CODEC_CLASSES_SM4_CTR_NOPADDING_KEY,
JceSm4CtrCryptoCodec.class.getName());
conf.set(HADOOP_SECURITY_CRYPTO_JCE_PROVIDER_KEY,
BouncyCastleProvider.PROVIDER_NAME);
Assert.assertEquals(null, OpensslCipher.getLoadingFailureReason());
cryptoCodecTest(conf, seed, 0,
jceSm4CodecClass, jceSm4CodecClass, iv);
cryptoCodecTest(conf, seed, count,
jceSm4CodecClass, jceSm4CodecClass, iv);
cryptoCodecTest(conf, seed, count,
jceSm4CodecClass, opensslSm4CodecClass, iv);
// Overflow test, IV: xx xx xx xx xx xx xx xx ff ff ff ff ff ff ff ff
for(int i = 0; i < 8; i++) {
iv[8 + i] = (byte) 0xff;
}
cryptoCodecTest(conf, seed, count,
jceSm4CodecClass, jceSm4CodecClass, iv);
cryptoCodecTest(conf, seed, count,
jceSm4CodecClass, opensslSm4CodecClass, iv);
}

@Test(timeout=120000)
Expand Down Expand Up @@ -164,6 +154,7 @@ public void testOpensslSm4CtrCryptoCodec() throws Exception {
LOG.warn("Skipping test since openSSL library not loaded");
Assume.assumeTrue(false);
}
Assume.assumeTrue(OpensslCipher.isSupported(CipherSuite.SM4_CTR_NOPADDING));
conf.set(HADOOP_SECURITY_CRYPTO_JCE_PROVIDER_KEY,
BouncyCastleProvider.PROVIDER_NAME);
Assert.assertEquals(null, OpensslCipher.getLoadingFailureReason());
Expand All @@ -181,6 +172,8 @@ public void testOpensslSm4CtrCryptoCodec() throws Exception {
opensslSm4CodecClass, opensslSm4CodecClass, iv);
cryptoCodecTest(conf, seed, count,
opensslSm4CodecClass, jceSm4CodecClass, iv);
cryptoCodecTest(conf, seed, count,
jceSm4CodecClass, opensslSm4CodecClass, iv);
}

private void cryptoCodecTest(Configuration conf, int seed, int count,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
import org.apache.hadoop.crypto.random.OsSecureRandom;
import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
import org.apache.hadoop.test.GenericTestUtils;
import org.junit.Assume;
import org.junit.BeforeClass;
import org.junit.Test;

Expand All @@ -40,6 +41,7 @@ public class TestCryptoStreamsWithOpensslSm4CtrCryptoCodec
@BeforeClass
public static void init() throws Exception {
GenericTestUtils.assumeInNativeProfile();
Assume.assumeTrue(OpensslCipher.isSupported(CipherSuite.SM4_CTR_NOPADDING));
Configuration conf = new Configuration();
conf.set(HADOOP_SECURITY_CRYPTO_CIPHER_SUITE_KEY, "SM4/CTR/NoPadding");
conf.set(HADOOP_SECURITY_CRYPTO_CODEC_CLASSES_SM4_CTR_NOPADDING_KEY,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,14 @@ public void testDoFinalArguments() throws Exception {
"Direct buffer is required", e);
}
}

@Test(timeout=120000)
public void testIsSupportedSuite() throws Exception {
Assume.assumeTrue("Skipping due to falilure of loading OpensslCipher.",
OpensslCipher.getLoadingFailureReason() == null);
Assert.assertFalse("Unknown suite must not be supported.",
OpensslCipher.isSupported(CipherSuite.UNKNOWN));
Assert.assertTrue("AES/CTR/NoPadding is not an optional suite.",
OpensslCipher.isSupported(CipherSuite.AES_CTR_NOPADDING));
}
}

0 comments on commit 2a50911

Please sign in to comment.