8031340: Better TLS/EC management
Summary: Make sure private key structure is freed for EC key pair generation
Reviewed-by: vinnie
--- a/jdk/make/mapfiles/libsunec/mapfile-vers Tue Feb 25 19:48:47 2014 +0400
+++ b/jdk/make/mapfiles/libsunec/mapfile-vers Wed Feb 26 18:56:33 2014 +0000
@@ -28,10 +28,9 @@
SUNWprivate_1.1 {
global:
Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair;
- Java_sun_security_ec_ECKeyPairGenerator_getEncodedBytes;
- Java_sun_security_ec_ECDSASignature_signDigest;
- Java_sun_security_ec_ECDSASignature_verifySignedDigest;
- Java_sun_security_ec_ECDHKeyAgreement_deriveKey;
+ Java_sun_security_ec_ECDSASignature_signDigest;
+ Java_sun_security_ec_ECDSASignature_verifySignedDigest;
+ Java_sun_security_ec_ECDHKeyAgreement_deriveKey;
local:
*;
};
--- a/jdk/src/share/classes/sun/security/ec/ECKeyPairGenerator.java Tue Feb 25 19:48:47 2014 +0400
+++ b/jdk/src/share/classes/sun/security/ec/ECKeyPairGenerator.java Wed Feb 26 18:56:33 2014 +0000
@@ -125,19 +125,18 @@
try {
- long[] handles = generateECKeyPair(keySize, encodedParams, seed);
+ Object[] keyBytes = generateECKeyPair(keySize, encodedParams, seed);
// The 'params' object supplied above is equivalent to the native
// one so there is no need to fetch it.
-
- // handles[0] points to the native private key
- BigInteger s = new BigInteger(1, getEncodedBytes(handles[0]));
+ // keyBytes[0] is the encoding of the native private key
+ BigInteger s = new BigInteger(1, (byte[])keyBytes[0]);
PrivateKey privateKey =
new ECPrivateKeyImpl(s, (ECParameterSpec)params);
- // handles[1] points to the native public key
- ECPoint w = ECUtil.decodePoint(getEncodedBytes(handles[1]),
+ // keyBytes[1] is the encoding of the native public key
+ ECPoint w = ECUtil.decodePoint((byte[])keyBytes[1],
((ECParameterSpec)params).getCurve());
PublicKey publicKey =
new ECPublicKeyImpl(w, (ECParameterSpec)params);
@@ -162,14 +161,9 @@
}
/*
- * Generates the keypair and returns a 2-element array of handles.
- * The first handle points to the private key, the second to the public key.
+ * Generates the keypair and returns a 2-element array of encoding bytes.
+ * The first one is for the private key, the second for the public key.
*/
- private static native long[] generateECKeyPair(int keySize,
+ private static native Object[] generateECKeyPair(int keySize,
byte[] encodedParams, byte[] seed) throws GeneralSecurityException;
-
- /*
- * Extracts the encoded key data using the supplied handle.
- */
- private static native byte[] getEncodedBytes(long handle);
}
--- a/jdk/src/share/native/sun/security/ec/ECC_JNI.cpp Tue Feb 25 19:48:47 2014 +0400
+++ b/jdk/src/share/native/sun/security/ec/ECC_JNI.cpp Wed Feb 26 18:56:33 2014 +0000
@@ -66,22 +66,39 @@
free(ecparams);
}
+jbyteArray getEncodedBytes(JNIEnv *env, SECItem *hSECItem)
+{
+ SECItem *s = (SECItem *)hSECItem;
+
+ jbyteArray jEncodedBytes = env->NewByteArray(s->len);
+ if (jEncodedBytes == NULL) {
+ return NULL;
+ }
+ // Copy bytes from a native SECItem buffer to Java byte array
+ env->SetByteArrayRegion(jEncodedBytes, 0, s->len, (jbyte *)s->data);
+ if (env->ExceptionCheck()) { // should never happen
+ return NULL;
+ }
+ return jEncodedBytes;
+}
+
/*
* Class: sun_security_ec_ECKeyPairGenerator
* Method: generateECKeyPair
- * Signature: (I[B[B)[J
+ * Signature: (I[B[B)[[B
*/
-JNIEXPORT jlongArray
+JNIEXPORT jobjectArray
JNICALL Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair
(JNIEnv *env, jclass clazz, jint keySize, jbyteArray encodedParams, jbyteArray seed)
{
- ECPrivateKey *privKey = NULL; /* contains both public and private values */
+ ECPrivateKey *privKey = NULL; // contains both public and private values
ECParams *ecparams = NULL;
SECKEYECParams params_item;
jint jSeedLength;
jbyte* pSeedBuffer = NULL;
- jlongArray result = NULL;
- jlong* resultElements = NULL;
+ jobjectArray result = NULL;
+ jclass baCls = NULL;
+ jbyteArray jba;
// Initialize the ECParams struct
params_item.len = env->GetArrayLength(encodedParams);
@@ -111,71 +128,62 @@
}
jboolean isCopy;
- result = env->NewLongArray(2);
+ baCls = env->FindClass("[B");
+ if (baCls == NULL) {
+ goto cleanup;
+ }
+ result = env->NewObjectArray(2, baCls, NULL);
if (result == NULL) {
goto cleanup;
}
+ jba = getEncodedBytes(env, &(privKey->privateValue));
+ if (jba == NULL) {
+ result = NULL;
+ goto cleanup;
+ }
+ env->SetObjectArrayElement(result, 0, jba); // big integer
+ if (env->ExceptionCheck()) { // should never happen
+ result = NULL;
+ goto cleanup;
+ }
- resultElements = env->GetLongArrayElements(result, &isCopy);
- if (resultElements == NULL) {
+ jba = getEncodedBytes(env, &(privKey->publicValue));
+ if (jba == NULL) {
+ result = NULL;
goto cleanup;
}
-
- resultElements[0] = (jlong) &(privKey->privateValue); // private big integer
- resultElements[1] = (jlong) &(privKey->publicValue); // encoded ec point
-
- // If the array is a copy then we must write back our changes
- if (isCopy == JNI_TRUE) {
- env->ReleaseLongArrayElements(result, resultElements, 0);
+ env->SetObjectArrayElement(result, 1, jba); // encoded ec point
+ if (env->ExceptionCheck()) { // should never happen
+ result = NULL;
+ goto cleanup;
}
cleanup:
{
- if (params_item.data)
+ if (params_item.data) {
env->ReleaseByteArrayElements(encodedParams,
(jbyte *) params_item.data, JNI_ABORT);
-
- if (ecparams)
+ }
+ if (ecparams) {
FreeECParams(ecparams, true);
-
+ }
if (privKey) {
FreeECParams(&privKey->ecParams, false);
SECITEM_FreeItem(&privKey->version, B_FALSE);
- // Don't free privKey->privateValue and privKey->publicValue
+ SECITEM_FreeItem(&privKey->privateValue, B_FALSE);
+ SECITEM_FreeItem(&privKey->publicValue, B_FALSE);
+ free(privKey);
}
- if (pSeedBuffer)
+ if (pSeedBuffer) {
delete [] pSeedBuffer;
+ }
}
return result;
}
/*
- * Class: sun_security_ec_ECKeyPairGenerator
- * Method: getEncodedBytes
- * Signature: (J)[B
- */
-JNIEXPORT jbyteArray
-JNICALL Java_sun_security_ec_ECKeyPairGenerator_getEncodedBytes
- (JNIEnv *env, jclass clazz, jlong hSECItem)
-{
- SECItem *s = (SECItem *)hSECItem;
- jbyteArray jEncodedBytes = env->NewByteArray(s->len);
- if (jEncodedBytes == NULL) {
- return NULL;
- }
-
- // Copy bytes from a native SECItem buffer to Java byte array
- env->SetByteArrayRegion(jEncodedBytes, 0, s->len, (jbyte *)s->data);
-
- // Use B_FALSE to free only the SECItem->data
- SECITEM_FreeItem(s, B_FALSE);
-
- return jEncodedBytes;
-}
-
-/*
* Class: sun_security_ec_ECDSASignature
* Method: signDigest
* Signature: ([B[B[B[B)[B
@@ -258,21 +266,26 @@
cleanup:
{
- if (params_item.data)
+ if (params_item.data) {
env->ReleaseByteArrayElements(encodedParams,
(jbyte *) params_item.data, JNI_ABORT);
-
- if (pDigestBuffer)
+ }
+ if (privKey.privateValue.data) {
+ env->ReleaseByteArrayElements(privateKey,
+ (jbyte *) privKey.privateValue.data, JNI_ABORT);
+ }
+ if (pDigestBuffer) {
delete [] pDigestBuffer;
-
- if (pSignedDigestBuffer)
+ }
+ if (pSignedDigestBuffer) {
delete [] pSignedDigestBuffer;
-
- if (pSeedBuffer)
+ }
+ if (pSeedBuffer) {
delete [] pSeedBuffer;
-
- if (ecparams)
+ }
+ if (ecparams) {
FreeECParams(ecparams, true);
+ }
}
return jSignedDigest;