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