pkcs15init: add update_cert functionality

classic Classic list List threaded Threaded
11 messages Options
Reply | Threaded
Open this post in threaded view
|

pkcs15init: add update_cert functionality

Stef Hoeben-2
Hi,

here a patch that allows to update a cert (while leaving the private key
intact,
very usefull for expired certs).

If the new cert is not bigger that the old one, the same file is used;
otherwise
the file is deleted and a new one with the same file ID is made.

Comments/questions?

Cheers,
Stef


_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel

update-cert.diff (10K) Download Attachment
Reply | Threaded
Open this post in threaded view
|

Re: pkcs15init: add update_cert functionality

Nils Larsch
Stef Hoeben wrote:

> Hi,
>
> here a patch that allows to update a cert (while leaving the private key
> intact,
> very usefull for expired certs).
>
> If the new cert is not bigger that the old one, the same file is used;
> otherwise
> the file is deleted and a new one with the same file ID is made.
>
> Comments/questions?

as you wish ;-)

> +int
> +sc_pkcs15init_update_certificate(sc_pkcs15_card_t *p15card,
...

> + /* Fill the remaining space in the EF (if any) with zeros */
> + if (certlen < file->size) {
> + unsigned char *tmp = (unsigned char *) calloc(file->size - certlen, 1);
> + if (tmp == NULL) {
> + r = SC_ERROR_OUT_OF_MEMORY;
> + goto done;
> + }
> + r = sc_update_binary(p15card->card, certlen, tmp, file->size - certlen, 0);
> + free(tmp);
> + }

why ?

> Index: tools/pkcs15-init.c
> ===================================================================
...

> +static int
> +do_read_check_certificate(sc_pkcs15_cert_t *sc_oldcert,
> + const char *filename, const char *format, sc_pkcs15_der_t *newcert_raw)
> +{
> + X509 *oldcert, *newcert;
> + EVP_PKEY *oldpk, *newpk;
> + BIO *bio = NULL;
> + int r;
> +
> + /* Get the public key from the old cert */
> + bio = BIO_new_mem_buf(sc_oldcert->data, sc_oldcert->data_len);
> + if (bio == NULL)
> + return SC_ERROR_INTERNAL;
> + oldcert = d2i_X509_bio(bio, NULL);
> + BIO_free(bio);

isn't this the same as
        u8 *ptr = sc_oldcert->data;

        oldcert = d2i_X509(NULL, &ptr, sc_oldcert->data_len);
just without using a BIO ?

> + if (oldcert == NULL)
> + return SC_ERROR_INTERNAL;
> + oldpk = X509_get_pubkey(oldcert);
> +
> + /* Read the new cert from file and get it's public key */
> + r = do_read_certificate(filename, format, &newcert);
> + if (r < 0) {
> + X509_free(oldcert);
> + return r;
> + }
> + newpk = X509_get_pubkey(newcert);
> +
> + /* Compare the public keys, there's no high level openssl function for this(?) */

what about "int EVP_PKEY_cmp(const EVP_PKEY *, const EVP_PKEY *)" ?

> + r = SC_ERROR_INVALID_ARGUMENTS;
> + if (oldpk->type == newpk->type)
> + {
> + if ((oldpk->type == EVP_PKEY_DSA) &&
> + !BN_cmp(oldpk->pkey.dsa->p, newpk->pkey.dsa->p) &&
> + !BN_cmp(oldpk->pkey.dsa->q, newpk->pkey.dsa->q) &&
> + !BN_cmp(oldpk->pkey.dsa->g, newpk->pkey.dsa->g))
> + r = 0;
> + else if ((oldpk->type == EVP_PKEY_RSA) &&
> + !BN_cmp(oldpk->pkey.rsa->n, newpk->pkey.rsa->n) &&
> + !BN_cmp(oldpk->pkey.rsa->e, newpk->pkey.rsa->e))
> + r = 0;
> + }
> +
> + X509_free(oldcert);
> +
> + if (r == 0)
> + r = do_convert_cert(newcert_raw, newcert);
> + else
> + error("the public keys in the old and new certificate differ");
> +
> + X509_free(newcert);

as X509_get_pubkey should increase the reference counter of the EVP_PKEY
object newpk you must free it with EVP_PKEY_free (mutatis mutandis for
oldpk).

Cheers,
Nils
_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

RE: pkcs15init: add update_cert functionality

Stef Hoeben-2
In reply to this post by Stef Hoeben-2
Hi Nils,

thx for the openssl improvements (if you know some docs
describing these functions, I'd be happy to read them..)

As for writing zeros at the end of the cert file if the new
cert is smaller: it's not realy nesessary because in that
case the index and offset are added to the EF's path in
the CDF; but it's just nicer not to have part of the old
cert left in the file, IMHO.

Cheers,
Stef

-----Original Message-----
From: Nils Larsch [mailto:[hidden email]]
Sent: donderdag 15 september 2005 13:18
To: Stef Hoeben
Cc: [hidden email]
Subject: Re: [opensc-devel] pkcs15init: add update_cert functionality


Stef Hoeben wrote:

> Hi,
>
> here a patch that allows to update a cert (while leaving the private
> key intact, very usefull for expired certs).
>
> If the new cert is not bigger that the old one, the same file is used;
> otherwise the file is deleted and a new one with the same file ID is
> made.
>
> Comments/questions?

as you wish ;-)

> +int
> +sc_pkcs15init_update_certificate(sc_pkcs15_card_t *p15card,
...
> + /* Fill the remaining space in the EF (if any) with zeros */
> + if (certlen < file->size) {
> + unsigned char *tmp = (unsigned char *) calloc(file->size -
certlen, 1);
> + if (tmp == NULL) {
> + r = SC_ERROR_OUT_OF_MEMORY;
> + goto done;
> + }
> + r = sc_update_binary(p15card->card, certlen, tmp, file->size
- certlen, 0);
> + free(tmp);
> + }

why ?

> Index: tools/pkcs15-init.c
> ===================================================================
...

> +static int
> +do_read_check_certificate(sc_pkcs15_cert_t *sc_oldcert,
> + const char *filename, const char *format, sc_pkcs15_der_t
> +*newcert_raw) {
> + X509 *oldcert, *newcert;
> + EVP_PKEY *oldpk, *newpk;
> + BIO *bio = NULL;
> + int r;
> +
> + /* Get the public key from the old cert */
> + bio = BIO_new_mem_buf(sc_oldcert->data, sc_oldcert->data_len);
> + if (bio == NULL)
> + return SC_ERROR_INTERNAL;
> + oldcert = d2i_X509_bio(bio, NULL);
> + BIO_free(bio);

isn't this the same as
        u8 *ptr = sc_oldcert->data;

        oldcert = d2i_X509(NULL, &ptr, sc_oldcert->data_len);
just without using a BIO ?

> + if (oldcert == NULL)
> + return SC_ERROR_INTERNAL;
> + oldpk = X509_get_pubkey(oldcert);
> +
> + /* Read the new cert from file and get it's public key */
> + r = do_read_certificate(filename, format, &newcert);
> + if (r < 0) {
> + X509_free(oldcert);
> + return r;
> + }
> + newpk = X509_get_pubkey(newcert);
> +
> + /* Compare the public keys, there's no high level openssl function
> +for this(?) */

what about "int EVP_PKEY_cmp(const EVP_PKEY *, const EVP_PKEY *)" ?

> + r = SC_ERROR_INVALID_ARGUMENTS;
> + if (oldpk->type == newpk->type)
> + {
> + if ((oldpk->type == EVP_PKEY_DSA) &&
> + !BN_cmp(oldpk->pkey.dsa->p, newpk->pkey.dsa->p) &&
> + !BN_cmp(oldpk->pkey.dsa->q, newpk->pkey.dsa->q) &&
> + !BN_cmp(oldpk->pkey.dsa->g, newpk->pkey.dsa->g))
> + r = 0;
> + else if ((oldpk->type == EVP_PKEY_RSA) &&
> + !BN_cmp(oldpk->pkey.rsa->n, newpk->pkey.rsa->n) &&
> + !BN_cmp(oldpk->pkey.rsa->e, newpk->pkey.rsa->e))
> + r = 0;
> + }
> +
> + X509_free(oldcert);
> +
> + if (r == 0)
> + r = do_convert_cert(newcert_raw, newcert);
> + else
> + error("the public keys in the old and new certificate
differ");
> +
> + X509_free(newcert);

as X509_get_pubkey should increase the reference counter of the EVP_PKEY
object newpk you must free it with EVP_PKEY_free (mutatis mutandis for
oldpk).

Cheers,
Nils
_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: pkcs15init: add update_cert functionality

Eric Norman
In reply to this post by Stef Hoeben-2

On Sep 15, 2005, at 5:10 AM, Stef Hoeben wrote:

> Hi,
>
> here a patch that allows to update a cert (while leaving the private
> key
> intact,
> very usefull for expired certs).

Be careful!  In the S/MIME protocols, certificates are identified by
issuer
and serial number.  What this means is that if a message was encrypted
in the past using the old, expired certificate, then deleting that
certificate
and replacing it with a new one will prevent mail agents from being able
to locate the key and decrypt the message.  Even if the new certificate
has the same public key.

This is really a documentation/usage problem, but methinks it says
something about what default behavior should be.

Eric Norman
University of WIsconsin

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

RE: pkcs15init: add update_cert functionality

Stef Hoeben-2
In reply to this post by Stef Hoeben-2
Hm, nasty issue indeed...

What could be done is to re-update again with the old cert
if mails need to be recovered (people should have a backup
of their encryption keys anyway), but I'll add a warning
in the usage info...

Thx,
Stef


-----Original Message-----
From: Eric Norman [mailto:[hidden email]]
Sent: donderdag 15 september 2005 16:53
To: OpenSC List
Subject: Re: [opensc-devel] pkcs15init: add update_cert functionality



On Sep 15, 2005, at 5:10 AM, Stef Hoeben wrote:

> Hi,
>
> here a patch that allows to update a cert (while leaving the private
> key
> intact,
> very usefull for expired certs).

Be careful!  In the S/MIME protocols, certificates are identified by
issuer
and serial number.  What this means is that if a message was encrypted in
the past using the old, expired certificate, then deleting that
certificate
and replacing it with a new one will prevent mail agents from being able to
locate the key and decrypt the message.  Even if the new certificate has the
same public key.

This is really a documentation/usage problem, but methinks it says something
about what default behavior should be.

Eric Norman
University of WIsconsin

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

RE: pkcs15init: add update_cert functionality

Stef Hoeben-2
In reply to this post by Stef Hoeben-2
Hi Nils,

can't find an EVP_PKEY_cmp() in my openssl-0.9.7d, only an
EVP_PKEY_cmp_parameters() which only works for DSA?

Looks like it's been added only in 0.9.8, which raises the
question if it's not too recent?

Cheers,
Stef

-----Original Message-----
From: Nils Larsch [mailto:[hidden email]]
Sent: donderdag 15 september 2005 13:18
To: Stef Hoeben
Cc: [hidden email]
Subject: Re: [opensc-devel] pkcs15init: add update_cert functionality


> + if (oldcert == NULL)
> + return SC_ERROR_INTERNAL;
> + oldpk = X509_get_pubkey(oldcert);
> +
> + /* Read the new cert from file and get it's public key */
> + r = do_read_certificate(filename, format, &newcert);
> + if (r < 0) {
> + X509_free(oldcert);
> + return r;
> + }
> + newpk = X509_get_pubkey(newcert);
> +
> + /* Compare the public keys, there's no high level openssl function
> +for this(?) */

what about "int EVP_PKEY_cmp(const EVP_PKEY *, const EVP_PKEY *)" ?
_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: pkcs15init: add update_cert functionality

Nils Larsch
Stef Hoeben wrote:
> Hi Nils,
>
> can't find an EVP_PKEY_cmp() in my openssl-0.9.7d, only an
> EVP_PKEY_cmp_parameters() which only works for DSA?
>
> Looks like it's been added only in 0.9.8, which raises the
> question if it's not too recent?

ops, sorry. You are right is has been recently added in 0.9.8
and above => it's definitly too recent. What about letting configure
finding out whether this function exists or not and if not
use a local function ?

Cheers,
Nils
_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: pkcs15init: add update_cert functionality

Nils Larsch
In reply to this post by Eric Norman
Eric Norman wrote:

>
> On Sep 15, 2005, at 5:10 AM, Stef Hoeben wrote:
>
>> Hi,
>>
>> here a patch that allows to update a cert (while leaving the private key
>> intact,
>> very usefull for expired certs).
>
>
> Be careful!  In the S/MIME protocols, certificates are identified by issuer
> and serial number.  What this means is that if a message was encrypted
> in the past using the old, expired certificate, then deleting that
> certificate
> and replacing it with a new one will prevent mail agents from being able
> to locate the key and decrypt the message.  Even if the new certificate
> has the same public key.

true, however due to the limited space on a smartcard you can't really
store much expired certs on the token. As Stef already wrote the user
should have a backup of the encryption key (+ certificate) anyway (for
example to prevent data loss if the card suddenly dies)

>
> This is really a documentation/usage problem, but methinks it says
> something about what default behavior should be.

it's more a certificate management problem, but that's definitely
something that should be put a card personalization guide ...

Cheers,
Nils
_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: pkcs15init: add update_cert functionality

Stef Hoeben-2
In reply to this post by Nils Larsch
Nils Larsch wrote:

> Stef Hoeben wrote:
>
>> Hi Nils,
>>
>> can't find an EVP_PKEY_cmp() in my openssl-0.9.7d, only an
>> EVP_PKEY_cmp_parameters() which only works for DSA?
>>
>> Looks like it's been added only in 0.9.8, which raises the
>> question if it's not too recent?
>
>
> ops, sorry. You are right is has been recently added in 0.9.8
> and above => it's definitly too recent. What about letting configure
> finding out whether this function exists or not and if not
> use a local function ?


Okay, I already checked all in using the local function; will try
tomorrow to add the pkginfo things.

Cheers,
Stef

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: pkcs15init: add update_cert functionality

Stef Hoeben-2
In reply to this post by Nils Larsch
Hi Nils,

attached is a patch to do it; but not tested with openssl 0.8.0,
it's a bit overkill IMHO...

Cheers,
Stef

Nils Larsch wrote:

> Stef Hoeben wrote:
>
>> Hi Nils,
>>
>> can't find an EVP_PKEY_cmp() in my openssl-0.9.7d, only an
>> EVP_PKEY_cmp_parameters() which only works for DSA?
>>
>> Looks like it's been added only in 0.9.8, which raises the
>> question if it's not too recent?
>
>
> ops, sorry. You are right is has been recently added in 0.9.8
> and above => it's definitly too recent. What about letting configure
> finding out whether this function exists or not and if not
> use a local function ?
>
> Cheers,
> Nils
>

Index: configure.in
===================================================================
--- configure.in (revision 2595)
+++ configure.in (working copy)
@@ -216,6 +216,22 @@
 
 AM_CONDITIONAL(HAVE_OPENSSL, test "x$OPENSSL_MSG" = "xyes")
 
+saved_LIBS="$LIBS"
+saved_CFLAGS="$CFLAGS"
+if test "OPENSSL_MSG" = "xyes"; then
+ CFLAGS="${OPENSSL_CFLAGS} $saved_CFLAGS"
+ LIBS="OPENSSL_LIBS $saved_LIBS"
+ AC_TRY_LINK([
+#include <openssl/evp.h>
+ ], [
+EVP_PKEY_cmp(NULL, NULL);
+ ], [
+ AC_DEFINE(HAVE_OPENSSL_NEW, 1, [openssl version with EVP_PKEY_cmp()])
+ ])
+fi
+LIBS="$saved_LIBS"
+CFLAGS="$saved_CFLAGS"
+
 case "$host" in
 *-*-darwin*)
  if test -z "$PCSC_LIBS" -a -z "$PCSC_LIBS"
Index: src/tools/pkcs15-init.c
===================================================================
--- src/tools/pkcs15-init.c (revision 2595)
+++ src/tools/pkcs15-init.c (working copy)
@@ -941,6 +941,9 @@
  newpk = X509_get_pubkey(newcert);
 
  /* Compare the public keys, there's no high level openssl function for this(?) */
+#ifdef HAVE_OPENSSL_NEW
+ r = EVP_PKEY_cmp(oldpk, newpk) == 0 ? 0 : SC_ERROR_INVALID_ARGUMENTS;
+#else
  r = SC_ERROR_INVALID_ARGUMENTS;
  if (oldpk->type == newpk->type)
  {
@@ -954,7 +957,7 @@
  !BN_cmp(oldpk->pkey.rsa->e, newpk->pkey.rsa->e))
  r = 0;
  }
-
+#endif
  EVP_PKEY_free(newpk);
  EVP_PKEY_free(oldpk);
  X509_free(oldcert);

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel
Reply | Threaded
Open this post in threaded view
|

Re: pkcs15init: add update_cert functionality

Nils Larsch
Stef Hoeben wrote:
> Hi Nils,
>
> attached is a patch to do it; but not tested with openssl 0.8.0,
> it's a bit overkill IMHO...

agree, currently that shouldn't be necessary. Attached is a somewhat
experimental patch that doesn't use EVP_PKEY at all, but that's not
really important.

Cheers,
Nils

Index: src/tools/pkcs15-init.c
===================================================================
--- src/tools/pkcs15-init.c (Revision 2596)
+++ src/tools/pkcs15-init.c (Arbeitskopie)
@@ -919,7 +919,7 @@
  const char *filename, const char *format, sc_pkcs15_der_t *newcert_raw)
 {
  X509 *oldcert, *newcert;
- EVP_PKEY *oldpk, *newpk;
+ X509_PUBKEY *k1, *k2;
  u8 *ptr;
  int r;
 
@@ -937,26 +937,15 @@
  return r;
  }
 
- oldpk = X509_get_pubkey(oldcert);
- newpk = X509_get_pubkey(newcert);
-
  /* Compare the public keys, there's no high level openssl function for this(?) */
  r = SC_ERROR_INVALID_ARGUMENTS;
- if (oldpk->type == newpk->type)
- {
- if ((oldpk->type == EVP_PKEY_DSA) &&
- !BN_cmp(oldpk->pkey.dsa->p, newpk->pkey.dsa->p) &&
- !BN_cmp(oldpk->pkey.dsa->q, newpk->pkey.dsa->q) &&
- !BN_cmp(oldpk->pkey.dsa->g, newpk->pkey.dsa->g))
- r = 0;
- else if ((oldpk->type == EVP_PKEY_RSA) &&
- !BN_cmp(oldpk->pkey.rsa->n, newpk->pkey.rsa->n) &&
- !BN_cmp(oldpk->pkey.rsa->e, newpk->pkey.rsa->e))
- r = 0;
- }
 
- EVP_PKEY_free(newpk);
- EVP_PKEY_free(oldpk);
+ k1 = X509_get_X509_PUBKEY(oldcert);
+ k2 = X509_get_X509_PUBKEY(newcert);
+ if (OBJ_obj2nid(k1->algor->algorithm) == OBJ_obj2nid(k2->algor->algorithm) &&
+    !M_ASN1_BIT_STRING_cmp(k1->public_key, k2->public_key))
+ r = 0;
+
  X509_free(oldcert);
 
  if (r == 0)
@@ -980,7 +969,6 @@
  sc_pkcs15_object_t *obj;
  sc_pkcs15_cert_info_t *certinfo;
  sc_pkcs15_cert_t *oldcert = NULL;
- X509 *newcert = NULL;
  sc_pkcs15_der_t newcert_raw;
  int r;
 

_______________________________________________
opensc-devel mailing list
[hidden email]
http://www.opensc.org/cgi-bin/mailman/listinfo/opensc-devel