HADOOP-17609. Make SM4 support optional for OpenSSL native code. (#3019)
Reviewed-by: Steve Loughran <stevel@apache.org> Reviewed-by: Wei-Chiu Chuang <weichiu@apache.org>
This commit is contained in:
parent
b189ef8197
commit
2a50911734
@ -177,6 +177,20 @@ private static Transform tokenizeTransformation(String transformation)
|
|||||||
}
|
}
|
||||||
return new Transform(parts[0], parts[1], parts[2]);
|
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.
|
* Initialize this cipher with a key and IV.
|
||||||
@ -298,5 +312,7 @@ private native int doFinal(long context, ByteBuffer output, int offset,
|
|||||||
|
|
||||||
private native void clean(long ctx, long engineNum);
|
private native void clean(long ctx, long engineNum);
|
||||||
|
|
||||||
|
private native static boolean isSupportedSuite(int alg, int padding);
|
||||||
|
|
||||||
public native static String getLibraryName();
|
public native static String getLibraryName();
|
||||||
}
|
}
|
||||||
|
@ -41,6 +41,10 @@ public OpensslSm4CtrCryptoCodec() {
|
|||||||
if (loadingFailureReason != null) {
|
if (loadingFailureReason != null) {
|
||||||
throw new RuntimeException(loadingFailureReason);
|
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
|
@Override
|
||||||
|
@ -232,7 +232,10 @@ JNIEXPORT void JNICALL Java_org_apache_hadoop_crypto_OpensslCipher_initIDs
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
loadAesCtr(env);
|
loadAesCtr(env);
|
||||||
|
#if !defined(OPENSSL_NO_SM4)
|
||||||
loadSm4Ctr(env);
|
loadSm4Ctr(env);
|
||||||
|
#endif
|
||||||
|
|
||||||
#if OPENSSL_VERSION_NUMBER >= 0x10101001L
|
#if OPENSSL_VERSION_NUMBER >= 0x10101001L
|
||||||
int ret = dlsym_OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
|
int ret = dlsym_OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
|
||||||
if(!ret) {
|
if(!ret) {
|
||||||
@ -245,7 +248,7 @@ JNIEXPORT void JNICALL Java_org_apache_hadoop_crypto_OpensslCipher_initIDs
|
|||||||
if (jthr) {
|
if (jthr) {
|
||||||
(*env)->DeleteLocalRef(env, jthr);
|
(*env)->DeleteLocalRef(env, jthr);
|
||||||
THROW(env, "java/lang/UnsatisfiedLinkError", \
|
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;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -554,3 +557,24 @@ JNIEXPORT jstring JNICALL Java_org_apache_hadoop_crypto_OpensslCipher_getLibrary
|
|||||||
}
|
}
|
||||||
#endif
|
#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;
|
||||||
|
}
|
||||||
|
@ -106,31 +106,21 @@ public void testJceAesCtrCryptoCodec() throws Exception {
|
|||||||
|
|
||||||
@Test(timeout=120000)
|
@Test(timeout=120000)
|
||||||
public void testJceSm4CtrCryptoCodec() throws Exception {
|
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_CIPHER_SUITE_KEY, "SM4/CTR/NoPadding");
|
||||||
conf.set(HADOOP_SECURITY_CRYPTO_CODEC_CLASSES_SM4_CTR_NOPADDING_KEY,
|
conf.set(HADOOP_SECURITY_CRYPTO_CODEC_CLASSES_SM4_CTR_NOPADDING_KEY,
|
||||||
JceSm4CtrCryptoCodec.class.getName());
|
JceSm4CtrCryptoCodec.class.getName());
|
||||||
conf.set(HADOOP_SECURITY_CRYPTO_JCE_PROVIDER_KEY,
|
conf.set(HADOOP_SECURITY_CRYPTO_JCE_PROVIDER_KEY,
|
||||||
BouncyCastleProvider.PROVIDER_NAME);
|
BouncyCastleProvider.PROVIDER_NAME);
|
||||||
Assert.assertEquals(null, OpensslCipher.getLoadingFailureReason());
|
|
||||||
cryptoCodecTest(conf, seed, 0,
|
cryptoCodecTest(conf, seed, 0,
|
||||||
jceSm4CodecClass, jceSm4CodecClass, iv);
|
jceSm4CodecClass, jceSm4CodecClass, iv);
|
||||||
cryptoCodecTest(conf, seed, count,
|
cryptoCodecTest(conf, seed, count,
|
||||||
jceSm4CodecClass, jceSm4CodecClass, iv);
|
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
|
// 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++) {
|
for(int i = 0; i < 8; i++) {
|
||||||
iv[8 + i] = (byte) 0xff;
|
iv[8 + i] = (byte) 0xff;
|
||||||
}
|
}
|
||||||
cryptoCodecTest(conf, seed, count,
|
cryptoCodecTest(conf, seed, count,
|
||||||
jceSm4CodecClass, jceSm4CodecClass, iv);
|
jceSm4CodecClass, jceSm4CodecClass, iv);
|
||||||
cryptoCodecTest(conf, seed, count,
|
|
||||||
jceSm4CodecClass, opensslSm4CodecClass, iv);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(timeout=120000)
|
@Test(timeout=120000)
|
||||||
@ -164,6 +154,7 @@ public void testOpensslSm4CtrCryptoCodec() throws Exception {
|
|||||||
LOG.warn("Skipping test since openSSL library not loaded");
|
LOG.warn("Skipping test since openSSL library not loaded");
|
||||||
Assume.assumeTrue(false);
|
Assume.assumeTrue(false);
|
||||||
}
|
}
|
||||||
|
Assume.assumeTrue(OpensslCipher.isSupported(CipherSuite.SM4_CTR_NOPADDING));
|
||||||
conf.set(HADOOP_SECURITY_CRYPTO_JCE_PROVIDER_KEY,
|
conf.set(HADOOP_SECURITY_CRYPTO_JCE_PROVIDER_KEY,
|
||||||
BouncyCastleProvider.PROVIDER_NAME);
|
BouncyCastleProvider.PROVIDER_NAME);
|
||||||
Assert.assertEquals(null, OpensslCipher.getLoadingFailureReason());
|
Assert.assertEquals(null, OpensslCipher.getLoadingFailureReason());
|
||||||
@ -181,6 +172,8 @@ public void testOpensslSm4CtrCryptoCodec() throws Exception {
|
|||||||
opensslSm4CodecClass, opensslSm4CodecClass, iv);
|
opensslSm4CodecClass, opensslSm4CodecClass, iv);
|
||||||
cryptoCodecTest(conf, seed, count,
|
cryptoCodecTest(conf, seed, count,
|
||||||
opensslSm4CodecClass, jceSm4CodecClass, iv);
|
opensslSm4CodecClass, jceSm4CodecClass, iv);
|
||||||
|
cryptoCodecTest(conf, seed, count,
|
||||||
|
jceSm4CodecClass, opensslSm4CodecClass, iv);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cryptoCodecTest(Configuration conf, int seed, int count,
|
private void cryptoCodecTest(Configuration conf, int seed, int count,
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
import org.apache.hadoop.crypto.random.OsSecureRandom;
|
import org.apache.hadoop.crypto.random.OsSecureRandom;
|
||||||
import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
|
import org.apache.hadoop.fs.CommonConfigurationKeysPublic;
|
||||||
import org.apache.hadoop.test.GenericTestUtils;
|
import org.apache.hadoop.test.GenericTestUtils;
|
||||||
|
import org.junit.Assume;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
@ -40,6 +41,7 @@ public class TestCryptoStreamsWithOpensslSm4CtrCryptoCodec
|
|||||||
@BeforeClass
|
@BeforeClass
|
||||||
public static void init() throws Exception {
|
public static void init() throws Exception {
|
||||||
GenericTestUtils.assumeInNativeProfile();
|
GenericTestUtils.assumeInNativeProfile();
|
||||||
|
Assume.assumeTrue(OpensslCipher.isSupported(CipherSuite.SM4_CTR_NOPADDING));
|
||||||
Configuration conf = new Configuration();
|
Configuration conf = new Configuration();
|
||||||
conf.set(HADOOP_SECURITY_CRYPTO_CIPHER_SUITE_KEY, "SM4/CTR/NoPadding");
|
conf.set(HADOOP_SECURITY_CRYPTO_CIPHER_SUITE_KEY, "SM4/CTR/NoPadding");
|
||||||
conf.set(HADOOP_SECURITY_CRYPTO_CODEC_CLASSES_SM4_CTR_NOPADDING_KEY,
|
conf.set(HADOOP_SECURITY_CRYPTO_CODEC_CLASSES_SM4_CTR_NOPADDING_KEY,
|
||||||
|
@ -107,4 +107,14 @@ public void testDoFinalArguments() throws Exception {
|
|||||||
"Direct buffer is required", e);
|
"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));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user