mirror of
git://git.gnupg.org/gnupg.git
synced 2025-07-03 22:56:33 +02:00
* app-p15.c (micardo_mse): New.
(do_sign): Call it. * iso7816.c (iso7816_manage_security_env): Allow passing DATA as NULL to indicate an empty Lc. * tlv.c (find_tlv): Check that a found object fits into the buffer. (find_tlv_unchecked): New as replacement for the old non-checking variant. * app.c (select_application): Keep on using the non-checking variant. * app-openpgp.c (get_one_do, dump_all_do): Ditto.
This commit is contained in:
parent
f2fe118bfb
commit
eb3f014b5d
7 changed files with 175 additions and 29 deletions
142
scd/app-p15.c
142
scd/app-p15.c
|
@ -59,11 +59,15 @@ static struct
|
|||
"\x90\x00\x66",
|
||||
CARD_TYPE_TCOS }, /* SLE66P */
|
||||
{ 27, "\x3B\xFF\x94\x00\xFF\x80\xB1\xFE\x45\x1F\x03\x00\x68\xD2\x76\x00"
|
||||
"\x00\x28\xFF\x05\x1E\x31\x80\x00\x90\x00\x23",
|
||||
"\x00\x28\xFF\x05\x1E\x31\x80\x00\x90\x00\x23",
|
||||
CARD_TYPE_MICARDO }, /* German BMI card */
|
||||
{ 19, "\x3B\x6F\x00\xFF\x00\x68\xD2\x76\x00\x00\x28\xFF\x05\x1E\x31\x80"
|
||||
"\x00\x90\x00",
|
||||
CARD_TYPE_MICARDO }, /* German BMI card (ATR due to reader problem) */
|
||||
{ 26, "\x3B\xFE\x94\x00\xFF\x80\xB1\xFA\x45\x1F\x03\x45\x73\x74\x45\x49"
|
||||
"\x44\x20\x76\x65\x72\x20\x31\x2E\x30\x43",
|
||||
CARD_TYPE_MICARDO }, /* EstEID (Estonian Big Brother card) */
|
||||
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
|
@ -392,7 +396,7 @@ select_and_read_binary (int slot, unsigned short efid, const char *efid_desc,
|
|||
}
|
||||
|
||||
|
||||
/* This function calls select file to read a file suing a complete
|
||||
/* This function calls select file to read a file using a complete
|
||||
path which may or may not start at the master file (MF). */
|
||||
static gpg_error_t
|
||||
select_ef_by_path (app_t app, const unsigned short *path, size_t pathlen)
|
||||
|
@ -2525,6 +2529,99 @@ do_readcert (app_t app, const char *certid,
|
|||
}
|
||||
|
||||
|
||||
/* Micardo cards require special treatment. This is a helper for the
|
||||
crypto functions to manage the security environment. We expect that
|
||||
the key file has already been selected. FID is the one of the
|
||||
selected key. */
|
||||
static gpg_error_t
|
||||
micardo_mse (app_t app, unsigned short fid)
|
||||
{
|
||||
gpg_error_t err;
|
||||
int recno;
|
||||
unsigned short refdata = 0;
|
||||
int se_num;
|
||||
unsigned char msebuf[10];
|
||||
|
||||
/* Read the KeyD file containing extra information on keys. */
|
||||
err = iso7816_select_file (app->slot, 0x0013, 0, NULL, NULL);
|
||||
if (err)
|
||||
{
|
||||
log_error ("error reading EF_keyD: %s\n", gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
|
||||
for (recno = 1, se_num = -1; ; recno++)
|
||||
{
|
||||
unsigned char *buffer;
|
||||
size_t buflen;
|
||||
size_t n, nn;
|
||||
const unsigned char *p, *pp;
|
||||
|
||||
err = iso7816_read_record (app->slot, recno, 1, 0, &buffer, &buflen);
|
||||
if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
|
||||
break; /* ready */
|
||||
if (err)
|
||||
{
|
||||
log_error ("error reading EF_keyD record: %s\n",
|
||||
gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
log_printhex ("keyD record:", buffer, buflen);
|
||||
p = find_tlv (buffer, buflen, 0x83, &n);
|
||||
if (p && n == 4 && ((p[2]<<8)|p[3]) == fid)
|
||||
{
|
||||
refdata = ((p[0]<<8)|p[1]);
|
||||
/* Locate the SE DO and the there included sec env number. */
|
||||
p = find_tlv (buffer, buflen, 0x7b, &n);
|
||||
if (p && n)
|
||||
{
|
||||
pp = find_tlv (p, n, 0x80, &nn);
|
||||
if (pp && nn == 1)
|
||||
{
|
||||
se_num = *pp;
|
||||
xfree (buffer);
|
||||
break; /* found. */
|
||||
}
|
||||
}
|
||||
}
|
||||
xfree (buffer);
|
||||
}
|
||||
if (se_num == -1)
|
||||
{
|
||||
log_error ("CRT for keyfile %04hX not found\n", fid);
|
||||
return gpg_error (GPG_ERR_NOT_FOUND);
|
||||
}
|
||||
|
||||
|
||||
/* Restore the security environment to SE_NUM if needed */
|
||||
if (se_num)
|
||||
{
|
||||
err = iso7816_manage_security_env (app->slot, 0xf3, se_num, NULL, 0);
|
||||
if (err)
|
||||
{
|
||||
log_error ("restoring SE to %d failed: %s\n",
|
||||
se_num, gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the DST reference data. */
|
||||
msebuf[0] = 0x83;
|
||||
msebuf[1] = 0x03;
|
||||
msebuf[2] = 0x80;
|
||||
msebuf[3] = (refdata >> 8);
|
||||
msebuf[4] = refdata;
|
||||
err = iso7816_manage_security_env (app->slot, 0x41, 0xb6, msebuf, 5);
|
||||
if (err)
|
||||
{
|
||||
log_error ("setting SE to reference file %04hX failed: %s\n",
|
||||
refdata, gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Handler for the PKSIGN command.
|
||||
|
||||
|
@ -2561,6 +2658,13 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
|
|||
err = prkdf_object_from_keyidstr (app, keyidstr, &prkdf);
|
||||
if (err)
|
||||
return err;
|
||||
if (!(prkdf->usageflags.sign || prkdf->usageflags.sign_recover
|
||||
||prkdf->usageflags.non_repudiation))
|
||||
{
|
||||
log_error ("key %s may not be used for signing\n", keyidstr);
|
||||
return gpg_error (GPG_ERR_WRONG_KEY_USAGE);
|
||||
}
|
||||
|
||||
if (!prkdf->authid)
|
||||
{
|
||||
log_error ("no authentication object defined for %s\n", keyidstr);
|
||||
|
@ -2597,6 +2701,16 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
|
|||
return gpg_error (GPG_ERR_INV_CARD);
|
||||
}
|
||||
|
||||
/* Select the key file. Note that this may change the security
|
||||
environment thus we do it before PIN verification. */
|
||||
err = select_ef_by_path (app, prkdf->path, prkdf->pathlen);
|
||||
if (err)
|
||||
{
|
||||
log_error ("error selecting file for key %s: %s\n",
|
||||
keyidstr, gpg_strerror (errno));
|
||||
return err;
|
||||
}
|
||||
|
||||
/* Now that we have all the information available, prepare and run
|
||||
the PIN verification.*/
|
||||
if (1)
|
||||
|
@ -2742,7 +2856,6 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
|
|||
memcpy (data+15, indata, indatalen);
|
||||
}
|
||||
|
||||
|
||||
/* Manage security environment needs to be weaked for certain cards. */
|
||||
if (app->app_local->card_type == CARD_TYPE_TCOS)
|
||||
{
|
||||
|
@ -2751,10 +2864,10 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
|
|||
}
|
||||
else if (app->app_local->card_type == CARD_TYPE_MICARDO)
|
||||
{
|
||||
/* Micardo cards are very special in that they need to restore a
|
||||
security environment using a infomration from a special
|
||||
file. */
|
||||
log_error ("WARNING: support for MICARDO cards is not yet available\n");
|
||||
if (!prkdf->pathlen)
|
||||
err = gpg_error (GPG_ERR_BUG);
|
||||
else
|
||||
err = micardo_mse (app, prkdf->path[prkdf->pathlen-1]);
|
||||
}
|
||||
else if (prkdf->key_reference_valid)
|
||||
{
|
||||
|
@ -2767,11 +2880,11 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
|
|||
err = iso7816_manage_security_env (app->slot,
|
||||
0x41, 0xB6,
|
||||
mse, sizeof mse);
|
||||
if (err)
|
||||
{
|
||||
log_error ("MSE failed: %s\n", gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
}
|
||||
if (err)
|
||||
{
|
||||
log_error ("MSE failed: %s\n", gpg_strerror (err));
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
@ -2782,9 +2895,6 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* Select the PKCS#15 application on the card in SLOT. */
|
||||
gpg_error_t
|
||||
app_select_p15 (app_t app)
|
||||
|
@ -2846,7 +2956,7 @@ app_select_p15 (app_t app)
|
|||
the common APP structure. */
|
||||
app->app_local->card_type = card_type;
|
||||
|
||||
/* Read basic information and check whether this is a real
|
||||
/* Read basic information and thus check whether this is a real
|
||||
card. */
|
||||
rc = read_p15_info (app);
|
||||
if (rc)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue