* passphrase.c (agent_get_passphrase): Add new arg CACHEID.
authorWerner Koch <wk@gnupg.org>
Tue, 3 May 2005 22:27:07 +0000 (22:27 +0000)
committerWerner Koch <wk@gnupg.org>
Tue, 3 May 2005 22:27:07 +0000 (22:27 +0000)
Changed all callers.
(ask_passphrase): Add new arg CACHEID and use it in agent mode.
Changed all callers.
(passphrase_clear_cache): New arg CACHEID.  Changed all callers.
* cardglue.c (format_cacheid): New.
(pin_cb): Compute a cache ID.
(agent_scd_pksign, agent_scd_pkdecrypt): Use it.
(agent_clear_pin_cache): New.
* card-util.c (change_pin): Clear the PIN cache.
(check_pin_for_key_operation): Ditto.

g10/ChangeLog
g10/card-util.c
g10/cardglue.c
g10/cardglue.h
g10/keydb.h
g10/passphrase.c
g10/seckey-cert.c
g10/sign.c

index 30f8939..b7ce53c 100644 (file)
@@ -1,3 +1,17 @@
+2005-05-03  Werner Koch  <wk@g10code.com>
+
+       * passphrase.c (agent_get_passphrase): Add new arg CACHEID.
+       Changed all callers.
+       (ask_passphrase): Add new arg CACHEID and use it in agent mode.
+       Changed all callers.
+       (passphrase_clear_cache): New arg CACHEID.  Changed all callers.
+       * cardglue.c (format_cacheid): New.
+       (pin_cb): Compute a cache ID.
+       (agent_scd_pksign, agent_scd_pkdecrypt): Use it.
+       (agent_clear_pin_cache): New.
+       * card-util.c (change_pin): Clear the PIN cache.
+       (check_pin_for_key_operation): Ditto.
+
 2005-04-24  David Shaw  <dshaw@jabberwocky.com>
 
        * trustdb.h, trustdb.c (mark_usable_uid_certs): Add flags for the
        here.  We'll fail quite happily later, and usually with a better
        error message to boot.
 
+2005-04-20  Werner Koch  <wk@g10code.com>
+
+       * sign.c (sign_file, sign_symencrypt_file): Allow for hash
+       debugging.
+
 2005-04-16  David Shaw  <dshaw@jabberwocky.com>
 
        * keyserver.c (keyserver_spawn): Free some memory.
index ecb80f0..8874935 100644 (file)
@@ -67,6 +67,8 @@ change_pin (int chvno, int allow_admin)
   log_info (_("OpenPGP card no. %s detected\n"),
               info.serialno? info.serialno : "[none]");
 
+  agent_clear_pin_cache (info.serialno);
+
   agent_release_card_info (&info);
 
   if (opt.batch)
@@ -950,6 +952,8 @@ check_pin_for_key_operation (struct agent_card_info_s *info, int *forced_chv1)
 {     
   int rc = 0;
 
+  agent_clear_pin_cache (info->serialno);
+
   *forced_chv1 = !info->chv1_cached;
   if (*forced_chv1)
     { /* Switch of the forced mode so that during key generation we
index 530e8a4..9e7aef8 100644 (file)
 #include "apdu.h"
 #include "app-common.h"
 
-struct ctrl_ctx_s {
+struct ctrl_ctx_s 
+{
   int (*status_cb)(void *opaque, const char *line);
   void *status_cb_arg;
 };
 
 
+struct pincb_parm_s
+{
+  const char *sn;
+};
+
+
 static char *default_reader_port;
 static APP current_app;
 
@@ -334,6 +341,39 @@ card_close (void)
 }
 
 
+/* Format a cache ID from the serialnumber in SN and return it as an
+   allocated string.  In case of an error NULL is returned. */
+static char *
+format_cacheid (const char *sn)
+{
+  const char *s;
+  size_t snlen;
+  char *cacheid = NULL;
+
+  /* The serialnumber we use for a card is "CARDSN:serialno".  Where
+     serialno is the BCD string (i.e. hex string) with the full
+     number.  The serial number expect here constsis of hexdigits
+     followed by other characters, we cut off these other
+     characters. */
+  if (sn)
+    {
+      for (s=sn,snlen=0; hexdigitp (s); s++, snlen++)
+        ;
+      if (snlen == 32)
+        {
+          /* Yes, this looks indeed like an OpenPGP card S/N. */
+          cacheid = xtrymalloc (7+snlen+1);
+          if (cacheid)
+            {
+              memcpy (cacheid, "CARDSN:", 7);
+              memcpy (cacheid+7, sn, snlen);
+              cacheid[7+snlen] = 0;
+            }
+        }
+    }
+  return cacheid;
+}
+
 /* Check that the serial number of the current card (as described by
    APP) matches SERIALNO.  If there is no match and we are not in
    batch mode, present a prompt to insert the desired card.  The
@@ -651,12 +691,14 @@ agent_scd_getattr (const char *name, struct agent_card_info_s *info)
 static int 
 pin_cb (void *opaque, const char *info, char **retstr)
 {
+  struct pincb_parm_s *parm = opaque;
   char *value;
   int canceled;
   int isadmin = 0;
   int newpin = 0;
   const char *again_text = NULL;
   const char *ends, *s;
+  char *cacheid = NULL;
 
   *retstr = NULL;
   /*   log_debug ("asking for PIN '%s'\n", info); */
@@ -674,9 +716,23 @@ pin_cb (void *opaque, const char *info, char **retstr)
         }
       info = ends+1;
     }
