Path: blob/master/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
41154 views
/*1* Copyright (c) 2003, 2021, 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.PasswordCallback;4142import com.sun.crypto.provider.ChaCha20Poly1305Parameters;4344import sun.security.util.Debug;45import sun.security.util.ResourcesMgr;46import static sun.security.util.SecurityConstants.PROVIDER_VER;47import static sun.security.util.SecurityProviderConstants.getAliases;4849import sun.security.pkcs11.Secmod.*;5051import sun.security.pkcs11.wrapper.*;52import static sun.security.pkcs11.wrapper.PKCS11Constants.*;53import static sun.security.pkcs11.wrapper.PKCS11Exception.*;5455/**56* PKCS#11 provider main class.57*58* @author Andreas Sterbenz59* @since 1.560*/61public final class SunPKCS11 extends AuthProvider {6263private static final long serialVersionUID = -1354835039035306505L;6465static final Debug debug = Debug.getInstance("sunpkcs11");66// the PKCS11 object through which we make the native calls67final PKCS11 p11;6869// configuration information70final Config config;7172// id of the PKCS#11 slot we are using73final long slotID;7475private CallbackHandler pHandler;76private final Object LOCK_HANDLER = new Object();7778final boolean removable;7980final Secmod.Module nssModule;8182final boolean nssUseSecmodTrust;8384private volatile Token token;8586private TokenPoller poller;8788static NativeResourceCleaner cleaner;8990Token getToken() {91return token;92}9394public SunPKCS11() {95super("SunPKCS11", PROVIDER_VER,96"Unconfigured and unusable PKCS11 provider");97p11 = null;98config = null;99slotID = 0;100pHandler = null;101removable = false;102nssModule = null;103nssUseSecmodTrust = false;104token = null;105poller = null;106}107108@SuppressWarnings("removal")109@Override110public Provider configure(String configArg) throws InvalidParameterException {111final String newConfigName = checkNull(configArg);112try {113return AccessController.doPrivileged(new PrivilegedExceptionAction<>() {114@Override115public SunPKCS11 run() throws Exception {116return new SunPKCS11(new Config(newConfigName));117}118});119} catch (PrivilegedActionException pae) {120InvalidParameterException ipe =121new InvalidParameterException("Error configuring SunPKCS11 provider");122throw (InvalidParameterException) ipe.initCause(pae.getException());123}124}125126@Override127public boolean isConfigured() {128return (config != null);129}130131private static <T> T checkNull(T obj) {132if (obj == null) {133throw new NullPointerException();134}135return obj;136}137138// Used by Secmod139SunPKCS11(Config c) {140super("SunPKCS11-" + c.getName(), PROVIDER_VER, c.getDescription());141this.config = c;142143if (debug != null) {144System.out.println("SunPKCS11 loading " + config.getFileName());145}146147String library = config.getLibrary();148String functionList = config.getFunctionList();149long slotID = config.getSlotID();150int slotListIndex = config.getSlotListIndex();151152boolean useSecmod = config.getNssUseSecmod();153boolean nssUseSecmodTrust = config.getNssUseSecmodTrust();154Secmod.Module nssModule = null;155156//157// Initialization via Secmod. The way this works is as follows:158// SunPKCS11 is either in normal mode or in NSS Secmod mode.159// Secmod is activated by specifying one or more of the following160// options in the config file:161// nssUseSecmod, nssSecmodDirectory, nssLibrary, nssModule162//163// XXX add more explanation here164//165// If we are in Secmod mode and configured to use either the166// nssKeyStore or the nssTrustAnchors module, we automatically167// switch to using the NSS trust attributes for trusted certs168// (KeyStore).169//170171if (useSecmod) {172// note: Config ensures library/slot/slotListIndex not specified173// in secmod mode.174Secmod secmod = Secmod.getInstance();175DbMode nssDbMode = config.getNssDbMode();176try {177String nssLibraryDirectory = config.getNssLibraryDirectory();178String nssSecmodDirectory = config.getNssSecmodDirectory();179boolean nssOptimizeSpace = config.getNssOptimizeSpace();180181if (secmod.isInitialized()) {182if (nssSecmodDirectory != null) {183String s = secmod.getConfigDir();184if ((s != null) &&185(s.equals(nssSecmodDirectory) == false)) {186throw new ProviderException("Secmod directory "187+ nssSecmodDirectory188+ " invalid, NSS already initialized with "189+ s);190}191}192if (nssLibraryDirectory != null) {193String s = secmod.getLibDir();194if ((s != null) &&195(s.equals(nssLibraryDirectory) == false)) {196throw new ProviderException("NSS library directory "197+ nssLibraryDirectory198+ " invalid, NSS already initialized with "199+ s);200}201}202} else {203if (nssDbMode != DbMode.NO_DB) {204if (nssSecmodDirectory == null) {205throw new ProviderException(206"Secmod not initialized and "207+ "nssSecmodDirectory not specified");208}209} else {210if (nssSecmodDirectory != null) {211throw new ProviderException(212"nssSecmodDirectory must not be "213+ "specified in noDb mode");214}215}216secmod.initialize(nssDbMode, nssSecmodDirectory,217nssLibraryDirectory, nssOptimizeSpace);218}219} catch (IOException e) {220// XXX which exception to throw221throw new ProviderException("Could not initialize NSS", e);222}223List<Secmod.Module> modules = secmod.getModules();224if (config.getShowInfo()) {225System.out.println("NSS modules: " + modules);226}227228String moduleName = config.getNssModule();229if (moduleName == null) {230nssModule = secmod.getModule(ModuleType.FIPS);231if (nssModule != null) {232moduleName = "fips";233} else {234moduleName = (nssDbMode == DbMode.NO_DB) ?235"crypto" : "keystore";236}237}238if (moduleName.equals("fips")) {239nssModule = secmod.getModule(ModuleType.FIPS);240nssUseSecmodTrust = true;241functionList = "FC_GetFunctionList";242} else if (moduleName.equals("keystore")) {243nssModule = secmod.getModule(ModuleType.KEYSTORE);244nssUseSecmodTrust = true;245} else if (moduleName.equals("crypto")) {246nssModule = secmod.getModule(ModuleType.CRYPTO);247} else if (moduleName.equals("trustanchors")) {248// XXX should the option be called trustanchor or trustanchors??249nssModule = secmod.getModule(ModuleType.TRUSTANCHOR);250nssUseSecmodTrust = true;251} else if (moduleName.startsWith("external-")) {252int moduleIndex;253try {254moduleIndex = Integer.parseInt255(moduleName.substring("external-".length()));256} catch (NumberFormatException e) {257moduleIndex = -1;258}259if (moduleIndex < 1) {260throw new ProviderException261("Invalid external module: " + moduleName);262}263int k = 0;264for (Secmod.Module module : modules) {265if (module.getType() == ModuleType.EXTERNAL) {266if (++k == moduleIndex) {267nssModule = module;268break;269}270}271}272if (nssModule == null) {273throw new ProviderException("Invalid module " + moduleName274+ ": only " + k + " external NSS modules available");275}276} else {277throw new ProviderException(278"Unknown NSS module: " + moduleName);279}280if (nssModule == null) {281throw new ProviderException(282"NSS module not available: " + moduleName);283}284if (nssModule.hasInitializedProvider()) {285throw new ProviderException("Secmod module already configured");286}287library = nssModule.libraryName;288slotListIndex = nssModule.slot;289}290this.nssUseSecmodTrust = nssUseSecmodTrust;291this.nssModule = nssModule;292293File libraryFile = new File(library);294// if the filename is a simple filename without path295// (e.g. "libpkcs11.so"), it may refer to a library somewhere on the296// OS library search path. Omit the test for file existance as that297// only looks in the current directory.298if (libraryFile.getName().equals(library) == false) {299if (new File(library).isFile() == false) {300String msg = "Library " + library + " does not exist";301if (config.getHandleStartupErrors() == Config.ERR_HALT) {302throw new ProviderException(msg);303} else {304throw new UnsupportedOperationException(msg);305}306}307}308309try {310if (debug != null) {311debug.println("Initializing PKCS#11 library " + library);312}313CK_C_INITIALIZE_ARGS initArgs = new CK_C_INITIALIZE_ARGS();314String nssArgs = config.getNssArgs();315if (nssArgs != null) {316initArgs.pReserved = nssArgs;317}318// request multithreaded access first319initArgs.flags = CKF_OS_LOCKING_OK;320PKCS11 tmpPKCS11;321try {322tmpPKCS11 = PKCS11.getInstance(323library, functionList, initArgs,324config.getOmitInitialize());325} catch (PKCS11Exception e) {326if (debug != null) {327debug.println("Multi-threaded initialization failed: " + e);328}329if (config.getAllowSingleThreadedModules() == false) {330throw e;331}332// fall back to single threaded access333if (nssArgs == null) {334// if possible, use null initArgs for better compatibility335initArgs = null;336} else {337initArgs.flags = 0;338}339tmpPKCS11 = PKCS11.getInstance(library,340functionList, initArgs, config.getOmitInitialize());341}342p11 = tmpPKCS11;343344CK_INFO p11Info = p11.C_GetInfo();345if (p11Info.cryptokiVersion.major < 2) {346throw new ProviderException("Only PKCS#11 v2.0 and later "347+ "supported, library version is v" + p11Info.cryptokiVersion);348}349boolean showInfo = config.getShowInfo();350if (showInfo) {351System.out.println("Information for provider " + getName());352System.out.println("Library info:");353System.out.println(p11Info);354}355356if ((slotID < 0) || showInfo) {357long[] slots = p11.C_GetSlotList(false);358if (showInfo) {359System.out.println("All slots: " + toString(slots));360slots = p11.C_GetSlotList(true);361System.out.println("Slots with tokens: " + toString(slots));362}363if (slotID < 0) {364if ((slotListIndex < 0)365|| (slotListIndex >= slots.length)) {366throw new ProviderException("slotListIndex is "367+ slotListIndex368+ " but token only has " + slots.length + " slots");369}370slotID = slots[slotListIndex];371}372}373this.slotID = slotID;374CK_SLOT_INFO slotInfo = p11.C_GetSlotInfo(slotID);375removable = (slotInfo.flags & CKF_REMOVABLE_DEVICE) != 0;376initToken(slotInfo);377if (nssModule != null) {378nssModule.setProvider(this);379}380} catch (Exception e) {381if (config.getHandleStartupErrors() == Config.ERR_IGNORE_ALL) {382throw new UnsupportedOperationException383("Initialization failed", e);384} else {385throw new ProviderException386("Initialization failed", e);387}388}389}390391private static String toString(long[] longs) {392if (longs.length == 0) {393return "(none)";394}395StringBuilder sb = new StringBuilder();396sb.append(longs[0]);397for (int i = 1; i < longs.length; i++) {398sb.append(", ");399sb.append(longs[i]);400}401return sb.toString();402}403404public boolean equals(Object obj) {405return this == obj;406}407408public int hashCode() {409return System.identityHashCode(this);410}411412private static final class Descriptor {413final String type;414final String algorithm;415final String className;416final List<String> aliases;417final int[] mechanisms;418419private Descriptor(String type, String algorithm, String className,420List<String> aliases, int[] mechanisms) {421this.type = type;422this.algorithm = algorithm;423this.className = className;424this.aliases = aliases;425this.mechanisms = mechanisms;426}427private P11Service service(Token token, int mechanism) {428return new P11Service429(token, type, algorithm, className, aliases, mechanism);430}431public String toString() {432return type + "." + algorithm;433}434}435436// Map from mechanism to List of Descriptors that should be437// registered if the mechanism is supported438private static final Map<Integer,List<Descriptor>> descriptors =439new HashMap<Integer,List<Descriptor>>();440441private static int[] m(long m1) {442return new int[] {(int)m1};443}444445private static int[] m(long m1, long m2) {446return new int[] {(int)m1, (int)m2};447}448449private static int[] m(long m1, long m2, long m3) {450return new int[] {(int)m1, (int)m2, (int)m3};451}452453private static int[] m(long m1, long m2, long m3, long m4) {454return new int[] {(int)m1, (int)m2, (int)m3, (int)m4};455}456457private static void d(String type, String algorithm, String className,458int[] m) {459register(new Descriptor(type, algorithm, className, null, m));460}461462private static void d(String type, String algorithm, String className,463List<String> aliases, int[] m) {464register(new Descriptor(type, algorithm, className, aliases, m));465}466467private static void dA(String type, String algorithm, String className,468int[] m) {469register(new Descriptor(type, algorithm, className,470getAliases(algorithm), m));471}472473private static void register(Descriptor d) {474for (int i = 0; i < d.mechanisms.length; i++) {475int m = d.mechanisms[i];476Integer key = Integer.valueOf(m);477List<Descriptor> list = descriptors.get(key);478if (list == null) {479list = new ArrayList<Descriptor>();480descriptors.put(key, list);481}482list.add(d);483}484}485486private static final String MD = "MessageDigest";487488private static final String SIG = "Signature";489490private static final String KPG = "KeyPairGenerator";491492private static final String KG = "KeyGenerator";493494private static final String AGP = "AlgorithmParameters";495496private static final String KF = "KeyFactory";497498private static final String SKF = "SecretKeyFactory";499500private static final String CIP = "Cipher";501502private static final String MAC = "Mac";503504private static final String KA = "KeyAgreement";505506private static final String KS = "KeyStore";507508private static final String SR = "SecureRandom";509510static {511// names of all the implementation classes512// use local variables, only used here513String P11Digest = "sun.security.pkcs11.P11Digest";514String P11Mac = "sun.security.pkcs11.P11Mac";515String P11KeyPairGenerator = "sun.security.pkcs11.P11KeyPairGenerator";516String P11KeyGenerator = "sun.security.pkcs11.P11KeyGenerator";517String P11RSAKeyFactory = "sun.security.pkcs11.P11RSAKeyFactory";518String P11DSAKeyFactory = "sun.security.pkcs11.P11DSAKeyFactory";519String P11DHKeyFactory = "sun.security.pkcs11.P11DHKeyFactory";520String P11ECKeyFactory = "sun.security.pkcs11.P11ECKeyFactory";521String P11KeyAgreement = "sun.security.pkcs11.P11KeyAgreement";522String P11SecretKeyFactory = "sun.security.pkcs11.P11SecretKeyFactory";523String P11Cipher = "sun.security.pkcs11.P11Cipher";524String P11RSACipher = "sun.security.pkcs11.P11RSACipher";525String P11AEADCipher = "sun.security.pkcs11.P11AEADCipher";526String P11Signature = "sun.security.pkcs11.P11Signature";527String P11PSSSignature = "sun.security.pkcs11.P11PSSSignature";528529// XXX register all aliases530531d(MD, "MD2", P11Digest,532m(CKM_MD2));533d(MD, "MD5", P11Digest,534m(CKM_MD5));535dA(MD, "SHA-1", P11Digest,536m(CKM_SHA_1));537538dA(MD, "SHA-224", P11Digest,539m(CKM_SHA224));540dA(MD, "SHA-256", P11Digest,541m(CKM_SHA256));542dA(MD, "SHA-384", P11Digest,543m(CKM_SHA384));544dA(MD, "SHA-512", P11Digest,545m(CKM_SHA512));546dA(MD, "SHA-512/224", P11Digest,547m(CKM_SHA512_224));548dA(MD, "SHA-512/256", P11Digest,549m(CKM_SHA512_256));550dA(MD, "SHA3-224", P11Digest,551m(CKM_SHA3_224));552dA(MD, "SHA3-256", P11Digest,553m(CKM_SHA3_256));554dA(MD, "SHA3-384", P11Digest,555m(CKM_SHA3_384));556dA(MD, "SHA3-512", P11Digest,557m(CKM_SHA3_512));558559d(MAC, "HmacMD5", P11Mac,560m(CKM_MD5_HMAC));561dA(MAC, "HmacSHA1", P11Mac,562m(CKM_SHA_1_HMAC));563dA(MAC, "HmacSHA224", P11Mac,564m(CKM_SHA224_HMAC));565dA(MAC, "HmacSHA256", P11Mac,566m(CKM_SHA256_HMAC));567dA(MAC, "HmacSHA384", P11Mac,568m(CKM_SHA384_HMAC));569dA(MAC, "HmacSHA512", P11Mac,570m(CKM_SHA512_HMAC));571dA(MAC, "HmacSHA512/224", P11Mac,572m(CKM_SHA512_224_HMAC));573dA(MAC, "HmacSHA512/256", P11Mac,574m(CKM_SHA512_256_HMAC));575dA(MAC, "HmacSHA3-224", P11Mac,576m(CKM_SHA3_224_HMAC));577dA(MAC, "HmacSHA3-256", P11Mac,578m(CKM_SHA3_256_HMAC));579dA(MAC, "HmacSHA3-384", P11Mac,580m(CKM_SHA3_384_HMAC));581dA(MAC, "HmacSHA3-512", P11Mac,582m(CKM_SHA3_512_HMAC));583d(MAC, "SslMacMD5", P11Mac,584m(CKM_SSL3_MD5_MAC));585d(MAC, "SslMacSHA1", P11Mac,586m(CKM_SSL3_SHA1_MAC));587588d(KPG, "RSA", P11KeyPairGenerator,589getAliases("PKCS1"),590m(CKM_RSA_PKCS_KEY_PAIR_GEN));591592List<String> dhAlias = List.of("DiffieHellman");593594dA(KPG, "DSA", P11KeyPairGenerator,595m(CKM_DSA_KEY_PAIR_GEN));596d(KPG, "DH", P11KeyPairGenerator,597dhAlias,598m(CKM_DH_PKCS_KEY_PAIR_GEN));599d(KPG, "EC", P11KeyPairGenerator,600m(CKM_EC_KEY_PAIR_GEN));601602dA(KG, "ARCFOUR", P11KeyGenerator,603m(CKM_RC4_KEY_GEN));604d(KG, "DES", P11KeyGenerator,605m(CKM_DES_KEY_GEN));606d(KG, "DESede", P11KeyGenerator,607m(CKM_DES3_KEY_GEN, CKM_DES2_KEY_GEN));608d(KG, "AES", P11KeyGenerator,609m(CKM_AES_KEY_GEN));610d(KG, "Blowfish", P11KeyGenerator,611m(CKM_BLOWFISH_KEY_GEN));612d(KG, "ChaCha20", P11KeyGenerator,613m(CKM_CHACHA20_KEY_GEN));614d(KG, "HmacMD5", P11KeyGenerator, // 1.3.6.1.5.5.8.1.1615m(CKM_GENERIC_SECRET_KEY_GEN));616dA(KG, "HmacSHA1", P11KeyGenerator,617m(CKM_SHA_1_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));618dA(KG, "HmacSHA224", P11KeyGenerator,619m(CKM_SHA224_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));620dA(KG, "HmacSHA256", P11KeyGenerator,621m(CKM_SHA256_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));622dA(KG, "HmacSHA384", P11KeyGenerator,623m(CKM_SHA384_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));624dA(KG, "HmacSHA512", P11KeyGenerator,625m(CKM_SHA512_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));626dA(KG, "HmacSHA512/224", P11KeyGenerator,627m(CKM_SHA512_224_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));628dA(KG, "HmacSHA512/256", P11KeyGenerator,629m(CKM_SHA512_256_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));630dA(KG, "HmacSHA3-224", P11KeyGenerator,631m(CKM_SHA3_224_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));632dA(KG, "HmacSHA3-256", P11KeyGenerator,633m(CKM_SHA3_256_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));634dA(KG, "HmacSHA3-384", P11KeyGenerator,635m(CKM_SHA3_384_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));636dA(KG, "HmacSHA3-512", P11KeyGenerator,637m(CKM_SHA3_512_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));638639// register (Secret)KeyFactories if there are any mechanisms640// for a particular algorithm that we support641d(KF, "RSA", P11RSAKeyFactory,642getAliases("PKCS1"),643m(CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_RSA_PKCS, CKM_RSA_X_509));644dA(KF, "DSA", P11DSAKeyFactory,645m(CKM_DSA_KEY_PAIR_GEN, CKM_DSA, CKM_DSA_SHA1));646d(KF, "DH", P11DHKeyFactory,647dhAlias,648m(CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE));649d(KF, "EC", P11ECKeyFactory,650m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,651CKM_ECDSA, CKM_ECDSA_SHA1));652653// AlgorithmParameters for EC.654// Only needed until we have an EC implementation in the SUN provider.655dA(AGP, "EC", "sun.security.util.ECParameters",656m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,657CKM_ECDSA, CKM_ECDSA_SHA1));658659660d(AGP, "GCM", "sun.security.util.GCMParameters",661m(CKM_AES_GCM));662663dA(AGP, "ChaCha20-Poly1305",664"com.sun.crypto.provider.ChaCha20Poly1305Parameters",665m(CKM_CHACHA20_POLY1305));666667d(KA, "DH", P11KeyAgreement,668dhAlias,669m(CKM_DH_PKCS_DERIVE));670d(KA, "ECDH", "sun.security.pkcs11.P11ECDHKeyAgreement",671m(CKM_ECDH1_DERIVE));672673dA(SKF, "ARCFOUR", P11SecretKeyFactory,674m(CKM_RC4));675d(SKF, "DES", P11SecretKeyFactory,676m(CKM_DES_CBC));677d(SKF, "DESede", P11SecretKeyFactory,678m(CKM_DES3_CBC));679dA(SKF, "AES", P11SecretKeyFactory,680m(CKM_AES_CBC));681d(SKF, "Blowfish", P11SecretKeyFactory,682m(CKM_BLOWFISH_CBC));683d(SKF, "ChaCha20", P11SecretKeyFactory,684m(CKM_CHACHA20_POLY1305));685686// XXX attributes for Ciphers (supported modes, padding)687dA(CIP, "ARCFOUR", P11Cipher,688m(CKM_RC4));689d(CIP, "DES/CBC/NoPadding", P11Cipher,690m(CKM_DES_CBC));691d(CIP, "DES/CBC/PKCS5Padding", P11Cipher,692m(CKM_DES_CBC_PAD, CKM_DES_CBC));693d(CIP, "DES/ECB/NoPadding", P11Cipher,694m(CKM_DES_ECB));695d(CIP, "DES/ECB/PKCS5Padding", P11Cipher,696List.of("DES"),697m(CKM_DES_ECB));698699d(CIP, "DESede/CBC/NoPadding", P11Cipher,700m(CKM_DES3_CBC));701d(CIP, "DESede/CBC/PKCS5Padding", P11Cipher,702m(CKM_DES3_CBC_PAD, CKM_DES3_CBC));703d(CIP, "DESede/ECB/NoPadding", P11Cipher,704m(CKM_DES3_ECB));705d(CIP, "DESede/ECB/PKCS5Padding", P11Cipher,706List.of("DESede"),707m(CKM_DES3_ECB));708d(CIP, "AES/CBC/NoPadding", P11Cipher,709m(CKM_AES_CBC));710dA(CIP, "AES_128/CBC/NoPadding", P11Cipher,711m(CKM_AES_CBC));712dA(CIP, "AES_192/CBC/NoPadding", P11Cipher,713m(CKM_AES_CBC));714dA(CIP, "AES_256/CBC/NoPadding", P11Cipher,715m(CKM_AES_CBC));716d(CIP, "AES/CBC/PKCS5Padding", P11Cipher,717m(CKM_AES_CBC_PAD, CKM_AES_CBC));718d(CIP, "AES/ECB/NoPadding", P11Cipher,719m(CKM_AES_ECB));720dA(CIP, "AES_128/ECB/NoPadding", P11Cipher,721m(CKM_AES_ECB));722dA(CIP, "AES_192/ECB/NoPadding", P11Cipher,723m(CKM_AES_ECB));724dA(CIP, "AES_256/ECB/NoPadding", P11Cipher,725m(CKM_AES_ECB));726d(CIP, "AES/ECB/PKCS5Padding", P11Cipher,727List.of("AES"),728m(CKM_AES_ECB));729d(CIP, "AES/CTR/NoPadding", P11Cipher,730m(CKM_AES_CTR));731732d(CIP, "AES/GCM/NoPadding", P11AEADCipher,733m(CKM_AES_GCM));734dA(CIP, "AES_128/GCM/NoPadding", P11AEADCipher,735m(CKM_AES_GCM));736dA(CIP, "AES_192/GCM/NoPadding", P11AEADCipher,737m(CKM_AES_GCM));738dA(CIP, "AES_256/GCM/NoPadding", P11AEADCipher,739m(CKM_AES_GCM));740741d(CIP, "Blowfish/CBC/NoPadding", P11Cipher,742m(CKM_BLOWFISH_CBC));743d(CIP, "Blowfish/CBC/PKCS5Padding", P11Cipher,744m(CKM_BLOWFISH_CBC));745746dA(CIP, "ChaCha20-Poly1305", P11AEADCipher,747m(CKM_CHACHA20_POLY1305));748749d(CIP, "RSA/ECB/PKCS1Padding", P11RSACipher,750List.of("RSA"),751m(CKM_RSA_PKCS));752d(CIP, "RSA/ECB/NoPadding", P11RSACipher,753m(CKM_RSA_X_509));754755d(SIG, "RawDSA", P11Signature,756List.of("NONEwithDSA"),757m(CKM_DSA));758dA(SIG, "SHA1withDSA", P11Signature,759m(CKM_DSA_SHA1, CKM_DSA));760dA(SIG, "SHA224withDSA", P11Signature,761m(CKM_DSA_SHA224));762dA(SIG, "SHA256withDSA", P11Signature,763m(CKM_DSA_SHA256));764dA(SIG, "SHA384withDSA", P11Signature,765m(CKM_DSA_SHA384));766dA(SIG, "SHA512withDSA", P11Signature,767m(CKM_DSA_SHA512));768dA(SIG, "SHA3-224withDSA", P11Signature,769m(CKM_DSA_SHA3_224));770dA(SIG, "SHA3-256withDSA", P11Signature,771m(CKM_DSA_SHA3_256));772dA(SIG, "SHA3-384withDSA", P11Signature,773m(CKM_DSA_SHA3_384));774dA(SIG, "SHA3-512withDSA", P11Signature,775m(CKM_DSA_SHA3_512));776d(SIG, "RawDSAinP1363Format", P11Signature,777List.of("NONEwithDSAinP1363Format"),778m(CKM_DSA));779d(SIG, "DSAinP1363Format", P11Signature,780List.of("SHA1withDSAinP1363Format"),781m(CKM_DSA_SHA1, CKM_DSA));782d(SIG, "SHA224withDSAinP1363Format", P11Signature,783m(CKM_DSA_SHA224));784d(SIG, "SHA256withDSAinP1363Format", P11Signature,785m(CKM_DSA_SHA256));786d(SIG, "SHA384withDSAinP1363Format", P11Signature,787m(CKM_DSA_SHA384));788d(SIG, "SHA512withDSAinP1363Format", P11Signature,789m(CKM_DSA_SHA512));790d(SIG, "SHA3-224withDSAinP1363Format", P11Signature,791m(CKM_DSA_SHA3_224));792d(SIG, "SHA3-256withDSAinP1363Format", P11Signature,793m(CKM_DSA_SHA3_256));794d(SIG, "SHA3-384withDSAinP1363Format", P11Signature,795m(CKM_DSA_SHA3_384));796d(SIG, "SHA3-512withDSAinP1363Format", P11Signature,797m(CKM_DSA_SHA3_512));798d(SIG, "NONEwithECDSA", P11Signature,799m(CKM_ECDSA));800dA(SIG, "SHA1withECDSA", P11Signature,801m(CKM_ECDSA_SHA1, CKM_ECDSA));802dA(SIG, "SHA224withECDSA", P11Signature,803m(CKM_ECDSA_SHA224, CKM_ECDSA));804dA(SIG, "SHA256withECDSA", P11Signature,805m(CKM_ECDSA_SHA256, CKM_ECDSA));806dA(SIG, "SHA384withECDSA", P11Signature,807m(CKM_ECDSA_SHA384, CKM_ECDSA));808dA(SIG, "SHA512withECDSA", P11Signature,809m(CKM_ECDSA_SHA512, CKM_ECDSA));810dA(SIG, "SHA3-224withECDSA", P11Signature,811m(CKM_ECDSA_SHA3_224, CKM_ECDSA));812dA(SIG, "SHA3-256withECDSA", P11Signature,813m(CKM_ECDSA_SHA3_256, CKM_ECDSA));814dA(SIG, "SHA3-384withECDSA", P11Signature,815m(CKM_ECDSA_SHA3_384, CKM_ECDSA));816dA(SIG, "SHA3-512withECDSA", P11Signature,817m(CKM_ECDSA_SHA3_512, CKM_ECDSA));818d(SIG, "NONEwithECDSAinP1363Format", P11Signature,819m(CKM_ECDSA));820d(SIG, "SHA1withECDSAinP1363Format", P11Signature,821m(CKM_ECDSA_SHA1, CKM_ECDSA));822d(SIG, "SHA224withECDSAinP1363Format", P11Signature,823m(CKM_ECDSA_SHA224, CKM_ECDSA));824d(SIG, "SHA256withECDSAinP1363Format", P11Signature,825m(CKM_ECDSA_SHA256, CKM_ECDSA));826d(SIG, "SHA384withECDSAinP1363Format", P11Signature,827m(CKM_ECDSA_SHA384, CKM_ECDSA));828d(SIG, "SHA512withECDSAinP1363Format", P11Signature,829m(CKM_ECDSA_SHA512, CKM_ECDSA));830d(SIG, "SHA3-224withECDSAinP1363Format", P11Signature,831m(CKM_ECDSA_SHA3_224, CKM_ECDSA));832d(SIG, "SHA3-256withECDSAinP1363Format", P11Signature,833m(CKM_ECDSA_SHA3_256, CKM_ECDSA));834d(SIG, "SHA3-384withECDSAinP1363Format", P11Signature,835m(CKM_ECDSA_SHA3_384, CKM_ECDSA));836d(SIG, "SHA3-512withECDSAinP1363Format", P11Signature,837m(CKM_ECDSA_SHA3_512, CKM_ECDSA));838839dA(SIG, "MD2withRSA", P11Signature,840m(CKM_MD2_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));841dA(SIG, "MD5withRSA", P11Signature,842m(CKM_MD5_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));843dA(SIG, "SHA1withRSA", P11Signature,844m(CKM_SHA1_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));845dA(SIG, "SHA224withRSA", P11Signature,846m(CKM_SHA224_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));847dA(SIG, "SHA256withRSA", P11Signature,848m(CKM_SHA256_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));849dA(SIG, "SHA384withRSA", P11Signature,850m(CKM_SHA384_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));851dA(SIG, "SHA512withRSA", P11Signature,852m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));853dA(SIG, "SHA3-224withRSA", P11Signature,854m(CKM_SHA3_224_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));855dA(SIG, "SHA3-256withRSA", P11Signature,856m(CKM_SHA3_256_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));857dA(SIG, "SHA3-384withRSA", P11Signature,858m(CKM_SHA3_384_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));859dA(SIG, "SHA3-512withRSA", P11Signature,860m(CKM_SHA3_512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));861dA(SIG, "RSASSA-PSS", P11PSSSignature,862m(CKM_RSA_PKCS_PSS));863d(SIG, "SHA1withRSASSA-PSS", P11PSSSignature,864m(CKM_SHA1_RSA_PKCS_PSS));865d(SIG, "SHA224withRSASSA-PSS", P11PSSSignature,866m(CKM_SHA224_RSA_PKCS_PSS));867d(SIG, "SHA256withRSASSA-PSS", P11PSSSignature,868m(CKM_SHA256_RSA_PKCS_PSS));869d(SIG, "SHA384withRSASSA-PSS", P11PSSSignature,870m(CKM_SHA384_RSA_PKCS_PSS));871d(SIG, "SHA512withRSASSA-PSS", P11PSSSignature,872m(CKM_SHA512_RSA_PKCS_PSS));873d(SIG, "SHA3-224withRSASSA-PSS", P11PSSSignature,874m(CKM_SHA3_224_RSA_PKCS_PSS));875d(SIG, "SHA3-256withRSASSA-PSS", P11PSSSignature,876m(CKM_SHA3_256_RSA_PKCS_PSS));877d(SIG, "SHA3-384withRSASSA-PSS", P11PSSSignature,878m(CKM_SHA3_384_RSA_PKCS_PSS));879d(SIG, "SHA3-512withRSASSA-PSS", P11PSSSignature,880m(CKM_SHA3_512_RSA_PKCS_PSS));881882d(KG, "SunTlsRsaPremasterSecret",883"sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",884List.of("SunTls12RsaPremasterSecret"),885m(CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_PRE_MASTER_KEY_GEN));886d(KG, "SunTlsMasterSecret",887"sun.security.pkcs11.P11TlsMasterSecretGenerator",888m(CKM_SSL3_MASTER_KEY_DERIVE, CKM_TLS_MASTER_KEY_DERIVE,889CKM_SSL3_MASTER_KEY_DERIVE_DH,890CKM_TLS_MASTER_KEY_DERIVE_DH));891d(KG, "SunTls12MasterSecret",892"sun.security.pkcs11.P11TlsMasterSecretGenerator",893m(CKM_TLS12_MASTER_KEY_DERIVE, CKM_TLS12_MASTER_KEY_DERIVE_DH));894d(KG, "SunTlsKeyMaterial",895"sun.security.pkcs11.P11TlsKeyMaterialGenerator",896m(CKM_SSL3_KEY_AND_MAC_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE));897d(KG, "SunTls12KeyMaterial",898"sun.security.pkcs11.P11TlsKeyMaterialGenerator",899m(CKM_TLS12_KEY_AND_MAC_DERIVE));900d(KG, "SunTlsPrf", "sun.security.pkcs11.P11TlsPrfGenerator",901m(CKM_TLS_PRF, CKM_NSS_TLS_PRF_GENERAL));902d(KG, "SunTls12Prf", "sun.security.pkcs11.P11TlsPrfGenerator",903m(CKM_TLS_MAC));904}905906// background thread that periodically checks for token insertion907// if no token is present. We need to do that in a separate thread because908// the insertion check may block for quite a long time on some tokens.909private static class TokenPoller extends Thread {910private final SunPKCS11 provider;911private volatile boolean enabled;912913private TokenPoller(SunPKCS11 provider) {914super((ThreadGroup)null, "Poller-" + provider.getName());915setContextClassLoader(null);916setDaemon(true);917setPriority(Thread.MIN_PRIORITY);918this.provider = provider;919enabled = true;920}921@Override922public void run() {923int interval = provider.config.getInsertionCheckInterval();924while (enabled) {925try {926Thread.sleep(interval);927} catch (InterruptedException e) {928break;929}930if (enabled == false) {931break;932}933try {934provider.initToken(null);935} catch (PKCS11Exception e) {936// ignore937}938}939}940void disable() {941enabled = false;942}943}944945// create the poller thread, if not already active946private void createPoller() {947if (poller != null) {948return;949}950poller = new TokenPoller(this);951poller.start();952}953954// destroy the poller thread, if active955private void destroyPoller() {956if (poller != null) {957poller.disable();958poller = null;959}960}961962private boolean hasValidToken() {963/* Commented out to work with Solaris softtoken impl which964returns 0-value flags, e.g. both REMOVABLE_DEVICE and965TOKEN_PRESENT are false, when it can't access the token.966if (removable == false) {967return true;968}969*/970Token token = this.token;971return (token != null) && token.isValid();972}973974private class NativeResourceCleaner extends Thread {975private long sleepMillis = config.getResourceCleanerShortInterval();976private int count = 0;977boolean keyRefFound, sessRefFound;978979private NativeResourceCleaner() {980super((ThreadGroup)null, "Cleanup-SunPKCS11");981setContextClassLoader(null);982setDaemon(true);983setPriority(Thread.MIN_PRIORITY);984}985986/*987* The cleaner.shortInterval and cleaner.longInterval properties988* may be defined in the pkcs11 config file and are specified in milliseconds989* Minimum value is 1000ms. Default values :990* cleaner.shortInterval : 2000ms991* cleaner.longInterval : 60000ms992*993* The cleaner thread runs at cleaner.shortInterval intervals994* while P11Key or Session references continue to be found for cleaning.995* If 100 iterations occur with no references being found, then the interval996* period moves to cleaner.longInterval value. The cleaner thread moves back997* to short interval checking if a resource is found998*/999@Override1000public void run() {1001while (true) {1002try {1003sleep(sleepMillis);1004} catch (InterruptedException ie) {1005break;1006}1007keyRefFound = P11Key.drainRefQueue();1008sessRefFound = Session.drainRefQueue();1009if (!keyRefFound && !sessRefFound) {1010count++;1011if (count > 100) {1012// no reference freed for some time1013// increase the sleep time1014sleepMillis = config.getResourceCleanerLongInterval();1015}1016} else {1017count = 0;1018sleepMillis = config.getResourceCleanerShortInterval();1019}1020}1021}1022}10231024// destroy the token. Called if we detect that it has been removed1025@SuppressWarnings("removal")1026synchronized void uninitToken(Token token) {1027if (this.token != token) {1028// mismatch, our token must already be destroyed1029return;1030}1031destroyPoller();1032this.token = null;1033// unregister all algorithms1034AccessController.doPrivileged(new PrivilegedAction<Object>() {1035public Object run() {1036clear();1037return null;1038}1039});1040// keep polling for token insertion unless configured not to1041if (removable && !config.getDestroyTokenAfterLogout()) {1042createPoller();1043}1044}10451046private static boolean isLegacy(CK_MECHANISM_INFO mechInfo)1047throws PKCS11Exception {1048// assume full support if no mech info available1049// For vendor-specific mechanisms, often no mech info is provided1050boolean partialSupport = false;10511052if (mechInfo != null) {1053if ((mechInfo.flags & CKF_DECRYPT) != 0) {1054// non-legacy cipher mechs should support encryption1055partialSupport |= ((mechInfo.flags & CKF_ENCRYPT) == 0);1056}1057if ((mechInfo.flags & CKF_VERIFY) != 0) {1058// non-legacy signature mechs should support signing1059partialSupport |= ((mechInfo.flags & CKF_SIGN) == 0);1060}1061}1062return partialSupport;1063}10641065// test if a token is present and initialize this provider for it if so.1066// does nothing if no token is found1067// called from constructor and by poller1068private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {1069if (slotInfo == null) {1070slotInfo = p11.C_GetSlotInfo(slotID);1071}1072if (removable && (slotInfo.flags & CKF_TOKEN_PRESENT) == 0) {1073createPoller();1074return;1075}1076destroyPoller();1077boolean showInfo = config.getShowInfo();1078if (showInfo) {1079System.out.println("Slot info for slot " + slotID + ":");1080System.out.println(slotInfo);1081}1082final Token token = new Token(this);1083if (showInfo) {1084System.out.println1085("Token info for token in slot " + slotID + ":");1086System.out.println(token.tokenInfo);1087}1088long[] supportedMechanisms = p11.C_GetMechanismList(slotID);10891090// Create a map from the various Descriptors to the "most1091// preferred" mechanism that was defined during the1092// static initialization. For example, DES/CBC/PKCS5Padding1093// could be mapped to CKM_DES_CBC_PAD or CKM_DES_CBC. Prefer1094// the earliest entry. When asked for "DES/CBC/PKCS5Padding", we1095// return a CKM_DES_CBC_PAD.1096final Map<Descriptor,Integer> supportedAlgs =1097new HashMap<Descriptor,Integer>();10981099for (int i = 0; i < supportedMechanisms.length; i++) {1100long longMech = supportedMechanisms[i];1101CK_MECHANISM_INFO mechInfo = token.getMechanismInfo(longMech);1102if (showInfo) {1103System.out.println("Mechanism " +1104Functions.getMechanismName(longMech) + ":");1105System.out.println(mechInfo == null?1106(Constants.INDENT + "info n/a") :1107mechInfo);1108}1109if (!config.isEnabled(longMech)) {1110if (showInfo) {1111System.out.println("DISABLED in configuration");1112}1113continue;1114}1115if (isLegacy(mechInfo)) {1116if (showInfo) {1117System.out.println("DISABLED due to legacy");1118}1119continue;1120}11211122// we do not know of mechs with the upper 32 bits set1123if (longMech >>> 32 != 0) {1124if (showInfo) {1125System.out.println("DISABLED due to unknown mech value");1126}1127continue;1128}1129int mech = (int)longMech;1130Integer integerMech = Integer.valueOf(mech);1131List<Descriptor> ds = descriptors.get(integerMech);1132if (ds == null) {1133continue;1134}1135for (Descriptor d : ds) {1136Integer oldMech = supportedAlgs.get(d);1137if (oldMech == null) {1138supportedAlgs.put(d, integerMech);1139continue;1140}1141// See if there is something "more preferred"1142// than what we currently have in the supportedAlgs1143// map.1144int intOldMech = oldMech.intValue();1145for (int j = 0; j < d.mechanisms.length; j++) {1146int nextMech = d.mechanisms[j];1147if (mech == nextMech) {1148supportedAlgs.put(d, integerMech);1149break;1150} else if (intOldMech == nextMech) {1151break;1152}1153}1154}11551156}11571158// register algorithms in provider1159@SuppressWarnings("removal")1160var dummy = AccessController.doPrivileged(new PrivilegedAction<Object>() {1161public Object run() {1162for (Map.Entry<Descriptor,Integer> entry1163: supportedAlgs.entrySet()) {1164Descriptor d = entry.getKey();1165int mechanism = entry.getValue().intValue();1166Service s = d.service(token, mechanism);1167putService(s);1168}1169if (((token.tokenInfo.flags & CKF_RNG) != 0)1170&& config.isEnabled(PCKM_SECURERANDOM)1171&& !token.sessionManager.lowMaxSessions()) {1172// do not register SecureRandom if the token does1173// not support many sessions. if we did, we might1174// run out of sessions in the middle of a1175// nextBytes() call where we cannot fail over.1176putService(new P11Service(token, SR, "PKCS11",1177"sun.security.pkcs11.P11SecureRandom", null,1178PCKM_SECURERANDOM));1179}1180if (config.isEnabled(PCKM_KEYSTORE)) {1181putService(new P11Service(token, KS, "PKCS11",1182"sun.security.pkcs11.P11KeyStore",1183List.of("PKCS11-" + config.getName()),1184PCKM_KEYSTORE));1185}1186return null;1187}1188});11891190this.token = token;1191if (cleaner == null) {1192cleaner = new NativeResourceCleaner();1193cleaner.start();1194}1195}11961197private static final class P11Service extends Service {11981199private final Token token;12001201private final long mechanism;12021203P11Service(Token token, String type, String algorithm,1204String className, List<String> al, long mechanism) {1205super(token.provider, type, algorithm, className, al,1206type.equals(SR) ? Map.of("ThreadSafe", "true") : null);1207this.token = token;1208this.mechanism = mechanism & 0xFFFFFFFFL;1209}12101211@Override1212public Object newInstance(Object param)1213throws NoSuchAlgorithmException {1214if (token.isValid() == false) {1215throw new NoSuchAlgorithmException("Token has been removed");1216}1217try {1218return newInstance0(param);1219} catch (PKCS11Exception e) {1220throw new NoSuchAlgorithmException(e);1221}1222}12231224public Object newInstance0(Object param) throws1225PKCS11Exception, NoSuchAlgorithmException {1226String algorithm = getAlgorithm();1227String type = getType();1228if (type == MD) {1229return new P11Digest(token, algorithm, mechanism);1230} else if (type == CIP) {1231if (algorithm.startsWith("RSA")) {1232return new P11RSACipher(token, algorithm, mechanism);1233} else if (algorithm.endsWith("GCM/NoPadding") ||1234algorithm.startsWith("ChaCha20-Poly1305")) {1235return new P11AEADCipher(token, algorithm, mechanism);1236} else {1237return new P11Cipher(token, algorithm, mechanism);1238}1239} else if (type == SIG) {1240if (algorithm.indexOf("RSASSA-PSS") != -1) {1241return new P11PSSSignature(token, algorithm, mechanism);1242} else {1243return new P11Signature(token, algorithm, mechanism);1244}1245} else if (type == MAC) {1246return new P11Mac(token, algorithm, mechanism);1247} else if (type == KPG) {1248return new P11KeyPairGenerator(token, algorithm, mechanism);1249} else if (type == KA) {1250if (algorithm.equals("ECDH")) {1251return new P11ECDHKeyAgreement(token, algorithm, mechanism);1252} else {1253return new P11KeyAgreement(token, algorithm, mechanism);1254}1255} else if (type == KF) {1256return token.getKeyFactory(algorithm);1257} else if (type == SKF) {1258return new P11SecretKeyFactory(token, algorithm);1259} else if (type == KG) {1260// reference equality1261if (algorithm == "SunTlsRsaPremasterSecret") {1262return new P11TlsRsaPremasterSecretGenerator(1263token, algorithm, mechanism);1264} else if (algorithm == "SunTlsMasterSecret"1265|| algorithm == "SunTls12MasterSecret") {1266return new P11TlsMasterSecretGenerator(1267token, algorithm, mechanism);1268} else if (algorithm == "SunTlsKeyMaterial"1269|| algorithm == "SunTls12KeyMaterial") {1270return new P11TlsKeyMaterialGenerator(1271token, algorithm, mechanism);1272} else if (algorithm == "SunTlsPrf"1273|| algorithm == "SunTls12Prf") {1274return new P11TlsPrfGenerator(token, algorithm, mechanism);1275} else {1276return new P11KeyGenerator(token, algorithm, mechanism);1277}1278} else if (type == SR) {1279return token.getRandom();1280} else if (type == KS) {1281return token.getKeyStore();1282} else if (type == AGP) {1283if (algorithm == "EC") {1284return new sun.security.util.ECParameters();1285} else if (algorithm == "GCM") {1286return new sun.security.util.GCMParameters();1287} else if (algorithm == "ChaCha20-Poly1305") {1288return new ChaCha20Poly1305Parameters(); // from SunJCE1289} else {1290throw new NoSuchAlgorithmException("Unsupported algorithm: "1291+ algorithm);1292}1293} else {1294throw new NoSuchAlgorithmException("Unknown type: " + type);1295}1296}12971298public boolean supportsParameter(Object param) {1299if ((param == null) || (token.isValid() == false)) {1300return false;1301}1302if (param instanceof Key == false) {1303throw new InvalidParameterException("Parameter must be a Key");1304}1305String algorithm = getAlgorithm();1306String type = getType();1307Key key = (Key)param;1308String keyAlgorithm = key.getAlgorithm();1309// RSA signatures and cipher1310if (((type == CIP) && algorithm.startsWith("RSA"))1311|| (type == SIG) && (algorithm.indexOf("RSA") != -1)) {1312if (keyAlgorithm.equals("RSA") == false) {1313return false;1314}1315return isLocalKey(key)1316|| (key instanceof RSAPrivateKey)1317|| (key instanceof RSAPublicKey);1318}1319// EC1320if (((type == KA) && algorithm.equals("ECDH"))1321|| ((type == SIG) && algorithm.contains("ECDSA"))) {1322if (keyAlgorithm.equals("EC") == false) {1323return false;1324}1325return isLocalKey(key)1326|| (key instanceof ECPrivateKey)1327|| (key instanceof ECPublicKey);1328}1329// DSA signatures1330if ((type == SIG) && algorithm.contains("DSA") &&1331!algorithm.contains("ECDSA")) {1332if (keyAlgorithm.equals("DSA") == false) {1333return false;1334}1335return isLocalKey(key)1336|| (key instanceof DSAPrivateKey)1337|| (key instanceof DSAPublicKey);1338}1339// MACs and symmetric ciphers1340if ((type == CIP) || (type == MAC)) {1341// do not check algorithm name, mismatch is unlikely anyway1342return isLocalKey(key) || "RAW".equals(key.getFormat());1343}1344// DH key agreement1345if (type == KA) {1346if (keyAlgorithm.equals("DH") == false) {1347return false;1348}1349return isLocalKey(key)1350|| (key instanceof DHPrivateKey)1351|| (key instanceof DHPublicKey);1352}1353// should not reach here,1354// unknown engine type or algorithm1355throw new AssertionError1356("SunPKCS11 error: " + type + ", " + algorithm);1357}13581359private boolean isLocalKey(Key key) {1360return (key instanceof P11Key) && (((P11Key)key).token == token);1361}13621363public String toString() {1364return super.toString() +1365" (" + Functions.getMechanismName(mechanism) + ")";1366}13671368}13691370/**1371* Log in to this provider.1372*1373* <p> If the token expects a PIN to be supplied by the caller,1374* the <code>handler</code> implementation must support1375* a <code>PasswordCallback</code>.1376*1377* <p> To determine if the token supports a protected authentication path,1378* the CK_TOKEN_INFO flag, CKF_PROTECTED_AUTHENTICATION_PATH, is consulted.1379*1380* @param subject this parameter is ignored1381* @param handler the <code>CallbackHandler</code> used by1382* this provider to communicate with the caller1383*1384* @throws IllegalStateException if the provider requires configuration1385* and Provider.configure has not been called1386* @throws LoginException if the login operation fails1387* @throws SecurityException if the does not pass a security check for1388* <code>SecurityPermission("authProvider.<i>name</i>")</code>,1389* where <i>name</i> is the value returned by1390* this provider's <code>getName</code> method1391*/1392public void login(Subject subject, CallbackHandler handler)1393throws LoginException {13941395if (!isConfigured()) {1396throw new IllegalStateException("Configuration is required");1397}13981399// security check1400@SuppressWarnings("removal")1401SecurityManager sm = System.getSecurityManager();1402if (sm != null) {1403if (debug != null) {1404debug.println("checking login permission");1405}1406sm.checkPermission(new SecurityPermission1407("authProvider." + this.getName()));1408}14091410if (!hasValidToken()) {1411throw new LoginException("No token present");14121413}14141415// see if a login is required1416if ((token.tokenInfo.flags & CKF_LOGIN_REQUIRED) == 0) {1417if (debug != null) {1418debug.println("login operation not required for token - " +1419"ignoring login request");1420}1421return;1422}14231424// see if user already logged in14251426try {1427if (token.isLoggedInNow(null)) {1428// user already logged in1429if (debug != null) {1430debug.println("user already logged in");1431}1432return;1433}1434} catch (PKCS11Exception e) {1435// ignore - fall thru and attempt login1436}14371438// get the pin if necessary14391440char[] pin = null;1441if ((token.tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) {14421443// get password14441445CallbackHandler myHandler = getCallbackHandler(handler);1446if (myHandler == null) {1447throw new LoginException1448("no password provided, and no callback handler " +1449"available for retrieving password");1450}14511452java.text.MessageFormat form = new java.text.MessageFormat1453(ResourcesMgr.getString1454("PKCS11.Token.providerName.Password."));1455Object[] source = { getName() };14561457PasswordCallback pcall = new PasswordCallback(form.format(source),1458false);1459Callback[] callbacks = { pcall };1460try {1461myHandler.handle(callbacks);1462} catch (Exception e) {1463LoginException le = new LoginException1464("Unable to perform password callback");1465le.initCause(e);1466throw le;1467}14681469pin = pcall.getPassword();1470pcall.clearPassword();1471if (pin == null) {1472if (debug != null) {1473debug.println("caller passed NULL pin");1474}1475}1476}14771478// perform token login14791480Session session = null;1481try {1482session = token.getOpSession();14831484// pin is NULL if using CKF_PROTECTED_AUTHENTICATION_PATH1485p11.C_Login(session.id(), CKU_USER, pin);1486if (debug != null) {1487debug.println("login succeeded");1488}1489} catch (PKCS11Exception pe) {1490if (pe.getErrorCode() == CKR_USER_ALREADY_LOGGED_IN) {1491// let this one go1492if (debug != null) {1493debug.println("user already logged in");1494}1495return;1496} else if (pe.getErrorCode() == CKR_PIN_INCORRECT) {1497FailedLoginException fle = new FailedLoginException();1498fle.initCause(pe);1499throw fle;1500} else {1501LoginException le = new LoginException();1502le.initCause(pe);1503throw le;1504}1505} finally {1506token.releaseSession(session);1507if (pin != null) {1508Arrays.fill(pin, ' ');1509}1510}15111512// we do not store the PIN in the subject for now1513}15141515/**1516* Log out from this provider1517*1518* @throws IllegalStateException if the provider requires configuration1519* and Provider.configure has not been called1520* @throws LoginException if the logout operation fails1521* @throws SecurityException if the does not pass a security check for1522* <code>SecurityPermission("authProvider.<i>name</i>")</code>,1523* where <i>name</i> is the value returned by1524* this provider's <code>getName</code> method1525*/1526public void logout() throws LoginException {1527if (!isConfigured()) {1528throw new IllegalStateException("Configuration is required");1529}15301531// security check1532@SuppressWarnings("removal")1533SecurityManager sm = System.getSecurityManager();1534if (sm != null) {1535sm.checkPermission1536(new SecurityPermission("authProvider." + this.getName()));1537}15381539if (hasValidToken() == false) {1540// app may call logout for cleanup, allow1541return;1542}15431544if ((token.tokenInfo.flags & CKF_LOGIN_REQUIRED) == 0) {1545if (debug != null) {1546debug.println("logout operation not required for token - " +1547"ignoring logout request");1548}1549return;1550}15511552try {1553if (!token.isLoggedInNow(null)) {1554if (debug != null) {1555debug.println("user not logged in");1556}1557if (config.getDestroyTokenAfterLogout()) {1558token.destroy();1559}1560return;1561}1562} catch (PKCS11Exception e) {1563// ignore1564}15651566// perform token logout1567Session session = null;1568try {1569session = token.getOpSession();1570p11.C_Logout(session.id());1571if (debug != null) {1572debug.println("logout succeeded");1573}1574} catch (PKCS11Exception pe) {1575if (pe.getErrorCode() == CKR_USER_NOT_LOGGED_IN) {1576// let this one go1577if (debug != null) {1578debug.println("user not logged in");1579}1580return;1581}1582LoginException le = new LoginException();1583le.initCause(pe);1584throw le;1585} finally {1586token.releaseSession(session);1587if (config.getDestroyTokenAfterLogout()) {1588token.destroy();1589}1590}1591}15921593/**1594* Set a <code>CallbackHandler</code>1595*1596* <p> The provider uses this handler if one is not passed to the1597* <code>login</code> method. The provider also uses this handler1598* if it invokes <code>login</code> on behalf of callers.1599* In either case if a handler is not set via this method,1600* the provider queries the1601* <i>auth.login.defaultCallbackHandler</i> security property1602* for the fully qualified class name of a default handler implementation.1603* If the security property is not set,1604* the provider is assumed to have alternative means1605* for obtaining authentication information.1606*1607* @param handler a <code>CallbackHandler</code> for obtaining1608* authentication information, which may be <code>null</code>1609*1610* @throws IllegalStateException if the provider requires configuration1611* and Provider.configure has not been called1612* @throws SecurityException if the caller does not pass a1613* security check for1614* <code>SecurityPermission("authProvider.<i>name</i>")</code>,1615* where <i>name</i> is the value returned by1616* this provider's <code>getName</code> method1617*/1618public void setCallbackHandler(CallbackHandler handler) {16191620if (!isConfigured()) {1621throw new IllegalStateException("Configuration is required");1622}16231624// security check1625@SuppressWarnings("removal")1626SecurityManager sm = System.getSecurityManager();1627if (sm != null) {1628sm.checkPermission1629(new SecurityPermission("authProvider." + this.getName()));1630}16311632synchronized (LOCK_HANDLER) {1633pHandler = handler;1634}1635}16361637private CallbackHandler getCallbackHandler(CallbackHandler handler) {16381639// get default handler if necessary16401641if (handler != null) {1642return handler;1643}16441645if (debug != null) {1646debug.println("getting provider callback handler");1647}16481649synchronized (LOCK_HANDLER) {1650// see if handler was set via setCallbackHandler1651if (pHandler != null) {1652return pHandler;1653}16541655try {1656if (debug != null) {1657debug.println("getting default callback handler");1658}16591660@SuppressWarnings("removal")1661CallbackHandler myHandler = AccessController.doPrivileged1662(new PrivilegedExceptionAction<CallbackHandler>() {1663public CallbackHandler run() throws Exception {16641665String defaultHandler =1666java.security.Security.getProperty1667("auth.login.defaultCallbackHandler");16681669if (defaultHandler == null ||1670defaultHandler.length() == 0) {16711672// ok1673if (debug != null) {1674debug.println("no default handler set");1675}1676return null;1677}16781679Class<?> c = Class.forName1680(defaultHandler,1681true,1682Thread.currentThread().getContextClassLoader());1683if (!javax.security.auth.callback.CallbackHandler.class.isAssignableFrom(c)) {1684// not the right subtype1685if (debug != null) {1686debug.println("default handler " + defaultHandler +1687" is not a CallbackHandler");1688}1689return null;1690}1691@SuppressWarnings("deprecation")1692Object result = c.newInstance();1693return (CallbackHandler)result;1694}1695});1696// save it1697pHandler = myHandler;1698return myHandler;16991700} catch (PrivilegedActionException pae) {1701// ok1702if (debug != null) {1703debug.println("Unable to load default callback handler");1704pae.printStackTrace();1705}1706}1707}1708return null;1709}17101711private Object writeReplace() throws ObjectStreamException {1712return new SunPKCS11Rep(this);1713}17141715/**1716* Serialized representation of the SunPKCS11 provider.1717*/1718private static class SunPKCS11Rep implements Serializable {17191720static final long serialVersionUID = -2896606995897745419L;17211722private final String providerName;17231724private final String configName;17251726SunPKCS11Rep(SunPKCS11 provider) throws NotSerializableException {1727providerName = provider.getName();1728configName = provider.config.getFileName();1729if (Security.getProvider(providerName) != provider) {1730throw new NotSerializableException("Only SunPKCS11 providers "1731+ "installed in java.security.Security can be serialized");1732}1733}17341735private Object readResolve() throws ObjectStreamException {1736SunPKCS11 p = (SunPKCS11)Security.getProvider(providerName);1737if ((p == null) || (p.config.getFileName().equals(configName) == false)) {1738throw new NotSerializableException("Could not find "1739+ providerName + " in installed providers");1740}1741return p;1742}1743}1744}174517461747