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