0N/A/*
4320N/A * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage sun.security.pkcs11;
0N/A
0N/Aimport java.io.*;
0N/Aimport java.util.*;
0N/A
0N/Aimport java.security.*;
0N/Aimport java.security.KeyStore.*;
0N/Aimport java.security.cert.X509Certificate;
0N/A
0N/Aimport sun.security.pkcs11.wrapper.*;
0N/Aimport static sun.security.pkcs11.wrapper.PKCS11Constants.*;
0N/A
0N/A/**
0N/A * The Secmod class defines the interface to the native NSS
0N/A * library and the configuration information it stores in its
0N/A * secmod.db file.
0N/A *
0N/A * <p>Example code:
0N/A * <pre>
0N/A * Secmod secmod = Secmod.getInstance();
0N/A * if (secmod.isInitialized() == false) {
0N/A * secmod.initialize("/home/myself/.mozilla", "/usr/sfw/lib/mozilla");
0N/A * }
0N/A *
0N/A * Provider p = secmod.getModule(ModuleType.KEYSTORE).getProvider();
0N/A * KeyStore ks = KeyStore.getInstance("PKCS11", p);
0N/A * ks.load(null, password);
0N/A * </pre>
0N/A *
0N/A * @since 1.6
0N/A * @author Andreas Sterbenz
0N/A */
0N/Apublic final class Secmod {
0N/A
0N/A private final static boolean DEBUG = false;
0N/A
0N/A private final static Secmod INSTANCE;
0N/A
0N/A static {
0N/A sun.security.pkcs11.wrapper.PKCS11.loadNative();
0N/A INSTANCE = new Secmod();
0N/A }
0N/A
0N/A private final static String NSS_LIB_NAME = "nss3";
0N/A
0N/A private final static String SOFTTOKEN_LIB_NAME = "softokn3";
0N/A
0N/A private final static String TRUST_LIB_NAME = "nssckbi";
0N/A
0N/A // handle to be passed to the native code, 0 means not initialized
0N/A private long nssHandle;
0N/A
0N/A // whether this is a supported version of NSS
0N/A private boolean supported;
0N/A
0N/A // list of the modules
0N/A private List<Module> modules;
0N/A
0N/A private String configDir;
0N/A
0N/A private String nssLibDir;
0N/A
0N/A private Secmod() {
0N/A // empty
0N/A }
0N/A
0N/A /**
0N/A * Return the singleton Secmod instance.
0N/A */
0N/A public static Secmod getInstance() {
0N/A return INSTANCE;
0N/A }
0N/A
0N/A private boolean isLoaded() {
0N/A if (nssHandle == 0) {
0N/A nssHandle = nssGetLibraryHandle(System.mapLibraryName(NSS_LIB_NAME));
0N/A if (nssHandle != 0) {
0N/A fetchVersions();
0N/A }
0N/A }
0N/A return (nssHandle != 0);
0N/A }
0N/A
0N/A private void fetchVersions() {
0N/A supported = nssVersionCheck(nssHandle, "3.7");
0N/A }
0N/A
0N/A /**
0N/A * Test whether this Secmod has been initialized. Returns true
0N/A * if NSS has been initialized using either the initialize() method
0N/A * or by directly calling the native NSS APIs. The latter may be
0N/A * the case if the current process contains components that use
0N/A * NSS directly.
0N/A *
0N/A * @throws IOException if an incompatible version of NSS
0N/A * has been loaded
0N/A */
0N/A public synchronized boolean isInitialized() throws IOException {
0N/A // NSS does not allow us to check if it is initialized already
0N/A // assume that if it is loaded it is also initialized
0N/A if (isLoaded() == false) {
0N/A return false;
0N/A }
0N/A if (supported == false) {
0N/A throw new IOException
0N/A ("An incompatible version of NSS is already loaded, "
0N/A + "3.7 or later required");
0N/A }
0N/A return true;
0N/A }
0N/A
0N/A String getConfigDir() {
0N/A return configDir;
0N/A }
0N/A
0N/A String getLibDir() {
0N/A return nssLibDir;
0N/A }
0N/A
0N/A /**
0N/A * Initialize this Secmod.
0N/A *
0N/A * @param configDir the directory containing the NSS configuration
0N/A * files such as secmod.db
0N/A * @param nssLibDir the directory containing the NSS libraries
0N/A * (libnss3.so or nss3.dll) or null if the library is on
0N/A * the system default shared library path
0N/A *
0N/A * @throws IOException if NSS has already been initialized,
0N/A * the specified directories are invalid, or initialization
0N/A * fails for any other reason
0N/A */
0N/A public void initialize(String configDir, String nssLibDir)
0N/A throws IOException {
0N/A initialize(DbMode.READ_WRITE, configDir, nssLibDir);
0N/A }
0N/A
0N/A public synchronized void initialize(DbMode dbMode, String configDir, String nssLibDir)
0N/A throws IOException {
0N/A if (isInitialized()) {
0N/A throw new IOException("NSS is already initialized");
0N/A }
0N/A
0N/A if (dbMode == null) {
0N/A throw new NullPointerException();
0N/A }
0N/A if ((dbMode != DbMode.NO_DB) && (configDir == null)) {
0N/A throw new NullPointerException();
0N/A }
0N/A String platformLibName = System.mapLibraryName("nss3");
0N/A String platformPath;
0N/A if (nssLibDir == null) {
0N/A platformPath = platformLibName;
0N/A } else {
0N/A File base = new File(nssLibDir);
0N/A if (base.isDirectory() == false) {
0N/A throw new IOException("nssLibDir must be a directory:" + nssLibDir);
0N/A }
0N/A File platformFile = new File(base, platformLibName);
0N/A if (platformFile.isFile() == false) {
0N/A throw new FileNotFoundException(platformFile.getPath());
0N/A }
0N/A platformPath = platformFile.getPath();
0N/A }
0N/A
0N/A if (configDir != null) {
0N/A File configBase = new File(configDir);
0N/A if (configBase.isDirectory() == false ) {
0N/A throw new IOException("configDir must be a directory: " + configDir);
0N/A }
0N/A File secmodFile = new File(configBase, "secmod.db");
0N/A if (secmodFile.isFile() == false) {
0N/A throw new FileNotFoundException(secmodFile.getPath());
0N/A }
0N/A }
0N/A
0N/A if (DEBUG) System.out.println("lib: " + platformPath);
0N/A nssHandle = nssLoadLibrary(platformPath);
0N/A if (DEBUG) System.out.println("handle: " + nssHandle);
0N/A fetchVersions();
0N/A if (supported == false) {
0N/A throw new IOException
0N/A ("The specified version of NSS is incompatible, "
0N/A + "3.7 or later required");
0N/A }
0N/A
0N/A if (DEBUG) System.out.println("dir: " + configDir);
0N/A boolean initok = nssInit(dbMode.functionName, nssHandle, configDir);
0N/A if (DEBUG) System.out.println("init: " + initok);
0N/A if (initok == false) {
0N/A throw new IOException("NSS initialization failed");
0N/A }
0N/A
0N/A this.configDir = configDir;
0N/A this.nssLibDir = nssLibDir;
0N/A }
0N/A
0N/A /**
0N/A * Return an immutable list of all available modules.
0N/A *
0N/A * @throws IllegalStateException if this Secmod is misconfigured
0N/A * or not initialized
0N/A */
0N/A public synchronized List<Module> getModules() {
0N/A try {
0N/A if (isInitialized() == false) {
0N/A throw new IllegalStateException("NSS not initialized");
0N/A }
0N/A } catch (IOException e) {
0N/A // IOException if misconfigured
0N/A throw new IllegalStateException(e);
0N/A }
0N/A if (modules == null) {
4320N/A List<Module> modules = (List<Module>)nssGetModuleList(nssHandle,
4320N/A nssLibDir);
0N/A this.modules = Collections.unmodifiableList(modules);
0N/A }
0N/A return modules;
0N/A }
0N/A
0N/A private static byte[] getDigest(X509Certificate cert, String algorithm) {
0N/A try {
0N/A MessageDigest md = MessageDigest.getInstance(algorithm);
0N/A return md.digest(cert.getEncoded());
0N/A } catch (GeneralSecurityException e) {
0N/A throw new ProviderException(e);
0N/A }
0N/A }
0N/A
0N/A boolean isTrusted(X509Certificate cert, TrustType trustType) {
0N/A Bytes bytes = new Bytes(getDigest(cert, "SHA-1"));
0N/A TrustAttributes attr = getModuleTrust(ModuleType.KEYSTORE, bytes);
0N/A if (attr == null) {
0N/A attr = getModuleTrust(ModuleType.FIPS, bytes);
0N/A if (attr == null) {
0N/A attr = getModuleTrust(ModuleType.TRUSTANCHOR, bytes);
0N/A }
0N/A }
0N/A return (attr == null) ? false : attr.isTrusted(trustType);
0N/A }
0N/A
0N/A private TrustAttributes getModuleTrust(ModuleType type, Bytes bytes) {
0N/A Module module = getModule(type);
0N/A TrustAttributes t = (module == null) ? null : module.getTrust(bytes);
0N/A return t;
0N/A }
0N/A
0N/A /**
0N/A * Constants describing the different types of NSS modules.
0N/A * For this API, NSS modules are classified as either one
0N/A * of the internal modules delivered as part of NSS or
0N/A * as an external module provided by a 3rd party.
0N/A */
0N/A public static enum ModuleType {
0N/A /**
0N/A * The NSS Softtoken crypto module. This is the first
0N/A * slot of the softtoken object.
0N/A * This module provides
0N/A * implementations for cryptographic algorithms but no KeyStore.
0N/A */
0N/A CRYPTO,
0N/A /**
0N/A * The NSS Softtoken KeyStore module. This is the second
0N/A * slot of the softtoken object.
0N/A * This module provides
0N/A * implementations for cryptographic algorithms (after login)
0N/A * and the KeyStore.
0N/A */
0N/A KEYSTORE,
0N/A /**
0N/A * The NSS Softtoken module in FIPS mode. Note that in FIPS mode the
0N/A * softtoken presents only one slot, not separate CRYPTO and KEYSTORE
0N/A * slots as in non-FIPS mode.
0N/A */
0N/A FIPS,
0N/A /**
0N/A * The NSS builtin trust anchor module. This is the
0N/A * NSSCKBI object. It provides no crypto functions.
0N/A */
0N/A TRUSTANCHOR,
0N/A /**
0N/A * An external module.
0N/A */
0N/A EXTERNAL,
0N/A }
0N/A
0N/A /**
0N/A * Returns the first module of the specified type. If no such
0N/A * module exists, this method returns null.
0N/A *
0N/A * @throws IllegalStateException if this Secmod is misconfigured
0N/A * or not initialized
0N/A */
0N/A public Module getModule(ModuleType type) {
0N/A for (Module module : getModules()) {
0N/A if (module.getType() == type) {
0N/A return module;
0N/A }
0N/A }
0N/A return null;
0N/A }
0N/A
0N/A static final String TEMPLATE_EXTERNAL =
0N/A "library = %s\n"
0N/A + "name = \"%s\"\n"
0N/A + "slotListIndex = %d\n";
0N/A
0N/A static final String TEMPLATE_TRUSTANCHOR =
0N/A "library = %s\n"
0N/A + "name = \"NSS Trust Anchors\"\n"
0N/A + "slotListIndex = 0\n"
0N/A + "enabledMechanisms = { KeyStore }\n"
0N/A + "nssUseSecmodTrust = true\n";
0N/A
0N/A static final String TEMPLATE_CRYPTO =
0N/A "library = %s\n"
0N/A + "name = \"NSS SoftToken Crypto\"\n"
0N/A + "slotListIndex = 0\n"
0N/A + "disabledMechanisms = { KeyStore }\n";
0N/A
0N/A static final String TEMPLATE_KEYSTORE =
0N/A "library = %s\n"
0N/A + "name = \"NSS SoftToken KeyStore\"\n"
0N/A + "slotListIndex = 1\n"
0N/A + "nssUseSecmodTrust = true\n";
0N/A
0N/A static final String TEMPLATE_FIPS =
0N/A "library = %s\n"
0N/A + "name = \"NSS FIPS SoftToken\"\n"
0N/A + "slotListIndex = 0\n"
0N/A + "nssUseSecmodTrust = true\n";
0N/A
0N/A /**
0N/A * A representation of one PKCS#11 slot in a PKCS#11 module.
0N/A */
0N/A public static final class Module {
4320N/A // path of the native library
0N/A final String libraryName;
0N/A // descriptive name used by NSS
0N/A final String commonName;
0N/A final int slot;
0N/A final ModuleType type;
0N/A
0N/A private String config;
0N/A private SunPKCS11 provider;
0N/A
0N/A // trust attributes. Used for the KEYSTORE and TRUSTANCHOR modules only
0N/A private Map<Bytes,TrustAttributes> trust;
0N/A
4320N/A Module(String libraryDir, String libraryName, String commonName,
4320N/A boolean fips, int slot) {
0N/A ModuleType type;
4320N/A
0N/A if ((libraryName == null) || (libraryName.length() == 0)) {
0N/A // must be softtoken
0N/A libraryName = System.mapLibraryName(SOFTTOKEN_LIB_NAME);
0N/A if (fips == false) {
0N/A type = (slot == 0) ? ModuleType.CRYPTO : ModuleType.KEYSTORE;
0N/A } else {
0N/A type = ModuleType.FIPS;
0N/A if (slot != 0) {
0N/A throw new RuntimeException
0N/A ("Slot index should be 0 for FIPS slot");
0N/A }
0N/A }
0N/A } else {
0N/A if (libraryName.endsWith(System.mapLibraryName(TRUST_LIB_NAME))
0N/A || commonName.equals("Builtin Roots Module")) {
0N/A type = ModuleType.TRUSTANCHOR;
0N/A } else {
0N/A type = ModuleType.EXTERNAL;
0N/A }
0N/A if (fips) {
0N/A throw new RuntimeException("FIPS flag set for non-internal "
0N/A + "module: " + libraryName + ", " + commonName);
0N/A }
0N/A }
4320N/A this.libraryName = (new File(libraryDir, libraryName)).getPath();
0N/A this.commonName = commonName;
0N/A this.slot = slot;
0N/A this.type = type;
0N/A initConfiguration();
0N/A }
0N/A
0N/A private void initConfiguration() {
0N/A switch (type) {
0N/A case EXTERNAL:
0N/A config = String.format(TEMPLATE_EXTERNAL, libraryName,
0N/A commonName + " " + slot, slot);
0N/A break;
0N/A case CRYPTO:
0N/A config = String.format(TEMPLATE_CRYPTO, libraryName);
0N/A break;
0N/A case KEYSTORE:
0N/A config = String.format(TEMPLATE_KEYSTORE, libraryName);
0N/A break;
0N/A case FIPS:
0N/A config = String.format(TEMPLATE_FIPS, libraryName);
0N/A break;
0N/A case TRUSTANCHOR:
0N/A config = String.format(TEMPLATE_TRUSTANCHOR, libraryName);
0N/A break;
0N/A default:
0N/A throw new RuntimeException("Unknown module type: " + type);
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Get the configuration for this module. This is a string
0N/A * in the SunPKCS11 configuration format. It can be
0N/A * customized with additional options and then made
0N/A * current using the setConfiguration() method.
0N/A */
0N/A @Deprecated
0N/A public synchronized String getConfiguration() {
0N/A return config;
0N/A }
0N/A
0N/A /**
0N/A * Set the configuration for this module.
0N/A *
0N/A * @throws IllegalStateException if the associated provider
0N/A * instance has already been created.
0N/A */
0N/A @Deprecated
0N/A public synchronized void setConfiguration(String config) {
0N/A if (provider != null) {
0N/A throw new IllegalStateException("Provider instance already created");
0N/A }
0N/A this.config = config;
0N/A }
0N/A
0N/A /**
0N/A * Return the pathname of the native library that implements
0N/A * this module. For example, /usr/lib/libpkcs11.so.
0N/A */
0N/A public String getLibraryName() {
0N/A return libraryName;
0N/A }
0N/A
0N/A /**
0N/A * Returns the type of this module.
0N/A */
0N/A public ModuleType getType() {
0N/A return type;
0N/A }
0N/A
0N/A /**
0N/A * Returns the provider instance that is associated with this
0N/A * module. The first call to this method creates the provider
0N/A * instance.
0N/A */
0N/A @Deprecated
0N/A public synchronized Provider getProvider() {
0N/A if (provider == null) {
0N/A provider = newProvider();
0N/A }
0N/A return provider;
0N/A }
0N/A
0N/A synchronized boolean hasInitializedProvider() {
0N/A return provider != null;
0N/A }
0N/A
0N/A void setProvider(SunPKCS11 p) {
0N/A if (provider != null) {
0N/A throw new ProviderException("Secmod provider already initialized");
0N/A }
0N/A provider = p;
0N/A }
0N/A
0N/A private SunPKCS11 newProvider() {
0N/A try {
0N/A InputStream in = new ByteArrayInputStream(config.getBytes("UTF8"));
0N/A return new SunPKCS11(in);
0N/A } catch (Exception e) {
0N/A // XXX
0N/A throw new ProviderException(e);
0N/A }
0N/A }
0N/A
0N/A synchronized void setTrust(Token token, X509Certificate cert) {
0N/A Bytes bytes = new Bytes(getDigest(cert, "SHA-1"));
0N/A TrustAttributes attr = getTrust(bytes);
0N/A if (attr == null) {
0N/A attr = new TrustAttributes(token, cert, bytes, CKT_NETSCAPE_TRUSTED_DELEGATOR);
0N/A trust.put(bytes, attr);
0N/A } else {
0N/A // does it already have the correct trust settings?
0N/A if (attr.isTrusted(TrustType.ALL) == false) {
0N/A // XXX not yet implemented
0N/A throw new ProviderException("Cannot change existing trust attributes");
0N/A }
0N/A }
0N/A }
0N/A
0N/A TrustAttributes getTrust(Bytes hash) {
0N/A if (trust == null) {
0N/A // If provider is not set, create a temporary provider to
0N/A // retrieve the trust information. This can happen if we need
0N/A // to get the trust information for the trustanchor module
0N/A // because we need to look for user customized settings in the
0N/A // keystore module (which may not have a provider created yet).
0N/A // Creating a temporary provider and then dropping it on the
0N/A // floor immediately is flawed, but it's the best we can do
0N/A // for now.
0N/A synchronized (this) {
0N/A SunPKCS11 p = provider;
0N/A if (p == null) {
0N/A p = newProvider();
0N/A }
0N/A try {
0N/A trust = Secmod.getTrust(p);
0N/A } catch (PKCS11Exception e) {
0N/A throw new RuntimeException(e);
0N/A }
0N/A }
0N/A }
0N/A return trust.get(hash);
0N/A }
0N/A
0N/A public String toString() {
0N/A return
0N/A commonName + " (" + type + ", " + libraryName + ", slot " + slot + ")";
0N/A }
0N/A
0N/A }
0N/A
0N/A /**
0N/A * Constants representing NSS trust categories.
0N/A */
0N/A public static enum TrustType {
0N/A /** Trusted for all purposes */
0N/A ALL,
0N/A /** Trusted for SSL client authentication */
0N/A CLIENT_AUTH,
0N/A /** Trusted for SSL server authentication */
0N/A SERVER_AUTH,
0N/A /** Trusted for code signing */
0N/A CODE_SIGNING,
0N/A /** Trusted for email protection */
0N/A EMAIL_PROTECTION,
0N/A }
0N/A
0N/A public static enum DbMode {
0N/A READ_WRITE("NSS_InitReadWrite"),
0N/A READ_ONLY ("NSS_Init"),
0N/A NO_DB ("NSS_NoDB_Init");
0N/A
0N/A final String functionName;
0N/A DbMode(String functionName) {
0N/A this.functionName = functionName;
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * A LoadStoreParameter for use with the NSS Softtoken or
0N/A * NSS TrustAnchor KeyStores.
0N/A * <p>
0N/A * It allows the set of trusted certificates that are returned by
0N/A * the KeyStore to be specified.
0N/A */
0N/A public static final class KeyStoreLoadParameter implements LoadStoreParameter {
0N/A final TrustType trustType;
0N/A final ProtectionParameter protection;
0N/A public KeyStoreLoadParameter(TrustType trustType, char[] password) {
0N/A this(trustType, new PasswordProtection(password));
0N/A
0N/A }
0N/A public KeyStoreLoadParameter(TrustType trustType, ProtectionParameter prot) {
0N/A if (trustType == null) {
0N/A throw new NullPointerException("trustType must not be null");
0N/A }
0N/A this.trustType = trustType;
0N/A this.protection = prot;
0N/A }
0N/A public ProtectionParameter getProtectionParameter() {
0N/A return protection;
0N/A }
0N/A public TrustType getTrustType() {
0N/A return trustType;
0N/A }
0N/A }
0N/A
0N/A static class TrustAttributes {
0N/A final long handle;
0N/A final long clientAuth, serverAuth, codeSigning, emailProtection;
0N/A final byte[] shaHash;
0N/A TrustAttributes(Token token, X509Certificate cert, Bytes bytes, long trustValue) {
0N/A Session session = null;
0N/A try {
0N/A session = token.getOpSession();
0N/A // XXX use KeyStore TrustType settings to determine which
0N/A // attributes to set
0N/A CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_TOKEN, true),
0N/A new CK_ATTRIBUTE(CKA_CLASS, CKO_NETSCAPE_TRUST),
0N/A new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_SERVER_AUTH, trustValue),
0N/A new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CODE_SIGNING, trustValue),
0N/A new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_EMAIL_PROTECTION, trustValue),
0N/A new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CLIENT_AUTH, trustValue),
0N/A new CK_ATTRIBUTE(CKA_NETSCAPE_CERT_SHA1_HASH, bytes.b),
0N/A new CK_ATTRIBUTE(CKA_NETSCAPE_CERT_MD5_HASH, getDigest(cert, "MD5")),
0N/A new CK_ATTRIBUTE(CKA_ISSUER, cert.getIssuerX500Principal().getEncoded()),
0N/A new CK_ATTRIBUTE(CKA_SERIAL_NUMBER, cert.getSerialNumber().toByteArray()),
0N/A // XXX per PKCS#11 spec, the serial number should be in ASN.1
0N/A };
0N/A handle = token.p11.C_CreateObject(session.id(), attrs);
0N/A shaHash = bytes.b;
0N/A clientAuth = trustValue;
0N/A serverAuth = trustValue;
0N/A codeSigning = trustValue;
0N/A emailProtection = trustValue;
0N/A } catch (PKCS11Exception e) {
0N/A throw new ProviderException("Could not create trust object", e);
0N/A } finally {
0N/A token.releaseSession(session);
0N/A }
0N/A }
0N/A TrustAttributes(Token token, Session session, long handle)
0N/A throws PKCS11Exception {
0N/A this.handle = handle;
0N/A CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_SERVER_AUTH),
0N/A new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CODE_SIGNING),
0N/A new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_EMAIL_PROTECTION),
0N/A new CK_ATTRIBUTE(CKA_NETSCAPE_CERT_SHA1_HASH),
0N/A };
0N/A
0N/A token.p11.C_GetAttributeValue(session.id(), handle, attrs);
0N/A serverAuth = attrs[0].getLong();
0N/A codeSigning = attrs[1].getLong();
0N/A emailProtection = attrs[2].getLong();
0N/A shaHash = attrs[3].getByteArray();
0N/A
0N/A attrs = new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_NETSCAPE_TRUST_CLIENT_AUTH),
0N/A };
0N/A long c;
0N/A try {
0N/A token.p11.C_GetAttributeValue(session.id(), handle, attrs);
0N/A c = attrs[0].getLong();
0N/A } catch (PKCS11Exception e) {
0N/A // trust anchor module does not support this attribute
0N/A c = serverAuth;
0N/A }
0N/A clientAuth = c;
0N/A }
0N/A Bytes getHash() {
0N/A return new Bytes(shaHash);
0N/A }
0N/A boolean isTrusted(TrustType type) {
0N/A switch (type) {
0N/A case CLIENT_AUTH:
0N/A return isTrusted(clientAuth);
0N/A case SERVER_AUTH:
0N/A return isTrusted(serverAuth);
0N/A case CODE_SIGNING:
0N/A return isTrusted(codeSigning);
0N/A case EMAIL_PROTECTION:
0N/A return isTrusted(emailProtection);
0N/A case ALL:
0N/A return isTrusted(TrustType.CLIENT_AUTH)
0N/A && isTrusted(TrustType.SERVER_AUTH)
0N/A && isTrusted(TrustType.CODE_SIGNING)
0N/A && isTrusted(TrustType.EMAIL_PROTECTION);
0N/A default:
0N/A return false;
0N/A }
0N/A }
0N/A
0N/A private boolean isTrusted(long l) {
0N/A // XXX CKT_TRUSTED?
0N/A return (l == CKT_NETSCAPE_TRUSTED_DELEGATOR);
0N/A }
0N/A
0N/A }
0N/A
0N/A private static class Bytes {
0N/A final byte[] b;
0N/A Bytes(byte[] b) {
0N/A this.b = b;
0N/A }
0N/A public int hashCode() {
0N/A return Arrays.hashCode(b);
0N/A }
0N/A public boolean equals(Object o) {
0N/A if (this == o) {
0N/A return true;
0N/A }
0N/A if (o instanceof Bytes == false) {
0N/A return false;
0N/A }
0N/A Bytes other = (Bytes)o;
0N/A return Arrays.equals(this.b, other.b);
0N/A }
0N/A }
0N/A
0N/A private static Map<Bytes,TrustAttributes> getTrust(SunPKCS11 provider)
0N/A throws PKCS11Exception {
0N/A Map<Bytes,TrustAttributes> trustMap = new HashMap<Bytes,TrustAttributes>();
0N/A Token token = provider.getToken();
0N/A Session session = null;
0N/A try {
0N/A session = token.getOpSession();
0N/A int MAX_NUM = 8192;
0N/A CK_ATTRIBUTE[] attrs = new CK_ATTRIBUTE[] {
0N/A new CK_ATTRIBUTE(CKA_CLASS, CKO_NETSCAPE_TRUST),
0N/A };
0N/A token.p11.C_FindObjectsInit(session.id(), attrs);
0N/A long[] handles = token.p11.C_FindObjects(session.id(), MAX_NUM);
0N/A token.p11.C_FindObjectsFinal(session.id());
0N/A if (DEBUG) System.out.println("handles: " + handles.length);
0N/A
0N/A for (long handle : handles) {
0N/A TrustAttributes trust = new TrustAttributes(token, session, handle);
0N/A trustMap.put(trust.getHash(), trust);
0N/A }
0N/A } finally {
0N/A token.releaseSession(session);
0N/A }
0N/A return trustMap;
0N/A }
0N/A
0N/A private static native long nssGetLibraryHandle(String libraryName);
0N/A
0N/A private static native long nssLoadLibrary(String name) throws IOException;
0N/A
0N/A private static native boolean nssVersionCheck(long handle, String minVersion);
0N/A
0N/A private static native boolean nssInit(String functionName, long handle, String configDir);
0N/A
4320N/A private static native Object nssGetModuleList(long handle, String libDir);
0N/A
0N/A}