1 /*
2 * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26 package sun.security.pkcs11;
27
28 import java.io.*;
29 import java.util.*;
30
31 import java.security.*;
32 import java.security.interfaces.*;
33
34 import javax.crypto.interfaces.*;
35
36 import javax.security.auth.Subject;
37 import javax.security.auth.login.LoginException;
38 import javax.security.auth.login.FailedLoginException;
39 import javax.security.auth.callback.Callback;
40 import javax.security.auth.callback.CallbackHandler;
41 import javax.security.auth.callback.ConfirmationCallback;
42 import javax.security.auth.callback.PasswordCallback;
43 import javax.security.auth.callback.TextOutputCallback;
44
45 import sun.security.util.Debug;
46 import sun.security.util.ResourcesMgr;
47 import static sun.security.util.SecurityConstants.PROVIDER_VER;
48
49 import sun.security.pkcs11.Secmod.*;
50
51 import sun.security.pkcs11.wrapper.*;
52 import static sun.security.pkcs11.wrapper.PKCS11Constants.*;
53
54 /**
55 * PKCS#11 provider main class.
56 *
57 * @author Andreas Sterbenz
58 * @since 1.5
59 */
60 public final class SunPKCS11 extends AuthProvider {
61
62 private static final long serialVersionUID = -1354835039035306505L;
63
64 static final Debug debug = Debug.getInstance("sunpkcs11");
65
66 // the PKCS11 object through which we make the native calls
67 final PKCS11 p11;
68
69 // configuration information
70 final Config config;
71
72 // id of the PKCS#11 slot we are using
73 final long slotID;
74
75 private CallbackHandler pHandler;
76 private final Object LOCK_HANDLER = new Object();
77
78 final boolean removable;
79
80 final Module nssModule;
81
82 final boolean nssUseSecmodTrust;
83
84 private volatile Token token;
85
86 private TokenPoller poller;
87
88 Token getToken() {
89 return token;
90 }
91
92 public SunPKCS11() {
93 super("SunPKCS11", PROVIDER_VER,
94 "Unconfigured and unusable PKCS11 provider");
95 p11 = null;
96 config = null;
97 slotID = 0;
98 pHandler = null;
99 removable = false;
100 nssModule = null;
101 nssUseSecmodTrust = false;
102 token = null;
103 poller = null;
104 }
105
106 @Override
107 public Provider configure(String configArg) throws InvalidParameterException {
108 final String newConfigName = checkNull(configArg);
109 try {
110 return AccessController.doPrivileged(new PrivilegedExceptionAction<>() {
111 @Override
112 public SunPKCS11 run() throws Exception {
113 return new SunPKCS11(new Config(newConfigName));
114 }
115 });
116 } catch (PrivilegedActionException pae) {
117 InvalidParameterException ipe =
118 new InvalidParameterException("Error configuring SunPKCS11 provider");
119 throw (InvalidParameterException) ipe.initCause(pae.getException());
120 }
121 }
122
123 @Override
124 public boolean isConfigured() {
125 return (config != null);
126 }
127
128 private static <T> T checkNull(T obj) {
129 if (obj == null) {
130 throw new NullPointerException();
131 }
132 return obj;
133 }
134
135 // Used by Secmod
136 SunPKCS11(Config c) {
137 super("SunPKCS11-" + c.getName(), PROVIDER_VER, c.getDescription());
138 this.config = c;
139
140 if (debug != null) {
141 System.out.println("SunPKCS11 loading " + config.getFileName());
142 }
143
144 String library = config.getLibrary();
145 String functionList = config.getFunctionList();
146 long slotID = config.getSlotID();
147 int slotListIndex = config.getSlotListIndex();
148
149 boolean useSecmod = config.getNssUseSecmod();
150 boolean nssUseSecmodTrust = config.getNssUseSecmodTrust();
151 Module nssModule = null;
152
153 //
154 // Initialization via Secmod. The way this works is as follows:
155 // SunPKCS11 is either in normal mode or in NSS Secmod mode.
156 // Secmod is activated by specifying one or more of the following
157 // options in the config file:
158 // nssUseSecmod, nssSecmodDirectory, nssLibrary, nssModule
159 //
160 // XXX add more explanation here
161 //
162 // If we are in Secmod mode and configured to use either the
163 // nssKeyStore or the nssTrustAnchors module, we automatically
164 // switch to using the NSS trust attributes for trusted certs
165 // (KeyStore).
166 //
167
168 if (useSecmod) {
169 // note: Config ensures library/slot/slotListIndex not specified
170 // in secmod mode.
171 Secmod secmod = Secmod.getInstance();
172 DbMode nssDbMode = config.getNssDbMode();
173 try {
174 String nssLibraryDirectory = config.getNssLibraryDirectory();
175 String nssSecmodDirectory = config.getNssSecmodDirectory();
176 boolean nssOptimizeSpace = config.getNssOptimizeSpace();
177
178 if (secmod.isInitialized()) {
179 if (nssSecmodDirectory != null) {
180 String s = secmod.getConfigDir();
181 if ((s != null) &&
182 (s.equals(nssSecmodDirectory) == false)) {
183 throw new ProviderException("Secmod directory "
184 + nssSecmodDirectory
185 + " invalid, NSS already initialized with "
186 + s);
187 }
188 }
189 if (nssLibraryDirectory != null) {
190 String s = secmod.getLibDir();
191 if ((s != null) &&
192 (s.equals(nssLibraryDirectory) == false)) {
193 throw new ProviderException("NSS library directory "
194 + nssLibraryDirectory
195 + " invalid, NSS already initialized with "
196 + s);
197 }
198 }
199 } else {
200 if (nssDbMode != DbMode.NO_DB) {
201 if (nssSecmodDirectory == null) {
202 throw new ProviderException(
203 "Secmod not initialized and "
204 + "nssSecmodDirectory not specified");
205 }
206 } else {
207 if (nssSecmodDirectory != null) {
208 throw new ProviderException(
209 "nssSecmodDirectory must not be "
210 + "specified in noDb mode");
211 }
212 }
213 secmod.initialize(nssDbMode, nssSecmodDirectory,
214 nssLibraryDirectory, nssOptimizeSpace);
215 }
216 } catch (IOException e) {
217 // XXX which exception to throw
218 throw new ProviderException("Could not initialize NSS", e);
219 }
220 List<Module> modules = secmod.getModules();
221 if (config.getShowInfo()) {
222 System.out.println("NSS modules: " + modules);
223 }
224
225 String moduleName = config.getNssModule();
226 if (moduleName == null) {
227 nssModule = secmod.getModule(ModuleType.FIPS);
228 if (nssModule != null) {
229 moduleName = "fips";
230 } else {
231 moduleName = (nssDbMode == DbMode.NO_DB) ?
232 "crypto" : "keystore";
233 }
234 }
235 if (moduleName.equals("fips")) {
236 nssModule = secmod.getModule(ModuleType.FIPS);
237 nssUseSecmodTrust = true;
238 functionList = "FC_GetFunctionList";
239 } else if (moduleName.equals("keystore")) {
240 nssModule = secmod.getModule(ModuleType.KEYSTORE);
241 nssUseSecmodTrust = true;
242 } else if (moduleName.equals("crypto")) {
243 nssModule = secmod.getModule(ModuleType.CRYPTO);
244 } else if (moduleName.equals("trustanchors")) {
245 // XXX should the option be called trustanchor or trustanchors??
246 nssModule = secmod.getModule(ModuleType.TRUSTANCHOR);
247 nssUseSecmodTrust = true;
248 } else if (moduleName.startsWith("external-")) {
249 int moduleIndex;
250 try {
251 moduleIndex = Integer.parseInt
252 (moduleName.substring("external-".length()));
253 } catch (NumberFormatException e) {
254 moduleIndex = -1;
255 }
256 if (moduleIndex < 1) {
257 throw new ProviderException
258 ("Invalid external module: " + moduleName);
259 }
260 int k = 0;
261 for (Module module : modules) {
262 if (module.getType() == ModuleType.EXTERNAL) {
263 if (++k == moduleIndex) {
264 nssModule = module;
265 break;
266 }
267 }
268 }
269 if (nssModule == null) {
270 throw new ProviderException("Invalid module " + moduleName
271 + ": only " + k + " external NSS modules available");
272 }
273 } else {
274 throw new ProviderException(
275 "Unknown NSS module: " + moduleName);
276 }
277 if (nssModule == null) {
278 throw new ProviderException(
279 "NSS module not available: " + moduleName);
280 }
281 if (nssModule.hasInitializedProvider()) {
282 throw new ProviderException("Secmod module already configured");
283 }
284 library = nssModule.libraryName;
285 slotListIndex = nssModule.slot;
286 }
287 this.nssUseSecmodTrust = nssUseSecmodTrust;
288 this.nssModule = nssModule;
289
290 File libraryFile = new File(library);
291 // if the filename is a simple filename without path
292 // (e.g. "libpkcs11.so"), it may refer to a library somewhere on the
293 // OS library search path. Omit the test for file existance as that
294 // only looks in the current directory.
295 if (libraryFile.getName().equals(library) == false) {
296 if (new File(library).isFile() == false) {
297 String msg = "Library " + library + " does not exist";
298 if (config.getHandleStartupErrors() == Config.ERR_HALT) {
299 throw new ProviderException(msg);
300 } else {
301 throw new UnsupportedOperationException(msg);
302 }
303 }
304 }
305
306 try {
307 if (debug != null) {
308 debug.println("Initializing PKCS#11 library " + library);
309 }
310 CK_C_INITIALIZE_ARGS initArgs = new CK_C_INITIALIZE_ARGS();
311 String nssArgs = config.getNssArgs();
312 if (nssArgs != null) {
313 initArgs.pReserved = nssArgs;
314 }
315 // request multithreaded access first
316 initArgs.flags = CKF_OS_LOCKING_OK;
317 PKCS11 tmpPKCS11;
318 try {
319 tmpPKCS11 = PKCS11.getInstance(
320 library, functionList, initArgs,
321 config.getOmitInitialize());
322 } catch (PKCS11Exception e) {
323 if (debug != null) {
324 debug.println("Multi-threaded initialization failed: " + e);
325 }
326 if (config.getAllowSingleThreadedModules() == false) {
327 throw e;
328 }
329 // fall back to single threaded access
330 if (nssArgs == null) {
331 // if possible, use null initArgs for better compatibility
332 initArgs = null;
333 } else {
334 initArgs.flags = 0;
335 }
336 tmpPKCS11 = PKCS11.getInstance(library,
337 functionList, initArgs, config.getOmitInitialize());
338 }
339 p11 = tmpPKCS11;
340
341 CK_INFO p11Info = p11.C_GetInfo();
342 if (p11Info.cryptokiVersion.major < 2) {
343 throw new ProviderException("Only PKCS#11 v2.0 and later "
344 + "supported, library version is v" + p11Info.cryptokiVersion);
345 }
346 boolean showInfo = config.getShowInfo();
347 if (showInfo) {
348 System.out.println("Information for provider " + getName());
349 System.out.println("Library info:");
350 System.out.println(p11Info);
351 }
352
353 if ((slotID < 0) || showInfo) {
354 long[] slots = p11.C_GetSlotList(false);
355 if (showInfo) {
356 System.out.println("All slots: " + toString(slots));
357 slots = p11.C_GetSlotList(true);
358 System.out.println("Slots with tokens: " + toString(slots));
359 }
360 if (slotID < 0) {
361 if ((slotListIndex < 0)
362 || (slotListIndex >= slots.length)) {
363 throw new ProviderException("slotListIndex is "
364 + slotListIndex
365 + " but token only has " + slots.length + " slots");
366 }
367 slotID = slots[slotListIndex];
368 }
369 }
370 this.slotID = slotID;
371 CK_SLOT_INFO slotInfo = p11.C_GetSlotInfo(slotID);
372 removable = (slotInfo.flags & CKF_REMOVABLE_DEVICE) != 0;
373 initToken(slotInfo);
374 if (nssModule != null) {
375 nssModule.setProvider(this);
376 }
377 } catch (Exception e) {
378 if (config.getHandleStartupErrors() == Config.ERR_IGNORE_ALL) {
379 throw new UnsupportedOperationException
380 ("Initialization failed", e);
381 } else {
382 throw new ProviderException
383 ("Initialization failed", e);
384 }
385 }
386 }
387
388 private static String toString(long[] longs) {
389 if (longs.length == 0) {
390 return "(none)";
391 }
392 StringBuilder sb = new StringBuilder();
393 sb.append(longs[0]);
394 for (int i = 1; i < longs.length; i++) {
395 sb.append(", ");
396 sb.append(longs[i]);
397 }
398 return sb.toString();
399 }
400
401 public boolean equals(Object obj) {
402 return this == obj;
403 }
404
405 public int hashCode() {
406 return System.identityHashCode(this);
407 }
408
409 private static String[] s(String ...aliases) {
410 return aliases;
411 }
412
413 private static final class Descriptor {
414 final String type;
415 final String algorithm;
416 final String className;
417 final String[] aliases;
418 final int[] mechanisms;
419
420 private Descriptor(String type, String algorithm, String className,
421 String[] aliases, int[] mechanisms) {
422 this.type = type;
423 this.algorithm = algorithm;
424 this.className = className;
425 this.aliases = aliases;
426 this.mechanisms = mechanisms;
427 }
428 private P11Service service(Token token, int mechanism) {
429 return new P11Service
430 (token, type, algorithm, className, aliases, mechanism);
431 }
432 public String toString() {
433 return type + "." + algorithm;
434 }
435 }
436
437 // Map from mechanism to List of Descriptors that should be
438 // registered if the mechanism is supported
439 private final static Map<Integer,List<Descriptor>> descriptors =
440 new HashMap<Integer,List<Descriptor>>();
441
442 private static int[] m(long m1) {
443 return new int[] {(int)m1};
444 }
445
446 private static int[] m(long m1, long m2) {
447 return new int[] {(int)m1, (int)m2};
448 }
449
450 private static int[] m(long m1, long m2, long m3) {
451 return new int[] {(int)m1, (int)m2, (int)m3};
452 }
453
454 private static int[] m(long m1, long m2, long m3, long m4) {
455 return new int[] {(int)m1, (int)m2, (int)m3, (int)m4};
456 }
457
458 private static void d(String type, String algorithm, String className,
459 int[] m) {
460 register(new Descriptor(type, algorithm, className, null, m));
461 }
462
463 private static void d(String type, String algorithm, String className,
464 String[] aliases, int[] m) {
465 register(new Descriptor(type, algorithm, className, aliases, m));
466 }
467
468 private static void register(Descriptor d) {
469 for (int i = 0; i < d.mechanisms.length; i++) {
470 int m = d.mechanisms[i];
471 Integer key = Integer.valueOf(m);
472 List<Descriptor> list = descriptors.get(key);
473 if (list == null) {
474 list = new ArrayList<Descriptor>();
475 descriptors.put(key, list);
476 }
477 list.add(d);
478 }
479 }
480
481 private final static String MD = "MessageDigest";
482
483 private final static String SIG = "Signature";
484
485 private final static String KPG = "KeyPairGenerator";
486
487 private final static String KG = "KeyGenerator";
488
489 private final static String AGP = "AlgorithmParameters";
490
491 private final static String KF = "KeyFactory";
492
493 private final static String SKF = "SecretKeyFactory";
494
495 private final static String CIP = "Cipher";
496
497 private final static String MAC = "Mac";
498
499 private final static String KA = "KeyAgreement";
500
501 private final static String KS = "KeyStore";
502
503 private final static String SR = "SecureRandom";
504
505 static {
506 // names of all the implementation classes
507 // use local variables, only used here
508 String P11Digest = "sun.security.pkcs11.P11Digest";
509 String P11MAC = "sun.security.pkcs11.P11MAC";
510 String P11KeyPairGenerator = "sun.security.pkcs11.P11KeyPairGenerator";
511 String P11KeyGenerator = "sun.security.pkcs11.P11KeyGenerator";
512 String P11RSAKeyFactory = "sun.security.pkcs11.P11RSAKeyFactory";
513 String P11DSAKeyFactory = "sun.security.pkcs11.P11DSAKeyFactory";
514 String P11DHKeyFactory = "sun.security.pkcs11.P11DHKeyFactory";
515 String P11KeyAgreement = "sun.security.pkcs11.P11KeyAgreement";
516 String P11SecretKeyFactory = "sun.security.pkcs11.P11SecretKeyFactory";
517 String P11Cipher = "sun.security.pkcs11.P11Cipher";
518 String P11RSACipher = "sun.security.pkcs11.P11RSACipher";
519 String P11Signature = "sun.security.pkcs11.P11Signature";
520
521 // XXX register all aliases
522
523 d(MD, "MD2", P11Digest,
524 m(CKM_MD2));
525 d(MD, "MD5", P11Digest,
526 m(CKM_MD5));
527 d(MD, "SHA1", P11Digest,
528 s("SHA", "SHA-1", "1.3.14.3.2.26", "OID.1.3.14.3.2.26"),
529 m(CKM_SHA_1));
530
531 d(MD, "SHA-224", P11Digest,
532 s("2.16.840.1.101.3.4.2.4", "OID.2.16.840.1.101.3.4.2.4"),
533 m(CKM_SHA224));
534 d(MD, "SHA-256", P11Digest,
535 s("2.16.840.1.101.3.4.2.1", "OID.2.16.840.1.101.3.4.2.1"),
536 m(CKM_SHA256));
537 d(MD, "SHA-384", P11Digest,
538 s("2.16.840.1.101.3.4.2.2", "OID.2.16.840.1.101.3.4.2.2"),
539 m(CKM_SHA384));
540 d(MD, "SHA-512", P11Digest,
541 s("2.16.840.1.101.3.4.2.3", "OID.2.16.840.1.101.3.4.2.3"),
542 m(CKM_SHA512));
543
544 d(MAC, "HmacMD5", P11MAC,
545 m(CKM_MD5_HMAC));
546 d(MAC, "HmacSHA1", P11MAC,
547 s("1.2.840.113549.2.7", "OID.1.2.840.113549.2.7"),
548 m(CKM_SHA_1_HMAC));
549 d(MAC, "HmacSHA224", P11MAC,
550 s("1.2.840.113549.2.8", "OID.1.2.840.113549.2.8"),
551 m(CKM_SHA224_HMAC));
552 d(MAC, "HmacSHA256", P11MAC,
553 s("1.2.840.113549.2.9", "OID.1.2.840.113549.2.9"),
554 m(CKM_SHA256_HMAC));
555 d(MAC, "HmacSHA384", P11MAC,
556 s("1.2.840.113549.2.10", "OID.1.2.840.113549.2.10"),
557 m(CKM_SHA384_HMAC));
558 d(MAC, "HmacSHA512", P11MAC,
559 s("1.2.840.113549.2.11", "OID.1.2.840.113549.2.11"),
560 m(CKM_SHA512_HMAC));
561 d(MAC, "SslMacMD5", P11MAC,
562 m(CKM_SSL3_MD5_MAC));
563 d(MAC, "SslMacSHA1", P11MAC,
564 m(CKM_SSL3_SHA1_MAC));
565
566 d(KPG, "RSA", P11KeyPairGenerator,
567 m(CKM_RSA_PKCS_KEY_PAIR_GEN));
568 d(KPG, "DSA", P11KeyPairGenerator,
569 s("1.3.14.3.2.12", "1.2.840.10040.4.1", "OID.1.2.840.10040.4.1"),
570 m(CKM_DSA_KEY_PAIR_GEN));
571 d(KPG, "DH", P11KeyPairGenerator, s("DiffieHellman"),
572 m(CKM_DH_PKCS_KEY_PAIR_GEN));
573 d(KPG, "EC", P11KeyPairGenerator,
574 m(CKM_EC_KEY_PAIR_GEN));
575
576 d(KG, "ARCFOUR", P11KeyGenerator, s("RC4"),
577 m(CKM_RC4_KEY_GEN));
578 d(KG, "DES", P11KeyGenerator,
579 m(CKM_DES_KEY_GEN));
580 d(KG, "DESede", P11KeyGenerator,
581 m(CKM_DES3_KEY_GEN, CKM_DES2_KEY_GEN));
582 d(KG, "AES", P11KeyGenerator,
583 m(CKM_AES_KEY_GEN));
584 d(KG, "Blowfish", P11KeyGenerator,
585 m(CKM_BLOWFISH_KEY_GEN));
586
587 // register (Secret)KeyFactories if there are any mechanisms
588 // for a particular algorithm that we support
589 d(KF, "RSA", P11RSAKeyFactory,
590 m(CKM_RSA_PKCS_KEY_PAIR_GEN, CKM_RSA_PKCS, CKM_RSA_X_509));
591 d(KF, "DSA", P11DSAKeyFactory,
592 s("1.3.14.3.2.12", "1.2.840.10040.4.1", "OID.1.2.840.10040.4.1"),
593 m(CKM_DSA_KEY_PAIR_GEN, CKM_DSA, CKM_DSA_SHA1));
594 d(KF, "DH", P11DHKeyFactory, s("DiffieHellman"),
595 m(CKM_DH_PKCS_KEY_PAIR_GEN, CKM_DH_PKCS_DERIVE));
596 d(KF, "EC", P11DHKeyFactory,
597 m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,
598 CKM_ECDSA, CKM_ECDSA_SHA1));
599
600 // AlgorithmParameters for EC.
601 // Only needed until we have an EC implementation in the SUN provider.
602 d(AGP, "EC", "sun.security.util.ECParameters",
603 s("1.2.840.10045.2.1"),
604 m(CKM_EC_KEY_PAIR_GEN, CKM_ECDH1_DERIVE,
605 CKM_ECDSA, CKM_ECDSA_SHA1));
606
607 d(KA, "DH", P11KeyAgreement, s("DiffieHellman"),
608 m(CKM_DH_PKCS_DERIVE));
609 d(KA, "ECDH", "sun.security.pkcs11.P11ECDHKeyAgreement",
610 m(CKM_ECDH1_DERIVE));
611
612 d(SKF, "ARCFOUR", P11SecretKeyFactory, s("RC4"),
613 m(CKM_RC4));
614 d(SKF, "DES", P11SecretKeyFactory,
615 m(CKM_DES_CBC));
616 d(SKF, "DESede", P11SecretKeyFactory,
617 m(CKM_DES3_CBC));
618 d(SKF, "AES", P11SecretKeyFactory,
619 s("2.16.840.1.101.3.4.1", "OID.2.16.840.1.101.3.4.1"),
620 m(CKM_AES_CBC));
621 d(SKF, "Blowfish", P11SecretKeyFactory,
622 m(CKM_BLOWFISH_CBC));
623
624 // XXX attributes for Ciphers (supported modes, padding)
625 d(CIP, "ARCFOUR", P11Cipher, s("RC4"),
626 m(CKM_RC4));
627 d(CIP, "DES/CBC/NoPadding", P11Cipher,
628 m(CKM_DES_CBC));
629 d(CIP, "DES/CBC/PKCS5Padding", P11Cipher,
630 m(CKM_DES_CBC_PAD, CKM_DES_CBC));
631 d(CIP, "DES/ECB/NoPadding", P11Cipher,
632 m(CKM_DES_ECB));
633 d(CIP, "DES/ECB/PKCS5Padding", P11Cipher, s("DES"),
634 m(CKM_DES_ECB));
635
636 d(CIP, "DESede/CBC/NoPadding", P11Cipher,
637 m(CKM_DES3_CBC));
638 d(CIP, "DESede/CBC/PKCS5Padding", P11Cipher,
639 m(CKM_DES3_CBC_PAD, CKM_DES3_CBC));
640 d(CIP, "DESede/ECB/NoPadding", P11Cipher,
641 m(CKM_DES3_ECB));
642 d(CIP, "DESede/ECB/PKCS5Padding", P11Cipher, s("DESede"),
643 m(CKM_DES3_ECB));
644 d(CIP, "AES/CBC/NoPadding", P11Cipher,
645 m(CKM_AES_CBC));
646 d(CIP, "AES_128/CBC/NoPadding", P11Cipher,
647 s("2.16.840.1.101.3.4.1.2", "OID.2.16.840.1.101.3.4.1.2"),
648 m(CKM_AES_CBC));
649 d(CIP, "AES_192/CBC/NoPadding", P11Cipher,
650 s("2.16.840.1.101.3.4.1.22", "OID.2.16.840.1.101.3.4.1.22"),
651 m(CKM_AES_CBC));
652 d(CIP, "AES_256/CBC/NoPadding", P11Cipher,
653 s("2.16.840.1.101.3.4.1.42", "OID.2.16.840.1.101.3.4.1.42"),
654 m(CKM_AES_CBC));
655 d(CIP, "AES/CBC/PKCS5Padding", P11Cipher,
656 m(CKM_AES_CBC_PAD, CKM_AES_CBC));
657 d(CIP, "AES/ECB/NoPadding", P11Cipher,
658 m(CKM_AES_ECB));
659 d(CIP, "AES_128/ECB/NoPadding", P11Cipher,
660 s("2.16.840.1.101.3.4.1.1", "OID.2.16.840.1.101.3.4.1.1"),
661 m(CKM_AES_ECB));
662 d(CIP, "AES_192/ECB/NoPadding", P11Cipher,
663 s("2.16.840.1.101.3.4.1.21", "OID.2.16.840.1.101.3.4.1.21"),
664 m(CKM_AES_ECB));
665 d(CIP, "AES_256/ECB/NoPadding", P11Cipher,
666 s("2.16.840.1.101.3.4.1.41", "OID.2.16.840.1.101.3.4.1.41"),
667 m(CKM_AES_ECB));
668 d(CIP, "AES/ECB/PKCS5Padding", P11Cipher, s("AES"),
669 m(CKM_AES_ECB));
670 d(CIP, "AES/CTR/NoPadding", P11Cipher,
671 m(CKM_AES_CTR));
672 d(CIP, "Blowfish/CBC/NoPadding", P11Cipher,
673 m(CKM_BLOWFISH_CBC));
674 d(CIP, "Blowfish/CBC/PKCS5Padding", P11Cipher,
675 m(CKM_BLOWFISH_CBC));
676
677 // XXX RSA_X_509, RSA_OAEP not yet supported
678 d(CIP, "RSA/ECB/PKCS1Padding", P11RSACipher, s("RSA"),
679 m(CKM_RSA_PKCS));
680 d(CIP, "RSA/ECB/NoPadding", P11RSACipher,
681 m(CKM_RSA_X_509));
682
683 d(SIG, "RawDSA", P11Signature, s("NONEwithDSA"),
684 m(CKM_DSA));
685 d(SIG, "DSA", P11Signature,
686 s("SHA1withDSA", "1.3.14.3.2.13", "1.3.14.3.2.27",
687 "1.2.840.10040.4.3", "OID.1.2.840.10040.4.3"),
688 m(CKM_DSA_SHA1, CKM_DSA));
689 d(SIG, "RawDSAinP1363Format", P11Signature,
690 s("NONEwithDSAinP1363Format"),
691 m(CKM_DSA));
692 d(SIG, "DSAinP1363Format", P11Signature,
693 s("SHA1withDSAinP1363Format"),
694 m(CKM_DSA_SHA1, CKM_DSA));
695 d(SIG, "NONEwithECDSA", P11Signature,
696 m(CKM_ECDSA));
697 d(SIG, "SHA1withECDSA", P11Signature,
698 s("ECDSA", "1.2.840.10045.4.1", "OID.1.2.840.10045.4.1"),
699 m(CKM_ECDSA_SHA1, CKM_ECDSA));
700 d(SIG, "SHA224withECDSA", P11Signature,
701 s("1.2.840.10045.4.3.1", "OID.1.2.840.10045.4.3.1"),
702 m(CKM_ECDSA));
703 d(SIG, "SHA256withECDSA", P11Signature,
704 s("1.2.840.10045.4.3.2", "OID.1.2.840.10045.4.3.2"),
705 m(CKM_ECDSA));
706 d(SIG, "SHA384withECDSA", P11Signature,
707 s("1.2.840.10045.4.3.3", "OID.1.2.840.10045.4.3.3"),
708 m(CKM_ECDSA));
709 d(SIG, "SHA512withECDSA", P11Signature,
710 s("1.2.840.10045.4.3.4", "OID.1.2.840.10045.4.3.4"),
711 m(CKM_ECDSA));
712 d(SIG, "NONEwithECDSAinP1363Format", P11Signature,
713 m(CKM_ECDSA));
714 d(SIG, "SHA1withECDSAinP1363Format", P11Signature,
715 m(CKM_ECDSA_SHA1, CKM_ECDSA));
716 d(SIG, "SHA224withECDSAinP1363Format", P11Signature,
717 m(CKM_ECDSA));
718 d(SIG, "SHA256withECDSAinP1363Format", P11Signature,
719 m(CKM_ECDSA));
720 d(SIG, "SHA384withECDSAinP1363Format", P11Signature,
721 m(CKM_ECDSA));
722 d(SIG, "SHA512withECDSAinP1363Format", P11Signature,
723 m(CKM_ECDSA));
724 d(SIG, "MD2withRSA", P11Signature,
725 s("1.2.840.113549.1.1.2", "OID.1.2.840.113549.1.1.2"),
726 m(CKM_MD2_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
727 d(SIG, "MD5withRSA", P11Signature,
728 s("1.2.840.113549.1.1.4", "OID.1.2.840.113549.1.1.4"),
729 m(CKM_MD5_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
730 d(SIG, "SHA1withRSA", P11Signature,
731 s("1.2.840.113549.1.1.5", "OID.1.2.840.113549.1.1.5",
732 "1.3.14.3.2.29"),
733 m(CKM_SHA1_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
734 d(SIG, "SHA224withRSA", P11Signature,
735 s("1.2.840.113549.1.1.14", "OID.1.2.840.113549.1.1.14"),
736 m(CKM_SHA224_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
737 d(SIG, "SHA256withRSA", P11Signature,
738 s("1.2.840.113549.1.1.11", "OID.1.2.840.113549.1.1.11"),
739 m(CKM_SHA256_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
740 d(SIG, "SHA384withRSA", P11Signature,
741 s("1.2.840.113549.1.1.12", "OID.1.2.840.113549.1.1.12"),
742 m(CKM_SHA384_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
743 d(SIG, "SHA512withRSA", P11Signature,
744 s("1.2.840.113549.1.1.13", "OID.1.2.840.113549.1.1.13"),
745 m(CKM_SHA512_RSA_PKCS, CKM_RSA_PKCS, CKM_RSA_X_509));
746
747 /*
748 * TLS 1.2 uses a different hash algorithm than 1.0/1.1 for the
749 * PRF calculations. As of 2010, there is no PKCS11-level
750 * support for TLS 1.2 PRF calculations, and no known OS's have
751 * an internal variant we could use. Therefore for TLS 1.2, we
752 * are updating JSSE to request different provider algorithms
753 * (e.g. "SunTls12Prf"), and currently only SunJCE has these
754 * TLS 1.2 algorithms.
755 *
756 * If we reused the names such as "SunTlsPrf", the PKCS11
757 * providers would need be updated to fail correctly when
758 * presented with the wrong version number (via
759 * Provider.Service.supportsParameters()), and we would also
760 * need to add the appropriate supportsParamters() checks into
761 * KeyGenerators (not currently there).
762 *
763 * In the future, if PKCS11 support is added, we will restructure
764 * this.
765 */
766 d(KG, "SunTlsRsaPremasterSecret",
767 "sun.security.pkcs11.P11TlsRsaPremasterSecretGenerator",
768 m(CKM_SSL3_PRE_MASTER_KEY_GEN, CKM_TLS_PRE_MASTER_KEY_GEN));
769 d(KG, "SunTlsMasterSecret",
770 "sun.security.pkcs11.P11TlsMasterSecretGenerator",
771 m(CKM_SSL3_MASTER_KEY_DERIVE, CKM_TLS_MASTER_KEY_DERIVE,
772 CKM_SSL3_MASTER_KEY_DERIVE_DH,
773 CKM_TLS_MASTER_KEY_DERIVE_DH));
774 d(KG, "SunTlsKeyMaterial",
775 "sun.security.pkcs11.P11TlsKeyMaterialGenerator",
776 m(CKM_SSL3_KEY_AND_MAC_DERIVE, CKM_TLS_KEY_AND_MAC_DERIVE));
777 d(KG, "SunTlsPrf", "sun.security.pkcs11.P11TlsPrfGenerator",
778 m(CKM_TLS_PRF, CKM_NSS_TLS_PRF_GENERAL));
779 }
780
781 // background thread that periodically checks for token insertion
782 // if no token is present. We need to do that in a separate thread because
783 // the insertion check may block for quite a long time on some tokens.
784 private static class TokenPoller implements Runnable {
785 private final SunPKCS11 provider;
786 private volatile boolean enabled;
787 private TokenPoller(SunPKCS11 provider) {
788 this.provider = provider;
789 enabled = true;
790 }
791 public void run() {
792 int interval = provider.config.getInsertionCheckInterval();
793 while (enabled) {
794 try {
795 Thread.sleep(interval);
796 } catch (InterruptedException e) {
797 break;
798 }
799 if (enabled == false) {
800 break;
801 }
802 try {
803 provider.initToken(null);
804 } catch (PKCS11Exception e) {
805 // ignore
806 }
807 }
808 }
809 void disable() {
810 enabled = false;
811 }
812 }
813
814 // create the poller thread, if not already active
815 private void createPoller() {
816 if (poller != null) {
817 return;
818 }
819 final TokenPoller poller = new TokenPoller(this);
820 Thread t = new Thread(null, poller, "Poller " + getName(), 0, false);
821 t.setContextClassLoader(null);
822 t.setDaemon(true);
823 t.setPriority(Thread.MIN_PRIORITY);
824 t.start();
825 this.poller = poller;
826 }
827
828 // destroy the poller thread, if active
829 private void destroyPoller() {
830 if (poller != null) {
831 poller.disable();
832 poller = null;
833 }
834 }
835
836 private boolean hasValidToken() {
837 /* Commented out to work with Solaris softtoken impl which
838 returns 0-value flags, e.g. both REMOVABLE_DEVICE and
839 TOKEN_PRESENT are false, when it can't access the token.
840 if (removable == false) {
841 return true;
842 }
843 */
844 Token token = this.token;
845 return (token != null) && token.isValid();
846 }
847
848 // destroy the token. Called if we detect that it has been removed
849 synchronized void uninitToken(Token token) {
850 if (this.token != token) {
851 // mismatch, our token must already be destroyed
852 return;
853 }
854 destroyPoller();
855 this.token = null;
856 // unregister all algorithms
857 AccessController.doPrivileged(new PrivilegedAction<Object>() {
858 public Object run() {
859 clear();
860 return null;
861 }
862 });
863 createPoller();
864 }
865
866 // test if a token is present and initialize this provider for it if so.
867 // does nothing if no token is found
868 // called from constructor and by poller
869 private void initToken(CK_SLOT_INFO slotInfo) throws PKCS11Exception {
870 if (slotInfo == null) {
871 slotInfo = p11.C_GetSlotInfo(slotID);
872 }
873 if (removable && (slotInfo.flags & CKF_TOKEN_PRESENT) == 0) {
874 createPoller();
875 return;
876 }
877 destroyPoller();
878 boolean showInfo = config.getShowInfo();
879 if (showInfo) {
880 System.out.println("Slot info for slot " + slotID + ":");
881 System.out.println(slotInfo);
882 }
883 final Token token = new Token(this);
884 if (showInfo) {
885 System.out.println
886 ("Token info for token in slot " + slotID + ":");
887 System.out.println(token.tokenInfo);
888 }
889 long[] supportedMechanisms = p11.C_GetMechanismList(slotID);
890
891 // Create a map from the various Descriptors to the "most
892 // preferred" mechanism that was defined during the
893 // static initialization. For example, DES/CBC/PKCS5Padding
894 // could be mapped to CKM_DES_CBC_PAD or CKM_DES_CBC. Prefer
895 // the earliest entry. When asked for "DES/CBC/PKCS5Padding", we
896 // return a CKM_DES_CBC_PAD.
897 final Map<Descriptor,Integer> supportedAlgs =
898 new HashMap<Descriptor,Integer>();
899 for (int i = 0; i < supportedMechanisms.length; i++) {
900 long longMech = supportedMechanisms[i];
901 boolean isEnabled = config.isEnabled(longMech);
902 if (showInfo) {
903 CK_MECHANISM_INFO mechInfo =
904 p11.C_GetMechanismInfo(slotID, longMech);
905 System.out.println("Mechanism " +
906 Functions.getMechanismName(longMech) + ":");
907 if (isEnabled == false) {
908 System.out.println("DISABLED in configuration");
909 }
910 System.out.println(mechInfo);
911 }
912 if (isEnabled == false) {
913 continue;
914 }
915 // we do not know of mechs with the upper 32 bits set
916 if (longMech >>> 32 != 0) {
917 continue;
918 }
919 int mech = (int)longMech;
920 Integer integerMech = Integer.valueOf(mech);
921 List<Descriptor> ds = descriptors.get(integerMech);
922 if (ds == null) {
923 continue;
924 }
925 for (Descriptor d : ds) {
926 Integer oldMech = supportedAlgs.get(d);
927 if (oldMech == null) {
928 supportedAlgs.put(d, integerMech);
929 continue;
930 }
931 // See if there is something "more preferred"
932 // than what we currently have in the supportedAlgs
933 // map.
934 int intOldMech = oldMech.intValue();
935 for (int j = 0; j < d.mechanisms.length; j++) {
936 int nextMech = d.mechanisms[j];
937 if (mech == nextMech) {
938 supportedAlgs.put(d, integerMech);
939 break;
940 } else if (intOldMech == nextMech) {
941 break;
942 }
943 }
944 }
945
946 }
947
948 // register algorithms in provider
949 AccessController.doPrivileged(new PrivilegedAction<Object>() {
950 public Object run() {
951 for (Map.Entry<Descriptor,Integer> entry
952 : supportedAlgs.entrySet()) {
953 Descriptor d = entry.getKey();
954 int mechanism = entry.getValue().intValue();
955 Service s = d.service(token, mechanism);
956 putService(s);
957 }
958 if (((token.tokenInfo.flags & CKF_RNG) != 0)
959 && config.isEnabled(PCKM_SECURERANDOM)
960 && !token.sessionManager.lowMaxSessions()) {
961 // do not register SecureRandom if the token does
962 // not support many sessions. if we did, we might
963 // run out of sessions in the middle of a
964 // nextBytes() call where we cannot fail over.
965 putService(new P11Service(token, SR, "PKCS11",
966 "sun.security.pkcs11.P11SecureRandom", null,
967 PCKM_SECURERANDOM));
968 }
969 if (config.isEnabled(PCKM_KEYSTORE)) {
970 putService(new P11Service(token, KS, "PKCS11",
971 "sun.security.pkcs11.P11KeyStore",
972 s("PKCS11-" + config.getName()),
973 PCKM_KEYSTORE));
974 }
975 return null;
976 }
977 });
978
979 this.token = token;
980 }
981
982 private static final class P11Service extends Service {
983
984 private final Token token;
985
986 private final long mechanism;
987
988 P11Service(Token token, String type, String algorithm,
989 String className, String[] al, long mechanism) {
990 super(token.provider, type, algorithm, className, toList(al),
991 type.equals(SR) ? Map.of("ThreadSafe", "true") : null);
992 this.token = token;
993 this.mechanism = mechanism & 0xFFFFFFFFL;
994 }
995
996 private static List<String> toList(String[] aliases) {
997 return (aliases == null) ? null : Arrays.asList(aliases);
998 }
999
1000 public Object newInstance(Object param)
1001 throws NoSuchAlgorithmException {
1002 if (token.isValid() == false) {
1003 throw new NoSuchAlgorithmException("Token has been removed");
1004 }
1005 try {
1006 return newInstance0(param);
1007 } catch (PKCS11Exception e) {
1008 throw new NoSuchAlgorithmException(e);
1009 }
1010 }
1011
1012 public Object newInstance0(Object param) throws
1013 PKCS11Exception, NoSuchAlgorithmException {
1014 String algorithm = getAlgorithm();
1015 String type = getType();
1016 if (type == MD) {
1017 return new P11Digest(token, algorithm, mechanism);
1018 } else if (type == CIP) {
1019 if (algorithm.startsWith("RSA")) {
1020 return new P11RSACipher(token, algorithm, mechanism);
1021 } else {
1022 return new P11Cipher(token, algorithm, mechanism);
1023 }
1024 } else if (type == SIG) {
1025 return new P11Signature(token, algorithm, mechanism);
1026 } else if (type == MAC) {
1027 return new P11Mac(token, algorithm, mechanism);
1028 } else if (type == KPG) {
1029 return new P11KeyPairGenerator(token, algorithm, mechanism);
1030 } else if (type == KA) {
1031 if (algorithm.equals("ECDH")) {
1032 return new P11ECDHKeyAgreement(token, algorithm, mechanism);
1033 } else {
1034 return new P11KeyAgreement(token, algorithm, mechanism);
1035 }
1036 } else if (type == KF) {
1037 return token.getKeyFactory(algorithm);
1038 } else if (type == SKF) {
1039 return new P11SecretKeyFactory(token, algorithm);
1040 } else if (type == KG) {
1041 // reference equality
1042 if (algorithm == "SunTlsRsaPremasterSecret") {
1043 return new P11TlsRsaPremasterSecretGenerator(
1044 token, algorithm, mechanism);
1045 } else if (algorithm == "SunTlsMasterSecret") {
1046 return new P11TlsMasterSecretGenerator(
1047 token, algorithm, mechanism);
1048 } else if (algorithm == "SunTlsKeyMaterial") {
1049 return new P11TlsKeyMaterialGenerator(
1050 token, algorithm, mechanism);
1051 } else if (algorithm == "SunTlsPrf") {
1052 return new P11TlsPrfGenerator(token, algorithm, mechanism);
1053 } else {
1054 return new P11KeyGenerator(token, algorithm, mechanism);
1055 }
1056 } else if (type == SR) {
1057 return token.getRandom();
1058 } else if (type == KS) {
1059 return token.getKeyStore();
1060 } else if (type == AGP) {
1061 return new sun.security.util.ECParameters();
1062 } else {
1063 throw new NoSuchAlgorithmException("Unknown type: " + type);
1064 }
1065 }
1066
1067 public boolean supportsParameter(Object param) {
1068 if ((param == null) || (token.isValid() == false)) {
1069 return false;
1070 }
1071 if (param instanceof Key == false) {
1072 throw new InvalidParameterException("Parameter must be a Key");
1073 }
1074 String algorithm = getAlgorithm();
1075 String type = getType();
1076 Key key = (Key)param;
1077 String keyAlgorithm = key.getAlgorithm();
1078 // RSA signatures and cipher
1079 if (((type == CIP) && algorithm.startsWith("RSA"))
1080 || (type == SIG) && algorithm.endsWith("RSA")) {
1081 if (keyAlgorithm.equals("RSA") == false) {
1082 return false;
1083 }
1084 return isLocalKey(key)
1085 || (key instanceof RSAPrivateKey)
1086 || (key instanceof RSAPublicKey);
1087 }
1088 // EC
1089 if (((type == KA) && algorithm.equals("ECDH"))
1090 || ((type == SIG) && algorithm.contains("ECDSA"))) {
1091 if (keyAlgorithm.equals("EC") == false) {
1092 return false;
1093 }
1094 return isLocalKey(key)
1095 || (key instanceof ECPrivateKey)
1096 || (key instanceof ECPublicKey);
1097 }
1098 // DSA signatures
1099 if ((type == SIG) && algorithm.contains("DSA") &&
1100 !algorithm.contains("ECDSA")) {
1101 if (keyAlgorithm.equals("DSA") == false) {
1102 return false;
1103 }
1104 return isLocalKey(key)
1105 || (key instanceof DSAPrivateKey)
1106 || (key instanceof DSAPublicKey);
1107 }
1108 // MACs and symmetric ciphers
1109 if ((type == CIP) || (type == MAC)) {
1110 // do not check algorithm name, mismatch is unlikely anyway
1111 return isLocalKey(key) || "RAW".equals(key.getFormat());
1112 }
1113 // DH key agreement
1114 if (type == KA) {
1115 if (keyAlgorithm.equals("DH") == false) {
1116 return false;
1117 }
1118 return isLocalKey(key)
1119 || (key instanceof DHPrivateKey)
1120 || (key instanceof DHPublicKey);
1121 }
1122 // should not reach here,
1123 // unknown engine type or algorithm
1124 throw new AssertionError
1125 ("SunPKCS11 error: " + type + ", " + algorithm);
1126 }
1127
1128 private boolean isLocalKey(Key key) {
1129 return (key instanceof P11Key) && (((P11Key)key).token == token);
1130 }
1131
1132 public String toString() {
1133 return super.toString() +
1134 " (" + Functions.getMechanismName(mechanism) + ")";
1135 }
1136
1137 }
1138
1139 /**
1140 * Log in to this provider.
1141 *
1142 * <p> If the token expects a PIN to be supplied by the caller,
1143 * the <code>handler</code> implementation must support
1144 * a <code>PasswordCallback</code>.
1145 *
1146 * <p> To determine if the token supports a protected authentication path,
1147 * the CK_TOKEN_INFO flag, CKF_PROTECTED_AUTHENTICATION_PATH, is consulted.
1148 *
1149 * @param subject this parameter is ignored
1150 * @param handler the <code>CallbackHandler</code> used by
1151 * this provider to communicate with the caller
1152 *
1153 * @throws IllegalStateException if the provider requires configuration
1154 * and Provider.configure has not been called
1155 * @throws LoginException if the login operation fails
1156 * @throws SecurityException if the does not pass a security check for
1157 * <code>SecurityPermission("authProvider.<i>name</i>")</code>,
1158 * where <i>name</i> is the value returned by
1159 * this provider's <code>getName</code> method
1160 */
1161 public void login(Subject subject, CallbackHandler handler)
1162 throws LoginException {
1163
1164 if (!isConfigured()) {
1165 throw new IllegalStateException("Configuration is required");
1166 }
1167
1168 // security check
1169 SecurityManager sm = System.getSecurityManager();
1170 if (sm != null) {
1171 if (debug != null) {
1172 debug.println("checking login permission");
1173 }
1174 sm.checkPermission(new SecurityPermission
1175 ("authProvider." + this.getName()));
1176 }
1177
1178 if (hasValidToken() == false) {
1179 throw new LoginException("No token present");
1180 }
1181
1182 // see if a login is required
1183
1184 if ((token.tokenInfo.flags & CKF_LOGIN_REQUIRED) == 0) {
1185 if (debug != null) {
1186 debug.println("login operation not required for token - " +
1187 "ignoring login request");
1188 }
1189 return;
1190 }
1191
1192 // see if user already logged in
1193
1194 try {
1195 if (token.isLoggedInNow(null)) {
1196 // user already logged in
1197 if (debug != null) {
1198 debug.println("user already logged in");
1199 }
1200 return;
1201 }
1202 } catch (PKCS11Exception e) {
1203 // ignore - fall thru and attempt login
1204 }
1205
1206 // get the pin if necessary
1207
1208 char[] pin = null;
1209 if ((token.tokenInfo.flags & CKF_PROTECTED_AUTHENTICATION_PATH) == 0) {
1210
1211 // get password
1212
1213 CallbackHandler myHandler = getCallbackHandler(handler);
1214 if (myHandler == null) {
1215 // XXX PolicyTool is dependent on this message text
1216 throw new LoginException
1217 ("no password provided, and no callback handler " +
1218 "available for retrieving password");
1219 }
1220
1221 java.text.MessageFormat form = new java.text.MessageFormat
1222 (ResourcesMgr.getString
1223 ("PKCS11.Token.providerName.Password."));
1224 Object[] source = { getName() };
1225
1226 PasswordCallback pcall = new PasswordCallback(form.format(source),
1227 false);
1228 Callback[] callbacks = { pcall };
1229 try {
1230 myHandler.handle(callbacks);
1231 } catch (Exception e) {
1232 LoginException le = new LoginException
1233 ("Unable to perform password callback");
1234 le.initCause(e);
1235 throw le;
1236 }
1237
1238 pin = pcall.getPassword();
1239 pcall.clearPassword();
1240 if (pin == null) {
1241 if (debug != null) {
1242 debug.println("caller passed NULL pin");
1243 }
1244 }
1245 }
1246
1247 // perform token login
1248
1249 Session session = null;
1250 try {
1251 session = token.getOpSession();
1252
1253 // pin is NULL if using CKF_PROTECTED_AUTHENTICATION_PATH
1254 p11.C_Login(session.id(), CKU_USER, pin);
1255 if (debug != null) {
1256 debug.println("login succeeded");
1257 }
1258 } catch (PKCS11Exception pe) {
1259 if (pe.getErrorCode() == CKR_USER_ALREADY_LOGGED_IN) {
1260 // let this one go
1261 if (debug != null) {
1262 debug.println("user already logged in");
1263 }
1264 return;
1265 } else if (pe.getErrorCode() == CKR_PIN_INCORRECT) {
1266 FailedLoginException fle = new FailedLoginException();
1267 fle.initCause(pe);
1268 throw fle;
1269 } else {
1270 LoginException le = new LoginException();
1271 le.initCause(pe);
1272 throw le;
1273 }
1274 } finally {
1275 token.releaseSession(session);
1276 if (pin != null) {
1277 Arrays.fill(pin, ' ');
1278 }
1279 }
1280
1281 // we do not store the PIN in the subject for now
1282 }
1283
1284 /**
1285 * Log out from this provider
1286 *
1287 * @throws IllegalStateException if the provider requires configuration
1288 * and Provider.configure has not been called
1289 * @throws LoginException if the logout operation fails
1290 * @throws SecurityException if the does not pass a security check for
1291 * <code>SecurityPermission("authProvider.<i>name</i>")</code>,
1292 * where <i>name</i> is the value returned by
1293 * this provider's <code>getName</code> method
1294 */
1295 public void logout() throws LoginException {
1296
1297 if (!isConfigured()) {
1298 throw new IllegalStateException("Configuration is required");
1299 }
1300
1301 // security check
1302 SecurityManager sm = System.getSecurityManager();
1303 if (sm != null) {
1304 sm.checkPermission
1305 (new SecurityPermission("authProvider." + this.getName()));
1306 }
1307
1308 if (hasValidToken() == false) {
1309 // app may call logout for cleanup, allow
1310 return;
1311 }
1312
1313 if ((token.tokenInfo.flags & CKF_LOGIN_REQUIRED) == 0) {
1314 if (debug != null) {
1315 debug.println("logout operation not required for token - " +
1316 "ignoring logout request");
1317 }
1318 return;
1319 }
1320
1321 try {
1322 if (token.isLoggedInNow(null) == false) {
1323 if (debug != null) {
1324 debug.println("user not logged in");
1325 }
1326 return;
1327 }
1328 } catch (PKCS11Exception e) {
1329 // ignore
1330 }
1331
1332 // perform token logout
1333
1334 Session session = null;
1335 try {
1336 session = token.getOpSession();
1337 p11.C_Logout(session.id());
1338 if (debug != null) {
1339 debug.println("logout succeeded");
1340 }
1341 } catch (PKCS11Exception pe) {
1342 if (pe.getErrorCode() == CKR_USER_NOT_LOGGED_IN) {
1343 // let this one go
1344 if (debug != null) {
1345 debug.println("user not logged in");
1346 }
1347 return;
1348 }
1349 LoginException le = new LoginException();
1350 le.initCause(pe);
1351 throw le;
1352 } finally {
1353 token.releaseSession(session);
1354 }
1355 }
1356
1357 /**
1358 * Set a <code>CallbackHandler</code>
1359 *
1360 * <p> The provider uses this handler if one is not passed to the
1361 * <code>login</code> method. The provider also uses this handler
1362 * if it invokes <code>login</code> on behalf of callers.
1363 * In either case if a handler is not set via this method,
1364 * the provider queries the
1365 * <i>auth.login.defaultCallbackHandler</i> security property
1366 * for the fully qualified class name of a default handler implementation.
1367 * If the security property is not set,
1368 * the provider is assumed to have alternative means
1369 * for obtaining authentication information.
1370 *
1371 * @param handler a <code>CallbackHandler</code> for obtaining
1372 * authentication information, which may be <code>null</code>
1373 *
1374 * @throws IllegalStateException if the provider requires configuration
1375 * and Provider.configure has not been called
1376 * @throws SecurityException if the caller does not pass a
1377 * security check for
1378 * <code>SecurityPermission("authProvider.<i>name</i>")</code>,
1379 * where <i>name</i> is the value returned by
1380 * this provider's <code>getName</code> method
1381 */
1382 public void setCallbackHandler(CallbackHandler handler) {
1383
1384 if (!isConfigured()) {
1385 throw new IllegalStateException("Configuration is required");
1386 }
1387
1388 // security check
1389 SecurityManager sm = System.getSecurityManager();
1390 if (sm != null) {
1391 sm.checkPermission
1392 (new SecurityPermission("authProvider." + this.getName()));
1393 }
1394
1395 synchronized (LOCK_HANDLER) {
1396 pHandler = handler;
1397 }
1398 }
1399
1400 private CallbackHandler getCallbackHandler(CallbackHandler handler) {
1401
1402 // get default handler if necessary
1403
1404 if (handler != null) {
1405 return handler;
1406 }
1407
1408 if (debug != null) {
1409 debug.println("getting provider callback handler");
1410 }
1411
1412 synchronized (LOCK_HANDLER) {
1413 // see if handler was set via setCallbackHandler
1414 if (pHandler != null) {
1415 return pHandler;
1416 }
1417
1418 try {
1419 if (debug != null) {
1420 debug.println("getting default callback handler");
1421 }
1422
1423 CallbackHandler myHandler = AccessController.doPrivileged
1424 (new PrivilegedExceptionAction<CallbackHandler>() {
1425 public CallbackHandler run() throws Exception {
1426
1427 String defaultHandler =
1428 java.security.Security.getProperty
1429 ("auth.login.defaultCallbackHandler");
1430
1431 if (defaultHandler == null ||
1432 defaultHandler.length() == 0) {
1433
1434 // ok
1435 if (debug != null) {
1436 debug.println("no default handler set");
1437 }
1438 return null;
1439 }
1440
1441 Class<?> c = Class.forName
1442 (defaultHandler,
1443 true,
1444 Thread.currentThread().getContextClassLoader());
1445 if (!javax.security.auth.callback.CallbackHandler.class.isAssignableFrom(c)) {
1446 // not the right subtype
1447 if (debug != null) {
1448 debug.println("default handler " + defaultHandler +
1449 " is not a CallbackHandler");
1450 }
1451 return null;
1452 }
1453 @SuppressWarnings("deprecation")
1454 Object result = c.newInstance();
1455 return (CallbackHandler)result;
1456 }
1457 });
1458 // save it
1459 pHandler = myHandler;
1460 return myHandler;
1461
1462 } catch (PrivilegedActionException pae) {
1463 // ok
1464 if (debug != null) {
1465 debug.println("Unable to load default callback handler");
1466 pae.printStackTrace();
1467 }
1468 }
1469 }
1470 return null;
1471 }
1472
1473 private Object writeReplace() throws ObjectStreamException {
1474 return new SunPKCS11Rep(this);
1475 }
1476
1477 /**
1478 * Serialized representation of the SunPKCS11 provider.
1479 */
1480 private static class SunPKCS11Rep implements Serializable {
1481
1482 static final long serialVersionUID = -2896606995897745419L;
1483
1484 private final String providerName;
1485
1486 private final String configName;
1487
1488 SunPKCS11Rep(SunPKCS11 provider) throws NotSerializableException {
1489 providerName = provider.getName();
1490 configName = provider.config.getFileName();
1491 if (Security.getProvider(providerName) != provider) {
1492 throw new NotSerializableException("Only SunPKCS11 providers "
1493 + "installed in java.security.Security can be serialized");
1494 }
1495 }
1496
1497 private Object readResolve() throws ObjectStreamException {
1498 SunPKCS11 p = (SunPKCS11)Security.getProvider(providerName);
1499 if ((p == null) || (p.config.getFileName().equals(configName) == false)) {
1500 throw new NotSerializableException("Could not find "
1501 + providerName + " in installed providers");
1502 }
1503 return p;
1504 }
1505 }
1506 }