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

* de.po: Updated.

* POTFILES.in: Add more files.

* app-openpgp.c (do_sign): Add the error string to the verify
failed messages.

* keylist.c (list_cert_colon): Make sure that the expired flag has
a higher precedence than the invalid flag.
This commit is contained in:
Werner Koch 2004-09-30 13:24:33 +00:00
parent ce6a094cc0
commit f67c66e56f
7 changed files with 396 additions and 96 deletions

View file

@ -1,3 +1,74 @@
2004-09-30 Werner Koch <wk@g10code.com>
* app-openpgp.c (do_sign): Add the error string to the verify
failed messages.
2004-09-27 Werner Koch <wk@g10code.com>
From gnupg 1.3
* app-openpgp.c: Made all strings translatable.
(verify_chv3) [GNUPG_MAJOR_VERSION]: Make opt.allow_admin
available for use in gnupg 2.
(verify_chv3): Reimplemented countdown showing to use only
functions from this module. Flush the CVH status cache on a
successful read.
(get_one_do): Hack to bypass the cache for cards versions > 1.0.
(store_fpr): Store the creation date for card version > 1.0.
* app-openpgp.c (app_openpgp_storekey): Call flush_cache.
(get_cached_data): Move local data initialization to ..
(app_select_openpgp): .. here. Read some flags for later use.
(do_getattr): New read-only attribute EXTCAP.
* apdu.c (open_pcsc_reader): Do not print empty reader string.
* ccid-driver.c (do_close_reader): Factored some code out from ...
(ccid_close_reader): ..here.
(ccid_shutdown_reader): New.
* apdu.c (apdu_shutdown_reader): New.
(shutdown_ccid_reader): New.
* apdu.c (open_ccid_reader): New arg PORTSTR. Pass it to
ccid_open_reader.
(apdu_open_reader): Pass portstr to open_ccid_reader.
(apdu_open_reader): No fallback if a full CCID reader id has been
given.
* ccid-driver.c (ccid_get_reader_list): New.
(ccid_open_reader): Changed API to take a string for the reader.
Removed al the cruft for the libusb development vesion which seems
not to be maintained anymore and there are no packages anyway.
The stable library works just fine.
(struct ccid_reader_id_s): Deleted and replaced everywhere by a
simple string.
(usb_get_string_simple): Removed.
(bulk_in): Do valgrind hack here and not just everywhere.
* ccid-driver.c (read_device_info): Removed.
(make_reader_id, scan_or_find_devices): New.
(ccid_open_reader): Simplified by make use of the new functions.
(ccid_set_debug_level): New. Changed the macros to make use of
it. It has turned out that it is often useful to enable debugging
at runtime so I added this option.
From gnupg 1.3 - David Shaw <dshaw@jabberwocky.com>
* app-openpgp.c (verify_chv3): Show a countdown of how many wrong
admin PINs can be entered before the card is locked.
* app-openpgp.c (get_cached_data): Avoid mallocing zero since it
breaks us when using --enable-m-guard.
* ccid-driver.c (usb_get_string_simple): Replacement function to
work with older libusb.
* ccid-driver.c (read_device_info): Fix segfault when usb device
is not accessible.
(ccid_open_reader): Allow working with an even older version of
libusb (usb_busses global instead of usb_get_busses()).
2004-09-11 Werner Koch <wk@g10code.com>
* app-openpgp.c (app_select_openpgp): Its app_munge_serialno and

View file

