gpg: Remove all assert.h and s/assert/log_assert/.
[gnupg.git] / g10 / mainproc.c
index d908d57..d56790b 100644 (file)
@@ -22,7 +22,6 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <assert.h>
 #include <time.h>
 
 #include "gpg.h"
@@ -38,8 +37,8 @@
 #include "trustdb.h"
 #include "keyserver-internal.h"
 #include "photoid.h"
-#include "pka.h"
-
+#include "mbox-util.h"
+#include "call-dirmngr.h"
 
 /* Put an upper limit on nested packets.  The 32 is an arbitrary
    value, a much lower should actually be sufficient.  */
@@ -106,7 +105,7 @@ struct mainproc_context
 
 
 /*** Local prototypes.  ***/
-static int do_proc_packets (CTX c, iobuf_t a);
+static int do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a);
 static void list_node (CTX c, kbnode_t node);
 static void proc_tree (CTX c, kbnode_t node);
 static int literals_seen;
@@ -256,7 +255,7 @@ symkey_decrypt_seskey (DEK *dek, byte *seskey, size_t slen)
     {
       log_error ( _("weird size for an encrypted session key (%d)\n"),
                  (int)slen);
-      return G10ERR_BAD_KEY;
+      return GPG_ERR_BAD_KEY;
     }
 
   if (openpgp_cipher_open (&hd, dek->algo, GCRY_CIPHER_MODE_CFB, 1))
@@ -366,7 +365,7 @@ proc_symkey_enc (CTX c, PACKET *pkt)
 
 
 static void
-proc_pubkey_enc (CTX c, PACKET *pkt)
+proc_pubkey_enc (ctrl_t ctrl, CTX c, PACKET *pkt)
 {
   PKT_pubkey_enc *enc;
   int result = 0;
@@ -387,7 +386,7 @@ proc_pubkey_enc (CTX c, PACKET *pkt)
          to the Libgcrypt defined one.  This is due a chicken-egg
          problem: We need to have code in Libgcrypt for a new
          algorithm so to implement a proposed new algorithm before the
-         IANA will finally assign an OpenPGP indentifier.  */
+         IANA will finally assign an OpenPGP identifier.  */
       snprintf (buf, sizeof buf, "%08lX%08lX %d 0",
                (ulong)enc->keyid[0], (ulong)enc->keyid[1], enc->pubkey_algo);
       write_status_text (STATUS_ENC_TO, buf);
@@ -406,12 +405,10 @@ proc_pubkey_enc (CTX c, PACKET *pkt)
           c->dek = NULL;
        }
     }
-  else if (is_ELGAMAL(enc->pubkey_algo)
-           || enc->pubkey_algo == PUBKEY_ALGO_DSA
-           || enc->pubkey_algo == PUBKEY_ALGO_ECDSA
-           || enc->pubkey_algo == PUBKEY_ALGO_EDDSA
+  else if (enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL_E
            || enc->pubkey_algo == PUBKEY_ALGO_ECDH
-           || is_RSA (enc->pubkey_algo)
+           || enc->pubkey_algo == PUBKEY_ALGO_RSA
+           || enc->pubkey_algo == PUBKEY_ALGO_RSA_E
            || enc->pubkey_algo == PUBKEY_ALGO_ELGAMAL)
     {
       /* Note that we also allow type 20 Elgamal keys for decryption.
@@ -430,7 +427,7 @@ proc_pubkey_enc (CTX c, PACKET *pkt)
           else
             {
               c->dek = xmalloc_secure_clear (sizeof *c->dek);
-              if ((result = get_session_key (enc, c->dek)))
+              if ((result = get_session_key (ctrl, enc, c->dek)))
                 {
                   /* Error: Delete the DEK. */
                   xfree (c->dek);
@@ -439,10 +436,10 @@ proc_pubkey_enc (CTX c, PACKET *pkt)
            }
        }
       else
-        result = G10ERR_NO_SECKEY;
+        result = GPG_ERR_NO_SECKEY;
     }
   else
