/* * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.pkcs11; import java.io.*;import java.util.*; import java.security.*;import java.security.KeyStore.*;import java.security.cert.X509Certificate; import sun.security.pkcs11.wrapper.*;import static sun.security.pkcs11.wrapper.PKCS11Constants.*; /** * The Secmod class defines the interface to the native NSS * library and the configuration information it stores in its * secmod.db file. * * <p>Example code: * <pre> * Secmod secmod = Secmod.getInstance(); * if (secmod.isInitialized() == false) { * secmod.initialize("/home/myself/.mozilla", "/usr/sfw/lib/mozilla"); * } * * Provider p = secmod.getModule(ModuleType.KEYSTORE).getProvider(); * KeyStore ks = KeyStore.getInstance("PKCS11", p); * ks.load(null, password); * </pre> * * @since 1.6 * @author Andreas Sterbenz */public final class Secmod { private final static boolean DEBUG = false; private final static Secmod INSTANCE; static { sun.security.pkcs11.wrapper.PKCS11.loadNative(); INSTANCE = new Secmod(); } private final static String NSS_LIB_NAME = "nss3"; private final static String SOFTTOKEN_LIB_NAME = "softokn3"; private final static String TRUST_LIB_NAME = "nssckbi"; // handle to be passed to the native code, 0 means not initialized private long nssHandle; // whether this is a supported version of NSS private boolean supported; // list of the modules private List<Module> modules; private String configDir; private String nssLibDir; private Secmod() { // empty } /** * Return the singleton Secmod instance. */ public static Secmod getInstance() { return INSTANCE; } private boolean isLoaded() { if (nssHandle == 0) { nssHandle = nssGetLibraryHandle(System.mapLibraryName(NSS_LIB_NAME)); if (nssHandle != 0) { fetchVersions(); } } return (nssHandle != 0); } private void fetchVersions() { supported = nssVersionCheck(nssHandle, "3.7"); } /** * Test whether this Secmod has been initialized. Returns true * if NSS has been initialized using either the initialize() method * or by directly calling the native NSS APIs. The latter may be * the case if the current process contains components that use * NSS directly. * * @throws IOException if an incompatible version of NSS * has been loaded */ public synchronized boolean isInitialized() throws IOException { // NSS does not allow us to check if it is initialized already // assume that if it is loaded it is also initialized if (isLoaded() == false) { return false; } if (supported == false) { throw new IOException ("An incompatible version of NSS is already loaded, " + "3.7 or later required"); } return true; } String getConfigDir() { return configDir; } String getLibDir() { return nssLibDir; } /** * Initialize this Secmod. * * @param configDir the directory containing the NSS configuration * files such as secmod.db * @param nssLibDir the directory containing the NSS libraries * (libnss3.so or nss3.dll) or null if the library is on * the system default shared library path * * @throws IOException if NSS has already been initialized, * the specified directories are invalid, or initialization * fails for any other reason */ public void initialize(String configDir, String nssLibDir) throws IOException { initialize(DbMode.READ_WRITE, configDir, nssLibDir); } public synchronized void initialize(DbMode dbMode, String configDir, String nssLibDir) throws IOException { if (isInitialized()) { throw new IOException("NSS is already initialized"); } if (dbMode == null) { throw new NullPointerException(); } if ((dbMode != DbMode.NO_DB) && (configDir == null)) { throw new NullPointerException(); } String platformLibName = System.mapLibraryName("nss3"); String platformPath; if (nssLibDir == null) { platformPath = platformLibName; } else { File base = new File(nssLibDir); if (base.isDirectory() == false) { throw new IOException("nssLibDir must be a directory:" + nssLibDir); } File platformFile = new File(base, platformLibName); if (platformFile.isFile() == false) { throw new FileNotFoundException(platformFile.getPath()); } platformPath = platformFile.getPath(); } if (configDir != null) { File configBase = new File(configDir); if (configBase.isDirectory() == false ) { throw new IOException("configDir must be a directory: " + configDir); } File secmodFile = new File(configBase, "secmod.db"); if (secmodFile.isFile() == false) { throw new FileNotFoundException(secmodFile.getPath()); } } if (DEBUG) System.out.println("lib: " + platformPath); nssHandle = nssLoadLibrary(platformPath); if (DEBUG) System.out.println("handle: " + nssHandle); fetchVersions(); if (supported == false) { throw new IOException ("The specified version of NSS is incompatible, " + "3.7 or later required"); } if (DEBUG) System.out.println("dir: " + configDir); boolean initok = nssInit(dbMode.functionName, nssHandle, configDir); if (DEBUG) System.out.println("init: " + initok); if (initok == false) { throw new IOException("NSS initialization failed"); } this.configDir = configDir; this.nssLibDir = nssLibDir; } /** * Return an immutable list of all available modules. * * @throws IllegalStateException if this Secmod is misconfigured * or not initialized */ public synchronized List<Module> getModules() { try { if (isInitialized() == false) { throw new IllegalStateException("NSS not initialized"); } } catch (IOException e) { // IOException if misconfigured throw new IllegalStateException(e); } if (modules == null) { List<Module> modules = (List<Module>)nssGetModuleList(nssHandle, nssLibDir); this.modules = Collections.unmodifiableList(modules); } return modules; } private static byte[] getDigest(X509Certificate cert, String algorithm) { try { MessageDigest md = MessageDigest.getInstance(algorithm); return md.digest(cert.getEncoded()); } catch (GeneralSecurityException e) { throw new ProviderException(e); } } boolean isTrusted(X509Certificate cert, TrustType trustType) { Bytes bytes = new Bytes(getDigest(cert, "SHA-1")); TrustAttributes attr = getModuleTrust(ModuleType.KEYSTORE, bytes); if (attr == null) { attr = getModuleTrust(ModuleType.FIPS, bytes); if (attr == null) { attr = getModuleTrust(ModuleType.TRUSTANCHOR, bytes); } } return (attr == null) ? false : attr.isTrusted(trustType); } private TrustAttributes getModuleTrust(ModuleType type, Bytes bytes) { Module module = getModule(type); TrustAttributes t = (module == null) ? null : module.getTrust(bytes); return t; } /** * Constants describing the different types of NSS modules. * For this API, NSS modules are classified as either one * of the internal modules delivered as part of NSS or * as an external module provided by a 3rd party. */ public static enum ModuleType { /** * The NSS Softtoken crypto module. This is the first * slot of the softtoken object. * This module provides * implementations for cryptographic algorithms but no KeyStore. */ CRYPTO, /** * The NSS Softtoken KeyStore module. This is the second * slot of the softtoken object. * This module provides * implementations for cryptographic algorithms (after login) * and the KeyStore. */ KEYSTORE, /** * The NSS Softtoken module in FIPS mode. Note that in FIPS mode the * softtoken presents only one slot, not separate CRYPTO and KEYSTORE * slots as in non-FIPS mode. */ FIPS, /** * The NSS builtin trust anchor module. This is the * NSSCKBI object. It provides no crypto functions. */ TRUSTANCHOR, /** * An external module. */ EXTERNAL, } /** * Returns the first module of the specified type. If no such * module exists, this method returns null. * * @throws IllegalStateException if this Secmod is misconfigured * or not initialized */ public Module getModule(ModuleType type) { for (Module module : getModules()) { if (module.getType() == type) { return module; } } return null; } static final String TEMPLATE_EXTERNAL = "library = %s\n" + "name = \"%s\"\n" + "slotListIndex = %d\n"; static final String TEMPLATE_TRUSTANCHOR = "library = %s\n" + "name = \"NSS Trust Anchors\"\n" + "slotListIndex = 0\n" + "enabledMechanisms = { KeyStore }\n" + "nssUseSecmodTrust = true\n"; static final String TEMPLATE_CRYPTO = "library = %s\n" + "name = \"NSS SoftToken Crypto\"\n" + "slotListIndex = 0\n" + "disabledMechanisms = { KeyStore }\n"; static final String TEMPLATE_KEYSTORE = "library = %s\n" + "name = \"NSS SoftToken KeyStore\"\n" + "slotListIndex = 1\n" + "nssUseSecmodTrust = true\n"; static final String TEMPLATE_FIPS = "library = %s\n" + "name = \"NSS FIPS SoftToken\"\n" + "slotListIndex = 0\n" + "nssUseSecmodTrust = true\n"; /** * A representation of one PKCS#11 slot in a PKCS#11 module. */ public static final class Module { // path of the native library final String libraryName; // descriptive name used by NSS final String commonName; final int slot; final ModuleType type; private String config; private SunPKCS11 provider; // trust attributes. Used for the KEYSTORE and TRUSTANCHOR modules only private Map<Bytes,TrustAttributes> trust; Module(String libraryDir, String libraryName, String commonName, boolean fips, int slot) { ModuleType type; if ((libraryName == null) || (libraryName.length() == 0)) { // must be softtoken libraryName = System.mapLibraryName(SOFTTOKEN_LIB_NAME); if (fips == false) { type = (slot == 0) ? ModuleType.CRYPTO : ModuleType.KEYSTORE; } else { type = ModuleType.FIPS; if (slot != 0) { throw new RuntimeException ("Slot index should be 0 for FIPS slot"); } } } else { if (libraryName.endsWith(System.mapLibraryName(TRUST_LIB_NAME)) || commonName.equals("Builtin Roots Module")) { type = ModuleType.TRUSTANCHOR; } else { type = ModuleType.EXTERNAL; } if (fips) { throw new RuntimeException("FIPS flag set for non-internal " + "module: " + libraryName + ", " + commonName); } } this.libraryName = (new File(libraryDir, libraryName)).getPath(); this.commonName = commonName; this.slot = slot; this.type = type; initConfiguration(); } private void initConfiguration() { switch (type) { case EXTERNAL: config = String.format(TEMPLATE_EXTERNAL, libraryName, commonName + " " + slot, slot); break; case CRYPTO: config = String.format(TEMPLATE_CRYPTO, libraryName); break; case KEYSTORE: config = String.format(TEMPLATE_KEYSTORE, libraryName); break; case FIPS: config = String.format(TEMPLATE_FIPS, libraryName); break; case TRUSTANCHOR: config = String.format(TEMPLATE_TRUSTANCHOR, libraryName); break; default: throw new RuntimeException("Unknown module type: " + type); } } /** * Get the configuration for this module. This is a string * in the SunPKCS11 configuration format. It can be * customized with additional options and then made * current using the setConfiguration() method. */ @Deprecated public synchronized String getConfiguration() { return config; } /** * Set the configuration for this module. * * @throws IllegalStateException if the associated provider * instance has already been created. */ @Deprecated public synchronized void setConfiguration(String config) { if (provider != null) { throw new IllegalStateException("Provider instance already created"); } this.config = config; } /** * Return the pathname of the native library that implements * this module. For example, /usr/lib/libpkcs11.so. */ public String getLibraryName() { return libraryName; } /** * Returns the type of this module. */ public ModuleType getType() { return type; } /** * Returns the provider instance that is associated with this * module. The first call to this method creates the provider * instance. */ @Deprecated public synchronized Provider getProvider() { if (provider == null) { provider = newProvider(); } return provider; } synchronized boolean hasInitializedProvider() { return provider != null; } void setProvider(SunPKCS11 p) { if (provider != null) { throw new ProviderException("Secmod provider already initialized"); } provider = p; } private SunPKCS11 newProvider() { try { InputStream in = new ByteArrayInputStream(config.getBytes("UTF8")); return new SunPKCS11(in);Lines 1–500 of 760. Load more
/* * Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.security.pkcs11; import java.io.*; import java.util.*; import java.security.*; import java.security.KeyStore.*; import java.security.cert.X509Certificate; import sun.security.pkcs11.wrapper.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*; /** * The Secmod class defines the interface to the native NSS * library and the configuration information it stores in its * secmod.db file. * * <p>Example code: * <pre> * Secmod secmod = Secmod.getInstance(); * if (secmod.isInitialized() == false) { * secmod.initialize("/home/myself/.mozilla", "/usr/sfw/lib/mozilla"); * } * * Provider p = secmod.getModule(ModuleType.KEYSTORE).getProvider(); * KeyStore ks = KeyStore.getInstance("PKCS11", p); * ks.load(null, password); * </pre> * * @since 1.6 * @author Andreas Sterbenz */ public final class Secmod { private final static boolean DEBUG = false; private final static Secmod INSTANCE; static { sun.security.pkcs11.wrapper.PKCS11.loadNative(); INSTANCE = new Secmod(); } private final static String NSS_LIB_NAME = "nss3"; private final static String SOFTTOKEN_LIB_NAME = "softokn3"; private final static String TRUST_LIB_NAME = "nssckbi"; // handle to be passed to the native code, 0 means not initialized private long nssHandle; // whether this is a supported version of NSS private boolean supported; // list of the modules private List<Module> modules; private String configDir; private String nssLibDir; private Secmod() { // empty } /** * Return the singleton Secmod instance. */ public static Secmod getInstance() { return INSTANCE; } private boolean isLoaded() { if (nssHandle == 0) { nssHandle = nssGetLibraryHandle(System.mapLibraryName(NSS_LIB_NAME)); if (nssHandle != 0) { fetchVersions(); } } return (nssHandle != 0); } private void fetchVersions() { supported = nssVersionCheck(nssHandle, "3.7"); } /** * Test whether this Secmod has been initialized. Returns true * if NSS has been initialized using either the initialize() method * or by directly calling the native NSS APIs. The latter may be * the case if the current process contains components that use * NSS directly. * * @throws IOException if an incompatible version of NSS * has been loaded */ public synchronized boolean isInitialized() throws IOException { // NSS does not allow us to check if it is initialized already // assume that if it is loaded it is also initialized if (isLoaded() == false) { return false; } if (supported == false) { throw new IOException ("An incompatible version of NSS is already loaded, " + "3.7 or later required"); } return true; } String getConfigDir() { return configDir; } String getLibDir() { return nssLibDir; } /** * Initialize this Secmod. * * @param configDir the directory containing the NSS configuration * files such as secmod.db * @param nssLibDir the directory containing the NSS libraries * (libnss3.so or nss3.dll) or null if the library is on * the system default shared library path * * @throws IOException if NSS has already been initialized, * the specified directories are invalid, or initialization * fails for any other reason */ public void initialize(String configDir, String nssLibDir) throws IOException { initialize(DbMode.READ_WRITE, configDir, nssLibDir); } public synchronized void initialize(DbMode dbMode, String configDir, String nssLibDir) throws IOException { if (isInitialized()) { throw new IOException("NSS is already initialized"); } if (dbMode == null) { throw new NullPointerException(); } if ((dbMode != DbMode.NO_DB) && (configDir == null)) { throw new NullPointerException(); } String platformLibName = System.mapLibraryName("nss3"); String platformPath; if (nssLibDir == null) { platformPath = platformLibName; } else { File base = new File(nssLibDir); if (base.isDirectory() == false) { throw new IOException("nssLibDir must be a directory:" + nssLibDir); } File platformFile = new File(base, platformLibName); if (platformFile.isFile() == false) { throw new FileNotFoundException(platformFile.getPath()); } platformPath = platformFile.getPath(); } if (configDir != null) { File configBase = new File(configDir); if (configBase.isDirectory() == false ) { throw new IOException("configDir must be a directory: " + configDir); } File secmodFile = new File(configBase, "secmod.db"); if (secmodFile.isFile() == false) { throw new FileNotFoundException(secmodFile.getPath()); } } if (DEBUG) System.out.println("lib: " + platformPath); nssHandle = nssLoadLibrary(platformPath); if (DEBUG) System.out.println("handle: " + nssHandle); fetchVersions(); if (supported == false) { throw new IOException ("The specified version of NSS is incompatible, " + "3.7 or later required"); } if (DEBUG) System.out.println("dir: " + configDir); boolean initok = nssInit(dbMode.functionName, nssHandle, configDir); if (DEBUG) System.out.println("init: " + initok); if (initok == false) { throw new IOException("NSS initialization failed"); } this.configDir = configDir; this.nssLibDir = nssLibDir; } /** * Return an immutable list of all available modules. * * @throws IllegalStateException if this Secmod is misconfigured * or not initialized */ public synchronized List<Module> getModules() { try { if (isInitialized() == false) { throw new IllegalStateException("NSS not initialized"); } } catch (IOException e) { // IOException if misconfigured throw new IllegalStateException(e); } if (modules == null) { List<Module> modules = (List<Module>)nssGetModuleList(nssHandle, nssLibDir); this.modules = Collections.unmodifiableList(modules); } return modules; } private static byte[] getDigest(X509Certificate cert, String algorithm) { try { MessageDigest md = MessageDigest.getInstance(algorithm); return md.digest(cert.getEncoded()); } catch (GeneralSecurityException e) { throw new ProviderException(e); } } boolean isTrusted(X509Certificate cert, TrustType trustType) { Bytes bytes = new Bytes(getDigest(cert, "SHA-1")); TrustAttributes attr = getModuleTrust(ModuleType.KEYSTORE, bytes); if (attr == null) { attr = getModuleTrust(ModuleType.FIPS, bytes); if (attr == null) { attr = getModuleTrust(ModuleType.TRUSTANCHOR, bytes); } } return (attr == null) ? false : attr.isTrusted(trustType); } private TrustAttributes getModuleTrust(ModuleType type, Bytes bytes) { Module module = getModule(type); TrustAttributes t = (module == null) ? null : module.getTrust(bytes); return t; } /** * Constants describing the different types of NSS modules. * For this API, NSS modules are classified as either one * of the internal modules delivered as part of NSS or * as an external module provided by a 3rd party. */ public static enum ModuleType { /** * The NSS Softtoken crypto module. This is the first * slot of the softtoken object. * This module provides * implementations for cryptographic algorithms but no KeyStore. */ CRYPTO, /** * The NSS Softtoken KeyStore module. This is the second * slot of the softtoken object. * This module provides * implementations for cryptographic algorithms (after login) * and the KeyStore. */ KEYSTORE, /** * The NSS Softtoken module in FIPS mode. Note that in FIPS mode the * softtoken presents only one slot, not separate CRYPTO and KEYSTORE * slots as in non-FIPS mode. */ FIPS, /** * The NSS builtin trust anchor module. This is the * NSSCKBI object. It provides no crypto functions. */ TRUSTANCHOR, /** * An external module. */ EXTERNAL, } /** * Returns the first module of the specified type. If no such * module exists, this method returns null. * * @throws IllegalStateException if this Secmod is misconfigured * or not initialized */ public Module getModule(ModuleType type) { for (Module module : getModules()) { if (module.getType() == type) { return module; } } return null; } static final String TEMPLATE_EXTERNAL = "library = %s\n" + "name = \"%s\"\n" + "slotListIndex = %d\n"; static final String TEMPLATE_TRUSTANCHOR = "library = %s\n" + "name = \"NSS Trust Anchors\"\n" + "slotListIndex = 0\n" + "enabledMechanisms = { KeyStore }\n" + "nssUseSecmodTrust = true\n"; static final String TEMPLATE_CRYPTO = "library = %s\n" + "name = \"NSS SoftToken Crypto\"\n" + "slotListIndex = 0\n" + "disabledMechanisms = { KeyStore }\n"; static final String TEMPLATE_KEYSTORE = "library = %s\n" + "name = \"NSS SoftToken KeyStore\"\n" + "slotListIndex = 1\n" + "nssUseSecmodTrust = true\n"; static final String TEMPLATE_FIPS = "library = %s\n" + "name = \"NSS FIPS SoftToken\"\n" + "slotListIndex = 0\n" + "nssUseSecmodTrust = true\n"; /** * A representation of one PKCS#11 slot in a PKCS#11 module. */ public static final class Module { // path of the native library final String libraryName; // descriptive name used by NSS final String commonName; final int slot; final ModuleType type; private String config; private SunPKCS11 provider; // trust attributes. Used for the KEYSTORE and TRUSTANCHOR modules only private Map<Bytes,TrustAttributes> trust; Module(String libraryDir, String libraryName, String commonName, boolean fips, int slot) { ModuleType type; if ((libraryName == null) || (libraryName.length() == 0)) { // must be softtoken libraryName = System.mapLibraryName(SOFTTOKEN_LIB_NAME); if (fips == false) { type = (slot == 0) ? ModuleType.CRYPTO : ModuleType.KEYSTORE; } else { type = ModuleType.FIPS; if (slot != 0) { throw new RuntimeException ("Slot index should be 0 for FIPS slot"); } } } else { if (libraryName.endsWith(System.mapLibraryName(TRUST_LIB_NAME)) || commonName.equals("Builtin Roots Module")) { type = ModuleType.TRUSTANCHOR; } else { type = ModuleType.EXTERNAL; } if (fips) { throw new RuntimeException("FIPS flag set for non-internal " + "module: " + libraryName + ", " + commonName); } } this.libraryName = (new File(libraryDir, libraryName)).getPath(); this.commonName = commonName; this.slot = slot; this.type = type; initConfiguration(); } private void initConfiguration() { switch (type) { case EXTERNAL: config = String.format(TEMPLATE_EXTERNAL, libraryName, commonName + " " + slot, slot); break; case CRYPTO: config = String.format(TEMPLATE_CRYPTO, libraryName); break; case KEYSTORE: config = String.format(TEMPLATE_KEYSTORE, libraryName); break; case FIPS: config = String.format(TEMPLATE_FIPS, libraryName); break; case TRUSTANCHOR: config = String.format(TEMPLATE_TRUSTANCHOR, libraryName); break; default: throw new RuntimeException("Unknown module type: " + type); } } /** * Get the configuration for this module. This is a string * in the SunPKCS11 configuration format. It can be * customized with additional options and then made * current using the setConfiguration() method. */ @Deprecated public synchronized String getConfiguration() { return config; } /** * Set the configuration for this module. * * @throws IllegalStateException if the associated provider * instance has already been created. */ @Deprecated public synchronized void setConfiguration(String config) { if (provider != null) { throw new IllegalStateException("Provider instance already created"); } this.config = config; } /** * Return the pathname of the native library that implements * this module. For example, /usr/lib/libpkcs11.so. */ public String getLibraryName() { return libraryName; } /** * Returns the type of this module. */ public ModuleType getType() { return type; } /** * Returns the provider instance that is associated with this * module. The first call to this method creates the provider * instance. */ @Deprecated public synchronized Provider getProvider() { if (provider == null) { provider = newProvider(); } return provider; } synchronized boolean hasInitializedProvider() { return provider != null; } void setProvider(SunPKCS11 p) { if (provider != null) { throw new ProviderException("Secmod provider already initialized"); } provider = p; } private SunPKCS11 newProvider() { try { InputStream in = new ByteArrayInputStream(config.getBytes("UTF8")); return new SunPKCS11(in);