[prev in list] [next in list] [prev in thread] [next in thread] 

List:       openssh-unix-dev
Subject:    OpenSC smartcard access should use raw public keys,
From:       Daniel Kahn Gillmor <dkg-openssh.com () fifthhorseman ! net>
Date:       2008-06-20 6:25:52
Message-ID: 878wx0zkpb.fsf () squeak ! fifthhorseman ! net
[Download RAW message or body]

[Attachment #2 (multipart/signed)]

[Attachment #4 (multipart/mixed)]

Hi OpenSSH people--

The OpenSC smartcard framework supports access to both raw public keys
and X.509 certificates on crypto tokens.  When OpenSSH is compiled
--with-opensc, it currently looks for X.509 certificates on any
smartcard it uses.  But OpenSSH itself uses raw public keys (and not
X.509), so requiring the presence of an X.509 cert on the smartcard is
unnecessary and potentially problematic.

Everyone who has an X.509 certificate already has (embedded in the
cert) a public key.  But you can load a raw key onto a card without
having a certificate.  So raw keys would seem to be the lowest common
denominator.  Is there some other reason to require an X.509
certificate that i'm missing?

The attached patch allows OpenSSH to use certificateless RSA keys on
any OpenSC-supported hardware crypto token.  Fixing this bug also
simplifies the sc_read_pubkey() implementation, reduces the number of
#includes in scard-opensc.c, and removes a compilation warning, for
whatever that's worth.

The patch was developed and tested against openssh 4.7p1 (from debian
unstable), but it also applies cleanly to CVS HEAD.  I used
libopensc2-dev version 0.11.4, and did my testing against an Axalto
CryptoFlex eGate 32k hardware token.

I'd appreciate any feedback on the patch.  If i can do anything to
encourage its adoption into the upstream codebase, let me know what it
needs.

Thanks for all the great work on OpenSSH!

Regards,

        --dkg

PS if you're wondering why i care: i just added a second key to my
   smartcard.  Although I added a gratuitous certificate to the card
   for my first key for the benefit of OpenSSH, the addition of the
   second key appears to have filled the card: there is no space for a
   second certificate, according to pkcs15-init.  So if i want to be
   able to use both keys, OpenSSH must not require X.509 certificates
   gratuitously.


["use-public-keys-instead-of-certs-with-opensc.patch" (text/x-diff)]

--- openssh-4.7p1/scard-opensc.c	2007-03-12 16:35:39.000000000 -0400
+++ openssh-4.7p1.dkg/scard-opensc.c	2008-06-20 01:49:58.000000000 -0400
@@ -28,9 +28,6 @@
 
 #include <sys/types.h>
 
-#include <openssl/evp.h>
-#include <openssl/x509.h>
-
 #include <stdarg.h>
 #include <string.h>
 
@@ -65,7 +62,7 @@
 
 struct sc_priv_data
 {
-	struct sc_pkcs15_id cert_id;
+	struct sc_pkcs15_id pubkey_id;
 	int ref_count;
 };
 
@@ -136,7 +133,7 @@
 			goto err;
 		}
 	}
