Skip to content

Commit 960fe83

Browse files
authored
Merge pull request #156 from WilburZjh/newPBE
Use the OpenSSL PKCS12 method for PBE and simplify NativeCrypto property checking
2 parents 82eb91d + caf7fb9 commit 960fe83

File tree

12 files changed

+273
-360
lines changed

12 files changed

+273
-360
lines changed

closed/src/java.base/share/classes/jdk/crypto/jniprovider/NativeCrypto.java

Lines changed: 110 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,18 +33,32 @@
3333
import jdk.internal.reflect.Reflection;
3434
import jdk.internal.reflect.CallerSensitive;
3535

36+
import sun.security.action.GetPropertyAction;
37+
3638
public class NativeCrypto {
3739

40+
/* Define constants for the native digest algorithm indices. */
41+
public static final int SHA1_160 = 0;
42+
public static final int SHA2_224 = 1;
43+
public static final int SHA2_256 = 2;
44+
public static final int SHA5_384 = 3;
45+
public static final int SHA5_512 = 4;
46+
3847
private static final Cleaner ECKeyCleaner = CleanerFactory.cleaner();
3948

49+
private static final boolean useNativeCrypto = Boolean.parseBoolean(
50+
GetPropertyAction.privilegedGetProperty("jdk.nativeCrypto", "true"));
51+
52+
private static final boolean traceEnabled = Boolean.parseBoolean(
53+
GetPropertyAction.privilegedGetProperty("jdk.nativeCryptoTrace", "false"));
54+
4055
//ossl_vers:
4156
// -1 : library load failed
4257
// 0 : openssl 1.0.x
4358
// 1 : openssl 1.1.x or newer
4459
private static final int ossl_ver = AccessController.doPrivileged(
4560
(PrivilegedAction<Integer>) () -> {
4661
int ossl_ver;
47-
boolean traceEnabled = Boolean.getBoolean("jdk.nativeCryptoTrace");
4862

4963
try {
5064
System.loadLibrary("jncrypto"); // check for native library
@@ -69,6 +83,92 @@ public static final int getVersion() {
6983
return ossl_ver;
7084
}
7185

86+
/**
87+
* Check whether native crypto is enabled. Note that, by default, native
88+
* crypto is enabled (the native crypto library implementation is used).
89+
*
90+
* The property 'jdk.nativeCrypto' is used to control enablement of all
91+
* native cryptos (Digest, CBC, GCM, RSA, ChaCha20, EC, and PBE), while
92+
* the given property should be used to control enablement of the given
93+
* native crypto algorithm.
94+
*
95+
* @param property the property used to control enablement of the given
96+
* algorithm
97+
* @param name the name of the class or the algorithm
98+
* @return whether the given native crypto algorithm is enabled
99+
*/
100+
public static final boolean isAlgorithmEnabled(String property, String name) {
101+
return isAlgorithmEnabled(property, name, true, null);
102+
}
103+
104+
/**
105+
* Check whether native crypto is enabled. Note that, by default, native
106+
* crypto is enabled (the native crypto library implementation is used).
107+
*
108+
* The property 'jdk.nativeCrypto' is used to control enablement of all
109+
* native cryptos (Digest, CBC, GCM, RSA, ChaCha20, EC, and PBE), while
110+
* the given property should be used to control enablement of the given
111+
* native crypto algorithm.
112+
*
113+
* This method is used for native cryptos that have additional requirements
114+
* in order to load.
115+
*
116+
* @param property the property used to control enablement of the given
117+
* algorithm
118+
* @param name the name of the class or the algorithm
119+
* @param satisfied whether the additional requirements are met
120+
* @param explanation explanation if the native crypto is not loaded
121+
* due to the additional requirements not being met
122+
* @return whether the given native crypto algorithm is enabled
123+
*/
124+
public static final boolean isAlgorithmEnabled(String property, String name, boolean satisfied, String explanation) {
125+
boolean useNativeAlgorithm = false;
126+
if (useNativeCrypto) {
127+
useNativeAlgorithm = Boolean.parseBoolean(
128+
GetPropertyAction.privilegedGetProperty(property, "true"));
129+
}
130+
if (useNativeAlgorithm) {
131+
/*
132+
* User wants to use the native crypto implementation. Ensure that the
133+
* native crypto library is loaded successfully. Otherwise, issue a warning
134+
* message and fall back to the built-in java crypto implementation.
135+
*/
136+
if (isLoaded()) {
137+
if (satisfied) {
138+
if (traceEnabled) {
139+
System.err.println(name + " - using native crypto library.");
140+
}
141+
} else {
142+
useNativeAlgorithm = false;
143+
if (traceEnabled) {
144+
System.err.println("Warning: " + name + " native requirements not satisfied. " +
145+
explanation + " Using Java crypto implementation.");
146+
}
147+
}
148+
} else {
149+
useNativeAlgorithm = false;
150+
if (traceEnabled) {
151+
System.err.println("Warning: Native crypto library load failed." +
152+
" Using Java crypto implementation.");
153+
}
154+
}
155+
} else {
156+
if (traceEnabled) {
157+
System.err.println(name + " native crypto implementation disabled." +
158+
" Using Java crypto implementation.");
159+
}
160+
}
161+
return useNativeAlgorithm;
162+
}
163+
164+
public static final boolean isEnabled() {
165+
return useNativeCrypto;
166+
}
167+
168+
public static final boolean isTraceEnabled() {
169+
return traceEnabled;
170+
}
171+
72172
private NativeCrypto() {
73173
// empty
74174
}
@@ -295,4 +395,13 @@ public final native int ECDeriveKey(long publicKey,
295395

296396
public final native boolean ECNativeGF2m();
297397

398+
public final native int PBEDerive(byte[] password,
399+
int passwordLength,
400+
byte[] salt,
401+
int saltLength,
402+
byte[] key,
403+
int iterations,
404+
int n,
405+
int id,
406+
int hashAlgorithm);
298407
}

closed/src/java.base/share/classes/sun/security/provider/NativeSHA.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,18 +24,20 @@
2424
*/
2525
/*
2626
* ===========================================================================
27-
* (c) Copyright IBM Corp. 2018, 2019 All Rights Reserved
27+
* (c) Copyright IBM Corp. 2018, 2022 All Rights Reserved
2828
* ===========================================================================
2929
*/
3030

3131
package sun.security.provider;
3232

33+
import jdk.crypto.jniprovider.NativeCrypto;
34+
3335
public final class NativeSHA extends NativeDigest {
3436

3537
/**
3638
* Creates a new native SHA object.
3739
*/
3840
public NativeSHA() {
39-
super("SHA-1", 20, 0);
41+
super("SHA-1", 20, NativeCrypto.SHA1_160);
4042
}
4143
}

closed/src/java.base/share/classes/sun/security/provider/NativeSHA2.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@
2424
*/
2525
/*
2626
* ===========================================================================
27-
* (c) Copyright IBM Corp. 2018, 2019 All Rights Reserved
27+
* (c) Copyright IBM Corp. 2018, 2022 All Rights Reserved
2828
* ===========================================================================
2929
*/
3030

3131
package sun.security.provider;
3232

33+
import jdk.crypto.jniprovider.NativeCrypto;
34+
3335
abstract class NativeSHA2 {
3436

3537
/**
@@ -38,7 +40,7 @@ abstract class NativeSHA2 {
3840
public static final class SHA224 extends NativeDigest {
3941

4042
public SHA224() {
41-
super("SHA-224", 28, 2);
43+
super("SHA-224", 28, NativeCrypto.SHA2_224);
4244
}
4345
}
4446

@@ -48,7 +50,7 @@ public SHA224() {
4850
public static final class SHA256 extends NativeDigest {
4951

5052
public SHA256() {
51-
super("SHA-256", 32, 1);
53+
super("SHA-256", 32, NativeCrypto.SHA2_256);
5254
}
5355
}
5456
}

closed/src/java.base/share/classes/sun/security/provider/NativeSHA5.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,14 @@
2424
*/
2525
/*
2626
* ===========================================================================
27-
* (c) Copyright IBM Corp. 2018, 2019 All Rights Reserved
27+
* (c) Copyright IBM Corp. 2018, 2022 All Rights Reserved
2828
* ===========================================================================
2929
*/
3030

3131
package sun.security.provider;
3232

33+
import jdk.crypto.jniprovider.NativeCrypto;
34+
3335
abstract class NativeSHA5 {
3436

3537
/**
@@ -38,7 +40,7 @@ abstract class NativeSHA5 {
3840
public static final class SHA512 extends NativeDigest {
3941

4042
public SHA512() {
41-
super("SHA-512", 64, 4);
43+
super("SHA-512", 64, NativeCrypto.SHA5_512);
4244
}
4345
}
4446

@@ -48,7 +50,7 @@ public SHA512() {
4850
public static final class SHA384 extends NativeDigest {
4951

5052
public SHA384() {
51-
super("SHA-384", 48, 3);
53+
super("SHA-384", 48, NativeCrypto.SHA5_384);
5254
}
5355
}
5456
}

closed/src/java.base/share/native/libjncrypto/NativeCrypto.c

Lines changed: 84 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include <openssl/err.h>
2828
#include <openssl/rsa.h>
2929
#include <openssl/ecdh.h>
30+
#include <openssl/pkcs12.h>
3031

3132
#include <jni.h>
3233
#include <stdio.h>
@@ -134,6 +135,8 @@ typedef int OSSL_EC_KEY_set_public_key_t(EC_KEY *, const EC_POINT *);
134135
typedef int OSSL_EC_KEY_check_key_t(const EC_KEY *);
135136
typedef int EC_set_public_key_t(EC_KEY *, BIGNUM *, BIGNUM *, int);
136137

138+
typedef int OSSL_PKCS12_key_gen_t(const char *, int, unsigned char *, int, int, int, int, unsigned char *, const EVP_MD *);
139+
137140
typedef int OSSL_CRYPTO_num_locks_t();
138141
typedef void OSSL_CRYPTO_THREADID_set_numeric_t(CRYPTO_THREADID *id, unsigned long val);
139142
typedef void* OSSL_OPENSSL_malloc_t(size_t num);
@@ -235,6 +238,9 @@ OSSL_EC_KEY_set_public_key_t* OSSL_EC_KEY_set_public_key;
235238
OSSL_EC_KEY_check_key_t* OSSL_EC_KEY_check_key;
236239
EC_set_public_key_t* EC_set_public_key;
237240

241+
/* Define pointers for OpenSSL functions to handle PBE algorithm. */
242+
OSSL_PKCS12_key_gen_t* OSSL_PKCS12_key_gen;
243+
238244
/* Structure for OpenSSL Digest context. */
239245
typedef struct OpenSSLMDContext {
240246
EVP_MD_CTX *ctx;
@@ -455,6 +461,9 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto
455461
OSSL_ECGF2M = JNI_TRUE;
456462
}
457463

464+
/* Load the functions symbols for OpenSSL PBE algorithm. */
465+
OSSL_PKCS12_key_gen = (OSSL_PKCS12_key_gen_t*)find_crypto_symbol(crypto_library, "PKCS12_key_gen_uni");
466+
458467
if ((NULL == OSSL_error_string) ||
459468
(NULL == OSSL_error_string_n) ||
460469
(NULL == OSSL_get_error) ||
@@ -513,6 +522,7 @@ JNIEXPORT jint JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_loadCrypto
513522
(NULL == OSSL_BN_CTX_free) ||
514523
(NULL == OSSL_EC_KEY_set_public_key) ||
515524
(NULL == OSSL_EC_KEY_check_key) ||
525+
(NULL == OSSL_PKCS12_key_gen) ||
516526
/* Check symbols that are only available in OpenSSL 1.1.x and above */
517527
((1 == ossl_ver) && ((NULL == OSSL_chacha20) || (NULL == OSSL_chacha20_poly1305))) ||
518528
/* Check symbols that are only available in OpenSSL 1.0.x and above */
@@ -703,19 +713,19 @@ JNIEXPORT jlong JNICALL Java_jdk_crypto_jniprovider_NativeCrypto_DigestCreateCon
703713
OpenSSLMDContext *context = NULL;
704714

705715
switch (algoIdx) {
706-
case 0:
716+
case jdk_crypto_jniprovider_NativeCrypto_SHA1_160:
707717
digestAlg = (*OSSL_sha1)();
708718
break;
709-
case 1:
710-
digestAlg = (*OSSL_sha256)();
711-
break;
712-
case 2:
719+
case jdk_crypto_jniprovider_NativeCrypto_SHA2_224:
713720
digestAlg = (*OSSL_sha224)();
714721
break;
715-
case 3:
722+
case jdk_crypto_jniprovider_NativeCrypto_SHA2_256:
723+
digestAlg = (*OSSL_sha256)();
724+
break;
725+
case jdk_crypto_jniprovider_NativeCrypto_SHA5_384:
716726
digestAlg = (*OSSL_sha384)();
717727
break;
718-
case 4:
728+
case jdk_crypto_jniprovider_NativeCrypto_SHA5_512:
719729
digestAlg = (*OSSL_sha512)();
720730
break;
721731
default:
@@ -2799,3 +2809,70 @@ setECPublicKey(EC_KEY *key, BIGNUM *x, BIGNUM *y, int field)
27992809

28002810
return ret;
28012811
}
2812+
2813+
/* Password-based encryption algorithm.
2814+
*
2815+
* Class: jdk_crypto_jniprovider_NativeCrypto
2816+
* Method: PBEDerive
2817+
* Signature: (J[BI[BI[BIIII)I
2818+
*/
2819+
JNIEXPORT jint JNICALL
2820+
Java_jdk_crypto_jniprovider_NativeCrypto_PBEDerive
2821+
(JNIEnv *env, jclass obj, jbyteArray password, jint passwordLength, jbyteArray salt, jint saltLength, jbyteArray key, jint iterations, jint n, jint id, jint hashAlgorithm)
2822+
{
2823+
const EVP_MD *digestAlgorithm = NULL;
2824+
char *nativePassword = NULL;
2825+
unsigned char *nativeSalt = NULL;
2826+
unsigned char *nativeKey = NULL;
2827+
jint ret = -1;
2828+
2829+
switch (hashAlgorithm) {
2830+
case jdk_crypto_jniprovider_NativeCrypto_SHA1_160:
2831+
digestAlgorithm = (*OSSL_sha1)();
2832+
break;
2833+
case jdk_crypto_jniprovider_NativeCrypto_SHA2_224:
2834+
digestAlgorithm = (*OSSL_sha224)();
2835+
break;
2836+
case jdk_crypto_jniprovider_NativeCrypto_SHA2_256:
2837+
digestAlgorithm = (*OSSL_sha256)();
2838+
break;
2839+
case jdk_crypto_jniprovider_NativeCrypto_SHA5_384:
2840+
digestAlgorithm = (*OSSL_sha384)();
2841+
break;
2842+
case jdk_crypto_jniprovider_NativeCrypto_SHA5_512:
2843+
digestAlgorithm = (*OSSL_sha512)();
2844+
break;
2845+
default:
2846+
goto cleanup;
2847+
}
2848+
2849+
nativePassword = (char*)((*env)->GetPrimitiveArrayCritical(env, password, 0));
2850+
if (NULL == nativePassword) {
2851+
goto cleanup;
2852+
}
2853+
nativeSalt = (unsigned char*)((*env)->GetPrimitiveArrayCritical(env, salt, 0));
2854+
if (NULL == nativeSalt) {
2855+
goto cleanup;
2856+
}
2857+
nativeKey = (unsigned char*)((*env)->GetPrimitiveArrayCritical(env, key, 0));
2858+
if (NULL == nativeKey) {
2859+
goto cleanup;
2860+
}
2861+
2862+
if (1 == (*OSSL_PKCS12_key_gen)(nativePassword, passwordLength, nativeSalt, saltLength, id, iterations, n, nativeKey, digestAlgorithm)) {
2863+
ret = 0;
2864+
}
2865+
2866+
cleanup:
2867+
if (NULL != nativePassword) {
2868+
(*env)->ReleasePrimitiveArrayCritical(env, password, nativePassword, JNI_ABORT);
2869+
}
2870+
if (NULL != nativeSalt) {
2871+
(*env)->ReleasePrimitiveArrayCritical(env, salt, nativeSalt, JNI_ABORT);
2872+
}
2873+
if (NULL != nativeKey) {
2874+
(*env)->ReleasePrimitiveArrayCritical(env, key, nativeKey, JNI_ABORT);
2875+
}
2876+
2877+
return ret;
2878+
}

0 commit comments

Comments
 (0)