JDK-7001094 : Can't initialize SunPKCS11 more times than PKCS11 driver maxSessionCount
  • Type: Bug
  • Component: security-libs
  • Sub-Component: java.security
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Fixed
  • OS: windows_xp
  • CPU: x86
  • Submitted: 2010-11-18
  • Updated: 2012-03-20
  • Resolved: 2011-06-22
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.
JDK 6 JDK 7
6u25-revFixed 7 b140Fixed
Description
FULL PRODUCT VERSION :
java version "1.6.0_22"
Java(TM) SE Runtime Environment (build 1.6.0_22-b04)
Java HotSpot(TM) Client VM (build 17.1-b03, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows XP [Version 5.1.2600]

EXTRA RELEVANT SYSTEM CONFIGURATION :
PKCS11 driver has limit for session count.

A DESCRIPTION OF THE PROBLEM :
After refactoring done in 1.6.0_21 in sun.security.pkcs11.SessionManager it is not possible to initialize SunPKCS11  provider more times than PKCS11 driver maxSessionCount limit. When initializing (maxLimitCount + 1) instance exception is thrown.

In 1.6.0_20 or earlier this works fine.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create in loop more than maxSessionCount (this is specific for PKCS11 driver).  In maxSessionCounty + 1 loop exception is thrown.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
no exception is thrown
ACTUAL -

Exception in thread "main" java.security.ProviderException: Initialization failed
	at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:340)
	at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:90)
	at pl.unizeto.procertum.pkcs11.SunPkcs11BugTest.main(SunPkcs11BugTest.java:29)
Caused by: java.security.ProviderException: Could not obtain session
	at sun.security.pkcs11.SessionManager.getOpSession(SessionManager.java:134)
	at sun.security.pkcs11.Token.<init>(Token.java:118)
	at sun.security.pkcs11.SunPKCS11.initToken(SunPKCS11.java:780)
	at sun.security.pkcs11.SunPKCS11.<init>(SunPKCS11.java:331)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
        // Maximum session count supported by pkcs11 driver.
        // If you don't know what is the limit for your driver set it to 1000
        // or higher value.
        // If driver has no limit for session count this test works fine.
        int driverMaxSessions = 32;
        
        StringBuilder pkcs11Cfg = new StringBuilder();
        pkcs11Cfg.append("name = PKCS11\n");
        pkcs11Cfg.append("library = crypto3PKCS.dll");
        
        for(int i=0; i < driverMaxSessions + 1; i++) {
        
            InputStream config = new ByteArrayInputStream(pkcs11Cfg.toString().getBytes());
            
            // fails with "java.security.ProviderException: Could not obtain session"
            // when in (driverMaxSession + 1) loop on JRE 6u20 or later
            SunPKCS11 provider = new sun.security.pkcs11.SunPKCS11(config);
            provider.logout();
        }
---------- END SOURCE ----------

Comments
EVALUATION The difference in behavior is due to the following bug fix: 6918573: sun.security.pkcs11.P11RSACipher.finalize() is a scalability blocker which uses PhantomReference for proper session cleanup. The current impl keeps track of the number of sessions by counting the number of PhantomReferences of session objects. This has the problem of being too restrictive when there are more than one SunPKCS11 providers. To fix the problem, we'll have to revert back to keeping track of the number of sessions inside each SessionManager instance.
24-02-2011