It's great to hear from you, Milton! Below I have placed everything into one report in order of importance. Perhaps someone could take a look at let me know what the solution is if there are some, and how we could work together to correct anything that could be an issue.
1. Correct procedure for PKCS11 provider shutdown and reload How do you shutdown the provider, zeroize all keys and passwords, and reopen it, without restarting the whole JVM? Also, assuming you can't shutdown and restart, why is the secure shutdown and finalization code comments out and not called, with just XXX and no explanation of why it was disabled? It's very important for FIPS that everything is shut down properly so things aren't left sitting around in memory. The details for this are rather long to describe, see below signature for more detail. 2. Code which logs contents of Private Keys in toString() by default Quite a number of bits of code are printing out the content of the private exponent of the RSA Private Keys by default into the toString() output, which could lead to key compromise if they're printed into a log. share/classes/sun/security/pkcs11/P11Key.java:552: sb.append("\n private exponent: "); share/classes/sun/security/pkcs11/P11Key.java:624: sb.append("\n private exponent: "); share/classes/sun/security/rsa/RSAPrivateCrtKeyImpl.java:238: sb.append("\n private exponent: "); share/classes/sun/security/rsa/RSAPrivateKeyImpl.java:105: + n + "\n private exponent: " + d; Ordinarily I believe FIPS and PCI would require that there isn't any code sitting around that could accidentally or unexpectedly print out the private key data. Is this toString() behaving that way for a good reason? 3. Key and password zeroization A number of pieces of code are zeroizing keys using \x20 instead of \x00: share/classes/com/sun/crypto/provider/PBEKey.java:70: java.util.Arrays.fill(passwd, ' '); share/classes/com/sun/crypto/provider/PBEKeyFactory.java:151: java.util.Arrays.fill(passwdChars, ' '); share/classes/com/sun/jmx/remote/security/FileLoginModule.java:561: Arrays.fill(password, ' '); share/classes/com/sun/security/auth/module/LdapLoginModule.java:1000: Arrays.fill(password, ' '); share/classes/java/io/Console.java:84: * java.util.Arrays.fill(passwd, ' '); share/classes/java/io/Console.java:388: Arrays.fill(rcb, 0, len, ' '); share/classes/java/security/KeyStore.java:297: Arrays.fill(password, ' '); share/classes/sun/net/www/protocol/http/spnego/NegotiateCallbackHandler.java:91: if (password != null) Arrays.fill(password, ' '); share/classes/sun/security/pkcs11/P11KeyStore.java:253: Arrays.fill(password, ' '); share/classes/sun/security/pkcs11/SunPKCS11.java:1191: Arrays.fill(pin, ' '); share/classes/sun/security/util/Password.java:104: Arrays.fill(lineBuffer, ' '); share/classes/sun/security/util/Password.java:118: Arrays.fill(buf, ' '); share/classes/sun/security/util/Password.java:123: Arrays.fill(consoleEntered, ' '); share/classes/sun/security/util/PolicyUtil.java:174: Arrays.fill(keyStorePassword, ' '); Officially I don't think this is allowed either, but it's a more minor issue than the other item I'm asking about. Thanks, Matthew. More detail on (1): Correct procedure for PKCS11 provider shutdown and reload In share/classes/sun/security/pkcs11/wrapper/PKCS11.java we have some methods: private static native void finalizeLibrary(); I could not find any code which ever called this method. In share/native/sun/security/pkcs11/wrapper/p11_general.c, all the implementation code for this native method is commented out, with an XXX marker but no explanation why it's commented out. public native void C_Finalize(Object pReserved) throws PKCS11Exception; I could not find any code which ever called this either, but at least the implementation code is not commented out, and looks like it would probably work if it was called. I believe that this method often implements zeroization so it seems like it could be an issue if nothing is ever calling this. /** * Calls disconnect() to cleanup the native part of the wrapper. Once this * method is called, this object cannot be used any longer. Any subsequent * call to a C_* method will result in a runtime exception. * * @exception Throwable If finalization fails. */ public void finalize() throws Throwable { disconnect(); } Next we have the finalizer, which calls the disconnect method. Note that it is documented as throwing an exception, but any exceptions during finalization would be ignored and not reported anywhere, which would mean we would not have a way of knowing that unloading is failing and nothing is getting zeroized properly. (This is according to Object#finalize documentation). Is there a way to obtain a reference to the PKCS11 wrapper and call this function explicitly? I could not find a good way to do it. Since finalize might never get called if the object never gets unreferences, I can't see how we could be sure the keys are zeroized right, even if some of the items inside of disconnect perform the zeroization, which I'm not sure that they do. /** * Disconnects the PKCS#11 library from this object. After calling this * method, this object is no longer connected to a native PKCS#11 module * and any subsequent calls to C_ methods will fail. This method is for * internal use only. * Declared private, because incorrect handling may result in errors in the * native part. * * @preconditions * @postconditions */ private native void disconnect(); Let's take a look at the implementation of disconnect from solaris/native/sun/security/pkcs11/wrapper/p11_md.c: /* * Class: sun_security_pkcs11_wrapper_PKCS11 * Method: disconnect * Signature: ()V */ JNIEXPORT void JNICALL Java_sun_security_pkcs11_wrapper_PKCS11_disconnect (JNIEnv *env, jobject obj) { ModuleData *moduleData; TRACE0("DEBUG: disconnecting module..."); moduleData = removeModuleEntry(env, obj); if (moduleData != NULL) { dlclose(moduleData->hModule); } free(moduleData); TRACE0("FINISHED\n"); } If you read through removeModuleEntry, the only interesting operation performed there is: (*env)->SetLongField(env, pkcs11Implementation, pNativeDataID, 0); This is setting the pNativeDataID field from the PKCS #11 class to zero. Then, the higher code in disconnect will dlclose the library. However dlclose is only reference-counting, and does not guarantee the library will be removed from memory, or that the removed memory will be zeroized. In addition if the keys are stored in a dynamic area and not a static area inside the library, which is what I suspect, they could still be present in memory after this point, which seems to be against what's required for zeroization in FIPS. Therefore I am asking now, if we are sure that the way all of this works will perform the key zeroization we expect. Can anybody comment on whether this could be an actual issue or not? Regards, Matthew.