-  else
+  else if (info && *info == '|')
     log_debug ("pin_cb called without proper PIN info hack\n");
 
+  /* If we are not requesting a new PIN and we are not requesting an
+     AdminPIN, compute a string to be used as the cacheID for
+     gpg-agent. */
+  if (!newpin && !isadmin && parm)
+    {
+      cacheid = format_cacheid (parm->sn);
+    }
+  else if (newpin && parm)
+    {
+      /* Make really sure that it is not cached anymore. */
+      agent_clear_pin_cache (parm->sn);
+    }
+
+
  again:
   if (is_status_enabled())
     write_status_text (STATUS_NEED_PASSPHRASE_PIN,
@@ -691,7 +747,10 @@ pin_cb (void *opaque, const char *info, char **retstr)
                           newpin?  _("Enter New PIN: ") :
                           isadmin? _("Enter Admin PIN: ")
                                  : _("Enter PIN: "),
+                          cacheid,
                           &canceled);
+  xfree (cacheid);
+  cacheid = NULL;
   again_text = NULL;
   if (!value && canceled)
     return -1;
@@ -702,7 +761,7 @@ pin_cb (void *opaque, const char *info, char **retstr)
     {
       char *value2;
 
-      value2 = ask_passphrase (info, NULL,
+      value2 = ask_passphrase (info, NULL, NULL,
                                "passphrase.pin.repeat", 
                                _("Repeat this PIN: "),
                               &canceled);
@@ -837,11 +896,14 @@ agent_scd_pksign (const char *serialno, int hashalgo,
                   const unsigned char *indata, size_t indatalen,
                   unsigned char **r_buf, size_t *r_buflen)
 {
+  struct pincb_parm_s parm;
   APP app;
   int rc;
 
   *r_buf = NULL;
   *r_buflen = 0;
+  memset (&parm, 0, sizeof parm);
+  parm.sn = serialno;
  retry:
   app = current_app? current_app : open_card ();
   if (!app)
@@ -854,11 +916,14 @@ agent_scd_pksign (const char *serialno, int hashalgo,
 
   if (!rc)
     rc = app->fnc.sign (app, serialno, hashalgo,
-                        pin_cb, NULL,
+                        pin_cb, &parm,
                         indata, indatalen,
                         r_buf, r_buflen);
   if (rc)
-    write_status (STATUS_SC_OP_FAILURE);
+    {
+      write_status (STATUS_SC_OP_FAILURE);
+      agent_clear_pin_cache (serialno);
+    }
   return rc;
 }
 
@@ -869,11 +934,14 @@ agent_scd_pkdecrypt (const char *serialno,
                      const unsigned char *indata, size_t indatalen,
                      unsigned char **r_buf, size_t *r_buflen)
 {
+  struct pincb_parm_s parm;
   APP app;
   int rc;
 
   *r_buf = NULL;
   *r_buflen = 0;
+  memset (&parm, 0, sizeof parm);
+  parm.sn = serialno;
  retry:
   app = current_app? current_app : open_card ();
   if (!app)
@@ -886,11 +954,14 @@ agent_scd_pkdecrypt (const char *serialno,
 
   if (!rc)
     rc = app->fnc.decipher (app, serialno, 
-                            pin_cb, NULL,
+                            pin_cb, &parm,
                             indata, indatalen,
                             r_buf, r_buflen);
   if (rc)
-    write_status (STATUS_SC_OP_FAILURE);
+    {
+      write_status (STATUS_SC_OP_FAILURE);
+      agent_clear_pin_cache (serialno);
+    }
   return rc;
 }
 
@@ -960,3 +1031,15 @@ agent_openpgp_storekey (int keyno,
     write_status (STATUS_SC_OP_FAILURE);
   return rc;
 }
+
+
+void
+agent_clear_pin_cache (const char *sn)
+{
+  char *cacheid = format_cacheid (sn);
+  if (cacheid)
+    {
+      passphrase_clear_cache (NULL, cacheid, 0);
+      xfree (cacheid);
+    }
+}
index 7ab04f0..068a1aa 100644 (file)
@@ -194,6 +194,10 @@ int agent_openpgp_storekey (int keyno,
                             const unsigned char *m, size_t mlen,
                             const unsigned char *e, size_t elen);
 
+/* Clear a cached PIN. */
+void agent_clear_pin_cache (const char *sn);
+
+
 #endif /*ENABLE_CARD_SUPPORT*/
 #endif /*GNUPG_G10_CARDGLUE_H*/
 
index 7ec0384..eca817e 100644 (file)
@@ -186,11 +186,12 @@ int  build_sk_list( STRLIST locusr, SK_LIST *ret_sk_list,
 /*-- passphrase.h --*/
 int  have_static_passphrase(void);
 void read_passphrase_from_fd( int fd );
-void passphrase_clear_cache ( u32 *keyid, int algo );
+void passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo );
 char *ask_passphrase (const char *description,
                       const char *tryagain_text,
                       const char *promptid,
-                      const char *prompt, int *canceled);
+                      const char *prompt, 
+                      const char *cacheid, int *canceled);
 DEK *passphrase_to_dek( u32 *keyid, int pubkey_algo,
                        int cipher_algo, STRING2KEY *s2k, int mode,
                         const char *tryagain_text, int *canceled);
index c309904..a68d564 100644 (file)
@@ -425,10 +425,13 @@ agent_okay_cb (void *opaque, const char *line)
  *
  * Note that TRYAGAIN_TEXT must not be translated.  If canceled is not
  * NULL, the function does set it to 1 if the user canceled the
- * operation.
+ * operation.  If CACHEID is not NULL, it will be used as the cacheID
+ * for the gpg-agent; if is NULL and a key fingerprint can be
+ * computed, this will be used as the cacheid.
  */
 static char *
-agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
+agent_get_passphrase ( u32 *keyid, int mode, const char *cacheid,
+                       const char *tryagain_text,
                        const char *custom_description,
                        const char *custom_prompt, int *canceled)
 {
@@ -545,11 +548,16 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
       line = xmalloc (15 + 46 
                       + 3*strlen (atext)
                       + 3*strlen (custom_prompt? custom_prompt:"")
+                      + (cacheid? (3*strlen (cacheid)): 0)
                       + 3*strlen (tryagain_text)
                       + 1);
       strcpy (line, "GET_PASSPHRASE ");
       p = line+15;
-      if (!mode && have_fpr)
+      if (!mode && cacheid)
+        {
+          p = percent_plus_escape (p, cacheid);
+        }
+      else if (!mode && have_fpr)
         {
           for (i=0; i < 20; i++, p +=2 )
             sprintf (p, "%02X", fpr[i]);
@@ -629,10 +637,11 @@ agent_get_passphrase ( u32 *keyid, int mode, const char *tryagain_text,
 
 
 /*
- * Clear the cached passphrase
+ * Clear the cached passphrase.  If CACHEID is not NULL, it will be
+ * used instead of a cache ID derived from KEYID.
  */
 void
-passphrase_clear_cache ( u32 *keyid, int algo )
+passphrase_clear_cache ( u32 *keyid, const char *cacheid, int algo )
 {
 #ifdef ENABLE_AGENT_SUPPORT
   assuan_context_t ctx = NULL;
@@ -646,17 +655,22 @@ passphrase_clear_cache ( u32 *keyid, int algo )
   if (!opt.use_agent)
     return;
   
-  pk = xcalloc (1, sizeof *pk);
-  memset (fpr, 0, MAX_FINGERPRINT_LEN );
-  if( !keyid || get_pubkey( pk, keyid ) )
+  if (!cacheid)
     {
-      goto failure; /* oops: no key for some reason */
-    }
+      pk = xcalloc (1, sizeof *pk);
+      memset (fpr, 0, MAX_FINGERPRINT_LEN );
+      if( !keyid || get_pubkey( pk, keyid ) )
+        {
+          goto failure; /* oops: no key for some reason */
+        }
   
-  {
-    size_t dummy;
-    fingerprint_from_pk( pk, fpr, &dummy );
-  }
+      {
+        size_t dummy;
+        fingerprint_from_pk( pk, fpr, &dummy );
+      }
+    }
+  else
+    pk = NULL;
     
   if ( !(ctx = agent_open ()) ) 
     goto failure;
@@ -665,11 +679,21 @@ passphrase_clear_cache ( u32 *keyid, int algo )
       char *line, *p;
       int i, rc; 
 
-      line = xmalloc (17 + 40 + 2);
-      strcpy (line, "CLEAR_PASSPHRASE ");
-      p = line+17;
-      for (i=0; i < 20; i++, p +=2 )
-        sprintf (p, "%02X", fpr[i]);
+      if (cacheid)
+        {
+          line = xmalloc (17 + 3*strlen (cacheid) + 2);
+          strcpy (line, "CLEAR_PASSPHRASE ");
+          p = line+17;
+          p = percent_plus_escape (p, cacheid);
+        }
+      else
+        {
+          line = xmalloc (17 + 40 + 2);
+          strcpy (line, "CLEAR_PASSPHRASE ");
+          p = line+17;
+          for (i=0; i < 20; i++, p +=2 )
+            sprintf (p, "%02X", fpr[i]);
+        }
       *p = 0;
 
       rc = assuan_transact (ctx, line, NULL, NULL, NULL, NULL, NULL, NULL);
@@ -696,7 +720,8 @@ char *
 ask_passphrase (const char *description,
                 const char *tryagain_text,
                 const char *promptid,
-                const char *prompt, int *canceled)
+                const char *prompt,
+                const char *cacheid, int *canceled)
 {
   char *pw = NULL;
   
@@ -709,7 +734,7 @@ ask_passphrase (const char *description,
  agent_died:
   if ( opt.use_agent ) 
     {
-      pw = agent_get_passphrase (NULL, 0,
+      pw = agent_get_passphrase (NULL, 0, cacheid,
                                  tryagain_text, description, prompt,
                                  canceled );
       if (!pw)
@@ -853,7 +878,7 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
     }
     else if ( opt.use_agent ) {
       /* Divert to the gpg-agent. */
-       pw = agent_get_passphrase ( keyid, mode == 2? 1: 0,
+        pw = agent_get_passphrase ( keyid, mode == 2? 1: 0, NULL,
                                     tryagain_text, NULL, NULL, canceled );
         if (!pw)
           {
@@ -862,7 +887,7 @@ passphrase_to_dek( u32 *keyid, int pubkey_algo,
             pw = m_strdup ("");
           }
         if( *pw && mode == 2 ) {
-          char *pw2 = agent_get_passphrase ( keyid, 2, NULL, NULL,
+            char *pw2 = agent_get_passphrase ( keyid, 2, NULL, NULL, NULL,
                                                NULL, canceled );
             if (!pw2)
               {
index 9153b95..fc318d0 100644 (file)
@@ -203,7 +203,7 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
        /* now let's see whether we have used the right passphrase */
        if( csum != sk->csum ) {
            copy_secret_key( sk, save_sk );
-            passphrase_clear_cache ( keyid, sk->pubkey_algo );
+            passphrase_clear_cache ( keyid, NULL, sk->pubkey_algo );
            free_secret_key( save_sk );
            return G10ERR_BAD_PASS;
        }
@@ -211,7 +211,7 @@ do_check( PKT_secret_key *sk, const char *tryagain_text, int mode,
        res = pubkey_check_secret_key( sk->pubkey_algo, sk->skey );
        if( res ) {
            copy_secret_key( sk, save_sk );
-            passphrase_clear_cache ( keyid, sk->pubkey_algo );
+            passphrase_clear_cache ( keyid, NULL, sk->pubkey_algo );
            free_secret_key( save_sk );
            return G10ERR_BAD_PASS;
        }
index 814f381..c65b827 100644 (file)
@@ -808,6 +808,8 @@ sign_file( STRLIST filenames, int detached, STRLIST locusr,
       }
 
     mfx.md = md_open(0, 0);
+    if (DBG_HASHING)
+       md_start_debug (mfx.md, "sign");
 
    /* If we're encrypting and signing, it is reasonable to pick the
        hash algorithm to use out of the recepient key prefs. */
@@ -1217,6 +1219,8 @@ sign_symencrypt_file (const char *fname, STRLIST locusr)
     if (opt.textmode)
        iobuf_push_filter (inp, text_filter, &tfx);
     mfx.md = md_open(0, 0);
+    if ( DBG_HASHING )
+       md_start_debug (mfx.md, "symc-sign");
 
     for (sk_rover = sk_list; sk_rover; sk_rover = sk_rover->next) {
        PKT_secret_key *sk = sk_rover->sk;