On Sat, 3 Oct 2009 11:00:16 +0300
Martin Paljak <[email protected]> wrote:

> Hi,
> 
> I can't use it:
> 
> $ patch -p0 < ../pkcs11.diff
> patching file src/pkcs11/framework-pkcs15.c
> patch: **** malformed patch at line 10: struct pkcs15_prkey_object {
> 
> Please provide a new patch against trunk (which is not @ r18006) as an  
> attachment.
> 

New attempt, this time against r3756 (r18006 was our internal repo, for
those curious :)), as an attachment and without a signature on the
mail. Hopefully everyone can read it this time.

Oh yeah, I also forgot to mention that this patch also adds some more
debug output. I found it helpful to see how the library chooses to
associate objects, even though it currently only prints the index
number.

Rgds
-- 
Pierre Ossman            OpenSource-based Thin Client Technology
System Developer         Telephone: +46-13-21 46 00
Cendio AB                Web: http://www.cendio.com
Index: src/pkcs11/framework-pkcs15.c
===================================================================
--- src/pkcs11/framework-pkcs15.c	(revision 3756)
+++ src/pkcs11/framework-pkcs15.c	(working copy)
@@ -82,6 +82,7 @@
 #define cert_p15obj		base.p15_object
 #define cert_pubkey		base.related_pubkey
 #define cert_issuer		base.related_cert
+#define cert_prvkey		base.related_privkey
 
 struct pkcs15_prkey_object {
 	struct pkcs15_any_object	base;
@@ -91,7 +92,6 @@
 #define prv_flags		base.base.flags
 #define prv_p15obj		base.p15_object
 #define prv_pubkey		base.related_pubkey
-#define prv_cert		base.related_cert
 #define prv_next		base.related_privkey
 
 struct pkcs15_pubkey_object {
@@ -102,7 +102,7 @@
 };
 #define pub_flags		base.base.flags
 #define pub_p15obj		base.p15_object
-#define pub_cert		base.related_cert
+#define pub_genfrom		base.related_cert
 
 #define __p15_type(obj)		(((obj) && (obj)->p15_object)? ((obj)->p15_object->type) : (unsigned int)-1)
 #define is_privkey(obj)		(__p15_type(obj) == SC_PKCS15_TYPE_PRKEY_RSA)
@@ -346,7 +346,7 @@
 	} else
 		obj2->pub_data = NULL; /* will copy from cert when cert is read */
 
-	obj2->pub_cert = object;
+	obj2->pub_genfrom = object;
 	object->cert_pubkey = obj2;
 
 	if (cert_object != NULL)
@@ -484,18 +484,12 @@
 				*pp = (struct pkcs15_prkey_object *) obj;
 			}
 		} else
