summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2009-08-05 13:24:43 +0200
committerWerner Koch <wk@gnupg.org>2009-08-05 13:24:43 +0200
commite57d2a86300b86799aa86f8172dfc0bae5db9bb4 (patch)
treed672f0589d85ebe4595ea6741b0d162d45af9d4e
parent* gpg.c (main): --pgp6 includes --disable-mdc. (diff)
downloadgnupg2-e57d2a86300b86799aa86f8172dfc0bae5db9bb4.tar.xz
gnupg2-e57d2a86300b86799aa86f8172dfc0bae5db9bb4.zip
Ask for the keysize when generating a new card key.
-rw-r--r--common/yesno.c6
-rw-r--r--g10/ChangeLog13
-rw-r--r--g10/call-agent.c6
-rw-r--r--g10/card-util.c163
-rw-r--r--g10/gpg.c1
-rw-r--r--scd/ChangeLog5
-rw-r--r--scd/app-openpgp.c48
7 files changed, 222 insertions, 20 deletions
diff --git a/common/yesno.c b/common/yesno.c
index fdbf7ddd1..a7131b7d5 100644
--- a/common/yesno.c
+++ b/common/yesno.c
@@ -24,8 +24,12 @@
#include "i18n.h"
#include "util.h"
+
+/* Check the string S for a YES or NO answer and take care of
+ localization. If no valid string is given the value of DEF_ANSWER
+ is returned. Returns 1 for yes and 0 for no. */
int
-answer_is_yes_no_default( const char *s, int def_answer )
+answer_is_yes_no_default (const char *s, int def_answer)
{
/* TRANSLATORS: See doc/TRANSLATE about this string. */
const char *long_yes = _("yes");
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 6e672871d..781ec57ab 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,16 @@
+2009-08-05 Werner Koch <wk@g10code.com>
+
+ * gpg.c: Add --key-edit alias.
+
+ * call-agent.c (scd_genkey_cb): Forward progress status lines.
+
+ * card-util.c (generate_card_keys): Remove special case for
+ GnuPG-2. Ask for the keysize and change it.
+ (card_generate_subkey): Ask for the keysize and change it.
+ (get_info_for_key_operation): Read KEY-ATTR.
+ (show_keysize_warning, ask_card_keysize): New.
+ (do_change_keysize): New.
+
2009-07-31 David Shaw <dshaw@jabberwocky.com>
* gpg.c (main): --pgp6 includes --disable-mdc.
diff --git a/g10/call-agent.c b/g10/call-agent.c
index 1b7578175..8a0b21a7a 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -667,7 +667,7 @@ scd_genkey_cb (void *opaque, const char *line)
{
parm->fprvalid = unhexify_fpr (line, parm->fpr);
}
- if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
+ else if (keywordlen == 8 && !memcmp (keyword, "KEY-DATA", keywordlen))
{
gcry_mpi_t a;
const char *name = line;
@@ -694,6 +694,10 @@ scd_genkey_cb (void *opaque, const char *line)
{
parm->created_at = (u32)strtoul (line, NULL, 10);
}
+ else if (keywordlen == 8 && !memcmp (keyword, "PROGRESS", keywordlen))
+ {
+ write_status_text (STATUS_PROGRESS, line);
+ }
return 0;
}
diff --git a/g10/card-util.c b/g10/card-util.c
index d03de0b46..5ba42b871 100644
--- a/g10/card-util.c
+++ b/g10/card-util.c
@@ -1158,6 +1158,8 @@ get_info_for_key_operation (struct agent_card_info_s *info)
rc = agent_scd_getattr ("DISP-NAME", info);
if (!rc)
rc = agent_scd_getattr ("EXTCAP", info);
+ if (!rc)
+ rc = agent_scd_getattr ("KEY-ATTR", info);
if (rc)
log_error (_("error getting current key info: %s\n"), gpg_strerror (rc));
return rc;
@@ -1254,33 +1256,113 @@ replace_existing_key_p (struct agent_card_info_s *info, int keyno)
static void
+show_keysize_warning (void)
+{
+ static int shown;
+
+ if (shown)
+ return;
+ shown = 1;
+ tty_printf
+ (_("NOTE: There is no guarantee that the card "
+ "supports the requested size.\n"
+ " If the key generation does not succeed, "
+ "please check the\n"
+ " documentation of your card to see what "
+ "sizes are allowed.\n"));
+}
+
+
+/* Ask for the size of a card key. NBITS is the current size
+ configured for the card. KEYNO is the number of the key used to
+ select the prompt. Returns 0 to use the default size (i.e. NBITS)
+ or the selected size. */
+static unsigned int
+ask_card_keysize (int keyno, unsigned int nbits)
+{
+ unsigned int min_nbits = 1024;
+ unsigned int max_nbits = 3072; /* GnuPG limit due to Assuan. */
+ char *prompt, *answer;
+ unsigned int req_nbits;
+
+ for (;;)
+ {
+ prompt = xasprintf
+ (keyno == 0?
+ _("What keysize do you want for the Signature key? (%u) "):
+ keyno == 1?
+ _("What keysize do you want for the Encryption key? (%u) "):
+ _("What keysize do you want for the Authentication key? (%u) "),
+ nbits);
+ answer = cpr_get ("cardedit.genkeys.size", prompt);
+ cpr_kill_prompt ();
+ req_nbits = *answer? atoi (answer): nbits;
+ xfree (prompt);
+ xfree (answer);
+
+ if (req_nbits != nbits && (req_nbits % 32) )
+ {
+ req_nbits = ((req_nbits + 31) / 32) * 32;
+ tty_printf (_("rounded up to %u bits\n"), req_nbits);
+ }
+
+ if (req_nbits == nbits)
+ return 0; /* Use default. */
+
+ if (req_nbits < min_nbits || req_nbits > max_nbits)
+ {
+ tty_printf (_("%s keysizes must be in the range %u-%u\n"),
+ "RSA", min_nbits, max_nbits);
+ }
+ else
+ {
+ tty_printf (_("The card will now be re-configured "
+ "to generate a key of %u bits\n"), req_nbits);
+ show_keysize_warning ();
+ return req_nbits;
+ }
+ }
+}
+
+
+/* Change the size of key KEYNO (0..2) to NBITS and show an error
+ message if that fails. */
+static gpg_error_t
+do_change_keysize (int keyno, unsigned int nbits)
+{
+ gpg_error_t err;
+ char args[100];
+
+ snprintf (args, sizeof args, "--force %d 1 %u", keyno+1, nbits);
+ err = agent_scd_setattr ("KEY-ATTR", args, strlen (args), NULL);
+ if (err)
+ log_error (_("error changing size of key %d to %u bits: %s\n"),
+ keyno+1, nbits, gpg_strerror (err));
+ return err;
+}
+
+
+static void
generate_card_keys (void)
{
struct agent_card_info_s info;
int forced_chv1;
int want_backup;
+ int keyno;
if (get_info_for_key_operation (&info))
return;
if (info.extcap.ki)
{
-#if GNUPG_MAJOR_VERSION == 1
char *answer;
-
answer = cpr_get ("cardedit.genkeys.backup_enc",
_("Make off-card backup of encryption key? (Y/n) "));
- want_backup=answer_is_yes_no_default(answer,1);
- cpr_kill_prompt();
- xfree(answer);
-#else
- want_backup = cpr_get_answer_is_yes
- ( "cardedit.genkeys.backup_enc",
- _("Make off-card backup of encryption key? (Y/n) "));
- /*FIXME: we need answer_is_yes_no_default()*/
-#endif
+ want_backup = answer_is_yes_no_default (answer, 1/*(default to Yes)*/);
+ cpr_kill_prompt ();
+ xfree (answer);
}
else
want_backup = 0;
@@ -1290,16 +1372,19 @@ generate_card_keys (void)
|| (info.fpr3valid && !fpr_is_zero (info.fpr3)))
{
tty_printf ("\n");
- log_info ("NOTE: keys are already stored on the card!\n");
+ log_info (_("NOTE: keys are already stored on the card!\n"));
tty_printf ("\n");
- if ( !cpr_get_answer_is_yes( "cardedit.genkeys.replace_keys",
- _("Replace existing keys? (y/N) ")))
+ if ( !cpr_get_answer_is_yes ("cardedit.genkeys.replace_keys",
+ _("Replace existing keys? (y/N) ")))
{
agent_release_card_info (&info);
return;
}
}
- else if (!info.disp_name || !*info.disp_name)
+
+ /* If no displayed name has been set, we assume that this is a fresh
+ card and print a hint about the default PINs. */
+ if (!info.disp_name || !*info.disp_name)
{
tty_printf ("\n");
tty_printf (_("Please note that the factory settings of the PINs are\n"
@@ -1311,9 +1396,31 @@ generate_card_keys (void)
if (check_pin_for_key_operation (&info, &forced_chv1))
goto leave;
-
- generate_keypair (NULL, info.serialno,
- want_backup? opt.homedir:NULL);
+
+ /* If the cards features changeable key attributes, we ask for the
+ key size. */
+ if (info.is_v2 && info.extcap.aac)
+ {
+ unsigned int nbits;
+
+ for (keyno = 0; keyno < DIM (info.key_attr); keyno++)
+ {
+ nbits = ask_card_keysize (keyno, info.key_attr[keyno].nbits);
+ if (nbits && do_change_keysize (keyno, nbits))
+ {
+ /* Error: Better read the default key size again. */
+ agent_release_card_info (&info);
+ if (get_info_for_key_operation (&info))
+ goto leave;
+ /* Ask again for this key size. */
+ keyno--;
+ }
+ }
+ /* Note that INFO has not be synced. However we will only use
+ the serialnumber and thus it won't harm. */
+ }
+
+ generate_keypair (NULL, info.serialno, want_backup? opt.homedir:NULL);
leave:
agent_release_card_info (&info);
@@ -1365,6 +1472,26 @@ card_generate_subkey (KBNODE pub_keyblock, KBNODE sec_keyblock)
if (check_pin_for_key_operation (&info, &forced_chv1))
goto leave;
+ /* If the cards features changeable key attributes, we ask for the
+ key size. */
+ if (info.is_v2 && info.extcap.aac)
+ {
+ unsigned int nbits;
+
+ ask_again:
+ nbits = ask_card_keysize (keyno-1, info.key_attr[keyno-1].nbits);
+ if (nbits && do_change_keysize (keyno-1, nbits))
+ {
+ /* Error: Better read the default key size again. */
+ agent_release_card_info (&info);
+ if (get_info_for_key_operation (&info))
+ goto leave;
+ goto ask_again;
+ }
+ /* Note that INFO has not be synced. However we will only use
+ the serialnumber and thus it won't harm. */
+ }
+
okay = generate_card_subkeypair (pub_keyblock, sec_keyblock,
keyno, info.serialno);
diff --git a/g10/gpg.c b/g10/gpg.c
index 08c91106c..640490bda 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -394,6 +394,7 @@ static ARGPARSE_OPTS opts[] = {
ARGPARSE_c (aSignKey, "sign-key" ,N_("sign a key")),
ARGPARSE_c (aLSignKey, "lsign-key" ,N_("sign a key locally")),
ARGPARSE_c (aEditKey, "edit-key" ,N_("sign or edit a key")),
+ ARGPARSE_c (aEditKey, "key-edit" ,"@"),
ARGPARSE_c (aGenRevoke, "gen-revoke",N_("generate a revocation certificate")),
ARGPARSE_c (aDesigRevoke, "desig-revoke","@" ),
ARGPARSE_c (aExport, "export" , N_("export keys") ),
diff --git a/scd/ChangeLog b/scd/ChangeLog
index 62af9cf3d..e7bf65339 100644
--- a/scd/ChangeLog
+++ b/scd/ChangeLog
@@ -1,3 +1,8 @@
+2009-08-05 Werner Koch <wk@g10code.com>
+
+ * app-openpgp.c (change_keyattr_from_string): New.
+ (do_setattr): Support KEY-ATTR.
+
2009-07-29 Marcus Brinkmann <marcus@g10code.com>
* ccid-driver.c (print_pr_data): Fix 64 bit compat problem.
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index d2b2bdd3f..2c10cd9bf 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -214,6 +214,11 @@ static gpg_error_t do_auth (app_t app, const char *keyidstr,
const void *indata, size_t indatalen,
unsigned char **outdata, size_t *outdatalen);
static void parse_algorithm_attribute (app_t app, int keyno);
+static gpg_error_t change_keyattr_from_string
+ (app_t app,
+ gpg_error_t (*pincb)(void*, const char *, char **),
+ void *pincb_arg,
+ const void *value, size_t valuelen);
@@ -1793,6 +1798,7 @@ do_setattr (app_t app, const char *name,
{ "CERT-3", 0x7F21, 3, 0, 1 },
{ "SM-KEY-ENC", 0x00D1, 3, 0, 1 },
{ "SM-KEY-MAC", 0x00D2, 3, 0, 1 },
+ { "KEY-ATTR", 0, 0, 3, 1 },
{ NULL, 0 }
};
int exmode;
@@ -1804,6 +1810,9 @@ do_setattr (app_t app, const char *name,
if (table[idx].need_v2 && !app->app_local->extcap.is_v2)
return gpg_error (GPG_ERR_NOT_SUPPORTED); /* Not yet supported. */
+ if (table[idx].special == 3)
+ return change_keyattr_from_string (app, pincb, pincb_arg, value, valuelen);
+
switch (table[idx].need_chv)
{
case 2:
@@ -2404,6 +2413,45 @@ change_keyattr (app_t app, int keyno, unsigned int nbits,
}
+/* Helper to process an setattr command for name KEY-ATTR. It expects
+ a string "--force <keyno> <algo> <nbits>" in (VALUE,VALUELEN). */
+static gpg_error_t
+change_keyattr_from_string (app_t app,
+ gpg_error_t (*pincb)(void*, const char *, char **),
+ void *pincb_arg,
+ const void *value, size_t valuelen)
+{
+ gpg_error_t err;
+ char *string;
+ int keyno, algo;
+ unsigned int nbits;
+
+ /* VALUE is expected to be a string but not guaranteed to be
+ terminated. Thus copy it to an allocated buffer first. */
+ string = xtrymalloc (valuelen+1);
+ if (!string)
+ return gpg_error_from_syserror ();
+ memcpy (string, value, valuelen);
+ string[valuelen] = 0;
+
+ /* Because this function deletes the key we require the string
+ "--force" in the data to make clear that something serious might
+ happen. */
+ if (sscanf (string, " --force %d %d %u", &keyno, &algo, &nbits) != 3)
+ err = gpg_error (GPG_ERR_INV_DATA);
+ else if (keyno < 1 || keyno > 3)
+ err = gpg_error (GPG_ERR_INV_ID);
+ else if (algo != 1)
+ err = gpg_error (GPG_ERR_PUBKEY_ALGO); /* Not RSA. */
+ else if (nbits < 1024)
+ err = gpg_error (GPG_ERR_TOO_SHORT);
+ else
+ err = change_keyattr (app, keyno-1, nbits, pincb, pincb_arg);
+
+ xfree (string);
+ return err;
+}
+
/* Handle the WRITEKEY command for OpenPGP. This function expects a
canonical encoded S-expression with the secret key in KEYDATA and