0N/A/*
4599N/A * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.security.pkcs11;
0N/A
0N/Aimport java.io.*;
0N/Aimport java.util.*;
0N/A
0N/Aimport java.security.*;
0N/Aimport java.security.interfaces.*;
0N/A
0N/Aimport javax.crypto.interfaces.*;
0N/A
0N/Aimport javax.security.auth.Subject;
0N/Aimport javax.security.auth.login.LoginException;
0N/Aimport javax.security.auth.login.FailedLoginException;
0N/Aimport javax.security.auth.callback.Callback;
0N/Aimport javax.security.auth.callback.CallbackHandler;
0N/Aimport javax.security.auth.callback.ConfirmationCallback;
0N/Aimport javax.security.auth.callback.PasswordCallback;
0N/Aimport javax.security.auth.callback.TextOutputCallback;
0N/A
0N/Aimport sun.security.util.Debug;
0N/Aimport sun.security.util.ResourcesMgr;
0N/A
0N/Aimport sun.security.pkcs11.Secmod.*;
0N/A
0N/Aimport sun.security.pkcs11.wrapper.*;
0N/Aimport static sun.security.pkcs11.wrapper.PKCS11Constants.*;
0N/A
0N/A/**
0N/A * PKCS#11 provider main class.
0N/A *
0N/A * @author Andreas Sterbenz
0N/A * @since 1.5
0N/A */
0N/Apublic final class SunPKCS11 extends AuthProvider {
0N/A
0N/A private static final long serialVersionUID = -1354835039035306505L;
0N/A
0N/A static final Debug debug = Debug.getInstance("sunpkcs11");
0N/A
0N/A private static int dummyConfigId;
0N/A
0N/A // the PKCS11 object through which we make the native calls
0N/A final PKCS11 p11;
0N/A
0N/A // name of the configuration file
0N/A private final String configName;
0N/A
0N/A // configuration information
0N/A final Config config;
0N/A
0N/A // id of the PKCS#11 slot we are using
0N/A final long slotID;
0N/A
0N/A private CallbackHandler pHandler;
0N/A private final Object LOCK_HANDLER = new Object();
0N/A
0N/A final boolean removable;
0N/A
0N/A final Module nssModule;
0N/A
0N/A final boolean nssUseSecmodTrust;
0N/A
0N/A private volatile Token token;
0N/A
0N/A private TokenPoller poller;
0N/A
0N/A Token getToken() {
0N/A return token;
0N/A }
0N/A
0N/A public SunPKCS11() {
0N/A super("SunPKCS11-Dummy", 1.7d, "SunPKCS11-Dummy");
0N/A throw new ProviderException
0N/A ("SunPKCS11 requires configuration file argument");
0N/A }
0N/A
0N/A public SunPKCS11(String configName) {
0N/A this(checkNull(configName), null);
0N/A }
0N/A
0N/A public SunPKCS11(InputStream configStream) {
0N/A this(getDummyConfigName(), checkNull(configStream));
0N/A }
0N/A
0N/A private static <T> T checkNull(T obj) {
0N/A if (obj == null) {
0N/A throw new NullPointerException();
0N/A }
0N/A return obj;
0N/A }
0N/A
0N/A private static synchronized String getDummyConfigName() {
0N/A int id = ++dummyConfigId;
0N/A return "---DummyConfig-" + id + "---";
0N/A }
0N/A
0N/A /**
1111N/A * @deprecated use new SunPKCS11(String) or new SunPKCS11(InputStream)
1111N/A * instead
0N/A */
0N/A @Deprecated
0N/A public SunPKCS11(String configName, InputStream configStream) {
1111N/A super("SunPKCS11-" +
1111N/A Config.getConfig(configName, configStream).getName(),
0N/A 1.7d, Config.getConfig(configName, configStream).getDescription());
0N/A this.configName = configName;
0N/A this.config = Config.removeConfig(configName);
0N/A
0N/A if (debug != null) {
0N/A System.out.println("SunPKCS11 loading " + configName);
0N/A }
0N/A
0N/A String library = config.getLibrary();
0N/A String functionList = config.getFunctionList();
0N/A long slotID = config.getSlotID();
0N/A int slotListIndex = config.getSlotListIndex();
0N/A
0N/A boolean useSecmod = config.getNssUseSecmod();
0N/A boolean nssUseSecmodTrust = config.getNssUseSecmodTrust();
0N/A Module nssModule = null;
0N/A
0N/A //
0N/A // Initialization via Secmod. The way this works is as follows:
0N/A // SunPKCS11 is either in normal mode or in NSS Secmod mode.
0N/A // Secmod is activated by specifying one or more of the following
0N/A // options in the config file:
0N/A // nssUseSecmod, nssSecmodDirectory, nssLibrary, nssModule
0N/A //
0N/A // XXX add more explanation here
0N/A //
0N/A // If we are in Secmod mode and configured to use either the
0N/A // nssKeyStore or the nssTrustAnchors module, we automatically
1111N/A // switch to using the NSS trust attributes for trusted certs
1111N/A // (KeyStore).
0N/A //
0N/A
0N/A if (useSecmod) {
0N/A // note: Config ensures library/slot/slotListIndex not specified
0N/A // in secmod mode.
0N/A Secmod secmod = Secmod.getInstance();
0N/A DbMode nssDbMode = config.getNssDbMode();
0N/A try {
0N/A String nssLibraryDirectory = config.getNssLibraryDirectory();
0N/A String nssSecmodDirectory = config.getNssSecmodDirectory();
0N/A
0N/A if (secmod.isInitialized()) {
0N/A if (nssSecmodDirectory != null) {
0N/A String s = secmod.getConfigDir();
1111N/A if ((s != null) &&
1111N/A (s.equals(nssSecmodDirectory) == false)) {
0N/A throw new ProviderException("Secmod directory "
0N/A + nssSecmodDirectory
1111N/A + " invalid, NSS already initialized with "
1111N/A + s);
0N/A }
0N/A }
0N/A if (nssLibraryDirectory != null) {
0N/A String s = secmod.getLibDir();
1111N/A if ((s != null) &&
1111N/A (s.equals(nssLibraryDirectory) == false)) {
0N/A throw new ProviderException("NSS library directory "
0N/A + nssLibraryDirectory
1111N/A + " invalid, NSS already initialized with "
1111N/A + s);
0N/A }
0N/A }
0N/A } else {
0N/A if (nssDbMode != DbMode.NO_DB) {
0N/A if (nssSecmodDirectory == null) {
1111N/A throw new ProviderException(
1111N/A "Secmod not initialized and "
1111N/A + "nssSecmodDirectory not specified");
0N/A }
0N/A } else {
0N/A if (nssSecmodDirectory != null) {
1111N/A throw new ProviderException(
1111N/A "nssSecmodDirectory must not be "
1111N/A + "specified in noDb mode");
0N/A }
0N/A }
1111N/A secmod.initialize(nssDbMode, nssSecmodDirectory,
1111N/A nssLibraryDirectory);
0N/A }
0N/A } catch (IOException e) {
0N/A // XXX which exception to throw
0N/A throw new ProviderException("Could not initialize NSS", e);
0N/A }
0N/A List<Module> modules = secmod.getModules();
0N/A if (config.getShowInfo()) {
0N/A System.out.println("NSS modules: " + modules);
0N/A }
0N/A
0N/A String moduleName = config.getNssModule();
0N/A if (moduleName == null) {
0N/A nssModule = secmod.getModule(ModuleType.FIPS);
0N/A if (nssModule != null) {
0N/A moduleName = "fips";
0N/A } else {
1111N/A moduleName = (nssDbMode == DbMode.NO_DB) ?
1111N/A "crypto" : "keystore";
0N/A }
0N/A }
0N/A if (moduleName.equals("fips")) {
0N/A nssModule = secmod.getModule(ModuleType.FIPS);
0N/A nssUseSecmodTrust = true;
0N/A functionList = "FC_GetFunctionList";
0N/A } else if (moduleName.equals("keystore")) {
0N/A nssModule = secmod.getModule(ModuleType.KEYSTORE);
0N/A nssUseSecmodTrust = true;
0N/A } else if (moduleName.equals("crypto")) {
0N/A nssModule = secmod.getModule(ModuleType.CRYPTO);
0N/A } else if (moduleName.equals("trustanchors")) {
0N/A // XXX should the option be called trustanchor or trustanchors??
0N/A nssModule = secmod.getModule(ModuleType.TRUSTANCHOR);
0N/A nssUseSecmodTrust = true;
0N/A } else if (moduleName.startsWith("external-")) {
0N/A int moduleIndex;
0N/A try {
0N/A moduleIndex = Integer.parseInt
0N/A (moduleName.substring("external-".length()));
0N/A } catch (NumberFormatException e) {
0N/A moduleIndex = -1;
0N/A }
0N/A if (moduleIndex < 1) {
0N/A throw new ProviderException
0N/A ("Invalid external module: " + moduleName);
0N/A }
0N/A int k = 0;
0N/A for (Module module : modules) {
0N/A if (module.getType() == ModuleType.EXTERNAL) {
0N/A if (++k == moduleIndex) {
0N/A nssModule = module;
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A if (nssModule == null) {
0N/A throw new ProviderException("Invalid module " + moduleName
0N/A + ": only " + k + " external NSS modules available");
0N/A }
0N/A } else {
1111N/A throw new ProviderException(
1111N/A "Unknown NSS module: " + moduleName);
0N/A }
0N/A if (nssModule == null) {
1111N/A throw new ProviderException(
1111N/A "NSS module not available: " + moduleName);
0N/A }
0N/A if (nssModule.hasInitializedProvider()) {
0N/A throw new ProviderException("Secmod module already configured");
0N/A }
0N/A library = nssModule.libraryName;
0N/A slotListIndex = nssModule.slot;
0N/A }
0N/A this.nssUseSecmodTrust = nssUseSecmodTrust;
0N/A this.nssModule = nssModule;
0N/A
0N/A File libraryFile = new File(library);
0N/A // if the filename is a simple filename without path
0N/A // (e.g. "libpkcs11.so"), it may refer to a library somewhere on the
0N/A // OS library search path. Omit the test for file existance as that
0N/A // only looks in the current directory.
0N/A if (libraryFile.getName().equals(library) == false) {
0N/A if (new File(library).isFile() == false) {
0N/A String msg = "Library " + library + " does not exist";
0N/A if (config.getHandleStartupErrors() == Config.ERR_HALT) {
0N/A throw new ProviderException(msg);
0N/A } else {
0N/A throw new UnsupportedOperationException(msg);
0N/A }
0N/A }
0N/A }
0N/A
0N/A try {
0N/A if (debug != null) {
0N/A debug.println("Initializing PKCS#11 library " + library);
0N/A }
0N/A CK_C_INITIALIZE_ARGS initArgs = new CK_C_INITIALIZE_ARGS();
0N/A String nssArgs = config.getNssArgs();
0N/A if (nssArgs != null) {
0N/A initArgs.pReserved = nssArgs;
0N/A }
0N/A // request multithreaded access first
0N/A initArgs.flags = CKF_OS_LOCKING_OK;
0N/A PKCS11 tmpPKCS11;
0N/A try {
1111N/A tmpPKCS11 = PKCS11.getInstance(
1111N/A library, functionList, initArgs,
1111N/A config.getOmitInitialize());
0N/A } catch (PKCS11Exception e) {
0N/A if (debug != null) {
0N/A debug.println("Multi-threaded initialization failed: " + e);
0N/A }
0N/A if (config.getAllowSingleThreadedModules() == false) {
0N/A throw e;
0N/A }
0N/A // fall back to single threaded access
0N/A if (nssArgs == null) {
0N/A // if possible, use null initArgs for better compatibility
0N/A initArgs = null;
0N/A } else {
0N/A initArgs.flags = 0;
0N/A }
1111N/A tmpPKCS11 = PKCS11.getInstance(library,
1111N/A functionList, initArgs, config.getOmitInitialize());
0N/A }
0N/A p11 = tmpPKCS11;
0N/A
0N/A CK_INFO p11Info = p11.C_GetInfo();
0N/A if (p11Info.cryptokiVersion.major < 2) {
0N/A throw new ProviderException("Only PKCS#11 v2.0 and later "
0N/A + "supported, library version is v" + p11Info.cryptokiVersion);
0N/A }
0N/A boolean showInfo = config.getShowInfo();
0N/A if (showInfo) {
0N/A System.out.println("Information for provider " + getName());
0N/A System.out.println("Library info:");
0N/A System.out.println(p11Info);
0N/A }
0N/A if ((slotID < 0) || showInfo) {
0N/A long[] slots = p11.C_GetSlotList(false);
0N/A if (showInfo) {
0N/A System.out.println("All slots: " + toString(slots));
0N/A slots = p11.C_GetSlotList(true);
0N/A System.out.println("Slots with tokens: " + toString(slots));
0N/A }
0N/A if (slotID < 0) {
1111N/A if ((slotListIndex < 0)
1111N/A || (slotListIndex >= slots.length)) {
1111N/A throw new ProviderException("slotListIndex is "
1111N/A + slotListIndex
0N/A + " but token only has " + slots.length + " slots");
0N/A }
0N/A slotID = slots[slotListIndex];
0N/A }
0N/A }
0N/A this.slotID = slotID;
0N/A CK_SLOT_INFO slotInfo = p11.C_GetSlotInfo(slotID);
0N/A removable = (slotInfo.flags & CKF_REMOVABLE_DEVICE) != 0;
0N/A initToken(slotInfo);
0N/A if (nssModule != null) {
0N/A nssModule.setProvider(this);
0N/A }
0N/A } catch (Exception e) {
0N/A if (config.getHandleStartupErrors() == Config.ERR_IGNORE_ALL) {
0N/A throw new UnsupportedOperationException
0N/A ("Initialization failed", e);
0N/A } else {
0N/A throw new ProviderException
0N/A ("Initialization failed", e);
0N/A }
0N/A }
0N/A }
0N/A
0N/A private static String toString(long[] longs) {
0N/A if (longs.length == 0) {
0N/A return "(none)";
0N/A }
0N/A StringBuilder sb = new StringBuilder();
0N/A sb.append(longs[0]);
0N/A for (int i = 1; i < longs.length; i++) {
0N/A sb.append(", ");
0N/A sb.append(longs[i]);
0N/A }
0N/A return sb.toString();
0N/A }
0N/A
0N/A public boolean equals(Object obj) {
0N/A return this == obj;
0N/A }
0N/A
0N/A public int hashCode() {
0N/A return System.identityHashCode(this);
0N/A }
0N/A
0N/A private static String[] s(String s1) {
0N/A return new String[] {s1};
0N/A }
0N/A
0N/A private static String[] s(String s1, String s2) {
0N/A return new String[] {s1, s2};
0N/A }
0N/A
0N/A private static final class Descriptor {
0N/A final String type;
0N/A final String algorithm;
0N/A final String className;
0N/A final String[] aliases;
0N/A final int[] mechanisms;
0N/A
0N/A private Descriptor(String type, String algorithm, String className,
0N/A String[] aliases, int[] mechanisms) {
0N/A this.type = type;
0N/A this.algorithm = algorithm;
0N/A this.className = className;
0N/A this.aliases = aliases;
0N/A this.mechanisms = mechanisms;
0N/A }
0N/A private P11Service service(Token token, int mechanism) {
0N/A return new P11Service
0N/A (token, type, algorithm, className, aliases, mechanism);
0N/A }
0N/A public String toString() {
0N/A return type + "." + algorithm;
0N/A }
0N/A }
0N/A
0N/A // Map from mechanism to List of Descriptors that should be
0N/A // registered if the mechanism is supported
0N/A private final static Map<Integer,List<Descriptor>> descriptors =
0N/A new HashMap<Integer,List<Descriptor>>();
0N/A
0N/A private static int[] m(long m1) {
0N/A return new int[] {(int)m1};
0N/A }
0N/A
0N/A private static int[] m(long m1, long m2) {
0N/A return new int[] {(int)m1, (int)m2};
0N/A }
0N/A
0N/A private static int[] m(long m1, long m2, long m3) {
0N/A return new int[] {(int)m1, (int)m2, (int)m3};
0N/A }
0N/A
0N/A private static int[] m(long m1, long m2, long m3, long m4) {
0N/A return new int[] {(int)m1, (int)m2, (int)m3, (int)m4};
0N/A }
0N/A
0N/A private static void d(String type, String algorithm, String className,
0N/A int[] m) {
0N/A register(new Descriptor(type, algorithm, className, null, m));
0N/A }
0N/A
0N/A private static void d(String type, String algorithm, String className,
0N/A String[] aliases, int[] m) {
0N/A register(new Descriptor(type, algorithm, className, aliases, m));
0N/A }
0N/A
0N/A private static void register(Descriptor d) {
0N/A for (int i = 0; i < d.mechanisms.length; i++) {
0N/A int m = d.mechanisms[i];
0N/A Integer key = Integer.valueOf(m);
0N/A List<Descriptor> list = descriptors.get(key);
0N/A if (list == null) {
0N/A list = new ArrayList<Descriptor>();
0N/A descriptors.put(key, list);
0N/A }
0N/A list.add(d);
0N/A }
0N/A }
0N/A
0N/A private final static String MD = "MessageDigest";
0N/A
0N/A private final static String SIG = "Signature";
0N/A
0N/A private final static String KPG = "KeyPairGenerator";
0N/A
0N/A private final static String KG = "KeyGenerator";
0N/A
0N/A private final static String AGP = "AlgorithmParameters";
0N/A
0N/A private final static String KF = "KeyFactory";
0N/A
0N/A private final static String SKF = "SecretKeyFactory";
0N/A
0N/A private final static String CIP = "Cipher";
0N/A
0N/A private final static String MAC = "Mac";
0N/A
0N/A private final static String KA = "KeyAgreement";
0N/A
0N/A private final static String KS = "KeyStore";
0N/A
0N/A private final static String SR = "SecureRandom";
0N/A
0N/A static {
0N/A // names of all the implementation classes
0N/A // use local variables, only used here
0N/A String P11Digest = "sun.security.pkcs11.P11Digest";
0N/A String P11MAC = "sun.security.pkcs11.P11MAC";
0N/A String P11KeyPairGenerator = "sun.security.pkcs11.P11KeyPairGenerator";
0N/A String P11KeyGenerator = "sun.security.pkcs11.P11KeyGenerator";
0N/A String P11RSAKeyFactory = "sun.security.pkcs11.P11RSAKeyFactory";
0N/A String P11DSAKeyFactory = "sun.security.pkcs11.P11DSAKeyFactory";
0N/A String P11DHKeyFactory = "sun.security.pkcs11.P11DHKeyFactory";
0N/A String P11KeyAgreement = "sun.security.pkcs11.P11KeyAgreement";
0N/A String P11SecretKeyFactory = "sun.security.pkcs11.P11SecretKeyFactory";
0N/A String P11Cipher = "sun.security.pkcs11.P11Cipher";
0N/A String P11RSACipher = "sun.security.pkcs11.P11RSACipher";
0N/A String P11Signature = "sun.security.pkcs11.P11Signature";
0N/A
0N/A // XXX register all aliases
0N/A
0N/A d(MD, "MD2", P11Digest,
0N/A m(CKM_MD2));
0N/A d(MD, "MD5", P11Digest,
0N/A m(CKM_MD5));
0N/A d(MD, "SHA1", P11Digest, s("SHA", "SHA-1"),
0N/A m(CKM_SHA_1));
0N/A d(MD, "SHA-256", P11Digest,
0N/A m(CKM_SHA256));
0N/A d(MD, "SHA-384", P11Digest,
0N/A m(CKM_SHA384));
0N/A d(MD, "SHA-512", P11Digest,
0N/A m(CKM_SHA512));
0N/A
0N/A d(MAC, "HmacMD5", P11MAC,
0N/A m(CKM_MD5_HMAC));
0N/A d(MAC, "HmacSHA1", P11MAC,
0N/A m(CKM_SHA_1_HMAC));
0N/A d(MAC, "HmacSHA256", P11MAC,
0N/A m(CKM_SHA256_HMAC));
0N/A d(MAC, "HmacSHA384", P11MAC,
0N/A m(CKM_SHA384_HMAC));
0N/A d(MAC, "HmacSHA512", P11MAC,
0N/A m(CKM_SHA512_HMAC));
0N/A d(MAC, "SslMacMD5", P11MAC,
0N/A m(CKM_SSL3_MD5_MAC));
0N/A d(MAC, "SslMacSHA1", P11MAC,
0N/A m(CKM_SSL3_SHA1_MAC));
0N/A
0N/A d(KPG, "RSA", P11KeyPairGenerator,
0N/A m(CKM_RSA_PKCS_KEY_PAIR_GEN));
0N/A d(KPG, "DSA", P11KeyPairGenerator,
0N/A m(CKM_DSA_KEY_PAIR_GEN));
0N/A d(KPG, "DH", P11KeyPairGenerator, s("DiffieHellman"),
0N/A m(CKM_DH_PKCS_KEY_PAIR_GEN));
0N/A d(KPG, "EC", P11KeyPairGenerator,
0N/A m(CKM_EC_KEY_PAIR_GEN));
0N/A
0N/A d(KG, "ARCFOUR", P11KeyGenerator, s("RC4"),
0N/A m(CKM_RC4_KEY_GEN));
0N/A d(KG, "DES", P11KeyGenerator,
0N/A m(CKM_DES_KEY_GEN));
0N/A d(KG, "DESede", P11KeyGenerator,
0N/A m(CKM_DES3_KEY_GEN, CKM_DES2_KEY_GEN));
0N/A d(KG, "AES", P11KeyGenerator,
0N/A m(CKM_AES_KEY_GEN));
0N/A d(KG, "Blowfish", P11KeyGenerator,
0N/A m(CKM_BLOWFISH_KEY_GEN));
0N/A
0N/A // register (Secret)KeyFactories if there are any mechanisms
0N/A // for a particular algorithm that we support
0N/A d(KF, "RSA", P11RSAKeyFactory,
0N/A m(CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_RSA_PKCS, CKM_RSA_X_509));
0N/A d(KF, "DSA", P11DSAKeyFactory,
0N/A m(CKM_DSA_KEY_PAIR_GEN, CKM_DSA, CKM_DSA_SHA1));
0N/A d(KF, "DH", P11DHKeyFactory, s("DiffieHellman"),
0N/A m(CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE));
0N/A d(KF, "EC", P11DHKeyFactory,
1111N/A m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,
1111N/A CKM_ECDSA, CKM_ECDSA_SHA1));
0N/A
0N/A // AlgorithmParameters for EC.
0N/A // Only needed until we have an EC implementation in the SUN provider.
1111N/A d(AGP, "EC", "sun.security.ec.ECParameters",
1111N/A s("1.2.840.10045.2.1"),
1111N/A m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,
1111N/A CKM_ECDSA, CKM_ECDSA_SHA1));
0N/A
0N/A d(KA, "DH", P11KeyAgreement, s("DiffieHellman"),
0N/A m(CKM_DH_PKCS_DERIVE));
0N/A d(KA, "ECDH", "sun.security.pkcs11.P11ECDHKeyAgreement",
0N/A m(CKM_ECDH1_DERIVE));
0N/A
0N/A d(SKF, "ARCFOUR", P11SecretKeyFactory, s("RC4"),
0N/A m(CKM_RC4));
0N/A d(SKF, "DES", P11SecretKeyFactory,
0N/A m(CKM_DES_CBC));
0N/A d(SKF, "DESede", P11SecretKeyFactory,
0N/A m(CKM_DES3_CBC));
0N/A d(SKF, "AES", P11SecretKeyFactory,
0N/A m(CKM_AES_CBC));
0N/A d(SKF, "Blowfish", P11SecretKeyFactory,
0N/A m(CKM_BLOWFISH_CBC));
0N/A
0N/A // XXX attributes for Ciphers (supported modes, padding)
0N/A d(CIP, "ARCFOUR", P11Cipher, s("RC4"),
0N/A m(CKM_RC4));
0N/A d(CIP, "DES/CBC/NoPadding", P11Cipher,
0N/A m(CKM_DES_CBC));
149N/A d(CIP, "DES/CBC/PKCS5Padding", P11Cipher,
149N/A m(CKM_DES_CBC_PAD, CKM_DES_CBC));
4599N/A d(CIP, "DES/ECB/NoPadding", P11Cipher,
149N/A m(CKM_DES_ECB));
4599N/A d(CIP, "DES/ECB/PKCS5Padding", P11Cipher, s("DES"),
4599N/A m(CKM_DES_ECB));
0N/A d(CIP, "DESede/CBC/NoPadding", P11Cipher,
0N/A m(CKM_DES3_CBC));
149N/A d(CIP, "DESede/CBC/PKCS5Padding", P11Cipher,
149N/A m(CKM_DES3_CBC_PAD, CKM_DES3_CBC));
4599N/A d(CIP, "DESede/ECB/NoPadding", P11Cipher,
4599N/A m(CKM_DES3_ECB));
4599N/A d(CIP, "DESede/ECB/PKCS5Padding", P11Cipher, s("DESede"),
149N/A m(CKM_DES3_ECB));
0N/A d(CIP, "AES/CBC/NoPadding", P11Cipher,
0N/A m(CKM_AES_CBC));
149N/A d(CIP, "AES/CBC/PKCS5Padding", P11Cipher,
149N/A m(CKM_AES_CBC_PAD, CKM_AES_CBC));
4599N/A d(CIP, "AES/ECB/NoPadding", P11Cipher,
4599N/A m(CKM_AES_ECB));
4599N/A d(CIP, "AES/ECB/PKCS5Padding", P11Cipher, s("AES"),
149N/A m(CKM_AES_ECB));
3645N/A d(CIP, "AES/CTR/NoPadding", P11Cipher,
3645N/A m(CKM_AES_CTR));
4599N/A d(CIP, "Blowfish/CBC/NoPadding", P11Cipher,
4599N/A m(CKM_BLOWFISH_CBC));
4599N/A d(CIP, "Blowfish/CBC/PKCS5Padding", P11Cipher,
0N/A m(CKM_BLOWFISH_CBC));
0N/A
0N/A // XXX RSA_X_509, RSA_OAEP not yet supported
3681N/A d(CIP, "RSA/ECB/PKCS1Padding", P11RSACipher, s("RSA"),
0N/A m(CKM_RSA_PKCS));
3681N/A d(CIP, "RSA/ECB/NoPadding", P11RSACipher,
3681N/A m(CKM_RSA_X_509));
0N/A
0N/A d(SIG, "RawDSA", P11Signature, s("NONEwithDSA"),
0N/A m(CKM_DSA));
0N/A d(SIG, "DSA", P11Signature, s("SHA1withDSA"),
0N/A m(CKM_DSA_SHA1, CKM_DSA));
0N/A d(SIG, "NONEwithECDSA", P11Signature,
0N/A m(CKM_ECDSA));
0N/A d(SIG, "SHA1withECDSA", P11Signature, s("ECDSA"),
0N/A m(CKM_ECDSA_SHA1, CKM_ECDSA));
0N/A d(SIG, "SHA256withECDSA", P11Signature,
0N/A m(CKM_ECDSA));
0N/A d(SIG, "SHA384withECDSA", P11Signature,
0N/A m(CKM_ECDSA));
0N/A d(SIG, "SHA512withECDSA", P11Signature,
0N/A m(CKM_ECDSA));
0N/A d(SIG, "MD2withRSA", P11Signature,
0N/A m(CKM_MD2_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
0N/A d(SIG, "MD5withRSA", P11Signature,
0N/A m(CKM_MD5_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
0N/A d(SIG, "SHA1withRSA", P11Signature,
0N/A m(CKM_SHA1_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
0N/A d(SIG, "SHA256withRSA", P11Signature,
0N/A m(CKM_SHA256_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
0N/A d(SIG, "SHA384withRSA", P11Signature,
0N/A m(CKM_SHA384_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
0N/A d(SIG, "SHA512withRSA", P11Signature,
0N/A m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
0N/A
3002N/A /*
3002N/A * TLS 1.2 uses a different hash algorithm than 1.0/1.1 for the
3002N/A * PRF calculations. As of 2010, there is no PKCS11-level
3002N/A * support for TLS 1.2 PRF calculations, and no known OS's have
3002N/A * an internal variant we could use. Therefore for TLS 1.2, we
3002N/A * are updating JSSE to request different provider algorithms
3002N/A * (e.g. "SunTls12Prf"), and currently only SunJCE has these
3002N/A * TLS 1.2 algorithms.
3002N/A *
3002N/A * If we reused the names such as "SunTlsPrf", the PKCS11
3002N/A * providers would need be updated to fail correctly when
3002N/A * presented with the wrong version number (via
3002N/A * Provider.Service.supportsParameters()), and we would also
3002N/A * need to add the appropriate supportsParamters() checks into
3002N/A * KeyGenerators (not currently there).
3002N/A *
3002N/A * In the future, if PKCS11 support is added, we will restructure
3002N/A * this.
3002N/A */
1111N/A d(KG, "SunTlsRsaPremasterSecret",
1111N/A "sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",
0N/A m(CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_PRE_MASTER_KEY_GEN));
1111N/A d(KG, "SunTlsMasterSecret",
1111N/A "sun.security.pkcs11.P11TlsMasterSecretGenerator",
0N/A m(CKM_SSL3_MASTER_KEY_DERIVE, CKM_TLS_MASTER_KEY_DERIVE,
1111N/A CKM_SSL3_MASTER_KEY_DERIVE_DH,
1111N/A CKM_TLS_MASTER_KEY_DERIVE_DH));
1111N/A d(KG, "SunTlsKeyMaterial",
1111N/A "sun.security.pkcs11.P11TlsKeyMaterialGenerator",
0N/A m(CKM_SSL3_KEY_AND_MAC_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE));
0N/A d(KG, "SunTlsPrf", "sun.security.pkcs11.P11TlsPrfGenerator",
0N/A m(CKM_TLS_PRF, CKM_NSS_TLS_PRF_GENERAL));
0N/A }
0N/A
0N/A // background thread that periodically checks for token insertion
0N/A // if no token is present. We need to do that in a separate thread because
0N/A // the insertion check may block for quite a long time on some tokens.
0N/A private static class TokenPoller implements Runnable {
0N/A private final SunPKCS11 provider;
0N/A private volatile boolean enabled;
0N/A private TokenPoller(SunPKCS11 provider) {
0N/A this.provider = provider;
0N/A enabled = true;
0N/A }
0N/A public void run() {
0N/A int interval = provider.config.getInsertionCheckInterval();
0N/A while (enabled) {
0N/A try {
0N/A Thread.sleep(interval);
0N/A } catch (InterruptedException e) {
0N/A break;
0N/A }
0N/A if (enabled == false) {
0N/A break;
0N/A }
0N/A try {
0N/A provider.initToken(null);
0N/A } catch (PKCS11Exception e) {
0N/A // ignore
0N/A }
0N/A }
0N/A }
0N/A void disable() {
0N/A enabled = false;
0N/A }
0N/A }
0N/A
0N/A // create the poller thread, if not already active
0N/A private void createPoller() {
0N/A if (poller != null) {
0N/A return;
0N/A }
0N/A TokenPoller poller = new TokenPoller(this);
0N/A Thread t = new Thread(poller, "Poller " + getName());
0N/A t.setDaemon(true);
0N/A t.setPriority(Thread.MIN_PRIORITY);
0N/A t.start();
0N/A this.poller = poller;
0N/A }
0N/A
0N/A // destroy the poller thread, if active
0N/A private void destroyPoller() {
0N/A if (poller != null) {
0N/A poller.disable();
0N/A poller = null;
0N/A }
0N/A }
0N/A
0N/A private boolean hasValidToken() {
264N/A /* Commented out to work with Solaris softtoken impl which
264N/A returns 0-value flags, e.g. both REMOVABLE_DEVICE and
264N/A TOKEN_PRESENT are false, when it can't access the token.
0N/A if (removable == false) {
0N/A return true;
0N/A }
264N/A */
0N/A Token token = this.token;
0N/A return (token != null) && token.isValid();
0N/A }
0N/A
0N/A // destroy the token. Called if we detect that it has been removed
0N/A synchronized void uninitToken(Token token) {
0N/A if (this.token != token) {
0N/A // mismatch, our token must already be destroyed
0N/A return;
0N/A }
0N/A destroyPoller();
0N/A this.token = null;
0N/A // unregister all algorithms
0N/A AccessController.doPrivileged(new PrivilegedAction<Object>() {
0N/A public Object run() {
0N/A clear();
0N/A return null;
0N/A }
0N/A });
0N/A createPoller();
0N/A }
0N/A
0N/A // test if a token is present and initialize this provider for it if so.
0N/A // does nothing if no token is found
0N/A // called from constructor and by poller
0N/A private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {
0N/A if (slotInfo == null) {
0N/A slotInfo = p11.C_GetSlotInfo(slotID);
0N/A }
264N/A if (removable && (slotInfo.flags & CKF_TOKEN_PRESENT) == 0) {
0N/A createPoller();
0N/A return;
0N/A }
0N/A destroyPoller();
0N/A boolean showInfo = config.getShowInfo();
0N/A if (showInfo) {
0N/A System.out.println("Slot info for slot " + slotID + ":");
0N/A System.out.println(slotInfo);
0N/A }
0N/A final Token token = new Token(this);
0N/A if (showInfo) {
0N/A System.out.println
0N/A ("Token info for token in slot " + slotID + ":");
0N/A System.out.println(token.tokenInfo);
0N/A }
0N/A long[] supportedMechanisms = p11.C_GetMechanismList(slotID);
1111N/A
1111N/A // Create a map from the various Descriptors to the "most
1111N/A // preferred" mechanism that was defined during the
1111N/A // static initialization. For example, DES/CBC/PKCS5Padding
1111N/A // could be mapped to CKM_DES_CBC_PAD or CKM_DES_CBC. Prefer
1111N/A // the earliest entry. When asked for "DES/CBC/PKCS5Padding", we
1111N/A // return a CKM_DES_CBC_PAD.
0N/A final Map<Descriptor,Integer> supportedAlgs =
0N/A new HashMap<Descriptor,Integer>();
0N/A for (int i = 0; i < supportedMechanisms.length; i++) {
0N/A long longMech = supportedMechanisms[i];
0N/A boolean isEnabled = config.isEnabled(longMech);
0N/A if (showInfo) {
0N/A CK_MECHANISM_INFO mechInfo =
0N/A p11.C_GetMechanismInfo(slotID, longMech);
0N/A System.out.println("Mechanism " +
0N/A Functions.getMechanismName(longMech) + ":");
0N/A if (isEnabled == false) {
0N/A System.out.println("DISABLED in configuration");
0N/A }
0N/A System.out.println(mechInfo);
0N/A }
0N/A if (isEnabled == false) {
0N/A continue;
0N/A }
0N/A // we do not know of mechs with the upper 32 bits set
0N/A if (longMech >>> 32 != 0) {
0N/A continue;
0N/A }
0N/A int mech = (int)longMech;
0N/A Integer integerMech = Integer.valueOf(mech);
0N/A List<Descriptor> ds = descriptors.get(integerMech);
0N/A if (ds == null) {
0N/A continue;
0N/A }
0N/A for (Descriptor d : ds) {
0N/A Integer oldMech = supportedAlgs.get(d);
0N/A if (oldMech == null) {
0N/A supportedAlgs.put(d, integerMech);
0N/A continue;
0N/A }
1111N/A // See if there is something "more preferred"
1111N/A // than what we currently have in the supportedAlgs
1111N/A // map.
0N/A int intOldMech = oldMech.intValue();
0N/A for (int j = 0; j < d.mechanisms.length; j++) {
0N/A int nextMech = d.mechanisms[j];
0N/A if (mech == nextMech) {
0N/A supportedAlgs.put(d, integerMech);
0N/A break;
0N/A } else if (intOldMech == nextMech) {
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A
0N/A }
0N/A
0N/A // register algorithms in provider
0N/A AccessController.doPrivileged(new PrivilegedAction<Object>() {
0N/A public Object run() {
0N/A for (Map.Entry<Descriptor,Integer> entry
0N/A : supportedAlgs.entrySet()) {
0N/A Descriptor d = entry.getKey();
0N/A int mechanism = entry.getValue().intValue();
0N/A Service s = d.service(token, mechanism);
0N/A putService(s);
0N/A }
0N/A if (((token.tokenInfo.flags & CKF_RNG) != 0)
0N/A && config.isEnabled(PCKM_SECURERANDOM)
0N/A && !token.sessionManager.lowMaxSessions()) {
0N/A // do not register SecureRandom if the token does
0N/A // not support many sessions. if we did, we might
0N/A // run out of sessions in the middle of a
0N/A // nextBytes() call where we cannot fail over.
0N/A putService(new P11Service(token, SR, "PKCS11",
0N/A "sun.security.pkcs11.P11SecureRandom", null,
0N/A PCKM_SECURERANDOM));
0N/A }
0N/A if (config.isEnabled(PCKM_KEYSTORE)) {
0N/A putService(new P11Service(token, KS, "PKCS11",
0N/A "sun.security.pkcs11.P11KeyStore",
0N/A s("PKCS11-" + config.getName()),
0N/A PCKM_KEYSTORE));
0N/A }
0N/A return null;
0N/A }
0N/A });
0N/A
0N/A this.token = token;
0N/A }
0N/A
0N/A private static final class P11Service extends Service {
0N/A
0N/A private final Token token;
0N/A
0N/A private final long mechanism;
0N/A
0N/A P11Service(Token token, String type, String algorithm,
0N/A String className, String[] al, long mechanism) {
0N/A super(token.provider, type, algorithm, className, toList(al), null);
0N/A this.token = token;
0N/A this.mechanism = mechanism & 0xFFFFFFFFL;
0N/A }
0N/A
0N/A private static List<String> toList(String[] aliases) {
0N/A return (aliases == null) ? null : Arrays.asList(aliases);
0N/A }
0N/A
3002N/A public Object newInstance(Object param)
3002N/A throws NoSuchAlgorithmException {
0N/A if (token.isValid() == false) {
0N/A throw new NoSuchAlgorithmException("Token has been removed");
0N/A }
0N/A try {
0N/A return newInstance0(param);
0N/A } catch (PKCS11Exception e) {
0N/A throw new NoSuchAlgorithmException(e);
0N/A }
0N/A }
0N/A
0N/A public Object newInstance0(Object param) throws
0N/A PKCS11Exception, NoSuchAlgorithmException {
0N/A String algorithm = getAlgorithm();
0N/A String type = getType();
0N/A if (type == MD) {
0N/A return new P11Digest(token, algorithm, mechanism);
0N/A } else if (type == CIP) {
0N/A if (algorithm.startsWith("RSA")) {
0N/A return new P11RSACipher(token, algorithm, mechanism);
0N/A } else {
0N/A return new P11Cipher(token, algorithm, mechanism);
0N/A }
0N/A } else if (type == SIG) {
0N/A return new P11Signature(token, algorithm, mechanism);
0N/A } else if (type == MAC) {
0N/A return new P11Mac(token, algorithm, mechanism);
0N/A } else if (type == KPG) {
0N/A return new P11KeyPairGenerator(token, algorithm, mechanism);
0N/A } else if (type == KA) {
0N/A if (algorithm.equals("ECDH")) {
0N/A return new P11ECDHKeyAgreement(token, algorithm, mechanism);
0N/A } else {
0N/A return new P11KeyAgreement(token, algorithm, mechanism);
0N/A }
0N/A } else if (type == KF) {
0N/A return token.getKeyFactory(algorithm);
0N/A } else if (type == SKF) {
0N/A return new P11SecretKeyFactory(token, algorithm);
0N/A } else if (type == KG) {
0N/A // reference equality
0N/A if (algorithm == "SunTlsRsaPremasterSecret") {
0N/A return new P11TlsRsaPremasterSecretGenerator(
0N/A token, algorithm, mechanism);
0N/A } else if (algorithm == "SunTlsMasterSecret") {
0N/A return new P11TlsMasterSecretGenerator(
0N/A token, algorithm, mechanism);
0N/A } else if (algorithm == "SunTlsKeyMaterial") {
0N/A return new P11TlsKeyMaterialGenerator(
0N/A token, algorithm, mechanism);
0N/A } else if (algorithm == "SunTlsPrf") {
0N/A return new P11TlsPrfGenerator(token, algorithm, mechanism);
0N/A } else {
0N/A return new P11KeyGenerator(token, algorithm, mechanism);
0N/A }
0N/A } else if (type == SR) {
0N/A return token.getRandom();
0N/A } else if (type == KS) {
0N/A return token.getKeyStore();
0N/A } else if (type == AGP) {
0N/A return new sun.security.ec.ECParameters();
0N/A } else {
0N/A throw new NoSuchAlgorithmException("Unknown type: " + type);
0N/A }
0N/A }
0N/A
0N/A public boolean supportsParameter(Object param) {
0N/A if ((param == null) || (token.isValid() == false)) {
0N/A return false;
0N/A }
0N/A if (param instanceof Key == false) {
0N/A throw new InvalidParameterException("Parameter must be a Key");
0N/A }
0N/A String algorithm = getAlgorithm();
0N/A String type = getType();
0N/A Key key = (Key)param;
0N/A String keyAlgorithm = key.getAlgorithm();
0N/A // RSA signatures and cipher
0N/A if (((type == CIP) && algorithm.startsWith("RSA"))
0N/A || (type == SIG) && algorithm.endsWith("RSA")) {
0N/A if (keyAlgorithm.equals("RSA") == false) {
0N/A return false;
0N/A }
0N/A return isLocalKey(key)
0N/A || (key instanceof RSAPrivateKey)
0N/A || (key instanceof RSAPublicKey);
0N/A }
0N/A // EC
0N/A if (((type == KA) && algorithm.equals("ECDH"))
0N/A || ((type == SIG) && algorithm.endsWith("ECDSA"))) {
0N/A if (keyAlgorithm.equals("EC") == false) {
0N/A return false;
0N/A }
0N/A return isLocalKey(key)
0N/A || (key instanceof ECPrivateKey)
0N/A || (key instanceof ECPublicKey);
0N/A }
0N/A // DSA signatures
0N/A if ((type == SIG) && algorithm.endsWith("DSA")) {
0N/A if (keyAlgorithm.equals("DSA") == false) {
0N/A return false;
0N/A }
0N/A return isLocalKey(key)
0N/A || (key instanceof DSAPrivateKey)
0N/A || (key instanceof DSAPublicKey);
0N/A }
0N/A // MACs and symmetric ciphers
0N/A if ((type == CIP) || (type == MAC)) {
0N/A // do not check algorithm name, mismatch is unlikely anyway
0N/A return isLocalKey(key) || "RAW".equals(key.getFormat());
0N/A }
0N/A // DH key agreement
0N/A if (type == KA) {
0N/A if (keyAlgorithm.equals("DH") == false) {
0N/A return false;
0N/A }
0N/A return isLocalKey(key)
0N/A || (key instanceof DHPrivateKey)
0N/A || (key instanceof DHPublicKey);
0N/A }
0N/A // should not reach here,
0N/A // unknown engine type or algorithm
0N/A throw new AssertionError
0N/A ("SunPKCS11 error: " + type + ", " + algorithm);
0N/A }
0N/A
0N/A private boolean isLocalKey(Key key) {
0N/A return (key instanceof P11Key) && (((P11Key)key).token == token);
0N/A }
0N/A
0N/A public String toString() {
0N/A return super.toString() +
0N/A " (" + Functions.getMechanismName(mechanism) + ")";
0N/A }
0N/A
0N/A }
0N/A
0N/A /**
0N/A * Log in to this provider.
0N/A *
0N/A * <p> If the token expects a PIN to be supplied by the caller,
0N/A * the <code>handler</code> implementation must support
0N/A * a <code>PasswordCallback</code>.
0N/A *
0N/A * <p> To determine if the token supports a protected authentication path,
0N/A * the CK_TOKEN_INFO flag, CKF_PROTECTED_AUTHENTICATION_PATH, is consulted.
0N/A *
0N/A * @param subject this parameter is ignored
0N/A * @param handler the <code>CallbackHandler</code> used by
0N/A * this provider to communicate with the caller
0N/A *
0N/A * @exception LoginException if the login operation fails
0N/A * @exception SecurityException if the does not pass a security check for
0N/A * <code>SecurityPermission("authProvider.<i>name</i>")</code>,
0N/A * where <i>name</i> is the value returned by
0N/A * this provider's <code>getName</code> method
0N/A */
0N/A public void login(Subject subject, CallbackHandler handler)
0N/A throws LoginException {
0N/A
0N/A // security check
0N/A
0N/A SecurityManager sm = System.getSecurityManager();
0N/A if (sm != null) {
0N/A if (debug != null) {
0N/A debug.println("checking login permission");
0N/A }
0N/A sm.checkPermission(new SecurityPermission
0N/A ("authProvider." + this.getName()));
0N/A }
0N/A
0N/A if (hasValidToken() == false) {
0N/A throw new LoginException("No token present");
0N/A }
0N/A
0N/A // see if a login is required
0N/A
0N/A if ((token.tokenInfo.flags & CKF_LOGIN_REQUIRED) == 0) {
0N/A if (debug != null) {
0N/A debug.println("login operation not required for token - " +
0N/A "ignoring login request");
0N/A }
0N/A return;
0N/A }
0N/A
0N/A // see if user already logged in
0N/A
0N/A try {
0N/A if (token.isLoggedInNow(null)) {
0N/A // user already logged in
0N/A if (debug != null) {
0N/A debug.println("user already logged in");
0N/A }
0N/A return;
0N/A }
0N/A } catch (PKCS11Exception e) {
0N/A // ignore - fall thru and attempt login
0N/A }
0N/A
0N/A // get the pin if necessary
0N/A
0N/A char[] pin = null;
0N/A if ((token.tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) {
0N/A
0N/A // get password
0N/A
0N/A CallbackHandler myHandler = getCallbackHandler(handler);
0N/A if (myHandler == null) {
0N/A // XXX PolicyTool is dependent on this message text
0N/A throw new LoginException
0N/A ("no password provided, and no callback handler " +
0N/A "available for retrieving password");
0N/A }
0N/A
0N/A java.text.MessageFormat form = new java.text.MessageFormat
0N/A (ResourcesMgr.getString
3050N/A ("PKCS11.Token.providerName.Password."));
0N/A Object[] source = { getName() };
0N/A
0N/A PasswordCallback pcall = new PasswordCallback(form.format(source),
0N/A false);
0N/A Callback[] callbacks = { pcall };
0N/A try {
0N/A myHandler.handle(callbacks);
0N/A } catch (Exception e) {
0N/A LoginException le = new LoginException
0N/A ("Unable to perform password callback");
0N/A le.initCause(e);
0N/A throw le;
0N/A }
0N/A
0N/A pin = pcall.getPassword();
0N/A pcall.clearPassword();
0N/A if (pin == null) {
0N/A if (debug != null) {
0N/A debug.println("caller passed NULL pin");
0N/A }
0N/A }
0N/A }
0N/A
0N/A // perform token login
0N/A
0N/A Session session = null;
0N/A try {
0N/A session = token.getOpSession();
0N/A
0N/A // pin is NULL if using CKF_PROTECTED_AUTHENTICATION_PATH
0N/A p11.C_Login(session.id(), CKU_USER, pin);
0N/A if (debug != null) {
0N/A debug.println("login succeeded");
0N/A }
0N/A } catch (PKCS11Exception pe) {
0N/A if (pe.getErrorCode() == CKR_USER_ALREADY_LOGGED_IN) {
0N/A // let this one go
0N/A if (debug != null) {
0N/A debug.println("user already logged in");
0N/A }
0N/A return;
0N/A } else if (pe.getErrorCode() == CKR_PIN_INCORRECT) {
0N/A FailedLoginException fle = new FailedLoginException();
0N/A fle.initCause(pe);
0N/A throw fle;
0N/A } else {
0N/A LoginException le = new LoginException();
0N/A le.initCause(pe);
0N/A throw le;
0N/A }
0N/A } finally {
0N/A token.releaseSession(session);
0N/A if (pin != null) {
0N/A Arrays.fill(pin, ' ');
0N/A }
0N/A }
0N/A
0N/A // we do not store the PIN in the subject for now
0N/A }
0N/A
0N/A /**
0N/A * Log out from this provider
0N/A *
0N/A * @exception LoginException if the logout operation fails
0N/A * @exception SecurityException if the does not pass a security check for
0N/A * <code>SecurityPermission("authProvider.<i>name</i>")</code>,
0N/A * where <i>name</i> is the value returned by
0N/A * this provider's <code>getName</code> method
0N/A */
0N/A public void logout() throws LoginException {
0N/A
0N/A // security check
0N/A
0N/A SecurityManager sm = System.getSecurityManager();
0N/A if (sm != null) {
0N/A sm.checkPermission
0N/A (new SecurityPermission("authProvider." + this.getName()));
0N/A }
0N/A
0N/A if (hasValidToken() == false) {
0N/A // app may call logout for cleanup, allow
0N/A return;
0N/A }
0N/A
0N/A if ((token.tokenInfo.flags & CKF_LOGIN_REQUIRED) == 0) {
0N/A if (debug != null) {
0N/A debug.println("logout operation not required for token - " +
0N/A "ignoring logout request");
0N/A }
0N/A return;
0N/A }
0N/A
0N/A try {
0N/A if (token.isLoggedInNow(null) == false) {
0N/A if (debug != null) {
0N/A debug.println("user not logged in");
0N/A }
0N/A return;
0N/A }
0N/A } catch (PKCS11Exception e) {
0N/A // ignore
0N/A }
0N/A
0N/A // perform token logout
0N/A
0N/A Session session = null;
0N/A try {
0N/A session = token.getOpSession();
0N/A p11.C_Logout(session.id());
0N/A if (debug != null) {
0N/A debug.println("logout succeeded");
0N/A }
0N/A } catch (PKCS11Exception pe) {
0N/A if (pe.getErrorCode() == CKR_USER_NOT_LOGGED_IN) {
0N/A // let this one go
0N/A if (debug != null) {
0N/A debug.println("user not logged in");
0N/A }
0N/A return;
0N/A }
0N/A LoginException le = new LoginException();
0N/A le.initCause(pe);
0N/A throw le;
0N/A } finally {
0N/A token.releaseSession(session);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Set a <code>CallbackHandler</code>
0N/A *
0N/A * <p> The provider uses this handler if one is not passed to the
0N/A * <code>login</code> method. The provider also uses this handler
0N/A * if it invokes <code>login</code> on behalf of callers.
0N/A * In either case if a handler is not set via this method,
0N/A * the provider queries the
0N/A * <i>auth.login.defaultCallbackHandler</i> security property
0N/A * for the fully qualified class name of a default handler implementation.
0N/A * If the security property is not set,
0N/A * the provider is assumed to have alternative means
0N/A * for obtaining authentication information.
0N/A *
0N/A * @param handler a <code>CallbackHandler</code> for obtaining
0N/A * authentication information, which may be <code>null</code>
0N/A *
0N/A * @exception SecurityException if the caller does not pass a
0N/A * security check for
0N/A * <code>SecurityPermission("authProvider.<i>name</i>")</code>,
0N/A * where <i>name</i> is the value returned by
0N/A * this provider's <code>getName</code> method
0N/A */
0N/A public void setCallbackHandler(CallbackHandler handler) {
0N/A
0N/A // security check
0N/A
0N/A SecurityManager sm = System.getSecurityManager();
0N/A if (sm != null) {
0N/A sm.checkPermission
0N/A (new SecurityPermission("authProvider." + this.getName()));
0N/A }
0N/A
0N/A synchronized (LOCK_HANDLER) {
0N/A pHandler = handler;
0N/A }
0N/A }
0N/A
0N/A private CallbackHandler getCallbackHandler(CallbackHandler handler) {
0N/A
0N/A // get default handler if necessary
0N/A
0N/A if (handler != null) {
0N/A return handler;
0N/A }
0N/A
0N/A if (debug != null) {
0N/A debug.println("getting provider callback handler");
0N/A }
0N/A
0N/A synchronized (LOCK_HANDLER) {
0N/A // see if handler was set via setCallbackHandler
0N/A if (pHandler != null) {
0N/A return pHandler;
0N/A }
0N/A
0N/A try {
0N/A if (debug != null) {
0N/A debug.println("getting default callback handler");
0N/A }
0N/A
0N/A CallbackHandler myHandler = AccessController.doPrivileged
0N/A (new PrivilegedExceptionAction<CallbackHandler>() {
0N/A public CallbackHandler run() throws Exception {
0N/A
0N/A String defaultHandler =
0N/A java.security.Security.getProperty
0N/A ("auth.login.defaultCallbackHandler");
0N/A
0N/A if (defaultHandler == null ||
0N/A defaultHandler.length() == 0) {
0N/A
0N/A // ok
0N/A if (debug != null) {
0N/A debug.println("no default handler set");
0N/A }
0N/A return null;
0N/A }
0N/A
0N/A Class c = Class.forName
0N/A (defaultHandler,
0N/A true,
0N/A Thread.currentThread().getContextClassLoader());
0N/A return (CallbackHandler)c.newInstance();
0N/A }
0N/A });
0N/A
0N/A // save it
0N/A pHandler = myHandler;
0N/A return myHandler;
0N/A
0N/A } catch (PrivilegedActionException pae) {
0N/A // ok
0N/A if (debug != null) {
0N/A debug.println("Unable to load default callback handler");
0N/A pae.printStackTrace();
0N/A }
0N/A }
0N/A }
0N/A return null;
0N/A }
0N/A
0N/A private Object writeReplace() throws ObjectStreamException {
0N/A return new SunPKCS11Rep(this);
0N/A }
0N/A
0N/A /**
0N/A * Serialized representation of the SunPKCS11 provider.
0N/A */
0N/A private static class SunPKCS11Rep implements Serializable {
0N/A
0N/A static final long serialVersionUID = -2896606995897745419L;
0N/A
0N/A private final String providerName;
0N/A
0N/A private final String configName;
0N/A
0N/A SunPKCS11Rep(SunPKCS11 provider) throws NotSerializableException {
0N/A providerName = provider.getName();
0N/A configName = provider.configName;
0N/A if (Security.getProvider(providerName) != provider) {
0N/A throw new NotSerializableException("Only SunPKCS11 providers "
0N/A + "installed in java.security.Security can be serialized");
0N/A }
0N/A }
0N/A
0N/A private Object readResolve() throws ObjectStreamException {
0N/A SunPKCS11 p = (SunPKCS11)Security.getProvider(providerName);
0N/A if ((p == null) || (p.configName.equals(configName) == false)) {
0N/A throw new NotSerializableException("Could not find "
0N/A + providerName + " in installed providers");
0N/A }
0N/A return p;
0N/A }
0N/A }
0N/A}