mirror of
git://git.gnupg.org/gnupg.git
synced 2024-10-31 20:08:43 +01: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
@ -1,5 +1,18 @@
|
||||
2005-04-27 Werner Koch <wk@g10code.com>
|
||||
|
||||
* 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.
|
||||
|
||||
|
||||
Removal of the old OpenSC based code.
|
||||
|
||||
* app-p15.c: New. Basic support for pkcs15 cards without OpenSC.
|
||||
|
@ -357,7 +357,7 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes,
|
||||
{
|
||||
const unsigned char *s;
|
||||
|
||||
s = find_tlv (buffer, buflen, tag, &valuelen);
|
||||
s = find_tlv_unchecked (buffer, buflen, tag, &valuelen);
|
||||
if (!s)
|
||||
value = NULL; /* not found */
|
||||
else if (valuelen > buflen - (s - buffer))
|
||||
@ -433,7 +433,7 @@ dump_all_do (int slot)
|
||||
|
||||
if (j==i || data_objects[i].tag != data_objects[j].get_from)
|
||||
continue;
|
||||
value = find_tlv (buffer, buflen,
|
||||
value = find_tlv_unchecked (buffer, buflen,
|
||||
data_objects[j].tag, &valuelen);
|
||||
if (!value)
|
||||
; /* not found */
|
||||
|
132
scd/app-p15.c
132
scd/app-p15.c
@ -61,9 +61,13 @@ static struct
|
||||
{ 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",
|
||||
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,12 +2880,12 @@ 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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
err = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen);
|
||||
@ -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)
|
||||
|
@ -83,7 +83,7 @@ select_application (ctrl_t ctrl, int slot, const char *name, app_t *r_app)
|
||||
size_t n;
|
||||
const unsigned char *p;
|
||||
|
||||
p = find_tlv (result, resultlen, 0x5A, &n);
|
||||
p = find_tlv_unchecked (result, resultlen, 0x5A, &n);
|
||||
if (p)
|
||||
resultlen -= (p-result);
|
||||
if (p && n > resultlen && n == 0x0d && resultlen+1 == n)
|
||||
|
@ -299,10 +299,11 @@ iso7816_manage_security_env (int slot, int p1, int p2,
|
||||
{
|
||||
int sw;
|
||||
|
||||
if (p1 < 0 || p1 > 255 || p2 < 0 || p2 > 255 || !data || !datalen)
|
||||
if (p1 < 0 || p1 > 255 || p2 < 0 || p2 > 255 )
|
||||
return gpg_error (GPG_ERR_INV_VALUE);
|
||||
|
||||
sw = apdu_send_simple (slot, 0x00, CMD_MSE, p1, p2, datalen, data);
|
||||
sw = apdu_send_simple (slot, 0x00, CMD_MSE, p1, p2,
|
||||
data? datalen : -1, data);
|
||||
return map_sw (sw);
|
||||
}
|
||||
|
||||
@ -605,7 +606,7 @@ iso7816_read_record (int slot, int recno, int reccount, int short_ef,
|
||||
|
||||
buffer = NULL;
|
||||
bufferlen = 0;
|
||||
/* Fixme: Either the ccid driver of the TCOS cards have problems
|
||||
/* Fixme: Either the ccid driver or the TCOS cards have problems
|
||||
with an Le of 0. */
|
||||
sw = apdu_send_le (slot, 0x00, CMD_READ_RECORD,
|
||||
recno,
|
||||
|
23
scd/tlv.c
23
scd/tlv.c
@ -1,5 +1,5 @@
|
||||
/* tlv.c - Tag-Length-Value Utilities
|
||||
* Copyright (C) 2003, 2004 Free Software Foundation, Inc.
|
||||
* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
*
|
||||
* This file is part of GnuPG.
|
||||
*
|
||||
@ -113,17 +113,32 @@ do_find_tlv (const unsigned char *buffer, size_t length,
|
||||
|
||||
/* Locate a TLV encoded data object in BUFFER of LENGTH and
|
||||
return a pointer to value as well as its length in NBYTES. Return
|
||||
NULL if it was not found. Note, that the function does not check
|
||||
whether the value fits into the provided buffer. */
|
||||
NULL if it was not found or if the object does not fit into the buffer. */
|
||||
const unsigned char *
|
||||
find_tlv (const unsigned char *buffer, size_t length,
|
||||
int tag, size_t *nbytes)
|
||||
{
|
||||
return do_find_tlv (buffer, length, tag, nbytes, 0);
|
||||
const unsigned char *p;
|
||||
|
||||
p = do_find_tlv (buffer, length, tag, nbytes, 0);
|
||||
if (p && *nbytes > (length - (p-buffer)))
|
||||
p = NULL; /* Object longer than buffer. */
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Locate a TLV encoded data object in BUFFER of LENGTH and
|
||||
return a pointer to value as well as its length in NBYTES. Return
|
||||
NULL if it was not found. Note, that the function does not check
|
||||
whether the value fits into the provided buffer. */
|
||||
const unsigned char *
|
||||
find_tlv_unchecked (const unsigned char *buffer, size_t length,
|
||||
int tag, size_t *nbytes)
|
||||
{
|
||||
return do_find_tlv (buffer, length, tag, nbytes, 0);
|
||||
}
|
||||
|
||||
|
||||
/* ASN.1 BER parser: Parse BUFFER of length SIZE and return the tag
|
||||
and the length part from the TLV triplet. Update BUFFER and SIZE
|
||||
|
@ -62,12 +62,19 @@ enum tlv_tag_type {
|
||||
};
|
||||
|
||||
|
||||
/* Locate a TLV encoded data object in BUFFER of LENGTH and return a
|
||||
pointer to value as well as its length in NBYTES. Return NULL if
|
||||
it was not found or if the object does not fit into the buffer. */
|
||||
const unsigned char *find_tlv (const unsigned char *buffer, size_t length,
|
||||
int tag, size_t *nbytes);
|
||||
|
||||
|
||||
/* Locate a TLV encoded data object in BUFFER of LENGTH and return a
|
||||
pointer to value as well as its length in NBYTES. Return NULL if
|
||||
it was not found. Note, that the function does not check whether
|
||||
the value fits into the provided buffer.*/
|
||||
const unsigned char *find_tlv (const unsigned char *buffer, size_t length,
|
||||
const unsigned char *find_tlv_unchecked (const unsigned char *buffer,
|
||||
size_t length,
|
||||
int tag, size_t *nbytes);
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user