I have an application running under Tomcat 9, using JDK 1.8.0_111 as the runtime, on Windows 7 x64, that's trying to use a NitroKey HSM through the SunPKCS11 CSP and the OpenSC driver.
This works fine from the command line, including from a shell running under the same account as the Tomcat service uses.
Under Tomcat, however, the SunPKCS11 constructor throws a ProviderException with the message "Initialization failed". So far I've debugged this down to C_GetSlotInfo returning CKR_GENERAL_ERROR; that becomes a PKCS11Exception (with no further detail) and that gets wrapped in the ProviderException.
The slot number is correct - the NitroKey only has a single slot, so the number is 0. Besides the application itself, I have no problems using the HSM with keytool, OpenSSL, etc through PKCS#11. (Or through CAPI, for that matter.) It only fails under Tomcat.
Any ideas? Some other people have posted queries about this sort of failure if the HSM (or smart card) has been removed and re-inserted - see for example remove and insert smartcard using sunpkcs#11 and tomcat - but that's not the case here. The token hasn't been removed and remains accessible to everything else. But those questions imply that there's no inherent restriction on using SunPKCS11 and OpenSC under Tomcat.
I'm going to grab the JDK sources and debug further into C_GetSlotInfo, and try some other experiments such as spawning keytool with the appropriate options to see if it can talk to the card. But if anyone has any other suggestions I'd be glad to hear them.
In case anyone wants details: I'm invoking the SunPKCS11 constructor with a single argument, the path to the configuration file. It's reading the file successfully (I get a different exception if the file path is bogus or the file is unreadable). The file is very simple:
# PKCS#11 configuration file for Java to use NitroKey in slot 0 on Windows
name = NitroKey
library = c:/Windows/System32/opensc-pkcs11.dll
slotListIndex = 0
At the point of failure, SunPKCS11 hasn't seen any other details yet, such as the key container name or HSM PIN. Those would come later if the constructor didn't throw the exception.