-    result = G10ERR_PUBKEY_ALGO;
+    result = GPG_ERR_PUBKEY_ALGO;
 
   if (result == -1)
     ;
@@ -504,7 +501,7 @@ print_pkenc_list (struct kidlist_item *list, int failed)
 
       free_public_key (pk);
 
-      if (list->reason == G10ERR_NO_SECKEY)
+      if (gpg_err_code (list->reason) == GPG_ERR_NO_SECKEY)
         {
           if (is_status_enabled())
             {
@@ -517,7 +514,7 @@ print_pkenc_list (struct kidlist_item *list, int failed)
       else if (list->reason)
         {
           log_info (_("public key decryption failed: %s\n"),
-                    g10_errstr(list->reason));
+                    gpg_strerror (list->reason));
           write_status_error ("pkdecrypt_failed", list->reason);
         }
     }
@@ -602,13 +599,29 @@ proc_encrypted (CTX c, PACKET *pkt)
         }
     }
   else if (!c->dek)
-    result = G10ERR_NO_SECKEY;
+    result = GPG_ERR_NO_SECKEY;
 
   if (!result)
     result = decrypt_data (c->ctrl, c, pkt->pkt.encrypted, c->dek );
 
   if (result == -1)
     ;
+  else if (!result
+           && !opt.ignore_mdc_error
+           && !pkt->pkt.encrypted->mdc_method
+           && openpgp_cipher_get_algo_blklen (c->dek->algo) != 8
+           && c->dek->algo != CIPHER_ALGO_TWOFISH)
+    {
+      /* The message has been decrypted but has no MDC despite that a
+         modern cipher (blocklength != 64 bit, except for Twofish) is
+         used and the option to ignore MDC errors is not used: To
+         avoid attacks changing an MDC message to a non-MDC message,
+         we fail here.  */
+      log_error (_("WARNING: message was not integrity protected\n"));
+      if (opt.verbose > 1)
+        log_info ("decryption forced to fail\n");
+      write_status (STATUS_DECRYPTION_FAILED);
+    }
   else if (!result || (gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE
                        && opt.ignore_mdc_error))
     {
@@ -620,7 +633,7 @@ proc_encrypted (CTX c, PACKET *pkt)
       else if (!opt.no_mdc_warn)
         log_info (_("WARNING: message was not integrity protected\n"));
     }
-  else if (gpg_err_code (result) == G10ERR_BAD_SIGN)
+  else if (gpg_err_code (result) == GPG_ERR_BAD_SIGNATURE)
     {
       glo_ctrl.lasterr = result;
       log_error (_("WARNING: encrypted message has been manipulated!\n"));
@@ -632,13 +645,14 @@ proc_encrypted (CTX c, PACKET *pkt)
       if (gpg_err_code (result) == GPG_ERR_BAD_KEY
           && *c->dek->s2k_cacheid != '\0')
         {
-          log_debug (_("cleared passphrase cached with ID: %s\n"),
-                     c->dek->s2k_cacheid);
+          if (opt.debug)
+            log_debug ("cleared passphrase cached with ID: %s\n",
+                       c->dek->s2k_cacheid);
           passphrase_clear_cache (NULL, c->dek->s2k_cacheid, 0);
         }
       glo_ctrl.lasterr = result;
       write_status (STATUS_DECRYPTION_FAILED);
-      log_error (_("decryption failed: %s\n"), g10_errstr(result));
+      log_error (_("decryption failed: %s\n"), gpg_strerror (result));
       /* Hmmm: does this work when we have encrypted using multiple
        * ways to specify the session key (symmmetric and PK). */
     }
@@ -755,7 +769,7 @@ proc_plaintext( CTX c, PACKET *pkt )
     }
 
   if (rc)
-    log_error ("handle plaintext failed: %s\n", g10_errstr(rc));
+    log_error ("handle plaintext failed: %s\n", gpg_strerror (rc));
 
   free_packet(pkt);
   c->last_was_session_key = 0;