-		if (is_cert(obj) && !pk->prv_cert) {
-			struct pkcs15_cert_object *cert;
-			
-			cert = (struct pkcs15_cert_object *) obj;
-			if (sc_pkcs15_compare_id(&cert->cert_info->id, id))
-				pk->prv_cert = cert;
-		} else
 		if (is_pubkey(obj) && !pk->prv_pubkey) {
 			struct pkcs15_pubkey_object *pubkey;
 			
 			pubkey = (struct pkcs15_pubkey_object *) obj;
 			if (sc_pkcs15_compare_id(&pubkey->pub_info->id, id)) {
+				sc_debug(context, "Associating object %d as public key", i);
 				pk->prv_pubkey = pubkey;
 				if (pk->prv_info->modulus_length == 0)
 					pk->prv_info->modulus_length = pubkey->pub_info->modulus_length;
@@ -507,25 +501,37 @@
 static void
 __pkcs15_cert_bind_related(struct pkcs15_fw_data *fw_data, struct pkcs15_cert_object *cert)
 {
-	struct sc_pkcs15_cert *c1 = cert->cert_data, *c2;
+	struct sc_pkcs15_cert *c1 = cert->cert_data;
+	sc_pkcs15_id_t *id = &cert->cert_info->id;
 	unsigned int i;
 
-	/* Loop over all certificates see if we find the certificate of
-	 * the issuer */
+	/* Loop over all objects to see if we find the certificate of
+	 * the issuer and the associated private key */
 	for (i = 0; i < fw_data->num_objects; i++) {
 		struct pkcs15_any_object *obj = fw_data->objects[i];
 
-		if (!is_cert(obj) || obj == (struct pkcs15_any_object *) cert)
-			continue;
+		if (is_cert(obj) && obj != (struct pkcs15_any_object *) cert) {
+			struct sc_pkcs15_cert *c2;
 
-		c2 = ((struct pkcs15_cert_object *) obj)->cert_data;
+			c2 = ((struct pkcs15_cert_object *) obj)->cert_data;
 
-		if (!c1 || !c2 || !c1->issuer_len || !c2->subject_len)
-			continue;
-		if (c1->issuer_len == c2->subject_len
-		 && !memcmp(c1->issuer, c2->subject, c1->issuer_len)) {
-			cert->cert_issuer = (struct pkcs15_cert_object *) obj;
-			return;
+			if (!c1 || !c2 || !c1->issuer_len || !c2->subject_len)
+				continue;
+			if (c1->issuer_len == c2->subject_len
+			 && !memcmp(c1->issuer, c2->subject, c1->issuer_len)) {
+				sc_debug(context, "Associating object %d as issuer", i);
+				cert->cert_issuer = (struct pkcs15_cert_object *) obj;
+				return;
+			}
+		} else
+		if (is_privkey(obj) && !cert->cert_prvkey) {
+			struct pkcs15_prkey_object *pk;
+			
+			pk = (struct pkcs15_prkey_object *) obj;
+			if (sc_pkcs15_compare_id(&pk->prv_info->id, id)) {
+				sc_debug(context, "Associating object %d as private key", i);
+				cert->cert_prvkey = pk;
+			}
 		}
 	}
 }
@@ -543,6 +549,9 @@
 
 		if (obj->base.flags & SC_PKCS11_OBJECT_HIDDEN)
 			continue;
+
+		sc_debug(context, "Looking for objects related to object %d", i);
+
 		if (is_privkey(obj)) {
 			__pkcs15_prkey_bind_related(fw_data, (struct pkcs15_prkey_object *) obj);
 		} else if (is_cert(obj)) {
@@ -609,6 +618,9 @@
 		  struct pkcs15_any_object *obj,
 		  CK_OBJECT_HANDLE_PTR pHandle)
 {
+	int i;
+	struct pkcs15_fw_data *card_fw_data;
+
 	if (obj == NULL
 	 || (obj->base.flags & (SC_PKCS11_OBJECT_HIDDEN | SC_PKCS11_OBJECT_RECURS)))
 		return;
@@ -633,9 +645,22 @@
 
 	switch (__p15_type(obj)) {
 	case SC_PKCS15_TYPE_PRKEY_RSA:
-		if (obj->related_cert == NULL)
-			pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_pubkey, NULL);
-		pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_cert, NULL);
+		pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_pubkey, NULL);
+		card_fw_data = (struct pkcs15_fw_data *) slot->card->fw_data;
+		for (i = 0; i < card_fw_data->num_objects; i++) {
+			struct pkcs15_any_object *obj2 = card_fw_data->objects[i];
+			struct pkcs15_cert_object *cert;
+
+			if (!is_cert(obj2))
+				continue;
+
+			cert = (struct pkcs15_cert_object*) obj2;
+
+			if (cert->cert_prvkey != obj)
+				continue;
+		
+			pkcs15_add_object(slot, obj2, NULL);
+		}
 		break;
 	case SC_PKCS15_TYPE_CERT_X509:
 		pkcs15_add_object(slot, (struct pkcs15_any_object *) obj->related_pubkey, NULL);
@@ -791,10 +816,15 @@
 		for (j=0; j < fw_data->num_objects; j++) {
 			struct pkcs15_any_object *obj = fw_data->objects[j];
 
+			/* "Fake" objects we've generated */
 			if (__p15_type(obj) == (unsigned int)-1)
 				continue;
-			else if (!sc_pkcs15_compare_id(&pin_info->auth_id, &obj->p15_object->auth_id))
+			/* Some objects have an auth_id even though they are
+			 * not private. Just ignore those... */
+			if (!(obj->p15_object->flags & SC_PKCS15_CO_FLAG_PRIVATE))
 				continue;
+			if (!sc_pkcs15_compare_id(&pin_info->auth_id, &obj->p15_object->auth_id))
+				continue;
 
 			if (is_privkey(obj)) {
 				sc_debug(context, "Adding private key %d to PIN %d\n", j, i);
@@ -1932,25 +1962,43 @@
 	unsigned int usage;
 	size_t len;
 
-	/* will use modulus from cert, or pubkey if possible */
-	if (prkey->prv_cert && prkey->prv_cert->cert_pubkey) {
-		/* make sure we have read the cert to get modulus etc but only if needed. */
-		switch(attr->type) {
-			case CKA_MODULUS:
-			case CKA_PUBLIC_EXPONENT:
-			case CKA_MODULUS_BITS:
-				if (check_cert_data_read(fw_data, prkey->prv_cert) != 0) {
-					/* no cert found, maybe we have a pub_key */
-					if (prkey->prv_pubkey && prkey->prv_pubkey->pub_data)
-						key = prkey->prv_pubkey->pub_data; /* may be NULL */
-				} else
-					key = prkey->prv_cert->cert_pubkey->pub_data;
-				break;
-			default:
-				key = prkey->prv_cert->cert_pubkey->pub_data;
+	/* PKCS#11 requires us to supply CKA_MODULUS for private keys,
+	 * although that is not generally available from a smart card
+	 * (the key is supposed to be safely locked away after all).
+	 *
+	 * To work around this, we hope that we either have an associated
+	 * public key, or we try to find a certificate with the
+	 * corresponding public key.
+	 *
+	 * Note: We do the same thing for CKA_PUBLIC_EXPONENT as some
+	 *       applications assume they can get that from the private
+	 *       key, something PKCS#11 doesn't guarantee.
+	 */
+	if ((attr->type == CKA_MODULUS) || (attr->type == CKA_PUBLIC_EXPONENT)) {
+		/* First see if we have a associated public key */
+		if (prkey->prv_pubkey)
+			key = prkey->prv_pubkey->pub_data;
+		else {
+			/* Try to find a certificate with the public key */
+			unsigned int i;
+
+			for (i = 0; i < fw_data->num_objects; i++) {
+				struct pkcs15_any_object *obj = fw_data->objects[i];
+				struct pkcs15_cert_object *cert;
+
+				if (!is_cert(obj))
+					continue;
+
+				cert = (struct pkcs15_cert_object*) obj;
+
+				if (cert->cert_prvkey != prkey)
+					continue;
+
+				if (check_cert_data_read(fw_data, cert) == 0)
+					key = cert->cert_pubkey->pub_data;
+			}
 		}
-	} else if (prkey->prv_pubkey)
-		key = prkey->prv_pubkey->pub_data;
+	}
 
 	switch (attr->type) {
 	case CKA_CLASS:
@@ -2272,7 +2320,7 @@
 				CK_ATTRIBUTE_PTR attr)
 {
 	struct pkcs15_pubkey_object *pubkey = (struct pkcs15_pubkey_object*) object;
-	struct pkcs15_cert_object *cert = pubkey->pub_cert;
+	struct pkcs15_cert_object *cert = pubkey->pub_genfrom;
 	struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) session->slot->card->fw_data;
 	size_t len;
 
_______________________________________________
opensc-devel mailing list
[email protected]
http://www.opensc-project.org/mailman/listinfo/opensc-devel

Reply via email to