mirror of
git://git.gnupg.org/gnupg.git
synced 2025-01-17 14:07:03 +01:00
Improvements for 2k keys.
This commit is contained in:
parent
8368144fa7
commit
761e997af5
@ -1,3 +1,10 @@
|
|||||||
|
2008-09-23 Werner Koch <wk@g10code.com>
|
||||||
|
|
||||||
|
* app-openpgp.c (do_sign): Support SHA-2 digests.
|
||||||
|
(verify_chv2): No CHV auto-sync for v2 cards.
|
||||||
|
(do_auth): Allow 2048 bit keys.
|
||||||
|
(parse_algorithm_attribute): New.
|
||||||
|
|
||||||
2008-09-23 Marcus Brinkmann <marcus@g10code.com>
|
2008-09-23 Marcus Brinkmann <marcus@g10code.com>
|
||||||
|
|
||||||
* apdu.c (pcsc_get_status): Be more relaxed with the usable flag
|
* apdu.c (pcsc_get_status): Be more relaxed with the usable flag
|
||||||
|
@ -887,7 +887,7 @@ retrieve_key_material (FILE *fp, const char *hexkeyid,
|
|||||||
size_t e_new_n = 0;
|
size_t e_new_n = 0;
|
||||||
|
|
||||||
/* Loop over all records until we have found the subkey
|
/* Loop over all records until we have found the subkey
|
||||||
corresponsing to the fingerprint. Inm general the first record
|
corresponding to the fingerprint. Inm general the first record
|
||||||
should be the pub record, but we don't rely on that. Given that
|
should be the pub record, but we don't rely on that. Given that
|
||||||
we only need to look at one key, it is sufficient to compare the
|
we only need to look at one key, it is sufficient to compare the
|
||||||
keyid so that we don't need to look at "fpr" records. */
|
keyid so that we don't need to look at "fpr" records. */
|
||||||
@ -1249,6 +1249,8 @@ do_learn_status (app_t app, ctrl_t ctrl)
|
|||||||
send_keypair_info (app, ctrl, 1);
|
send_keypair_info (app, ctrl, 1);
|
||||||
send_keypair_info (app, ctrl, 2);
|
send_keypair_info (app, ctrl, 2);
|
||||||
send_keypair_info (app, ctrl, 3);
|
send_keypair_info (app, ctrl, 3);
|
||||||
|
/* Note: We do not send the Cardholder Certificate, because that is
|
||||||
|
relativly long and for OpenPGP applications not really needed. */
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1493,7 +1495,8 @@ verify_chv2 (app_t app,
|
|||||||
|
|
||||||
app->did_chv2 = 1;
|
app->did_chv2 = 1;
|
||||||
|
|
||||||
if (!app->did_chv1 && !app->force_chv1 && pinvalue)
|
if (!app->did_chv1 && !app->force_chv1 && pinvalue
|
||||||
|
&& !app->app_local->extcap.is_v2)
|
||||||
{
|
{
|
||||||
/* For convenience we verify CHV1 here too. We do this only if
|
/* For convenience we verify CHV1 here too. We do this only if
|
||||||
the card is not configured to require a verification before
|
the card is not configured to require a verification before
|
||||||
@ -2373,15 +2376,32 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
|
|||||||
const void *indata, size_t indatalen,
|
const void *indata, size_t indatalen,
|
||||||
unsigned char **outdata, size_t *outdatalen )
|
unsigned char **outdata, size_t *outdatalen )
|
||||||
{
|
{
|
||||||
static unsigned char sha1_prefix[15] = /* Object ID is 1.3.14.3.2.26 */
|
|
||||||
{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
|
|
||||||
0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
|
|
||||||
static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
|
static unsigned char rmd160_prefix[15] = /* Object ID is 1.3.36.3.2.1 */
|
||||||
{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
|
{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x24, 0x03,
|
||||||
0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
|
0x02, 0x01, 0x05, 0x00, 0x04, 0x14 };
|
||||||
|
static unsigned char sha1_prefix[15] = /* (1.3.14.3.2.26) */
|
||||||
|
{ 0x30, 0x21, 0x30, 0x09, 0x06, 0x05, 0x2b, 0x0e, 0x03,
|
||||||
|
0x02, 0x1a, 0x05, 0x00, 0x04, 0x14 };
|
||||||
|
static unsigned char sha224_prefix[19] = /* (2.16.840.1.101.3.4.2.4) */
|
||||||
|
{ 0x30, 0x2D, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48,
|
||||||
|
0x01, 0x65, 0x03, 0x04, 0x02, 0x04, 0x05, 0x00, 0x04,
|
||||||
|
0x1C };
|
||||||
|
static unsigned char sha256_prefix[19] = /* (2.16.840.1.101.3.4.2.1) */
|
||||||
|
{ 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
|
||||||
|
0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05,
|
||||||
|
0x00, 0x04, 0x20 };
|
||||||
|
static unsigned char sha384_prefix[19] = /* (2.16.840.1.101.3.4.2.2) */
|
||||||
|
{ 0x30, 0x41, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
|
||||||
|
0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x02, 0x05,
|
||||||
|
0x00, 0x04, 0x30 };
|
||||||
|
static unsigned char sha512_prefix[19] = /* (2.16.840.1.101.3.4.2.3) */
|
||||||
|
{ 0x30, 0x51, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86,
|
||||||
|
0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x03, 0x05,
|
||||||
|
0x00, 0x04, 0x40 };
|
||||||
int rc;
|
int rc;
|
||||||
unsigned char data[35];
|
unsigned char data[19+64];
|
||||||
unsigned char tmp_sn[20]; /* actually 16 but we use it also for the fpr. */
|
size_t datalen;
|
||||||
|
unsigned char tmp_sn[20]; /* Actually 16 bytes but also for the fpr. */
|
||||||
const char *s;
|
const char *s;
|
||||||
int n;
|
int n;
|
||||||
const char *fpr = NULL;
|
const char *fpr = NULL;
|
||||||
@ -2390,26 +2410,38 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
|
|||||||
|
|
||||||
if (!keyidstr || !*keyidstr)
|
if (!keyidstr || !*keyidstr)
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
|
/* Strip off known prefixes. */
|
||||||
|
#define X(a,b,c,d) \
|
||||||
|
if (hashalgo == GCRY_MD_ ## a \
|
||||||
|
&& (d) \
|
||||||
|
&& indatalen == sizeof b ## _prefix + (c) \
|
||||||
|
&& !memcmp (indata, b ## _prefix, sizeof b ## _prefix)) \
|
||||||
|
{ \
|
||||||
|
indata = (const char*)indata + sizeof b ## _prefix; \
|
||||||
|
indatalen -= sizeof b ## _prefix; \
|
||||||
|
}
|
||||||
|
|
||||||
if (indatalen == 20)
|
if (indatalen == 20)
|
||||||
;
|
; /* Assume a plain SHA-1 or RMD160 digest has been given. */
|
||||||
else if (indatalen == (15 + 20) && hashalgo == GCRY_MD_SHA1
|
else X(SHA1, sha1, 20, 1)
|
||||||
&& !memcmp (indata, sha1_prefix, 15))
|
else X(RMD160, rmd160, 20, 1)
|
||||||
{
|
else X(SHA224, sha224, 28, app->app_local->extcap.is_v2)
|
||||||
indata = (const char*)indata + 15;
|
else X(SHA256, sha256, 32, app->app_local->extcap.is_v2)
|
||||||
indatalen -= 15;
|
else X(SHA384, sha384, 48, app->app_local->extcap.is_v2)
|
||||||
}
|
else X(SHA512, sha512, 64, app->app_local->extcap.is_v2)
|
||||||
else if (indatalen == (15 + 20) && hashalgo == GCRY_MD_RMD160
|
else if ((indatalen == 28 || indatalen == 32
|
||||||
&& !memcmp (indata, rmd160_prefix, 15))
|
|| indatalen == 48 || indatalen ==64)
|
||||||
{
|
&& app->app_local->extcap.is_v2)
|
||||||
indata = (const char*)indata + 15;
|
; /* Assume a plain SHA-3 digest has been given. */
|
||||||
indatalen -= 15;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_error (_("card does not support digest algorithm %s\n"),
|
log_error (_("card does not support digest algorithm %s\n"),
|
||||||
gcry_md_algo_name (hashalgo));
|
gcry_md_algo_name (hashalgo));
|
||||||
|
/* Or the supplied digest length does not match an algorithm. */
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
}
|
}
|
||||||
|
#undef X
|
||||||
|
|
||||||
/* Check whether an OpenPGP card of any version has been requested. */
|
/* Check whether an OpenPGP card of any version has been requested. */
|
||||||
if (!strcmp (keyidstr, "OPENPGP.1"))
|
if (!strcmp (keyidstr, "OPENPGP.1"))
|
||||||
@ -2450,25 +2482,39 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
|
|||||||
if (rc)
|
if (rc)
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
if (hashalgo == GCRY_MD_SHA1)
|
/* Concatenate prefix and digest. */
|
||||||
memcpy (data, sha1_prefix, 15);
|
#define X(a,b,d) \
|
||||||
else if (hashalgo == GCRY_MD_RMD160)
|
if (hashalgo == GCRY_MD_ ## a && (d) ) \
|
||||||
memcpy (data, rmd160_prefix, 15);
|
{ \
|
||||||
|
datalen = sizeof b ## _prefix + indatalen; \
|
||||||
|
assert (datalen <= sizeof data); \
|
||||||
|
memcpy (data, b ## _prefix, sizeof b ## _prefix); \
|
||||||
|
memcpy (data + sizeof b ## _prefix, indata, indatalen); \
|
||||||
|
}
|
||||||
|
|
||||||
|
X(SHA1, sha1, 1)
|
||||||
|
else X(RMD160, rmd160, 1)
|
||||||
|
else X(SHA224, sha224, app->app_local->extcap.is_v2)
|
||||||
|
else X(SHA256, sha256, app->app_local->extcap.is_v2)
|
||||||
|
else X(SHA384, sha384, app->app_local->extcap.is_v2)
|
||||||
|
else X(SHA512, sha512, app->app_local->extcap.is_v2)
|
||||||
else
|
else
|
||||||
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
|
return gpg_error (GPG_ERR_UNSUPPORTED_ALGORITHM);
|
||||||
memcpy (data+15, indata, indatalen);
|
#undef X
|
||||||
|
|
||||||
|
/* Redirect to the AUTH command if asked to. */
|
||||||
if (use_auth)
|
if (use_auth)
|
||||||
{
|
{
|
||||||
/* This is a hack to redirect to the internal authenticate command. */
|
|
||||||
return do_auth (app, "OPENPGP.3", pincb, pincb_arg,
|
return do_auth (app, "OPENPGP.3", pincb, pincb_arg,
|
||||||
data, 35,
|
data, datalen,
|
||||||
outdata, outdatalen);
|
outdata, outdatalen);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Show the number of signature done using this key. */
|
||||||
sigcount = get_sig_counter (app);
|
sigcount = get_sig_counter (app);
|
||||||
log_info (_("signatures created so far: %lu\n"), sigcount);
|
log_info (_("signatures created so far: %lu\n"), sigcount);
|
||||||
|
|
||||||
|
/* Check CHV if needed. */
|
||||||
if (!app->did_chv1 || app->force_chv1 )
|
if (!app->did_chv1 || app->force_chv1 )
|
||||||
{
|
{
|
||||||
char *pinvalue;
|
char *pinvalue;
|
||||||
@ -2479,10 +2525,13 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
|
|||||||
|
|
||||||
app->did_chv1 = 1;
|
app->did_chv1 = 1;
|
||||||
|
|
||||||
if (!app->did_chv2 && pinvalue)
|
/* For cards with versions < 2 we want to keep CHV1 and CHV2 in
|
||||||
|
sync, thus we verify CHV2 here using the given PIN. Cards
|
||||||
|
with version2 to not have the need for a separate CHV2 and
|
||||||
|
internally use just one. Obviously we can't do that if the
|
||||||
|
keypad has been used. */
|
||||||
|
if (!app->did_chv2 && pinvalue && !app->app_local->extcap.is_v2)
|
||||||
{
|
{
|
||||||
/* We should also verify CHV2. Note, that we can't do that
|
|
||||||
if the keypad has been used. */
|
|
||||||
rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue));
|
rc = iso7816_verify (app->slot, 0x82, pinvalue, strlen (pinvalue));
|
||||||
if (gpg_err_code (rc) == GPG_ERR_BAD_PIN)
|
if (gpg_err_code (rc) == GPG_ERR_BAD_PIN)
|
||||||
rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED);
|
rc = gpg_error (GPG_ERR_PIN_NOT_SYNCED);
|
||||||
@ -2498,7 +2547,7 @@ do_sign (app_t app, const char *keyidstr, int hashalgo,
|
|||||||
xfree (pinvalue);
|
xfree (pinvalue);
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = iso7816_compute_ds (app->slot, data, 35, outdata, outdatalen);
|
rc = iso7816_compute_ds (app->slot, data, datalen, outdata, outdatalen);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2520,14 +2569,14 @@ do_auth (app_t app, const char *keyidstr,
|
|||||||
unsigned char **outdata, size_t *outdatalen )
|
unsigned char **outdata, size_t *outdatalen )
|
||||||
{
|
{
|
||||||
int rc;
|
int rc;
|
||||||
unsigned char tmp_sn[20]; /* actually 16 but we use it also for the fpr. */
|
unsigned char tmp_sn[20]; /* Actually 16 but we use it also for the fpr. */
|
||||||
const char *s;
|
const char *s;
|
||||||
int n;
|
int n;
|
||||||
const char *fpr = NULL;
|
const char *fpr = NULL;
|
||||||
|
|
||||||
if (!keyidstr || !*keyidstr)
|
if (!keyidstr || !*keyidstr)
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
if (indatalen > 50) /* For a 1024 bit key. */
|
if (indatalen > 101) /* For a 2048 bit key. */
|
||||||
return gpg_error (GPG_ERR_INV_VALUE);
|
return gpg_error (GPG_ERR_INV_VALUE);
|
||||||
|
|
||||||
/* Check whether an OpenPGP card of any version has been requested. */
|
/* Check whether an OpenPGP card of any version has been requested. */
|
||||||
@ -2842,6 +2891,51 @@ parse_historical (struct app_local_s *apploc,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Read and parse the algorithm attributes for KEYNO. KEYNO must be
|
||||||
|
in the range 0..2. */
|
||||||
|
static void
|
||||||
|
parse_algorithm_attribute (app_t app, int keyno)
|
||||||
|
{
|
||||||
|
unsigned char *buffer;
|
||||||
|
size_t buflen;
|
||||||
|
void *relptr;
|
||||||
|
const char const desc[3][5] = {"sign", "encr", "auth"};
|
||||||
|
|
||||||
|
assert (keyno >=0 && keyno <= 2);
|
||||||
|
|
||||||
|
relptr = get_one_do (app, 0xC1+keyno, &buffer, &buflen, NULL);
|
||||||
|
if (!relptr)
|
||||||
|
{
|
||||||
|
log_error ("error reading DO 0x%02X\n", 0xc1+keyno);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (buflen < 1)
|
||||||
|
{
|
||||||
|
log_error ("error reading DO 0x%02X\n", 0xc1+keyno);
|
||||||
|
xfree (relptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log_info ("Key-Attr-%s ..: ", desc[keyno]);
|
||||||
|
if (*buffer == 1 && (buflen == 5 || buflen == 6))
|
||||||
|
{
|
||||||
|
log_printf ("RSA, n=%d, e=%d",
|
||||||
|
(buffer[1]<<8 | buffer[2]),
|
||||||
|
(buffer[3]<<8 | buffer[4]));
|
||||||
|
if (buflen == 6)
|
||||||
|
log_printf (", format=%s",
|
||||||
|
buffer[5] == 0? "std" :
|
||||||
|
buffer[5] == 1? "std+n" :
|
||||||
|
buffer[5] == 2? "crt" :
|
||||||
|
buffer[5] == 2? "crt+n" : "?");
|
||||||
|
log_printf ("\n");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
log_printhex ("", buffer, buflen);
|
||||||
|
|
||||||
|
xfree (relptr);
|
||||||
|
}
|
||||||
|
|
||||||
/* Select the OpenPGP application on the card in SLOT. This function
|
/* Select the OpenPGP application on the card in SLOT. This function
|
||||||
must be used before any other OpenPGP application functions. */
|
must be used before any other OpenPGP application functions. */
|
||||||
gpg_error_t
|
gpg_error_t
|
||||||
@ -2914,7 +3008,6 @@ app_select_openpgp (app_t app)
|
|||||||
xfree (relptr);
|
xfree (relptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Read the force-chv1 flag. */
|
/* Read the force-chv1 flag. */
|
||||||
relptr = get_one_do (app, 0x00C4, &buffer, &buflen, NULL);
|
relptr = get_one_do (app, 0x00C4, &buffer, &buflen, NULL);
|
||||||
if (!relptr)
|
if (!relptr)
|
||||||
@ -2953,7 +3046,7 @@ app_select_openpgp (app_t app)
|
|||||||
app->app_local->extcap.max_rsp_data = (buffer[8] << 8 | buffer[9]);
|
app->app_local->extcap.max_rsp_data = (buffer[8] << 8 | buffer[9]);
|
||||||
}
|
}
|
||||||
xfree (relptr);
|
xfree (relptr);
|
||||||
|
|
||||||
/* Some of the first cards accidently don't set the
|
/* Some of the first cards accidently don't set the
|
||||||
CHANGE_FORCE_CHV bit but allow it anyway. */
|
CHANGE_FORCE_CHV bit but allow it anyway. */
|
||||||
if (app->card_version <= 0x0100 && manufacturer == 1)
|
if (app->card_version <= 0x0100 && manufacturer == 1)
|
||||||
@ -2964,6 +3057,13 @@ app_select_openpgp (app_t app)
|
|||||||
if (opt.verbose)
|
if (opt.verbose)
|
||||||
show_caps (app->app_local);
|
show_caps (app->app_local);
|
||||||
|
|
||||||
|
if (opt.verbose)
|
||||||
|
{
|
||||||
|
parse_algorithm_attribute (app, 0);
|
||||||
|
parse_algorithm_attribute (app, 1);
|
||||||
|
parse_algorithm_attribute (app, 2);
|
||||||
|
}
|
||||||
|
|
||||||
if (opt.verbose > 1)
|
if (opt.verbose > 1)
|
||||||
dump_all_do (slot);
|
dump_all_do (slot);
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user