aboutsummaryrefslogtreecommitdiffstats
path: root/scd/sc-investigate.c
diff options
context:
space:
mode:
Diffstat (limited to 'scd/sc-investigate.c')
-rw-r--r--scd/sc-investigate.c143
1 files changed, 137 insertions, 6 deletions
diff --git a/scd/sc-investigate.c b/scd/sc-investigate.c
index 6f8b330b1..3882e1dfd 100644
--- a/scd/sc-investigate.c
+++ b/scd/sc-investigate.c
@@ -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;
+
+}
+