public SunPKCS11(String configName,
InputStream configStream) {
super("SunPKCS11-" + Config.getConfig(configName, configStream).getName(),
1.7d, Config.getConfig(configName, configStream).getDescription());
this.configName = configName;
this.config = Config.removeConfig(configName);
if (debug != null) {
System.out.println("SunPKCS11 loading " + configName);
}
String library = config.getLibrary();
String functionList = config.getFunctionList();
long slotID = config.getSlotID();
int slotListIndex = config.getSlotListIndex();
boolean useSecmod = config.getNssUseSecmod();
boolean nssUseSecmodTrust = config.getNssUseSecmodTrust();
Module nssModule = null;
//
// Initialization via Secmod. The way this works is as follows:
// SunPKCS11 is either in normal mode or in NSS Secmod mode.
// Secmod is activated by specifying one or more of the following
// options in the config file:
// nssUseSecmod, nssSecmodDirectory, nssLibrary, nssModule
//
// XXX add more explanation here
//
// If we are in Secmod mode and configured to use either the
// nssKeyStore or the nssTrustAnchors module, we automatically
// switch to using the NSS trust attributes for trusted certs (KeyStore).
//
if (useSecmod) {
// note: Config ensures library/slot/slotListIndex not specified
// in secmod mode.
Secmod secmod = Secmod.getInstance();
DbMode nssDbMode = config.getNssDbMode();
try {
String nssLibraryDirectory = config.getNssLibraryDirectory();
String nssSecmodDirectory = config.getNssSecmodDirectory();
if (secmod.isInitialized()) {
if (nssSecmodDirectory != null) {
String s = secmod.getConfigDir();
if ((s != null) && (s.equals(nssSecmodDirectory) == false)) {
throw new ProviderException("Secmod directory "
+ nssSecmodDirectory
+ " invalid, NSS already initialized with " + s);
}
}
if (nssLibraryDirectory != null) {
String s = secmod.getLibDir();
if ((s != null) && (s.equals(nssLibraryDirectory) == false)) {
throw new ProviderException("NSS library directory "
+ nssLibraryDirectory
+ " invalid, NSS already initialized with " + s);
}
}
} else {
if (nssDbMode != DbMode.NO_DB) {
if (nssSecmodDirectory == null) {
throw new ProviderException("Secmod not initialized and "
+ "nssSecmodDirectory not specified");
}
} else {
if (nssSecmodDirectory != null) {
throw new ProviderException
("nssSecmodDirectory must not be specified in noDb mode");
}
}
secmod.initialize(nssDbMode, nssSecmodDirectory, nssLibraryDirectory);
}
} catch (IOException e) {
// XXX which exception to throw
throw new ProviderException("Could not initialize NSS", e);
}
List< Module > modules = secmod.getModules();
if (config.getShowInfo()) {
System.out.println("NSS modules: " + modules);
}
String moduleName = config.getNssModule();
if (moduleName == null) {
nssModule = secmod.getModule(ModuleType.FIPS);
if (nssModule != null) {
moduleName = "fips";
} else {
moduleName = (nssDbMode == DbMode.NO_DB) ? "crypto" : "keystore";
}
}
if (moduleName.equals("fips")) {
nssModule = secmod.getModule(ModuleType.FIPS);
nssUseSecmodTrust = true;
functionList = "FC_GetFunctionList";
} else if (moduleName.equals("keystore")) {
nssModule = secmod.getModule(ModuleType.KEYSTORE);
nssUseSecmodTrust = true;
} else if (moduleName.equals("crypto")) {
nssModule = secmod.getModule(ModuleType.CRYPTO);
} else if (moduleName.equals("trustanchors")) {
// XXX should the option be called trustanchor or trustanchors??
nssModule = secmod.getModule(ModuleType.TRUSTANCHOR);
nssUseSecmodTrust = true;
} else if (moduleName.startsWith("external-")) {
int moduleIndex;
try {
moduleIndex = Integer.parseInt
(moduleName.substring("external-".length()));
} catch (NumberFormatException e) {
moduleIndex = -1;
}
if (moduleIndex < 1) {
throw new ProviderException
("Invalid external module: " + moduleName);
}
int k = 0;
for (Module module : modules) {
if (module.getType() == ModuleType.EXTERNAL) {
if (++k == moduleIndex) {
nssModule = module;
break;
}
}
}
if (nssModule == null) {
throw new ProviderException("Invalid module " + moduleName
+ ": only " + k + " external NSS modules available");
}
} else {
throw new ProviderException("Unknown NSS module: " + moduleName);
}
if (nssModule == null) {
throw new ProviderException("NSS module not available: " + moduleName);
}
if (nssModule.hasInitializedProvider()) {
throw new ProviderException("Secmod module already configured");
}
library = nssModule.libraryName;
slotListIndex = nssModule.slot;
}
this.nssUseSecmodTrust = nssUseSecmodTrust;
this.nssModule = nssModule;
File libraryFile = new File(library);
// if the filename is a simple filename without path
// (e.g. "libpkcs11.so"), it may refer to a library somewhere on the
// OS library search path. Omit the test for file existance as that
// only looks in the current directory.
if (libraryFile.getName().equals(library) == false) {
if (new File(library).isFile() == false) {
String msg = "Library " + library + " does not exist";
if (config.getHandleStartupErrors() == Config.ERR_HALT) {
throw new ProviderException(msg);
} else {
throw new UnsupportedOperationException(msg);
}
}
}
try {
if (debug != null) {
debug.println("Initializing PKCS#11 library " + library);
}
CK_C_INITIALIZE_ARGS initArgs = new CK_C_INITIALIZE_ARGS();
String nssArgs = config.getNssArgs();
if (nssArgs != null) {
initArgs.pReserved = nssArgs;
}
// request multithreaded access first
initArgs.flags = CKF_OS_LOCKING_OK;
PKCS11 tmpPKCS11;
try {
tmpPKCS11 = PKCS11.getInstance
(library, functionList, initArgs, config.getOmitInitialize());
} catch (PKCS11Exception e) {
if (debug != null) {
debug.println("Multi-threaded initialization failed: " + e);
}
if (config.getAllowSingleThreadedModules() == false) {
throw e;
}
// fall back to single threaded access
if (nssArgs == null) {
// if possible, use null initArgs for better compatibility
initArgs = null;
} else {
initArgs.flags = 0;
}
tmpPKCS11 = PKCS11.getInstance
(library, functionList, initArgs, config.getOmitInitialize());
}
p11 = tmpPKCS11;
CK_INFO p11Info = p11.C_GetInfo();
if (p11Info.cryptokiVersion.major < 2) {
throw new ProviderException("Only PKCS#11 v2.0 and later "
+ "supported, library version is v" + p11Info.cryptokiVersion);
}
boolean showInfo = config.getShowInfo();
if (showInfo) {
System.out.println("Information for provider " + getName());
System.out.println("Library info:");
System.out.println(p11Info);
}
if ((slotID < 0) || showInfo) {
long[] slots = p11.C_GetSlotList(false);
if (showInfo) {
System.out.println("All slots: " + toString(slots));
slots = p11.C_GetSlotList(true);
System.out.println("Slots with tokens: " + toString(slots));
}
if (slotID < 0) {
if ((slotListIndex < 0) || (slotListIndex >= slots.length)) {
throw new ProviderException("slotListIndex is " + slotListIndex
+ " but token only has " + slots.length + " slots");
}
slotID = slots[slotListIndex];
}
}
this.slotID = slotID;
CK_SLOT_INFO slotInfo = p11.C_GetSlotInfo(slotID);
removable = (slotInfo.flags & CKF_REMOVABLE_DEVICE) != 0;
initToken(slotInfo);
if (nssModule != null) {
nssModule.setProvider(this);
}
} catch (Exception e) {
if (config.getHandleStartupErrors() == Config.ERR_IGNORE_ALL) {
throw new UnsupportedOperationException
("Initialization failed", e);
} else {
throw new ProviderException
("Initialization failed", e);
}
}
}
|