--- old/make/mapfiles/libsunec/mapfile-vers 2014-05-27 12:59:25.895788000 -0700 +++ new/make/mapfiles/libsunec/mapfile-vers 2014-05-27 12:59:25.716787000 -0700 @@ -29,6 +29,7 @@ global: Java_sun_security_ec_ECKeyPairGenerator_generateECKeyPair; Java_sun_security_ec_ECKeyPairGenerator_getEncodedBytes; + Java_sun_security_ec_ECKeyPairGenerator_releaseECKeyPairData; Java_sun_security_ec_ECDSASignature_signDigest; Java_sun_security_ec_ECDSASignature_verifySignedDigest; Java_sun_security_ec_ECDHKeyAgreement_deriveKey; --- old/src/share/classes/sun/security/ec/ECKeyPairGenerator.java 2014-05-27 12:59:26.544793000 -0700 +++ new/src/share/classes/sun/security/ec/ECKeyPairGenerator.java 2014-05-27 12:59:26.392796000 -0700 @@ -123,9 +123,10 @@ } random.nextBytes(seed); + long[] handles = null; try { - long[] handles = generateECKeyPair(keySize, encodedParams, seed); + handles = generateECKeyPair(keySize, encodedParams, seed); // The 'params' object supplied above is equivalent to the native // one so there is no need to fetch it. @@ -146,6 +147,12 @@ } catch (Exception e) { throw new ProviderException(e); + } finally { + if (handles != null) { + // handles[2] points to the data structure containing + // both the native public and private key. + releaseECKeyPairData(handles[2]); + } } } @@ -168,6 +175,12 @@ private static native long[] generateECKeyPair(int keySize, byte[] encodedParams, byte[] seed) throws GeneralSecurityException; + + /* + * Releases the native memory allocated by generateECKeyPair. + */ + private static native void releaseECKeyPairData(long privKeyHandle); + /* * Extracts the encoded key data using the supplied handle. */ --- old/src/share/native/sun/security/ec/ECC_JNI.cpp 2014-05-27 12:59:27.132797000 -0700 +++ new/src/share/native/sun/security/ec/ECC_JNI.cpp 2014-05-27 12:59:26.974799000 -0700 @@ -62,8 +62,9 @@ SECITEM_FreeItem(&ecparams->order, B_FALSE); SECITEM_FreeItem(&ecparams->DEREncoding, B_FALSE); SECITEM_FreeItem(&ecparams->curveOID, B_FALSE); - if (freeStruct) - free(ecparams); + if (freeStruct) { + PORT_ZFree(ecparams, sizeof(ECParams)); + } } /* @@ -139,9 +140,11 @@ FreeECParams(ecparams, true); if (privKey) { - FreeECParams(&privKey->ecParams, false); SECITEM_FreeItem(&privKey->version, B_FALSE); - // Don't free privKey->privateValue and privKey->publicValue + // Don't free privKey->privateValue and privKey->publicValue. + // Also, don't free privKey->ecParams, because it contains our only + // link to the arena. If this code is ever migrated to use arenas, + // then we will need to free it later. } if (pSeedBuffer) @@ -152,6 +155,31 @@ } /* + * Class: sun_security_ec_ECKeyPairGenerator + * Method: releaseECKeyPairData + * Signature: (JJ)V + */ +JNIEXPORT void +JNICALL Java_sun_security_ec_ECKeyPairGenerator_releaseECKeyPairData + (JNIEnv *env, jclass clazz, jlong pk) { + ECPrivateKey *privKey = reinterpret_cast(pk); + if (privKey) { + PRArenaPool *arena = privKey->ecParams.arena; + + FreeECParams(&privKey->ecParams, false); + SECITEM_FreeItem(&privKey->privateValue, B_FALSE); + SECITEM_FreeItem(&privKey->publicValue, B_FALSE); + + // In principle, we should just be able to free the arena. + // We add ZFree here because the JDK's FreeArena is currently a nop. + PORT_ZFree(privKey, sizeof(ECPrivateKey)); + if (arena) { + PORT_FreeArena(arena, B_TRUE); + } + } +} + +/* * Class: sun_security_ec_ECKeyPairGenerator * Method: getEncodedBytes * Signature: (J)[B --- old/src/share/native/sun/security/ec/impl/ec.c 2014-05-27 12:59:27.753806000 -0700 +++ new/src/share/native/sun/security/ec/impl/ec.c 2014-05-27 12:59:27.575804000 -0700 @@ -55,16 +55,6 @@ #include "mpi.h" #include "ecc_impl.h" -#ifdef _KERNEL -#define PORT_ZFree(p, l) bzero((p), (l)); kmem_free((p), (l)) -#else -#ifndef _WIN32 -#define PORT_ZFree(p, l) bzero((p), (l)); free((p)) -#else -#define PORT_ZFree(p, l) memset((p), 0, (l)); free((p)) -#endif /* _WIN32 */ -#endif - /* * Returns true if pointP is the point at infinity, false otherwise */ @@ -422,11 +412,7 @@ rv = SECFailure; } if (rv != SECSuccess && privKeyBytes) { -#ifdef _KERNEL - kmem_free(privKeyBytes, 2*len); -#else - free(privKeyBytes); -#endif + PORT_ZFree(privKeyBytes, 2*len); privKeyBytes = NULL; } return privKeyBytes; --- old/src/share/native/sun/security/ec/impl/ecc_impl.h 2014-05-27 12:59:28.369804000 -0700 +++ new/src/share/native/sun/security/ec/impl/ecc_impl.h 2014-05-27 12:59:28.191803000 -0700 @@ -43,6 +43,7 @@ extern "C" { #endif +#include #include #include "ecl-exp.h" @@ -101,12 +102,22 @@ #define PORT_ArenaGrow(a, b, c, d) NULL #define PORT_ZAlloc(n, f) kmem_zalloc((n), (f)) #define PORT_Alloc(n, f) kmem_alloc((n), (f)) +#define PORT_ZFree(p, l) \ + do { \ + memset((p), 0, (l)); \ + kmem_free((p), (l)); \ + } while (0) #else #define PORT_ArenaAlloc(a, n, f) malloc((n)) #define PORT_ArenaZAlloc(a, n, f) calloc(1, (n)) #define PORT_ArenaGrow(a, b, c, d) NULL #define PORT_ZAlloc(n, f) calloc(1, (n)) #define PORT_Alloc(n, f) malloc((n)) +#define PORT_ZFree(p, l) \ + do { \ + memset((p), 0, (l)); \ + free((p)); \ + } while (0) #endif #define PORT_NewArena(b) (char *)12345