@ -34,12 +34,12 @@
#include "errors.h"
#include "memory.h"
#include "util.h"
#include "i18n.h"
#include "cardglue.h"
#else /* GNUPG_MAJOR_VERSION != 1 */
#include "scdaemon.h"
#endif /* GNUPG_MAJOR_VERSION != 1 */
#include "i18n.h"
#include "iso7816.h"
#include "app-common.h"
#include "tlv.h"
@ -52,27 +52,33 @@ static struct {
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. */
char *desc;
} data_objects[] = {
{ 0x005E, 0, 0, 1, 0, 0, "Login Data" },
{ 0x5F50, 0, 0, 0, 0, 0, "URL" },
{ 0x0065, 1, 0, 1, 0, 0, "Cardholder Related Data"},
{ 0x005B, 0, 0x65, 0, 0, 0, "Name" },
{ 0x5F2D, 0, 0x65, 0, 0, 0, "Language preferences" },
{ 0x5F35, 0, 0x65, 0, 0, 0, "Sex" },
{ 0x006E, 1, 0, 1, 0, 0, "Application Related Data" },
{ 0x004F, 0, 0x6E, 1, 0, 0, "AID" },
{ 0x0073, 1, 0, 1, 0, 0, "Discretionary Data Objects" },
{ 0x0047, 0, 0x6E, 1, 0, 0, "Card Capabilities" },
{ 0x00C0, 0, 0x6E, 1, 0, 0, "Extended Card Capabilities" },
{ 0x00C1, 0, 0x6E, 1, 0, 0, "Algorithm Attributes Signature" },
{ 0x00C2, 0, 0x6E, 1, 0, 0, "Algorithm Attributes Decryption" },
{ 0x00C3, 0, 0x6E, 1, 0, 0, "Algorithm Attributes Authentication" },
{ 0x00C4, 0, 0x6E, 1, 0, 1, "CHV Status Bytes" },
{ 0x00C5, 0, 0x6E, 1, 0, 0, "Fingerprints" },
{ 0x00C6, 0, 0x6E, 1, 0, 0, "CA Fingerprints" },
{ 0x007A, 1, 0, 1, 0, 0, "Security Support Template" },
{ 0x0093, 0, 0x7A, 1, 1, 0, "Digital Signature Counter" },
{ 0x005E, 0, 0, 1, 0, 0, 0, "Login Data" },
{ 0x5F50, 0, 0, 0, 0, 0, 0, "URL" },
{ 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" },
{ 0x007A, 1, 0, 1, 0, 0, 0, "Security Support Template" },
{ 0x0093, 0, 0x7A, 1, 1, 0, 0, "Digital Signature Counter" },
{ 0 }
};
@ -86,6 +92,13 @@ struct cache_s {
struct app_local_s {
struct cache_s *cache;
struct
{
unsigned int get_challenge:1;
unsigned int key_import:1;
unsigned int change_force_chv:1;
unsigned int private_dos:1;
} extcap;
};
@ -124,24 +137,26 @@ get_cached_data (app_t app, int tag,
size_t len;
struct cache_s *c;
*result = NULL;
*resultlen = 0;
if (app->app_local)
{
for (c=app->app_local->cache; c; c = c->next)
if (c->tag == tag)
for (c=app->app_local->cache; c; c = c->next)
if (c->tag == tag)
{
if(c->length)
{
p = xtrymalloc (c->length);
if (!p)
return gpg_error (gpg_err_code_from_errno (errno));
memcpy (p, c->data, c->length);
*resultlen = c->length;
*result = p;
return 0;
p = xtrymalloc (c->length);
if (!p)
return gpg_error (gpg_err_code_from_errno (errno));
memcpy (p, c->data, c->length);
*result = p;
}
}
*resultlen = c->length;
return 0;
}
err = iso7816_get_data (app->slot, tag, &p, &len);
if (err)
@ -159,24 +174,18 @@ get_cached_data (app_t app, int tag,
}
/* No, cache it. */
if (!app->app_local)
app->app_local = xtrycalloc (1, sizeof *app->app_local);
/* Note that we can safely ignore out of core errors. */
if (app->app_local)
for (c=app->app_local->cache; c; c = c->next)
assert (c->tag != tag);
c = xtrymalloc (sizeof *c + len);
if (c)
{
for (c=app->app_local->cache; c; c = c->next)
assert (c->tag != tag);
c = xtrymalloc (sizeof *c + len);
if (c)
{
memcpy (c->data, p, len);
c->length = len;
c->tag = tag;
c->next = app->app_local->cache;
app->app_local->cache = c;
}
memcpy (c->data, p, len);
c->length = len;
c->tag = tag;
c->next = app->app_local->cache;
app->app_local->cache = c;
}
return 0;
@ -202,7 +211,9 @@ flush_cache_item (app_t app, int tag)
xfree (c);
for (c=app->app_local->cache; c ; c = c->next)
assert (c->tag != tag); /* Oops: duplicated entry. */
{
assert (c->tag != tag); /* Oops: duplicated entry. */
}
return;
}
@ -262,6 +273,15 @@ get_one_do (app_t app, int tag, unsigned char **result, size_t *nbytes)
for (i=0; data_objects[i].tag && data_objects[i].tag != tag; i++)
;
if (app->card_version > 0x0100 && data_objects[i].get_immediate_in_v11)
{
if( iso7816_get_data (app->slot, tag, &buffer, &buflen))
return NULL;
*result = buffer;
*nbytes = buflen;
return buffer;
}
value = NULL;
rc = -1;
if (data_objects[i].tag && data_objects[i].get_from)
@ -428,7 +448,6 @@ store_fpr (int slot, int keynumber, u32 timestamp,
*p++ = nbits;
memcpy (p, e, elen); p += elen;
log_printhex ("fprbuf:", buffer, n+3);
gcry_md_hash_buffer (GCRY_MD_SHA1, fpr, buffer, n+3);
xfree (buffer);
@ -436,7 +455,22 @@ store_fpr (int slot, int keynumber, u32 timestamp,
rc = iso7816_put_data (slot, (card_version > 0x0007? 0xC7 : 0xC6)
+ keynumber, fpr, 20);
if (rc)
log_error ("failed to store the fingerprint: %s\n",gpg_strerror (rc));
log_error (_("failed to store the fingerprint: %s\n"),gpg_strerror (rc));
if (!rc && card_version > 0x0100)
{
unsigned char buf[4];
buf[0] = timestamp >> 24;
buf[1] = timestamp >> 16;
buf[2] = timestamp >> 8;
buf[3] = timestamp;
rc = iso7816_put_data (slot, 0xCE + keynumber, buf, 4);
if (rc)
log_error (_("failed to store the creation date: %s\n"),
gpg_strerror (rc));
}
return rc;
}
@ -502,6 +536,7 @@ do_getattr (APP app, CTRL ctrl, const char *name)
{ "SIG-COUNTER", 0x0093, 2 },
{ "SERIALNO", 0x004F, -1 },
{ "AID", 0x004F },
{ "EXTCAP", 0x0000, -2 },
{ NULL, 0 }
};
int idx, i;
@ -536,6 +571,18 @@ do_getattr (APP app, CTRL ctrl, const char *name)
}
return 0;
}
if (table[idx].special == -2)
{
char tmp[50];
sprintf (tmp, "gc=%d ki=%d fc=%d pd=%d",
app->app_local->extcap.get_challenge,
app->app_local->extcap.key_import,
app->app_local->extcap.change_force_chv,
app->app_local->extcap.private_dos);
send_status_info (ctrl, table[idx].name, tmp, strlen (tmp), NULL, 0);
return 0;
}
relptr = get_one_do (app, table[idx].tag, &value, &valuelen);
if (relptr)
@ -575,6 +622,7 @@ do_getattr (APP app, CTRL ctrl, const char *name)
static int
do_learn_status (APP app, CTRL ctrl)
{
do_getattr (app, ctrl, "EXTCAP");
do_getattr (app, ctrl, "DISP-NAME");
do_getattr (app, ctrl, "DISP-LANG");
do_getattr (app, ctrl, "DISP-SEX");
@ -605,13 +653,14 @@ verify_chv2 (app_t app,
rc = pincb (pincb_arg, "PIN", &pinvalue);
if (rc)
{
log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
log_info (_("PIN callback returned error: %s\n"), gpg_strerror (rc));
return rc;
}
if (strlen (pinvalue) < 6)
{
log_error ("prassphrase (CHV2) is too short; minimum length is 6\n");
log_error (_("prassphrase (CHV%d) is too short;"
" minimum length is %d\n"), 2, 6);
xfree (pinvalue);
return gpg_error (GPG_ERR_BAD_PIN);
}
@ -619,7 +668,7 @@ verify_chv2 (app_t app,
rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue));
if (rc)
{
log_error ("verify CHV2 failed: %s\n", gpg_strerror (rc));
log_error (_("verify CHV%d failed: %s\n"), 2, gpg_strerror (rc));
xfree (pinvalue);
flush_cache_after_error (app);
return rc;
@ -633,7 +682,7 @@ verify_chv2 (app_t app,
rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED);
if (rc)
{
log_error ("verify CHV1 failed: %s\n", gpg_strerror (rc));
log_error (_("verify CHV%d failed: %s\n"), 1, gpg_strerror (rc));
xfree (pinvalue);
flush_cache_after_error (app);
return rc;
@ -653,26 +702,54 @@ verify_chv3 (APP app,
{
int rc = 0;
#if GNUPG_MAJOR_VERSION != 1
if (!opt.allow_admin)
{
log_info ("access to admin commands is not configured\n");
log_info (_("access to admin commands is not configured\n"));
return gpg_error (GPG_ERR_EACCES);
}
#endif
if (!app->did_chv3)
{
char *pinvalue;
void *relptr;
unsigned char *value;
size_t valuelen;
int reread_chv_status;
rc = pincb (pincb_arg, "Admin PIN", &pinvalue);
relptr = get_one_do (app, 0x00C4, &value, &valuelen);
if (!relptr || valuelen < 7)
{
log_error (_("error retrieving CHV status from card\n"));
xfree (relptr);
return gpg_error (GPG_ERR_CARD);
}
if (value[6] == 0)
{
log_info (_("card is permanently locked!\n"));
xfree (relptr);
return gpg_error (GPG_ERR_BAD_PIN);
}
reread_chv_status = (value[6] < 3);
log_info(_("%d Admin PIN attempts remaining before card"
" is permanently locked\n"), value[6]);
xfree (relptr);
rc = pincb (pincb_arg, _("Admin PIN"), &pinvalue);
if (rc)
{
log_info ("PIN callback returned error: %s\n", gpg_strerror (rc));
log_info (_("PIN callback returned error: %s\n"), gpg_strerror (rc));
return rc;
}
if (strlen (pinvalue) < 6)
{
log_error ("prassphrase (CHV3) is too short; minimum length is 6\n");
log_error (_("prassphrase (CHV%d) is too short;"
" minimum length is %d\n"), 3, 6);
xfree (pinvalue);
return gpg_error (GPG_ERR_BAD_PIN);
}
@ -681,11 +758,18 @@ verify_chv3 (APP app,
xfree (pinvalue);
if (rc)
{
log_error ("verify CHV3 failed: %s\n", gpg_strerror (rc));
log_error (_("verify CHV%d failed: %s\n"), 3, gpg_strerror (rc));
flush_cache_after_error (app);
return rc;
}
app->did_chv3 = 1;
/* If the PIN has been entered wrongly before, we need to flush
the cached value so that the next read correctly reflects the
resetted retry counter. Note that version 1.1 of the specs
allow direct reading of that DO, so that we could actually
flush it in all cases. */
if (reread_chv_status)
flush_cache_item (app, 0x00C4);
}
return rc;
}
@ -1149,7 +1233,8 @@ do_sign (APP app, const char *keyidstr, int hashalgo,
if (strlen (pinvalue) < 6)
{
log_error ("prassphrase (CHV1) is too short; minimum length is 6\n");
log_error (_("prassphrase (CHV%d) is too short;"
" minimum length is %d\n"), 1, 6);
xfree (pinvalue);
return gpg_error (GPG_ERR_BAD_PIN);
}
@ -1157,7 +1242,7 @@ do_sign (APP app, const char *keyidstr, int hashalgo,
rc = iso7816_verify (app->slot, 0x81, pinvalue, strlen (pinvalue));
if (rc)
{
log_error ("verify CHV1 failed\n");
log_error (_("verify CHV%d failed: %s\n"), 1, gpg_strerror (rc));
xfree (pinvalue);
flush_cache_after_error (app);
return rc;
@ -1171,7 +1256,7 @@ do_sign (APP app, const char *keyidstr, int hashalgo,
rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED);
if (rc)
{
log_error ("verify CHV2 failed\n");
log_error (_("verify CHV%d failed: %s\n"), 2, gpg_strerror (rc));
xfree (pinvalue);
flush_cache_after_error (app);
return rc;
@ -1375,11 +1460,14 @@ app_select_openpgp (APP app)
rc = iso7816_select_application (slot, aid, sizeof aid);
if (!rc)
{
unsigned int manufacturer;
app->apptype = "OPENPGP";
app->did_chv1 = 0;
app->did_chv2 = 0;
app->did_chv3 = 0;
app->app_local = NULL;
/* The OpenPGP card returns the serial number as part of the
AID; because we prefer to use OpenPGP serial numbers, we
@ -1391,33 +1479,57 @@ app_select_openpgp (APP app)
goto leave;
if (opt.verbose)
{
log_info ("got AID: ");
log_info ("AID: ");
log_printhex ("", buffer, buflen);
}
#if GNUPG_MAJOR_VERSION != 1
/* A valid OpenPGP card should never need this but well the test
is cheap. */
rc = app_munge_serialno (app);
if (rc)
goto leave;
#endif
app->card_version = buffer[6] << 8;
app->card_version |= buffer[7];
manufacturer = (buffer[8]<<8 | buffer[9]);
xfree (app->serialno);
app->serialno = buffer;
app->serialnolen = buflen;
buffer = NULL;
app->app_local = xtrycalloc (1, sizeof *app->app_local);
if (!app->app_local)
{
rc = gpg_error (gpg_err_code_from_errno (errno));
goto leave;
}
relptr = get_one_do (app, 0x00C4, &buffer, &buflen);
if (!relptr)
{
log_error ("can't access CHV Status Bytes - invalid OpenPGP card?\n");
log_error (_("can't access CHV Status Bytes "
"- invalid OpenPGP card?\n"));
goto leave;
}
app->force_chv1 = (buflen && *buffer == 0);
xfree (relptr);
relptr = get_one_do (app, 0x00C0, &buffer, &buflen);
if (!relptr)
{
log_error (_("can't access Extended Capability Flags - "
"invalid OpenPGP card?\n"));
goto leave;
}
if (buflen)
{
app->app_local->extcap.get_challenge = !!(*buffer & 0x40);
app->app_local->extcap.key_import = !!(*buffer & 0x20);
app->app_local->extcap.change_force_chv = !!(*buffer & 0x10);
app->app_local->extcap.private_dos = !!(*buffer & 0x08);
}
xfree (relptr);
/* Some of the first cards accidently don't set the
CHANGE_FORCE_CHV bit but allow it anyway. */
if (app->card_version <= 0x0100 && manufacturer == 1)
app->app_local->extcap.change_force_chv = 1;
if (opt.verbose > 1)
dump_all_do (slot);
@ -1435,6 +1547,8 @@ app_select_openpgp (APP app)
}
leave:
if (rc)
do_deinit (app);
return rc;
}
@ -1467,7 +1581,8 @@ app_openpgp_cardinfo (APP app,
rc = app_get_serial_and_stamp (app, serialno, &dummy);
if (rc)
{
log_error ("error getting serial number: %s\n", gpg_strerror (rc));
log_error (_("error getting serial number: %s\n"),
gpg_strerror (rc));
return rc;
}
}
@ -1554,13 +1669,14 @@ app_openpgp_storekey (APP app, int keyno,
if (rc)
goto leave;
flush_cache (app);
rc = iso7816_put_data (app->slot,
(app->card_version > 0x0007? 0xE0 : 0xE9) + keyno,
template, template_len);
if (rc)
{
log_error ("failed to store the key: rc=%s\n", gpg_strerror (rc));
log_error (_("failed to store the key: %s\n"), gpg_strerror (rc));
rc = gpg_error (GPG_ERR_CARD);
goto leave;
}
@ -1602,14 +1718,14 @@ app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen,
if (rc)
{
rc = gpg_error (GPG_ERR_CARD);
log_error ("reading key failed\n");
log_error (_("reading the key failed\n"));
goto leave;
}
keydata = find_tlv (buffer, buflen, 0x7F49, &keydatalen);
if (!keydata)
{
log_error ("response does not contain the public key data\n");
log_error (_("response does not contain the public key data\n"));
rc = gpg_error (GPG_ERR_CARD);
goto leave;
}
@ -1617,7 +1733,7 @@ app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen,
a = find_tlv (keydata, keydatalen, 0x0081, &alen);
if (!a)
{
log_error ("response does not contain the RSA modulus\n");
log_error (_("response does not contain the RSA modulus\n"));
rc = gpg_error (GPG_ERR_CARD);
goto leave;
}
@ -1628,7 +1744,7 @@ app_openpgp_readkey (APP app, int keyno, unsigned char **m, size_t *mlen,
a = find_tlv (keydata, keydatalen, 0x0082, &alen);
if (!a)
{
log_error ("response does not contain the RSA public exponent\n");
log_error (_("response does not contain the RSA public exponent\n"));
rc = gpg_error (GPG_ERR_CARD);
goto leave;
}