PKCS #11 provider shutdown process, key zeroization

Matthew Hall mhall at mhcomputing.net
Mon Mar 18 22:13:01 UTC 2013


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.




More information about the security-dev mailing list