PKCS #11 provider shutdown process, key zeroization

Matthew Hall mhall at mhcomputing.net
Tue Feb 19 19:56:00 UTC 2013


Hello,

I am working on a product which uses the Sun PKCS #11 provider. I was curious 
how the FIPS mode worked, in particular about the shutdown procedure and 
whether or not it performed key and password zeroization, so I was reading 
through the OpenJDK 7 trunk version of the implementation code to learn more.

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?

In addition, I noticed there are a number of pieces of code that 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.

Regards,
Matthew.



More information about the security-dev mailing list