Attached is a patch file to implement the changes I outlined below.
I would like comments on this before doing a commit. The one big change was
that the sc_pkcs15_cert now has a pointer to the sc_pkcs15_pubkey. This
required a few changes. I think I got all of them.

On 10/6/2010 3:12 PM, Martin Paljak wrote:
Hello,

On Oct 6, 2010, at 7:10 PM, Douglas E. Engert wrote:
PROPOSAL:

I would like to do the following to cleanup some of the duplication:

Replace sc_pkcs15_pubkey_from_cert with non OpenSSL code, that would
use the sc_asn1_decode_algorithm_id, and other code from parse_x509_cert
to get the algorithm, its parameter, and the pubkey.
OK. This helps with reducing OpenSSL dependancies and reduce duplicated 
functionality.
OpenSC should not implement any pubkey methods itself, so having OpenSSL 
objects does not make much sense and parsing ASN.1 directly is sufficient.


The sc_pkcs15_pubkey_from_cert was removed from pkcs15-pubkey.c and
added and a new version was added to pkcs15-cert.c This new version
calls parse_x509_cert, keeps the sc_pkcs15_pubkey, and frees the
cert.


parse_x509_cert would call sc_pkcs15_pubkey_from_cert.

The sc_pubkey would contain an sc_algorithm_id (or a pointer to one.)

It has a pointer to it.


The sc_pkcs15_pubkey_rsa would not change, but the
sc_pkcs15_pubkey_dsa would change, as the DSA parameters are now
in the sc_algorithm_id parameters.
I don't have a card to verify, but is there any hope currently that a 
pre-initialized card with a DSA key could actually work?
pkcs15-init sure does not support creating DSA keys, so I doubt anything else 
works as well, skimming through the rest of the code leaves the same impression.

So I would not say it would be improving/changing DSA related code, it would be 
implementing DSA support. Thus anything goes.


I have not done anything with DSA for this yet.


The processing of the goostr3410 looks like it not completed,
as the algorithm parameters where never copied to the
sc_pkcs15_pubkey_gostr3410. So very little would need to change.
as the parameters would be in the sc_algrithm_id that is part
of  the sc_pubkey.

The sc_pkcs15_cert rather then having a sc_pkcs15_pubkey, would
have a pointer to one.


Using pointers rather then embedding the algorithm and pubkey in
other structure would allow one to parts a certificate, and copy
the pubkey pointer then free the certificate.
Makes sense.

I hoped to prepare the release candidates for 0.11.14/0.12.0 but as my office 
internet connection got screwed I need to wait for the ISP guy to come and 
fix/replace the dsl router so that non-http download and any kind of upload 
traffic would actually survive more than a few packets :/ I gave up trying to 
upload anything. That would make sense for 0.12.1 if that feels like a 
reasonable target.



--

 Douglas E. Engert  <deeng...@anl.gov>
 Argonne National Laboratory
 9700 South Cass Avenue
 Argonne, Illinois  60439
 (630) 252-5444
Index: pkcs11/framework-pkcs15.c
===================================================================
--- pkcs11/framework-pkcs15.c   (revision 4799)
+++ pkcs11/framework-pkcs15.c   (working copy)
@@ -426,16 +426,14 @@
          return rv;    
        
        if (p15_cert) {
-               obj2->pub_data = &p15_cert->key;
-               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, &p15_cert->key, 
sizeof(sc_pkcs15_pubkey_t));
+                /* we take the pubkey from the cert, as it in not needed */
+               obj2->pub_data = p15_cert->key;
                /* invalidate public data of the cert object so that 
sc_pkcs15_cert_free
                 * does not free the public key data as well (something like
                 * sc_pkcs15_pubkey_dup would have been nice here) -- Nils
                 */
-               memset(&p15_cert->key, 0, sizeof(sc_pkcs15_pubkey_t));
+               p15_cert->key = NULL;
+               
        } else
                obj2->pub_data = NULL; /* will copy from cert when cert is read 
*/
 
