Path: blob/master/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SunPKCS11.java
66646 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 jdk.internal.misc.InnocuousThread;45import sun.security.util.Debug;46import sun.security.util.ResourcesMgr;47import static sun.security.util.SecurityConstants.PROVIDER_VER;48import static sun.security.util.SecurityProviderConstants.getAliases;4950import sun.security.pkcs11.Secmod.*;5152import sun.security.pkcs11.wrapper.*;53import static sun.security.pkcs11.wrapper.PKCS11Constants.*;54import static sun.security.pkcs11.wrapper.PKCS11Exception.*;5556/**57* PKCS#11 provider main class.58*59* @author Andreas Sterbenz60* @since 1.561*/62public final class SunPKCS11 extends AuthProvider {6364private static final long serialVersionUID = -1354835039035306505L;6566static final Debug debug = Debug.getInstance("sunpkcs11");67// the PKCS11 object through which we make the native calls68final PKCS11 p11;6970// configuration information71final Config config;7273// id of the PKCS#11 slot we are using74final long slotID;7576private CallbackHandler pHandler;77private final Object LOCK_HANDLER = new Object();7879final boolean removable;8081final Secmod.Module nssModule;8283final boolean nssUseSecmodTrust;8485private volatile Token token;8687private TokenPoller poller;8889static NativeResourceCleaner cleaner;9091Token getToken() {92return token;93}9495public SunPKCS11() {96super("SunPKCS11", PROVIDER_VER,97"Unconfigured and unusable PKCS11 provider");98p11 = null;99config = null;100slotID = 0;101pHandler = null;102removable = false;103nssModule = null;104nssUseSecmodTrust = false;105token = null;106poller = null;107}108109@SuppressWarnings("removal")110@Override111public Provider configure(String configArg) throws InvalidParameterException {112final String newConfigName = checkNull(configArg);113try {114return AccessController.doPrivileged(new PrivilegedExceptionAction<>() {115@Override116public SunPKCS11 run() throws Exception {117return new SunPKCS11(new Config(newConfigName));118}119});120} catch (PrivilegedActionException pae) {121InvalidParameterException ipe =122new InvalidParameterException("Error configuring SunPKCS11 provider");123throw (InvalidParameterException) ipe.initCause(pae.getException());124}125}126127@Override128public boolean isConfigured() {129return (config != null);130}131132private static <T> T checkNull(T obj) {133if (obj == null) {134throw new NullPointerException();135}136return obj;137}138139// Used by Secmod140SunPKCS11(Config c) {141super("SunPKCS11-" + c.getName(), PROVIDER_VER, c.getDescription());142this.config = c;143144if (debug != null) {145System.out.println("SunPKCS11 loading " + config.getFileName());146}147148String library = config.getLibrary();149String functionList = config.getFunctionList();150long slotID = config.getSlotID();151int slotListIndex = config.getSlotListIndex();152153boolean useSecmod = config.getNssUseSecmod();154boolean nssUseSecmodTrust = config.getNssUseSecmodTrust();155Secmod.Module nssModule = null;156157//158// Initialization via Secmod. The way this works is as follows:159// SunPKCS11 is either in normal mode or in NSS Secmod mode.160// Secmod is activated by specifying one or more of the following161// options in the config file:162// nssUseSecmod, nssSecmodDirectory, nssLibrary, nssModule163//164// XXX add more explanation here165//166// If we are in Secmod mode and configured to use either the167// nssKeyStore or the nssTrustAnchors module, we automatically168// switch to using the NSS trust attributes for trusted certs169// (KeyStore).170//171172if (useSecmod) {173// note: Config ensures library/slot/slotListIndex not specified174// in secmod mode.175Secmod secmod = Secmod.getInstance();176DbMode nssDbMode = config.getNssDbMode();177try {178String nssLibraryDirectory = config.getNssLibraryDirectory();179String nssSecmodDirectory = config.getNssSecmodDirectory();180boolean nssOptimizeSpace = config.getNssOptimizeSpace();181182if (secmod.isInitialized()) {183if (nssSecmodDirectory != null) {184String s = secmod.getConfigDir();185if ((s != null) &&186(s.equals(nssSecmodDirectory) == false)) {187throw new ProviderException("Secmod directory "188+ nssSecmodDirectory189+ " invalid, NSS already initialized with "190+ s);191}192}193if (nssLibraryDirectory != null) {194String s = secmod.getLibDir();195if ((s != null) &&196(s.equals(nssLibraryDirectory) == false)) {197throw new ProviderException("NSS library directory "198+ nssLibraryDirectory199+ " invalid, NSS already initialized with "200+ s);201}202}203} else {204if (nssDbMode != DbMode.NO_DB) {205if (nssSecmodDirectory == null) {206throw new ProviderException(207"Secmod not initialized and "208+ "nssSecmodDirectory not specified");209}210} else {211if (nssSecmodDirectory != null) {212throw new ProviderException(213"nssSecmodDirectory must not be "214+ "specified in noDb mode");215}216}217secmod.initialize(nssDbMode, nssSecmodDirectory,218nssLibraryDirectory, nssOptimizeSpace);219}220} catch (IOException e) {221// XXX which exception to throw222throw new ProviderException("Could not initialize NSS", e);223}224List<Secmod.Module> modules = secmod.getModules();225if (config.getShowInfo()) {226System.out.println("NSS modules: " + modules);227}228229String moduleName = config.getNssModule();230if (moduleName == null) {231nssModule = secmod.getModule(ModuleType.FIPS);232if (nssModule != null) {233moduleName = "fips";234} else {235moduleName = (nssDbMode == DbMode.NO_DB) ?236"crypto" : "keystore";237}238}239if (moduleName.equals("fips")) {240nssModule = secmod.getModule(ModuleType.FIPS);241nssUseSecmodTrust = true;242functionList = "FC_GetFunctionList";243} else if (moduleName.equals("keystore")) {244nssModule = secmod.getModule(ModuleType.KEYSTORE);245nssUseSecmodTrust = true;246} else if (moduleName.equals("crypto")) {247nssModule = secmod.getModule(ModuleType.CRYPTO);248} else if (moduleName.equals("trustanchors")) {249// XXX should the option be called trustanchor or trustanchors??250nssModule = secmod.getModule(ModuleType.TRUSTANCHOR);251nssUseSecmodTrust = true;252} else if (moduleName.startsWith("external-")) {253int moduleIndex;254try {255moduleIndex = Integer.parseInt256(moduleName.substring("external-".length()));257} catch (NumberFormatException e) {258moduleIndex = -1;259}260if (moduleIndex < 1) {261throw new ProviderException262("Invalid external module: " + moduleName);263}264int k = 0;265for (Secmod.Module module : modules) {266if (module.getType() == ModuleType.EXTERNAL) {267if (++k == moduleIndex) {268nssModule = module;269break;270}271}272}273if (nssModule == null) {274throw new ProviderException("Invalid module " + moduleName275+ ": only " + k + " external NSS modules available");276}277} else {278throw new ProviderException(279"Unknown NSS module: " + moduleName);280}281if (nssModule == null) {282throw new ProviderException(283"NSS module not available: " + moduleName);284}285if (nssModule.hasInitializedProvider()) {286throw new ProviderException("Secmod module already configured");287}288library = nssModule.libraryName;289slotListIndex = nssModule.slot;290}291this.nssUseSecmodTrust = nssUseSecmodTrust;292this.nssModule = nssModule;293294File libraryFile = new File(library);295// if the filename is a simple filename without path296// (e.g. "libpkcs11.so"), it may refer to a library somewhere on the297// OS library search path. Omit the test for file existence as that298// only looks in the current directory.299if (libraryFile.getName().equals(library) == false) {300if (new File(library).isFile() == false) {301String msg = "Library " + library + " does not exist";302if (config.getHandleStartupErrors() == Config.ERR_HALT) {303throw new ProviderException(msg);304} else {305throw new UnsupportedOperationException(msg);306}307}308}309310try {311if (debug != null) {312debug.println("Initializing PKCS#11 library " + library);313}314CK_C_INITIALIZE_ARGS initArgs = new CK_C_INITIALIZE_ARGS();315String nssArgs = config.getNssArgs();316if (nssArgs != null) {317initArgs.pReserved = nssArgs;318}319// request multithreaded access first320initArgs.flags = CKF_OS_LOCKING_OK;321PKCS11 tmpPKCS11;322try {323tmpPKCS11 = PKCS11.getInstance(324library, functionList, initArgs,325config.getOmitInitialize());326} catch (PKCS11Exception e) {327if (debug != null) {328debug.println("Multi-threaded initialization failed: " + e);329}330if (config.getAllowSingleThreadedModules() == false) {331throw e;332}333// fall back to single threaded access334if (nssArgs == null) {335// if possible, use null initArgs for better compatibility336initArgs = null;337} else {338initArgs.flags = 0;339}340tmpPKCS11 = PKCS11.getInstance(library,341functionList, initArgs, config.getOmitInitialize());342}343p11 = tmpPKCS11;344345CK_INFO p11Info = p11.C_GetInfo();346if (p11Info.cryptokiVersion.major < 2) {347throw new ProviderException("Only PKCS#11 v2.0 and later "348+ "supported, library version is v" + p11Info.cryptokiVersion);349}350boolean showInfo = config.getShowInfo();351if (showInfo) {352System.out.println("Information for provider " + getName());353System.out.println("Library info:");354System.out.println(p11Info);355}356357if ((slotID < 0) || showInfo) {358long[] slots = p11.C_GetSlotList(false);359if (showInfo) {360System.out.println("All slots: " + toString(slots));361slots = p11.C_GetSlotList(true);362System.out.println("Slots with tokens: " + toString(slots));363}364if (slotID < 0) {365if ((slotListIndex < 0)366|| (slotListIndex >= slots.length)) {367throw new ProviderException("slotListIndex is "368+ slotListIndex369+ " but token only has " + slots.length + " slots");370}371slotID = slots[slotListIndex];372}373}374this.slotID = slotID;375CK_SLOT_INFO slotInfo = p11.C_GetSlotInfo(slotID);376removable = (slotInfo.flags & CKF_REMOVABLE_DEVICE) != 0;377initToken(slotInfo);378if (nssModule != null) {379nssModule.setProvider(this);380}381} catch (Exception e) {382if (config.getHandleStartupErrors() == Config.ERR_IGNORE_ALL) {383throw new UnsupportedOperationException384("Initialization failed", e);385} else {386throw new ProviderException387("Initialization failed", e);388}389}390}391392private static String toString(long[] longs) {393if (longs.length == 0) {394return "(none)";395}396StringBuilder sb = new StringBuilder();397sb.append(longs[0]);398for (int i = 1; i < longs.length; i++) {399sb.append(", ");400sb.append(longs[i]);401}402return sb.toString();403}404405public boolean equals(Object obj) {406return this == obj;407}408409public int hashCode() {410return System.identityHashCode(this);411}412413private static final class Descriptor {414final String type;415final String algorithm;416final String className;417final List<String> aliases;418final int[] mechanisms;419420private Descriptor(String type, String algorithm, String className,421List<String> aliases, int[] mechanisms) {422this.type = type;423this.algorithm = algorithm;424this.className = className;425this.aliases = aliases;426this.mechanisms = mechanisms;427}428private P11Service service(Token token, int mechanism) {429return new P11Service430(token, type, algorithm, className, aliases, mechanism);431}432public String toString() {433return type + "." + algorithm;434}435}436437// Map from mechanism to List of Descriptors that should be438// registered if the mechanism is supported439private static final Map<Integer,List<Descriptor>> descriptors =440new HashMap<Integer,List<Descriptor>>();441442private static int[] m(long m1) {443return new int[] {(int)m1};444}445446private static int[] m(long m1, long m2) {447return new int[] {(int)m1, (int)m2};448}449450private static int[] m(long m1, long m2, long m3) {451return new int[] {(int)m1, (int)m2, (int)m3};452}453454private static int[] m(long m1, long m2, long m3, long m4) {455return new int[] {(int)m1, (int)m2, (int)m3, (int)m4};456}457458private static void d(String type, String algorithm, String className,459int[] m) {460register(new Descriptor(type, algorithm, className, null, m));461}462463private static void d(String type, String algorithm, String className,464List<String> aliases, int[] m) {465register(new Descriptor(type, algorithm, className, aliases, m));466}467468private static void dA(String type, String algorithm, String className,469int[] m) {470register(new Descriptor(type, algorithm, className,471getAliases(algorithm), m));472}473474private static void register(Descriptor d) {475for (int i = 0; i < d.mechanisms.length; i++) {476int m = d.mechanisms[i];477Integer key = Integer.valueOf(m);478List<Descriptor> list = descriptors.get(key);479if (list == null) {480list = new ArrayList<Descriptor>();481descriptors.put(key, list);482}483list.add(d);484}485}486487private static final String MD = "MessageDigest";488489private static final String SIG = "Signature";490491private static final String KPG = "KeyPairGenerator";492493private static final String KG = "KeyGenerator";494495private static final String AGP = "AlgorithmParameters";496497private static final String KF = "KeyFactory";498499private static final String SKF = "SecretKeyFactory";500501private static final String CIP = "Cipher";502503private static final String MAC = "Mac";504505private static final String KA = "KeyAgreement";506507private static final String KS = "KeyStore";508509private static final String SR = "SecureRandom";510511static {512// names of all the implementation classes513// use local variables, only used here514String P11Digest = "sun.security.pkcs11.P11Digest";515String P11Mac = "sun.security.pkcs11.P11Mac";516String P11KeyPairGenerator = "sun.security.pkcs11.P11KeyPairGenerator";517String P11KeyGenerator = "sun.security.pkcs11.P11KeyGenerator";518String P11RSAKeyFactory = "sun.security.pkcs11.P11RSAKeyFactory";519String P11DSAKeyFactory = "sun.security.pkcs11.P11DSAKeyFactory";520String P11DHKeyFactory = "sun.security.pkcs11.P11DHKeyFactory";521String P11ECKeyFactory = "sun.security.pkcs11.P11ECKeyFactory";522String P11KeyAgreement = "sun.security.pkcs11.P11KeyAgreement";523String P11SecretKeyFactory = "sun.security.pkcs11.P11SecretKeyFactory";524String P11Cipher = "sun.security.pkcs11.P11Cipher";525String P11RSACipher = "sun.security.pkcs11.P11RSACipher";526String P11AEADCipher = "sun.security.pkcs11.P11AEADCipher";527String P11Signature = "sun.security.pkcs11.P11Signature";528String P11PSSSignature = "sun.security.pkcs11.P11PSSSignature";529530// XXX register all aliases531532d(MD, "MD2", P11Digest,533m(CKM_MD2));534d(MD, "MD5", P11Digest,535m(CKM_MD5));536dA(MD, "SHA-1", P11Digest,537m(CKM_SHA_1));538539dA(MD, "SHA-224", P11Digest,540m(CKM_SHA224));541dA(MD, "SHA-256", P11Digest,542m(CKM_SHA256));543dA(MD, "SHA-384", P11Digest,544m(CKM_SHA384));545dA(MD, "SHA-512", P11Digest,546m(CKM_SHA512));547dA(MD, "SHA-512/224", P11Digest,548m(CKM_SHA512_224));549dA(MD, "SHA-512/256", P11Digest,550m(CKM_SHA512_256));551dA(MD, "SHA3-224", P11Digest,552m(CKM_SHA3_224));553dA(MD, "SHA3-256", P11Digest,554m(CKM_SHA3_256));555dA(MD, "SHA3-384", P11Digest,556m(CKM_SHA3_384));557dA(MD, "SHA3-512", P11Digest,558m(CKM_SHA3_512));559560d(MAC, "HmacMD5", P11Mac,561m(CKM_MD5_HMAC));562dA(MAC, "HmacSHA1", P11Mac,563m(CKM_SHA_1_HMAC));564dA(MAC, "HmacSHA224", P11Mac,565m(CKM_SHA224_HMAC));566dA(MAC, "HmacSHA256", P11Mac,567m(CKM_SHA256_HMAC));568dA(MAC, "HmacSHA384", P11Mac,569m(CKM_SHA384_HMAC));570dA(MAC, "HmacSHA512", P11Mac,571m(CKM_SHA512_HMAC));572dA(MAC, "HmacSHA512/224", P11Mac,573m(CKM_SHA512_224_HMAC));574dA(MAC, "HmacSHA512/256", P11Mac,575m(CKM_SHA512_256_HMAC));576dA(MAC, "HmacSHA3-224", P11Mac,577m(CKM_SHA3_224_HMAC));578dA(MAC, "HmacSHA3-256", P11Mac,579m(CKM_SHA3_256_HMAC));580dA(MAC, "HmacSHA3-384", P11Mac,581m(CKM_SHA3_384_HMAC));582dA(MAC, "HmacSHA3-512", P11Mac,583m(CKM_SHA3_512_HMAC));584d(MAC, "SslMacMD5", P11Mac,585m(CKM_SSL3_MD5_MAC));586d(MAC, "SslMacSHA1", P11Mac,587m(CKM_SSL3_SHA1_MAC));588589d(KPG, "RSA", P11KeyPairGenerator,590getAliases("PKCS1"),591m(CKM_RSA_PKCS_KEY_PAIR_GEN));592593List<String> dhAlias = List.of("DiffieHellman");594595dA(KPG, "DSA", P11KeyPairGenerator,596m(CKM_DSA_KEY_PAIR_GEN));597d(KPG, "DH", P11KeyPairGenerator,598dhAlias,599m(CKM_DH_PKCS_KEY_PAIR_GEN));600d(KPG, "EC", P11KeyPairGenerator,601m(CKM_EC_KEY_PAIR_GEN));602603dA(KG, "ARCFOUR", P11KeyGenerator,604m(CKM_RC4_KEY_GEN));605d(KG, "DES", P11KeyGenerator,606m(CKM_DES_KEY_GEN));607d(KG, "DESede", P11KeyGenerator,608m(CKM_DES3_KEY_GEN, CKM_DES2_KEY_GEN));609d(KG, "AES", P11KeyGenerator,610m(CKM_AES_KEY_GEN));611d(KG, "Blowfish", P11KeyGenerator,612m(CKM_BLOWFISH_KEY_GEN));613d(KG, "ChaCha20", P11KeyGenerator,614m(CKM_CHACHA20_KEY_GEN));615d(KG, "HmacMD5", P11KeyGenerator, // 1.3.6.1.5.5.8.1.1616m(CKM_GENERIC_SECRET_KEY_GEN));617dA(KG, "HmacSHA1", P11KeyGenerator,618m(CKM_SHA_1_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));619dA(KG, "HmacSHA224", P11KeyGenerator,620m(CKM_SHA224_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));621dA(KG, "HmacSHA256", P11KeyGenerator,622m(CKM_SHA256_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));623dA(KG, "HmacSHA384", P11KeyGenerator,624m(CKM_SHA384_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));625dA(KG, "HmacSHA512", P11KeyGenerator,626m(CKM_SHA512_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));627dA(KG, "HmacSHA512/224", P11KeyGenerator,628m(CKM_SHA512_224_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));629dA(KG, "HmacSHA512/256", P11KeyGenerator,630m(CKM_SHA512_256_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));631dA(KG, "HmacSHA3-224", P11KeyGenerator,632m(CKM_SHA3_224_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));633dA(KG, "HmacSHA3-256", P11KeyGenerator,634m(CKM_SHA3_256_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));635dA(KG, "HmacSHA3-384", P11KeyGenerator,636m(CKM_SHA3_384_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));637dA(KG, "HmacSHA3-512", P11KeyGenerator,638m(CKM_SHA3_512_KEY_GEN, CKM_GENERIC_SECRET_KEY_GEN));639640// register (Secret)KeyFactories if there are any mechanisms641// for a particular algorithm that we support642d(KF, "RSA", P11RSAKeyFactory,643getAliases("PKCS1"),644m(CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_RSA_PKCS, CKM_RSA_X_509));645dA(KF, "DSA", P11DSAKeyFactory,646m(CKM_DSA_KEY_PAIR_GEN, CKM_DSA, CKM_DSA_SHA1));647d(KF, "DH", P11DHKeyFactory,648dhAlias,649m(CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE));650d(KF, "EC", P11ECKeyFactory,651m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,652CKM_ECDSA, CKM_ECDSA_SHA1));653654// AlgorithmParameters for EC.655// Only needed until we have an EC implementation in the SUN provider.656dA(AGP, "EC", "sun.security.util.ECParameters",657m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,658CKM_ECDSA, CKM_ECDSA_SHA1));659660661d(AGP, "GCM", "sun.security.util.GCMParameters",662m(CKM_AES_GCM));663664dA(AGP, "ChaCha20-Poly1305",665"com.sun.crypto.provider.ChaCha20Poly1305Parameters",666m(CKM_CHACHA20_POLY1305));667668d(KA, "DH", P11KeyAgreement,669dhAlias,670m(CKM_DH_PKCS_DERIVE));671d(KA, "ECDH", "sun.security.pkcs11.P11ECDHKeyAgreement",672m(CKM_ECDH1_DERIVE));673674dA(SKF, "ARCFOUR", P11SecretKeyFactory,675m(CKM_RC4));676d(SKF, "DES", P11SecretKeyFactory,677m(CKM_DES_CBC));678d(SKF, "DESede", P11SecretKeyFactory,679m(CKM_DES3_CBC));680dA(SKF, "AES", P11SecretKeyFactory,681m(CKM_AES_CBC));682d(SKF, "Blowfish", P11SecretKeyFactory,683m(CKM_BLOWFISH_CBC));684d(SKF, "ChaCha20", P11SecretKeyFactory,685m(CKM_CHACHA20_POLY1305));686687// XXX attributes for Ciphers (supported modes, padding)688dA(CIP, "ARCFOUR", P11Cipher,689m(CKM_RC4));690d(CIP, "DES/CBC/NoPadding", P11Cipher,691m(CKM_DES_CBC));692d(CIP, "DES/CBC/PKCS5Padding", P11Cipher,693m(CKM_DES_CBC_PAD, CKM_DES_CBC));694d(CIP, "DES/ECB/NoPadding", P11Cipher,695m(CKM_DES_ECB));696d(CIP, "DES/ECB/PKCS5Padding", P11Cipher,697List.of("DES"),698m(CKM_DES_ECB));699700d(CIP, "DESede/CBC/NoPadding", P11Cipher,701m(CKM_DES3_CBC));702d(CIP, "DESede/CBC/PKCS5Padding", P11Cipher,703m(CKM_DES3_CBC_PAD, CKM_DES3_CBC));704d(CIP, "DESede/ECB/NoPadding", P11Cipher,705m(CKM_DES3_ECB));706d(CIP, "DESede/ECB/PKCS5Padding", P11Cipher,707List.of("DESede"),708m(CKM_DES3_ECB));709d(CIP, "AES/CBC/NoPadding", P11Cipher,710m(CKM_AES_CBC));711dA(CIP, "AES_128/CBC/NoPadding", P11Cipher,712m(CKM_AES_CBC));713dA(CIP, "AES_192/CBC/NoPadding", P11Cipher,714m(CKM_AES_CBC));715dA(CIP, "AES_256/CBC/NoPadding", P11Cipher,716m(CKM_AES_CBC));717d(CIP, "AES/CBC/PKCS5Padding", P11Cipher,718m(CKM_AES_CBC_PAD, CKM_AES_CBC));719d(CIP, "AES/ECB/NoPadding", P11Cipher,720m(CKM_AES_ECB));721dA(CIP, "AES_128/ECB/NoPadding", P11Cipher,722m(CKM_AES_ECB));723dA(CIP, "AES_192/ECB/NoPadding", P11Cipher,724m(CKM_AES_ECB));725dA(CIP, "AES_256/ECB/NoPadding", P11Cipher,726m(CKM_AES_ECB));727d(CIP, "AES/ECB/PKCS5Padding", P11Cipher,728List.of("AES"),729m(CKM_AES_ECB));730d(CIP, "AES/CTR/NoPadding", P11Cipher,731m(CKM_AES_CTR));732733d(CIP, "AES/GCM/NoPadding", P11AEADCipher,734m(CKM_AES_GCM));735dA(CIP, "AES_128/GCM/NoPadding", P11AEADCipher,736m(CKM_AES_GCM));737dA(CIP, "AES_192/GCM/NoPadding", P11AEADCipher,738m(CKM_AES_GCM));739dA(CIP, "AES_256/GCM/NoPadding", P11AEADCipher,740m(CKM_AES_GCM));741742d(CIP, "Blowfish/CBC/NoPadding", P11Cipher,743m(CKM_BLOWFISH_CBC));744d(CIP, "Blowfish/CBC/PKCS5Padding", P11Cipher,745m(CKM_BLOWFISH_CBC));746747dA(CIP, "ChaCha20-Poly1305", P11AEADCipher,748m(CKM_CHACHA20_POLY1305));749750d(CIP, "RSA/ECB/PKCS1Padding", P11RSACipher,751List.of("RSA"),752m(CKM_RSA_PKCS));753d(CIP, "RSA/ECB/NoPadding", P11RSACipher,754m(CKM_RSA_X_509));755756d(SIG, "RawDSA", P11Signature,757List.of("NONEwithDSA"),758m(CKM_DSA));759dA(SIG, "SHA1withDSA", P11Signature,760m(CKM_DSA_SHA1, CKM_DSA));761dA(SIG, "SHA224withDSA", P11Signature,762m(CKM_DSA_SHA224));763dA(SIG, "SHA256withDSA", P11Signature,764m(CKM_DSA_SHA256));765dA(SIG, "SHA384withDSA", P11Signature,766m(CKM_DSA_SHA384));767dA(SIG, "SHA512withDSA", P11Signature,768m(CKM_DSA_SHA512));769dA(SIG, "SHA3-224withDSA", P11Signature,770m(CKM_DSA_SHA3_224));771dA(SIG, "SHA3-256withDSA", P11Signature,772m(CKM_DSA_SHA3_256));773dA(SIG, "SHA3-384withDSA", P11Signature,774m(CKM_DSA_SHA3_384));775dA(SIG, "SHA3-512withDSA", P11Signature,776m(CKM_DSA_SHA3_512));777d(SIG, "RawDSAinP1363Format", P11Signature,778List.of("NONEwithDSAinP1363Format"),779m(CKM_DSA));780d(SIG, "DSAinP1363Format", P11Signature,781List.of("SHA1withDSAinP1363Format"),782m(CKM_DSA_SHA1, CKM_DSA));783d(SIG, "SHA224withDSAinP1363Format", P11Signature,784m(CKM_DSA_SHA224));785d(SIG, "SHA256withDSAinP1363Format", P11Signature,786m(CKM_DSA_SHA256));787d(SIG, "SHA384withDSAinP1363Format", P11Signature,788m(CKM_DSA_SHA384));789d(SIG, "SHA512withDSAinP1363Format", P11Signature,790m(CKM_DSA_SHA512));791d(SIG, "SHA3-224withDSAinP1363Format", P11Signature,792m(CKM_DSA_SHA3_224));793d(SIG, "SHA3-256withDSAinP1363Format", P11Signature,794m(CKM_DSA_SHA3_256));795d(SIG, "SHA3-384withDSAinP1363Format", P11Signature,796m(CKM_DSA_SHA3_384));797d(SIG, "SHA3-512withDSAinP1363Format", P11Signature,798m(CKM_DSA_SHA3_512));799d(SIG, "NONEwithECDSA", P11Signature,800m(CKM_ECDSA));801dA(SIG, "SHA1withECDSA", P11Signature,802m(CKM_ECDSA_SHA1, CKM_ECDSA));803dA(SIG, "SHA224withECDSA", P11Signature,804m(CKM_ECDSA_SHA224, CKM_ECDSA));805dA(SIG, "SHA256withECDSA", P11Signature,806m(CKM_ECDSA_SHA256, CKM_ECDSA));807dA(SIG, "SHA384withECDSA", P11Signature,808m(CKM_ECDSA_SHA384, CKM_ECDSA));809dA(SIG, "SHA512withECDSA", P11Signature,810m(CKM_ECDSA_SHA512, CKM_ECDSA));811dA(SIG, "SHA3-224withECDSA", P11Signature,812m(CKM_ECDSA_SHA3_224, CKM_ECDSA));813dA(SIG, "SHA3-256withECDSA", P11Signature,814m(CKM_ECDSA_SHA3_256, CKM_ECDSA));815dA(SIG, "SHA3-384withECDSA", P11Signature,816m(CKM_ECDSA_SHA3_384, CKM_ECDSA));817dA(SIG, "SHA3-512withECDSA", P11Signature,818m(CKM_ECDSA_SHA3_512, CKM_ECDSA));819d(SIG, "NONEwithECDSAinP1363Format", P11Signature,820m(CKM_ECDSA));821d(SIG, "SHA1withECDSAinP1363Format", P11Signature,822m(CKM_ECDSA_SHA1, CKM_ECDSA));823d(SIG, "SHA224withECDSAinP1363Format", P11Signature,824m(CKM_ECDSA_SHA224, CKM_ECDSA));825d(SIG, "SHA256withECDSAinP1363Format", P11Signature,826m(CKM_ECDSA_SHA256, CKM_ECDSA));827d(SIG, "SHA384withECDSAinP1363Format", P11Signature,828m(CKM_ECDSA_SHA384, CKM_ECDSA));829d(SIG, "SHA512withECDSAinP1363Format", P11Signature,830m(CKM_ECDSA_SHA512, CKM_ECDSA));831d(SIG, "SHA3-224withECDSAinP1363Format", P11Signature,832m(CKM_ECDSA_SHA3_224, CKM_ECDSA));833d(SIG, "SHA3-256withECDSAinP1363Format", P11Signature,834m(CKM_ECDSA_SHA3_256, CKM_ECDSA));835d(SIG, "SHA3-384withECDSAinP1363Format", P11Signature,836m(CKM_ECDSA_SHA3_384, CKM_ECDSA));837d(SIG, "SHA3-512withECDSAinP1363Format", P11Signature,838m(CKM_ECDSA_SHA3_512, CKM_ECDSA));839840dA(SIG, "MD2withRSA", P11Signature,841m(CKM_MD2_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));842dA(SIG, "MD5withRSA", P11Signature,843m(CKM_MD5_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));844dA(SIG, "SHA1withRSA", P11Signature,845m(CKM_SHA1_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));846dA(SIG, "SHA224withRSA", P11Signature,847m(CKM_SHA224_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));848dA(SIG, "SHA256withRSA", P11Signature,849m(CKM_SHA256_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));850dA(SIG, "SHA384withRSA", P11Signature,851m(CKM_SHA384_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));852dA(SIG, "SHA512withRSA", P11Signature,853m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));854dA(SIG, "SHA3-224withRSA", P11Signature,855m(CKM_SHA3_224_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));856dA(SIG, "SHA3-256withRSA", P11Signature,857m(CKM_SHA3_256_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));858dA(SIG, "SHA3-384withRSA", P11Signature,859m(CKM_SHA3_384_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));860dA(SIG, "SHA3-512withRSA", P11Signature,861m(CKM_SHA3_512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));862dA(SIG, "RSASSA-PSS", P11PSSSignature,863m(CKM_RSA_PKCS_PSS));864d(SIG, "SHA1withRSASSA-PSS", P11PSSSignature,865m(CKM_SHA1_RSA_PKCS_PSS));866d(SIG, "SHA224withRSASSA-PSS", P11PSSSignature,867m(CKM_SHA224_RSA_PKCS_PSS));868d(SIG, "SHA256withRSASSA-PSS", P11PSSSignature,869m(CKM_SHA256_RSA_PKCS_PSS));870d(SIG, "SHA384withRSASSA-PSS", P11PSSSignature,871m(CKM_SHA384_RSA_PKCS_PSS));872d(SIG, "SHA512withRSASSA-PSS", P11PSSSignature,873m(CKM_SHA512_RSA_PKCS_PSS));874d(SIG, "SHA3-224withRSASSA-PSS", P11PSSSignature,875m(CKM_SHA3_224_RSA_PKCS_PSS));876d(SIG, "SHA3-256withRSASSA-PSS", P11PSSSignature,877m(CKM_SHA3_256_RSA_PKCS_PSS));878d(SIG, "SHA3-384withRSASSA-PSS", P11PSSSignature,879m(CKM_SHA3_384_RSA_PKCS_PSS));880d(SIG, "SHA3-512withRSASSA-PSS", P11PSSSignature,881m(CKM_SHA3_512_RSA_PKCS_PSS));882883d(KG, "SunTlsRsaPremasterSecret",884"sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",885List.of("SunTls12RsaPremasterSecret"),886m(CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_PRE_MASTER_KEY_GEN));887d(KG, "SunTlsMasterSecret",888"sun.security.pkcs11.P11TlsMasterSecretGenerator",889m(CKM_SSL3_MASTER_KEY_DERIVE, CKM_TLS_MASTER_KEY_DERIVE,890CKM_SSL3_MASTER_KEY_DERIVE_DH,891CKM_TLS_MASTER_KEY_DERIVE_DH));892d(KG, "SunTls12MasterSecret",893"sun.security.pkcs11.P11TlsMasterSecretGenerator",894m(CKM_TLS12_MASTER_KEY_DERIVE, CKM_TLS12_MASTER_KEY_DERIVE_DH));895d(KG, "SunTlsKeyMaterial",896"sun.security.pkcs11.P11TlsKeyMaterialGenerator",897m(CKM_SSL3_KEY_AND_MAC_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE));898d(KG, "SunTls12KeyMaterial",899"sun.security.pkcs11.P11TlsKeyMaterialGenerator",900m(CKM_TLS12_KEY_AND_MAC_DERIVE));901d(KG, "SunTlsPrf", "sun.security.pkcs11.P11TlsPrfGenerator",902m(CKM_TLS_PRF, CKM_NSS_TLS_PRF_GENERAL));903d(KG, "SunTls12Prf", "sun.security.pkcs11.P11TlsPrfGenerator",904m(CKM_TLS_MAC));905}906907// background thread that periodically checks for token insertion908// if no token is present. We need to do that in a separate thread because909// the insertion check may block for quite a long time on some tokens.910private static class TokenPoller implements Runnable {911private final SunPKCS11 provider;912private volatile boolean enabled;913914private TokenPoller(SunPKCS11 provider) {915this.provider = provider;916enabled = true;917}918@Override919public void run() {920int interval = provider.config.getInsertionCheckInterval();921while (enabled) {922try {923Thread.sleep(interval);924} catch (InterruptedException e) {925break;926}927if (enabled == false) {928break;929}930try {931provider.initToken(null);932} catch (PKCS11Exception e) {933// ignore934}935}936}937void disable() {938enabled = false;939}940}941942// create the poller thread, if not already active943@SuppressWarnings("removal")944private void createPoller() {945if (poller != null) {946return;947}948poller = new TokenPoller(this);949Thread t = InnocuousThread.newSystemThread(950"Poller-" + getName(),951poller,952Thread.MIN_PRIORITY);953assert t.getContextClassLoader() == null;954t.setDaemon(true);955t.start();956957}958959// destroy the poller thread, if active960private void destroyPoller() {961if (poller != null) {962poller.disable();963poller = null;964}965}966967private boolean hasValidToken() {968/* Commented out to work with Solaris softtoken impl which969returns 0-value flags, e.g. both REMOVABLE_DEVICE and970TOKEN_PRESENT are false, when it can't access the token.971if (removable == false) {972return true;973}974*/975Token token = this.token;976return (token != null) && token.isValid();977}978979private class NativeResourceCleaner implements Runnable {980private long sleepMillis = config.getResourceCleanerShortInterval();981private int count = 0;982boolean keyRefFound, sessRefFound;983984/*985* The cleaner.shortInterval and cleaner.longInterval properties986* may be defined in the pkcs11 config file and are specified in milliseconds987* Minimum value is 1000ms. Default values :988* cleaner.shortInterval : 2000ms989* cleaner.longInterval : 60000ms990*991* The cleaner thread runs at cleaner.shortInterval intervals992* while P11Key or Session references continue to be found for cleaning.993* If 100 iterations occur with no references being found, then the interval994* period moves to cleaner.longInterval value. The cleaner thread moves back995* to short interval checking if a resource is found996*/997@Override998public void run() {999while (true) {1000try {1001Thread.sleep(sleepMillis);1002} catch (InterruptedException ie) {1003break;1004}1005keyRefFound = P11Key.drainRefQueue();1006sessRefFound = Session.drainRefQueue();1007if (!keyRefFound && !sessRefFound) {1008count++;1009if (count > 100) {1010// no reference freed for some time1011// increase the sleep time1012sleepMillis = config.getResourceCleanerLongInterval();1013}1014} else {1015count = 0;1016sleepMillis = config.getResourceCleanerShortInterval();1017}1018}1019}1020}10211022// create the cleaner thread, if not already active1023@SuppressWarnings("removal")1024private void createCleaner() {1025cleaner = new NativeResourceCleaner();1026Thread t = InnocuousThread.newSystemThread(1027"Cleanup-SunPKCS11",1028cleaner,1029Thread.MIN_PRIORITY);1030assert t.getContextClassLoader() == null;1031t.setDaemon(true);1032t.start();1033}10341035// destroy the token. Called if we detect that it has been removed1036@SuppressWarnings("removal")1037synchronized void uninitToken(Token token) {1038if (this.token != token) {1039// mismatch, our token must already be destroyed1040return;1041}1042destroyPoller();1043this.token = null;1044// unregister all algorithms1045AccessController.doPrivileged(new PrivilegedAction<Object>() {1046public Object run() {1047clear();1048return null;1049}1050});1051// keep polling for token insertion unless configured not to1052if (removable && !config.getDestroyTokenAfterLogout()) {1053createPoller();1054}1055}10561057private static boolean isLegacy(CK_MECHANISM_INFO mechInfo)1058throws PKCS11Exception {1059// assume full support if no mech info available1060// For vendor-specific mechanisms, often no mech info is provided1061boolean partialSupport = false;10621063if (mechInfo != null) {1064if ((mechInfo.flags & CKF_DECRYPT) != 0) {1065// non-legacy cipher mechs should support encryption1066partialSupport |= ((mechInfo.flags & CKF_ENCRYPT) == 0);1067}1068if ((mechInfo.flags & CKF_VERIFY) != 0) {1069// non-legacy signature mechs should support signing1070partialSupport |= ((mechInfo.flags & CKF_SIGN) == 0);1071}1072}1073return partialSupport;1074}10751076// test if a token is present and initialize this provider for it if so.1077// does nothing if no token is found1078// called from constructor and by poller1079private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {1080if (slotInfo == null) {1081slotInfo = p11.C_GetSlotInfo(slotID);1082}1083if (removable && (slotInfo.flags & CKF_TOKEN_PRESENT) == 0) {1084createPoller();1085return;1086}1087destroyPoller();1088boolean showInfo = config.getShowInfo();1089if (showInfo) {1090System.out.println("Slot info for slot " + slotID + ":");1091System.out.println(slotInfo);1092}1093final Token token = new Token(this);1094if (showInfo) {1095System.out.println1096("Token info for token in slot " + slotID + ":");1097System.out.println(token.tokenInfo);1098}1099long[] supportedMechanisms = p11.C_GetMechanismList(slotID);11001101// Create a map from the various Descriptors to the "most1102// preferred" mechanism that was defined during the1103// static initialization. For example, DES/CBC/PKCS5Padding1104// could be mapped to CKM_DES_CBC_PAD or CKM_DES_CBC. Prefer1105// the earliest entry. When asked for "DES/CBC/PKCS5Padding", we1106// return a CKM_DES_CBC_PAD.1107final Map<Descriptor,Integer> supportedAlgs =1108new HashMap<Descriptor,Integer>();11091110for (int i = 0; i < supportedMechanisms.length; i++) {1111long longMech = supportedMechanisms[i];1112CK_MECHANISM_INFO mechInfo = token.getMechanismInfo(longMech);1113if (showInfo) {1114System.out.println("Mechanism " +1115Functions.getMechanismName(longMech) + ":");1116System.out.println(mechInfo == null?1117(Constants.INDENT + "info n/a") :1118mechInfo);1119}1120if (!config.isEnabled(longMech)) {1121if (showInfo) {1122System.out.println("DISABLED in configuration");1123}1124continue;1125}1126if (isLegacy(mechInfo)) {1127if (showInfo) {1128System.out.println("DISABLED due to legacy");1129}1130continue;1131}11321133// we do not know of mechs with the upper 32 bits set1134if (longMech >>> 32 != 0) {1135if (showInfo) {1136System.out.println("DISABLED due to unknown mech value");1137}1138continue;1139}1140int mech = (int)longMech;1141Integer integerMech = Integer.valueOf(mech);1142List<Descriptor> ds = descriptors.get(integerMech);1143if (ds == null) {1144continue;1145}1146for (Descriptor d : ds) {1147Integer oldMech = supportedAlgs.get(d);1148if (oldMech == null) {1149supportedAlgs.put(d, integerMech);1150continue;1151}1152// See if there is something "more preferred"1153// than what we currently have in the supportedAlgs1154// map.1155int intOldMech = oldMech.intValue();1156for (int j = 0; j < d.mechanisms.length; j++) {1157int nextMech = d.mechanisms[j];1158if (mech == nextMech) {1159supportedAlgs.put(d, integerMech);1160break;1161} else if (intOldMech == nextMech) {1162break;1163}1164}1165}11661167}11681169// register algorithms in provider1170@SuppressWarnings("removal")1171var dummy = AccessController.doPrivileged(new PrivilegedAction<Object>() {1172public Object run() {1173for (Map.Entry<Descriptor,Integer> entry1174: supportedAlgs.entrySet()) {1175Descriptor d = entry.getKey();1176int mechanism = entry.getValue().intValue();1177Service s = d.service(token, mechanism);1178putService(s);1179}1180if (((token.tokenInfo.flags & CKF_RNG) != 0)1181&& config.isEnabled(PCKM_SECURERANDOM)1182&& !token.sessionManager.lowMaxSessions()) {1183// do not register SecureRandom if the token does1184// not support many sessions. if we did, we might1185// run out of sessions in the middle of a1186// nextBytes() call where we cannot fail over.1187putService(new P11Service(token, SR, "PKCS11",1188"sun.security.pkcs11.P11SecureRandom", null,1189PCKM_SECURERANDOM));1190}1191if (config.isEnabled(PCKM_KEYSTORE)) {1192putService(new P11Service(token, KS, "PKCS11",1193"sun.security.pkcs11.P11KeyStore",1194List.of("PKCS11-" + config.getName()),1195PCKM_KEYSTORE));1196}1197return null;1198}1199});12001201this.token = token;1202if (cleaner == null) {1203createCleaner();1204}1205}12061207private static final class P11Service extends Service {12081209private final Token token;12101211private final long mechanism;12121213P11Service(Token token, String type, String algorithm,1214String className, List<String> al, long mechanism) {1215super(token.provider, type, algorithm, className, al,1216type.equals(SR) ? Map.of("ThreadSafe", "true") : null);1217this.token = token;1218this.mechanism = mechanism & 0xFFFFFFFFL;1219}12201221@Override1222public Object newInstance(Object param)1223throws NoSuchAlgorithmException {1224if (token.isValid() == false) {1225throw new NoSuchAlgorithmException("Token has been removed");1226}1227try {1228return newInstance0(param);1229} catch (PKCS11Exception e) {1230throw new NoSuchAlgorithmException(e);1231}1232}12331234public Object newInstance0(Object param) throws1235PKCS11Exception, NoSuchAlgorithmException {1236String algorithm = getAlgorithm();1237String type = getType();1238if (type == MD) {1239return new P11Digest(token, algorithm, mechanism);1240} else if (type == CIP) {1241if (algorithm.startsWith("RSA")) {1242return new P11RSACipher(token, algorithm, mechanism);1243} else if (algorithm.endsWith("GCM/NoPadding") ||1244algorithm.startsWith("ChaCha20-Poly1305")) {1245return new P11AEADCipher(token, algorithm, mechanism);1246} else {1247return new P11Cipher(token, algorithm, mechanism);1248}1249} else if (type == SIG) {1250if (algorithm.indexOf("RSASSA-PSS") != -1) {1251return new P11PSSSignature(token, algorithm, mechanism);1252} else {1253return new P11Signature(token, algorithm, mechanism);1254}1255} else if (type == MAC) {1256return new P11Mac(token, algorithm, mechanism);1257} else if (type == KPG) {1258return new P11KeyPairGenerator(token, algorithm, mechanism);1259} else if (type == KA) {1260if (algorithm.equals("ECDH")) {1261return new P11ECDHKeyAgreement(token, algorithm, mechanism);1262} else {1263return new P11KeyAgreement(token, algorithm, mechanism);1264}1265} else if (type == KF) {1266return token.getKeyFactory(algorithm);1267} else if (type == SKF) {1268return new P11SecretKeyFactory(token, algorithm);1269} else if (type == KG) {1270// reference equality1271if (algorithm == "SunTlsRsaPremasterSecret") {1272return new P11TlsRsaPremasterSecretGenerator(1273token, algorithm, mechanism);1274} else if (algorithm == "SunTlsMasterSecret"1275|| algorithm == "SunTls12MasterSecret") {1276return new P11TlsMasterSecretGenerator(1277token, algorithm, mechanism);1278} else if (algorithm == "SunTlsKeyMaterial"1279|| algorithm == "SunTls12KeyMaterial") {1280return new P11TlsKeyMaterialGenerator(1281token, algorithm, mechanism);1282} else if (algorithm == "SunTlsPrf"1283|| algorithm == "SunTls12Prf") {1284return new P11TlsPrfGenerator(token, algorithm, mechanism);1285} else {1286return new P11KeyGenerator(token, algorithm, mechanism);1287}1288} else if (type == SR) {1289return token.getRandom();1290} else if (type == KS) {1291return token.getKeyStore();1292} else if (type == AGP) {1293if (algorithm == "EC") {1294return new sun.security.util.ECParameters();1295} else if (algorithm == "GCM") {1296return new sun.security.util.GCMParameters();1297} else if (algorithm == "ChaCha20-Poly1305") {1298return new ChaCha20Poly1305Parameters(); // from SunJCE1299} else {1300throw new NoSuchAlgorithmException("Unsupported algorithm: "1301+ algorithm);1302}1303} else {1304throw new NoSuchAlgorithmException("Unknown type: " + type);1305}1306}13071308public boolean supportsParameter(Object param) {1309if ((param == null) || (token.isValid() == false)) {1310return false;1311}1312if (param instanceof Key == false) {1313throw new InvalidParameterException("Parameter must be a Key");1314}1315String algorithm = getAlgorithm();1316String type = getType();1317Key key = (Key)param;1318String keyAlgorithm = key.getAlgorithm();1319// RSA signatures and cipher1320if (((type == CIP) && algorithm.startsWith("RSA"))1321|| (type == SIG) && (algorithm.indexOf("RSA") != -1)) {1322if (keyAlgorithm.equals("RSA") == false) {1323return false;1324}1325return isLocalKey(key)1326|| (key instanceof RSAPrivateKey)1327|| (key instanceof RSAPublicKey);1328}1329// EC1330if (((type == KA) && algorithm.equals("ECDH"))1331|| ((type == SIG) && algorithm.contains("ECDSA"))) {1332if (keyAlgorithm.equals("EC") == false) {1333return false;1334}1335return isLocalKey(key)1336|| (key instanceof ECPrivateKey)1337|| (key instanceof ECPublicKey);1338}1339// DSA signatures1340if ((type == SIG) && algorithm.contains("DSA") &&1341!algorithm.contains("ECDSA")) {1342if (keyAlgorithm.equals("DSA") == false) {1343return false;1344}1345return isLocalKey(key)1346|| (key instanceof DSAPrivateKey)1347|| (key instanceof DSAPublicKey);1348}1349// MACs and symmetric ciphers1350if ((type == CIP) || (type == MAC)) {1351// do not check algorithm name, mismatch is unlikely anyway1352return isLocalKey(key) || "RAW".equals(key.getFormat());1353}1354// DH key agreement1355if (type == KA) {1356if (keyAlgorithm.equals("DH") == false) {1357return false;1358}1359return isLocalKey(key)1360|| (key instanceof DHPrivateKey)1361|| (key instanceof DHPublicKey);1362}1363// should not reach here,1364// unknown engine type or algorithm1365throw new AssertionError1366("SunPKCS11 error: " + type + ", " + algorithm);1367}13681369private boolean isLocalKey(Key key) {1370return (key instanceof P11Key) && (((P11Key)key).token == token);1371}13721373public String toString() {1374return super.toString() +1375" (" + Functions.getMechanismName(mechanism) + ")";1376}13771378}13791380/**1381* Log in to this provider.1382*1383* <p> If the token expects a PIN to be supplied by the caller,1384* the <code>handler</code> implementation must support1385* a <code>PasswordCallback</code>.1386*1387* <p> To determine if the token supports a protected authentication path,1388* the CK_TOKEN_INFO flag, CKF_PROTECTED_AUTHENTICATION_PATH, is consulted.1389*1390* @param subject this parameter is ignored1391* @param handler the <code>CallbackHandler</code> used by1392* this provider to communicate with the caller1393*1394* @throws IllegalStateException if the provider requires configuration1395* and Provider.configure has not been called1396* @throws LoginException if the login operation fails1397* @throws SecurityException if the does not pass a security check for1398* <code>SecurityPermission("authProvider.<i>name</i>")</code>,1399* where <i>name</i> is the value returned by1400* this provider's <code>getName</code> method1401*/1402public void login(Subject subject, CallbackHandler handler)1403throws LoginException {14041405if (!isConfigured()) {1406throw new IllegalStateException("Configuration is required");1407}14081409// security check1410@SuppressWarnings("removal")1411SecurityManager sm = System.getSecurityManager();1412if (sm != null) {1413if (debug != null) {1414debug.println("checking login permission");1415}1416sm.checkPermission(new SecurityPermission1417("authProvider." + this.getName()));1418}14191420if (!hasValidToken()) {1421throw new LoginException("No token present");14221423}14241425// see if a login is required1426if ((token.tokenInfo.flags & CKF_LOGIN_REQUIRED) == 0) {1427if (debug != null) {1428debug.println("login operation not required for token - " +1429"ignoring login request");1430}1431return;1432}14331434// see if user already logged in14351436try {1437if (token.isLoggedInNow(null)) {1438// user already logged in1439if (debug != null) {1440debug.println("user already logged in");1441}1442return;1443}1444} catch (PKCS11Exception e) {1445// ignore - fall thru and attempt login1446}14471448// get the pin if necessary14491450char[] pin = null;1451if ((token.tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) {14521453// get password14541455CallbackHandler myHandler = getCallbackHandler(handler);1456if (myHandler == null) {1457throw new LoginException1458("no password provided, and no callback handler " +1459"available for retrieving password");1460}14611462java.text.MessageFormat form = new java.text.MessageFormat1463(ResourcesMgr.getString1464("PKCS11.Token.providerName.Password."));1465Object[] source = { getName() };14661467PasswordCallback pcall = new PasswordCallback(form.format(source),1468false);1469Callback[] callbacks = { pcall };1470try {1471myHandler.handle(callbacks);1472} catch (Exception e) {1473LoginException le = new LoginException1474("Unable to perform password callback");1475le.initCause(e);1476throw le;1477}14781479pin = pcall.getPassword();1480pcall.clearPassword();1481if (pin == null) {1482if (debug != null) {1483debug.println("caller passed NULL pin");1484}1485}1486}14871488// perform token login14891490Session session = null;1491try {1492session = token.getOpSession();14931494// pin is NULL if using CKF_PROTECTED_AUTHENTICATION_PATH1495p11.C_Login(session.id(), CKU_USER, pin);1496if (debug != null) {1497debug.println("login succeeded");1498}1499} catch (PKCS11Exception pe) {1500if (pe.getErrorCode() == CKR_USER_ALREADY_LOGGED_IN) {1501// let this one go1502if (debug != null) {1503debug.println("user already logged in");1504}1505return;1506} else if (pe.getErrorCode() == CKR_PIN_INCORRECT) {1507FailedLoginException fle = new FailedLoginException();1508fle.initCause(pe);1509throw fle;1510} else {1511LoginException le = new LoginException();1512le.initCause(pe);1513throw le;1514}1515} finally {1516token.releaseSession(session);1517if (pin != null) {1518Arrays.fill(pin, ' ');1519}1520}15211522// we do not store the PIN in the subject for now1523}15241525/**1526* Log out from this provider1527*1528* @throws IllegalStateException if the provider requires configuration1529* and Provider.configure has not been called1530* @throws LoginException if the logout operation fails1531* @throws SecurityException if the does not pass a security check for1532* <code>SecurityPermission("authProvider.<i>name</i>")</code>,1533* where <i>name</i> is the value returned by1534* this provider's <code>getName</code> method1535*/1536public void logout() throws LoginException {1537if (!isConfigured()) {1538throw new IllegalStateException("Configuration is required");1539}15401541// security check1542@SuppressWarnings("removal")1543SecurityManager sm = System.getSecurityManager();1544if (sm != null) {1545sm.checkPermission1546(new SecurityPermission("authProvider." + this.getName()));1547}15481549if (hasValidToken() == false) {1550// app may call logout for cleanup, allow1551return;1552}15531554if ((token.tokenInfo.flags & CKF_LOGIN_REQUIRED) == 0) {1555if (debug != null) {1556debug.println("logout operation not required for token - " +1557"ignoring logout request");1558}1559return;1560}15611562try {1563if (!token.isLoggedInNow(null)) {1564if (debug != null) {1565debug.println("user not logged in");1566}1567if (config.getDestroyTokenAfterLogout()) {1568token.destroy();1569}1570return;1571}1572} catch (PKCS11Exception e) {1573// ignore1574}15751576// perform token logout1577Session session = null;1578try {1579session = token.getOpSession();1580p11.C_Logout(session.id());1581if (debug != null) {1582debug.println("logout succeeded");1583}1584} catch (PKCS11Exception pe) {1585if (pe.getErrorCode() == CKR_USER_NOT_LOGGED_IN) {1586// let this one go1587if (debug != null) {1588debug.println("user not logged in");1589}1590return;1591}1592LoginException le = new LoginException();1593le.initCause(pe);1594throw le;1595} finally {1596token.releaseSession(session);1597if (config.getDestroyTokenAfterLogout()) {1598token.destroy();1599}1600}1601}16021603/**1604* Set a <code>CallbackHandler</code>1605*1606* <p> The provider uses this handler if one is not passed to the1607* <code>login</code> method. The provider also uses this handler1608* if it invokes <code>login</code> on behalf of callers.1609* In either case if a handler is not set via this method,1610* the provider queries the1611* <i>auth.login.defaultCallbackHandler</i> security property1612* for the fully qualified class name of a default handler implementation.1613* If the security property is not set,1614* the provider is assumed to have alternative means1615* for obtaining authentication information.1616*1617* @param handler a <code>CallbackHandler</code> for obtaining1618* authentication information, which may be <code>null</code>1619*1620* @throws IllegalStateException if the provider requires configuration1621* and Provider.configure has not been called1622* @throws SecurityException if the caller does not pass a1623* security check for1624* <code>SecurityPermission("authProvider.<i>name</i>")</code>,1625* where <i>name</i> is the value returned by1626* this provider's <code>getName</code> method1627*/1628public void setCallbackHandler(CallbackHandler handler) {16291630if (!isConfigured()) {1631throw new IllegalStateException("Configuration is required");1632}16331634// security check1635@SuppressWarnings("removal")1636SecurityManager sm = System.getSecurityManager();1637if (sm != null) {1638sm.checkPermission1639(new SecurityPermission("authProvider." + this.getName()));1640}16411642synchronized (LOCK_HANDLER) {1643pHandler = handler;1644}1645}16461647private CallbackHandler getCallbackHandler(CallbackHandler handler) {16481649// get default handler if necessary16501651if (handler != null) {1652return handler;1653}16541655if (debug != null) {1656debug.println("getting provider callback handler");1657}16581659synchronized (LOCK_HANDLER) {1660// see if handler was set via setCallbackHandler1661if (pHandler != null) {1662return pHandler;1663}16641665try {1666if (debug != null) {1667debug.println("getting default callback handler");1668}16691670@SuppressWarnings("removal")1671CallbackHandler myHandler = AccessController.doPrivileged1672(new PrivilegedExceptionAction<CallbackHandler>() {1673public CallbackHandler run() throws Exception {16741675String defaultHandler =1676java.security.Security.getProperty1677("auth.login.defaultCallbackHandler");16781679if (defaultHandler == null ||1680defaultHandler.length() == 0) {16811682// ok1683if (debug != null) {1684debug.println("no default handler set");1685}1686return null;1687}16881689Class<?> c = Class.forName1690(defaultHandler,1691true,1692Thread.currentThread().getContextClassLoader());1693if (!javax.security.auth.callback.CallbackHandler.class.isAssignableFrom(c)) {1694// not the right subtype1695if (debug != null) {1696debug.println("default handler " + defaultHandler +1697" is not a CallbackHandler");1698}1699return null;1700}1701@SuppressWarnings("deprecation")1702Object result = c.newInstance();1703return (CallbackHandler)result;1704}1705});1706// save it1707pHandler = myHandler;1708return myHandler;17091710} catch (PrivilegedActionException pae) {1711// ok1712if (debug != null) {1713debug.println("Unable to load default callback handler");1714pae.printStackTrace();1715}1716}1717}1718return null;1719}17201721private Object writeReplace() throws ObjectStreamException {1722return new SunPKCS11Rep(this);1723}17241725/**1726* Serialized representation of the SunPKCS11 provider.1727*/1728private static class SunPKCS11Rep implements Serializable {17291730static final long serialVersionUID = -2896606995897745419L;17311732private final String providerName;17331734private final String configName;17351736SunPKCS11Rep(SunPKCS11 provider) throws NotSerializableException {1737providerName = provider.getName();1738configName = provider.config.getFileName();1739if (Security.getProvider(providerName) != provider) {1740throw new NotSerializableException("Only SunPKCS11 providers "1741+ "installed in java.security.Security can be serialized");1742}1743}17441745private Object readResolve() throws ObjectStreamException {1746SunPKCS11 p = (SunPKCS11)Security.getProvider(providerName);1747if ((p == null) || (p.config.getFileName().equals(configName) == false)) {1748throw new NotSerializableException("Could not find "1749+ providerName + " in installed providers");1750}1751return p;1752}1753}1754}175517561757