* call-agent.c (agent_scd_getattr): Don't clear the passed info
authorWerner Koch <wk@gnupg.org>
Wed, 8 Oct 2003 10:46:58 +0000 (10:46 +0000)
committerWerner Koch <wk@gnupg.org>
Wed, 8 Oct 2003 10:46:58 +0000 (10:46 +0000)
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.

NEWS
README
TODO
g10/ChangeLog
g10/call-agent.c
g10/card-util.c
g10/g10.c
g10/keygen.c
g10/main.h
scd/ChangeLog
scd/app-openpgp.c

diff --git a/NEWS b/NEWS
index 558a5e8..b708d44 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,6 +1,11 @@
 Noteworthy changes in version 1.9.2 (unreleased)
 ------------------------------------------------
 
 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)
 
 
 Noteworthy changes in version 1.9.1 (2003-09-06)
diff --git a/README b/README
index 8dea9db..60b6133 100644 (file)
--- 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.
 
    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
 
 
 OPTIONS
diff --git a/TODO b/TODO
index 11b887b..e8aa872 100644 (file)
--- 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.
 * 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
 
 * sm/keydb.c
 ** Check file permissions
index 563c71e..cb5a8ad 100644 (file)
@@ -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. 
 2003-10-01  Werner Koch  <wk@gnupg.org>
 
        * card-util.c: Tweaked to use this source also under 1.3. 
index f07c01f..c6c8faa 100644 (file)
@@ -600,7 +600,6 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info)
   if (rc)
     return rc;
 
   if (rc)
     return rc;
 
-  memset (info, 0, sizeof *info);
   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
                         learn_status_cb, info);
   
   rc = assuan_transact (agent_ctx, line, NULL, NULL, NULL, NULL,
                         learn_status_cb, info);
   
index 70518e9..6699277 100644 (file)
@@ -241,6 +241,17 @@ print_isoname (FILE *fp, const char *text, const char *tag, const char *name)
     tty_fprintf (fp, "\n");
 }
 
     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
 
 /* 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. */
 
 /* 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,
     cmdNOP = 0,
     cmdQUIT, cmdHELP, cmdLIST, cmdDEBUG,
     cmdNAME, cmdURL, cmdLOGIN, cmdLANG, cmdSEX,
-    cmdFORCESIG,
+    cmdFORCESIG, cmdGENERATE,
     cmdINVCMD
   };
 
     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_("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 } 
   };
  
     { NULL, cmdINVCMD } 
   };
  
@@ -725,6 +807,10 @@ card_edit (STRLIST commands)
           toggle_forcesig ();
           break;
 
           toggle_forcesig ();
           break;
 
+        case cmdGENERATE:
+          generate_card_keys ();
+          break;
+
         case cmdQUIT:
           goto leave;
 
         case cmdQUIT:
           goto leave;
 
index cdd10d8..984e50d 100644 (file)
--- 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]");
        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");
        }
        else {
            if( argc )
                wrong_args("--gen-key");
-           generate_keypair(NULL);
+           generate_keypair(NULL, NULL);
        }
        break;
 
        }
        break;
 
index 38e9115..935cff3 100644 (file)
@@ -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 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);
 
 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
  */
 void
-generate_keypair( const char *fname )
+generate_keypair( const char *fname, const char *card_serialno )
 {
   unsigned int nbits;
   char *uid = NULL;
 {
   unsigned int nbits;
   char *uid = NULL;
@@ -2232,42 +2232,34 @@ generate_keypair( const char *fname )
   int algo;
   unsigned int use;
   int both = 0;
   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;
   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));
 
 
   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;
     }
 
       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;
       r->key = pSERIALNO;
-      strcpy( r->u.value, serialno);
+      strcpy( r->u.value, card_serialno);
       r->next = para;
       para = r;
       r->next = para;
       para = r;
-      xfree (serialno); serialno = NULL;
-    }
 
 
-  if (card)
-    {
       algo = PUBKEY_ALGO_RSA;
 
       r = xcalloc (1, sizeof *r + 20 );
       algo = PUBKEY_ALGO_RSA;
 
       r = xcalloc (1, sizeof *r + 20 );
@@ -2388,7 +2380,7 @@ generate_keypair( const char *fname )
   r->next = para;
   para = r;
 
   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 );
   if (dek)
     {
       r = xcalloc (1, sizeof *r );
@@ -2403,7 +2395,7 @@ generate_keypair( const char *fname )
       para = r;
     }
   
       para = r;
     }
   
-  proc_parameter_file (para, "[internal]", &outctrl, card);
+  proc_parameter_file (para, "[internal]", &outctrl, !!card_serialno);
   release_parameter_list (para);
 }
 
   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 */
   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);  /* shallow copy in card mode. */
 }
 
 
 }
 
 
@@ -2848,158 +2840,6 @@ write_keyblock( iobuf_t out, KBNODE node )
 }
 
 \f
 }
 
 \f
-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,
 
 static int
 gen_card_key (int algo, int keyno, KBNODE pub_root, KBNODE sec_root,
index 76562fa..d00044c 100644 (file)
@@ -165,7 +165,7 @@ void show_basic_key_info (KBNODE keyblock);
 /*-- keygen.c --*/
 u32 ask_expire_interval(int object);
 u32 ask_expiredate(void);
 /*-- 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 );
 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 );
index f090e34..86068b2 100644 (file)
@@ -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.
 2003-10-01  Werner Koch  <wk@gnupg.org>
 
        * ccid-driver.c: Detect GnuPG 1.3 and include appropriate files.
index e8fe19e..174d2e9 100644 (file)
@@ -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 },
     { "CA-FPR",       0x00C6, 3 },
     { "CHV-STATUS",   0x00C4, 1 },
     { "SIG-COUNTER",  0x0093, 2 },
+    { "SERIALNO",     0x004F, -1 },
+    { "AID",          0x004F },
     { NULL, 0 }
   };
   int idx, i;
     { 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].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)
     {
   relptr = get_one_do (app->slot, table[idx].tag, &value, &valuelen);
   if (relptr)
     {