Am Mittwoch 03 Februar 2010 16:02:22 schrieb Christian Horn:
> On Wed, Feb 03, 2010 at 10:56:01AM +0100, Andreas Jellinghaus wrote:
> > if opensc 0.11.12 doesn't work, does an older version of opensc work?
> 
> 0.11.9 works, 0.11.10 is broken for this.

so it has to be between 3715 and 3777.

> pinned down to rev3784, thats the last one working.

doesn't help much. 3785 is a huge merge of trunk into branches/martin/0.12.

you could 
svn co http://www.opensc-
project.org/opensc/browser/branches/martin/0.12?rev=3784
with different revisions, to see where it got broken.

but maybe the analysis from 0.11.9 to 0.11.10 will help already.
unfortunatly a lot of things changed between those two versions:
 52 files changed, 5793 insertions(+), 288 deletions(-)

on the other hand about every change seems to be related to other
drivers or part of the kill-the-warning initiative - stuff that
shouldn't have any impact.

your log files differ with pkcs11-object.c C_FindObjectsInit,
but that function and that file was not changed. the logs have
no context before that, so we can't see what the information
is that opensc read before. so there is not much we can do with
those log files.

...
> gives you the last working version,
...
> gives the broken one.

ok, so I generated the diff that breaks things from that, attached.

I searched for "pub_genfrom" in my mail archive, since we have no
proper history after the svn merge/remove/move, and found this
change, that might be the cause:
Revision: 3769
Author:   s
Date:     2009-10-06 13:32:27 +0000 (Tue, 06 Oct 2009)

Log Message:
-----------
fix OpenSC PKCS#11 object grouping

Thanks to Pierre Ossman


Pierre, any idea what side effects that change could have?

