8210476: sun/security/mscapi/PrngSlow.java fails with Still too slow

Reviewed-by: xuelei, igerasim, rriggs
This commit is contained in:
Weijun Wang 2018-12-03 23:58:15 +08:00
parent 86a41aa926
commit 3254283f79
4 changed files with 124 additions and 28 deletions

View File

@ -25,6 +25,7 @@
package sun.security.mscapi;
import java.lang.ref.Cleaner;
import java.security.ProviderException;
import java.security.SecureRandomSpi;
@ -43,12 +44,31 @@ public final class PRNG extends SecureRandomSpi
* The CryptGenRandom function fills a buffer with cryptographically random
* bytes.
*/
private static native byte[] generateSeed(int length, byte[] seed);
private static native byte[] generateSeed(long ctxt, int length, byte[] seed);
private static native long getContext();
private static native void releaseContext(long ctxt);
private static final Cleaner CLEANER = Cleaner.create();
private transient long ctxt;
private static class State implements Runnable {
private final long ctxt;
State(long ctxt) {
this.ctxt = ctxt;
}
@Override
public void run() {
releaseContext(ctxt);
}
}
/**
* Creates a random number generator.
*/
public PRNG() {
ctxt = getContext();
CLEANER.register(this, new State(ctxt));
}
/**
@ -59,9 +79,9 @@ public final class PRNG extends SecureRandomSpi
* @param seed the seed.
*/
@Override
protected void engineSetSeed(byte[] seed) {
protected synchronized void engineSetSeed(byte[] seed) {
if (seed != null) {
generateSeed(-1, seed);
generateSeed(ctxt, -1, seed);
}
}
@ -71,9 +91,9 @@ public final class PRNG extends SecureRandomSpi
* @param bytes the array to be filled in with random bytes.
*/
@Override
protected void engineNextBytes(byte[] bytes) {
protected synchronized void engineNextBytes(byte[] bytes) {
if (bytes != null) {
if (generateSeed(0, bytes) == null) {
if (generateSeed(ctxt, 0, bytes) == null) {
throw new ProviderException("Error generating random bytes");
}
}
@ -88,12 +108,20 @@ public final class PRNG extends SecureRandomSpi
* @return the seed bytes.
*/
@Override
protected byte[] engineGenerateSeed(int numBytes) {
byte[] seed = generateSeed(numBytes, null);
protected synchronized byte[] engineGenerateSeed(int numBytes) {
byte[] seed = generateSeed(ctxt, numBytes, null);
if (seed == null) {
throw new ProviderException("Error generating seed bytes");
}
return seed;
}
private void readObject(java.io.ObjectInputStream s)
throws java.io.IOException, ClassNotFoundException
{
s.defaultReadObject();
ctxt = getContext();
CLEANER.register(this, new State(ctxt));
}
}

View File

@ -240,34 +240,56 @@ bool GetCertificateChain(LPSTR lpszKeyUsageIdentifier, PCCERT_CONTEXT pCertConte
/////////////////////////////////////////////////////////////////////////////
//
/*
* Class: sun_security_mscapi_PRNG
* Method: getContext
* Signature: ()J
*/
JNIEXPORT jlong JNICALL Java_sun_security_mscapi_PRNG_getContext
(JNIEnv *env, jclass clazz) {
HCRYPTPROV hCryptProv = NULL;
if(::CryptAcquireContext(
&hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT) == FALSE)
{
ThrowException(env, PROVIDER_EXCEPTION, GetLastError());
}
return hCryptProv;
}
/*
* Class: sun_security_mscapi_PRNG
* Method: releaseContext
* Signature: (J)V
*/
JNIEXPORT void JNICALL Java_sun_security_mscapi_PRNG_releaseContext
(JNIEnv *env, jclass clazz, jlong ctxt) {
if (ctxt) {
::CryptReleaseContext((HCRYPTPROV)ctxt, 0);
}
}
/*
* Class: sun_security_mscapi_PRNG
* Method: generateSeed
* Signature: (I[B)[B
* Signature: (JI[B)[B
*/
JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed
(JNIEnv *env, jclass clazz, jint length, jbyteArray seed)
(JNIEnv *env, jclass clazz, jlong ctxt, jint length, jbyteArray seed)
{
HCRYPTPROV hCryptProv = NULL;
HCRYPTPROV hCryptProv = (HCRYPTPROV)ctxt;
jbyte* reseedBytes = NULL;
jbyte* seedBytes = NULL;
jbyteArray result = NULL;
__try
{
// Acquire a CSP context.
if(::CryptAcquireContext(
&hCryptProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_VERIFYCONTEXT) == FALSE)
{
ThrowException(env, PROVIDER_EXCEPTION, GetLastError());
__leave;
}
/*
* If length is negative then use the supplied seed to re-seed the
* generator and return null.
@ -330,9 +352,6 @@ JNIEXPORT jbyteArray JNICALL Java_sun_security_mscapi_PRNG_generateSeed
if (seedBytes)
env->ReleaseByteArrayElements(seed, seedBytes, 0); // update orig
if (hCryptProv)
::CryptReleaseContext(hCryptProv, 0);
}
return result;

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/**
* @test
* @bug 8210476
* @requires os.family == "windows"
* @summary MSCAPI's PRNG should support serialization
* @library /test/lib
* @run main PrngSerialize
*/
import jdk.test.lib.util.SerializationUtils;
import java.security.SecureRandom;
public class PrngSerialize {
public static void main(String[] args) throws Exception {
SecureRandom sr = SecureRandom.getInstance("Windows-PRNG", "SunMSCAPI");
sr = (SecureRandom) SerializationUtils.deserialize(SerializationUtils.serialize(sr));
// This line is likely to release the context in the original sr.
System.gc();
// Make sure the new object is still useable.
sr.nextInt();
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2006, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -23,7 +23,7 @@
/**
* @test
* @bug 6449335
* @bug 6449335 8210476
* @requires os.family == "windows"
* @summary MSCAPI's PRNG is too slow
* @key randomness
@ -44,7 +44,7 @@ public class PrngSlow {
};
t = (System.nanoTime() - start) / 1000000000.0;
System.err.println("\nSpend " + t + " seconds");
if (t > 5)
if (t > 0.5)
throw new RuntimeException("Still too slow");
}
}