How to finalize SunPKCS11 Provider after it is initialized?

Import class

import sun.security.pkcs11.SunPKCS11;
import sun.security.pkcs11.wrapper.PKCS11

Use this method to close PKCSS Wrapper

    private void finalizePKCS11Wrapper(PKCS11 pkcs11) throws IOException{
    try {
        Field f = PKCS11.class.getDeclaredField("moduleMap"); 
        f.setAccessible(true);
        Map moduleMap = (Map) f.get(pkcs11);
        moduleMap.clear();
        pkcs11.C_Finalize(PKCS11Constants.NULL_PTR);
    } catch (IllegalAccessException | IllegalArgumentException | NoSuchFieldException | SecurityException | PKCS11Exception e) {
        throw new IOException("No se pudo cerrar la sessión con el token",e);
    }
}

And close sunPKCS11 connection

    public void logout() throws Exception {
    if(sunPKCS11==null)
        return;
    try {
        // Obtenemos el Wrapper del sunPKCS11
        Field f = SunPKCS11.class.getDeclaredField("p11"); 
        f.setAccessible(true);
        PKCS11 objectPKCS11 = (PKCS11)f.get(sunPKCS11);
        finalizePKCS11Wrapper(objectPKCS11);
    } catch (Exception e) {
        e.printStackTrace();
    }
    sunPKCS11.clear();
    sunPKCS11.setCallbackHandler(null);
    Security.removeProvider(sunPKCS11.getName());
    sunPKCS11 = null;
    keyStore = null;
    System.gc();
}

Finally was able to find a solution. The Sun's Provider uses the Wrapper underneath. So the trick is to use the Sun's PKCS#11 Wrapper to get the current instance, and finalize it. Obviously this finalizing of the session feature is not exposed in the Provider. But there is a workaround, and it looks like this:

public static void providerAndWrapperIssue() throws Exception
{
    final String name = "ANY_NAME";
    final String library = "LOCATION OF THE TOKENS DLL/SO";
    final String slot = "SLOT NUMBER";

    // SUN PKCS#11 Provider -------------------------------------------

    StringBuilder builder = new StringBuilder();
    builder.append("name=" + name);
    builder.append(System.getProperty("line.separator"));
    builder.append("library=\"" + library + "\"");
    builder.append(System.getProperty("line.separator"));
    builder.append("slot=" + slot);

    ByteArrayInputStream bais = new ByteArrayInputStream(builder.toString().getBytes());
    Provider provider = new sun.security.pkcs11.SunPKCS11(bais);
    provider.setProperty("pkcs11LibraryPath", library);
    Security.addProvider(provider);

    KeyStore ks = KeyStore.getInstance("PKCS11");
    ks.load(null, null);

    Enumeration<String> aliases = ks.aliases();
    while (aliases.hasMoreElements())
        System.out.println(aliases.nextElement());

    // ====================================
    // Solved it using the SUN PKCS#11 Wrapper

    PKCS11 pkcs11 = PKCS11.getInstance(((sun.security.pkcs11.SunPKCS11) provider).getProperty("pkcs11LibraryPath"), null, null, true);
    pkcs11.C_Finalize(PKCS11Constants.NULL_PTR);

    // ====================================

    // IAIK PKCS#11 Wrapper -------------------------------------------

    Module pkcs11Module = Module.getInstance(library, false);
    pkcs11Module.initialize(null);

    Slot[] slots = pkcs11Module.getSlotList(true);

    Session session = slots[0].getToken().openSession(true, true, null, null);
    session.login(Session.UserType.USER, "".toCharArray());

    session.logout();
    session.closeSession();

    slots[0].getToken().closeAllSessions();

    pkcs11Module.finalize(null);
}

Tags:

Java

Hsm

Pkcs#11