JDK-6837847 : PKCS#11 A SecureRandom and a serialization error following installation of 1.5.0_18
  • Type: Bug
  • Component: security-libs
  • Sub-Component: java.security
  • Affected Version: 5.0,6u16
  • Priority: P3
  • Status: Resolved
  • Resolution: Fixed
  • OS: solaris_10
  • CPU: sparc
  • Submitted: 2009-05-06
  • Updated: 2011-02-16
  • Resolved: 2010-04-14
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other JDK 6 JDK 7 Other
5.0u25,OpenJDK6Fixed 6u18-revFixed 7 b89Fixed OpenJDK6Fixed
Description
FULL PRODUCT VERSION :
java version "1.5.0_18"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_18-b02)
Java HotSpot(TM) Server VM (build 1.5.0_18-b02, mixed mode)


ADDITIONAL OS VERSION INFORMATION :
SunOS d05prapp01 5.10 Generic_138888-08 sun4v sparc SUNW,SPARC-Enterprise-T5220


A DESCRIPTION OF THE PROBLEM :
Following upgrade from 1.5.0_17 to 1.5.0_18, experienced different errors related to Sun PKCS11 provider. One error was:

Caused by java.lang.NullPointerException
        at sun.security.pkcs11.P11SecureRandom.engineNextBytes
(P11SecureRandom.java110)
        at java.security.SecureRandom.nextBytes(SecureRandom.java413)

The application code did not change and simply called SecureRandom.nextBytes. Reverting back to 1.5.0_17 resolved the problem.

Also received a related error:

java.io.NotSerializableException Could not find token
        at sun.security.pkcs11.Token$TokenRep.readResolve(Token.java358)

Again, the error was not seen after fallback to 1.5.0_17.

Looking at the 1.5.0_18 release notes, the fix for bug 6591117 would appear to look suspicious.

Created a test program to serialize/deserialize the a SecureRandom object to reproduce the NullPointerException seen in our application.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Compile and run the source code included below.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Doesn't get exception.
ACTUAL -
Exception received with 1.5.0_18 runtime. No exception with 1.5.0_17 runtime


ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.NullPointerException
        at sun.security.pkcs11.P11SecureRandom.engineNextBytes(P11SecureRandom.java:110)
        at java.security.SecureRandom.nextBytes(SecureRandom.java:413)
        at pkcs11test.main(pkcs11test.java:15)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.security.SecureRandom;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

public class pkcs11test {

public static void main(String[] args) throws Exception {
    SecureRandom r = new SecureRandom();
    r.setSeed(System.currentTimeMillis());
    byte[] buf = new byte[16];
    byte[] ser = toByteArray(r);
    SecureRandom r2 = fromByteArray(ser);
    r2.nextBytes(buf);
    System.out.println("Done");
}


public static byte[] toByteArray(Object obj) throws Exception {
    ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
    ObjectOutputStream outStream = null;
    ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
    ObjectOutputStream outStream = null;
    try {
        outStream = new ObjectOutputStream(out);
        outStream.writeObject(obj);
        return out.toByteArray();
    } finally {
        if (outStream != null) {
            outStream.close();
        }
    }
}

public static SecureRandom fromByteArray(byte[] buf) throws Exception {
    SecureRandom r = null;
    ByteArrayInputStream is = new ByteArrayInputStream(buf);
    ObjectInputStream ois = null;
    try {
        ois = new ObjectInputStream(is);
        r = (SecureRandom) ois.readObject();
    } finally {
        if (ois != null) {
            ois.close();
        if (ois != null) {
            ois.close();
        }
    }
    return r;
}
}

---------- END SOURCE ----------

Release Regression From : 5.0u17
The above release value was the last known release where this 
bug was not reproducible. Since then there has been a regression.

Comments
EVALUATION For the NotSerializable error, did they by chance pull the token or try to deserialize on a different VM? The code I just reviewed looks ok, but this is somewhat concerning.
20-02-2010

EVALUATION Yes, the NPE is due to synchronizing on a transient field (added when fixing 6591117) whose value is null as a result of default deserialization. Not sure what the related error is about.
11-05-2009

EVALUATION This may be a result of fixing 6591117. I'm RE'ing the original engineer for the JDK7 fix, and cc'ing the RE who made this fix.
07-05-2009