Index: libopensc/card-piv.c
===================================================================
--- libopensc/card-piv.c        (revision 4799)
+++ libopensc/card-piv.c        (working copy)
@@ -998,8 +998,10 @@
 
                /* end of read pub key from file */
 #else
-               sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"Requires OpenSSL");
-               r = SC_ERROR_NOT_SUPPORTED;
+               if (getenv(keyenvname)) 
+                       sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL,"Requires 
OpenSSL");
+               r = SC_ERROR_FILE_NOT_FOUND;
+               goto err;
 #endif /* ENABLE_OPENSSL */
        } else {
 
Index: libopensc/pkcs15-piv.c
===================================================================
--- libopensc/pkcs15-piv.c      (revision 4799)
+++ libopensc/pkcs15-piv.c      (working copy)
@@ -557,14 +557,14 @@
                        continue;
                }
                /* TODO support EC keys */
-               ckis[i].key_alg = cert_out->key.algorithm;
-               if (cert_out->key.algorithm == SC_ALGORITHM_RSA) {
+               ckis[i].key_alg = cert_out->key->algorithm;
+               if (cert_out->key->algorithm == SC_ALGORITHM_RSA) {
                        /* save modulus_len for pub and priv */
-                       ckis[i].modulus_len = cert_out->key.u.rsa.modulus.len * 
8;
+                       ckis[i].modulus_len = cert_out->key->u.rsa.modulus.len 
* 8;
                } else {
 /*TODO add the SC_ALGORITHM_EC */
 
-                       sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unsuported 
key.algorithm %d", cert_out->key.algorithm);
+                       sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "Unsuported 
key.algorithm %d", cert_out->key->algorithm);
                        ckis[i].modulus_len = 1024; /* set some value for now */
                }
                sc_pkcs15_free_certificate(cert_out);
Index: libopensc/pkcs15-pubkey.c
===================================================================
--- libopensc/pkcs15-pubkey.c   (revision 4799)
+++ libopensc/pkcs15-pubkey.c   (working copy)
@@ -623,81 +623,13 @@
        return SC_SUCCESS;
 }
 