@@ -837,9 +851,10 @@ do_check_sig (CTX c, kbnode_t node, int *is_selfsig,
   PKT_signature *sig;
   gcry_md_hd_t md = NULL;
   gcry_md_hd_t md2 = NULL;
+  gcry_md_hd_t md_good = NULL;
   int algo, rc;
 
-  assert (node->pkt->pkttype == PKT_SIGNATURE);
+  log_assert (node->pkt->pkttype == PKT_SIGNATURE);
   if (is_selfsig)
     *is_selfsig = 0;
   sig = node->pkt->pkt.signature;
@@ -858,7 +873,7 @@ do_check_sig (CTX c, kbnode_t node, int *is_selfsig,
         }
       else /* detached signature */
         {
-          /* signature_check() will enable the md. */
+          /* check_signature() will enable the md. */
           if (gcry_md_open (&md, 0, 0 ))
             BUG ();
         }
@@ -877,7 +892,7 @@ do_check_sig (CTX c, kbnode_t node, int *is_selfsig,
       else /* detached signature */
         {
           log_debug ("Do we really need this here?");
-          /* signature_check() will enable the md*/
+          /* check_signature() will enable the md*/
           if (gcry_md_open (&md, 0, 0 ))
             BUG ();
           if (gcry_md_open (&md2, 0, 0 ))
@@ -900,20 +915,35 @@ do_check_sig (CTX c, kbnode_t node, int *is_selfsig,
         {
           log_error (_("standalone revocation - "
                        "use \"gpg --import\" to apply\n"));
-          return G10ERR_NOT_PROCESSED;
+          return GPG_ERR_NOT_PROCESSED;
        }
       else
         {
           log_error ("invalid root packet for sigclass %02x\n", sig->sig_class);
-          return G10ERR_SIG_CLASS;
+          return GPG_ERR_SIG_CLASS;
        }
     }
   else
-    return G10ERR_SIG_CLASS;
+    return GPG_ERR_SIG_CLASS;
+
+  /* We only get here if we are checking the signature of a binary
+     (0x00) or text document (0x01).  */
+  rc = check_signature2 (sig, md, NULL, is_expkey, is_revkey, NULL);
+  if (! rc)
+    md_good = md;
+  else if (gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE && md2)
+    {
+      rc = check_signature2 (sig, md2, NULL, is_expkey, is_revkey, NULL);
+      if (! rc)
+       md_good = md2;
+    }
 
-  rc = signature_check2 (sig, md, NULL, is_expkey, is_revkey, NULL);
-  if (gpg_err_code (rc) == GPG_ERR_BAD_SIGNATURE && md2)
-    rc = signature_check2 (sig, md2, NULL, is_expkey, is_revkey, NULL);
+  if (md_good)
+    {
+      unsigned char *buffer = gcry_md_read (md_good, 0);
+      sig->digest_len = gcry_md_get_algo_dlen (map_md_openpgp_to_gcry (algo));
+      memcpy (sig->digest, buffer, sig->digest_len);
+    }
 
   gcry_md_close (md);
   gcry_md_close (md2);
@@ -930,15 +960,15 @@ print_userid (PACKET *pkt)
 
   if (pkt->pkttype != PKT_USER_ID)
     {
-      printf ("ERROR: unexpected packet type %d", pkt->pkttype );
+      es_printf ("ERROR: unexpected packet type %d", pkt->pkttype );
       return;
     }
   if (opt.with_colons)
     {
       if (pkt->pkt.user_id->attrib_data)
-        printf("%u %lu",
-               pkt->pkt.user_id->numattribs,
-               pkt->pkt.user_id->attrib_len);
+        es_printf("%u %lu",
+                  pkt->pkt.user_id->numattribs,
+                  pkt->pkt.user_id->attrib_len);
       else
         es_write_sanitized (es_stdout, pkt->pkt.user_id->name,
                             pkt->pkt.user_id->len, ":", NULL);
@@ -1033,7 +1063,9 @@ list_node (CTX c, kbnode_t node)
                     es_printf ("%s:::::::::",
                                node->pkt->pkt.user_id->attrib_data?"uat":"uid");
                   else
-                    es_printf ("uid%*s", 28, "" );
+                    es_printf ("uid%*s",
+                               (int)keystrlen ()+(opt.legacy_list_mode? 9:11),
+                               "" );
                   print_userid (node->pkt);
                   if (opt.with_colons)
                     es_putc (':', es_stdout);
@@ -1059,7 +1091,7 @@ list_node (CTX c, kbnode_t node)
     {
 
       log_debug ("FIXME: No way to print secret key packets here\n");
-      /* fixme: We may use a fucntion to turn a secret key packet into
+      /* fixme: We may use a function to turn a secret key packet into
          a public key one and use that here.  */
     }
   else if (node->pkt->pkttype == PKT_SIGNATURE)
@@ -1128,7 +1160,7 @@ list_node (CTX c, kbnode_t node)
         es_printf ("%c       %s %s   ",
                    sigrc, keystr (sig->keyid), datestr_from_sig(sig));
       if (sigrc == '%')
-        es_printf ("[%s] ", g10_errstr(rc2) );
+        es_printf ("[%s] ", gpg_strerror (rc2) );
       else if (sigrc == '?')
         ;
       else if (is_selfsig)
@@ -1163,7 +1195,7 @@ proc_packets (ctrl_t ctrl, void *anchor, iobuf_t a )
 
   c->ctrl = ctrl;
   c->anchor = anchor;
-  rc = do_proc_packets (c, a);
+  rc = do_proc_packets (ctrl, c, a);
   xfree (c);
 
   return rc;
@@ -1186,7 +1218,7 @@ proc_signature_packets (ctrl_t ctrl, void *anchor, iobuf_t a,
   c->signed_data.used = !!signedfiles;
 
   c->sigfilename = sigfilename;
-  rc = do_proc_packets ( c, a );
+  rc = do_proc_packets (ctrl, c, a);
 
   /* If we have not encountered any signature we print an error
      messages, send a NODATA status back and return an error code.
@@ -1197,7 +1229,7 @@ proc_signature_packets (ctrl_t ctrl, void *anchor, iobuf_t a,
     {
       write_status_text (STATUS_NODATA, "4");
       log_error (_("no signature found\n"));
-      rc = G10ERR_NO_DATA;
+      rc = GPG_ERR_NO_DATA;
     }
 
   /* Propagate the signature seen flag upward. Do this only on success
@@ -1229,7 +1261,7 @@ proc_signature_packets_by_fd (ctrl_t ctrl,
   c->signed_data.data_names = NULL;
   c->signed_data.used = (signed_data_fd != -1);
 
-  rc = do_proc_packets ( c, a );
+  rc = do_proc_packets (ctrl, c, a);
 
   /* If we have not encountered any signature we print an error
      messages, send a NODATA status back and return an error code.
@@ -1262,7 +1294,7 @@ proc_encryption_packets (ctrl_t ctrl, void *anchor, iobuf_t a )
   c->ctrl = ctrl;
   c->anchor = anchor;
   c->encrypt_only = 1;
-  rc = do_proc_packets (c, a);
+  rc = do_proc_packets (ctrl, c, a);
   xfree (c);
   return rc;
 }
@@ -1288,7 +1320,7 @@ check_nesting (CTX c)
 
 
 static int
-do_proc_packets (CTX c, iobuf_t a)
+do_proc_packets (ctrl_t ctrl, CTX c, iobuf_t a)
 {
   PACKET *pkt;
   int rc = 0;
@@ -1320,7 +1352,7 @@ do_proc_packets (CTX c, iobuf_t a)
         {
           switch (pkt->pkttype)
             {
-            case PKT_PUBKEY_ENC:    proc_pubkey_enc (c, pkt); break;
+            case PKT_PUBKEY_ENC:    proc_pubkey_enc (ctrl, c, pkt); break;
             case PKT_SYMKEY_ENC:    proc_symkey_enc (c, pkt); break;
             case PKT_ENCRYPTED:
             case PKT_ENCRYPTED_MDC: proc_encrypted (c, pkt); break;
@@ -1340,7 +1372,7 @@ do_proc_packets (CTX c, iobuf_t a)
             case PKT_ENCRYPTED:
             case PKT_ENCRYPTED_MDC:
               write_status_text( STATUS_UNEXPECTED, "0" );
-              rc = G10ERR_UNEXPECTED;
+              rc = GPG_ERR_UNEXPECTED;
               goto leave;
 
             case PKT_SIGNATURE:   newpkt = add_signature (c, pkt); break;
@@ -1359,12 +1391,12 @@ do_proc_packets (CTX c, iobuf_t a)
             case PKT_SECRET_KEY:
             case PKT_USER_ID:
               write_status_text (STATUS_UNEXPECTED, "0");
-              rc = G10ERR_UNEXPECTED;
+              rc = GPG_ERR_UNEXPECTED;
               goto leave;
 
             case PKT_SIGNATURE:   newpkt = add_signature (c, pkt); break;
             case PKT_SYMKEY_ENC:  proc_symkey_enc (c, pkt); break;
-            case PKT_PUBKEY_ENC:  proc_pubkey_enc (c, pkt); break;
+            case PKT_PUBKEY_ENC:  proc_pubkey_enc (ctrl, c, pkt); break;
             case PKT_ENCRYPTED:
             case PKT_ENCRYPTED_MDC: proc_encrypted (c, pkt); break;
             case PKT_PLAINTEXT:   proc_plaintext (c, pkt); break;
@@ -1390,7 +1422,7 @@ do_proc_packets (CTX c, iobuf_t a)
               break;
             case PKT_USER_ID:     newpkt = add_user_id (c, pkt); break;
             case PKT_SIGNATURE:   newpkt = add_signature (c, pkt); break;
-            case PKT_PUBKEY_ENC:  proc_pubkey_enc (c, pkt); break;
+            case PKT_PUBKEY_ENC:  proc_pubkey_enc (ctrl, c, pkt); break;
             case PKT_SYMKEY_ENC:  proc_symkey_enc (c, pkt); break;
             case PKT_ENCRYPTED:
             case PKT_ENCRYPTED_MDC: proc_encrypted (c, pkt); break;
@@ -1410,7 +1442,7 @@ do_proc_packets (CTX c, iobuf_t a)
        * I used it.  Adding the MDC check here is a hack.
        * The right solution is to initiate another context for encrypted
        * packet and not to reuse the current one ...  It works right
-       * when there is a compression packet inbetween which adds just
+       * when there is a compression packet between which adds just
        * an extra layer.
        * Hmmm: Rewrite this whole module here??
        */
@@ -1428,7 +1460,7 @@ do_proc_packets (CTX c, iobuf_t a)
         free_packet(pkt);
     }
 
-  if (rc == G10ERR_INVALID_PACKET)
+  if (rc == GPG_ERR_INV_PACKET)
     write_status_text (STATUS_NODATA, "3");
 
   if (any_data)
@@ -1486,25 +1518,37 @@ get_pka_address (PKT_signature *sig)
    be retrieved for the signature we merely return it; if not we go
    out and try to get that DNS record. */
 static const char *
-pka_uri_from_sig (PKT_signature *sig)
+pka_uri_from_sig (CTX c, PKT_signature *sig)
 {
   if (!sig->flags.pka_tried)
     {
-      assert (!sig->pka_info);
+      log_assert (!sig->pka_info);
       sig->flags.pka_tried = 1;
       sig->pka_info = get_pka_address (sig);
       if (sig->pka_info)
         {
-          char *uri;
+          char *url;
+          unsigned char *fpr;
+          size_t fprlen;
 
-          uri = get_pka_info (sig->pka_info->email, sig->pka_info->fpr);
-          if (uri)
+          if (!gpg_dirmngr_get_pka (c->ctrl, sig->pka_info->email,
+                                    &fpr, &fprlen, &url))
             {
-              sig->pka_info->valid = 1;
-              if (!*uri)
-                xfree (uri);
-              else
-                sig->pka_info->uri = uri;
+              if (fpr && fprlen == sizeof sig->pka_info->fpr)
+                {
+                  memcpy (sig->pka_info->fpr, fpr, fprlen);
+                  if (url)
+                    {
+                      sig->pka_info->valid = 1;
+                      if (!*url)
+                        xfree (url);
+                      else
+                        sig->pka_info->uri = url;
+                      url = NULL;
+                    }
+                }
+              xfree (fpr);
+              xfree (url);
             }
         }
     }
@@ -1592,7 +1636,7 @@ check_sig_and_print (CTX c, kbnode_t node)
 /*     dump_kbnode (c->list); */
 
     n = c->list;
-    assert (n);
+    log_assert (n);
     if ( n->pkt->pkttype == PKT_SIGNATURE )
       {
         /* This is either "S{1,n}" case (detached signature) or
@@ -1668,6 +1712,8 @@ check_sig_and_print (CTX c, kbnode_t node)
       }
   }
 
+  write_status_text (STATUS_NEWSIG, NULL);
+
   astr = openpgp_pk_algo_name ( sig->pubkey_algo );
   if (keystrlen () > 8)
     {
@@ -1684,7 +1730,7 @@ check_sig_and_print (CTX c, kbnode_t node)
 
   /* If the key isn't found, check for a preferred keyserver */
 
-  if (gpg_err_code (rc) == G10ERR_NO_PUBKEY && sig->flags.pref_ks)
+  if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY && sig->flags.pref_ks)
     {
       const byte *p;
       int seq = 0;
@@ -1726,11 +1772,11 @@ check_sig_and_print (CTX c, kbnode_t node)
 
   /* If the preferred keyserver thing above didn't work, our second
      try is to use the URI from a DNS PKA record. */
-  if (gpg_err_code (rc) == G10ERR_NO_PUBKEY
+  if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
       && (opt.keyserver_options.options & KEYSERVER_AUTO_KEY_RETRIEVE)
       && (opt.keyserver_options.options & KEYSERVER_HONOR_PKA_RECORD))
     {
-      const char *uri = pka_uri_from_sig (sig);
+      const char *uri = pka_uri_from_sig (c, sig);
 
       if (uri)
         {
@@ -1739,7 +1785,7 @@ check_sig_and_print (CTX c, kbnode_t node)
           int res;
           struct keyserver_spec *spec;
 
-          spec = parse_keyserver_uri (uri, 1, NULL, 0);
+          spec = parse_keyserver_uri (uri, 1);
           if (spec)
             {
               glo_ctrl.in_auto_key_retrieve++;
@@ -1755,9 +1801,9 @@ check_sig_and_print (CTX c, kbnode_t node)
   /* If the preferred keyserver thing above didn't work and we got
        no information from the DNS PKA, this is a third try. */
 
-  if (gpg_err_code (rc) == G10ERR_NO_PUBKEY
-      && opt.keyserver
-      && (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE))
+  if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY
+      && (opt.keyserver_options.options&KEYSERVER_AUTO_KEY_RETRIEVE)
+      && keyserver_any_configured (c->ctrl))
     {
       int res;
 
@@ -1792,7 +1838,8 @@ check_sig_and_print (CTX c, kbnode_t node)
       snprintf (keyid_str, sizeof keyid_str, "%08lX%08lX [uncertain] ",
                 (ulong)sig->keyid[0], (ulong)sig->keyid[1]);
 
-      /* Find and print the primary user ID.  */
+      /* Find and print the primary user ID along with the
+         "Good|Expired|Bad signature" line.  */
       for (un=keyblock; un; un = un->next)
         {
           int valid;
@@ -1816,11 +1863,17 @@ check_sig_and_print (CTX c, kbnode_t node)
           if (un->pkt->pkt.user_id->attrib_data)
             continue;
 
-          assert (pk);
+          log_assert (pk);
 
-          /* Get it before we print anything to avoid interrupting the
-             output with the "please do a --check-trustdb" line. */
-          valid = get_validity (pk, un->pkt->pkt.user_id);
+         /* Since this is just informational, don't actually ask the
+            user to update any trust information.  (Note: we register
+            the signature later.)  Because print_good_bad_signature
+            does not print a LF we need to compute the validity
+            before calling that function.  */
+          if ((opt.verify_options & VERIFY_SHOW_UID_VALIDITY))
+            valid = get_validity (pk, un->pkt->pkt.user_id, NULL, 0);
+          else
+            valid = 0; /* Not used.  */
 
           keyid_str[17] = 0; /* cut off the "[uncertain]" part */
 
@@ -1831,11 +1884,17 @@ check_sig_and_print (CTX c, kbnode_t node)
           else
             log_printf ("\n");
 
+          /* Get a string description of the algo for informational
+             output we want to print later.  It is convenient to do it
+             here because we already have the right public key. */
           pubkey_string (pk, pkstrbuf, sizeof pkstrbuf);
           count++;
        }
 
-      if (!count)  /* Just in case that we have no valid textual userid */
+      /* In case we did not found a valid valid textual userid above
+         we print the first user id packet or a "[?]" instead along
+         with the "Good|Expired|Bad signature" line.  */
+      if (!count)
         {
           /* Try for an invalid textual userid */
           for (un=keyblock; un; un = un->next)
@@ -1880,11 +1939,12 @@ check_sig_and_print (CTX c, kbnode_t node)
                    || un->pkt->pkt.user_id->is_expired)
                   && !(opt.verify_options & VERIFY_SHOW_UNUSABLE_UIDS))
                 continue;
-              /* Only skip textual primaries */
+              /* Skip textual primary user ids which we printed above. */
               if (un->pkt->pkt.user_id->is_primary
                   && !un->pkt->pkt.user_id->attrib_data )
                 continue;
 
+              /* If this user id has attribute data, print that.  */
               if (un->pkt->pkt.user_id->attrib_data)
                 {
                   dump_attribs (un->pkt->pkt.user_id, pk);
@@ -1909,8 +1969,11 @@ check_sig_and_print (CTX c, kbnode_t node)
                   else if (un->pkt->pkt.user_id->is_expired)
                     valid = _("expired");
                   else
+                   /* Since this is just informational, don't
+                      actually ask the user to update any trust
+                      information.  */
                     valid = (trust_value_to_string
-                             (get_validity (pk, un->pkt->pkt.user_id)));
+                             (get_validity (pk, un->pkt->pkt.user_id, sig, 0)));
                   log_printf (" [%s]\n",valid);
                 }
               else
@@ -1919,6 +1982,7 @@ check_sig_and_print (CTX c, kbnode_t node)
        }
       release_kbnode( keyblock );
 
+      /* For good signatures print notation data.  */
       if (!rc)
         {
           if ((opt.verify_options & VERIFY_SHOW_POLICY_URLS))
@@ -1940,9 +2004,9 @@ check_sig_and_print (CTX c, kbnode_t node)
             show_notation (sig, 0, 2, 0);
         }
 
+      /* For good signatures print the VALIDSIG status line.  */
       if (!rc && is_status_enabled ())
         {
-          /* Print a status response with the fingerprint. */
           PKT_public_key *vpk = xmalloc_clear (sizeof *vpk);
 
           if (!get_pubkey (vpk, sig->keyid))
@@ -1990,17 +2054,21 @@ check_sig_and_print (CTX c, kbnode_t node)
           free_public_key (vpk);
        }
 
+      /* For good signatures compute and print the trust information.
+         Note that in the Tofu trust model this may ask the user on
+         how to resolve a conflict.  */
       if (!rc)
         {
           if ((opt.verify_options & VERIFY_PKA_LOOKUPS))
-            pka_uri_from_sig (sig); /* Make sure PKA info is available. */
+            pka_uri_from_sig (c, sig); /* Make sure PKA info is available. */
           rc = check_signatures_trust (sig);
         }
 
+      /* Print extra information about the signature.  */
       if (sig->flags.expired)
         {
           log_info (_("Signature expired %s\n"), asctimestamp(sig->expiredate));
-          rc = G10ERR_GENERAL; /* need a better error here? */
+          rc = GPG_ERR_GENERAL; /* Need a better error here?  */
         }
       else if (sig->expiredate)
         log_info (_("Signature expires %s\n"), asctimestamp(sig->expiredate));
@@ -2013,6 +2081,7 @@ check_sig_and_print (CTX c, kbnode_t node)
                   *pkstrbuf?_(", key algorithm "):"",
                   pkstrbuf);
 
+      /* Print final warnings.  */
       if (!rc && !c->signed_data.used)
         {
           /* Signature is basically good but we test whether the
@@ -2065,13 +2134,13 @@ check_sig_and_print (CTX c, kbnode_t node)
                 sig->pubkey_algo, sig->digest_algo,
                 sig->sig_class, (ulong)sig->timestamp, rc);
       write_status_text (STATUS_ERRSIG, buf);
-      if (gpg_err_code (rc) == G10ERR_NO_PUBKEY)
+      if (gpg_err_code (rc) == GPG_ERR_NO_PUBKEY)
         {
           buf[16] = 0;
           write_status_text (STATUS_NO_PUBKEY, buf);
        }
-      if (gpg_err_code (rc) != G10ERR_NOT_PROCESSED)
-        log_error (_("Can't check signature: %s\n"), g10_errstr(rc));
+      if (gpg_err_code (rc) != GPG_ERR_NOT_PROCESSED)
+        log_error (_("Can't check signature: %s\n"), gpg_strerror (rc));
     }
 
   return rc;
@@ -2123,8 +2192,9 @@ proc_tree (CTX c, kbnode_t node)
 
           free_md_filter_context (&c->mfx);
           /* Prepare to create all requested message digests.  */
-          if (gcry_md_open (&c->mfx.md, 0, 0))
-            BUG ();
+          rc = gcry_md_open (&c->mfx.md, 0, 0);
+          if (rc)
+            goto hash_err;
 
           /* Fixme: why looking for the signature packet and not the
              one-pass packet?  */
@@ -2154,9 +2224,10 @@ proc_tree (CTX c, kbnode_t node)
                                               use_textmode);
            }
 
+        hash_err:
           if (rc)
             {
-              log_error ("can't hash datafile: %s\n", g10_errstr (rc));
+              log_error ("can't hash datafile: %s\n", gpg_strerror (rc));
               return;
            }
        }
@@ -2225,8 +2296,9 @@ proc_tree (CTX c, kbnode_t node)
         {
           /* Detached signature */
           free_md_filter_context (&c->mfx);
-          if (gcry_md_open (&c->mfx.md, sig->digest_algo, 0))
-            BUG ();
+          rc = gcry_md_open (&c->mfx.md, sig->digest_algo, 0);
+          if (rc)
+            goto detached_hash_err;
 
           if (RFC2440 || RFC4880)
             ; /* Strict RFC mode.  */
@@ -2236,8 +2308,9 @@ proc_tree (CTX c, kbnode_t node)
             {
               /* Enable a workaround for a pgp5 bug when the detached
                * signature has been created in textmode.  */
-              if (gcry_md_open (&c->mfx.md2, sig->digest_algo, 0 ))
-                BUG ();
+              rc = gcry_md_open (&c->mfx.md2, sig->digest_algo, 0);
+              if (rc)
+                goto detached_hash_err;
            }
 
           /* Here we used to have another hack to work around a pgp
@@ -2276,9 +2349,10 @@ proc_tree (CTX c, kbnode_t node)
                                               (sig->sig_class == 0x01));
            }
 
+        detached_hash_err:
           if (rc)
             {
-              log_error ("can't hash datafile: %s\n", g10_errstr(rc));
+              log_error ("can't hash datafile: %s\n", gpg_strerror (rc));
               return;
            }
        }