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