1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-15 00:29:49 +02:00

Return the balance of a Geldkarte.

This commit is contained in:
Werner Koch 2009-01-27 16:38:33 +00:00
parent 51e4831685
commit 92cb022675
2 changed files with 90 additions and 18 deletions

View File

@ -1,5 +1,7 @@
2009-01-27 Werner Koch <wk@g10code.com> 2009-01-27 Werner Koch <wk@g10code.com>
* app-geldkarte.c: Changed to use an AID.
* app.c (app_munge_serialno): Add case for no serialno. * app.c (app_munge_serialno): Add case for no serialno.
(app_get_serial_and_stamp): Ditto. (app_get_serial_and_stamp): Ditto.

View File

@ -20,10 +20,9 @@
/* This is a read-only application to quickly dump information of a /* This is a read-only application to quickly dump information of a
German Geldkarte (debit card for small amounts). German Geldkarte (debit card for small amounts). We only support
newer Geldkarte (with the AID DF_BOERSE_NEU) issued since 2000 or
Because this application does no use an AID it is best to test for even earlier.
it after the test for other applications.
*/ */
@ -58,6 +57,9 @@ struct app_local_s
unsigned int currency_mult100; unsigned int currency_mult100;
unsigned char chipid; unsigned char chipid;
unsigned char osvers; unsigned char osvers;
int balance;
int maxamount;
int maxamount1;
}; };
@ -109,11 +111,6 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
err = send_one_string (ctrl, name, ld->country); err = send_one_string (ctrl, name, ld->country);
else if (!strcmp (name, "X-CURRENCY")) else if (!strcmp (name, "X-CURRENCY"))
err = send_one_string (ctrl, name, ld->currency); err = send_one_string (ctrl, name, ld->currency);
else if (!strcmp (name, "X-CRNCMULT"))
{
snprintf (numbuf, sizeof numbuf, "%u", ld->currency_mult100);
err = send_one_string (ctrl, name, numbuf);
}
else if (!strcmp (name, "X-ZKACHIPID")) else if (!strcmp (name, "X-ZKACHIPID"))
{ {
snprintf (numbuf, sizeof numbuf, "0x%02X", ld->chipid); snprintf (numbuf, sizeof numbuf, "0x%02X", ld->chipid);
@ -124,6 +121,24 @@ do_getattr (app_t app, ctrl_t ctrl, const char *name)
snprintf (numbuf, sizeof numbuf, "0x%02X", ld->osvers); snprintf (numbuf, sizeof numbuf, "0x%02X", ld->osvers);
err = send_one_string (ctrl, name, numbuf); err = send_one_string (ctrl, name, numbuf);
} }
else if (!strcmp (name, "X-BALANCE"))
{
snprintf (numbuf, sizeof numbuf, "%.2f",
(double)ld->balance / 100 * ld->currency_mult100);
err = send_one_string (ctrl, name, numbuf);
}
else if (!strcmp (name, "X-MAXAMOUNT"))
{
snprintf (numbuf, sizeof numbuf, "%.2f",
(double)ld->maxamount / 100 * ld->currency_mult100);
err = send_one_string (ctrl, name, numbuf);
}
else if (!strcmp (name, "X-MAXAMOUNT1"))
{
snprintf (numbuf, sizeof numbuf, "%.2f",
(double)ld->maxamount1 / 100 * ld->currency_mult100);
err = send_one_string (ctrl, name, numbuf);
}
else else
err = gpg_error (GPG_ERR_INV_NAME); err = gpg_error (GPG_ERR_INV_NAME);
@ -142,9 +157,11 @@ do_learn_status (app_t app, ctrl_t ctrl)
"X-VALIDFROM", "X-VALIDFROM",
"X-COUNTRY", "X-COUNTRY",
"X-CURRENCY", "X-CURRENCY",
"X-CRNCMULT",
"X-ZKACHIPID", "X-ZKACHIPID",
"X-OSVERSION", "X-OSVERSION",
"X-BALANCE",
"X-MAXAMOUNT",
"X-MAXAMOUNT1",
NULL NULL
}; };
gpg_error_t err = 0; gpg_error_t err = 0;
@ -235,12 +252,28 @@ copy_bcd (const unsigned char *string, size_t length)
} }
/* Convert the BCD number at STING of LENGTH into an integer and store
that at RESULT. Return 0 on success. */
static gpg_error_t
bcd_to_int (const unsigned char *string, size_t length, int *result)
{
char *tmp;
tmp = copy_bcd (string, length);
if (!tmp)
return gpg_error (GPG_ERR_BAD_DATA);
*result = strtol (tmp, NULL, 10);
xfree (tmp);
return 0;
}
/* Select the Geldkarte application. */ /* Select the Geldkarte application. */
gpg_error_t gpg_error_t
app_select_geldkarte (app_t app) app_select_geldkarte (app_t app)
{ {
static unsigned char const aid[] =
{ 0xD2, 0x76, 0x00, 0x00, 0x25, 0x45, 0x50, 0x02, 0x00 };
gpg_error_t err; gpg_error_t err;
int slot = app->slot; int slot = app->slot;
unsigned char *result = NULL; unsigned char *result = NULL;
@ -248,16 +281,16 @@ app_select_geldkarte (app_t app)
struct app_local_s *ld; struct app_local_s *ld;
const char *banktype; const char *banktype;
err = iso7816_select_file (slot, 0x3f00, 1, NULL, NULL); err = iso7816_select_application (slot, aid, sizeof aid, 0);
if (err) if (err)
goto leave; /* Oops. */ goto leave;
/* Read short EF 0xbc. We require this record to be at least 24 /* Read the first record of EF_ID (SFI=0x17). We require this
bytes with the the first byte 0x67 and a correct the filler record to be at least 24 bytes with the the first byte 0x67 and a
byte. */ correct filler byte. */
err = iso7816_read_record (slot, 1, 1, 0xbc, &result, &resultlen); err = iso7816_read_record (slot, 1, 1, ((0x17 << 3)|4), &result, &resultlen);
if (err) if (err)
goto leave; /* No such record or other error - not a Geldkarte. */ goto leave; /* Oops - not a Geldkarte. */
if (resultlen < 24 || *result != 0x67 || result[22]) if (resultlen < 24 || *result != 0x67 || result[22])
{ {
err = gpg_error (GPG_ERR_NOT_FOUND); err = gpg_error (GPG_ERR_NOT_FOUND);
@ -280,6 +313,23 @@ app_select_geldkarte (app_t app)
app->apptype = "GELDKARTE"; app->apptype = "GELDKARTE";
app->fnc.deinit = do_deinit; app->fnc.deinit = do_deinit;
/* If we don't have a serialno yet construct it from the EF_ID. */
if (!app->serialno)
{
app->serialno = xtrymalloc (10);
if (!app->serialno)
{
err = gpg_error_from_syserror ();
goto leave;
}
memcpy (app->serialno, result, 10);
app->serialnolen = 10;
err = app_munge_serialno (app);
if (err)
goto leave;
}
app->app_local = ld = xtrycalloc (1, sizeof *app->app_local); app->app_local = ld = xtrycalloc (1, sizeof *app->app_local);
if (!app->app_local) if (!app->app_local)
{ {
@ -324,6 +374,26 @@ app_select_geldkarte (app_t app)
ld->chipid = result[21]; ld->chipid = result[21];
ld->osvers = result[23]; ld->osvers = result[23];
/* Read the first record of EF_BETRAG (SFI=0x18). */
xfree (result);
err = iso7816_read_record (slot, 1, 1, ((0x18 << 3)|4), &result, &resultlen);
if (err)
goto leave; /* It does not make sense to continue. */
if (resultlen < 12)
{
err = gpg_error (GPG_ERR_NOT_FOUND);
goto leave;
}
err = bcd_to_int (result+0, 3, &ld->balance);
if (!err)
err = bcd_to_int (result+3, 3, &ld->maxamount);
if (!err)
err = bcd_to_int (result+6, 3, &ld->maxamount1);
/* The next 3 bytes are the maximum amount chargable without using a
MAC. This is usually 0. */
if (err)
goto leave;
/* Setup the rest of the methods. */ /* Setup the rest of the methods. */
app->fnc.learn_status = do_learn_status; app->fnc.learn_status = do_learn_status;
app->fnc.getattr = do_getattr; app->fnc.getattr = do_getattr;