2

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-----
Huckle
  • 1,810
  • 3
  • 26
  • 40
  • 1
    Seems Thread.sleep approach isn't rare for Allading etoken: http://prenninger.com/wp/pdf-signing-using-etoken-in-java-en – Marek Gregor Apr 29 '14 at 05:57
  • I haven't had to remove the token or release the provider, but I'm also use eToken.so instead of eTPKCS11.ddll. But this is ammunition for an argument that some code somewhere in the stack is not being handled correctly. More than likely it appears to be in the eToken side. – Huckle Apr 29 '14 at 17:53

0 Answers0