1
0
Fork 0
mirror of git://git.gnupg.org/gnupg.git synced 2025-07-02 22:46:30 +02:00

Add readcert command.

fix reading large certificates.
This commit is contained in:
Werner Koch 2009-06-17 09:45:50 +00:00
parent bdbeb0ac2b
commit 5f8acaccc0
10 changed files with 232 additions and 67 deletions

View file

@ -75,43 +75,45 @@ static struct {
int tag;
int constructed;
int get_from; /* Constructed DO with this DO or 0 for direct access. */
int binary;
int dont_cache;
int flush_on_error;
int get_immediate_in_v11; /* Enable a hack to bypass the cache of
this data object if it is used in 1.1
and later versions of the card. This
does not work with composite DO and is
currently only useful for the CHV
status bytes. */
int binary:1;
int dont_cache:1;
int flush_on_error:1;
int get_immediate_in_v11:1; /* Enable a hack to bypass the cache of
this data object if it is used in 1.1
and later versions of the card. This
does not work with composite DO and
is currently only useful for the CHV
status bytes. */
int try_extlen:1; /* Large object; try to use an extended
length APDU. */
char *desc;
} data_objects[] = {
{ 0x005E, 0, 0, 1, 0, 0, 0, "Login Data" },
{ 0x5F50, 0, 0, 0, 0, 0, 0, "URL" },
{ 0x5F52, 0, 0, 1, 0, 0, 0, "Historical Bytes" },
{ 0x0065, 1, 0, 1, 0, 0, 0, "Cardholder Related Data"},
{ 0x005B, 0, 0x65, 0, 0, 0, 0, "Name" },
{ 0x5F2D, 0, 0x65, 0, 0, 0, 0, "Language preferences" },
{ 0x5F35, 0, 0x65, 0, 0, 0, 0, "Sex" },
{ 0x006E, 1, 0, 1, 0, 0, 0, "Application Related Data" },
{ 0x004F, 0, 0x6E, 1, 0, 0, 0, "AID" },
{ 0x0073, 1, 0, 1, 0, 0, 0, "Discretionary Data Objects" },
{ 0x0047, 0, 0x6E, 1, 1, 0, 0, "Card Capabilities" },
{ 0x00C0, 0, 0x6E, 1, 1, 0, 0, "Extended Card Capabilities" },
{ 0x00C1, 0, 0x6E, 1, 1, 0, 0, "Algorithm Attributes Signature" },
{ 0x00C2, 0, 0x6E, 1, 1, 0, 0, "Algorithm Attributes Decryption" },
{ 0x00C3, 0, 0x6E, 1, 1, 0, 0, "Algorithm Attributes Authentication" },
{ 0x00C4, 0, 0x6E, 1, 0, 1, 1, "CHV Status Bytes" },
{ 0x00C5, 0, 0x6E, 1, 0, 0, 0, "Fingerprints" },
{ 0x00C6, 0, 0x6E, 1, 0, 0, 0, "CA Fingerprints" },
{ 0x00CD, 0, 0x6E, 1, 0, 0, 0, "Generation time" },
{ 0x007A, 1, 0, 1, 0, 0, 0, "Security Support Template" },
{ 0x0093, 0, 0x7A, 1, 1, 0, 0, "Digital Signature Counter" },
{ 0x0101, 0, 0, 0, 0, 0, 0, "Private DO 1"},
{ 0x0102, 0, 0, 0, 0, 0, 0, "Private DO 2"},
{ 0x0103, 0, 0, 0, 0, 0, 0, "Private DO 3"},
{ 0x0104, 0, 0, 0, 0, 0, 0, "Private DO 4"},
{ 0x7F21, 1, 0, 1, 0, 0, 0, "Cardholder certificate"},
{ 0x005E, 0, 0, 1, 0, 0, 0, 0, "Login Data" },
{ 0x5F50, 0, 0, 0, 0, 0, 0, 0, "URL" },
{ 0x5F52, 0, 0, 1, 0, 0, 0, 0, "Historical Bytes" },
{ 0x0065, 1, 0, 1, 0, 0, 0, 0, "Cardholder Related Data"},
{ 0x005B, 0, 0x65, 0, 0, 0, 0, 0, "Name" },
{ 0x5F2D, 0, 0x65, 0, 0, 0, 0, 0, "Language preferences" },
{ 0x5F35, 0, 0x65, 0, 0, 0, 0, 0, "Sex" },
{ 0x006E, 1, 0, 1, 0, 0, 0, 0, "Application Related Data" },
{ 0x004F, 0, 0x6E, 1, 0, 0, 0, 0, "AID" },
{ 0x0073, 1, 0, 1, 0, 0, 0, 0, "Discretionary Data Objects" },
{ 0x0047, 0, 0x6E, 1, 1, 0, 0, 0, "Card Capabilities" },
{ 0x00C0, 0, 0x6E, 1, 1, 0, 0, 0, "Extended Card Capabilities" },
{ 0x00C1, 0, 0x6E, 1, 1, 0, 0, 0, "Algorithm Attributes Signature" },
{ 0x00C2, 0, 0x6E, 1, 1, 0, 0, 0, "Algorithm Attributes Decryption" },
{ 0x00C3, 0, 0x6E, 1, 1, 0, 0, 0, "Algorithm Attributes Authentication" },
{ 0x00C4, 0, 0x6E, 1, 0, 1, 1, 0, "CHV Status Bytes" },
{ 0x00C5, 0, 0x6E, 1, 0, 0, 0, 0, "Fingerprints" },
{ 0x00C6, 0, 0x6E, 1, 0, 0, 0, 0, "CA Fingerprints" },
{ 0x00CD, 0, 0x6E, 1, 0, 0, 0, 0, "Generation time" },
{ 0x007A, 1, 0, 1, 0, 0, 0, 0, "Security Support Template" },
{ 0x0093, 0, 0x7A, 1, 1, 0, 0, 0, "Digital Signature Counter" },
{ 0x0101, 0, 0, 0, 0, 0, 0, 0, "Private DO 1"},
{ 0x0102, 0, 0, 0, 0, 0, 0, 0, "Private DO 2"},
{ 0x0103, 0, 0, 0, 0, 0, 0, 0, "Private DO 3"},
{ 0x0104, 0, 0, 0, 0, 0, 0, 0, "Private DO 4"},
{ 0x7F21, 1, 0, 1, 0, 0, 0, 1, "Cardholder certificate"},
{ 0 }
};
@ -244,17 +246,19 @@ do_deinit (app_t app)
/* Wrapper around iso7816_get_data which first tries to get the data
from the cache. With GET_IMMEDIATE passed as true, the cache is
bypassed. */
bypassed. With TRY_EXTLEN extended lengths APDUs are use if
supported by the card. */
static gpg_error_t
get_cached_data (app_t app, int tag,
unsigned char **result, size_t *resultlen,
int get_immediate)
int get_immediate, int try_extlen)
{
gpg_error_t err;
int i;
unsigned char *p;
size_t len;
struct cache_s *c;
int exmode;
*result = NULL;
*resultlen = 0;
@ -279,7 +283,12 @@ get_cached_data (app_t app, int tag,
}
}
err = iso7816_get_data (app->slot, tag, &p, &len);
if (try_extlen && app->app_local->cardcap.ext_lc_le)
exmode = app->app_local->extcap.max_rsp_data;
else
exmode = 0;
err = iso7816_get_data (app->slot, exmode, tag, &p, &len);
if (err)
return err;
*result = p;
@ -392,6 +401,7 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes,
unsigned char *value;
size_t valuelen;
int dummyrc;
int exmode;
if (!r_rc)
r_rc = &dummyrc;
@ -404,7 +414,11 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes,
if (app->card_version > 0x0100 && data_objects[i].get_immediate_in_v11)
{
rc = iso7816_get_data (app->slot, tag, &buffer, &buflen);
if (data_objects[i].try_extlen && app->app_local->cardcap.ext_lc_le)
exmode = app->app_local->extcap.max_rsp_data;
else
exmode = 0;
rc = iso7816_get_data (app->slot, exmode, tag, &buffer, &buflen);
if (rc)
{
*r_rc = rc;
@ -422,7 +436,8 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes,
rc = get_cached_data (app, data_objects[i].get_from,
&buffer, &buflen,
(data_objects[i].dont_cache
|| data_objects[i].get_immediate_in_v11));
|| data_objects[i].get_immediate_in_v11),
data_objects[i].try_extlen);
if (!rc)
{
const unsigned char *s;
@ -445,7 +460,8 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes,
{
rc = get_cached_data (app, tag, &buffer, &buflen,
(data_objects[i].dont_cache
|| data_objects[i].get_immediate_in_v11));
|| data_objects[i].get_immediate_in_v11),
data_objects[i].try_extlen);
if (!rc)
{
value = buffer;
@ -476,7 +492,9 @@ dump_all_do (int slot)
if (data_objects[i].get_from)
continue;
rc = iso7816_get_data (slot, data_objects[i].tag, &buffer, &buflen);
/* We don't try extended length APDU because such large DO would
be pretty useless in a log file. */
rc = iso7816_get_data (slot, 0, data_objects[i].tag, &buffer, &buflen);
if (gpg_err_code (rc) == GPG_ERR_NO_OBJ)
;
else if (rc)
@ -621,13 +639,14 @@ parse_login_data (app_t app)
/* Note, that FPR must be at least 20 bytes. */
static gpg_error_t
store_fpr (int slot, int keynumber, u32 timestamp,
store_fpr (app_t app, int keynumber, u32 timestamp,
const unsigned char *m, size_t mlen,
const unsigned char *e, size_t elen,
unsigned char *fpr, unsigned int card_version)
{
unsigned int n, nbits;
unsigned char *buffer, *p;
int tag, tag2;
int rc;
for (; mlen && !*m; mlen--, m++) /* strip leading zeroes */
@ -662,9 +681,12 @@ store_fpr (int slot, int keynumber, u32 timestamp,
xfree (buffer);
rc = iso7816_put_data (slot, 0,
(card_version > 0x0007? 0xC7 : 0xC6)
+ keynumber, fpr, 20);
tag = (card_version > 0x0007? 0xC7 : 0xC6) + keynumber;
flush_cache_item (app, tag);
tag2 = 0xCE + keynumber;
flush_cache_item (app, tag2);
rc = iso7816_put_data (app->slot, 0, tag, fpr, 20);
if (rc)
log_error (_("failed to store the fingerprint: %s\n"),gpg_strerror (rc));
@ -677,7 +699,7 @@ store_fpr (int slot, int keynumber, u32 timestamp,
buf[2] = timestamp >> 8;
buf[3] = timestamp;
rc = iso7816_put_data (slot, 0, 0xCE + keynumber, buf, 4);
rc = iso7816_put_data (app->slot, 0, tag2, buf, 4);
if (rc)
log_error (_("failed to store the creation date: %s\n"),
gpg_strerror (rc));
@ -2131,7 +2153,7 @@ does_key_exist (app_t app, int keyidx, int force)
assert (keyidx >=0 && keyidx <= 2);
if (iso7816_get_data (app->slot, 0x006E, &buffer, &buflen))
if (iso7816_get_data (app->slot, 0, 0x006E, &buffer, &buflen))
{
log_error (_("error reading application data\n"));
return gpg_error (GPG_ERR_GENERAL);
@ -2623,7 +2645,7 @@ do_writekey (app_t app, ctrl_t ctrl,
goto leave;
}
err = store_fpr (app->slot, keyno, created_at,
err = store_fpr (app, keyno, created_at,
rsa_n, rsa_n_len, rsa_e, rsa_e_len,
fprbuf, app->card_version);
if (err)
@ -2757,7 +2779,7 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
send_status_info (ctrl, "KEY-CREATED-AT",
numbuf, (size_t)strlen(numbuf), NULL, 0);
rc = store_fpr (app->slot, keyno, (u32)created_at,
rc = store_fpr (app, keyno, (u32)created_at,
m, mlen, e, elen, fprbuf, app->card_version);
if (rc)
goto leave;
@ -2811,7 +2833,7 @@ compare_fingerprint (app_t app, int keyno, unsigned char *sha1fpr)
assert (keyno >= 1 && keyno <= 3);
rc = get_cached_data (app, 0x006E, &buffer, &buflen, 0);
rc = get_cached_data (app, 0x006E, &buffer, &buflen, 0, 0);
if (rc)
{
log_error (_("error reading application data\n"));
@ -3502,7 +3524,7 @@ app_select_openpgp (app_t app)
replace a possibly already set one from a EF.GDO with this
one. Note, that for current OpenPGP cards, no EF.GDO exists
and thus it won't matter at all. */
rc = iso7816_get_data (slot, 0x004F, &buffer, &buflen);
rc = iso7816_get_data (slot, 0, 0x004F, &buffer, &buflen);
if (rc)
goto leave;
if (opt.verbose)