-
-int
-sc_pkcs15_pubkey_from_cert(struct sc_context *ctx,
-               struct sc_pkcs15_der *cert_blob, struct sc_pkcs15_pubkey **out)
-{
-#ifndef ENABLE_OPENSSL
-       SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_NOT_SUPPORTED);
-#else
-       EVP_PKEY *pkey = NULL;
-       X509 *x = NULL;
-       BIO *mem = NULL;
-       struct sc_pkcs15_pubkey *pubkey = NULL;
-       int rv = 0;
-
-       assert(cert_blob && out);
-
-       pubkey = calloc(1, sizeof(struct sc_pkcs15_pubkey));
-       if (!pubkey)
-               SC_TEST_RET(ctx, SC_LOG_DEBUG_NORMAL, SC_ERROR_OUT_OF_MEMORY, 
"Cannot allocate pubkey");
-
-       pubkey->algorithm = SC_ALGORITHM_RSA;
-       do   {  
-               rv = SC_ERROR_INVALID_DATA;
-               mem = BIO_new_mem_buf(cert_blob->value, cert_blob->len);
-               if (!mem)
-                       break;
-
-               x = d2i_X509_bio(mem, NULL);
-               if (!x)
-                       break;
-
-               pkey=X509_get_pubkey(x);
-               if (!pkey || pkey->type != EVP_PKEY_RSA)
-                       break;
-
-               pubkey->u.rsa.modulus.len = BN_num_bytes(pkey->pkey.rsa->n);
-               pubkey->u.rsa.modulus.data = calloc(1, 
pubkey->u.rsa.modulus.len); 
-
-               pubkey->u.rsa.exponent.len = BN_num_bytes(pkey->pkey.rsa->e);
-               pubkey->u.rsa.exponent.data = calloc(1, 
pubkey->u.rsa.exponent.len); 
-
-               rv = SC_ERROR_OUT_OF_MEMORY;
-               if (!pubkey->u.rsa.modulus.data || !pubkey->u.rsa.exponent.data)
-                       break;
-
-               BN_bn2bin(pkey->pkey.rsa->n, pubkey->u.rsa.modulus.data);
-               BN_bn2bin(pkey->pkey.rsa->e, pubkey->u.rsa.exponent.data);
-
-               rv = SC_SUCCESS;
-       } while (0);
-
-       if (pkey)
-               EVP_PKEY_free(pkey);
-
-       if (x)
-               X509_free(x);
-
-       if (mem)
-               BIO_free(mem);
-
-       if (rv)  {
-               sc_pkcs15_free_pubkey(pubkey);
-               pubkey = NULL;
-       }
-
-       *out = pubkey;
-
-       SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, rv);
-#endif
-}
-
-
 void sc_pkcs15_erase_pubkey(struct sc_pkcs15_pubkey *key)
 {
        assert(key != NULL);
+       if (key->alg_id) {
+               sc_asn1_clear_algorithm_id(key->alg_id);
+               free(key->alg_id);
+       }
        switch (key->algorithm) {
        case SC_ALGORITHM_RSA:
                if (key->u.rsa.modulus.data)
Index: libopensc/pkcs15.h
===================================================================
--- libopensc/pkcs15.h  (revision 4799)
+++ libopensc/pkcs15.h  (working copy)
@@ -160,6 +160,7 @@
 
 struct sc_pkcs15_pubkey {
        int algorithm;
+       struct sc_algorithm_id * alg_id;
 
        /* Decoded key */
        union {
@@ -175,6 +176,8 @@
 
 struct sc_pkcs15_prkey {
        unsigned int algorithm;
+/* TODO do we need:    struct sc_algorithm_id * alg_id; */
+
        union {
                struct sc_pkcs15_prkey_rsa rsa;
                struct sc_pkcs15_prkey_dsa dsa;
@@ -207,7 +210,7 @@
        u8 *crl;
        size_t crl_len;
 
-       struct sc_pkcs15_pubkey key;
+       struct sc_pkcs15_pubkey * key;
        u8 *data;       /* DER encoded raw cert */
        size_t data_len;
 };
Index: libopensc/pkcs15-cert.c
===================================================================
--- libopensc/pkcs15-cert.c     (revision 4799)
+++ libopensc/pkcs15-cert.c     (working copy)
@@ -37,6 +37,7 @@
 {
        int r;
        struct sc_algorithm_id pk_alg, sig_alg;
+       struct sc_pkcs15_pubkey pubkey;
        sc_pkcs15_der_t pk = { NULL, 0 };
        u8 *serial = NULL;
        size_t serial_len = 0;
@@ -86,6 +87,8 @@
        size_t objlen;
        
        memset(cert, 0, sizeof(*cert));
+       memset(&pk_alg, 0, sizeof(pk_alg));
+       memset(&pubkey, 0, sizeof(pubkey));
        obj = sc_asn1_verify_tag(ctx, buf, buflen, SC_ASN1_TAG_SEQUENCE | 
SC_ASN1_CONS,
                                 &objlen);
        if (obj == NULL) {
@@ -98,14 +101,23 @@
 
        cert->version++;
 
-       cert->key.algorithm = pk_alg.algorithm;
+       cert->key = malloc(sizeof(struct sc_pkcs15_pubkey));
+       if (cert->key == NULL)
+               return SC_ERROR_OUT_OF_MEMORY;
+       memcpy(cert->key, &pubkey, sizeof(struct sc_pkcs15_pubkey));
+
+       cert->key->alg_id = malloc(sizeof(struct sc_algorithm_id));
+       if (cert->key->alg_id == NULL)
+               return SC_ERROR_OUT_OF_MEMORY;
+       memcpy(cert->key->alg_id, &pk_alg, sizeof(struct sc_algorithm_id));
+       cert->key->algorithm = pk_alg.algorithm;
        pk.len >>= 3;   /* convert number of bits to bytes */
-       cert->key.data = pk;
+       cert->key->data = pk;
 
-       r = sc_pkcs15_decode_pubkey(ctx, &cert->key, pk.value, pk.len);
+       r = sc_pkcs15_decode_pubkey(ctx, cert->key, pk.value, pk.len);
        if (r < 0)
                free(pk.value);
-       sc_asn1_clear_algorithm_id(&pk_alg);
+
        sc_asn1_clear_algorithm_id(&sig_alg);
 
        if (serial && serial_len)   {
@@ -117,6 +129,26 @@
        return r;
 }
 
+int
+sc_pkcs15_pubkey_from_cert(struct sc_context *ctx,
+               struct sc_pkcs15_der *cert_blob, struct sc_pkcs15_pubkey **out)
+{
+       int rv;
+       struct sc_pkcs15_cert * cert;
+
+       cert =  calloc(1, sizeof(struct sc_pkcs15_cert));
+       if (cert == NULL)
+               return SC_ERROR_OUT_OF_MEMORY;
+       
+       rv = parse_x509_cert(ctx, cert_blob->value, cert_blob->len, cert);
+       
+       *out = cert->key;
+       cert->key = NULL;
+       sc_pkcs15_free_certificate(cert);
+
+       SC_FUNC_RETURN(ctx, SC_LOG_DEBUG_NORMAL, rv);
+}
+
 int sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card,
                               const struct sc_pkcs15_cert_info *info,
                               struct sc_pkcs15_cert **cert_out)
@@ -149,7 +181,7 @@
        memset(cert, 0, sizeof(struct sc_pkcs15_cert));
        if (parse_x509_cert(p15card->card->ctx, data, len, cert)) {
                free(data);
-               free(cert);
+               sc_pkcs15_free_certificate(cert);
                return SC_ERROR_INVALID_ASN1_OBJECT;
        }
        cert->data = data;
@@ -286,7 +318,8 @@
 {
        assert(cert != NULL);
 
-       sc_pkcs15_erase_pubkey(&cert->key);
+       if (cert->key)
+               sc_pkcs15_free_pubkey(cert->key);
        free(cert->subject);
        free(cert->issuer);
        free(cert->serial);
Index: libopensc/apdu.c
===================================================================
--- libopensc/apdu.c    (revision 4799)
+++ libopensc/apdu.c    (working copy)
@@ -490,7 +490,8 @@
                                        SC_FUNC_RETURN(ctx, 
SC_LOG_DEBUG_VERBOSE, r);
 
                                if (buflen < le)
-                                       return SC_ERROR_WRONG_LENGTH;
+                               /* copy as much as will fit in requested buffer 
*/
+                                       le = buflen;
 
                                memcpy(buf, tbuf, le);
                                buf    += le;
Index: libopensc/pkcs15-gemsafeGPK.c
===================================================================
--- libopensc/pkcs15-gemsafeGPK.c       (revision 4799)
+++ libopensc/pkcs15-gemsafeGPK.c       (working copy)
@@ -408,9 +408,9 @@
                }
 
                for (j = 0; j < num_keyinfo; j++) { 
-                       if (cert_out->key.u.rsa.modulus.len == 
kinfo[j].modulus_len &&  
-                                       
memcmp(cert_out->key.u.rsa.modulus.data, 
-                                       &kinfo[j].modulus, 
cert_out->key.u.rsa.modulus.len) == 0) { 
+                       if (cert_out->key->u.rsa.modulus.len == 
kinfo[j].modulus_len && 
+                                       
memcmp(cert_out->key->u.rsa.modulus.data, 
+                                       &kinfo[j].modulus, 
cert_out->key->u.rsa.modulus.len) == 0) { 
                        memcpy(&kinfo[j].id, &cert_info.id, 
sizeof(sc_pkcs15_id_t));
                        sc_debug(card->ctx, SC_LOG_DEBUG_NORMAL, "found match");
                        }
_______________________________________________
opensc-devel mailing list
opensc-devel@lists.opensc-project.org
http://www.opensc-project.org/mailman/listinfo/opensc-devel

Reply via email to