1 /* 2 * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package sun.security.pkcs11; 27 28 import java.io.*; 29 import java.util.*; 30 31 import java.security.*; 32 import java.security.KeyStore.*; 33 import java.security.cert.X509Certificate; 34 35 import sun.security.pkcs11.wrapper.*; 36 import static sun.security.pkcs11.wrapper.PKCS11Constants.*; 37 38 39 /** 40 * The Secmod class defines the interface to the native NSS 41 * library and the configuration information it stores in its 42 * secmod.db file. 43 * 44 * <p>Example code: 45 * <pre> 46 * Secmod secmod = Secmod.getInstance(); 47 * if (secmod.isInitialized() == false) { 48 * secmod.initialize("/home/myself/.mozilla"); 49 * } 50 * 51 * Provider p = secmod.getModule(ModuleType.KEYSTORE).getProvider(); 52 * KeyStore ks = KeyStore.getInstance("PKCS11", p); 53 * ks.load(null, password); 54 * </pre> 55 * 56 * @since 1.6 57 * @author Andreas Sterbenz 58 */ 59 public final class Secmod { 60 61 private final static boolean DEBUG = false; 62 63 private final static Secmod INSTANCE; 64 65 static { sun.security.pkcs11.wrapper.PKCS11.loadNative()66 sun.security.pkcs11.wrapper.PKCS11.loadNative(); 67 INSTANCE = new Secmod(); 68 } 69 70 private final static String NSS_LIB_NAME = "nss3"; 71 72 private final static String SOFTTOKEN_LIB_NAME = "softokn3"; 73 74 private final static String TRUST_LIB_NAME = "nssckbi"; 75 76 // handle to be passed to the native code, 0 means not initialized 77 private long nssHandle; 78 79 // whether this is a supported version of NSS 80 private boolean supported; 81 82 // list of the modules 83 private List<Module> modules; 84 85 private String configDir; 86 87 private String nssLibDir; 88 Secmod()89 private Secmod() { 90 // empty 91 } 92 93 /** 94 * Return the singleton Secmod instance. 95 */ getInstance()96 public static Secmod getInstance() { 97 return INSTANCE; 98 } 99 isLoaded()100 private boolean isLoaded() { 101 if (nssHandle == 0) { 102 nssHandle = nssGetLibraryHandle(System.mapLibraryName(NSS_LIB_NAME)); 103 if (nssHandle != 0) { 104 fetchVersions(); 105 } 106 } 107 return (nssHandle != 0); 108 } 109 fetchVersions()110 private void fetchVersions() { 111 supported = nssVersionCheck(nssHandle, "3.7"); 112 } 113 114 /** 115 * Test whether this Secmod has been initialized. Returns true 116 * if NSS has been initialized using either the initialize() method 117 * or by directly calling the native NSS APIs. The latter may be 118 * the case if the current process contains components that use 119 * NSS directly. 120 * 121 * @throws IOException if an incompatible version of NSS 122 * has been loaded 123 */ isInitialized()124 public synchronized boolean isInitialized() throws IOException { 125 // NSS does not allow us to check if it is initialized already 126 // assume that if it is loaded it is also initialized 127 if (isLoaded() == false) { 128 return false; 129 } 130 if (supported == false) { 131 throw new IOException 132 ("An incompatible version of NSS is already loaded, " 133 + "3.7 or later required"); 134 } 135 return true; 136 } 137 getConfigDir()138 String getConfigDir() { 139 return configDir; 140 } 141 getLibDir()142 String getLibDir() { 143 return nssLibDir; 144 } 145 146 /** 147 * Initialize this Secmod. 148 * 149 * @param configDir the directory containing the NSS configuration 150 * files such as secmod.db 151 * @param nssLibDir the directory containing the NSS libraries 152 * (libnss3.so or nss3.dll) or null if the library is on 153 * the system default shared library path 154 * 155 * @throws IOException if NSS has already been initialized, 156 * the specified directories are invalid, or initialization 157 * fails for any other reason 158 */ initialize(String configDir, String nssLibDir)159 public void initialize(String configDir, String nssLibDir) 160 throws IOException { 161 initialize(DbMode.READ_WRITE, configDir, nssLibDir, false); 162 } 163 initialize(DbMode dbMode, String configDir, String nssLibDir)164 public void initialize(DbMode dbMode, String configDir, String nssLibDir) 165 throws IOException { 166 initialize(dbMode, configDir, nssLibDir, false); 167 } 168 initialize(DbMode dbMode, String configDir, String nssLibDir, boolean nssOptimizeSpace)169 public synchronized void initialize(DbMode dbMode, String configDir, 170 String nssLibDir, boolean nssOptimizeSpace) throws IOException { 171 172 if (isInitialized()) { 173 throw new IOException("NSS is already initialized"); 174 } 175 176 if (dbMode == null) { 177 throw new NullPointerException(); 178 } 179 if ((dbMode != DbMode.NO_DB) && (configDir == null)) { 180 throw new NullPointerException(); 181 } 182 String platformLibName = System.mapLibraryName("nss3"); 183 String platformPath; 184 if (nssLibDir == null) { 185 platformPath = platformLibName; 186 } else { 187 File base = new File(nssLibDir); 188 if (base.isDirectory() == false) { 189 throw new IOException("nssLibDir must be a directory:" + nssLibDir); 190 } 191 File platformFile = new File(base, platformLibName); 192 if (platformFile.isFile() == false) { 193 throw new FileNotFoundException(platformFile.getPath()); 194 } 195 platformPath = platformFile.getPath(); 196 } 197 198 if (configDir != null) { 199 String configDirPath = null; 200 String sqlPrefix = "sql:"; 201 if (!configDir.startsWith(sqlPrefix)) { 202 configDirPath = configDir; 203 } else { 204 StringBuilder configDirPathSB = new StringBuilder(configDir); 205 configDirPath = configDirPathSB.substring(sqlPrefix.length()); 206 } 207 File configBase = new File(configDirPath); 208 if (configBase.isDirectory() == false ) { 209 throw new IOException("configDir must be a directory: " + configDirPath); 210 } 211 if (!configDir.startsWith(sqlPrefix)) { 212 File secmodFile = new File(configBase, "secmod.db"); 213 if (secmodFile.isFile() == false) { 214 throw new FileNotFoundException(secmodFile.getPath()); 215 } 216 } 217 } 218 219 if (DEBUG) System.out.println("lib: " + platformPath); 220 nssHandle = nssLoadLibrary(platformPath); 221 if (DEBUG) System.out.println("handle: " + nssHandle); 222 fetchVersions(); 223 if (supported == false) { 224 throw new IOException 225 ("The specified version of NSS is incompatible, " 226 + "3.7 or later required"); 227 } 228 229 if (DEBUG) System.out.println("dir: " + configDir); 230 boolean initok = nssInitialize(dbMode.functionName, nssHandle, 231 configDir, nssOptimizeSpace); 232 if (DEBUG) System.out.println("init: " + initok); 233 if (initok == false) { 234 throw new IOException("NSS initialization failed"); 235 } 236 237 this.configDir = configDir; 238 this.nssLibDir = nssLibDir; 239 } 240 241 /** 242 * Return an immutable list of all available modules. 243 * 244 * @throws IllegalStateException if this Secmod is misconfigured 245 * or not initialized 246 */ getModules()247 public synchronized List<Module> getModules() { 248 try { 249 if (isInitialized() == false) { 250 throw new IllegalStateException("NSS not initialized"); 251 } 252 } catch (IOException e) { 253 // IOException if misconfigured 254 throw new IllegalStateException(e); 255 } 256 if (modules == null) { 257 @SuppressWarnings("unchecked") 258 List<Module> modules = (List<Module>)nssGetModuleList(nssHandle, 259 nssLibDir); 260 this.modules = Collections.unmodifiableList(modules); 261 } 262 return modules; 263 } 264 getDigest(X509Certificate cert, String algorithm)265 private static byte[] getDigest(X509Certificate cert, String algorithm) { 266 try { 267 MessageDigest md = MessageDigest.getInstance(algorithm); 268 return md.digest(cert.getEncoded()); 269 } catch (GeneralSecurityException e) { 270 throw new ProviderException(e); 271 } 272 } 273 isTrusted(X509Certificate cert, TrustType trustType)274 boolean isTrusted(X509Certificate cert, TrustType trustType) { 275 Bytes bytes = new Bytes(getDigest(cert, "SHA-1")); 276 TrustAttributes attr = getModuleTrust(ModuleType.KEYSTORE, bytes); 277 if (attr == null) { 278 attr = getModuleTrust(ModuleType.FIPS, bytes); 279 if (attr == null) { 280 attr = getModuleTrust(ModuleType.TRUSTANCHOR, bytes); 281 } 282 } 283 return (attr == null) ? false : attr.isTrusted(trustType); 284 } 285 getModuleTrust(ModuleType type, Bytes bytes)286 private TrustAttributes getModuleTrust(ModuleType type, Bytes bytes) { 287 Module module = getModule(type); 288 TrustAttributes t = (module == null) ? null : module.getTrust(bytes); 289 return t; 290 } 291 292 /** 293 * Constants describing the different types of NSS modules. 294 * For this API, NSS modules are classified as either one 295 * of the internal modules delivered as part of NSS or 296 * as an external module provided by a 3rd party. 297 */ 298 public static enum ModuleType { 299 /** 300 * The NSS Softtoken crypto module. This is the first 301 * slot of the softtoken object. 302 * This module provides 303 * implementations for cryptographic algorithms but no KeyStore. 304 */ 305 CRYPTO, 306 /** 307 * The NSS Softtoken KeyStore module. This is the second 308 * slot of the softtoken object. 309 * This module provides 310 * implementations for cryptographic algorithms (after login) 311 * and the KeyStore. 312 */ 313 KEYSTORE, 314 /** 315 * The NSS Softtoken module in FIPS mode. Note that in FIPS mode the 316 * softtoken presents only one slot, not separate CRYPTO and KEYSTORE 317 * slots as in non-FIPS mode. 318 */ 319 FIPS, 320 /** 321 * The NSS builtin trust anchor module. This is the 322 * NSSCKBI object. It provides no crypto functions. 323 */ 324 TRUSTANCHOR, 325 /** 326 * An external module. 327 */ 328 EXTERNAL, 329 } 330 331 /** 332 * Returns the first module of the specified type. If no such 333 * module exists, this method returns null. 334 * 335 * @throws IllegalStateException if this Secmod is misconfigured 336 * or not initialized 337 */ getModule(ModuleType type)338 public Module getModule(ModuleType type) { 339 for (Module module : getModules()) { 340 if (module.getType() == type) { 341 return module; 342 } 343 } 344 return null; 345 } 346 347 static final String TEMPLATE_EXTERNAL = 348 "library = %s\n" 349 + "name = \"%s\"\n" 350 + "slotListIndex = %d\n"; 351 352 static final String TEMPLATE_TRUSTANCHOR = 353 "library = %s\n" 354 + "name = \"NSS Trust Anchors\"\n" 355 + "slotListIndex = 0\n" 356 + "enabledMechanisms = { KeyStore }\n" 357 + "nssUseSecmodTrust = true\n"; 358 359 static final String TEMPLATE_CRYPTO = 360 "library = %s\n" 361 + "name = \"NSS SoftToken Crypto\"\n" 362 + "slotListIndex = 0\n" 363 + "disabledMechanisms = { KeyStore }\n"; 364 365 static final String TEMPLATE_KEYSTORE = 366 "library = %s\n" 367 + "name = \"NSS SoftToken KeyStore\"\n" 368 + "slotListIndex = 1\n" 369 + "nssUseSecmodTrust = true\n"; 370 371 static final String TEMPLATE_FIPS = 372 "library = %s\n" 373 + "name = \"NSS FIPS SoftToken\"\n" 374 + "slotListIndex = 0\n" 375 + "nssUseSecmodTrust = true\n"; 376 377 /** 378 * A representation of one PKCS#11 slot in a PKCS#11 module. 379 */ 380 public static final class Module { 381 // path of the native library 382 final String libraryName; 383 // descriptive name used by NSS 384 final String commonName; 385 final int slot; 386 final ModuleType type; 387 388 private String config; 389 private SunPKCS11 provider; 390 391 // trust attributes. Used for the KEYSTORE and TRUSTANCHOR modules only 392 private Map<Bytes,TrustAttributes> trust; 393 Module(String libraryDir, String libraryName, String commonName, boolean fips, int slot)394 Module(String libraryDir, String libraryName, String commonName, 395 boolean fips, int slot) { 396 ModuleType type; 397 398 if ((libraryName == null) || (libraryName.length() == 0)) { 399 // must be softtoken 400 libraryName = System.mapLibraryName(SOFTTOKEN_LIB_NAME); 401 if (fips == false) { 402 type = (slot == 0) ? ModuleType.CRYPTO : ModuleType.KEYSTORE; 403 } else { 404 type = ModuleType.FIPS; 405 if (slot != 0) { 406 throw new RuntimeException 407 ("Slot index should be 0 for FIPS slot"); 408 } 409 } 410 } else { 411 if (libraryName.endsWith(System.mapLibraryName(TRUST_LIB_NAME)) 412 || commonName.equals("Builtin Roots Module")) { 413 type = ModuleType.TRUSTANCHOR; 414 } else { 415 type = ModuleType.EXTERNAL; 416 } 417 } 418 // On Ubuntu the libsoftokn3 library is located in a subdirectory 419 // of the system libraries directory. (Since Ubuntu 11.04.) 420 File libraryFile = new File(libraryDir, libraryName); 421 if (!libraryFile.isFile()) { 422 File failover = new File(libraryDir, "nss/" + libraryName); 423 if (failover.isFile()) { 424 libraryFile = failover; 425 } 426 } 427 this.libraryName = libraryFile.getPath(); 428 this.commonName = commonName; 429 this.slot = slot; 430 this.type = type; 431 initConfiguration(); 432 } 433 initConfiguration()434 private void initConfiguration() { 435 switch (type) { 436 case EXTERNAL: 437 config = String.format(TEMPLATE_EXTERNAL, libraryName, 438 commonName + " " + slot, slot); 439 break; 440 case CRYPTO: 441 config = String.format(TEMPLATE_CRYPTO, libraryName); 442 break; 443 case KEYSTORE: 444 config = String.format(TEMPLATE_KEYSTORE, libraryName); 445 break; 446 case FIPS: 447 config = String.format(TEMPLATE_FIPS, libraryName); 448 break; 449 case TRUSTANCHOR: 450 config = String.format(TEMPLATE_TRUSTANCHOR, libraryName); 451 break; 452 default: 453 throw new RuntimeException("Unknown module type: " + type); 454 } 455 } 456 457 /** 458 * Get the configuration for this module. This is a string 459 * in the SunPKCS11 configuration format. It can be 460 * customized with additional options and then made 461 * current using the setConfiguration() method. 462 */ 463 @Deprecated getConfiguration()464 public synchronized String getConfiguration() { 465 return config; 466 } 467 468 /** 469 * Set the configuration for this module. 470 * 471 * @throws IllegalStateException if the associated provider 472 * instance has already been created. 473 */ 474 @Deprecated setConfiguration(String config)475 public synchronized void setConfiguration(String config) { 476 if (provider != null) { 477 throw new IllegalStateException("Provider instance already created"); 478 } 479 this.config = config; 480 } 481 482 /** 483 * Return the pathname of the native library that implements 484 * this module. For example, /usr/lib/libpkcs11.so. 485 */ getLibraryName()486 public String getLibraryName() { 487 return libraryName; 488 } 489 490 /** 491 * Returns the type of this module. 492 */ getType()493 public ModuleType getType() { 494 return type; 495 } 496 497 /** 498 * Returns the provider instance that is associated with this 499 * module. The first call to this method creates the provider 500 * instance. 501 */ 502 @Deprecated getProvider()503 public synchronized Provider getProvider() { 504 if (provider == null) { 505 provider = newProvider(); 506 } 507 return provider; 508 } 509 hasInitializedProvider()510 synchronized boolean hasInitializedProvider() { 511 return provider != null; 512 } 513 setProvider(SunPKCS11 p)514 void setProvider(SunPKCS11 p) { 515 if (provider != null) { 516 throw new ProviderException("Secmod provider already initialized"); 517 } 518 provider = p; 519 } 520 newProvider()521 private SunPKCS11 newProvider() { 522 try { 523 return new SunPKCS11(new Config("--" + config)); 524 } catch (Exception e) { 525 // XXX 526 throw new ProviderException(e); 527 } 528 } 529 setTrust(Token token, X509Certificate cert)530 synchronized void setTrust(Token token, X509Certificate cert) { 531 Bytes bytes = new Bytes(getDigest(cert, "SHA-1")); 532 TrustAttributes attr = getTrust(bytes); 533 if (attr == null) { 534 attr = new TrustAttributes(token, cert, bytes, CKT_NETSCAPE_TRUSTED_DELEGATOR); 535 trust.put(bytes, attr); 536 } else { 537 // does it already have the correct trust settings? 538 if (attr.isTrusted(TrustType.ALL) == false) { 539 // XXX not yet implemented 540 throw new ProviderException("Cannot change existing trust attributes"); 541 } 542 } 543 } 544 getTrust(Bytes hash)545 TrustAttributes getTrust(Bytes hash) { 546 if (trust == null) { 547 // If provider is not set, create a temporary provider to 548 // retrieve the trust information. This can happen if we need 549 // to get the trust information for the trustanchor module 550 // because we need to look for user customized settings in the 551 // keystore module (which may not have a provider created yet). 552 // Creating a temporary provider and then dropping it on the 553 // floor immediately is flawed, but it's the best we can do 554 // for now. 555 synchronized (this) { 556 SunPKCS11 p = provider; 557 if (p == null) { 558 p = newProvider(); 559 } 560 try { 561 trust = Secmod.getTrust(p); 562 } catch (PKCS11Exception e) { 563 throw new RuntimeException(e); 564 } 565 } 566 } 567 return trust.get(hash); 568 } 569 toString()570 public String toString() { 571 return 572 commonName + " (" + type + ", " + libraryName + ", slot " + slot + ")"; 573 } 574 575 } 576 577 /** 578 * Constants representing NSS trust categories. 579 */ 580 public static enum TrustType { 581 /** Trusted for all purposes */ 582 ALL, 583 /** Trusted for SSL client authentication */ 584 CLIENT_AUTH, 585 /** Trusted for SSL server authentication */ 586 SERVER_AUTH, 587 /** Trusted for code signing */ 588 CODE_SIGNING, 589 /** Trusted for email protection */ 590 EMAIL_PROTECTION, 591 } 592 593 public static enum DbMode { 594 READ_WRITE("NSS_InitReadWrite"), 595 READ_ONLY ("NSS_Init"), 596 NO_DB ("NSS_NoDB_Init"); 597 598 final String functionName; DbMode(String functionName)599 DbMode(String functionName) { 600 this.functionName = functionName; 601 } 602 } 603 604 /** 605 * A LoadStoreParameter for use with the NSS Softtoken or 606 * NSS TrustAnchor KeyStores. 607 * <p> 608 * It allows the set of trusted certificates that are returned by 609 * the KeyStore to be specified. 610 */ 611 public static final class KeyStoreLoadParameter implements LoadStoreParameter { 612 final TrustType trustType; 613 final ProtectionParameter protection; KeyStoreLoadParameter(TrustType trustType, char[] password)614 public KeyStoreLoadParameter(TrustType trustType, char[] password) { 615 this(trustType, new PasswordProtection(password)); 616 617 } KeyStoreLoadParameter(TrustType trustType, ProtectionParameter prot)618 public KeyStoreLoadParameter(TrustType trustType, ProtectionParameter prot) { 619 if (trustType == null) { 620 throw new NullPointerException("trustType must not be null"); 621 } 622 this.trustType = trustType; 623 this.protection = prot; 624 } getProtectionParameter()625 public ProtectionParameter getProtectionParameter() { 626 return protection; 627 } getTrustType()628 public TrustType getTrustType() { 629 return trustType; 630 } 631 } 632 633 static class TrustAttributes { 634 final long handle; 635 final long clientAuth, serverAuth, codeSigning, emailProtection; 636 final byte[] shaHash; TrustAttributes(Token token, X509Certificate cert, Bytes bytes, long trustValue)637 TrustAttributes(Token token, X509Certificate cert, Bytes bytes, long trustValue) { 638 Session session = null; 639 try { 640 session = token.getOpSession(); 641 // XXX use KeyStore TrustType settings to determine which 642 // attributes to set 643 CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] { 644 new CK_ATTRIBUTE(CKA_TOKEN, true), 645 new CK_ATTRIBUTE(CKA_CLASS, CKO_NETSCAPE_TRUST), 646 new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_SERVER_AUTH, trustValue), 647 new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CODE_SIGNING, trustValue), 648 new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_EMAIL_PROTECTION, trustValue), 649 new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CLIENT_AUTH, trustValue), 650 new CK_ATTRIBUTE(CKA_NETSCAPE_CERT_SHA1_HASH, bytes.b), 651 new CK_ATTRIBUTE(CKA_NETSCAPE_CERT_MD5_HASH, getDigest(cert, "MD5")), 652 new CK_ATTRIBUTE(CKA_ISSUER, cert.getIssuerX500Principal().getEncoded()), 653 new CK_ATTRIBUTE(CKA_SERIAL_NUMBER, cert.getSerialNumber().toByteArray()), 654 // XXX per PKCS#11 spec, the serial number should be in ASN.1 655 }; 656 handle = token.p11.C_CreateObject(session.id(), attrs); 657 shaHash = bytes.b; 658 clientAuth = trustValue; 659 serverAuth = trustValue; 660 codeSigning = trustValue; 661 emailProtection = trustValue; 662 } catch (PKCS11Exception e) { 663 throw new ProviderException("Could not create trust object", e); 664 } finally { 665 token.releaseSession(session); 666 } 667 } TrustAttributes(Token token, Session session, long handle)668 TrustAttributes(Token token, Session session, long handle) 669 throws PKCS11Exception { 670 this.handle = handle; 671 CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] { 672 new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_SERVER_AUTH), 673 new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CODE_SIGNING), 674 new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_EMAIL_PROTECTION), 675 new CK_ATTRIBUTE(CKA_NETSCAPE_CERT_SHA1_HASH), 676 }; 677 678 token.p11.C_GetAttributeValue(session.id(), handle, attrs); 679 serverAuth = attrs[0].getLong(); 680 codeSigning = attrs[1].getLong(); 681 emailProtection = attrs[2].getLong(); 682 shaHash = attrs[3].getByteArray(); 683 684 attrs = new CK_ATTRIBUTE[] { 685 new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CLIENT_AUTH), 686 }; 687 long c; 688 try { 689 token.p11.C_GetAttributeValue(session.id(), handle, attrs); 690 c = attrs[0].getLong(); 691 } catch (PKCS11Exception e) { 692 // trust anchor module does not support this attribute 693 c = serverAuth; 694 } 695 clientAuth = c; 696 } getHash()697 Bytes getHash() { 698 return new Bytes(shaHash); 699 } isTrusted(TrustType type)700 boolean isTrusted(TrustType type) { 701 switch (type) { 702 case CLIENT_AUTH: 703 return isTrusted(clientAuth); 704 case SERVER_AUTH: 705 return isTrusted(serverAuth); 706 case CODE_SIGNING: 707 return isTrusted(codeSigning); 708 case EMAIL_PROTECTION: 709 return isTrusted(emailProtection); 710 case ALL: 711 return isTrusted(TrustType.CLIENT_AUTH) 712 && isTrusted(TrustType.SERVER_AUTH) 713 && isTrusted(TrustType.CODE_SIGNING) 714 && isTrusted(TrustType.EMAIL_PROTECTION); 715 default: 716 return false; 717 } 718 } 719 isTrusted(long l)720 private boolean isTrusted(long l) { 721 // XXX CKT_TRUSTED? 722 return (l == CKT_NETSCAPE_TRUSTED_DELEGATOR); 723 } 724 725 } 726 727 private static class Bytes { 728 final byte[] b; Bytes(byte[] b)729 Bytes(byte[] b) { 730 this.b = b; 731 } hashCode()732 public int hashCode() { 733 return Arrays.hashCode(b); 734 } equals(Object o)735 public boolean equals(Object o) { 736 if (this == o) { 737 return true; 738 } 739 if (o instanceof Bytes == false) { 740 return false; 741 } 742 Bytes other = (Bytes)o; 743 return Arrays.equals(this.b, other.b); 744 } 745 } 746 getTrust(SunPKCS11 provider)747 private static Map<Bytes,TrustAttributes> getTrust(SunPKCS11 provider) 748 throws PKCS11Exception { 749 Map<Bytes,TrustAttributes> trustMap = new HashMap<Bytes,TrustAttributes>(); 750 Token token = provider.getToken(); 751 Session session = null; 752 boolean exceptionOccurred = true; 753 try { 754 session = token.getOpSession(); 755 int MAX_NUM = 8192; 756 CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] { 757 new CK_ATTRIBUTE(CKA_CLASS, CKO_NETSCAPE_TRUST), 758 }; 759 token.p11.C_FindObjectsInit(session.id(), attrs); 760 long[] handles = token.p11.C_FindObjects(session.id(), MAX_NUM); 761 token.p11.C_FindObjectsFinal(session.id()); 762 if (DEBUG) System.out.println("handles: " + handles.length); 763 764 for (long handle : handles) { 765 try { 766 TrustAttributes trust = new TrustAttributes(token, session, handle); 767 trustMap.put(trust.getHash(), trust); 768 } catch (PKCS11Exception e) { 769 // skip put on pkcs11 error 770 } 771 } 772 exceptionOccurred = false; 773 } finally { 774 if (exceptionOccurred) { 775 token.killSession(session); 776 } else { 777 token.releaseSession(session); 778 } 779 } 780 return trustMap; 781 } 782 nssGetLibraryHandle(String libraryName)783 private static native long nssGetLibraryHandle(String libraryName); 784 nssLoadLibrary(String name)785 private static native long nssLoadLibrary(String name) throws IOException; 786 nssVersionCheck(long handle, String minVersion)787 private static native boolean nssVersionCheck(long handle, String minVersion); 788 nssInitialize(String functionName, long handle, String configDir, boolean nssOptimizeSpace)789 private static native boolean nssInitialize(String functionName, long handle, String configDir, boolean nssOptimizeSpace); 790 nssGetModuleList(long handle, String libDir)791 private static native Object nssGetModuleList(long handle, String libDir); 792 793 } 794