summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorWerner Koch <wk@gnupg.org>2003-10-08 12:46:58 +0200
committerWerner Koch <wk@gnupg.org>2003-10-08 12:46:58 +0200
commit30342b06efcc779b9222513d8dbfb85436ab624c (patch)
tree2e0aef9b5c20a30dfa1ceb9ce60098a66f37e500
parentFixes to make inclusion of card raleted source files into 1.3 easier. (diff)
downloadgnupg2-30342b06efcc779b9222513d8dbfb85436ab624c.tar.xz
gnupg2-30342b06efcc779b9222513d8dbfb85436ab624c.zip
* call-agent.c (agent_scd_getattr): Don't clear the passed info
structure, so that it can indeed be updated. * card-util.c (fpr_is_zero): New. (generate_card_keys): New. (card_edit): New command "generate". * keygen.c (generate_keypair): New arg CARD_SERIALNO, removed call to check_smartcard. (check_smartcard,show_smartcard): Removed. (show_sha1_fpr,fpr_is_zero): Removed. * app-openpgp.c (do_getattr): Support SERIALNO and AID.
-rw-r--r--NEWS5
-rw-r--r--README4
-rw-r--r--TODO1
-rw-r--r--g10/ChangeLog13
-rw-r--r--g10/call-agent.c1
-rw-r--r--g10/card-util.c88
-rw-r--r--g10/g10.c4
-rw-r--r--g10/keygen.c192
-rw-r--r--g10/main.h2
-rw-r--r--scd/ChangeLog4
-rw-r--r--scd/app-openpgp.c25
11 files changed, 158 insertions, 181 deletions
diff --git a/NEWS b/NEWS
index 558a5e8ac..b708d44cf 100644
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,11 @@
Noteworthy changes in version 1.9.2 (unreleased)
------------------------------------------------
+ * On card key generation is no longer done using the --gen-key
+ command but from the menu provided by the new --card-edit command.
+
+ * PINs are now properly cached and there are only 2 PINs visible.
+ The 3rd PIN (CHV2) is internally syncronized with the regular PIN.
Noteworthy changes in version 1.9.1 (2003-09-06)
diff --git a/README b/README
index 8dea9dbb9..60b613362 100644
--- a/README
+++ b/README
@@ -47,6 +47,10 @@ gpg2:
Offers a menu to change the PIN of OpenPGP smartcards and to reset
the retry counters.
+--card-edit
+
+ Offers a menu to change any data object on the card and to generate
+ the keys.
OPTIONS
diff --git a/TODO b/TODO
index 11b887b9e..e8aa872a1 100644
--- a/TODO
+++ b/TODO
@@ -33,6 +33,7 @@ might want to have an agent context for each service request
* sm/gpgsm.c
** Support --output
** mark all unimplemented commands and options.
+** Print a hint when of MD2 is the cause for a problem.
* sm/keydb.c
** Check file permissions
diff --git a/g10/ChangeLog b/g10/ChangeLog
index 563c71eee..cb5a8ad64 100644
--- a/g10/ChangeLog
+++ b/g10/ChangeLog
@@ -1,3 +1,16 @@
+2003-10-08 Werner Koch <wk@gnupg.org>
+
+ * call-agent.c (agent_scd_getattr): Don't clear the passed info
+ structure, so that it can indeed be updated.
+
+ * card-util.c (fpr_is_zero): New.
+ (generate_card_keys): New.
+ (card_edit): New command "generate".
+ * keygen.c (generate_keypair): New arg CARD_SERIALNO, removed call
+ to check_smartcard.
+ (check_smartcard,show_smartcard): Removed.
+ (show_sha1_fpr,fpr_is_zero): Removed.
+
2003-10-01 Werner Koch <wk@gnupg.org>
* card-util.c: Tweaked to use this source also under 1.3.
diff --git a/g10/call-agent.c b/g10/call-agent.c
index f07c01f2a..c6c8faaec 100644
--- a/g10/call-agent.c
+++ b/g10/call-agent.c
@@ -600,7 +600,6 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info)
if (rc)
return rc;
- memset (info, 0, sizeof *info);
rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
learn_status_cb, info);
diff --git a/g10/card-util.c b/g10/card-util.c
index 70518e9ce..669927707 100644
--- a/g10/card-util.c
+++ b/g10/card-util.c
@@ -241,6 +241,17 @@ print_isoname (FILE *fp, const char *text, const char *tag, const char *name)
tty_fprintf (fp, "\n");
}
+/* Return true if the SHA1 fingerprint FPR consists only of zeroes. */
+static int
+fpr_is_zero (const char *fpr)
+{
+ int i;
+
+ for (i=0; i < 20 && !fpr[i]; i++)
+ ;
+ return (i == 20);
+}
+
/* Print all available information about the current card. */
void
@@ -569,6 +580,76 @@ toggle_forcesig (void)
}
+static void
+generate_card_keys (void)
+{
+ struct agent_card_info_s info;
+ int rc;
+ int forced_chv1;
+
+ memset (&info, 0, sizeof info);
+ rc = agent_scd_getattr ("KEY-FPR", &info);
+ if (!rc)
+ rc = agent_scd_getattr ("SERIALNO", &info);
+ if (!rc)
+ rc = agent_scd_getattr ("CHV-STATUS", &info);
+ if (!rc)
+ rc = agent_scd_getattr ("DISP-NAME", &info);
+ if (rc)
+ {
+ log_error ("error getting current key info: %s\n", gpg_strerror (rc));
+ return;
+ }
+ if ( (info.fpr1valid && !fpr_is_zero (info.fpr1))
+ || (info.fpr2valid && !fpr_is_zero (info.fpr2))
+ || (info.fpr3valid && !fpr_is_zero (info.fpr3)))
+ {
+ tty_printf ("\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? ")))
+ {
+ agent_release_card_info (&info);
+ return;
+ }
+ }
+ else if (!info.disp_name || !*info.disp_name)
+ {
+ tty_printf ("\n");
+ tty_printf (_("Please note that the factory settings of the PINs are\n"
+ " PIN = \"%s\" Admin PIN = \"%s\"\n"
+ "You should change them using the command --change-pin\n"),
+ "123456", "12345678");
+ tty_printf ("\n");
+ }
+
+ forced_chv1 = !info.chv1_cached;
+ if (forced_chv1)
+ { /* Switch of the forced mode so that during key generation we
+ don't get bothered with PIN queries for each
+ self-signature. */
+ rc = agent_scd_setattr ("CHV-STATUS-1", "\x01", 1);
+ if (rc)
+ {
+ log_error ("error clearing forced signature PIN flag: %s\n",
+ gpg_strerror (rc));
+ return;
+ }
+ }
+ generate_keypair (NULL, info.serialno);
+ agent_release_card_info (&info);
+ if (forced_chv1)
+ { /* Switch back to forced state. */
+ rc = agent_scd_setattr ("CHV-STATUS-1", "", 1);
+ if (rc)
+ {
+ log_error ("error setting forced signature PIN flag: %s\n",
+ gpg_strerror (rc));
+ return;
+ }
+ }
+}
/* Menu to edit all user changeable values on an OpenPGP card. Only
Key creation is not handled here. */
@@ -579,7 +660,7 @@ card_edit (STRLIST commands)
cmdNOP = 0,
cmdQUIT, cmdHELP, cmdLIST, cmdDEBUG,
cmdNAME, cmdURL, cmdLOGIN, cmdLANG, cmdSEX,
- cmdFORCESIG,
+ cmdFORCESIG, cmdGENERATE,
cmdINVCMD
};
@@ -601,6 +682,7 @@ card_edit (STRLIST commands)
{ N_("lang") , cmdLANG , N_("change the language preferences") },
{ N_("sex") , cmdSEX , N_("change card holder's sex") },
{ N_("forcesig"), cmdFORCESIG, N_("toggle the signature force PIN flag") },
+ { N_("generate"), cmdGENERATE, N_("generate new keys") },
{ NULL, cmdINVCMD }
};
@@ -725,6 +807,10 @@ card_edit (STRLIST commands)
toggle_forcesig ();
break;
+ case cmdGENERATE:
+ generate_card_keys ();
+ break;
+
case cmdQUIT:
goto leave;
diff --git a/g10/g10.c b/g10/g10.c
index cdd10d845..984e50d9c 100644
--- a/g10/g10.c
+++ b/g10/g10.c
@@ -2555,12 +2555,12 @@ main( int argc, char **argv )
if( opt.batch ) {
if( argc > 1 )
wrong_args("--gen-key [parameterfile]");
- generate_keypair( argc? *argv : NULL );
+ generate_keypair( argc? *argv : NULL, NULL );
}
else {
if( argc )
wrong_args("--gen-key");
- generate_keypair(NULL);
+ generate_keypair(NULL, NULL);
}
break;
diff --git a/g10/keygen.c b/g10/keygen.c
index 38e9115b3..935cff330 100644
--- a/g10/keygen.c
+++ b/g10/keygen.c
@@ -117,7 +117,6 @@ static int mdc_available,ks_modify;
static void do_generate_keypair( struct para_data_s *para,
struct output_control_s *outctrl, int card);
static int write_keyblock( iobuf_t out, KBNODE node );
-static int check_smartcard (char **);
static int gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root,
u32 expireval, struct para_data_s *para);
@@ -2219,11 +2218,12 @@ read_parameter_file( const char *fname )
/****************
- * Generate a keypair
- * (fname is only used in batch mode)
+ * Generate a keypair (fname is only used in batch mode) If
+ * CARD_SERIALNO is not NULL the fucntion will create the keys on an
+ * OpenPGP Card.
*/
void
-generate_keypair( const char *fname )
+generate_keypair( const char *fname, const char *card_serialno )
{
unsigned int nbits;
char *uid = NULL;
@@ -2232,42 +2232,34 @@ generate_keypair( const char *fname )
int algo;
unsigned int use;
int both = 0;
- int card = 0;
u32 expire;
struct para_data_s *para = NULL;
struct para_data_s *r;
struct output_control_s outctrl;
- char *serialno = NULL;
memset (&outctrl, 0, sizeof (outctrl));
- if (opt.batch)
+ if (opt.batch && card_serialno)
{
- read_parameter_file( fname );
+ /* We don't yet support unattended key generation. */
+ log_error (_("sorry, can't do this in batch mode\n"));
return;
}
- do
+ if (opt.batch)
{
- xfree (serialno); serialno = NULL;
- card = check_smartcard (&serialno);
- if (card < 0)
- return;
+ read_parameter_file( fname );
+ return;
}
- while (card > 1);
- if (serialno)
+ if (card_serialno)
{
- r = xcalloc (1, sizeof *r + strlen (serialno) );
+ r = xcalloc (1, sizeof *r + strlen (card_serialno) );
r->key = pSERIALNO;
- strcpy( r->u.value, serialno);
+ strcpy( r->u.value, card_serialno);
r->next = para;
para = r;
- xfree (serialno); serialno = NULL;
- }
- if (card)
- {
algo = PUBKEY_ALGO_RSA;
r = xcalloc (1, sizeof *r + 20 );
@@ -2388,7 +2380,7 @@ generate_keypair( const char *fname )
r->next = para;
para = r;
- dek = card? NULL : ask_passphrase( &s2k );
+ dek = card_serialno? NULL : ask_passphrase( &s2k );
if (dek)
{
r = xcalloc (1, sizeof *r );
@@ -2403,7 +2395,7 @@ generate_keypair( const char *fname )
para = r;
}
- proc_parameter_file (para, "[internal]", &outctrl, card);
+ proc_parameter_file (para, "[internal]", &outctrl, !!card_serialno);
release_parameter_list (para);
}
@@ -2719,7 +2711,7 @@ do_generate_keypair (struct para_data_s *para,
release_kbnode (pub_root);
release_kbnode (sec_root);
if (sk && !card) /* The unprotected secret key unless we have */
- free_secret_key (sk); /* shallow copy in card mode. */
+ free_secret_key (sk); /* a shallow copy in card mode. */
}
@@ -2848,158 +2840,6 @@ write_keyblock( iobuf_t out, KBNODE node )
}
-static void
-show_sha1_fpr (const unsigned char *fpr)
-{
- int i;
-
- if (fpr)
- {
- for (i=0; i < 20 ; i+=2, fpr += 2 )
- {
- if (i == 10 )
- tty_printf (" ");
- tty_printf (" %02X%02X", *fpr, fpr[1]);
- }
- }
- else
- tty_printf (" [none]");
- tty_printf ("\n");
-}
-
-static void
-show_smartcard (struct agent_card_info_s *info)
-{
- PKT_public_key *pk = xcalloc (1, sizeof *pk);
-
- /* FIXME: Sanitize what we show. */
- tty_printf ("Name of cardholder: %s\n",
- info->disp_name && *info->disp_name? info->disp_name
- : "[not set]");
- tty_printf ("URL of public key : %s\n",
- info->pubkey_url && *info->pubkey_url? info->pubkey_url
- : "[not set]");
- tty_printf ("Signature key ....:");
- show_sha1_fpr (info->fpr1valid? info->fpr1:NULL);
- tty_printf ("Encryption key....:");
- show_sha1_fpr (info->fpr2valid? info->fpr2:NULL);
- tty_printf ("Authentication key:");
- show_sha1_fpr (info->fpr3valid? info->fpr3:NULL);
-
- if (info->fpr1valid && !get_pubkey_byfprint (pk, info->fpr1, 20))
- print_pubkey_info (NULL, pk);
-
- free_public_key( pk );
-}
-
-/* Return true if the SHA1 fingerprint FPR consists only of zeroes. */
-static int
-fpr_is_zero (const char *fpr)
-{
- int i;
-
- for (i=0; i < 20 && !fpr[i]; i++)
- ;
- return (i == 20);
-}
-
-/* Check whether a smartcatrd is available and alow to select it as
- the target for key generation.
-
- Return values: -1 = Quit generation
- 0 = No smartcard
- 1 = Generate keypair
-*/
-static int
-check_smartcard (char **r_serialno)
-{
- struct agent_card_info_s info;
- int rc;
-
- rc = agent_learn (&info);
- if (rc)
- {
- tty_printf (_("OpenPGP card not available: %s\n"),
- gpg_strerror (rc));
- return 0;
- }
-
- tty_printf (_("OpenPGP card no. %s detected\n"),
- info.serialno? info.serialno : "[none]");
-
-
- for (;;)
- {
- char *answer;
- int reread = 0;
-
- tty_printf ("\n");
- show_smartcard (&info);
-
- tty_printf ("\n"
- "K - generate all keys\n"
- "Q - quit\n"
- "\n");
-
- answer = cpr_get("keygen.smartcard.menu",_("Your selection? "));
- cpr_kill_prompt();
- if (strlen (answer) != 1)
- continue;
-
- rc = 0;
- if ( *answer == 'K' || *answer == 'k')
- {
- if ( (info.fpr1valid && !fpr_is_zero (info.fpr1))
- || (info.fpr2valid && !fpr_is_zero (info.fpr2))
- || (info.fpr3valid && !fpr_is_zero (info.fpr3)))
- {
- tty_printf ("\n");
- log_error ("WARNING: key does already exists!\n");
- tty_printf ("\n");
- if ( cpr_get_answer_is_yes( "keygen.card.replace_key",
- _("Replace existing key? ")))
- {
- rc = 1;
- break;
- }
- }
- else
- {
- rc = 1;
- break;
- }
- }
- else if ( *answer == 'q' || *answer == 'Q')
- {
- rc = -1;
- break;
- }
-
- if (reread)
- {
- agent_release_card_info (&info);
- rc = agent_learn (&info);
- if (rc)
- {
- tty_printf (_("OpenPGP card not anymore available: %s\n"),
- gpg_strerror (rc));
- g10_exit (1);
- }
- reread = 0;
- }
- }
-
- if (r_serialno && rc > 0)
- {
- *r_serialno = info.serialno;
- info.serialno = NULL;
- }
- agent_release_card_info (&info);
-
- return rc;
-}
-
-
static int
gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root,
diff --git a/g10/main.h b/g10/main.h
index 76562fa91..d00044c9f 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -165,7 +165,7 @@ void show_basic_key_info (KBNODE keyblock);
/*-- keygen.c --*/
u32 ask_expire_interval(int object);
u32 ask_expiredate(void);
-void generate_keypair( const char *fname );
+void generate_keypair( const char *fname, const char *card_serialno );
int keygen_set_std_prefs (const char *string,int personal);
PKT_user_id *keygen_get_std_prefs (void);
int keygen_add_key_expire( PKT_signature *sig, void *opaque );
diff --git a/scd/ChangeLog b/scd/ChangeLog
index f090e34c0..86068b245 100644
--- a/scd/ChangeLog
+++ b/scd/ChangeLog
@@ -1,3 +1,7 @@
+2003-10-08 Werner Koch <wk@gnupg.org>
+
+ * app-openpgp.c (do_getattr): Support SERIALNO and AID.
+
2003-10-01 Werner Koch <wk@gnupg.org>
* ccid-driver.c: Detect GnuPG 1.3 and include appropriate files.
diff --git a/scd/app-openpgp.c b/scd/app-openpgp.c
index e8fe19ea1..174d2e974 100644
--- a/scd/app-openpgp.c
+++ b/scd/app-openpgp.c
@@ -425,6 +425,8 @@ do_getattr (APP app, CTRL ctrl, const char *name)
{ "CA-FPR", 0x00C6, 3 },
{ "CHV-STATUS", 0x00C4, 1 },
{ "SIG-COUNTER", 0x0093, 2 },
+ { "SERIALNO", 0x004F, -1 },
+ { "AID", 0x004F },
{ NULL, 0 }
};
int idx, i;
@@ -437,6 +439,29 @@ do_getattr (APP app, CTRL ctrl, const char *name)
if (!table[idx].name)
return gpg_error (GPG_ERR_INV_NAME);
+ if (table[idx].special == -1)
+ {
+ /* The serial number is very special. We could have used the
+ AID DO to retrieve it, but we have it already in the app
+ context and the stanmp argument is required anyway which we
+ can't by other means. The AID DO is available anyway but not
+ hex formatted. */
+ char *serial;
+ time_t stamp;
+ char tmp[50];
+
+ if (!app_get_serial_and_stamp (app, &serial, &stamp))
+ {
+ sprintf (tmp, "%lu", (unsigned long)stamp);
+ send_status_info (ctrl, "SERIALNO",
+ serial, strlen (serial),
+ tmp, strlen (tmp),
+ NULL, 0);
+ xfree (serial);
+ }
+ return 0;
+ }
+
relptr = get_one_do (app->slot, table[idx].tag, &value, &valuelen);
if (relptr)
{