| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package sun.security.pkcs11;  | 
 | 
 | 
 | 
import java.io.*;  | 
 | 
import java.util.*;  | 
 | 
 | 
 | 
import java.security.*;  | 
 | 
import java.security.interfaces.*;  | 
 | 
 | 
 | 
import javax.crypto.interfaces.*;  | 
 | 
 | 
 | 
import javax.security.auth.Subject;  | 
 | 
import javax.security.auth.login.LoginException;  | 
 | 
import javax.security.auth.login.FailedLoginException;  | 
 | 
import javax.security.auth.callback.Callback;  | 
 | 
import javax.security.auth.callback.CallbackHandler;  | 
 | 
import javax.security.auth.callback.ConfirmationCallback;  | 
 | 
import javax.security.auth.callback.PasswordCallback;  | 
 | 
import javax.security.auth.callback.TextOutputCallback;  | 
 | 
 | 
 | 
import sun.security.util.Debug;  | 
 | 
import sun.security.util.ResourcesMgr;  | 
 | 
 | 
 | 
import sun.security.pkcs11.Secmod.*;  | 
 | 
 | 
 | 
import sun.security.pkcs11.wrapper.*;  | 
 | 
import static sun.security.pkcs11.wrapper.PKCS11Constants.*;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
public final class SunPKCS11 extends AuthProvider { | 
 | 
 | 
 | 
    private static final long serialVersionUID = -1354835039035306505L;  | 
 | 
 | 
 | 
    static final Debug debug = Debug.getInstance("sunpkcs11"); | 
 | 
 | 
 | 
    private static int dummyConfigId;  | 
 | 
 | 
 | 
      | 
 | 
    final PKCS11 p11;  | 
 | 
 | 
 | 
      | 
 | 
    private final String configName;  | 
 | 
 | 
 | 
      | 
 | 
    final Config config;  | 
 | 
 | 
 | 
      | 
 | 
    final long slotID;  | 
 | 
 | 
 | 
    private CallbackHandler pHandler;  | 
 | 
    private final Object LOCK_HANDLER = new Object();  | 
 | 
 | 
 | 
    final boolean removable;  | 
 | 
 | 
 | 
    final Module nssModule;  | 
 | 
 | 
 | 
    final boolean nssUseSecmodTrust;  | 
 | 
 | 
 | 
    private volatile Token token;  | 
 | 
 | 
 | 
    private TokenPoller poller;  | 
 | 
 | 
 | 
    Token getToken() { | 
 | 
        return token;  | 
 | 
    }  | 
 | 
 | 
 | 
    public SunPKCS11() { | 
 | 
        super("SunPKCS11-Dummy", 1.8d, "SunPKCS11-Dummy"); | 
 | 
        throw new ProviderException  | 
 | 
            ("SunPKCS11 requires configuration file argument"); | 
 | 
    }  | 
 | 
 | 
 | 
    public SunPKCS11(String configName) { | 
 | 
        this(checkNull(configName), null);  | 
 | 
    }  | 
 | 
 | 
 | 
    public SunPKCS11(InputStream configStream) { | 
 | 
        this(getDummyConfigName(), checkNull(configStream));  | 
 | 
    }  | 
 | 
 | 
 | 
    private static <T> T checkNull(T obj) { | 
 | 
        if (obj == null) { | 
 | 
            throw new NullPointerException();  | 
 | 
        }  | 
 | 
        return obj;  | 
 | 
    }  | 
 | 
 | 
 | 
    private static synchronized String getDummyConfigName() { | 
 | 
        int id = ++dummyConfigId;  | 
 | 
        return "---DummyConfig-" + id + "---";  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    @Deprecated  | 
 | 
    public SunPKCS11(String configName, InputStream configStream) { | 
 | 
        super("SunPKCS11-" + | 
 | 
            Config.getConfig(configName, configStream).getName(),  | 
 | 
            1.8d, Config.getConfig(configName, configStream).getDescription());  | 
 | 
        this.configName = configName;  | 
 | 
        this.config = Config.removeConfig(configName);  | 
 | 
 | 
 | 
        if (debug != null) { | 
 | 
            System.out.println("SunPKCS11 loading " + configName); | 
 | 
        }  | 
 | 
 | 
 | 
        String library = config.getLibrary();  | 
 | 
        String functionList = config.getFunctionList();  | 
 | 
        long slotID = config.getSlotID();  | 
 | 
        int slotListIndex = config.getSlotListIndex();  | 
 | 
 | 
 | 
        boolean useSecmod = config.getNssUseSecmod();  | 
 | 
        boolean nssUseSecmodTrust = config.getNssUseSecmodTrust();  | 
 | 
        Module nssModule = null;  | 
 | 
 | 
 | 
        //  | 
 | 
        // Initialization via Secmod. The way this works is as follows:  | 
 | 
        // SunPKCS11 is either in normal mode or in NSS Secmod mode.  | 
 | 
        // Secmod is activated by specifying one or more of the following  | 
 | 
        // options in the config file:  | 
 | 
        // nssUseSecmod, nssSecmodDirectory, nssLibrary, nssModule  | 
 | 
        //  | 
 | 
        // XXX add more explanation here  | 
 | 
        //  | 
 | 
        // If we are in Secmod mode and configured to use either the  | 
 | 
        // nssKeyStore or the nssTrustAnchors module, we automatically  | 
 | 
        // switch to using the NSS trust attributes for trusted certs  | 
 | 
        // (KeyStore).  | 
 | 
        //  | 
 | 
 | 
 | 
        if (useSecmod) { | 
 | 
            // note: Config ensures library/slot/slotListIndex not specified  | 
 | 
              | 
 | 
            Secmod secmod = Secmod.getInstance();  | 
 | 
            DbMode nssDbMode = config.getNssDbMode();  | 
 | 
            try { | 
 | 
                String nssLibraryDirectory = config.getNssLibraryDirectory();  | 
 | 
                String nssSecmodDirectory = config.getNssSecmodDirectory();  | 
 | 
                boolean nssOptimizeSpace = config.getNssOptimizeSpace();  | 
 | 
 | 
 | 
                if (secmod.isInitialized()) { | 
 | 
                    if (nssSecmodDirectory != null) { | 
 | 
                        String s = secmod.getConfigDir();  | 
 | 
                        if ((s != null) &&  | 
 | 
                                (s.equals(nssSecmodDirectory) == false)) { | 
 | 
                            throw new ProviderException("Secmod directory " | 
 | 
                                + nssSecmodDirectory  | 
 | 
                                + " invalid, NSS already initialized with "  | 
 | 
                                + s);  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                    if (nssLibraryDirectory != null) { | 
 | 
                        String s = secmod.getLibDir();  | 
 | 
                        if ((s != null) &&  | 
 | 
                                (s.equals(nssLibraryDirectory) == false)) { | 
 | 
                            throw new ProviderException("NSS library directory " | 
 | 
                                + nssLibraryDirectory  | 
 | 
                                + " invalid, NSS already initialized with "  | 
 | 
                                + s);  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                } else { | 
 | 
                    if (nssDbMode != DbMode.NO_DB) { | 
 | 
                        if (nssSecmodDirectory == null) { | 
 | 
                            throw new ProviderException(  | 
 | 
                                "Secmod not initialized and "  | 
 | 
                                 + "nssSecmodDirectory not specified");  | 
 | 
                        }  | 
 | 
                    } else { | 
 | 
                        if (nssSecmodDirectory != null) { | 
 | 
                            throw new ProviderException(  | 
 | 
                                "nssSecmodDirectory must not be "  | 
 | 
                                + "specified in noDb mode");  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                    secmod.initialize(nssDbMode, nssSecmodDirectory,  | 
 | 
                        nssLibraryDirectory, nssOptimizeSpace);  | 
 | 
                }  | 
 | 
            } catch (IOException e) { | 
 | 
                  | 
 | 
                throw new ProviderException("Could not initialize NSS", e); | 
 | 
            }  | 
 | 
            List<Module> modules = secmod.getModules();  | 
 | 
            if (config.getShowInfo()) { | 
 | 
                System.out.println("NSS modules: " + modules); | 
 | 
            }  | 
 | 
 | 
 | 
            String moduleName = config.getNssModule();  | 
 | 
            if (moduleName == null) { | 
 | 
                nssModule = secmod.getModule(ModuleType.FIPS);  | 
 | 
                if (nssModule != null) { | 
 | 
                    moduleName = "fips";  | 
 | 
                } else { | 
 | 
                    moduleName = (nssDbMode == DbMode.NO_DB) ?  | 
 | 
                        "crypto" : "keystore";  | 
 | 
                }  | 
 | 
            }  | 
 | 
            if (moduleName.equals("fips")) { | 
 | 
                nssModule = secmod.getModule(ModuleType.FIPS);  | 
 | 
                nssUseSecmodTrust = true;  | 
 | 
                functionList = "FC_GetFunctionList";  | 
 | 
            } else if (moduleName.equals("keystore")) { | 
 | 
                nssModule = secmod.getModule(ModuleType.KEYSTORE);  | 
 | 
                nssUseSecmodTrust = true;  | 
 | 
            } else if (moduleName.equals("crypto")) { | 
 | 
                nssModule = secmod.getModule(ModuleType.CRYPTO);  | 
 | 
            } else if (moduleName.equals("trustanchors")) { | 
 | 
                  | 
 | 
                nssModule = secmod.getModule(ModuleType.TRUSTANCHOR);  | 
 | 
                nssUseSecmodTrust = true;  | 
 | 
            } else if (moduleName.startsWith("external-")) { | 
 | 
                int moduleIndex;  | 
 | 
                try { | 
 | 
                    moduleIndex = Integer.parseInt  | 
 | 
                            (moduleName.substring("external-".length())); | 
 | 
                } catch (NumberFormatException e) { | 
 | 
                    moduleIndex = -1;  | 
 | 
                }  | 
 | 
                if (moduleIndex < 1) { | 
 | 
                    throw new ProviderException  | 
 | 
                            ("Invalid external module: " + moduleName); | 
 | 
                }  | 
 | 
                int k = 0;  | 
 | 
                for (Module module : modules) { | 
 | 
                    if (module.getType() == ModuleType.EXTERNAL) { | 
 | 
                        if (++k == moduleIndex) { | 
 | 
                            nssModule = module;  | 
 | 
                            break;  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                }  | 
 | 
                if (nssModule == null) { | 
 | 
                    throw new ProviderException("Invalid module " + moduleName | 
 | 
                        + ": only " + k + " external NSS modules available");  | 
 | 
                }  | 
 | 
            } else { | 
 | 
                throw new ProviderException(  | 
 | 
                    "Unknown NSS module: " + moduleName);  | 
 | 
            }  | 
 | 
            if (nssModule == null) { | 
 | 
                throw new ProviderException(  | 
 | 
                    "NSS module not available: " + moduleName);  | 
 | 
            }  | 
 | 
            if (nssModule.hasInitializedProvider()) { | 
 | 
                throw new ProviderException("Secmod module already configured"); | 
 | 
            }  | 
 | 
            library = nssModule.libraryName;  | 
 | 
            slotListIndex = nssModule.slot;  | 
 | 
        }  | 
 | 
        this.nssUseSecmodTrust = nssUseSecmodTrust;  | 
 | 
        this.nssModule = nssModule;  | 
 | 
 | 
 | 
        File libraryFile = new File(library);  | 
 | 
        // if the filename is a simple filename without path  | 
 | 
        // (e.g. "libpkcs11.so"), it may refer to a library somewhere on the  | 
 | 
        // OS library search path. Omit the test for file existance as that  | 
 | 
          | 
 | 
        if (libraryFile.getName().equals(library) == false) { | 
 | 
            if (new File(library).isFile() == false) { | 
 | 
                String msg = "Library " + library + " does not exist";  | 
 | 
                if (config.getHandleStartupErrors() == Config.ERR_HALT) { | 
 | 
                    throw new ProviderException(msg);  | 
 | 
                } else { | 
 | 
                    throw new UnsupportedOperationException(msg);  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        try { | 
 | 
            if (debug != null) { | 
 | 
                debug.println("Initializing PKCS#11 library " + library); | 
 | 
            }  | 
 | 
            CK_C_INITIALIZE_ARGS initArgs = new CK_C_INITIALIZE_ARGS();  | 
 | 
            String nssArgs = config.getNssArgs();  | 
 | 
            if (nssArgs != null) { | 
 | 
                initArgs.pReserved = nssArgs;  | 
 | 
            }  | 
 | 
              | 
 | 
            initArgs.flags = CKF_OS_LOCKING_OK;  | 
 | 
            PKCS11 tmpPKCS11;  | 
 | 
            try { | 
 | 
                tmpPKCS11 = PKCS11.getInstance(  | 
 | 
                    library, functionList, initArgs,  | 
 | 
                    config.getOmitInitialize());  | 
 | 
            } catch (PKCS11Exception e) { | 
 | 
                if (debug != null) { | 
 | 
                    debug.println("Multi-threaded initialization failed: " + e); | 
 | 
                }  | 
 | 
                if (config.getAllowSingleThreadedModules() == false) { | 
 | 
                    throw e;  | 
 | 
                }  | 
 | 
                  | 
 | 
                if (nssArgs == null) { | 
 | 
                      | 
 | 
                    initArgs = null;  | 
 | 
                } else { | 
 | 
                    initArgs.flags = 0;  | 
 | 
                }  | 
 | 
                tmpPKCS11 = PKCS11.getInstance(library,  | 
 | 
                    functionList, initArgs, config.getOmitInitialize());  | 
 | 
            }  | 
 | 
            p11 = tmpPKCS11;  | 
 | 
 | 
 | 
            CK_INFO p11Info = p11.C_GetInfo();  | 
 | 
            if (p11Info.cryptokiVersion.major < 2) { | 
 | 
                throw new ProviderException("Only PKCS#11 v2.0 and later " | 
 | 
                + "supported, library version is v" + p11Info.cryptokiVersion);  | 
 | 
            }  | 
 | 
            boolean showInfo = config.getShowInfo();  | 
 | 
            if (showInfo) { | 
 | 
                System.out.println("Information for provider " + getName()); | 
 | 
                System.out.println("Library info:"); | 
 | 
                System.out.println(p11Info);  | 
 | 
            }  | 
 | 
 | 
 | 
            if ((slotID < 0) || showInfo) { | 
 | 
                long[] slots = p11.C_GetSlotList(false);  | 
 | 
                if (showInfo) { | 
 | 
                    System.out.println("All slots: " + toString(slots)); | 
 | 
                    slots = p11.C_GetSlotList(true);  | 
 | 
                    System.out.println("Slots with tokens: " + toString(slots)); | 
 | 
                }  | 
 | 
                if (slotID < 0) { | 
 | 
                    if ((slotListIndex < 0)  | 
 | 
                            || (slotListIndex >= slots.length)) { | 
 | 
                        throw new ProviderException("slotListIndex is " | 
 | 
                            + slotListIndex  | 
 | 
                            + " but token only has " + slots.length + " slots");  | 
 | 
                    }  | 
 | 
                    slotID = slots[slotListIndex];  | 
 | 
                }  | 
 | 
            }  | 
 | 
            this.slotID = slotID;  | 
 | 
            CK_SLOT_INFO slotInfo = p11.C_GetSlotInfo(slotID);  | 
 | 
            removable = (slotInfo.flags & CKF_REMOVABLE_DEVICE) != 0;  | 
 | 
            initToken(slotInfo);  | 
 | 
            if (nssModule != null) { | 
 | 
                nssModule.setProvider(this);  | 
 | 
            }  | 
 | 
        } catch (Exception e) { | 
 | 
            if (config.getHandleStartupErrors() == Config.ERR_IGNORE_ALL) { | 
 | 
                throw new UnsupportedOperationException  | 
 | 
                        ("Initialization failed", e); | 
 | 
            } else { | 
 | 
                throw new ProviderException  | 
 | 
                        ("Initialization failed", e); | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private static String toString(long[] longs) { | 
 | 
        if (longs.length == 0) { | 
 | 
            return "(none)";  | 
 | 
        }  | 
 | 
        StringBuilder sb = new StringBuilder();  | 
 | 
        sb.append(longs[0]);  | 
 | 
        for (int i = 1; i < longs.length; i++) { | 
 | 
            sb.append(", "); | 
 | 
            sb.append(longs[i]);  | 
 | 
        }  | 
 | 
        return sb.toString();  | 
 | 
    }  | 
 | 
 | 
 | 
    public boolean equals(Object obj) { | 
 | 
        return this == obj;  | 
 | 
    }  | 
 | 
 | 
 | 
    public int hashCode() { | 
 | 
        return System.identityHashCode(this);  | 
 | 
    }  | 
 | 
 | 
 | 
    private static String[] s(String ...aliases) { | 
 | 
        return aliases;  | 
 | 
    }  | 
 | 
 | 
 | 
    private static final class Descriptor { | 
 | 
        final String type;  | 
 | 
        final String algorithm;  | 
 | 
        final String className;  | 
 | 
        final String[] aliases;  | 
 | 
        final int[] mechanisms;  | 
 | 
 | 
 | 
        private Descriptor(String type, String algorithm, String className,  | 
 | 
                String[] aliases, int[] mechanisms) { | 
 | 
            this.type = type;  | 
 | 
            this.algorithm = algorithm;  | 
 | 
            this.className = className;  | 
 | 
            this.aliases = aliases;  | 
 | 
            this.mechanisms = mechanisms;  | 
 | 
        }  | 
 | 
        private P11Service service(Token token, int mechanism) { | 
 | 
            return new P11Service  | 
 | 
                (token, type, algorithm, className, aliases, mechanism);  | 
 | 
        }  | 
 | 
        public String toString() { | 
 | 
            return type + "." + algorithm;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    // Map from mechanism to List of Descriptors that should be  | 
 | 
      | 
 | 
    private final static Map<Integer,List<Descriptor>> descriptors =  | 
 | 
        new HashMap<Integer,List<Descriptor>>();  | 
 | 
 | 
 | 
    private static int[] m(long m1) { | 
 | 
        return new int[] {(int)m1}; | 
 | 
    }  | 
 | 
 | 
 | 
    private static int[] m(long m1, long m2) { | 
 | 
        return new int[] {(int)m1, (int)m2}; | 
 | 
    }  | 
 | 
 | 
 | 
    private static int[] m(long m1, long m2, long m3) { | 
 | 
        return new int[] {(int)m1, (int)m2, (int)m3}; | 
 | 
    }  | 
 | 
 | 
 | 
    private static int[] m(long m1, long m2, long m3, long m4) { | 
 | 
        return new int[] {(int)m1, (int)m2, (int)m3, (int)m4}; | 
 | 
    }  | 
 | 
 | 
 | 
    private static void d(String type, String algorithm, String className,  | 
 | 
            int[] m) { | 
 | 
        register(new Descriptor(type, algorithm, className, null, m));  | 
 | 
    }  | 
 | 
 | 
 | 
    private static void d(String type, String algorithm, String className,  | 
 | 
            String[] aliases, int[] m) { | 
 | 
        register(new Descriptor(type, algorithm, className, aliases, m));  | 
 | 
    }  | 
 | 
 | 
 | 
    private static void register(Descriptor d) { | 
 | 
        for (int i = 0; i < d.mechanisms.length; i++) { | 
 | 
            int m = d.mechanisms[i];  | 
 | 
            Integer key = Integer.valueOf(m);  | 
 | 
            List<Descriptor> list = descriptors.get(key);  | 
 | 
            if (list == null) { | 
 | 
                list = new ArrayList<Descriptor>();  | 
 | 
                descriptors.put(key, list);  | 
 | 
            }  | 
 | 
            list.add(d);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private final static String MD  = "MessageDigest";  | 
 | 
 | 
 | 
    private final static String SIG = "Signature";  | 
 | 
 | 
 | 
    private final static String KPG = "KeyPairGenerator";  | 
 | 
 | 
 | 
    private final static String KG  = "KeyGenerator";  | 
 | 
 | 
 | 
    private final static String AGP = "AlgorithmParameters";  | 
 | 
 | 
 | 
    private final static String KF  = "KeyFactory";  | 
 | 
 | 
 | 
    private final static String SKF = "SecretKeyFactory";  | 
 | 
 | 
 | 
    private final static String CIP = "Cipher";  | 
 | 
 | 
 | 
    private final static String MAC = "Mac";  | 
 | 
 | 
 | 
    private final static String KA  = "KeyAgreement";  | 
 | 
 | 
 | 
    private final static String KS  = "KeyStore";  | 
 | 
 | 
 | 
    private final static String SR  = "SecureRandom";  | 
 | 
 | 
 | 
    static { | 
 | 
        // names of all the implementation classes  | 
 | 
          | 
 | 
        String P11Digest           = "sun.security.pkcs11.P11Digest";  | 
 | 
        String P11MAC              = "sun.security.pkcs11.P11MAC";  | 
 | 
        String P11KeyPairGenerator = "sun.security.pkcs11.P11KeyPairGenerator";  | 
 | 
        String P11KeyGenerator     = "sun.security.pkcs11.P11KeyGenerator";  | 
 | 
        String P11RSAKeyFactory    = "sun.security.pkcs11.P11RSAKeyFactory";  | 
 | 
        String P11DSAKeyFactory    = "sun.security.pkcs11.P11DSAKeyFactory";  | 
 | 
        String P11DHKeyFactory     = "sun.security.pkcs11.P11DHKeyFactory";  | 
 | 
        String P11KeyAgreement     = "sun.security.pkcs11.P11KeyAgreement";  | 
 | 
        String P11SecretKeyFactory = "sun.security.pkcs11.P11SecretKeyFactory";  | 
 | 
        String P11Cipher           = "sun.security.pkcs11.P11Cipher";  | 
 | 
        String P11RSACipher        = "sun.security.pkcs11.P11RSACipher";  | 
 | 
        String P11AEADCipher       = "sun.security.pkcs11.P11AEADCipher";  | 
 | 
        String P11Signature        = "sun.security.pkcs11.P11Signature";  | 
 | 
        String P11PSSSignature     = "sun.security.pkcs11.P11PSSSignature";  | 
 | 
 | 
 | 
        // XXX register all aliases  | 
 | 
 | 
 | 
        d(MD, "MD2",            P11Digest,  | 
 | 
                m(CKM_MD2));  | 
 | 
        d(MD, "MD5",            P11Digest,  | 
 | 
                m(CKM_MD5));  | 
 | 
        d(MD, "SHA1",           P11Digest,  | 
 | 
                s("SHA", "SHA-1", "1.3.14.3.2.26", "OID.1.3.14.3.2.26"), | 
 | 
                m(CKM_SHA_1));  | 
 | 
 | 
 | 
        d(MD, "SHA-224",        P11Digest,  | 
 | 
                s("2.16.840.1.101.3.4.2.4", "OID.2.16.840.1.101.3.4.2.4"), | 
 | 
                m(CKM_SHA224));  | 
 | 
        d(MD, "SHA-256",        P11Digest,  | 
 | 
                s("2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1"), | 
 | 
                m(CKM_SHA256));  | 
 | 
        d(MD, "SHA-384",        P11Digest,  | 
 | 
                s("2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2"), | 
 | 
                m(CKM_SHA384));  | 
 | 
        d(MD, "SHA-512",        P11Digest,  | 
 | 
                s("2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3"), | 
 | 
                m(CKM_SHA512));  | 
 | 
        d(MD, "SHA-512/224",        P11Digest,  | 
 | 
                s("2.16.840.1.101.3.4.2.5", "OID.2.16.840.1.101.3.4.2.5"), | 
 | 
                m(CKM_SHA512_224));  | 
 | 
        d(MD, "SHA-512/256",        P11Digest,  | 
 | 
                s("2.16.840.1.101.3.4.2.6", "OID.2.16.840.1.101.3.4.2.6"), | 
 | 
                m(CKM_SHA512_256));  | 
 | 
 | 
 | 
        d(MAC, "HmacMD5",       P11MAC,  | 
 | 
                m(CKM_MD5_HMAC));  | 
 | 
        d(MAC, "HmacSHA1",      P11MAC,  | 
 | 
                s("1.2.840.113549.2.7", "OID.1.2.840.113549.2.7"), | 
 | 
                m(CKM_SHA_1_HMAC));  | 
 | 
        d(MAC, "HmacSHA224",    P11MAC,  | 
 | 
                s("1.2.840.113549.2.8", "OID.1.2.840.113549.2.8"), | 
 | 
                m(CKM_SHA224_HMAC));  | 
 | 
        d(MAC, "HmacSHA256",    P11MAC,  | 
 | 
                s("1.2.840.113549.2.9", "OID.1.2.840.113549.2.9"), | 
 | 
                m(CKM_SHA256_HMAC));  | 
 | 
        d(MAC, "HmacSHA384",    P11MAC,  | 
 | 
                s("1.2.840.113549.2.10", "OID.1.2.840.113549.2.10"), | 
 | 
                m(CKM_SHA384_HMAC));  | 
 | 
        d(MAC, "HmacSHA512",    P11MAC,  | 
 | 
                s("1.2.840.113549.2.11", "OID.1.2.840.113549.2.11"), | 
 | 
                m(CKM_SHA512_HMAC));  | 
 | 
        d(MAC, "HmacSHA512/224",    P11MAC,  | 
 | 
                s("1.2.840.113549.2.12", "OID.1.2.840.113549.2.12"), | 
 | 
                m(CKM_SHA512_224_HMAC));  | 
 | 
        d(MAC, "HmacSHA512/256",    P11MAC,  | 
 | 
                s("1.2.840.113549.2.13", "OID.1.2.840.113549.2.13"), | 
 | 
                m(CKM_SHA512_256_HMAC));  | 
 | 
 | 
 | 
        d(MAC, "SslMacMD5",     P11MAC,  | 
 | 
                m(CKM_SSL3_MD5_MAC));  | 
 | 
        d(MAC, "SslMacSHA1",    P11MAC,  | 
 | 
                m(CKM_SSL3_SHA1_MAC));  | 
 | 
 | 
 | 
        d(KPG, "RSA",           P11KeyPairGenerator,  | 
 | 
                s("1.2.840.113549.1.1", "OID.1.2.840.113549.1.1"), | 
 | 
                m(CKM_RSA_PKCS_KEY_PAIR_GEN));  | 
 | 
 | 
 | 
        d(KPG, "DSA",           P11KeyPairGenerator,  | 
 | 
                s("1.3.14.3.2.12", "1.2.840.10040.4.1", "OID.1.2.840.10040.4.1"), | 
 | 
                m(CKM_DSA_KEY_PAIR_GEN));  | 
 | 
        d(KPG, "DH",            P11KeyPairGenerator,    s("DiffieHellman"), | 
 | 
                m(CKM_DH_PKCS_KEY_PAIR_GEN));  | 
 | 
        d(KPG, "EC",            P11KeyPairGenerator,  | 
 | 
                m(CKM_EC_KEY_PAIR_GEN));  | 
 | 
 | 
 | 
        d(KG,  "ARCFOUR",       P11KeyGenerator,        s("RC4"), | 
 | 
                m(CKM_RC4_KEY_GEN));  | 
 | 
        d(KG,  "DES",           P11KeyGenerator,  | 
 | 
                m(CKM_DES_KEY_GEN));  | 
 | 
        d(KG,  "DESede",        P11KeyGenerator,  | 
 | 
                m(CKM_DES3_KEY_GEN, CKM_DES2_KEY_GEN));  | 
 | 
        d(KG,  "AES",           P11KeyGenerator,  | 
 | 
                m(CKM_AES_KEY_GEN));  | 
 | 
        d(KG,  "Blowfish",      P11KeyGenerator,  | 
 | 
                m(CKM_BLOWFISH_KEY_GEN));  | 
 | 
 | 
 | 
        // register (Secret)KeyFactories if there are any mechanisms  | 
 | 
          | 
 | 
        d(KF, "RSA",            P11RSAKeyFactory,  | 
 | 
                s("1.2.840.113549.1.1", "OID.1.2.840.113549.1.1"), | 
 | 
                m(CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_RSA_PKCS, CKM_RSA_X_509));  | 
 | 
        d(KF, "DSA",            P11DSAKeyFactory,  | 
 | 
                s("1.3.14.3.2.12", "1.2.840.10040.4.1", "OID.1.2.840.10040.4.1"), | 
 | 
                m(CKM_DSA_KEY_PAIR_GEN, CKM_DSA, CKM_DSA_SHA1));  | 
 | 
        d(KF, "DH",             P11DHKeyFactory,        s("DiffieHellman"), | 
 | 
                m(CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE));  | 
 | 
        d(KF, "EC",             P11DHKeyFactory,  | 
 | 
                m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,  | 
 | 
                    CKM_ECDSA, CKM_ECDSA_SHA1));  | 
 | 
 | 
 | 
        // AlgorithmParameters for EC.  | 
 | 
          | 
 | 
        d(AGP, "EC",            "sun.security.util.ECParameters",  | 
 | 
                s("1.2.840.10045.2.1"), | 
 | 
                m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,  | 
 | 
                    CKM_ECDSA, CKM_ECDSA_SHA1));  | 
 | 
 | 
 | 
        d(AGP, "GCM",            "sun.security.util.GCMParameters",  | 
 | 
                m(CKM_AES_GCM));  | 
 | 
 | 
 | 
        d(KA, "DH",             P11KeyAgreement,        s("DiffieHellman"), | 
 | 
                m(CKM_DH_PKCS_DERIVE));  | 
 | 
        d(KA, "ECDH",           "sun.security.pkcs11.P11ECDHKeyAgreement",  | 
 | 
                m(CKM_ECDH1_DERIVE));  | 
 | 
 | 
 | 
        d(SKF, "ARCFOUR",       P11SecretKeyFactory,    s("RC4"), | 
 | 
                m(CKM_RC4));  | 
 | 
        d(SKF, "DES",           P11SecretKeyFactory,  | 
 | 
                m(CKM_DES_CBC));  | 
 | 
        d(SKF, "DESede",        P11SecretKeyFactory,  | 
 | 
                m(CKM_DES3_CBC));  | 
 | 
        d(SKF, "AES",           P11SecretKeyFactory,  | 
 | 
                s("2.16.840.1.101.3.4.1", "OID.2.16.840.1.101.3.4.1"), | 
 | 
                m(CKM_AES_CBC));  | 
 | 
        d(SKF, "Blowfish",      P11SecretKeyFactory,  | 
 | 
                m(CKM_BLOWFISH_CBC));  | 
 | 
 | 
 | 
          | 
 | 
        d(CIP, "ARCFOUR",                       P11Cipher,      s("RC4"), | 
 | 
                m(CKM_RC4));  | 
 | 
        d(CIP, "DES/CBC/NoPadding",             P11Cipher,  | 
 | 
                m(CKM_DES_CBC));  | 
 | 
        d(CIP, "DES/CBC/PKCS5Padding",          P11Cipher,  | 
 | 
                m(CKM_DES_CBC_PAD, CKM_DES_CBC));  | 
 | 
        d(CIP, "DES/ECB/NoPadding",             P11Cipher,  | 
 | 
                m(CKM_DES_ECB));  | 
 | 
        d(CIP, "DES/ECB/PKCS5Padding",          P11Cipher,      s("DES"), | 
 | 
                m(CKM_DES_ECB));  | 
 | 
 | 
 | 
        d(CIP, "DESede/CBC/NoPadding",          P11Cipher,  | 
 | 
                m(CKM_DES3_CBC));  | 
 | 
        d(CIP, "DESede/CBC/PKCS5Padding",       P11Cipher,  | 
 | 
                m(CKM_DES3_CBC_PAD, CKM_DES3_CBC));  | 
 | 
        d(CIP, "DESede/ECB/NoPadding",          P11Cipher,  | 
 | 
                m(CKM_DES3_ECB));  | 
 | 
        d(CIP, "DESede/ECB/PKCS5Padding",       P11Cipher,      s("DESede"), | 
 | 
                m(CKM_DES3_ECB));  | 
 | 
        d(CIP, "AES/CBC/NoPadding",             P11Cipher,  | 
 | 
                m(CKM_AES_CBC));  | 
 | 
        d(CIP, "AES_128/CBC/NoPadding",          P11Cipher,  | 
 | 
                s("2.16.840.1.101.3.4.1.2", "OID.2.16.840.1.101.3.4.1.2"), | 
 | 
                m(CKM_AES_CBC));  | 
 | 
        d(CIP, "AES_192/CBC/NoPadding",          P11Cipher,  | 
 | 
                s("2.16.840.1.101.3.4.1.22", "OID.2.16.840.1.101.3.4.1.22"), | 
 | 
                m(CKM_AES_CBC));  | 
 | 
        d(CIP, "AES_256/CBC/NoPadding",          P11Cipher,  | 
 | 
                s("2.16.840.1.101.3.4.1.42", "OID.2.16.840.1.101.3.4.1.42"), | 
 | 
                m(CKM_AES_CBC));  | 
 | 
        d(CIP, "AES/CBC/PKCS5Padding",          P11Cipher,  | 
 | 
                m(CKM_AES_CBC_PAD, CKM_AES_CBC));  | 
 | 
        d(CIP, "AES/ECB/NoPadding",             P11Cipher,  | 
 | 
                m(CKM_AES_ECB));  | 
 | 
        d(CIP, "AES_128/ECB/NoPadding",          P11Cipher,  | 
 | 
                s("2.16.840.1.101.3.4.1.1", "OID.2.16.840.1.101.3.4.1.1"), | 
 | 
                m(CKM_AES_ECB));  | 
 | 
        d(CIP, "AES_192/ECB/NoPadding",          P11Cipher,  | 
 | 
                s("2.16.840.1.101.3.4.1.21", "OID.2.16.840.1.101.3.4.1.21"), | 
 | 
                m(CKM_AES_ECB));  | 
 | 
        d(CIP, "AES_256/ECB/NoPadding",          P11Cipher,  | 
 | 
                s("2.16.840.1.101.3.4.1.41", "OID.2.16.840.1.101.3.4.1.41"), | 
 | 
                m(CKM_AES_ECB));  | 
 | 
        d(CIP, "AES/ECB/PKCS5Padding",          P11Cipher,      s("AES"), | 
 | 
                m(CKM_AES_ECB));  | 
 | 
        d(CIP, "AES/CTR/NoPadding",             P11Cipher,  | 
 | 
                m(CKM_AES_CTR));  | 
 | 
 | 
 | 
        d(CIP, "AES/GCM/NoPadding",             P11AEADCipher,  | 
 | 
                m(CKM_AES_GCM));  | 
 | 
        d(CIP, "AES_128/GCM/NoPadding",          P11AEADCipher,  | 
 | 
                s("2.16.840.1.101.3.4.1.6", "OID.2.16.840.1.101.3.4.1.6"), | 
 | 
                m(CKM_AES_GCM));  | 
 | 
        d(CIP, "AES_192/GCM/NoPadding",          P11AEADCipher,  | 
 | 
                s("2.16.840.1.101.3.4.1.26", "OID.2.16.840.1.101.3.4.1.26"), | 
 | 
                m(CKM_AES_GCM));  | 
 | 
        d(CIP, "AES_256/GCM/NoPadding",          P11AEADCipher,  | 
 | 
                s("2.16.840.1.101.3.4.1.46", "OID.2.16.840.1.101.3.4.1.46"), | 
 | 
                m(CKM_AES_GCM));  | 
 | 
 | 
 | 
        d(CIP, "Blowfish/CBC/NoPadding",        P11Cipher,  | 
 | 
                m(CKM_BLOWFISH_CBC));  | 
 | 
        d(CIP, "Blowfish/CBC/PKCS5Padding",     P11Cipher,  | 
 | 
                m(CKM_BLOWFISH_CBC));  | 
 | 
 | 
 | 
        d(CIP, "RSA/ECB/PKCS1Padding",          P11RSACipher,   s("RSA"), | 
 | 
                m(CKM_RSA_PKCS));  | 
 | 
        d(CIP, "RSA/ECB/NoPadding",             P11RSACipher,  | 
 | 
                m(CKM_RSA_X_509));  | 
 | 
 | 
 | 
        d(SIG, "RawDSA",        P11Signature,   s("NONEwithDSA"), | 
 | 
                m(CKM_DSA));  | 
 | 
        d(SIG, "DSA",           P11Signature,  | 
 | 
                s("SHA1withDSA", "1.3.14.3.2.13", "1.3.14.3.2.27", | 
 | 
                  "1.2.840.10040.4.3", "OID.1.2.840.10040.4.3"),  | 
 | 
                m(CKM_DSA_SHA1, CKM_DSA));  | 
 | 
        d(SIG, "SHA224withDSA", P11Signature,  | 
 | 
                s("2.16.840.1.101.3.4.3.1", "OID.2.16.840.1.101.3.4.3.1"), | 
 | 
                m(CKM_DSA_SHA224));  | 
 | 
        d(SIG, "SHA256withDSA", P11Signature,  | 
 | 
                s("2.16.840.1.101.3.4.3.2", "OID.2.16.840.1.101.3.4.3.2"), | 
 | 
                m(CKM_DSA_SHA256));  | 
 | 
        d(SIG, "SHA384withDSA", P11Signature,  | 
 | 
                s("2.16.840.1.101.3.4.3.3", "OID.2.16.840.1.101.3.4.3.3"), | 
 | 
                m(CKM_DSA_SHA384));  | 
 | 
        d(SIG, "SHA512withDSA", P11Signature,  | 
 | 
                s("2.16.840.1.101.3.4.3.4", "OID.2.16.840.1.101.3.4.3.4"), | 
 | 
                m(CKM_DSA_SHA512));  | 
 | 
 | 
 | 
        d(SIG, "NONEwithECDSA", P11Signature,  | 
 | 
                m(CKM_ECDSA));  | 
 | 
        d(SIG, "SHA1withECDSA", P11Signature,  | 
 | 
                s("ECDSA", "1.2.840.10045.4.1", "OID.1.2.840.10045.4.1"), | 
 | 
                m(CKM_ECDSA_SHA1, CKM_ECDSA));  | 
 | 
        d(SIG, "SHA224withECDSA",       P11Signature,  | 
 | 
                s("1.2.840.10045.4.3.1", "OID.1.2.840.10045.4.3.1"), | 
 | 
                m(CKM_ECDSA));  | 
 | 
        d(SIG, "SHA256withECDSA",       P11Signature,  | 
 | 
                s("1.2.840.10045.4.3.2", "OID.1.2.840.10045.4.3.2"), | 
 | 
                m(CKM_ECDSA));  | 
 | 
        d(SIG, "SHA384withECDSA",       P11Signature,  | 
 | 
                s("1.2.840.10045.4.3.3", "OID.1.2.840.10045.4.3.3"), | 
 | 
                m(CKM_ECDSA));  | 
 | 
        d(SIG, "SHA512withECDSA",       P11Signature,  | 
 | 
                s("1.2.840.10045.4.3.4", "OID.1.2.840.10045.4.3.4"), | 
 | 
                m(CKM_ECDSA));  | 
 | 
        d(SIG, "MD2withRSA",    P11Signature,  | 
 | 
                s("1.2.840.113549.1.1.2", "OID.1.2.840.113549.1.1.2"), | 
 | 
                m(CKM_MD2_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));  | 
 | 
        d(SIG, "MD5withRSA",    P11Signature,  | 
 | 
                s("1.2.840.113549.1.1.4", "OID.1.2.840.113549.1.1.4"), | 
 | 
                m(CKM_MD5_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));  | 
 | 
        d(SIG, "SHA1withRSA",   P11Signature,  | 
 | 
                s("1.2.840.113549.1.1.5", "OID.1.2.840.113549.1.1.5", | 
 | 
                  "1.3.14.3.2.29"),  | 
 | 
                m(CKM_SHA1_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));  | 
 | 
        d(SIG, "SHA224withRSA", P11Signature,  | 
 | 
                s("1.2.840.113549.1.1.14", "OID.1.2.840.113549.1.1.14"), | 
 | 
                m(CKM_SHA224_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));  | 
 | 
        d(SIG, "SHA256withRSA", P11Signature,  | 
 | 
                s("1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11"), | 
 | 
                m(CKM_SHA256_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));  | 
 | 
        d(SIG, "SHA384withRSA", P11Signature,  | 
 | 
                s("1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12"), | 
 | 
                m(CKM_SHA384_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));  | 
 | 
        d(SIG, "SHA512withRSA", P11Signature,  | 
 | 
                s("1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13"), | 
 | 
                m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));  | 
 | 
        d(SIG, "RSASSA-PSS", P11PSSSignature,  | 
 | 
                s("1.2.840.113549.1.1.10", "OID.1.2.840.113549.1.1.10"), | 
 | 
                m(CKM_RSA_PKCS_PSS));  | 
 | 
        d(SIG, "SHA1withRSASSA-PSS", P11PSSSignature,  | 
 | 
                m(CKM_SHA1_RSA_PKCS_PSS));  | 
 | 
        d(SIG, "SHA224withRSASSA-PSS", P11PSSSignature,  | 
 | 
                m(CKM_SHA224_RSA_PKCS_PSS));  | 
 | 
        d(SIG, "SHA256withRSASSA-PSS", P11PSSSignature,  | 
 | 
                m(CKM_SHA256_RSA_PKCS_PSS));  | 
 | 
        d(SIG, "SHA384withRSASSA-PSS", P11PSSSignature,  | 
 | 
                m(CKM_SHA384_RSA_PKCS_PSS));  | 
 | 
        d(SIG, "SHA512withRSASSA-PSS", P11PSSSignature,  | 
 | 
                m(CKM_SHA512_RSA_PKCS_PSS));  | 
 | 
 | 
 | 
        d(KG, "SunTlsRsaPremasterSecret",  | 
 | 
                    "sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",  | 
 | 
                    s("SunTls12RsaPremasterSecret"), | 
 | 
                m(CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_PRE_MASTER_KEY_GEN));  | 
 | 
        d(KG, "SunTlsMasterSecret",  | 
 | 
                    "sun.security.pkcs11.P11TlsMasterSecretGenerator",  | 
 | 
                m(CKM_SSL3_MASTER_KEY_DERIVE, CKM_TLS_MASTER_KEY_DERIVE,  | 
 | 
                    CKM_SSL3_MASTER_KEY_DERIVE_DH,  | 
 | 
                    CKM_TLS_MASTER_KEY_DERIVE_DH));  | 
 | 
        d(KG, "SunTls12MasterSecret",  | 
 | 
                "sun.security.pkcs11.P11TlsMasterSecretGenerator",  | 
 | 
            m(CKM_TLS12_MASTER_KEY_DERIVE, CKM_TLS12_MASTER_KEY_DERIVE_DH));  | 
 | 
        d(KG, "SunTlsKeyMaterial",  | 
 | 
                    "sun.security.pkcs11.P11TlsKeyMaterialGenerator",  | 
 | 
                m(CKM_SSL3_KEY_AND_MAC_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE));  | 
 | 
        d(KG, "SunTls12KeyMaterial",  | 
 | 
                "sun.security.pkcs11.P11TlsKeyMaterialGenerator",  | 
 | 
            m(CKM_TLS12_KEY_AND_MAC_DERIVE));  | 
 | 
        d(KG, "SunTlsPrf", "sun.security.pkcs11.P11TlsPrfGenerator",  | 
 | 
                m(CKM_TLS_PRF, CKM_NSS_TLS_PRF_GENERAL));  | 
 | 
        d(KG, "SunTls12Prf", "sun.security.pkcs11.P11TlsPrfGenerator",  | 
 | 
                m(CKM_TLS_MAC));  | 
 | 
    }  | 
 | 
 | 
 | 
    // background thread that periodically checks for token insertion  | 
 | 
    // if no token is present. We need to do that in a separate thread because  | 
 | 
      | 
 | 
    private static class TokenPoller implements Runnable { | 
 | 
        private final SunPKCS11 provider;  | 
 | 
        private volatile boolean enabled;  | 
 | 
        private TokenPoller(SunPKCS11 provider) { | 
 | 
            this.provider = provider;  | 
 | 
            enabled = true;  | 
 | 
        }  | 
 | 
        public void run() { | 
 | 
            int interval = provider.config.getInsertionCheckInterval();  | 
 | 
            while (enabled) { | 
 | 
                try { | 
 | 
                    Thread.sleep(interval);  | 
 | 
                } catch (InterruptedException e) { | 
 | 
                    break;  | 
 | 
                }  | 
 | 
                if (enabled == false) { | 
 | 
                    break;  | 
 | 
                }  | 
 | 
                try { | 
 | 
                    provider.initToken(null);  | 
 | 
                } catch (PKCS11Exception e) { | 
 | 
                    // ignore  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
        void disable() { | 
 | 
            enabled = false;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    private void createPoller() { | 
 | 
        if (poller != null) { | 
 | 
            return;  | 
 | 
        }  | 
 | 
        TokenPoller poller = new TokenPoller(this);  | 
 | 
        Thread t = new Thread(poller, "Poller " + getName());  | 
 | 
        t.setDaemon(true);  | 
 | 
        t.setPriority(Thread.MIN_PRIORITY);  | 
 | 
        t.start();  | 
 | 
        this.poller = poller;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    private void destroyPoller() { | 
 | 
        if (poller != null) { | 
 | 
            poller.disable();  | 
 | 
            poller = null;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private boolean hasValidToken() { | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
        */  | 
 | 
        Token token = this.token;  | 
 | 
        return (token != null) && token.isValid();  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
    synchronized void uninitToken(Token token) { | 
 | 
        if (this.token != token) { | 
 | 
              | 
 | 
            return;  | 
 | 
        }  | 
 | 
        destroyPoller();  | 
 | 
        this.token = null;  | 
 | 
          | 
 | 
        AccessController.doPrivileged(new PrivilegedAction<Object>() { | 
 | 
            public Object run() { | 
 | 
                clear();  | 
 | 
                return null;  | 
 | 
            }  | 
 | 
        });  | 
 | 
        createPoller();  | 
 | 
    }  | 
 | 
 | 
 | 
    // test if a token is present and initialize this provider for it if so.  | 
 | 
    // does nothing if no token is found  | 
 | 
      | 
 | 
    private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception { | 
 | 
        if (slotInfo == null) { | 
 | 
            slotInfo = p11.C_GetSlotInfo(slotID);  | 
 | 
        }  | 
 | 
        if (removable && (slotInfo.flags & CKF_TOKEN_PRESENT) == 0) { | 
 | 
            createPoller();  | 
 | 
            return;  | 
 | 
        }  | 
 | 
        destroyPoller();  | 
 | 
        boolean showInfo = config.getShowInfo();  | 
 | 
        if (showInfo) { | 
 | 
            System.out.println("Slot info for slot " + slotID + ":"); | 
 | 
            System.out.println(slotInfo);  | 
 | 
        }  | 
 | 
        final Token token = new Token(this);  | 
 | 
        if (showInfo) { | 
 | 
            System.out.println  | 
 | 
                ("Token info for token in slot " + slotID + ":"); | 
 | 
            System.out.println(token.tokenInfo);  | 
 | 
        }  | 
 | 
        long[] supportedMechanisms = p11.C_GetMechanismList(slotID);  | 
 | 
 | 
 | 
        // Create a map from the various Descriptors to the "most  | 
 | 
        // preferred" mechanism that was defined during the  | 
 | 
        // static initialization.  For example, DES/CBC/PKCS5Padding  | 
 | 
        // could be mapped to CKM_DES_CBC_PAD or CKM_DES_CBC.  Prefer  | 
 | 
        // the earliest entry.  When asked for "DES/CBC/PKCS5Padding", we  | 
 | 
          | 
 | 
        final Map<Descriptor,Integer> supportedAlgs =  | 
 | 
                                        new HashMap<Descriptor,Integer>();  | 
 | 
        for (int i = 0; i < supportedMechanisms.length; i++) { | 
 | 
            long longMech = supportedMechanisms[i];  | 
 | 
            boolean isEnabled = config.isEnabled(longMech);  | 
 | 
            if (showInfo) { | 
 | 
                CK_MECHANISM_INFO mechInfo =  | 
 | 
                        p11.C_GetMechanismInfo(slotID, longMech);  | 
 | 
                System.out.println("Mechanism " + | 
 | 
                        Functions.getMechanismName(longMech) + ":");  | 
 | 
                if (isEnabled == false) { | 
 | 
                    System.out.println("DISABLED in configuration"); | 
 | 
                }  | 
 | 
                System.out.println(mechInfo);  | 
 | 
            }  | 
 | 
            if (isEnabled == false) { | 
 | 
                continue;  | 
 | 
            }  | 
 | 
              | 
 | 
            if (longMech >>> 32 != 0) { | 
 | 
                continue;  | 
 | 
            }  | 
 | 
            int mech = (int)longMech;  | 
 | 
            Integer integerMech = Integer.valueOf(mech);  | 
 | 
            List<Descriptor> ds = descriptors.get(integerMech);  | 
 | 
            if (ds == null) { | 
 | 
                continue;  | 
 | 
            }  | 
 | 
            for (Descriptor d : ds) { | 
 | 
                Integer oldMech = supportedAlgs.get(d);  | 
 | 
                if (oldMech == null) { | 
 | 
                    supportedAlgs.put(d, integerMech);  | 
 | 
                    continue;  | 
 | 
                }  | 
 | 
                // See if there is something "more preferred"  | 
 | 
                // than what we currently have in the supportedAlgs  | 
 | 
                  | 
 | 
                int intOldMech = oldMech.intValue();  | 
 | 
                for (int j = 0; j < d.mechanisms.length; j++) { | 
 | 
                    int nextMech = d.mechanisms[j];  | 
 | 
                    if (mech == nextMech) { | 
 | 
                        supportedAlgs.put(d, integerMech);  | 
 | 
                        break;  | 
 | 
                    } else if (intOldMech == nextMech) { | 
 | 
                        break;  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
 | 
 | 
        }  | 
 | 
 | 
 | 
          | 
 | 
        AccessController.doPrivileged(new PrivilegedAction<Object>() { | 
 | 
            public Object run() { | 
 | 
                for (Map.Entry<Descriptor,Integer> entry  | 
 | 
                        : supportedAlgs.entrySet()) { | 
 | 
                    Descriptor d = entry.getKey();  | 
 | 
                    int mechanism = entry.getValue().intValue();  | 
 | 
                    Service s = d.service(token, mechanism);  | 
 | 
                    putService(s);  | 
 | 
                }  | 
 | 
                if (((token.tokenInfo.flags & CKF_RNG) != 0)  | 
 | 
                        && config.isEnabled(PCKM_SECURERANDOM)  | 
 | 
                        && !token.sessionManager.lowMaxSessions()) { | 
 | 
                    // do not register SecureRandom if the token does  | 
 | 
                    // not support many sessions. if we did, we might  | 
 | 
                    // run out of sessions in the middle of a  | 
 | 
                      | 
 | 
                    putService(new P11Service(token, SR, "PKCS11",  | 
 | 
                        "sun.security.pkcs11.P11SecureRandom", null,  | 
 | 
                        PCKM_SECURERANDOM));  | 
 | 
                }  | 
 | 
                if (config.isEnabled(PCKM_KEYSTORE)) { | 
 | 
                    putService(new P11Service(token, KS, "PKCS11",  | 
 | 
                        "sun.security.pkcs11.P11KeyStore",  | 
 | 
                        s("PKCS11-" + config.getName()), | 
 | 
                        PCKM_KEYSTORE));  | 
 | 
                }  | 
 | 
                return null;  | 
 | 
            }  | 
 | 
        });  | 
 | 
 | 
 | 
        this.token = token;  | 
 | 
    }  | 
 | 
 | 
 | 
    private static final class P11Service extends Service { | 
 | 
 | 
 | 
        private final Token token;  | 
 | 
 | 
 | 
        private final long mechanism;  | 
 | 
 | 
 | 
        P11Service(Token token, String type, String algorithm,  | 
 | 
                String className, String[] al, long mechanism) { | 
 | 
            super(token.provider, type, algorithm, className, toList(al), null);  | 
 | 
            this.token = token;  | 
 | 
            this.mechanism = mechanism & 0xFFFFFFFFL;  | 
 | 
        }  | 
 | 
 | 
 | 
        private static List<String> toList(String[] aliases) { | 
 | 
            return (aliases == null) ? null : Arrays.asList(aliases);  | 
 | 
        }  | 
 | 
 | 
 | 
        public Object newInstance(Object param)  | 
 | 
                throws NoSuchAlgorithmException { | 
 | 
            if (token.isValid() == false) { | 
 | 
                throw new NoSuchAlgorithmException("Token has been removed"); | 
 | 
            }  | 
 | 
            try { | 
 | 
                return newInstance0(param);  | 
 | 
            } catch (PKCS11Exception e) { | 
 | 
                throw new NoSuchAlgorithmException(e);  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public Object newInstance0(Object param) throws  | 
 | 
                PKCS11Exception, NoSuchAlgorithmException { | 
 | 
            String algorithm = getAlgorithm();  | 
 | 
            String type = getType();  | 
 | 
            if (type == MD) { | 
 | 
                return new P11Digest(token, algorithm, mechanism);  | 
 | 
            } else if (type == CIP) { | 
 | 
                if (algorithm.startsWith("RSA")) { | 
 | 
                    return new P11RSACipher(token, algorithm, mechanism);  | 
 | 
                } else if (algorithm.endsWith("GCM/NoPadding")) { | 
 | 
                    return new P11AEADCipher(token, algorithm, mechanism);  | 
 | 
                } else { | 
 | 
                    return new P11Cipher(token, algorithm, mechanism);  | 
 | 
                }  | 
 | 
            } else if (type == SIG) { | 
 | 
                if (algorithm.indexOf("RSASSA-PSS") != -1) { | 
 | 
                    return new P11PSSSignature(token, algorithm, mechanism);  | 
 | 
                } else { | 
 | 
                    return new P11Signature(token, algorithm, mechanism);  | 
 | 
                }  | 
 | 
            } else if (type == MAC) { | 
 | 
                return new P11Mac(token, algorithm, mechanism);  | 
 | 
            } else if (type == KPG) { | 
 | 
                return new P11KeyPairGenerator(token, algorithm, mechanism);  | 
 | 
            } else if (type == KA) { | 
 | 
                if (algorithm.equals("ECDH")) { | 
 | 
                    return new P11ECDHKeyAgreement(token, algorithm, mechanism);  | 
 | 
                } else { | 
 | 
                    return new P11KeyAgreement(token, algorithm, mechanism);  | 
 | 
                }  | 
 | 
            } else if (type == KF) { | 
 | 
                return token.getKeyFactory(algorithm);  | 
 | 
            } else if (type == SKF) { | 
 | 
                return new P11SecretKeyFactory(token, algorithm);  | 
 | 
            } else if (type == KG) { | 
 | 
                  | 
 | 
                if (algorithm == "SunTlsRsaPremasterSecret") { | 
 | 
                    return new P11TlsRsaPremasterSecretGenerator(  | 
 | 
                        token, algorithm, mechanism);  | 
 | 
                } else if (algorithm == "SunTlsMasterSecret"  | 
 | 
                        || algorithm == "SunTls12MasterSecret") { | 
 | 
                    return new P11TlsMasterSecretGenerator(  | 
 | 
                        token, algorithm, mechanism);  | 
 | 
                } else if (algorithm == "SunTlsKeyMaterial"  | 
 | 
                        || algorithm == "SunTls12KeyMaterial") { | 
 | 
                    return new P11TlsKeyMaterialGenerator(  | 
 | 
                        token, algorithm, mechanism);  | 
 | 
                } else if (algorithm == "SunTlsPrf"  | 
 | 
                        || algorithm == "SunTls12Prf") { | 
 | 
                    return new P11TlsPrfGenerator(token, algorithm, mechanism);  | 
 | 
                } else { | 
 | 
                    return new P11KeyGenerator(token, algorithm, mechanism);  | 
 | 
                }  | 
 | 
            } else if (type == SR) { | 
 | 
                return token.getRandom();  | 
 | 
            } else if (type == KS) { | 
 | 
                return token.getKeyStore();  | 
 | 
            } else if (type == AGP) { | 
 | 
                if (algorithm == "EC") { | 
 | 
                    return new sun.security.util.ECParameters();  | 
 | 
                } else if (algorithm == "GCM") { | 
 | 
                    return new sun.security.util.GCMParameters();  | 
 | 
                } else { | 
 | 
                    throw new NoSuchAlgorithmException("Unsupported algorithm: " | 
 | 
                            + algorithm);  | 
 | 
                }  | 
 | 
            } else { | 
 | 
                throw new NoSuchAlgorithmException("Unknown type: " + type); | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public boolean supportsParameter(Object param) { | 
 | 
            if ((param == null) || (token.isValid() == false)) { | 
 | 
                return false;  | 
 | 
            }  | 
 | 
            if (param instanceof Key == false) { | 
 | 
                throw new InvalidParameterException("Parameter must be a Key"); | 
 | 
            }  | 
 | 
            String algorithm = getAlgorithm();  | 
 | 
            String type = getType();  | 
 | 
            Key key = (Key)param;  | 
 | 
            String keyAlgorithm = key.getAlgorithm();  | 
 | 
              | 
 | 
            if (((type == CIP) && algorithm.startsWith("RSA")) | 
 | 
                    || (type == SIG) && (algorithm.indexOf("RSA") != -1)) { | 
 | 
                if (keyAlgorithm.equals("RSA") == false) { | 
 | 
                    return false;  | 
 | 
                }  | 
 | 
                return isLocalKey(key)  | 
 | 
                        || (key instanceof RSAPrivateKey)  | 
 | 
                        || (key instanceof RSAPublicKey);  | 
 | 
            }  | 
 | 
              | 
 | 
            if (((type == KA) && algorithm.equals("ECDH")) | 
 | 
                    || ((type == SIG) && algorithm.endsWith("ECDSA"))) { | 
 | 
                if (keyAlgorithm.equals("EC") == false) { | 
 | 
                    return false;  | 
 | 
                }  | 
 | 
                return isLocalKey(key)  | 
 | 
                        || (key instanceof ECPrivateKey)  | 
 | 
                        || (key instanceof ECPublicKey);  | 
 | 
            }  | 
 | 
              | 
 | 
            if ((type == SIG) && algorithm.endsWith("DSA")) { | 
 | 
                if (keyAlgorithm.equals("DSA") == false) { | 
 | 
                    return false;  | 
 | 
                }  | 
 | 
                return isLocalKey(key)  | 
 | 
                        || (key instanceof DSAPrivateKey)  | 
 | 
                        || (key instanceof DSAPublicKey);  | 
 | 
            }  | 
 | 
              | 
 | 
            if ((type == CIP) || (type == MAC)) { | 
 | 
                  | 
 | 
                return isLocalKey(key) || "RAW".equals(key.getFormat());  | 
 | 
            }  | 
 | 
              | 
 | 
            if (type == KA) { | 
 | 
                if (keyAlgorithm.equals("DH") == false) { | 
 | 
                    return false;  | 
 | 
                }  | 
 | 
                return isLocalKey(key)  | 
 | 
                        || (key instanceof DHPrivateKey)  | 
 | 
                        || (key instanceof DHPublicKey);  | 
 | 
            }  | 
 | 
            // should not reach here,  | 
 | 
              | 
 | 
            throw new AssertionError  | 
 | 
                ("SunPKCS11 error: " + type + ", " + algorithm); | 
 | 
        }  | 
 | 
 | 
 | 
        private boolean isLocalKey(Key key) { | 
 | 
            return (key instanceof P11Key) && (((P11Key)key).token == token);  | 
 | 
        }  | 
 | 
 | 
 | 
        public String toString() { | 
 | 
            return super.toString() +  | 
 | 
                " (" + Functions.getMechanismName(mechanism) + ")"; | 
 | 
        }  | 
 | 
 | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public void login(Subject subject, CallbackHandler handler)  | 
 | 
        throws LoginException { | 
 | 
 | 
 | 
        // security check  | 
 | 
 | 
 | 
        SecurityManager sm = System.getSecurityManager();  | 
 | 
        if (sm != null) { | 
 | 
            if (debug != null) { | 
 | 
                debug.println("checking login permission"); | 
 | 
            }  | 
 | 
            sm.checkPermission(new SecurityPermission  | 
 | 
                        ("authProvider." + this.getName())); | 
 | 
        }  | 
 | 
 | 
 | 
        if (hasValidToken() == false) { | 
 | 
            throw new LoginException("No token present"); | 
 | 
        }  | 
 | 
 | 
 | 
        // see if a login is required  | 
 | 
 | 
 | 
        if ((token.tokenInfo.flags & CKF_LOGIN_REQUIRED) == 0) { | 
 | 
            if (debug != null) { | 
 | 
                debug.println("login operation not required for token - " + | 
 | 
                                "ignoring login request");  | 
 | 
            }  | 
 | 
            return;  | 
 | 
        }  | 
 | 
 | 
 | 
        // see if user already logged in  | 
 | 
 | 
 | 
        try { | 
 | 
            if (token.isLoggedInNow(null)) { | 
 | 
                  | 
 | 
                if (debug != null) { | 
 | 
                    debug.println("user already logged in"); | 
 | 
                }  | 
 | 
                return;  | 
 | 
            }  | 
 | 
        } catch (PKCS11Exception e) { | 
 | 
            // ignore - fall thru and attempt login  | 
 | 
        }  | 
 | 
 | 
 | 
        // get the pin if necessary  | 
 | 
 | 
 | 
        char[] pin = null;  | 
 | 
        if ((token.tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) { | 
 | 
 | 
 | 
            // get password  | 
 | 
 | 
 | 
            CallbackHandler myHandler = getCallbackHandler(handler);  | 
 | 
            if (myHandler == null) { | 
 | 
                  | 
 | 
                throw new LoginException  | 
 | 
                        ("no password provided, and no callback handler " + | 
 | 
                        "available for retrieving password");  | 
 | 
            }  | 
 | 
 | 
 | 
            java.text.MessageFormat form = new java.text.MessageFormat  | 
 | 
                        (ResourcesMgr.getString  | 
 | 
                        ("PKCS11.Token.providerName.Password.")); | 
 | 
            Object[] source = { getName() }; | 
 | 
 | 
 | 
            PasswordCallback pcall = new PasswordCallback(form.format(source),  | 
 | 
                                                        false);  | 
 | 
            Callback[] callbacks = { pcall }; | 
 | 
            try { | 
 | 
                myHandler.handle(callbacks);  | 
 | 
            } catch (Exception e) { | 
 | 
                LoginException le = new LoginException  | 
 | 
                        ("Unable to perform password callback"); | 
 | 
                le.initCause(e);  | 
 | 
                throw le;  | 
 | 
            }  | 
 | 
 | 
 | 
            pin = pcall.getPassword();  | 
 | 
            pcall.clearPassword();  | 
 | 
            if (pin == null) { | 
 | 
                if (debug != null) { | 
 | 
                    debug.println("caller passed NULL pin"); | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        // perform token login  | 
 | 
 | 
 | 
        Session session = null;  | 
 | 
        try { | 
 | 
            session = token.getOpSession();  | 
 | 
 | 
 | 
              | 
 | 
            p11.C_Login(session.id(), CKU_USER, pin);  | 
 | 
            if (debug != null) { | 
 | 
                debug.println("login succeeded"); | 
 | 
            }  | 
 | 
        } catch (PKCS11Exception pe) { | 
 | 
            if (pe.getErrorCode() == CKR_USER_ALREADY_LOGGED_IN) { | 
 | 
                  | 
 | 
                if (debug != null) { | 
 | 
                    debug.println("user already logged in"); | 
 | 
                }  | 
 | 
                return;  | 
 | 
            } else if (pe.getErrorCode() == CKR_PIN_INCORRECT) { | 
 | 
                FailedLoginException fle = new FailedLoginException();  | 
 | 
                fle.initCause(pe);  | 
 | 
                throw fle;  | 
 | 
            } else { | 
 | 
                LoginException le = new LoginException();  | 
 | 
                le.initCause(pe);  | 
 | 
                throw le;  | 
 | 
            }  | 
 | 
        } finally { | 
 | 
            token.releaseSession(session);  | 
 | 
            if (pin != null) { | 
 | 
                Arrays.fill(pin, ' ');  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        // we do not store the PIN in the subject for now  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public void logout() throws LoginException { | 
 | 
 | 
 | 
        // security check  | 
 | 
 | 
 | 
        SecurityManager sm = System.getSecurityManager();  | 
 | 
        if (sm != null) { | 
 | 
            sm.checkPermission  | 
 | 
                (new SecurityPermission("authProvider." + this.getName())); | 
 | 
        }  | 
 | 
 | 
 | 
        if (hasValidToken() == false) { | 
 | 
              | 
 | 
            return;  | 
 | 
        }  | 
 | 
 | 
 | 
        if ((token.tokenInfo.flags & CKF_LOGIN_REQUIRED) == 0) { | 
 | 
            if (debug != null) { | 
 | 
                debug.println("logout operation not required for token - " + | 
 | 
                                "ignoring logout request");  | 
 | 
            }  | 
 | 
            return;  | 
 | 
        }  | 
 | 
 | 
 | 
        try { | 
 | 
            if (token.isLoggedInNow(null) == false) { | 
 | 
                if (debug != null) { | 
 | 
                    debug.println("user not logged in"); | 
 | 
                }  | 
 | 
                return;  | 
 | 
            }  | 
 | 
        } catch (PKCS11Exception e) { | 
 | 
            // ignore  | 
 | 
        }  | 
 | 
 | 
 | 
        // perform token logout  | 
 | 
 | 
 | 
        Session session = null;  | 
 | 
        try { | 
 | 
            session = token.getOpSession();  | 
 | 
            p11.C_Logout(session.id());  | 
 | 
            if (debug != null) { | 
 | 
                debug.println("logout succeeded"); | 
 | 
            }  | 
 | 
        } catch (PKCS11Exception pe) { | 
 | 
            if (pe.getErrorCode() == CKR_USER_NOT_LOGGED_IN) { | 
 | 
                  | 
 | 
                if (debug != null) { | 
 | 
                    debug.println("user not logged in"); | 
 | 
                }  | 
 | 
                return;  | 
 | 
            }  | 
 | 
            LoginException le = new LoginException();  | 
 | 
            le.initCause(pe);  | 
 | 
            throw le;  | 
 | 
        } finally { | 
 | 
            token.releaseSession(session);  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public void setCallbackHandler(CallbackHandler handler) { | 
 | 
 | 
 | 
        // security check  | 
 | 
 | 
 | 
        SecurityManager sm = System.getSecurityManager();  | 
 | 
        if (sm != null) { | 
 | 
            sm.checkPermission  | 
 | 
                (new SecurityPermission("authProvider." + this.getName())); | 
 | 
        }  | 
 | 
 | 
 | 
        synchronized (LOCK_HANDLER) { | 
 | 
            pHandler = handler;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
    private CallbackHandler getCallbackHandler(CallbackHandler handler) { | 
 | 
 | 
 | 
        // get default handler if necessary  | 
 | 
 | 
 | 
        if (handler != null) { | 
 | 
            return handler;  | 
 | 
        }  | 
 | 
 | 
 | 
        if (debug != null) { | 
 | 
            debug.println("getting provider callback handler"); | 
 | 
        }  | 
 | 
 | 
 | 
        synchronized (LOCK_HANDLER) { | 
 | 
              | 
 | 
            if (pHandler != null) { | 
 | 
                return pHandler;  | 
 | 
            }  | 
 | 
 | 
 | 
            try { | 
 | 
                if (debug != null) { | 
 | 
                    debug.println("getting default callback handler"); | 
 | 
                }  | 
 | 
 | 
 | 
                CallbackHandler myHandler = AccessController.doPrivileged  | 
 | 
                    (new PrivilegedExceptionAction<CallbackHandler>() { | 
 | 
                    public CallbackHandler run() throws Exception { | 
 | 
 | 
 | 
                        String defaultHandler =  | 
 | 
                                java.security.Security.getProperty  | 
 | 
                                ("auth.login.defaultCallbackHandler"); | 
 | 
 | 
 | 
                        if (defaultHandler == null ||  | 
 | 
                            defaultHandler.length() == 0) { | 
 | 
 | 
 | 
                              | 
 | 
                            if (debug != null) { | 
 | 
                                debug.println("no default handler set"); | 
 | 
                            }  | 
 | 
                            return null;  | 
 | 
                        }  | 
 | 
 | 
 | 
                        Class<?> c = Class.forName  | 
 | 
                                   (defaultHandler,  | 
 | 
                                   true,  | 
 | 
                                   Thread.currentThread().getContextClassLoader());  | 
 | 
                        return (CallbackHandler)c.newInstance();  | 
 | 
                    }  | 
 | 
                });  | 
 | 
 | 
 | 
                  | 
 | 
                pHandler = myHandler;  | 
 | 
                return myHandler;  | 
 | 
 | 
 | 
            } catch (PrivilegedActionException pae) { | 
 | 
                  | 
 | 
                if (debug != null) { | 
 | 
                    debug.println("Unable to load default callback handler"); | 
 | 
                    pae.printStackTrace();  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return null;  | 
 | 
    }  | 
 | 
 | 
 | 
    private Object writeReplace() throws ObjectStreamException { | 
 | 
        return new SunPKCS11Rep(this);  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    private static class SunPKCS11Rep implements Serializable { | 
 | 
 | 
 | 
        static final long serialVersionUID = -2896606995897745419L;  | 
 | 
 | 
 | 
        private final String providerName;  | 
 | 
 | 
 | 
        private final String configName;  | 
 | 
 | 
 | 
        SunPKCS11Rep(SunPKCS11 provider) throws NotSerializableException { | 
 | 
            providerName = provider.getName();  | 
 | 
            configName = provider.configName;  | 
 | 
            if (Security.getProvider(providerName) != provider) { | 
 | 
                throw new NotSerializableException("Only SunPKCS11 providers " | 
 | 
                    + "installed in java.security.Security can be serialized");  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        private Object readResolve() throws ObjectStreamException { | 
 | 
            SunPKCS11 p = (SunPKCS11)Security.getProvider(providerName);  | 
 | 
            if ((p == null) || (p.configName.equals(configName) == false)) { | 
 | 
                throw new NotSerializableException("Could not find " | 
 | 
                        + providerName + " in installed providers");  | 
 | 
            }  | 
 | 
            return p;  | 
 | 
        }  | 
 | 
    }  | 
 | 
}  |