Hej!

Jag har experimenterat lite med att importera den PKCS#12-fil som
skapats av FriBID till ett smartkort (i mitt fall en med
SafeSign-appleten) och sedan försökt använda kortet med FriBID.

Se bifogad guide howto-fribid-p12-to-smartcard.txt.

Eftersom mitt kort bara har stöd för en PKCS#11 slot så försökte jag
lägga både authentiserings- och signerings-certen (+nycklar) på samma
slot men det visade sig att FriBID inte stödde detta. Det var även
problem om kortet innehöll andra certifikat före de från BankID.

Den bifogade patchen multiple-certs-in-slot-1.patch är tänkt att lösa
dessa problem genom att inte avbryta om ett okänt certifikat påträffats
utan istället fortsätta och kontrollera övriga och lägga till alla som
matchar samt att det valda certifikatet sedan används istället för
alltid det första.


Mvh
Markus Kilås
>From c64e28e3ead0947fd053d514f0dbab58bdda0da3 Mon Sep 17 00:00:00 2001
From: Markus KilÃ¥s <[email protected]>
Date: Jun 4, 2012 8:32:36 AM

Support for multiple certificates and key-pairs in the same PKCS#11 slot.

diff --git a/client/pkcs11.c b/client/pkcs11.c
index df49969..42e6744 100644
--- a/client/pkcs11.c
+++ b/client/pkcs11.c
@@ -52,6 +52,7 @@
 struct PKCS11Token {
     Token base;
     PKCS11_SLOT *slot;
+    PKCS11_CERT *cert;
     PKCS11_CERT *certs;
     unsigned int ncerts;
 };
@@ -89,7 +90,7 @@
 static TokenError _backend_getBase64Chain(const PKCS11Token *token,
                                           char ***certs, size_t *count) {
     
-    X509 *cert = token->certs[0].x509;
+    X509 *cert = token->cert[0].x509;
     if (!cert) {
         return TokenError_Unknown;
     }
@@ -133,7 +134,7 @@
     }
 
     // Find the key for the token
-    PKCS11_CERT *cert = &token->certs[0];
+    PKCS11_CERT *cert = token->cert;
     PKCS11_KEY *key = PKCS11_find_key(cert);
 
     if (!key) return TokenError_BadPin;
@@ -159,40 +160,46 @@
  */
 static void pkcs11_found_token(Backend *backend, PKCS11_SLOT *slot) {
     int rc;
-    
-    PKCS11Token *token = calloc(1, sizeof(PKCS11Token));
-    if (!token) return;
-
-    token->slot = slot;
 
     // Scan card
-    rc = PKCS11_enumerate_certs(slot->token, &token->certs, &token->ncerts);
-    if (rc || token->ncerts == 0)
-        goto fail;
-
-    // Firts cert in the chain is the user cert. Rest is associated authority certs
-    X509 *x = token->certs[0].x509;
-    X509_NAME *id = X509_get_subject_name(x);
-
-    if (!certutil_hasKeyUsage(x, backend->notifier->keyUsage))
-        goto fail;
-
-    if (!certutil_matchSubjectFilter(backend->notifier->subjectFilter, id))
-        goto fail;
-
-    token->base.backend = backend;
-    if (slot->token->secureLogin == 0) {
-        token->base.status = TokenStatus_NeedPassword;
-    } else {
-        token->base.status = TokenStatus_NeedPIN;
+    unsigned int ncerts = 0;
+    PKCS11_CERT *certs;
+    rc = PKCS11_enumerate_certs(slot->token, &certs, &ncerts);
+    if (rc || ncerts == 0) {
+        fprintf(stderr, BINNAME ": found no certificates in slot\n");
+        return;
     }
-    token->base.displayName = certutil_getDisplayNameFromDN(id);
-    token->base.tag = slot->token->label;
-    backend->notifier->notifyFunction(&token->base, TokenChange_Added);
-    return;
 
-fail:
-    backend->freeToken(token);
+    for (unsigned int i = 0; i < ncerts; i++) {
+        // Check if this certificate is a BankID and has the right key usage
+        X509 *x = certs[i].x509;
+        X509_NAME *id = X509_get_subject_name(x);
+
+        if (!certutil_hasKeyUsage(x, backend->notifier->keyUsage))
+        continue;
+
+        if (!certutil_matchSubjectFilter(backend->notifier->subjectFilter, id))
+        continue;
+
+        PKCS11Token *token = calloc(1, sizeof(PKCS11Token));
+        if (!token) return;
+
+        token->slot = slot;
+        token->cert = &certs[i];
+        token->certs = certs;
+        token->ncerts = ncerts;
+
+        token->base.backend = backend;
+        if (slot->token->secureLogin == 0) {
+            token->base.status = TokenStatus_NeedPassword;
+        } else {
+            token->base.status = TokenStatus_NeedPIN;
+        }
+        token->base.displayName = certutil_getDisplayNameFromDN(id);
+        token->base.tag = slot->token->label;
+        backend->notifier->notifyFunction(&token->base, TokenChange_Added);
+     }
+
 }
 
 /**
Fribid p12 to smartcard
-----------------------


The format of the PKCS#12 file produced by Fribid is not compatible with Java 
which I will be using to import the keys and certificates to the smart card so 
we will first have to create a new PKCS#12 using OpenSSL.

Notice: Fribid expects different slots for the auth and sign 
key-pairs/certificates so a patch is required for the below setup with both 
certificates in the same slot.


1. Use OpenSSL to "import" the PKCS#12 file
openssl pkcs12 -nomacver -in "(110327 13.37) MY NAME - BankID på fil.p12" -out 
myname-bankid-auth.pem

2. Make a copy of myname-bankid-sign.pem
cp myname-bankid-auth.pem myname-bankid-sign.pem

3. Open and edit myname-bankid-auth.pem so that it only contains the first 
private key and the authentication certificate and the CA certificates
nano myname-bankid-auth.pem

4. Open and edit myname-bankid-sign.pem so that it only contains the second 
private key and the signature certificate and the CA certificates
nano myname-bankid-sign.pem

5. Use OpenSSL to "export" them to new PKCS#12 files
openssl pkcs12 -export -in myname-bankid-auth.pem -out myname-bankid-auth.p12 
-name "myname-bankid-auth"
openssl pkcs12 -export -in myname-bankid-sign.pem -out myname-bankid-sign.p12 
-name "myname-bankid-sign"

3. Create a SunPkcs11 config file pointing out the PKCS#11 module. For SafeSign 
the following works:
name=SafeSign
library=/usr/lib/libaetpkss.so
slotListIndex = 0

4. Use Java Keytool to import the keystores to the card
keytool -importkeystore -srckeystore myname-bankid-auth.p12 -srcstoretype 
pkcs12 -destkeystore NONE -deststoretype PKCS11 -providerClass 
sun.security.pkcs11.SunPKCS11 -providerArg sunp11-safesign.conf
keytool -importkeystore -srckeystore myname-bankid-sign.p12 -srcstoretype 
pkcs12 -destkeystore NONE -deststoretype PKCS11 -providerClass 
sun.security.pkcs11.SunPKCS11 -providerArg sunp11-safesign.conf

5. Use Java Keytool to see that both entris are available and with the 
certificate chains
keytool -keystore NONE -storetype PKCS11 -providerClass 
sun.security.pkcs11.SunPKCS11 -providerArg sunp11-safesign.conf -list -v

6. Configure FriBid to use the SafeSign PKCS#11 module by adding the following 
to ~/.config/fribid/config
[pkcs11]
module=/usr/lib/libaetpkss.so


Till