Path: blob/aarch64-shenandoah-jdk8u272-b10/jdk/src/share/classes/sun/security/pkcs11/SunPKCS11.java
38919 views
/*1* Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425package sun.security.pkcs11;2627import java.io.*;28import java.util.*;2930import java.security.*;31import java.security.interfaces.*;3233import javax.crypto.interfaces.*;3435import javax.security.auth.Subject;36import javax.security.auth.login.LoginException;37import javax.security.auth.login.FailedLoginException;38import javax.security.auth.callback.Callback;39import javax.security.auth.callback.CallbackHandler;40import javax.security.auth.callback.ConfirmationCallback;41import javax.security.auth.callback.PasswordCallback;42import javax.security.auth.callback.TextOutputCallback;4344import sun.security.util.Debug;45import sun.security.util.ResourcesMgr;4647import sun.security.pkcs11.Secmod.*;4849import sun.security.pkcs11.wrapper.*;50import static sun.security.pkcs11.wrapper.PKCS11Constants.*;5152/**53* PKCS#11 provider main class.54*55* @author Andreas Sterbenz56* @since 1.557*/58public final class SunPKCS11 extends AuthProvider {5960private static final long serialVersionUID = -1354835039035306505L;6162static final Debug debug = Debug.getInstance("sunpkcs11");6364private static int dummyConfigId;6566// the PKCS11 object through which we make the native calls67final PKCS11 p11;6869// name of the configuration file70private final String configName;7172// configuration information73final Config config;7475// id of the PKCS#11 slot we are using76final long slotID;7778private CallbackHandler pHandler;79private final Object LOCK_HANDLER = new Object();8081final boolean removable;8283final Module nssModule;8485final boolean nssUseSecmodTrust;8687private volatile Token token;8889private TokenPoller poller;9091Token getToken() {92return token;93}9495public SunPKCS11() {96super("SunPKCS11-Dummy", 1.8d, "SunPKCS11-Dummy");97throw new ProviderException98("SunPKCS11 requires configuration file argument");99}100101public SunPKCS11(String configName) {102this(checkNull(configName), null);103}104105public SunPKCS11(InputStream configStream) {106this(getDummyConfigName(), checkNull(configStream));107}108109private static <T> T checkNull(T obj) {110if (obj == null) {111throw new NullPointerException();112}113return obj;114}115116private static synchronized String getDummyConfigName() {117int id = ++dummyConfigId;118return "---DummyConfig-" + id + "---";119}120121/**122* @deprecated use new SunPKCS11(String) or new SunPKCS11(InputStream)123* instead124*/125@Deprecated126public SunPKCS11(String configName, InputStream configStream) {127super("SunPKCS11-" +128Config.getConfig(configName, configStream).getName(),1291.8d, Config.getConfig(configName, configStream).getDescription());130this.configName = configName;131this.config = Config.removeConfig(configName);132133if (debug != null) {134System.out.println("SunPKCS11 loading " + configName);135}136137String library = config.getLibrary();138String functionList = config.getFunctionList();139long slotID = config.getSlotID();140int slotListIndex = config.getSlotListIndex();141142boolean useSecmod = config.getNssUseSecmod();143boolean nssUseSecmodTrust = config.getNssUseSecmodTrust();144Module nssModule = null;145146//147// Initialization via Secmod. The way this works is as follows:148// SunPKCS11 is either in normal mode or in NSS Secmod mode.149// Secmod is activated by specifying one or more of the following150// options in the config file:151// nssUseSecmod, nssSecmodDirectory, nssLibrary, nssModule152//153// XXX add more explanation here154//155// If we are in Secmod mode and configured to use either the156// nssKeyStore or the nssTrustAnchors module, we automatically157// switch to using the NSS trust attributes for trusted certs158// (KeyStore).159//160161if (useSecmod) {162// note: Config ensures library/slot/slotListIndex not specified163// in secmod mode.164Secmod secmod = Secmod.getInstance();165DbMode nssDbMode = config.getNssDbMode();166try {167String nssLibraryDirectory = config.getNssLibraryDirectory();168String nssSecmodDirectory = config.getNssSecmodDirectory();169boolean nssOptimizeSpace = config.getNssOptimizeSpace();170171if (secmod.isInitialized()) {172if (nssSecmodDirectory != null) {173String s = secmod.getConfigDir();174if ((s != null) &&175(s.equals(nssSecmodDirectory) == false)) {176throw new ProviderException("Secmod directory "177+ nssSecmodDirectory178+ " invalid, NSS already initialized with "179+ s);180}181}182if (nssLibraryDirectory != null) {183String s = secmod.getLibDir();184if ((s != null) &&185(s.equals(nssLibraryDirectory) == false)) {186throw new ProviderException("NSS library directory "187+ nssLibraryDirectory188+ " invalid, NSS already initialized with "189+ s);190}191}192} else {193if (nssDbMode != DbMode.NO_DB) {194if (nssSecmodDirectory == null) {195throw new ProviderException(196"Secmod not initialized and "197+ "nssSecmodDirectory not specified");198}199} else {200if (nssSecmodDirectory != null) {201throw new ProviderException(202"nssSecmodDirectory must not be "203+ "specified in noDb mode");204}205}206secmod.initialize(nssDbMode, nssSecmodDirectory,207nssLibraryDirectory, nssOptimizeSpace);208}209} catch (IOException e) {210// XXX which exception to throw211throw new ProviderException("Could not initialize NSS", e);212}213List<Module> modules = secmod.getModules();214if (config.getShowInfo()) {215System.out.println("NSS modules: " + modules);216}217218String moduleName = config.getNssModule();219if (moduleName == null) {220nssModule = secmod.getModule(ModuleType.FIPS);221if (nssModule != null) {222moduleName = "fips";223} else {224moduleName = (nssDbMode == DbMode.NO_DB) ?225"crypto" : "keystore";226}227}228if (moduleName.equals("fips")) {229nssModule = secmod.getModule(ModuleType.FIPS);230nssUseSecmodTrust = true;231functionList = "FC_GetFunctionList";232} else if (moduleName.equals("keystore")) {233nssModule = secmod.getModule(ModuleType.KEYSTORE);234nssUseSecmodTrust = true;235} else if (moduleName.equals("crypto")) {236nssModule = secmod.getModule(ModuleType.CRYPTO);237} else if (moduleName.equals("trustanchors")) {238// XXX should the option be called trustanchor or trustanchors??239nssModule = secmod.getModule(ModuleType.TRUSTANCHOR);240nssUseSecmodTrust = true;241} else if (moduleName.startsWith("external-")) {242int moduleIndex;243try {244moduleIndex = Integer.parseInt245(moduleName.substring("external-".length()));246} catch (NumberFormatException e) {247moduleIndex = -1;248}249if (moduleIndex < 1) {250throw new ProviderException251("Invalid external module: " + moduleName);252}253int k = 0;254for (Module module : modules) {255if (module.getType() == ModuleType.EXTERNAL) {256if (++k == moduleIndex) {257nssModule = module;258break;259}260}261}262if (nssModule == null) {263throw new ProviderException("Invalid module " + moduleName264+ ": only " + k + " external NSS modules available");265}266} else {267throw new ProviderException(268"Unknown NSS module: " + moduleName);269}270if (nssModule == null) {271throw new ProviderException(272"NSS module not available: " + moduleName);273}274if (nssModule.hasInitializedProvider()) {275throw new ProviderException("Secmod module already configured");276}277library = nssModule.libraryName;278slotListIndex = nssModule.slot;279}280this.nssUseSecmodTrust = nssUseSecmodTrust;281this.nssModule = nssModule;282283File libraryFile = new File(library);284// if the filename is a simple filename without path285// (e.g. "libpkcs11.so"), it may refer to a library somewhere on the286// OS library search path. Omit the test for file existance as that287// only looks in the current directory.288if (libraryFile.getName().equals(library) == false) {289if (new File(library).isFile() == false) {290String msg = "Library " + library + " does not exist";291if (config.getHandleStartupErrors() == Config.ERR_HALT) {292throw new ProviderException(msg);293} else {294throw new UnsupportedOperationException(msg);295}296}297}298299try {300if (debug != null) {301debug.println("Initializing PKCS#11 library " + library);302}303CK_C_INITIALIZE_ARGS initArgs = new CK_C_INITIALIZE_ARGS();304String nssArgs = config.getNssArgs();305if (nssArgs != null) {306initArgs.pReserved = nssArgs;307}308// request multithreaded access first309initArgs.flags = CKF_OS_LOCKING_OK;310PKCS11 tmpPKCS11;311try {312tmpPKCS11 = PKCS11.getInstance(313library, functionList, initArgs,314config.getOmitInitialize());315} catch (PKCS11Exception e) {316if (debug != null) {317debug.println("Multi-threaded initialization failed: " + e);318}319if (config.getAllowSingleThreadedModules() == false) {320throw e;321}322// fall back to single threaded access323if (nssArgs == null) {324// if possible, use null initArgs for better compatibility325initArgs = null;326} else {327initArgs.flags = 0;328}329tmpPKCS11 = PKCS11.getInstance(library,330functionList, initArgs, config.getOmitInitialize());331}332p11 = tmpPKCS11;333334CK_INFO p11Info = p11.C_GetInfo();335if (p11Info.cryptokiVersion.major < 2) {336throw new ProviderException("Only PKCS#11 v2.0 and later "337+ "supported, library version is v" + p11Info.cryptokiVersion);338}339boolean showInfo = config.getShowInfo();340if (showInfo) {341System.out.println("Information for provider " + getName());342System.out.println("Library info:");343System.out.println(p11Info);344}345346if ((slotID < 0) || showInfo) {347long[] slots = p11.C_GetSlotList(false);348if (showInfo) {349System.out.println("All slots: " + toString(slots));350slots = p11.C_GetSlotList(true);351System.out.println("Slots with tokens: " + toString(slots));352}353if (slotID < 0) {354if ((slotListIndex < 0)355|| (slotListIndex >= slots.length)) {356throw new ProviderException("slotListIndex is "357+ slotListIndex358+ " but token only has " + slots.length + " slots");359}360slotID = slots[slotListIndex];361}362}363this.slotID = slotID;364CK_SLOT_INFO slotInfo = p11.C_GetSlotInfo(slotID);365removable = (slotInfo.flags & CKF_REMOVABLE_DEVICE) != 0;366initToken(slotInfo);367if (nssModule != null) {368nssModule.setProvider(this);369}370} catch (Exception e) {371if (config.getHandleStartupErrors() == Config.ERR_IGNORE_ALL) {372throw new UnsupportedOperationException373("Initialization failed", e);374} else {375throw new ProviderException376("Initialization failed", e);377}378}379}380381private static String toString(long[] longs) {382if (longs.length == 0) {383return "(none)";384}385StringBuilder sb = new StringBuilder();386sb.append(longs[0]);387for (int i = 1; i < longs.length; i++) {388sb.append(", ");389sb.append(longs[i]);390}391return sb.toString();392}393394public boolean equals(Object obj) {395return this == obj;396}397398public int hashCode() {399return System.identityHashCode(this);400}401402private static String[] s(String ...aliases) {403return aliases;404}405406private static final class Descriptor {407final String type;408final String algorithm;409final String className;410final String[] aliases;411final int[] mechanisms;412413private Descriptor(String type, String algorithm, String className,414String[] aliases, int[] mechanisms) {415this.type = type;416this.algorithm = algorithm;417this.className = className;418this.aliases = aliases;419this.mechanisms = mechanisms;420}421private P11Service service(Token token, int mechanism) {422return new P11Service423(token, type, algorithm, className, aliases, mechanism);424}425public String toString() {426return type + "." + algorithm;427}428}429430// Map from mechanism to List of Descriptors that should be431// registered if the mechanism is supported432private final static Map<Integer,List<Descriptor>> descriptors =433new HashMap<Integer,List<Descriptor>>();434435private static int[] m(long m1) {436return new int[] {(int)m1};437}438439private static int[] m(long m1, long m2) {440return new int[] {(int)m1, (int)m2};441}442443private static int[] m(long m1, long m2, long m3) {444return new int[] {(int)m1, (int)m2, (int)m3};445}446447private static int[] m(long m1, long m2, long m3, long m4) {448return new int[] {(int)m1, (int)m2, (int)m3, (int)m4};449}450451private static void d(String type, String algorithm, String className,452int[] m) {453register(new Descriptor(type, algorithm, className, null, m));454}455456private static void d(String type, String algorithm, String className,457String[] aliases, int[] m) {458register(new Descriptor(type, algorithm, className, aliases, m));459}460461private static void register(Descriptor d) {462for (int i = 0; i < d.mechanisms.length; i++) {463int m = d.mechanisms[i];464Integer key = Integer.valueOf(m);465List<Descriptor> list = descriptors.get(key);466if (list == null) {467list = new ArrayList<Descriptor>();468descriptors.put(key, list);469}470list.add(d);471}472}473474private final static String MD = "MessageDigest";475476private final static String SIG = "Signature";477478private final static String KPG = "KeyPairGenerator";479480private final static String KG = "KeyGenerator";481482private final static String AGP = "AlgorithmParameters";483484private final static String KF = "KeyFactory";485486private final static String SKF = "SecretKeyFactory";487488private final static String CIP = "Cipher";489490private final static String MAC = "Mac";491492private final static String KA = "KeyAgreement";493494private final static String KS = "KeyStore";495496private final static String SR = "SecureRandom";497498static {499// names of all the implementation classes500// use local variables, only used here501String P11Digest = "sun.security.pkcs11.P11Digest";502String P11MAC = "sun.security.pkcs11.P11MAC";503String P11KeyPairGenerator = "sun.security.pkcs11.P11KeyPairGenerator";504String P11KeyGenerator = "sun.security.pkcs11.P11KeyGenerator";505String P11RSAKeyFactory = "sun.security.pkcs11.P11RSAKeyFactory";506String P11DSAKeyFactory = "sun.security.pkcs11.P11DSAKeyFactory";507String P11DHKeyFactory = "sun.security.pkcs11.P11DHKeyFactory";508String P11KeyAgreement = "sun.security.pkcs11.P11KeyAgreement";509String P11SecretKeyFactory = "sun.security.pkcs11.P11SecretKeyFactory";510String P11Cipher = "sun.security.pkcs11.P11Cipher";511String P11RSACipher = "sun.security.pkcs11.P11RSACipher";512String P11AEADCipher = "sun.security.pkcs11.P11AEADCipher";513String P11Signature = "sun.security.pkcs11.P11Signature";514String P11PSSSignature = "sun.security.pkcs11.P11PSSSignature";515516// XXX register all aliases517518d(MD, "MD2", P11Digest,519m(CKM_MD2));520d(MD, "MD5", P11Digest,521m(CKM_MD5));522d(MD, "SHA1", P11Digest,523s("SHA", "SHA-1", "1.3.14.3.2.26", "OID.1.3.14.3.2.26"),524m(CKM_SHA_1));525526d(MD, "SHA-224", P11Digest,527s("2.16.840.1.101.3.4.2.4", "OID.2.16.840.1.101.3.4.2.4"),528m(CKM_SHA224));529d(MD, "SHA-256", P11Digest,530s("2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1"),531m(CKM_SHA256));532d(MD, "SHA-384", P11Digest,533s("2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2"),534m(CKM_SHA384));535d(MD, "SHA-512", P11Digest,536s("2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3"),537m(CKM_SHA512));538d(MD, "SHA-512/224", P11Digest,539s("2.16.840.1.101.3.4.2.5", "OID.2.16.840.1.101.3.4.2.5"),540m(CKM_SHA512_224));541d(MD, "SHA-512/256", P11Digest,542s("2.16.840.1.101.3.4.2.6", "OID.2.16.840.1.101.3.4.2.6"),543m(CKM_SHA512_256));544545d(MAC, "HmacMD5", P11MAC,546m(CKM_MD5_HMAC));547d(MAC, "HmacSHA1", P11MAC,548s("1.2.840.113549.2.7", "OID.1.2.840.113549.2.7"),549m(CKM_SHA_1_HMAC));550d(MAC, "HmacSHA224", P11MAC,551s("1.2.840.113549.2.8", "OID.1.2.840.113549.2.8"),552m(CKM_SHA224_HMAC));553d(MAC, "HmacSHA256", P11MAC,554s("1.2.840.113549.2.9", "OID.1.2.840.113549.2.9"),555m(CKM_SHA256_HMAC));556d(MAC, "HmacSHA384", P11MAC,557s("1.2.840.113549.2.10", "OID.1.2.840.113549.2.10"),558m(CKM_SHA384_HMAC));559d(MAC, "HmacSHA512", P11MAC,560s("1.2.840.113549.2.11", "OID.1.2.840.113549.2.11"),561m(CKM_SHA512_HMAC));562d(MAC, "HmacSHA512/224", P11MAC,563s("1.2.840.113549.2.12", "OID.1.2.840.113549.2.12"),564m(CKM_SHA512_224_HMAC));565d(MAC, "HmacSHA512/256", P11MAC,566s("1.2.840.113549.2.13", "OID.1.2.840.113549.2.13"),567m(CKM_SHA512_256_HMAC));568569d(MAC, "SslMacMD5", P11MAC,570m(CKM_SSL3_MD5_MAC));571d(MAC, "SslMacSHA1", P11MAC,572m(CKM_SSL3_SHA1_MAC));573574d(KPG, "RSA", P11KeyPairGenerator,575s("1.2.840.113549.1.1", "OID.1.2.840.113549.1.1"),576m(CKM_RSA_PKCS_KEY_PAIR_GEN));577578d(KPG, "DSA", P11KeyPairGenerator,579s("1.3.14.3.2.12", "1.2.840.10040.4.1", "OID.1.2.840.10040.4.1"),580m(CKM_DSA_KEY_PAIR_GEN));581d(KPG, "DH", P11KeyPairGenerator, s("DiffieHellman"),582m(CKM_DH_PKCS_KEY_PAIR_GEN));583d(KPG, "EC", P11KeyPairGenerator,584m(CKM_EC_KEY_PAIR_GEN));585586d(KG, "ARCFOUR", P11KeyGenerator, s("RC4"),587m(CKM_RC4_KEY_GEN));588d(KG, "DES", P11KeyGenerator,589m(CKM_DES_KEY_GEN));590d(KG, "DESede", P11KeyGenerator,591m(CKM_DES3_KEY_GEN, CKM_DES2_KEY_GEN));592d(KG, "AES", P11KeyGenerator,593m(CKM_AES_KEY_GEN));594d(KG, "Blowfish", P11KeyGenerator,595m(CKM_BLOWFISH_KEY_GEN));596597// register (Secret)KeyFactories if there are any mechanisms598// for a particular algorithm that we support599d(KF, "RSA", P11RSAKeyFactory,600s("1.2.840.113549.1.1", "OID.1.2.840.113549.1.1"),601m(CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_RSA_PKCS, CKM_RSA_X_509));602d(KF, "DSA", P11DSAKeyFactory,603s("1.3.14.3.2.12", "1.2.840.10040.4.1", "OID.1.2.840.10040.4.1"),604m(CKM_DSA_KEY_PAIR_GEN, CKM_DSA, CKM_DSA_SHA1));605d(KF, "DH", P11DHKeyFactory, s("DiffieHellman"),606m(CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE));607d(KF, "EC", P11DHKeyFactory,608m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,609CKM_ECDSA, CKM_ECDSA_SHA1));610611// AlgorithmParameters for EC.612// Only needed until we have an EC implementation in the SUN provider.613d(AGP, "EC", "sun.security.util.ECParameters",614s("1.2.840.10045.2.1"),615m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,616CKM_ECDSA, CKM_ECDSA_SHA1));617618d(AGP, "GCM", "sun.security.util.GCMParameters",619m(CKM_AES_GCM));620621d(KA, "DH", P11KeyAgreement, s("DiffieHellman"),622m(CKM_DH_PKCS_DERIVE));623d(KA, "ECDH", "sun.security.pkcs11.P11ECDHKeyAgreement",624m(CKM_ECDH1_DERIVE));625626d(SKF, "ARCFOUR", P11SecretKeyFactory, s("RC4"),627m(CKM_RC4));628d(SKF, "DES", P11SecretKeyFactory,629m(CKM_DES_CBC));630d(SKF, "DESede", P11SecretKeyFactory,631m(CKM_DES3_CBC));632d(SKF, "AES", P11SecretKeyFactory,633s("2.16.840.1.101.3.4.1", "OID.2.16.840.1.101.3.4.1"),634m(CKM_AES_CBC));635d(SKF, "Blowfish", P11SecretKeyFactory,636m(CKM_BLOWFISH_CBC));637638// XXX attributes for Ciphers (supported modes, padding)639d(CIP, "ARCFOUR", P11Cipher, s("RC4"),640m(CKM_RC4));641d(CIP, "DES/CBC/NoPadding", P11Cipher,642m(CKM_DES_CBC));643d(CIP, "DES/CBC/PKCS5Padding", P11Cipher,644m(CKM_DES_CBC_PAD, CKM_DES_CBC));645d(CIP, "DES/ECB/NoPadding", P11Cipher,646m(CKM_DES_ECB));647d(CIP, "DES/ECB/PKCS5Padding", P11Cipher, s("DES"),648m(CKM_DES_ECB));649650d(CIP, "DESede/CBC/NoPadding", P11Cipher,651m(CKM_DES3_CBC));652d(CIP, "DESede/CBC/PKCS5Padding", P11Cipher,653m(CKM_DES3_CBC_PAD, CKM_DES3_CBC));654d(CIP, "DESede/ECB/NoPadding", P11Cipher,655m(CKM_DES3_ECB));656d(CIP, "DESede/ECB/PKCS5Padding", P11Cipher, s("DESede"),657m(CKM_DES3_ECB));658d(CIP, "AES/CBC/NoPadding", P11Cipher,659m(CKM_AES_CBC));660d(CIP, "AES_128/CBC/NoPadding", P11Cipher,661s("2.16.840.1.101.3.4.1.2", "OID.2.16.840.1.101.3.4.1.2"),662m(CKM_AES_CBC));663d(CIP, "AES_192/CBC/NoPadding", P11Cipher,664s("2.16.840.1.101.3.4.1.22", "OID.2.16.840.1.101.3.4.1.22"),665m(CKM_AES_CBC));666d(CIP, "AES_256/CBC/NoPadding", P11Cipher,667s("2.16.840.1.101.3.4.1.42", "OID.2.16.840.1.101.3.4.1.42"),668m(CKM_AES_CBC));669d(CIP, "AES/CBC/PKCS5Padding", P11Cipher,670m(CKM_AES_CBC_PAD, CKM_AES_CBC));671d(CIP, "AES/ECB/NoPadding", P11Cipher,672m(CKM_AES_ECB));673d(CIP, "AES_128/ECB/NoPadding", P11Cipher,674s("2.16.840.1.101.3.4.1.1", "OID.2.16.840.1.101.3.4.1.1"),675m(CKM_AES_ECB));676d(CIP, "AES_192/ECB/NoPadding", P11Cipher,677s("2.16.840.1.101.3.4.1.21", "OID.2.16.840.1.101.3.4.1.21"),678m(CKM_AES_ECB));679d(CIP, "AES_256/ECB/NoPadding", P11Cipher,680s("2.16.840.1.101.3.4.1.41", "OID.2.16.840.1.101.3.4.1.41"),681m(CKM_AES_ECB));682d(CIP, "AES/ECB/PKCS5Padding", P11Cipher, s("AES"),683m(CKM_AES_ECB));684d(CIP, "AES/CTR/NoPadding", P11Cipher,685m(CKM_AES_CTR));686687d(CIP, "AES/GCM/NoPadding", P11AEADCipher,688m(CKM_AES_GCM));689d(CIP, "AES_128/GCM/NoPadding", P11AEADCipher,690s("2.16.840.1.101.3.4.1.6", "OID.2.16.840.1.101.3.4.1.6"),691m(CKM_AES_GCM));692d(CIP, "AES_192/GCM/NoPadding", P11AEADCipher,693s("2.16.840.1.101.3.4.1.26", "OID.2.16.840.1.101.3.4.1.26"),694m(CKM_AES_GCM));695d(CIP, "AES_256/GCM/NoPadding", P11AEADCipher,696s("2.16.840.1.101.3.4.1.46", "OID.2.16.840.1.101.3.4.1.46"),697m(CKM_AES_GCM));698699d(CIP, "Blowfish/CBC/NoPadding", P11Cipher,700m(CKM_BLOWFISH_CBC));701d(CIP, "Blowfish/CBC/PKCS5Padding", P11Cipher,702m(CKM_BLOWFISH_CBC));703704d(CIP, "RSA/ECB/PKCS1Padding", P11RSACipher, s("RSA"),705m(CKM_RSA_PKCS));706d(CIP, "RSA/ECB/NoPadding", P11RSACipher,707m(CKM_RSA_X_509));708709d(SIG, "RawDSA", P11Signature, s("NONEwithDSA"),710m(CKM_DSA));711d(SIG, "DSA", P11Signature,712s("SHA1withDSA", "1.3.14.3.2.13", "1.3.14.3.2.27",713"1.2.840.10040.4.3", "OID.1.2.840.10040.4.3"),714m(CKM_DSA_SHA1, CKM_DSA));715d(SIG, "SHA224withDSA", P11Signature,716s("2.16.840.1.101.3.4.3.1", "OID.2.16.840.1.101.3.4.3.1"),717m(CKM_DSA_SHA224));718d(SIG, "SHA256withDSA", P11Signature,719s("2.16.840.1.101.3.4.3.2", "OID.2.16.840.1.101.3.4.3.2"),720m(CKM_DSA_SHA256));721d(SIG, "SHA384withDSA", P11Signature,722s("2.16.840.1.101.3.4.3.3", "OID.2.16.840.1.101.3.4.3.3"),723m(CKM_DSA_SHA384));724d(SIG, "SHA512withDSA", P11Signature,725s("2.16.840.1.101.3.4.3.4", "OID.2.16.840.1.101.3.4.3.4"),726m(CKM_DSA_SHA512));727728d(SIG, "NONEwithECDSA", P11Signature,729m(CKM_ECDSA));730d(SIG, "SHA1withECDSA", P11Signature,731s("ECDSA", "1.2.840.10045.4.1", "OID.1.2.840.10045.4.1"),732m(CKM_ECDSA_SHA1, CKM_ECDSA));733d(SIG, "SHA224withECDSA", P11Signature,734s("1.2.840.10045.4.3.1", "OID.1.2.840.10045.4.3.1"),735m(CKM_ECDSA));736d(SIG, "SHA256withECDSA", P11Signature,737s("1.2.840.10045.4.3.2", "OID.1.2.840.10045.4.3.2"),738m(CKM_ECDSA));739d(SIG, "SHA384withECDSA", P11Signature,740s("1.2.840.10045.4.3.3", "OID.1.2.840.10045.4.3.3"),741m(CKM_ECDSA));742d(SIG, "SHA512withECDSA", P11Signature,743s("1.2.840.10045.4.3.4", "OID.1.2.840.10045.4.3.4"),744m(CKM_ECDSA));745d(SIG, "MD2withRSA", P11Signature,746s("1.2.840.113549.1.1.2", "OID.1.2.840.113549.1.1.2"),747m(CKM_MD2_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));748d(SIG, "MD5withRSA", P11Signature,749s("1.2.840.113549.1.1.4", "OID.1.2.840.113549.1.1.4"),750m(CKM_MD5_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));751d(SIG, "SHA1withRSA", P11Signature,752s("1.2.840.113549.1.1.5", "OID.1.2.840.113549.1.1.5",753"1.3.14.3.2.29"),754m(CKM_SHA1_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));755d(SIG, "SHA224withRSA", P11Signature,756s("1.2.840.113549.1.1.14", "OID.1.2.840.113549.1.1.14"),757m(CKM_SHA224_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));758d(SIG, "SHA256withRSA", P11Signature,759s("1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11"),760m(CKM_SHA256_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));761d(SIG, "SHA384withRSA", P11Signature,762s("1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12"),763m(CKM_SHA384_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));764d(SIG, "SHA512withRSA", P11Signature,765s("1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13"),766m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));767d(SIG, "RSASSA-PSS", P11PSSSignature,768s("1.2.840.113549.1.1.10", "OID.1.2.840.113549.1.1.10"),769m(CKM_RSA_PKCS_PSS));770d(SIG, "SHA1withRSASSA-PSS", P11PSSSignature,771m(CKM_SHA1_RSA_PKCS_PSS));772d(SIG, "SHA224withRSASSA-PSS", P11PSSSignature,773m(CKM_SHA224_RSA_PKCS_PSS));774d(SIG, "SHA256withRSASSA-PSS", P11PSSSignature,775m(CKM_SHA256_RSA_PKCS_PSS));776d(SIG, "SHA384withRSASSA-PSS", P11PSSSignature,777m(CKM_SHA384_RSA_PKCS_PSS));778d(SIG, "SHA512withRSASSA-PSS", P11PSSSignature,779m(CKM_SHA512_RSA_PKCS_PSS));780781d(KG, "SunTlsRsaPremasterSecret",782"sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",783s("SunTls12RsaPremasterSecret"),784m(CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_PRE_MASTER_KEY_GEN));785d(KG, "SunTlsMasterSecret",786"sun.security.pkcs11.P11TlsMasterSecretGenerator",787m(CKM_SSL3_MASTER_KEY_DERIVE, CKM_TLS_MASTER_KEY_DERIVE,788CKM_SSL3_MASTER_KEY_DERIVE_DH,789CKM_TLS_MASTER_KEY_DERIVE_DH));790d(KG, "SunTls12MasterSecret",791"sun.security.pkcs11.P11TlsMasterSecretGenerator",792m(CKM_TLS12_MASTER_KEY_DERIVE, CKM_TLS12_MASTER_KEY_DERIVE_DH));793d(KG, "SunTlsKeyMaterial",794"sun.security.pkcs11.P11TlsKeyMaterialGenerator",795m(CKM_SSL3_KEY_AND_MAC_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE));796d(KG, "SunTls12KeyMaterial",797"sun.security.pkcs11.P11TlsKeyMaterialGenerator",798m(CKM_TLS12_KEY_AND_MAC_DERIVE));799d(KG, "SunTlsPrf", "sun.security.pkcs11.P11TlsPrfGenerator",800m(CKM_TLS_PRF, CKM_NSS_TLS_PRF_GENERAL));801d(KG, "SunTls12Prf", "sun.security.pkcs11.P11TlsPrfGenerator",802m(CKM_TLS_MAC));803}804805// background thread that periodically checks for token insertion806// if no token is present. We need to do that in a separate thread because807// the insertion check may block for quite a long time on some tokens.808private static class TokenPoller implements Runnable {809private final SunPKCS11 provider;810private volatile boolean enabled;811private TokenPoller(SunPKCS11 provider) {812this.provider = provider;813enabled = true;814}815public void run() {816int interval = provider.config.getInsertionCheckInterval();817while (enabled) {818try {819Thread.sleep(interval);820} catch (InterruptedException e) {821break;822}823if (enabled == false) {824break;825}826try {827provider.initToken(null);828} catch (PKCS11Exception e) {829// ignore830}831}832}833void disable() {834enabled = false;835}836}837838// create the poller thread, if not already active839private void createPoller() {840if (poller != null) {841return;842}843TokenPoller poller = new TokenPoller(this);844Thread t = new Thread(poller, "Poller " + getName());845t.setDaemon(true);846t.setPriority(Thread.MIN_PRIORITY);847t.start();848this.poller = poller;849}850851// destroy the poller thread, if active852private void destroyPoller() {853if (poller != null) {854poller.disable();855poller = null;856}857}858859private boolean hasValidToken() {860/* Commented out to work with Solaris softtoken impl which861returns 0-value flags, e.g. both REMOVABLE_DEVICE and862TOKEN_PRESENT are false, when it can't access the token.863if (removable == false) {864return true;865}866*/867Token token = this.token;868return (token != null) && token.isValid();869}870871// destroy the token. Called if we detect that it has been removed872synchronized void uninitToken(Token token) {873if (this.token != token) {874// mismatch, our token must already be destroyed875return;876}877destroyPoller();878this.token = null;879// unregister all algorithms880AccessController.doPrivileged(new PrivilegedAction<Object>() {881public Object run() {882clear();883return null;884}885});886createPoller();887}888889// test if a token is present and initialize this provider for it if so.890// does nothing if no token is found891// called from constructor and by poller892private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {893if (slotInfo == null) {894slotInfo = p11.C_GetSlotInfo(slotID);895}896if (removable && (slotInfo.flags & CKF_TOKEN_PRESENT) == 0) {897createPoller();898return;899}900destroyPoller();901boolean showInfo = config.getShowInfo();902if (showInfo) {903System.out.println("Slot info for slot " + slotID + ":");904System.out.println(slotInfo);905}906final Token token = new Token(this);907if (showInfo) {908System.out.println909("Token info for token in slot " + slotID + ":");910System.out.println(token.tokenInfo);911}912long[] supportedMechanisms = p11.C_GetMechanismList(slotID);913914// Create a map from the various Descriptors to the "most915// preferred" mechanism that was defined during the916// static initialization. For example, DES/CBC/PKCS5Padding917// could be mapped to CKM_DES_CBC_PAD or CKM_DES_CBC. Prefer918// the earliest entry. When asked for "DES/CBC/PKCS5Padding", we919// return a CKM_DES_CBC_PAD.920final Map<Descriptor,Integer> supportedAlgs =921new HashMap<Descriptor,Integer>();922for (int i = 0; i < supportedMechanisms.length; i++) {923long longMech = supportedMechanisms[i];924boolean isEnabled = config.isEnabled(longMech);925if (showInfo) {926CK_MECHANISM_INFO mechInfo =927p11.C_GetMechanismInfo(slotID, longMech);928System.out.println("Mechanism " +929Functions.getMechanismName(longMech) + ":");930if (isEnabled == false) {931System.out.println("DISABLED in configuration");932}933System.out.println(mechInfo);934}935if (isEnabled == false) {936continue;937}938// we do not know of mechs with the upper 32 bits set939if (longMech >>> 32 != 0) {940continue;941}942int mech = (int)longMech;943Integer integerMech = Integer.valueOf(mech);944List<Descriptor> ds = descriptors.get(integerMech);945if (ds == null) {946continue;947}948for (Descriptor d : ds) {949Integer oldMech = supportedAlgs.get(d);950if (oldMech == null) {951supportedAlgs.put(d, integerMech);952continue;953}954// See if there is something "more preferred"955// than what we currently have in the supportedAlgs956// map.957int intOldMech = oldMech.intValue();958for (int j = 0; j < d.mechanisms.length; j++) {959int nextMech = d.mechanisms[j];960if (mech == nextMech) {961supportedAlgs.put(d, integerMech);962break;963} else if (intOldMech == nextMech) {964break;965}966}967}968969}970971// register algorithms in provider972AccessController.doPrivileged(new PrivilegedAction<Object>() {973public Object run() {974for (Map.Entry<Descriptor,Integer> entry975: supportedAlgs.entrySet()) {976Descriptor d = entry.getKey();977int mechanism = entry.getValue().intValue();978Service s = d.service(token, mechanism);979putService(s);980}981if (((token.tokenInfo.flags & CKF_RNG) != 0)982&& config.isEnabled(PCKM_SECURERANDOM)983&& !token.sessionManager.lowMaxSessions()) {984// do not register SecureRandom if the token does985// not support many sessions. if we did, we might986// run out of sessions in the middle of a987// nextBytes() call where we cannot fail over.988putService(new P11Service(token, SR, "PKCS11",989"sun.security.pkcs11.P11SecureRandom", null,990PCKM_SECURERANDOM));991}992if (config.isEnabled(PCKM_KEYSTORE)) {993putService(new P11Service(token, KS, "PKCS11",994"sun.security.pkcs11.P11KeyStore",995s("PKCS11-" + config.getName()),996PCKM_KEYSTORE));997}998return null;999}1000});10011002this.token = token;1003}10041005private static final class P11Service extends Service {10061007private final Token token;10081009private final long mechanism;10101011P11Service(Token token, String type, String algorithm,1012String className, String[] al, long mechanism) {1013super(token.provider, type, algorithm, className, toList(al), null);1014this.token = token;1015this.mechanism = mechanism & 0xFFFFFFFFL;1016}10171018private static List<String> toList(String[] aliases) {1019return (aliases == null) ? null : Arrays.asList(aliases);1020}10211022public Object newInstance(Object param)1023throws NoSuchAlgorithmException {1024if (token.isValid() == false) {1025throw new NoSuchAlgorithmException("Token has been removed");1026}1027try {1028return newInstance0(param);1029} catch (PKCS11Exception e) {1030throw new NoSuchAlgorithmException(e);1031}1032}10331034public Object newInstance0(Object param) throws1035PKCS11Exception, NoSuchAlgorithmException {1036String algorithm = getAlgorithm();1037String type = getType();1038if (type == MD) {1039return new P11Digest(token, algorithm, mechanism);1040} else if (type == CIP) {1041if (algorithm.startsWith("RSA")) {1042return new P11RSACipher(token, algorithm, mechanism);1043} else if (algorithm.endsWith("GCM/NoPadding")) {1044return new P11AEADCipher(token, algorithm, mechanism);1045} else {1046return new P11Cipher(token, algorithm, mechanism);1047}1048} else if (type == SIG) {1049if (algorithm.indexOf("RSASSA-PSS") != -1) {1050return new P11PSSSignature(token, algorithm, mechanism);1051} else {1052return new P11Signature(token, algorithm, mechanism);1053}1054} else if (type == MAC) {1055return new P11Mac(token, algorithm, mechanism);1056} else if (type == KPG) {1057return new P11KeyPairGenerator(token, algorithm, mechanism);1058} else if (type == KA) {1059if (algorithm.equals("ECDH")) {1060return new P11ECDHKeyAgreement(token, algorithm, mechanism);1061} else {1062return new P11KeyAgreement(token, algorithm, mechanism);1063}1064} else if (type == KF) {1065return token.getKeyFactory(algorithm);1066} else if (type == SKF) {1067return new P11SecretKeyFactory(token, algorithm);1068} else if (type == KG) {1069// reference equality1070if (algorithm == "SunTlsRsaPremasterSecret") {1071return new P11TlsRsaPremasterSecretGenerator(1072token, algorithm, mechanism);1073} else if (algorithm == "SunTlsMasterSecret"1074|| algorithm == "SunTls12MasterSecret") {1075return new P11TlsMasterSecretGenerator(1076token, algorithm, mechanism);1077} else if (algorithm == "SunTlsKeyMaterial"1078|| algorithm == "SunTls12KeyMaterial") {1079return new P11TlsKeyMaterialGenerator(1080token, algorithm, mechanism);1081} else if (algorithm == "SunTlsPrf"1082|| algorithm == "SunTls12Prf") {1083return new P11TlsPrfGenerator(token, algorithm, mechanism);1084} else {1085return new P11KeyGenerator(token, algorithm, mechanism);1086}1087} else if (type == SR) {1088return token.getRandom();1089} else if (type == KS) {1090return token.getKeyStore();1091} else if (type == AGP) {1092if (algorithm == "EC") {1093return new sun.security.util.ECParameters();1094} else if (algorithm == "GCM") {1095return new sun.security.util.GCMParameters();1096} else {1097throw new NoSuchAlgorithmException("Unsupported algorithm: "1098+ algorithm);1099}1100} else {1101throw new NoSuchAlgorithmException("Unknown type: " + type);1102}1103}11041105public boolean supportsParameter(Object param) {1106if ((param == null) || (token.isValid() == false)) {1107return false;1108}1109if (param instanceof Key == false) {1110throw new InvalidParameterException("Parameter must be a Key");1111}1112String algorithm = getAlgorithm();1113String type = getType();1114Key key = (Key)param;1115String keyAlgorithm = key.getAlgorithm();1116// RSA signatures and cipher1117if (((type == CIP) && algorithm.startsWith("RSA"))1118|| (type == SIG) && (algorithm.indexOf("RSA") != -1)) {1119if (keyAlgorithm.equals("RSA") == false) {1120return false;1121}1122return isLocalKey(key)1123|| (key instanceof RSAPrivateKey)1124|| (key instanceof RSAPublicKey);1125}1126// EC1127if (((type == KA) && algorithm.equals("ECDH"))1128|| ((type == SIG) && algorithm.endsWith("ECDSA"))) {1129if (keyAlgorithm.equals("EC") == false) {1130return false;1131}1132return isLocalKey(key)1133|| (key instanceof ECPrivateKey)1134|| (key instanceof ECPublicKey);1135}1136// DSA signatures1137if ((type == SIG) && algorithm.endsWith("DSA")) {1138if (keyAlgorithm.equals("DSA") == false) {1139return false;1140}1141return isLocalKey(key)1142|| (key instanceof DSAPrivateKey)1143|| (key instanceof DSAPublicKey);1144}1145// MACs and symmetric ciphers1146if ((type == CIP) || (type == MAC)) {1147// do not check algorithm name, mismatch is unlikely anyway1148return isLocalKey(key) || "RAW".equals(key.getFormat());1149}1150// DH key agreement1151if (type == KA) {1152if (keyAlgorithm.equals("DH") == false) {1153return false;1154}1155return isLocalKey(key)1156|| (key instanceof DHPrivateKey)1157|| (key instanceof DHPublicKey);1158}1159// should not reach here,1160// unknown engine type or algorithm1161throw new AssertionError1162("SunPKCS11 error: " + type + ", " + algorithm);1163}11641165private boolean isLocalKey(Key key) {1166return (key instanceof P11Key) && (((P11Key)key).token == token);1167}11681169public String toString() {1170return super.toString() +1171" (" + Functions.getMechanismName(mechanism) + ")";1172}11731174}11751176/**1177* Log in to this provider.1178*1179* <p> If the token expects a PIN to be supplied by the caller,1180* the <code>handler</code> implementation must support1181* a <code>PasswordCallback</code>.1182*1183* <p> To determine if the token supports a protected authentication path,1184* the CK_TOKEN_INFO flag, CKF_PROTECTED_AUTHENTICATION_PATH, is consulted.1185*1186* @param subject this parameter is ignored1187* @param handler the <code>CallbackHandler</code> used by1188* this provider to communicate with the caller1189*1190* @exception LoginException if the login operation fails1191* @exception SecurityException if the does not pass a security check for1192* <code>SecurityPermission("authProvider.<i>name</i>")</code>,1193* where <i>name</i> is the value returned by1194* this provider's <code>getName</code> method1195*/1196public void login(Subject subject, CallbackHandler handler)1197throws LoginException {11981199// security check12001201SecurityManager sm = System.getSecurityManager();1202if (sm != null) {1203if (debug != null) {1204debug.println("checking login permission");1205}1206sm.checkPermission(new SecurityPermission1207("authProvider." + this.getName()));1208}12091210if (hasValidToken() == false) {1211throw new LoginException("No token present");1212}12131214// see if a login is required12151216if ((token.tokenInfo.flags & CKF_LOGIN_REQUIRED) == 0) {1217if (debug != null) {1218debug.println("login operation not required for token - " +1219"ignoring login request");1220}1221return;1222}12231224// see if user already logged in12251226try {1227if (token.isLoggedInNow(null)) {1228// user already logged in1229if (debug != null) {1230debug.println("user already logged in");1231}1232return;1233}1234} catch (PKCS11Exception e) {1235// ignore - fall thru and attempt login1236}12371238// get the pin if necessary12391240char[] pin = null;1241if ((token.tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) {12421243// get password12441245CallbackHandler myHandler = getCallbackHandler(handler);1246if (myHandler == null) {1247// XXX PolicyTool is dependent on this message text1248throw new LoginException1249("no password provided, and no callback handler " +1250"available for retrieving password");1251}12521253java.text.MessageFormat form = new java.text.MessageFormat1254(ResourcesMgr.getString1255("PKCS11.Token.providerName.Password."));1256Object[] source = { getName() };12571258PasswordCallback pcall = new PasswordCallback(form.format(source),1259false);1260Callback[] callbacks = { pcall };1261try {1262myHandler.handle(callbacks);1263} catch (Exception e) {1264LoginException le = new LoginException1265("Unable to perform password callback");1266le.initCause(e);1267throw le;1268}12691270pin = pcall.getPassword();1271pcall.clearPassword();1272if (pin == null) {1273if (debug != null) {1274debug.println("caller passed NULL pin");1275}1276}1277}12781279// perform token login12801281Session session = null;1282try {1283session = token.getOpSession();12841285// pin is NULL if using CKF_PROTECTED_AUTHENTICATION_PATH1286p11.C_Login(session.id(), CKU_USER, pin);1287if (debug != null) {1288debug.println("login succeeded");1289}1290} catch (PKCS11Exception pe) {1291if (pe.getErrorCode() == CKR_USER_ALREADY_LOGGED_IN) {1292// let this one go1293if (debug != null) {1294debug.println("user already logged in");1295}1296return;1297} else if (pe.getErrorCode() == CKR_PIN_INCORRECT) {1298FailedLoginException fle = new FailedLoginException();1299fle.initCause(pe);1300throw fle;1301} else {1302LoginException le = new LoginException();1303le.initCause(pe);1304throw le;1305}1306} finally {1307token.releaseSession(session);1308if (pin != null) {1309Arrays.fill(pin, ' ');1310}1311}13121313// we do not store the PIN in the subject for now1314}13151316/**1317* Log out from this provider1318*1319* @exception LoginException if the logout operation fails1320* @exception SecurityException if the does not pass a security check for1321* <code>SecurityPermission("authProvider.<i>name</i>")</code>,1322* where <i>name</i> is the value returned by1323* this provider's <code>getName</code> method1324*/1325public void logout() throws LoginException {13261327// security check13281329SecurityManager sm = System.getSecurityManager();1330if (sm != null) {1331sm.checkPermission1332(new SecurityPermission("authProvider." + this.getName()));1333}13341335if (hasValidToken() == false) {1336// app may call logout for cleanup, allow1337return;1338}13391340if ((token.tokenInfo.flags & CKF_LOGIN_REQUIRED) == 0) {1341if (debug != null) {1342debug.println("logout operation not required for token - " +1343"ignoring logout request");1344}1345return;1346}13471348try {1349if (token.isLoggedInNow(null) == false) {1350if (debug != null) {1351debug.println("user not logged in");1352}1353return;1354}1355} catch (PKCS11Exception e) {1356// ignore1357}13581359// perform token logout13601361Session session = null;1362try {1363session = token.getOpSession();1364p11.C_Logout(session.id());1365if (debug != null) {1366debug.println("logout succeeded");1367}1368} catch (PKCS11Exception pe) {1369if (pe.getErrorCode() == CKR_USER_NOT_LOGGED_IN) {1370// let this one go1371if (debug != null) {1372debug.println("user not logged in");1373}1374return;1375}1376LoginException le = new LoginException();1377le.initCause(pe);1378throw le;1379} finally {1380token.releaseSession(session);1381}1382}13831384/**1385* Set a <code>CallbackHandler</code>1386*1387* <p> The provider uses this handler if one is not passed to the1388* <code>login</code> method. The provider also uses this handler1389* if it invokes <code>login</code> on behalf of callers.1390* In either case if a handler is not set via this method,1391* the provider queries the1392* <i>auth.login.defaultCallbackHandler</i> security property1393* for the fully qualified class name of a default handler implementation.1394* If the security property is not set,1395* the provider is assumed to have alternative means1396* for obtaining authentication information.1397*1398* @param handler a <code>CallbackHandler</code> for obtaining1399* authentication information, which may be <code>null</code>1400*1401* @exception SecurityException if the caller does not pass a1402* security check for1403* <code>SecurityPermission("authProvider.<i>name</i>")</code>,1404* where <i>name</i> is the value returned by1405* this provider's <code>getName</code> method1406*/1407public void setCallbackHandler(CallbackHandler handler) {14081409// security check14101411SecurityManager sm = System.getSecurityManager();1412if (sm != null) {1413sm.checkPermission1414(new SecurityPermission("authProvider." + this.getName()));1415}14161417synchronized (LOCK_HANDLER) {1418pHandler = handler;1419}1420}14211422private CallbackHandler getCallbackHandler(CallbackHandler handler) {14231424// get default handler if necessary14251426if (handler != null) {1427return handler;1428}14291430if (debug != null) {1431debug.println("getting provider callback handler");1432}14331434synchronized (LOCK_HANDLER) {1435// see if handler was set via setCallbackHandler1436if (pHandler != null) {1437return pHandler;1438}14391440try {1441if (debug != null) {1442debug.println("getting default callback handler");1443}14441445CallbackHandler myHandler = AccessController.doPrivileged1446(new PrivilegedExceptionAction<CallbackHandler>() {1447public CallbackHandler run() throws Exception {14481449String defaultHandler =1450java.security.Security.getProperty1451("auth.login.defaultCallbackHandler");14521453if (defaultHandler == null ||1454defaultHandler.length() == 0) {14551456// ok1457if (debug != null) {1458debug.println("no default handler set");1459}1460return null;1461}14621463Class<?> c = Class.forName1464(defaultHandler,1465true,1466Thread.currentThread().getContextClassLoader());1467return (CallbackHandler)c.newInstance();1468}1469});14701471// save it1472pHandler = myHandler;1473return myHandler;14741475} catch (PrivilegedActionException pae) {1476// ok1477if (debug != null) {1478debug.println("Unable to load default callback handler");1479pae.printStackTrace();1480}1481}1482}1483return null;1484}14851486private Object writeReplace() throws ObjectStreamException {1487return new SunPKCS11Rep(this);1488}14891490/**1491* Serialized representation of the SunPKCS11 provider.1492*/1493private static class SunPKCS11Rep implements Serializable {14941495static final long serialVersionUID = -2896606995897745419L;14961497private final String providerName;14981499private final String configName;15001501SunPKCS11Rep(SunPKCS11 provider) throws NotSerializableException {1502providerName = provider.getName();1503configName = provider.configName;1504if (Security.getProvider(providerName) != provider) {1505throw new NotSerializableException("Only SunPKCS11 providers "1506+ "installed in java.security.Security can be serialized");1507}1508}15091510private Object readResolve() throws ObjectStreamException {1511SunPKCS11 p = (SunPKCS11)Security.getProvider(providerName);1512if ((p == null) || (p.configName.equals(configName) == false)) {1513throw new NotSerializableException("Could not find "1514+ providerName + " in installed providers");1515}1516return p;1517}1518}1519}152015211522