diff --git a/scd/ChangeLog b/scd/ChangeLog index e0cfda805..32ed893e9 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,12 @@ +2002-08-16 Werner Koch + + * card-common.h (struct p15_private_s): Forward declaration. Add + it to card_ctx_s. + * card.c (card_close): Make sure private data is released. + * card-p15.c (p15_release_private_data): New. + (init_private_data): New to work around an OpenSC weirdness. + (p15_enum_keypairs): Do an OpenSC get_objects only once. + 2002-08-09 Werner Koch * card.c (card_get_serial_and_stamp): Use the tokeinfo serial diff --git a/scd/Makefile.am b/scd/Makefile.am index b306a3a73..8812d1b9a 100644 --- a/scd/Makefile.am +++ b/scd/Makefile.am @@ -23,8 +23,8 @@ INCLUDES = -I../intl -DLOCALEDIR=\"$(localedir)\" bin_PROGRAMS = scdaemon -AM_CPPFLAGS = -I$(top_srcdir)/common $(LIBOPENSC_CFLAGS) $(LIBGCRYPT_CFLAGS) \ - $(LIBKSBA_CFLAGS) +AM_CPPFLAGS = -I$(top_srcdir)/common $(OPENSC_CFLAGS) $(LIBGCRYPT_CFLAGS) \ + $(KSBA_CFLAGS) LDFLAGS = @LDFLAGS@ scdaemon_SOURCES = \ @@ -33,12 +33,9 @@ scdaemon_SOURCES = \ card-common.h \ card-p15.c card-dinsig.c -# fixme: We added -lpcslite because the opensc config script can't cope with -# a static only libopensc. scdaemon_LDADD = ../jnlib/libjnlib.a ../assuan/libassuan.a \ ../common/libcommon.a \ - $(LIBOPENSC_LIBS) $(LIBGCRYPT_LIBS) $(LIBKSBA_LIBS) \ - -lpcsclite -lpthread + $(OPENSC_LIBS) $(LIBGCRYPT_LIBS) $(KSBA_LIBS) diff --git a/scd/card-common.h b/scd/card-common.h index 1c912b744..62b9a8737 100644 --- a/scd/card-common.h +++ b/scd/card-common.h @@ -21,12 +21,16 @@ #ifndef CARD_COMMON_H #define CARD_COMMON_H +/* Declaration of private data structure used by card-p15.c */ +struct p15private_s; + struct card_ctx_s { int reader; /* used reader */ struct sc_context *ctx; struct sc_card *scard; struct sc_pkcs15_card *p15card; /* only if there is a pkcs15 application */ + struct p15private_s *p15priv; /* private data used by card-p15.c */ struct { int initialized; /* the card has been initialied and the function @@ -57,7 +61,8 @@ struct card_ctx_s { int map_sc_err (int rc); int card_help_get_keygrip (KsbaCert cert, unsigned char *array); - +/*-- card-15.c --*/ +void p15_release_private_data (CARD card); /* constructors */ void card_p15_bind (CARD card); diff --git a/scd/card-p15.c b/scd/card-p15.c index 6248ddfe2..c0758161f 100644 --- a/scd/card-p15.c +++ b/scd/card-p15.c @@ -32,6 +32,61 @@ #include "card-common.h" +struct p15private_s { + int n_prkey_rsa_objs; + struct sc_pkcs15_object *prkey_rsa_objs[32]; +}; + + +/* Allocate private data. */ +static int +init_private_data (CARD card) +{ + struct p15private_s *priv; + int rc; + + if (card->p15priv) + return 0; /* already done. */ + + priv = xtrycalloc (1, sizeof *priv); + if (!priv) + return GNUPG_Out_Of_Core; + + /* OpenSC (0.7.0) is a bit strange in that the get_objects functions + tries to be a bit too clever and implicitly does an enumeration + which eventually leads to the fact that every call to this + fucntion returns one more macthing object. The old code in + p15_enum_keypairs assume that it would alwyas return the same + numer of objects and used this to figure out what the last object + enumerated is. We now do an enum_objects just once and keep it + in the private data. */ + rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_PRKEY_RSA, + priv->prkey_rsa_objs, + DIM (priv->prkey_rsa_objs)); + if (rc < 0) + { + log_error ("private keys enumeration failed: %s\n", sc_strerror (rc)); + xfree (priv); + return GNUPG_Card_Error; + } + priv->n_prkey_rsa_objs = rc; + card->p15priv = priv; + return 0; +} + + +/* Release private data used in this module. */ +void +p15_release_private_data (CARD card) +{ + if (!card->p15priv) + return; + xfree (card->p15priv); + card->p15priv = NULL; +} + + + /* See card.c for interface description */ static int p15_enum_keypairs (CARD card, int idx, @@ -39,25 +94,23 @@ p15_enum_keypairs (CARD card, int idx, { int rc; KsbaError krc; - struct sc_pkcs15_object *objs[32], *tmpobj; + struct p15private_s *priv; + struct sc_pkcs15_object *tmpobj; int nobjs; struct sc_pkcs15_prkey_info *pinfo; struct sc_pkcs15_cert_info *certinfo; struct sc_pkcs15_cert *certder; KsbaCert cert; - rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_PRKEY_RSA, - objs, DIM (objs)); - if (rc < 0) - { - log_error ("private keys enumeration failed: %s\n", sc_strerror (rc)); - return GNUPG_Card_Error; - } - nobjs = rc; + rc = init_private_data (card); + if (rc) + return rc; + priv = card->p15priv; + nobjs = priv->n_prkey_rsa_objs; rc = 0; if (idx >= nobjs) return -1; - pinfo = objs[idx]->data; + pinfo = priv->prkey_rsa_objs[idx]->data; /* now we need to read the certificate so that we can calculate the keygrip */ diff --git a/scd/card.c b/scd/card.c index 9c22867a1..34812b8a1 100644 --- a/scd/card.c +++ b/scd/card.c @@ -162,6 +162,8 @@ card_close (CARD card) sc_pkcs15_unbind (card->p15card); card->p15card = NULL; } + if (card->p15priv) + p15_release_private_data (card); if (card->scard) { sc_unlock (card->scard);