Reputation: 1940
I've been experimenting with an SafeNet (Aladdin) eToken and Java 8's PKCS11 interface. I noticed that when I was debugging the following code snippet it would work. If I ran it without the debugger I got an exception. I introduced an artificial delay and suddenly it worked without the debugger. This leads me to believe there is a race condition in my code. Is there a better way to be doing this? Or is this specific to my token? Or is this a new bug in Java 8 x64 for debian based systems?
public class CertificteRequestTest {
public static void main(String[] args) throws Exception{
KeyStore keyStore = getPKCS11Keys();
PrivateKey privateKey = (PrivateKey)keyStore.getKey("onekey",null);
PublicKey publicKey = ((KeyStore.PrivateKeyEntry)keyStore.getEntry("onekey",null)).getCertificate().getPublicKey();
X500Principal principal = new X500Principal("CN=onesubject");
PKCS10CertificationRequestBuilder builder
= new JcaPKCS10CertificationRequestBuilder(principal,publicKey);
ContentSigner signer
= new JcaContentSignerBuilder("SHA256withRSA").build(privateKey);
/* Removing this causes the Signer to think the token is not logged in */
Thread.sleep(1000);
PKCS10CertificationRequest csr = builder.build(signer);
PEMWriter writer = new PEMWriter(new PrintWriter(System.out));
writer.writeObject(csr);
writer.close();
}
public static KeyStore getPKCS11Keys() throws KeyStoreException {
SunPKCS11 provider = new SunPKCS11ProviderFactory()
.withDescription("PKCS11TestProvider - libeToken 8")
.withName("PKCS11TestProvider")
.withLibrary("/lib64/libeToken.so.8").build();
Security.addProvider(provider);
KeyStore.CallbackHandlerProtection pinHandler
= new KeyStore.CallbackHandlerProtection(new TextCallbackHandler());
return KeyStore.Builder.newInstance("PKCS11",provider,pinHandler).getKeyStore();
}
}
The exception that is thrown seems to indicate that I've not logged into the token, but I have done so. Entering the wrong PIN results in a failed login attempt.
$ java ... com.test.CertificteRequestTest
PKCS11 Token [SunPKCS11-PKCS11TestProvider] Password:
Exception in thread "main" java.security.ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_USER_NOT_LOGGED_IN
at sun.security.pkcs11.P11Signature.engineSign(P11Signature.java:588)
at java.security.Signature$Delegate.engineSign(Signature.java:1162)
at java.security.Signature.sign(Signature.java:554)
at org.bouncycastle.operator.jcajce.JcaContentSignerBuilder$SignatureOutputStream.getSignature(Unknown Source)
at org.bouncycastle.operator.jcajce.JcaContentSignerBuilder$1.getSignature(Unknown Source)
at org.bouncycastle.pkcs.PKCS10CertificationRequestBuilder.build(Unknown Source)
...
Caused by: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_USER_NOT_LOGGED_IN
at sun.security.pkcs11.wrapper.PKCS11.C_Sign(Native Method)
at sun.security.pkcs11.P11Signature.engineSign(P11Signature.java:579)
With the artificial delay installed this is the result of a successful run:
$ java ... com.test.CertificteRequestTest
PKCS11 Token [SunPKCS11-PKCS11TestProvider] Password:
-----BEGIN CERTIFICATE REQUEST-----
MIICW...
-----END CERTIFICATE REQUEST-----
Upvotes: 2
Views: 1784