From 7db161552c9b8c34f48c37b71867c8343c95adbd Mon Sep 17 00:00:00 2001 From: Werner Koch Date: Fri, 12 Apr 2002 18:55:05 +0000 Subject: [PATCH] * scdaemon.c: New option --debug-sc N. * card.c (card_open): set it here. * card-p15.c (p15_prepare_key): Factored out common code from ... (p15_sign, p15_decipher): here and made the decryption work the regular way. --- scd/ChangeLog | 9 ++++ scd/card-p15.c | 139 +++++++++++++++++++++---------------------------- scd/card.c | 11 ++-- scd/scdaemon.c | 3 ++ scd/scdaemon.h | 1 + 5 files changed, 78 insertions(+), 85 deletions(-) diff --git a/scd/ChangeLog b/scd/ChangeLog index 1ce2befc4..bda647334 100644 --- a/scd/ChangeLog +++ b/scd/ChangeLog @@ -1,3 +1,12 @@ +2002-04-12 Werner Koch + + * scdaemon.c: New option --debug-sc N. + * card.c (card_open): set it here. + + * card-p15.c (p15_prepare_key): Factored out common code from ... + (p15_sign, p15_decipher): here and made the decryption work the + regular way. + 2002-04-10 Werner Koch * card.c (card_open): Return immediately when no reader is available. diff --git a/scd/card-p15.c b/scd/card-p15.c index 14a274480..a70bc665e 100644 --- a/scd/card-p15.c +++ b/scd/card-p15.c @@ -32,9 +32,6 @@ #include "card-common.h" - - - /* See card.c for interface description */ static int p15_enum_keypairs (CARD card, int idx, @@ -198,26 +195,19 @@ p15_read_cert (CARD card, const char *certidstr, } + + -/* See card.c for interface description */ -static int -p15_sign (CARD card, const char *keyidstr, int hashalgo, - int (pincb)(void*, const char *, char **), - void *pincb_arg, - const void *indata, size_t indatalen, - void **outdata, size_t *outdatalen ) +static int +p15_prepare_key (CARD card, const char *keyidstr, + int (pincb)(void*, const char *, char **), + void *pincb_arg, struct sc_pkcs15_object **r_keyobj) { - unsigned int cryptflags = 0; struct sc_pkcs15_id keyid; struct sc_pkcs15_pin_info *pin; struct sc_pkcs15_object *keyobj, *pinobj; char *pinvalue; int rc; - unsigned char *outbuf = NULL; - size_t outbuflen; - - if (hashalgo != GCRY_MD_SHA1) - return GNUPG_Unsupported_Algorithm; rc = idstr_to_id (keyidstr, &keyid); if (rc) @@ -227,18 +217,15 @@ p15_sign (CARD card, const char *keyidstr, int hashalgo, if (rc < 0) { log_error ("private key not found: %s\n", sc_strerror(rc)); - rc = GNUPG_No_Secret_Key; - goto leave; + return GNUPG_No_Secret_Key; } - rc = 0; rc = sc_pkcs15_find_pin_by_auth_id (card->p15card, &keyobj->auth_id, &pinobj); if (rc) { log_error ("failed to find PIN by auth ID: %s\n", sc_strerror (rc)); - rc = GNUPG_Bad_PIN_Method; - goto leave; + return GNUPG_Bad_PIN_Method; } pin = pinobj->data; @@ -249,7 +236,7 @@ p15_sign (CARD card, const char *keyidstr, int hashalgo, if (rc) { log_info ("PIN callback returned error: %s\n", gnupg_strerror (rc)); - goto leave; + return rc; } rc = sc_pkcs15_verify_pin (card->p15card, pin, @@ -258,11 +245,37 @@ p15_sign (CARD card, const char *keyidstr, int hashalgo, if (rc) { log_info ("PIN verification failed: %s\n", sc_strerror (rc)); - rc = GNUPG_Bad_PIN; - goto leave; + return GNUPG_Bad_PIN; } - cryptflags |= SC_ALGORITHM_RSA_PAD_PKCS1; + /* fixme: check wheter we need to release KEYOBJ in case of an error */ + *r_keyobj = keyobj; + return 0; +} + + +/* See card.c for interface description */ +static int +p15_sign (CARD card, const char *keyidstr, int hashalgo, + int (pincb)(void*, const char *, char **), + void *pincb_arg, + const void *indata, size_t indatalen, + void **outdata, size_t *outdatalen ) +{ + unsigned int cryptflags; + struct sc_pkcs15_object *keyobj; + int rc; + unsigned char *outbuf = NULL; + size_t outbuflen; + + if (hashalgo != GCRY_MD_SHA1) + return GNUPG_Unsupported_Algorithm; + + rc = p15_prepare_key (card, keyidstr, pincb, pincb_arg, &keyobj); + if (rc) + return rc; + + cryptflags = SC_ALGORITHM_RSA_PAD_PKCS1; outbuflen = 1024; outbuf = xtrymalloc (outbuflen); @@ -286,8 +299,6 @@ p15_sign (CARD card, const char *keyidstr, int hashalgo, rc = 0; } - -leave: xfree (outbuf); return rc; } @@ -301,55 +312,31 @@ p15_decipher (CARD card, const char *keyidstr, const void *indata, size_t indatalen, void **outdata, size_t *outdatalen ) { - struct sc_pkcs15_id keyid; - struct sc_pkcs15_pin_info *pin; - struct sc_pkcs15_object *keyobj, *pinobj; - char *pinvalue; + struct sc_pkcs15_object *keyobj; int rc; unsigned char *outbuf = NULL; size_t outbuflen; - rc = idstr_to_id (keyidstr, &keyid); + rc = p15_prepare_key (card, keyidstr, pincb, pincb_arg, &keyobj); if (rc) return rc; - rc = sc_pkcs15_find_prkey_by_id (card->p15card, &keyid, &keyobj); - if (rc < 0) + if (card && card->scard && card->scard->driver + && !strcasecmp (card->scard->driver->short_name, "tcos")) { - log_error ("private key not found: %s\n", sc_strerror(rc)); - rc = GNUPG_No_Secret_Key; - goto leave; - } - rc = 0; - - rc = sc_pkcs15_find_pin_by_auth_id (card->p15card, - &keyobj->auth_id, &pinobj); - if (rc) - { - log_error ("failed to find PIN by auth ID: %s\n", sc_strerror (rc)); - rc = GNUPG_Bad_PIN_Method; - goto leave; - } - pin = pinobj->data; - - /* Fixme: pack this into a verification loop */ - /* Fixme: we might want to pass pin->min_length and - pin->stored_length */ - rc = pincb (pincb_arg, pinobj->label, &pinvalue); - if (rc) - { - log_info ("PIN callback returned error: %s\n", gnupg_strerror (rc)); - goto leave; - } - - rc = sc_pkcs15_verify_pin (card->p15card, pin, - pinvalue, strlen (pinvalue)); - xfree (pinvalue); - if (rc) - { - log_info ("PIN verification failed: %s\n", sc_strerror (rc)); - rc = GNUPG_Bad_PIN; - goto leave; + /* very ugly hack to force the use of a local key. We need this + until we have fixed the initialization code for TCOS cards */ + struct sc_pkcs15_prkey_info *prkey = keyobj->data; + if ( !(prkey->key_reference & 0x80)) + { + prkey->key_reference |= 0x80; + log_debug ("using TCOS hack to force the use of local keys\n"); + } + if (*keyidstr && keyidstr[strlen(keyidstr)-1] == '6') + { + prkey->key_reference |= 1; + log_debug ("warning: using even more TCOS hacks\n"); + } } outbuflen = indatalen < 256? 256 : indatalen; @@ -357,17 +344,12 @@ p15_decipher (CARD card, const char *keyidstr, if (!outbuf) return GNUPG_Out_Of_Core; - /* OpenSC does not yet support decryption for cryptflex cards */ -/* rc = sc_pkcs15_decipher (card->p15card, key, */ -/* indata, indatalen, */ -/* outbuf, outbuflen); */ - rc = sc_pkcs15_compute_signature (card->p15card, keyobj, - 0, - indata, indatalen, - outbuf, outbuflen ); + rc = sc_pkcs15_decipher (card->p15card, keyobj, + indata, indatalen, + outbuf, outbuflen); if (rc < 0) { - log_error ("failed to decipger the data: %s\n", sc_strerror (rc)); + log_error ("failed to decipher the data: %s\n", sc_strerror (rc)); rc = GNUPG_Card_Error; } else @@ -378,15 +360,12 @@ p15_decipher (CARD card, const char *keyidstr, rc = 0; } - -leave: xfree (outbuf); return rc; } - /* Bind our operations to the card */ void card_p15_bind (CARD card) diff --git a/scd/card.c b/scd/card.c index 629e2936b..d17ae1947 100644 --- a/scd/card.c +++ b/scd/card.c @@ -141,10 +141,9 @@ card_open (CARD *rcard) goto leave; } card->ctx->error_file = log_get_stream (); - if (opt.debug) - { - card->ctx->debug_file = log_get_stream (); - } + card->ctx->debug = opt.debug_sc; + card->ctx->debug_file = log_get_stream (); + if (sc_detect_card_presence (card->ctx->reader[card->reader], 0) != 1) { rc = GNUPG_Card_Not_Present; @@ -258,7 +257,9 @@ card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp) /* We should lookup the iso 7812-1 and 8583-3 - argh ISO practice is suppressing innovation - IETF rules! So we - always get the serialnumber from the 2F00 GDO file. */ + always get the serialnumber from the 2F02 GDO file. */ + /* FIXME: in case we can't parse the 2F02 EF and we have a P15 card, + we should get the serial number from the respective P15 file */ sc_format_path ("3F002F02", &path); rc = sc_select_file (card->scard, &path, &file); if (rc) diff --git a/scd/scdaemon.c b/scd/scdaemon.c index 92bccec9e..a6f18cc36 100644 --- a/scd/scdaemon.c +++ b/scd/scdaemon.c @@ -60,6 +60,7 @@ enum cmd_and_opt_values oDebug, oDebugAll, oDebugWait, + oDebugSC, oNoGreeting, oNoOptions, oHomedir, @@ -86,6 +87,7 @@ static ARGPARSE_OPTS opts[] = { { oDebug, "debug" ,4|16, N_("set debugging flags")}, { oDebugAll, "debug-all" ,0, N_("enable full debugging")}, { oDebugWait,"debug-wait",1, "@"}, + { oDebugSC, "debug-sc", 1, N_("N|set OpenSC debug level to N")}, { oNoDetach, "no-detach" ,0, N_("do not detach from the console")}, { oLogFile, "log-file" ,2, N_("use a log file for the server")}, @@ -344,6 +346,7 @@ main (int argc, char **argv ) case oDebug: opt.debug |= pargs.r.ret_ulong; break; case oDebugAll: opt.debug = ~0; break; case oDebugWait: debug_wait = pargs.r.ret_int; break; + case oDebugSC: opt.debug_sc = pargs.r.ret_int; break; case oOptions: /* config files may not be nested (silently ignore them) */ diff --git a/scd/scdaemon.h b/scd/scdaemon.h index 9c8af5d92..97bf93d36 100644 --- a/scd/scdaemon.h +++ b/scd/scdaemon.h @@ -31,6 +31,7 @@ /* A large struct name "opt" to keep global flags */ struct { unsigned int debug; /* debug flags (DBG_foo_VALUE) */ + int debug_sc; /* OpenSC debug level */ int verbose; /* verbosity level */ int quiet; /* be as quiet as possible */ int dry_run; /* don't change any persistent data */