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