1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-03 22:56:33 +02:00

The BELPIC card does now work.

This commit is contained in:
Werner Koch 2005-09-06 18:42:13 +00:00
parent 12f7e943cc
commit d9d2d3da91
11 changed files with 352 additions and 196 deletions

View file

@ -1,3 +1,9 @@
2005-09-06 Werner Koch <wk@g10code.com>
* app-p15.c (do_sign): Tweaked for BELPIC cards.
(read_home_df): New arg R_BELPIC.
(app_select_p15): Set card type for BELPIC.
2005-09-05 Werner Koch <wk@g10code.com>
* iso7816.c (iso7816_select_path): New.

View file

@ -39,8 +39,10 @@ typedef enum
{
CARD_TYPE_UNKNOWN,
CARD_TYPE_TCOS,
CARD_TYPE_MICARDO
} card_type_t;
CARD_TYPE_MICARDO,
CARD_TYPE_BELPIC /* Belgian eID card specs. */
}
card_type_t;
/* A list card types with ATRs noticed with these cards. */
#define X(a) ((unsigned char const *)(a))
@ -2771,6 +2773,8 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
+ the largest OID prefix above. */
prkdf_object_t prkdf; /* The private key object. */
aodf_object_t aodf; /* The associated authentication object. */
int no_data_padding = 0; /* True if the card want the data without padding.*/
int mse_done = 0; /* Set to true if the MSE has been done. */
if (!keyidstr || !*keyidstr)
return gpg_error (GPG_ERR_INV_VALUE);
@ -2833,6 +2837,35 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
return err;
}
/* Due to the fact that the non-repudiation signature on a BELPIC
card requires a ver verify immediately before the DSO we set the
MSE before we do the verification. Other cards might allow to do
this also but I don't want to break anything, thus we do it only
for the BELPIC card here. */
if (app->app_local->card_type == CARD_TYPE_BELPIC)
{
unsigned char mse[5];
mse[0] = 4; /* Length of the template. */
mse[1] = 0x80; /* Algorithm reference tag. */
mse[2] = 0x02; /* Algorithm: RSASSA-PKCS1-v1.5 using SHA1. */
mse[3] = 0x84; /* Private key reference tag. */
mse[4] = prkdf->key_reference_valid? prkdf->key_reference : 0x82;
err = iso7816_manage_security_env (app->slot,
0x41, 0xB6,
mse, sizeof mse);
no_data_padding = 1;
mse_done = 1;
}
if (err)
{
log_error ("MSE failed: %s\n", gpg_strerror (err));
return err;
}
/* Now that we have all the information available, prepare and run
the PIN verification.*/
if (1)
@ -2841,8 +2874,12 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
size_t pinvaluelen;
const char *errstr;
const char *s;
err = pincb (pincb_arg, "PIN", &pinvalue);
if (prkdf->usageflags.non_repudiation
&& app->app_local->card_type == CARD_TYPE_BELPIC)
err = pincb (pincb_arg, "PIN (qualified signature!)", &pinvalue);
else
err = pincb (pincb_arg, "PIN", &pinvalue);
if (err)
{
log_info ("PIN callback returned error: %s\n", gpg_strerror (err));
@ -2884,8 +2921,6 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
switch (aodf->pintype)
{
case PIN_TYPE_BCD:
errstr = "PIN type BCD is not supported";
break;
case PIN_TYPE_ASCII_NUMERIC:
for (s=pinvalue; digitp (s); s++)
;
@ -2914,7 +2949,39 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
return err? err : gpg_error (GPG_ERR_BAD_PIN_METHOD);
}
if (aodf->pinflags.needs_padding)
if (aodf->pintype == PIN_TYPE_BCD )
{
char *paddedpin;
int ndigits;
for (ndigits=0, s=pinvalue; *s; ndigits++, s++)
;
paddedpin = xtrymalloc (aodf->stored_length+1);
if (!paddedpin)
{
err = gpg_error_from_errno (errno);
xfree (pinvalue);
return err;
}
i = 0;
paddedpin[i++] = 0x20 | (ndigits & 0x0f);
for (s=pinvalue; i < aodf->stored_length && *s && s[1]; s = s+2 )
paddedpin[i++] = (((*s - '0') << 4) | ((s[1] - '0') & 0x0f));
if (i < aodf->stored_length && *s)
paddedpin[i++] = (((*s - '0') << 4)
|((aodf->pad_char_valid?aodf->pad_char:0)&0x0f));
if (aodf->pinflags.needs_padding)
while (i < aodf->stored_length)
paddedpin[i++] = aodf->pad_char_valid? aodf->pad_char : 0;
xfree (pinvalue);
pinvalue = paddedpin;
pinvaluelen = i;
}
else if (aodf->pinflags.needs_padding)
{
char *paddedpin;
@ -2979,7 +3046,9 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
}
/* Manage security environment needs to be weaked for certain cards. */
if (app->app_local->card_type == CARD_TYPE_TCOS)
if (mse_done)
err = 0;
else if (app->app_local->card_type == CARD_TYPE_TCOS)
{
/* TCOS creates signatures always using the local key 0. MSE
may not be used. */
@ -3009,18 +3078,21 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
return err;
}
err = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen);
if (no_data_padding)
err = iso7816_compute_ds (app->slot, data+15, 20, outdata, outdatalen);
else
err = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen);
return err;
}
/* Assume that EF(DIR) has been selected. Read its content and figure
out the home EF of pkcs#15. Return that home DF or 0 if not
found. */
out the home EF of pkcs#15. Return that home DF or 0 if not found
and the value at the address of BELPIC indicates whether it was
found by the belpic aid. */
static unsigned short
read_home_df (int slot)
read_home_df (int slot, int *r_belpic)
{
gpg_error_t err;
unsigned char *buffer;
@ -3028,6 +3100,8 @@ read_home_df (int slot)
size_t buflen, n, nn;
unsigned short result = 0;
*r_belpic = 0;
err = iso7816_read_binary (slot, 0, 0, &buffer, &buflen);
if (err)
{
@ -3040,9 +3114,9 @@ read_home_df (int slot)
if (p && n)
{
pp = find_tlv (p, n, 0x4f, &nn);
if (pp
&& ((nn == sizeof pkcs15_aid && !memcmp (pp, pkcs15_aid, nn))
||(nn == sizeof pkcs15be_aid && !memcmp (pp, pkcs15be_aid, nn))))
if (pp && ((nn == sizeof pkcs15_aid && !memcmp (pp, pkcs15_aid, nn))
|| (*r_belpic = (nn == sizeof pkcs15be_aid
&& !memcmp (pp, pkcs15be_aid, nn)))))
{
pp = find_tlv (p, n, 0x50, &nn);
if (pp) /* fixme: Filter log value? */
@ -3072,10 +3146,15 @@ app_select_p15 (app_t app)
unsigned short def_home_df = 0;
card_type_t card_type = CARD_TYPE_UNKNOWN;
int direct = 0;
int is_belpic = 0;
rc = iso7816_select_application (slot, pkcs15_aid, sizeof pkcs15_aid);
if (rc)
rc = iso7816_select_application (slot, pkcs15be_aid, sizeof pkcs15be_aid);
{
rc = iso7816_select_application (slot, pkcs15be_aid,sizeof pkcs15be_aid);
if (!rc)
is_belpic = 1;
}
if (rc)
{ /* Not found: Try to locate it from 2F00. We use direct path
selection here because it seems that the Belgian eID card
@ -3087,7 +3166,7 @@ app_select_p15 (app_t app)
if (!rc)
{
direct = 1;
def_home_df = read_home_df (slot);
def_home_df = read_home_df (slot, &is_belpic);
if (def_home_df)
{
path[0] = def_home_df;
@ -3102,24 +3181,33 @@ app_select_p15 (app_t app)
}
if (!rc)
{
/* We need to know the ATR for tweaking some security operations. */
unsigned char *atr;
size_t atrlen;
int i;
atr = apdu_get_atr (app->slot, &atrlen);
if (!atr)
rc = gpg_error (GPG_ERR_INV_CARD);
/* Determine the type of the card. The general case is to look
it up from the ATR table. For the Belgian eID card we know
it instantly from the AID. */
if (is_belpic)
{
card_type = CARD_TYPE_BELPIC;
}
else
{
for (i=0; card_atr_list[i].atrlen; i++)
if (card_atr_list[i].atrlen == atrlen
&& !memcmp (card_atr_list[i].atr, atr, atrlen))
{
card_type = card_atr_list[i].type;
break;
}
xfree (atr);
unsigned char *atr;
size_t atrlen;
int i;
atr = apdu_get_atr (app->slot, &atrlen);
if (!atr)
rc = gpg_error (GPG_ERR_INV_CARD);
else
{
for (i=0; card_atr_list[i].atrlen; i++)
if (card_atr_list[i].atrlen == atrlen
&& !memcmp (card_atr_list[i].atr, atr, atrlen))
{
card_type = card_atr_list[i].type;
break;
}
xfree (atr);
}
}
}
if (!rc)

View file

@ -667,7 +667,7 @@ pin_cb (void *opaque, const char *info, char **retstr)
return gpg_error (gpg_err_code_from_errno (errno));
/* Fixme: Write an inquire function which returns the result in
secure memory and check all futher handling of the PIN. */
secure memory and check all further handling of the PIN. */
rc = assuan_inquire (ctx, command, &value, &valuelen, MAXLEN_PIN);
free (command);
if (rc)