Support writing of existing keys with non-matching key sizes.

This commit is contained in:
Werner Koch 2009-07-09 14:54:18 +00:00
parent 0c9dfcb09c
commit 31084d6dc9
6 changed files with 100 additions and 10 deletions

5
NEWS
View File

@ -13,6 +13,11 @@ Noteworthy changes in version 2.0.13
* New option --re-import for GPGSM's IMPORT server command. * New option --re-import for GPGSM's IMPORT server command.
* Enhanced writing of existing keys to OpenPGP v2 cards.
* Add hack to the internal CCID driver to allow the use of some
Omnikey based card readers with 2048 bit keys.
* Minor bug fixes. * Minor bug fixes.

View File

@ -503,8 +503,9 @@ more arguments in future versions.
"char" is the character displayed with no --status-fd enabled, with "char" is the character displayed with no --status-fd enabled, with
the linefeed replaced by an 'X'. "cur" is the current amount the linefeed replaced by an 'X'. "cur" is the current amount
done and "total" is amount to be done; a "total" of 0 indicates that done and "total" is amount to be done; a "total" of 0 indicates that
the total amount is not known. 100/100 may be used to detect the the total amount is not known. The condition
end of operation. TOATL && CUR == TOTAL
may be used to detect the end of an operation.
Well known values for WHAT: Well known values for WHAT:
"pk_dsa" - DSA key generation "pk_dsa" - DSA key generation
"pk_elg" - Elgamal key generation "pk_elg" - Elgamal key generation

View File

@ -1,5 +1,8 @@
2009-07-09 Werner Koch <wk@g10code.com> 2009-07-09 Werner Koch <wk@g10code.com>
* card-util.c (card_store_subkey): Do not restrict to 1024 bit keys.
Print an error message on write errors.
* gpg.c (main): Remove the SHA-1 default from the personal digest * gpg.c (main): Remove the SHA-1 default from the personal digest
list. This was used in the past as a hack to avoid preferring list. This was used in the past as a hack to avoid preferring
RMD-160. RMD-160.

View File

@ -1,5 +1,5 @@
/* card-util.c - Utility functions for the OpenPGP card. /* card-util.c - Utility functions for the OpenPGP card.
* Copyright (C) 2003, 2004, 2005 Free Software Foundation, Inc. * Copyright (C) 2003, 2004, 2005, 2009 Free Software Foundation, Inc.
* *
* This file is part of GnuPG. * This file is part of GnuPG.
* *
@ -1393,7 +1393,8 @@ card_store_subkey (KBNODE node, int use)
show_card_key_info (&info); show_card_key_info (&info);
if (!is_RSA (sk->pubkey_algo) || nbits_from_sk (sk) != 1024 ) if (!is_RSA (sk->pubkey_algo)
|| (!info.is_v2 && nbits_from_sk (sk) != 1024) )
{ {
tty_printf ("You may only store a 1024 bit RSA key on the card\n"); tty_printf ("You may only store a 1024 bit RSA key on the card\n");
tty_printf ("\n"); tty_printf ("\n");
@ -1461,7 +1462,10 @@ card_store_subkey (KBNODE node, int use)
rc = save_unprotected_key_to_card (sk, keyno); rc = save_unprotected_key_to_card (sk, keyno);
if (rc) if (rc)
goto leave; {
log_error (_("error writing key to card: %s\n"), gpg_strerror (rc));
goto leave;
}
/* Get back to the maybe protected original secret key. */ /* Get back to the maybe protected original secret key. */
if (copied_sk) if (copied_sk)

View File

@ -1,3 +1,11 @@
2009-07-09 Werner Koch <wk@g10code.com>
* app-openpgp.c (change_keyattr): New.
(do_writekey): Call it.
* app-openpgp.c (does_key_exist): Add arg GENERATING. Change
callers.
2009-06-30 Werner Koch <wk@g10code.com> 2009-06-30 Werner Koch <wk@g10code.com>
* ccid-driver.c (ccid_transceive): Set RESYNCING flag. * ccid-driver.c (ccid_transceive): Set RESYNCING flag.

View File