Regards, Andreas
diff -udrNPp --exclude=.svn trunk_3784_plus_partcommit/src/pkcs11/framework-pkcs15.c trunk_3785_bad/src/pkcs11/framework-pkcs15.c
--- trunk_3784_plus_partcommit/src/pkcs11/framework-pkcs15.c	2010-02-03 16:36:08.000000000 +0100
+++ trunk_3785_bad/src/pkcs11/framework-pkcs15.c	2010-02-03 16:36:14.000000000 +0100
@@ -75,6 +75,7 @@ struct pkcs15_cert_object {
 #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;
@@ -84,7 +85,6 @@ struct pkcs15_prkey_object {
 #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 {
@@ -95,7 +95,7 @@ struct pkcs15_pubkey_object {
 };
 #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 || __p15_type(obj) == SC_PKCS15_TYPE_PRKEY_GOSTR3410)
@@ -350,7 +350,7 @@ __pkcs15_create_cert_object(struct pkcs1
 	} 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)
@@ -470,6 +470,9 @@ __pkcs15_prkey_bind_related(struct pkcs1
 	sc_pkcs15_id_t *id = &pk->prv_info->id;
 	unsigned int i;
 
+	sc_debug(context, "Object is a private key and has id %s",
+	         sc_pkcs15_print_id(id));
+
 	for (i = 0; i < fw_data->num_objects; i++) {
 		struct pkcs15_any_object *obj = fw_data->objects[i];
 
@@ -488,18 +491,12 @@ __pkcs15_prkey_bind_related(struct pkcs1
 				*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;
@@ -511,25 +508,43 @@ __pkcs15_prkey_bind_related(struct pkcs1
 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 */
+	sc_debug(context, "Object is a certificate and has id %s",
+	         sc_pkcs15_print_id(id));
+
+	/* 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 pkcs15_cert_object *cert2;
+			struct sc_pkcs15_cert *c2;
 
-		c2 = ((struct pkcs15_cert_object *) obj)->cert_data;
+			cert2 = (struct pkcs15_cert_object *) obj;
+			c2 = cert2->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 (id %s) as issuer",
+				         i, sc_pkcs15_print_id(&cert2->cert_info->id));
+				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;
+			}
 		}
 	}
 }
@@ -547,6 +562,9 @@ pkcs15_bind_related_objects(struct pkcs1
 
 		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)) {
@@ -578,7 +596,7 @@ check_cert_data_read(struct pkcs15_fw_da
 	/* update the related public key object */
 	obj2 = cert->cert_pubkey;
 
-    obj2->pub_data = (sc_pkcs15_pubkey_t *)calloc(1, sizeof(sc_pkcs15_pubkey_t));
+	obj2->pub_data = (sc_pkcs15_pubkey_t *)calloc(1, sizeof(sc_pkcs15_pubkey_t));
 	if (!obj2->pub_data)
 		return SC_ERROR_OUT_OF_MEMORY;
 	memcpy(obj2->pub_data, &cert->cert_data->key, sizeof(sc_pkcs15_pubkey_t));
@@ -613,6 +631,9 @@ pkcs15_add_object(struct sc_pkcs11_slot 
 		  struct pkcs15_any_object *obj,
 		  CK_OBJECT_HANDLE_PTR pHandle)
 {
+	unsigned int i;
+	struct pkcs15_fw_data *card_fw_data;
+
 	if (obj == NULL
 	 || (obj->base.flags & (SC_PKCS11_OBJECT_HIDDEN | SC_PKCS11_OBJECT_RECURS)))
 		return;
@@ -632,14 +653,23 @@ pkcs15_add_object(struct sc_pkcs11_slot 
 
 	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);
-		break;
 	case SC_PKCS15_TYPE_PRKEY_GOSTR3410:
-		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 ((struct pkcs15_any_object*)(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);
@@ -818,9 +848,14 @@ static CK_RV pkcs15_create_tokens(struct
 		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)) {
@@ -1020,7 +1055,7 @@ static CK_RV pkcs15_init_pin(struct sc_p
 
 	rc = sc_pkcs15init_bind(p11card->card, "pkcs15", NULL, &profile);
 	if (rc < 0) {
-		sc_lock(p11card->card);
+		sc_unlock(p11card->card);
 		return sc_to_cryptoki_error(rc, p11card->reader);
 	}
 
@@ -1030,8 +1065,8 @@ static CK_RV pkcs15_init_pin(struct sc_p
 	args.pin_len = ulPinLen;
 	rc = sc_pkcs15init_store_pin(fw_data->p15_card, profile, &args);
 
-	sc_lock(p11card->card);
 	sc_pkcs15init_unbind(profile);
+	sc_unlock(p11card->card);
 	if (rc < 0)
 		return sc_to_cryptoki_error(rc, p11card->reader);
 
@@ -1769,7 +1804,7 @@ static CK_RV pkcs15_set_attrib(struct sc
 
 	rc = sc_pkcs15init_bind(p11card->card, "pkcs15", NULL, &profile);
 	if (rc < 0) {
-		rc = sc_unlock(p11card->card);
+		sc_unlock(p11card->card);
 		return sc_to_cryptoki_error(rc, p11card->reader);
 	}
 
@@ -2000,25 +2035,43 @@ static CK_RV pkcs15_prkey_get_attribute(
 	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:
@@ -2053,7 +2106,7 @@ static CK_RV pkcs15_prkey_get_attribute(
 		break;
 	case CKA_KEY_TYPE:
 		check_attribute_buffer(attr, sizeof(CK_KEY_TYPE));
-		if (key && key->algorithm == SC_ALGORITHM_GOSTR3410)
+		if (prkey->prv_p15obj->type == SC_PKCS15_TYPE_PRKEY_GOSTR3410)
 			*(CK_KEY_TYPE*)attr->pValue = CKK_GOSTR3410;
 		else
 			*(CK_KEY_TYPE*)attr->pValue = CKK_RSA;
@@ -2157,9 +2210,6 @@ static CK_RV pkcs15_prkey_sign(struct sc
 	case CKM_RSA_X_509:
 		flags = SC_ALGORITHM_RSA_RAW;
 		break;
-	case CKM_OPENSC_GOST: /* FIXME: */
-		flags = SC_ALGORITHM_GOST;
-		break;
 	case CKM_GOSTR3410:
 		flags = SC_ALGORITHM_GOSTR3410_HASH_NONE;
 		break;
@@ -2235,10 +2285,8 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_se
 	case CKM_RSA_X_509:
 		flags |= SC_ALGORITHM_RSA_RAW;
 		break;
-	case CKM_OPENSC_GOST:
-		flags |= SC_ALGORITHM_GOST;
 	default:
-		return CKR_MECHANISM_INVALID;		
+		return CKR_MECHANISM_INVALID;
 	}
 
 	rv = sc_lock(ses->slot->card->card);
@@ -2336,7 +2384,7 @@ static CK_RV pkcs15_pubkey_get_attribute
 				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;
 
@@ -2886,22 +2934,6 @@ static int register_mechanisms(struct sc
 		}
 		if (alg_info->algorithm == SC_ALGORITHM_GOSTR3410)
 			flags |= alg_info->flags;
-#if 0 /* FIXME: */
-		if (alg_info->algorithm == SC_ALGORITHM_GOST){
-		    mech_info.flags = CKF_HW | CKF_SIGN | CKF_ENCRYPT | CKF_DECRYPT;
-		    #ifdef ENABLE_OPENSSL
-		    mech_info.flags |= CKF_VERIFY;
-		    #endif
-		    mech_info.ulMinKeySize = 32;
-		    mech_info.ulMaxKeySize = 32;
-		    mt = sc_pkcs11_new_fw_mechanism(CKM_OPENSC_GOST,
-					&mech_info, CKK_RSA, NULL);
-		    rc = sc_pkcs11_register_mechanism(p11card, mt);
-			sc_debug(card->ctx, "register GOST!!! %d", rc);
-			if(rc < 0)
-				return rc;	
-		}
-#endif
 		alg_info++;
 	}
 
diff -udrNPp --exclude=.svn trunk_3784_plus_partcommit/src/pkcs11/pkcs11-global.c trunk_3785_bad/src/pkcs11/pkcs11-global.c
--- trunk_3784_plus_partcommit/src/pkcs11/pkcs11-global.c	2010-02-03 16:36:08.000000000 +0100
+++ trunk_3785_bad/src/pkcs11/pkcs11-global.c	2010-02-03 16:36:14.000000000 +0100
@@ -175,7 +175,8 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs
 #if !defined(_WIN32)
 	pid_t current_pid = getpid();
 #endif
-	int i, rc, rv;
+	unsigned int i;
+	int  rc, rv;
 	sc_context_param_t ctx_opts;
 
 	/* Handle fork() exception */
@@ -323,7 +324,7 @@ CK_RV C_GetSlotList(CK_BBOOL       token
 		    CK_ULONG_PTR   pulCount)      /* receives the number of slots */
 {
 	CK_SLOT_ID_PTR found = NULL;
-	int i;
+	unsigned int i;
 	CK_ULONG numMatches;
 	sc_pkcs11_slot_t *slot;
 	CK_RV rv;
diff -udrNPp --exclude=.svn trunk_3784_plus_partcommit/src/pkcs11/pkcs11-opensc.h trunk_3785_bad/src/pkcs11/pkcs11-opensc.h
--- trunk_3784_plus_partcommit/src/pkcs11/pkcs11-opensc.h	2010-02-03 16:36:08.000000000 +0100
+++ trunk_3785_bad/src/pkcs11/pkcs11-opensc.h	2010-02-03 16:36:14.000000000 +0100
@@ -3,8 +3,4 @@
 
 /* OpenSC specific extensions */
 
-#define CKK_OPENSC_GOST	(CKK_VENDOR_DEFINED+1)
-#define CKA_OPENSC_GOST	(CKA_VENDOR_DEFINED+1)
-#define CKM_OPENSC_GOST	(CKM_VENDOR_DEFINED+1)
-
 #endif

Attachment: change.mbox
Description: application/mbox

_______________________________________________
opensc-devel mailing list
opensc-devel@lists.opensc-project.org
http://www.opensc-project.org/mailman/listinfo/opensc-devel

Reply via email to