[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Using Heimdal PKINIT with OpenSC-0.10.0 loading the key before loadingthe cert



OpenSC-0.10.0, engine-pkcs11-0.1.2, and libp11-0.2.0 were released
yesterday. They contain two fixes and a change in the format of the string
used withthe PKINIT  KEY= and CERT=.


ENGINE:KEY=slot_0,CERT=slot_0 will no longer work, but
ENGINE:KEY=1,CERT=1 will. This says use cert and key ID 1 from the
first card found. (Other formats may also work but not slot_0)

The first fix causes the PKCS11 to be closed and the card disconnected
when the engine is finished.  Without this fix gdm uisng pam_krb5
to use PKINIT would lock on to the card/reader and not allow other
processes to use the card, as gdm keeps running in the background.

The second fix allows the engine load_cert_ctrl routines to be called
after the engine_load_private_key. Before this fix if the order was
switched the engine could not access the key when needed, as the
load_cert_ctrl would have dropped the connection for the key.

Attached is a patch to pkinit.c that reverses the order of the calls
to the load_cert_ctrl and the load_private_key, so the load_private_key
is done first. This will use the PIN to login to the card, and will
then allow pin protected certificates to be read off the card.

The NIST SP800-73 PIV card specification calls for the certificate to
be protected by the pin, so this change will allow these cards to work.
NIST may change the standard, as there are no other cards that keep
the certificate private, and most other applications try and read the
certificate before asking for a pin.

So if this patch is installed, engine_pkcs11-0.1.2 is also required.

Thanks.



-- 

  Douglas E. Engert  <DEEngert@anl.gov>
  Argonne National Laboratory
  9700 South Cass Avenue
  Argonne, Illinois  60439
  (630) 252-5444
--- lib/krb5/,pkinit.c	Sun Sep 25 10:14:31 2005
+++ lib/krb5/pkinit.c	Wed Oct 19 08:13:36 2005
@@ -2307,32 +2307,7 @@
     if (ret)
 	goto out;
 
-    /*
-     * If the engine supports a LOAD_CERT_CTRL function, lets try
-     * it. OpenSC support this function. Eventially this should be
-     * a ENGINE_load_cert function if it failes, treat it like a
-     * non fatal error.
-     */
-    {
-	struct {
-	    const char * cert_id;
-	    X509 * cert;
-	} parms;
-
-	parms.cert_id = ctx.cert_file;
-	parms.cert = NULL;
-	ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 1); 
-	if (parms.cert) {
-	    id->cert = sk_X509_new_null();
-	    sk_X509_insert(id->cert, parms.cert, 0);	
-	}  
-    }
-
-    if (id->cert == NULL) {
-	ret = load_openssl_cert(context, ctx.cert_file, &id->cert);
-	if (ret)
-	    goto out;
-    }
+	/* load key before cert, incase smartcard pin is required for cert */
 
     {
 	UI_METHOD * krb5_ui_method = NULL;
@@ -2362,6 +2337,33 @@
 	UI_destroy_method(krb5_ui_method);
     }
 	
+    /*
+     * If the engine supports a LOAD_CERT_CTRL function, lets try
+     * it. OpenSC support this function. Eventially this should be
+     * a ENGINE_load_cert function if it failes, treat it like a
+     * non fatal error.
+     */
+    {
+	struct {
+	    const char * cert_id;
+	    X509 * cert;
+	} parms;
+
+	parms.cert_id = ctx.cert_file;
+	parms.cert = NULL;
+	ENGINE_ctrl_cmd(e, "LOAD_CERT_CTRL", 0, &parms, NULL, 1); 
+	if (parms.cert) {
+	    id->cert = sk_X509_new_null();
+	    sk_X509_insert(id->cert, parms.cert, 0);	
+	}  
+    }
+
+    if (id->cert == NULL) {
+	ret = load_openssl_cert(context, ctx.cert_file, &id->cert);
+	if (ret)
+	    goto out;
+    }
+
     if (id->private_key == NULL) {
 	krb5_set_error_string(context,
 			      "PKINIT: failed to load private key: %s",