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