*** empty log message ***

This commit is contained in:
Werner Koch 2004-03-16 10:49:37 +00:00
parent 1a389c1e1e
commit f8d44bc637
14 changed files with 200 additions and 46 deletions

View File

@ -1,3 +1,17 @@
2004-03-11 Werner Koch <wk@gnupg.org>
* scdaemon.h (out_of_core): Removed. Replaced callers by standard
gpg_error function.
* apdu.c, iso7816.c, ccid-driver.c [GNUPG_SCD_MAIN_HEADER]: Allow
to include a header defined by the compiler. This helps us to
reuse the source in other software.
2004-03-10 Werner Koch <wk@gnupg.org>
* iso7816.c (iso7816_read_record): New arg SHORT_EF. Changed all
callers.
2004-02-18 Werner Koch <wk@gnupg.org>
* sc-investigate.c (main): Setup the used character set.

View File

@ -28,7 +28,9 @@
# include <opensc/opensc.h>
#endif
#if GNUPG_MAJOR_VERSION == 1
#if defined(GNUPG_SCD_MAIN_HEADER)
#include GNUPG_SCD_MAIN_HEADER
#elif GNUPG_MAJOR_VERSION == 1
/* This is used with GnuPG version < 1.9. The code has been source
copied from the current GnuPG >= 1.9 and is maintained over
there. */

View File

