1394 lines · 52.3 KB · Java
RawDownload
/* * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation.  Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ 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.*; /** * PKCS#11 provider main class. * * @author  Andreas Sterbenz * @since   1.5 */public final class SunPKCS11 extends AuthProvider {     private static final long serialVersionUID = -1354835039035306505L;     static final Debug debug = Debug.getInstance("sunpkcs11");     private static int dummyConfigId;     // the PKCS11 object through which we make the native calls    final PKCS11 p11;     // name of the configuration file    private final String configName;     // configuration information    final Config config;     // id of the PKCS#11 slot we are using    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.7d, "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 use new SunPKCS11(String) or new SunPKCS11(InputStream)     *         instead     */    @Deprecated    public SunPKCS11(String configName, InputStream configStream) {        super("SunPKCS11-" +            Config.getConfig(configName, configStream).getName(),            1.7d, 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            // in secmod mode.            Secmod secmod = Secmod.getInstance();            DbMode nssDbMode = config.getNssDbMode();            try {                String nssLibraryDirectory = config.getNssLibraryDirectory();                String nssSecmodDirectory = config.getNssSecmodDirectory();                 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);                }            } catch (IOException e) {                // XXX which exception to throw                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")) {                // XXX should the option be called trustanchor or 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        // only looks in the current directory.        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;            }            // request multithreaded access first            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;                }                // fall back to single threaded access                if (nssArgs == null) {                    // if possible, use null initArgs for better compatibility                    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 s1) {        return new String[] {s1};    }     private static String[] s(String s1, String s2) {        return new String[] {s1, s2};    }     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    // registered if the mechanism is supported    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"; 

Lines 1–500 of 1394.