aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--scd/ChangeLog9
-rw-r--r--scd/card-p15.c139
-rw-r--r--scd/card.c11
-rw-r--r--scd/scdaemon.c3
-rw-r--r--scd/scdaemon.h1
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 <[email protected]>
+
+ * 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 <[email protected]>
* 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)
- {
- 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)
+ if (card && card->scard && card->scard->driver
+ && !strcasecmp (card->scard->driver->short_name, "tcos"))
{
- 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 */