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