diff --git a/scd/ChangeLog b/scd/ChangeLog index 32ed893e9..da3cdb42a 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,11 +1,17 @@ 2002-08-16 Werner Koch + * scdaemon.c: Include i18n.h. + * 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_enum_certs): New. * 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. + (p15_enum_certs): New. + (card_p15_bind): Bind new function. + * command.c (cmd_learn): Return information about the certificates. 2002-08-09 Werner Koch diff --git a/scd/card-common.h b/scd/card-common.h index 62b9a8737..50014cead 100644 --- a/scd/card-common.h +++ b/scd/card-common.h @@ -40,6 +40,7 @@ struct card_ctx_s { int (*enum_keypairs) (CARD card, int idx, unsigned char *keygrip, char **keyid); + int (*enum_certs) (CARD card, int idx, char **certid, int *certtype); int (*read_cert) (CARD card, const char *certidstr, unsigned char **cert, size_t *ncert); int (*sign) (CARD card, diff --git a/scd/card-p15.c b/scd/card-p15.c index c0758161f..25502a610 100644 --- a/scd/card-p15.c +++ b/scd/card-p15.c @@ -35,6 +35,8 @@ struct p15private_s { int n_prkey_rsa_objs; struct sc_pkcs15_object *prkey_rsa_objs[32]; + int n_cert_objs; + struct sc_pkcs15_object *cert_objs[32]; }; @@ -70,6 +72,19 @@ init_private_data (CARD card) return GNUPG_Card_Error; } priv->n_prkey_rsa_objs = rc; + + /* Read all certificate objects. */ + rc = sc_pkcs15_get_objects (card->p15card, SC_PKCS15_TYPE_CERT_X509, + priv->cert_objs, + DIM (priv->cert_objs)); + if (rc < 0) + { + log_error ("private keys enumeration failed: %s\n", sc_strerror (rc)); + xfree (priv); + return GNUPG_Card_Error; + } + priv->n_cert_objs = rc; + card->p15priv = priv; return 0; } @@ -174,6 +189,57 @@ p15_enum_keypairs (CARD card, int idx, return rc; } +/* See card.c for interface description */ +static int +p15_enum_certs (CARD card, int idx, char **certid, int *type) +{ + int rc; + struct p15private_s *priv; + struct sc_pkcs15_object *obj; + struct sc_pkcs15_cert_info *cinfo; + int nobjs; + + rc = init_private_data (card); + if (rc) + return rc; + priv = card->p15priv; + nobjs = priv->n_cert_objs; + rc = 0; + if (idx >= nobjs) + return -1; + obj = priv->cert_objs[idx]; + cinfo = obj->data; + + if (certid) + { + char *p; + int i; + + *certid = p = xtrymalloc (9+cinfo->id.len*2+1); + if (!*certid) + return GNUPG_Out_Of_Core; + p = stpcpy (p, "P15-5015."); + for (i=0; i < cinfo->id.len; i++, p += 2) + sprintf (p, "%02X", cinfo->id.value[i]); + *p = 0; + } + if (type) + { + if (!obj->df) + *type = 0; /* unknown */ + else if (obj->df->type == SC_PKCS15_CDF) + *type = 100; + else if (obj->df->type == SC_PKCS15_CDF_TRUSTED) + *type = 101; + else if (obj->df->type == SC_PKCS15_CDF_USEFUL) + *type = 102; + else + *type = 0; /* error -> unknown */ + } + + return rc; +} + static int @@ -425,6 +491,7 @@ void card_p15_bind (CARD card) { card->fnc.enum_keypairs = p15_enum_keypairs; + card->fnc.enum_certs = p15_enum_certs; card->fnc.read_cert = p15_read_cert; card->fnc.sign = p15_sign; card->fnc.decipher = p15_decipher; diff --git a/scd/card.c b/scd/card.c index 34812b8a1..9e0f060e5 100644 --- a/scd/card.c +++ b/scd/card.c @@ -428,6 +428,39 @@ card_enum_keypairs (CARD card, int idx, } +/* Enumerate all trusted certificates available on the card, return + their ID in CERT and the type in CERTTYPE. Types of certificates + are: + 0 := Unknown + 100 := Regular X.509 cert + 101 := Trusted X.509 cert + 102 := Useful X.509 cert + */ +int +card_enum_certs (CARD card, int idx, char **certid, int *certtype) +{ + int rc; + + if (certid) + *certid = NULL; + + if (!card) + return GNUPG_Invalid_Value; + if (idx < 0) + return GNUPG_Invalid_Index; + if (!card->fnc.initialized) + return GNUPG_Card_Not_Initialized; + if (!card->fnc.enum_certs) + return GNUPG_Unsupported_Operation; + rc = card->fnc.enum_certs (card, idx, certid, certtype); + if (opt.verbose) + log_info ("card operation enum_certs result: %s\n", + gnupg_strerror (rc)); + return rc; +} + + + /* Read the certificate identified by CERTIDSTR which is the hexadecimal encoded ID of the certificate, prefixed with the string "3F005015.". The certificate is return in DER encoded form in CERT diff --git a/scd/command.c b/scd/command.c index 9e0ddc502..aa410a6ee 100644 --- a/scd/command.c +++ b/scd/command.c @@ -151,7 +151,17 @@ cmd_serialno (ASSUAN_CONTEXT ctx, char *line) S KEYPAIRINFO If there is no certificate yet stored on the card a single "X" is - returned as the keygrip. + returned as the keygrip. In addition to the keypair info, information + about all certificates stored on the card is also returned: + + S CERTINFO + + Where CERTINFO is a number indicating the type of certificate: + 0 := Unknown + 100 := Regular X.509 cert + 101 := Trusted X.509 cert + 102 := Useful X.509 cert + */ static int @@ -209,6 +219,34 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line) free (serial_and_stamp); } + /* Return information about the certificates. */ + for (idx=0; !rc; idx++) + { + char *certid; + int certtype; + + rc = card_enum_certs (ctrl->card_ctx, idx, &certid, &certtype); + if (!rc) + { + char *buf; + + buf = xtrymalloc (40 + 1 + strlen (certid) + 1); + if (!buf) + rc = GNUPG_Out_Of_Core; + else + { + sprintf (buf, "%d %s", certtype, certid); + assuan_write_status (ctx, "CERTINFO", buf); + xfree (buf); + } + } + xfree (certid); + } + if (rc == -1) + rc = 0; + + + /* Return information about the keys. */ for (idx=0; !rc; idx++) { unsigned char keygrip[20]; diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 29256d811..6001faf5c 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -41,12 +41,10 @@ #include "scdaemon.h" #include "../assuan/assuan.h" /* malloc hooks */ +#include "i18n.h" #include "sysutils.h" -#define N_(a) a -#define _(a) a - enum cmd_and_opt_values { aNull = 0, diff --git a/scd/scdaemon.h b/scd/scdaemon.h index 97bf93d36..9fbf891bb 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -85,6 +85,7 @@ int card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp); int card_enum_keypairs (CARD card, int idx, unsigned char *keygrip, char **keyid); +int card_enum_certs (CARD card, int idx, char **certid, int *certtype); int card_read_cert (CARD card, const char *certidstr, unsigned char **cert, size_t *ncert); int card_sign (CARD card,