-	r = sc_pkcs15_find_prkey_by_id_usage(p15card, &priv->cert_id,
+	r = sc_pkcs15_find_prkey_by_id_usage(p15card, &priv->pubkey_id,
 		usage, &key_obj);
 	if (r) {
 		error("Unable to find private key from SmartCard: %s",
@@ -343,52 +340,48 @@
 }
 
 static int
-sc_read_pubkey(Key * k, const struct sc_pkcs15_object *cert_obj)
+sc_read_pubkey(Key * k, const struct sc_pkcs15_object *pubkey_obj)
 {
 	int r;
-	sc_pkcs15_cert_t *cert = NULL;
+	sc_pkcs15_pubkey_t *pkey = NULL;
 	struct sc_priv_data *priv = NULL;
-	sc_pkcs15_cert_info_t *cinfo = cert_obj->data;
+	sc_pkcs15_pubkey_info_t *cinfo = pubkey_obj->data;
 
-	X509 *x509 = NULL;
-	EVP_PKEY *pubkey = NULL;
-	u8 *p;
 	char *tmp;
 
-	debug("sc_read_pubkey() with cert id %02X", cinfo->id.value[0]);
-	r = sc_pkcs15_read_certificate(p15card, cinfo, &cert);
+	debug("sc_read_pubkey() with pubkey id %02X", cinfo->id.value[0]);
+	r = sc_pkcs15_read_pubkey(p15card, pubkey_obj, &pkey);
 	if (r) {
-		logit("Certificate read failed: %s", sc_strerror(r));
-		goto err;
-	}
-	x509 = X509_new();
-	if (x509 == NULL) {
-		r = -1;
-		goto err;
-	}
-	p = cert->data;
-	if (!d2i_X509(&x509, &p, cert->data_len)) {
-		logit("Unable to parse X.509 certificate");
-		r = -1;
+		logit("Public key read failed: %s", sc_strerror(r));
 		goto err;
 	}
-	sc_pkcs15_free_certificate(cert);
-	cert = NULL;
-	pubkey = X509_get_pubkey(x509);
-	X509_free(x509);
-	x509 = NULL;
-	if (pubkey->type != EVP_PKEY_RSA) {
-		logit("Public key is of unknown type");
+	
+	if (pkey->algorithm != SC_ALGORITHM_RSA) {
+		logit("Smartcard key is not RSA");
 		r = -1;
-		goto err;
+ 		goto err;
 	}
-	k->rsa = EVP_PKEY_get1_RSA(pubkey);
-	EVP_PKEY_free(pubkey);
+
+	k->rsa = RSA_new();
+
+	/* this is only a pubkey, so wipe secret values: */
+	k->rsa->d = NULL;
+	k->rsa->p = NULL;
+	k->rsa->q = NULL;
+	k->rsa->dmp1 = NULL;
+	k->rsa->dmq1 = NULL;
+	k->rsa->iqmp = NULL;
+
+	k->rsa->n = BN_bin2bn(pkey->u.rsa.modulus.data, pkey->u.rsa.modulus.len, NULL);
+	k->rsa->e = BN_bin2bn(pkey->u.rsa.exponent.data, pkey->u.rsa.exponent.len, NULL);
+
+	sc_pkcs15_free_pubkey(pkey);
+	pkey = NULL;
 
 	k->rsa->flags |= RSA_FLAG_SIGN_VER;
 	RSA_set_method(k->rsa, sc_get_rsa_method());
 	priv = xmalloc(sizeof(struct sc_priv_data));
-	priv->cert_id = cinfo->id;
+	priv->pubkey_id = cinfo->id;
 	priv->ref_count = 1;
 	RSA_set_app_data(k->rsa, priv);
 
@@ -399,12 +392,8 @@
 
 	return 0;
 err:
-	if (cert)
-		sc_pkcs15_free_certificate(cert);
-	if (pubkey)
-		EVP_PKEY_free(pubkey);
-	if (x509)
-		X509_free(x509);
+	if (pkey)
+		sc_pkcs15_free_pubkey(pkey);
 	return r;
 }
 
@@ -413,8 +402,8 @@
 {
 	Key *k, **keys;
 	int i, r, real_count = 0, key_count;
-	sc_pkcs15_id_t cert_id;
-	sc_pkcs15_object_t *certs[32];
+	sc_pkcs15_id_t pubkey_id;
+	sc_pkcs15_object_t *pubkeys[32];
 	char *buf = xstrdup(id), *p;
 
 	debug("sc_get_keys called: id = %s", id);
@@ -423,11 +412,11 @@
 		xfree(sc_pin);
 	sc_pin = (pin == NULL) ? NULL : xstrdup(pin);
 
-	cert_id.len = 0;
+	pubkey_id.len = 0;
 	if ((p = strchr(buf, ':')) != NULL) {
 		*p = 0;
 		p++;
-		sc_pkcs15_hex_string_to_id(p, &cert_id);
+		sc_pkcs15_hex_string_to_id(p, &pubkey_id);
 	}
 	r = sscanf(buf, "%d", &sc_reader_id);
 	xfree(buf);
@@ -441,20 +430,20 @@
 			goto err;
 		}
 	}
-	if (cert_id.len) {
-		r = sc_pkcs15_find_cert_by_id(p15card, &cert_id, &certs[0]);
+	if (pubkey_id.len) {
+		r = sc_pkcs15_find_pubkey_by_id(p15card, &pubkey_id, &pubkeys[0]);
 		if (r < 0)
 			goto err;
 		key_count = 1;
 	} else {
-		r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_CERT_X509,
-					  certs, 32);
+		r = sc_pkcs15_get_objects(p15card, SC_PKCS15_TYPE_PUBKEY,
+					  pubkeys, 32);
 		if (r == 0) {
-			logit("No certificates found on smartcard");
+			logit("No public keys found on smartcard");
 			r = -1;
 			goto err;
 		} else if (r < 0) {
-			error("Certificate enumeration failed: %s",
+			error("Public key enumeration failed: %s",
 			      sc_strerror(r));
 			goto err;
 		}
@@ -465,15 +454,15 @@
 	keys = xcalloc(key_count * 2 + 1, sizeof(Key *));
 	for (i = 0; i < key_count; i++) {
 		sc_pkcs15_object_t *tmp_obj = NULL;
-		cert_id = ((sc_pkcs15_cert_info_t *)(certs[i]->data))->id;
-		if (sc_pkcs15_find_prkey_by_id(p15card, &cert_id, &tmp_obj))
-			/* skip the public key (certificate) if no
+		pubkey_id = ((sc_pkcs15_pubkey_info_t *)(pubkeys[i]->data))->id;
+		if (sc_pkcs15_find_prkey_by_id(p15card, &pubkey_id, &tmp_obj))
+			/* skip the public key if no
 			 * corresponding private key is present */
 			continue;
 		k = key_new(KEY_RSA);
 		if (k == NULL)
 			break;
-		r = sc_read_pubkey(k, certs[i]);
+		r = sc_read_pubkey(k, pubkeys[i]);
 		if (r) {
 			error("sc_read_pubkey failed: %s", sc_strerror(r));
 			key_free(k);
@@ -516,7 +505,7 @@
 		/* internal error => return default label */
 		return xstrdup("smartcard key");
 	}
-	r = sc_pkcs15_find_prkey_by_id(p15card, &priv->cert_id, &key_obj);
+	r = sc_pkcs15_find_prkey_by_id(p15card, &priv->pubkey_id, &key_obj);
 	if (r) {
 		logit("Unable to find private key from SmartCard: %s",
 		      sc_strerror(r));

[Attachment #8 (application/pgp-signature)]

_______________________________________________
openssh-unix-dev mailing list
openssh-unix-dev@mindrot.org
https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev


[prev in list] [next in list] [prev in thread] [next in thread] 

Configure | About | News | Add a list | Sponsored by KoreLogic