@ -130,10 +130,10 @@ keygripstr_from_pk_file (int slot, int fid, char *r_gripstr)
err = iso7816_select_file (slot, fid, 0, NULL, NULL);
if (err)
return err;
err = iso7816_read_record (slot, 1, 1, &buffer[0], &buflen[0]);
err = iso7816_read_record (slot, 1, 1, 0, &buffer[0], &buflen[0]);
if (err)
return err;
err = iso7816_read_record (slot, 2, 1, &buffer[1], &buflen[1]);
err = iso7816_read_record (slot, 2, 1, 0, &buffer[1], &buflen[1]);
if (err)
{
xfree (buffer[0]);

View File

@ -245,7 +245,7 @@ store_fpr (int slot, int keynumber, u32 timestamp,
n = 6 + 2 + mlen + 2 + elen;
p = buffer = xtrymalloc (3 + n);
if (!buffer)
return out_of_core ();
return gpg_error (gpg_err_code_from_errno (errno));
*p++ = 0x99; /* ctb */
*p++ = n >> 8; /* 2 byte length header */

View File

@ -47,7 +47,7 @@ select_application (ctrl_t ctrl, int slot, const char *name)
app = xtrycalloc (1, sizeof *app);
if (!app)
{
rc = out_of_core ();
rc = gpg_error (gpg_err_code_from_errno (errno));
log_info ("error allocating context: %s\n", gpg_strerror (rc));
return NULL;
}

View File

@ -141,7 +141,7 @@ dinsig_enum_keypairs (CARD card, int idx,
{
*keyid = xtrymalloc (17);
if (!*keyid)
return out_of_core ();
return gpg_error (gpg_err_code_from_errno (errno));
if (!idx)
strcpy (*keyid, "DINSIG-DF01.C000");
else
@ -193,7 +193,7 @@ dinsig_read_cert (CARD card, const char *certidstr,
buf = xtrymalloc (file->size);
if (!buf)
{
gpg_error_t tmperr = out_of_core ();
gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
sc_file_free (file);
return tmperr;
}

View File

@ -53,7 +53,7 @@ init_private_data (CARD card)
priv = xtrycalloc (1, sizeof *priv);
if (!priv)
return out_of_core ();
return gpg_error (gpg_err_code_from_errno (errno));
/* 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
@ -179,7 +179,7 @@ p15_enum_keypairs (CARD card, int idx,
*keyid = p = xtrymalloc (9+pinfo->id.len*2+1);
if (!*keyid)
return out_of_core ();
return gpg_error (gpg_err_code_from_errno (errno));
p = stpcpy (p, "P15-5015.");
for (i=0; i < pinfo->id.len; i++, p += 2)
sprintf (p, "%02X", pinfo->id.value[i]);
@ -217,7 +217,7 @@ p15_enum_certs (CARD card, int idx, char **certid, int *type)
*certid = p = xtrymalloc (9+cinfo->id.len*2+1);
if (!*certid)
return out_of_core ();
return gpg_error (gpg_err_code_from_errno (errno));
p = stpcpy (p, "P15-5015.");
for (i=0; i < cinfo->id.len; i++, p += 2)
sprintf (p, "%02X", cinfo->id.value[i]);
@ -304,7 +304,7 @@ p15_read_cert (CARD card, const char *certidstr,
*cert = xtrymalloc (certder->data_len);
if (!*cert)
{
gpg_error_t tmperr = out_of_core ();
gpg_error_t tmperr = gpg_error (gpg_err_code_from_errno (errno));
sc_pkcs15_free_certificate (certder);
return tmperr;
}
@ -400,7 +400,7 @@ p15_sign (CARD card, const char *keyidstr, int hashalgo,
outbuflen = 1024;
outbuf = xtrymalloc (outbuflen);
if (!outbuf)
return out_of_core ();
return gpg_error (gpg_err_code_from_errno (errno));
rc = sc_pkcs15_compute_signature (card->p15card, keyobj,
cryptflags,
@ -462,7 +462,7 @@ p15_decipher (CARD card, const char *keyidstr,
outbuflen = indatalen < 256? 256 : indatalen;
outbuf = xtrymalloc (outbuflen);
if (!outbuf)
return out_of_core ();
return gpg_error (gpg_err_code_from_errno (errno));
rc = sc_pkcs15_decipher (card->p15card, keyobj,
0,

View File

@ -108,7 +108,7 @@ card_open (CARD *rcard)
card = xtrycalloc (1, sizeof *card);
if (!card)
return out_of_core ();
return gpg_error (gpg_err_code_from_errno (errno));
card->reader = 0;
rc = sc_establish_context (&card->ctx, "scdaemon");
@ -275,7 +275,7 @@ find_iccsn (const unsigned char *buffer, size_t length, char **serial)
*serial = p = xtrymalloc (2*n+1);
if (!*serial)
return out_of_core ();
return gpg_error (gpg_err_code_from_errno (errno));
for (; n; n--, p += 2, s++)
sprintf (p, "%02X", *s);
*p = 0;
@ -389,7 +389,7 @@ card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp)
*serial = NULL;
p = xtrymalloc (strlen (efser) + 7);
if (!p)
rc = out_of_core ();
rc = gpg_error (gpg_err_code_from_errno (errno));
else
{
strcpy (p, "FF0100");
@ -405,7 +405,7 @@ card_get_serial_and_stamp (CARD card, char **serial, time_t *stamp)
{
xfree (*serial);
*serial = NULL;
rc = out_of_core ();
rc = gpg_error (gpg_err_code_from_errno (errno));
}
else
{

View File

@ -87,16 +87,24 @@
#define DRVNAME "ccid-driver: "
#ifdef GNUPG_MAJOR_VERSION /* This source is used within GnuPG. */
/* Depending on how this source is used we either define our error
output to go to stderr or to the jnlib based logging functions. We
use the latter when GNUPG_MAJOR_VERSION is defines or when both,
GNUPG_SCD_MAIN_HEADER and HAVE_JNLIB_LOGGING are defined.
*/
#if defined(GNUPG_MAJOR_VERSION) \
|| (defined(GNUPG_SCD_MAIN_HEADER) && defined(HAVE_JNLIB_LOGGING))
# if GNUPG_MAJOR_VERSION == 1 /* GnuPG Version is < 1.9. */
#if defined(GNUPG_SCD_MAIN_HEADER)
# include GNUPG_SCD_MAIN_HEADER
#elif GNUPG_MAJOR_VERSION == 1 /* GnuPG Version is < 1.9. */
# include "options.h"
# include "util.h"
# include "memory.h"
# include "cardglue.h"
# else /* This is the modularized GnuPG 1.9 or later. */
# include "scdaemon.h"
# endif
#endif
/* Disable all debugging output for now. */
#undef DBG_CARD_IO

View File

@ -351,7 +351,7 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line)
buf = xtrymalloc (40 + 1 + strlen (certid) + 1);
if (!buf)
rc = out_of_core ();
rc = gpg_error (gpg_err_code_from_errno (errno));
else
{
sprintf (buf, "%d %s", certtype, certid);
@ -389,7 +389,7 @@ cmd_learn (ASSUAN_CONTEXT ctx, char *line)
buf = p = xtrymalloc (40 + 1 + strlen (keyid) + 1);
if (!buf)
rc = out_of_core ();
rc = gpg_error (gpg_err_code_from_errno (errno));
else
{
int i;
@ -577,7 +577,7 @@ pin_cb (void *opaque, const char *info, char **retstr)
rc = asprintf (&command, "NEEDPIN %s", info);
if (rc < 0)
return out_of_core ();
return gpg_error (gpg_err_code_from_errno (errno));
/* FIXME: Write an inquire function which returns the result in
secure memory */

View File

@ -24,7 +24,9 @@
#include <stdlib.h>
#include <string.h>
#if GNUPG_MAJOR_VERSION == 1
#if defined(GNUPG_SCD_MAIN_HEADER)
#include GNUPG_SCD_MAIN_HEADER
#elif GNUPG_MAJOR_VERSION == 1
/* This is used with GnuPG version < 1.9. The code has been source
copied from the current GnuPG >= 1.9 and is maintained over
there. */
@ -200,7 +202,7 @@ iso7816_change_reference_data (int slot, int chvno,
buf = xtrymalloc (oldchvlen + newchvlen);
if (!buf)
return out_of_core ();
return gpg_error (gpg_err_code_from_errno (errno));
if (oldchvlen)
memcpy (buf, oldchv, oldchvlen);
memcpy (buf+oldchvlen, newchv, newchvlen);
@ -341,7 +343,8 @@ iso7816_decipher (int slot, const unsigned char *data, size_t datalen,
/* We need to prepend the padding indicator. */
buf = xtrymalloc (datalen + 1);
if (!buf)
return out_of_core ();
return gpg_error (gpg_err_code_from_errno (errno));
*buf = padind; /* Padding indicator. */
memcpy (buf+1, data, datalen);
sw = apdu_send (slot, 0x00, CMD_PSO, 0x80, 0x86, datalen+1, buf,
@ -550,11 +553,13 @@ iso7816_read_binary (int slot, size_t offset, size_t nmax,
/* Perform a READ RECORD command. RECNO gives the record number to
read with 0 indicating the current record. RECCOUNT must be 1 (not
all cards support reading of more than one record). The result is
stored in a newly allocated buffer at the address passed by RESULT.
Returns the length of this data at the address of RESULTLEN. */
all cards support reading of more than one record). SHORT_EF
should be 0 to read the current EF or contain a short EF. The
result is stored in a newly allocated buffer at the address passed
by RESULT. Returns the length of this data at the address of
RESULTLEN. */
gpg_error_t
iso7816_read_record (int slot, int recno, int reccount,
iso7816_read_record (int slot, int recno, int reccount, int short_ef,
unsigned char **result, size_t *resultlen)
{
int sw;
@ -568,7 +573,8 @@ iso7816_read_record (int slot, int recno, int reccount,
/* We can only encode 15 bits in p0,p1 to indicate an offset. Thus
we check for this limit. */
if (recno < 0 || recno > 255 || reccount != 1)
if (recno < 0 || recno > 255 || reccount != 1
|| short_ef < 0 || short_ef > 254 )
return gpg_error (GPG_ERR_INV_VALUE);
buffer = NULL;
@ -577,7 +583,7 @@ iso7816_read_record (int slot, int recno, int reccount,
with an Le of 0. */
sw = apdu_send_le (slot, 0x00, CMD_READ_RECORD,
recno,
0x04,
short_ef? short_ef : 0x04,
-1, NULL,
254, &buffer, &bufferlen);

View File

@ -67,6 +67,7 @@ gpg_error_t iso7816_get_challenge (int slot,
gpg_error_t iso7816_read_binary (int slot, size_t offset, size_t nmax,
unsigned char **result, size_t *resultlen);
gpg_error_t iso7816_read_record (int slot, int recno, int reccount,
int short_ef,
unsigned char **result, size_t *resultlen);
#endif /*ISO7816_H*/

View File

@ -50,8 +50,10 @@ enum cmd_and_opt_values
{
oInteractive = 'i',
oVerbose = 'v',
oQuiet = 'q',
oReaderPort = 500,
octapiDriver,
oDebug,
oDebugAll,
@ -68,6 +70,7 @@ static ARGPARSE_OPTS opts[] = {
{ 301, NULL, 0, "@Options:\n " },
{ oInteractive, "interactive", 0, "start in interactive explorer mode"},
{ oQuiet, "quiet", 0, "quiet" },
{ oVerbose, "verbose", 0, "verbose" },
{ oReaderPort, "reader-port", 2, "|N|connect to reader at port N"},
{ octapiDriver, "ctapi-driver", 2, "NAME|use NAME as ctAPI driver"},
@ -86,7 +89,7 @@ static ARGPARSE_OPTS opts[] = {
static void interactive_shell (int slot);
static void dump_other_cards (int slot);
static const char *
my_strusage (int level)
@ -168,6 +171,7 @@ main (int argc, char **argv )
switch (pargs.r_opt)
{
case oVerbose: opt.verbose++; break;
case oQuiet: opt.quiet++; break;
case oDebug: opt.debug |= pargs.r.ret_ulong; break;
case oDebugAll: opt.debug = ~0; break;
case oReaderPort: reader_port = pargs.r.ret_str; break;
@ -191,7 +195,7 @@ main (int argc, char **argv )
if (slot == -1)
exit (1);
if (!gen_random)
if (!gen_random && !opt.quiet)
{
rc = atr_dump (slot, stdout);
if (rc)
@ -210,12 +214,17 @@ main (int argc, char **argv )
rc = app_select_openpgp (&appbuf);
if (rc)
{
log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc));
if (!opt.quiet)
log_info ("selecting openpgp failed: %s\n", gpg_strerror (rc));
memset (&appbuf, 0, sizeof appbuf);
appbuf.slot = slot;
rc = app_select_dinsig (&appbuf);
if (rc)
log_info ("selecting dinsig failed: %s\n", gpg_strerror (rc));
{
if (!opt.quiet)
log_info ("selecting dinsig failed: %s\n", gpg_strerror (rc));
dump_other_cards (slot);
}
else
{
appbuf.initialized = 1;
@ -398,6 +407,7 @@ interactive_shell (int slot)
cmdAPP,
cmdREAD,
cmdREADREC,
cmdREADSHORTREC,
cmdDEBUG,
cmdVERIFY,
cmdCHANGEREF,
@ -425,6 +435,7 @@ interactive_shell (int slot)
{ "rb" , cmdREAD, NULL },
{ "readrec", cmdREADREC, "read record(s)" },
{ "rr" , cmdREADREC, NULL },
{ "rsr" , cmdREADSHORTREC, "readshortrec RECNO SHORT_EF" },
{ "verify" , cmdVERIFY, "verify CHVNO PIN" },
{ "ver" , cmdVERIFY, NULL },
{ "changeref", cmdCHANGEREF, "change reference data" },
@ -559,7 +570,8 @@ interactive_shell (int slot)
for (i=1, err=0; !err; i++)
{
xfree (result); result = NULL;
err = iso7816_read_record (slot, i, 1, &result, &resultlen);
err = iso7816_read_record (slot, i, 1, 0,
&result, &resultlen);
if (!err)
dump_buffer (result, resultlen);
}
@ -568,13 +580,31 @@ interactive_shell (int slot)
}
else
{
err = iso7816_read_record (slot, arg_number, 1,
err = iso7816_read_record (slot, arg_number, 1, 0,
&result, &resultlen);
if (!err)
dump_or_store_buffer (arg_string, result, resultlen);
}
break;
case cmdREADSHORTREC:
{
int short_ef;
short_ef = strtol (arg_next, NULL, 0);
if (short_ef < 1 || short_ef > 254)
printf ("error: short EF must be between 1 and 254\n");
else
{
err = iso7816_read_record (slot, arg_number, 1, short_ef,
&result, &resultlen);
if (!err)
dump_or_store_buffer (arg_string, result, resultlen);
}
}
break;
case cmdVERIFY:
if (arg_number < 0 || arg_number > 255 || (arg_number & 127) > 31)
printf ("error: invalid CHVNO\n");
@ -637,3 +667,104 @@ interactive_shell (int slot)
;
}
/* Figure out whether the current card is a German Geldkarte and print
what we know about it. */
static int
dump_geldkarte (int slot)
{
unsigned char *r = NULL;
size_t rlen;
const char *t;
if (iso7816_read_record (slot, 1, 1, 0xbc, &r, &rlen))
return -1;
/* We require that the record is at least 24 bytes, the first byte
is 0x67 and the filler byte is correct. */
if (rlen < 24 || *r != 0x67 || r[22])
return -1;
/* The short Bankleitzahl consists of 3 bytes at offset 1. */
switch (r[1])
{
case 0x21: t = "Oeffentlich-rechtliche oder private Bank"; break;
case 0x22: t = "Privat- oder Geschäftsbank"; break;
case 0x25: t = "Sparkasse"; break;
case 0x26:
case 0x29: t = "Genossenschaftsbank"; break;
default:
xfree (r);
return -1; /* Probably not a Geldkarte. */
}
printf ("KBLZ .....: %02X-%02X%02X (%s)\n", r[1], r[2], r[3], t);
printf ("Card-No ..: %02X%02X%02X%02X%02X\n", r[4], r[5], r[6], r[7], r[8]);
/* Byte 10 enthält im linken Halbbyte eine Prüfziffer, die nach dem */
/* Verfahren 'Luhn formula for computing modulus 10' über die Ziffern der */
/* ersten 9 Byte berechnet ist. */
/* Das rechte Halbbyte wird zu 'D' gesetzt. */
/* Für die Berechnung der Luhn-Prüfziffer sind die folgenden Schritte */
/* durchzuführen: */
/* Schritt 1: Mit der rechtesten Ziffer beginnend ist einschließlich dieser */
/* Ziffer jede übernächste Ziffer zu verdoppeln (mit 2 multiplizieren). */
/* Schritt 2: Die einzelnen Ziffern der Produkte aus Schritt 1 und die bei */
/* diesen Multiplikationen unberührt gebliebenen Ziffern sind zu addieren. */
/* Schritt 3: Das Ergebnis der Addition aus Schritt 2 ist von dem auf die */
/* nächst höhere Zahl mit der Einerstelle 0 aufgerundeten Ergebnis der */
/* Addition aus Schritt 2 abzuziehen. Wenn das Ergebnis der Addition aus */
/* Schritt 2 bereits eine Zahl mit der Einerstelle 0 ergibt (z.B. 30, 40, */
/* usw.), ist die Prüfziffer 0. */
/* Beispiel: Kartennummer ohne Prüfziffer: 992 839 871 */
/* 9 9 2 8 3 9 8 7 1 */
/* x 2 x 2 x 2 x 2 x 2 Schritt 1 */
/* 18 4 6 16 2 */
/* 1+8 +9 +4 +8 +6 +9 +1+6 +7 +2 = 61 Schritt 2 */
/* 70-61 = 9 Schritt 3 */
/* Prüfziffer zu 992 839 871 = 9 */
printf ("Expires at: %02X/%02X\n", r[11], r[10] );
printf ("Valid from: %02X.%02X.%02X\n", r[14], r[13], r[12]);
printf ("Country ..: %02X%02X\n", r[15], r[16]);
printf ("Currency .: %c%c%c\n", isascii (r[17])? r[17]:' ',
isascii (r[18])? r[18]:' ', isascii (r[19])? r[19]:' ');
printf ("Cur.-Mult : %s\n",
r[20] == 0x01? "0.01":
r[20] == 0x02? "0.1":
r[20] == 0x04? "1":
r[20] == 0x08? "10":
r[20] == 0x10? "100":
r[20] == 0x20? "1000": "?");
printf ("ZKA ChipID: %02X\n", r[21]);
printf ("OS version: %02X\n", r[23]);
xfree (r);
return 0;
}
/* Try to figure out the type of teh card and dump its contents. */
static void
dump_other_cards (int slot)
{
if (!dump_geldkarte (slot))
return;
}

View File

@ -33,14 +33,6 @@
#include "../common/util.h"
#include "../common/errors.h"
/* Convenience funcion to be used instead of returning the old
GNUPG_Out_Of_Core. */
static __inline__ gpg_error_t
out_of_core (void)
{
return gpg_error (gpg_err_code_from_errno (errno));
}
#define MAX_DIGEST_LEN 24