@ -213,6 +213,7 @@ static gpg_error_t do_auth (app_t app, const char *keyidstr,
void *pincb_arg, void *pincb_arg,
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 void parse_algorithm_attribute (app_t app, int keyno);
@ -2144,9 +2145,10 @@ do_change_pin (app_t app, ctrl_t ctrl, const char *chvnostr,
/* Check whether a key already exists. KEYIDX is the index of the key /* Check whether a key already exists. KEYIDX is the index of the key
(0..2). If FORCE is TRUE a diagnositic will be printed but no (0..2). If FORCE is TRUE a diagnositic will be printed but no
error returned if the key already exists. */ error returned if the key already exists. The flag GENERATING is
only used to print correct messages. */
static gpg_error_t static gpg_error_t
does_key_exist (app_t app, int keyidx, int force) does_key_exist (app_t app, int keyidx, int generating, int force)
{ {
const unsigned char *fpr; const unsigned char *fpr;
unsigned char *buffer; unsigned char *buffer;
@ -2178,8 +2180,10 @@ does_key_exist (app_t app, int keyidx, int force)
} }
else if (i!=20) else if (i!=20)
log_info (_("existing key will be replaced\n")); log_info (_("existing key will be replaced\n"));
else else if (generating)
log_info (_("generating new key\n")); log_info (_("generating new key\n"));
else
log_info (_("writing new key\n"));
return 0; return 0;
} }
@ -2340,6 +2344,63 @@ build_privkey_template (app_t app, int keyno,
} }
/* Helper for do_writekley to change the size of a key. Not ethat
this deletes the entire key without asking. */
static gpg_error_t
change_keyattr (app_t app, int keyno, unsigned int nbits,
gpg_error_t (*pincb)(void*, const char *, char **),
void *pincb_arg)
{
gpg_error_t err;
unsigned char *buffer;
size_t buflen;
void *relptr;
assert (keyno >=0 && keyno <= 2);
if (nbits > 3072)
return gpg_error (GPG_ERR_TOO_LARGE);
/* Read the current attributes into a buffer. */
relptr = get_one_do (app, 0xC1+keyno, &buffer, &buflen, NULL);
if (!relptr)
return gpg_error (GPG_ERR_CARD);
if (buflen < 6 || buffer[0] != 1)
{
/* Attriutes too short or not an RSA key. */
xfree (relptr);
return gpg_error (GPG_ERR_CARD);
}
/* We only change n_bits and don't touch anything else. Before we
do so, we round up NBITS to a sensible way in the same way as
gpg's key generation does it. This may help to sort out problems
with a few bits too short keys. */
nbits = ((nbits + 31) / 32) * 32;
buffer[1] = (nbits >> 8);
buffer[2] = nbits;
/* Prepare for storing the key. */
err = verify_chv3 (app, pincb, pincb_arg);
if (err)
{
xfree (relptr);
return err;
}
/* Change the attribute. */
err = iso7816_put_data (app->slot, 0, 0xC1+keyno, buffer, buflen);
xfree (relptr);
if (err)
log_error ("error changing size of key %d to %u bits\n", keyno+1, nbits);
else
log_info ("size of key %d changed to %u bits\n", keyno+1, nbits);
flush_cache (app);
parse_algorithm_attribute (app, keyno);
return err;
}
/* Handle the WRITEKEY command for OpenPGP. This function expects a /* Handle the WRITEKEY command for OpenPGP. This function expects a
canonical encoded S-expression with the secret key in KEYDATA and canonical encoded S-expression with the secret key in KEYDATA and
@ -2385,7 +2446,7 @@ do_writekey (app_t app, ctrl_t ctrl,
else else
return gpg_error (GPG_ERR_INV_ID); return gpg_error (GPG_ERR_INV_ID);
err = does_key_exist (app, keyno, force); err = does_key_exist (app, keyno, 0, force);
if (err) if (err)
return err; return err;
@ -2515,6 +2576,14 @@ do_writekey (app_t app, ctrl_t ctrl,
if (opt.verbose) if (opt.verbose)
log_info ("RSA modulus size is %u bits (%u bytes)\n", log_info ("RSA modulus size is %u bits (%u bytes)\n",
nbits, (unsigned int)rsa_n_len); nbits, (unsigned int)rsa_n_len);
if (nbits && nbits != maxbits
&& app->app_local->extcap.algo_attr_change)
{
/* Try to switch the key to a new length. */
err = change_keyattr (app, keyno, nbits, pincb, pincb_arg);
if (!err)
maxbits = app->app_local->keyattr[keyno].n_bits;
}
if (nbits != maxbits) if (nbits != maxbits)
{ {
log_error (_("RSA modulus missing or not of size %d bits\n"), log_error (_("RSA modulus missing or not of size %d bits\n"),
@ -2696,7 +2765,7 @@ do_genkey (app_t app, ctrl_t ctrl, const char *keynostr, unsigned int flags,
app->app_local->pk[keyno].read_done = 0; app->app_local->pk[keyno].read_done = 0;
/* Check whether a key already exists. */ /* Check whether a key already exists. */
rc = does_key_exist (app, keyno, force); rc = does_key_exist (app, keyno, 1, force);
if (rc) if (rc)
return rc; return rc;