gpg: Avoid endless loop in a tofu error case.
[gnupg.git] / g10 / keyedit.c
index 84f0431..d05ea5d 100644 (file)
@@ -1,6 +1,6 @@
 /* keyedit.c - Edit properties of a key
  * Copyright (C) 1998-2010 Free Software Foundation, Inc.
- * Copyright (C) 1998-2015 Werner Koch
+ * Copyright (C) 1998-2016 Werner Koch
  * Copyright (C) 2015, 2016 g10 Code GmbH
  *
  * This file is part of GnuPG.
@@ -24,7 +24,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <assert.h>
 #include <ctype.h>
 #ifdef HAVE_LIBREADLINE
 # define GNUPG_LIBREADLINE_H_INCLUDED
@@ -52,7 +51,8 @@
 
 static void show_prefs (PKT_user_id * uid, PKT_signature * selfsig,
                        int verbose);
-static void show_names (estream_t fp, KBNODE keyblock, PKT_public_key * pk,
+static void show_names (ctrl_t ctrl, estream_t fp,
+                        kbnode_t keyblock, PKT_public_key * pk,
                        unsigned int flag, int with_prefs);
 static void show_key_with_all_names (ctrl_t ctrl, estream_t fp,
                                      KBNODE keyblock, int only_marked,
@@ -62,8 +62,8 @@ static void show_key_with_all_names (ctrl_t ctrl, estream_t fp,
 static void show_key_and_fingerprint (kbnode_t keyblock, int with_subkeys);
 static void show_key_and_grip (kbnode_t keyblock);
 static void subkey_expire_warning (kbnode_t keyblock);
-static int menu_adduid (KBNODE keyblock, int photo, const char *photo_name,
-                        const char *uidstr);
+static int menu_adduid (ctrl_t ctrl, kbnode_t keyblock,
+                        int photo, const char *photo_name, const char *uidstr);
 static void menu_deluid (KBNODE pub_keyblock);
 static int menu_delsig (KBNODE pub_keyblock);
 static int menu_clean (KBNODE keyblock, int self_only);
@@ -86,13 +86,13 @@ static int count_selected_uids (KBNODE keyblock);
 static int real_uids_left (KBNODE keyblock);
 static int count_selected_keys (KBNODE keyblock);
 static int menu_revsig (KBNODE keyblock);
-static int menu_revuid (KBNODE keyblock);
+static int menu_revuid (ctrl_t ctrl, kbnode_t keyblock);
 static int menu_revkey (KBNODE pub_keyblock);
 static int menu_revsubkey (KBNODE pub_keyblock);
 #ifndef NO_TRUST_MODELS
 static int enable_disable_key (KBNODE keyblock, int disable);
 #endif /*!NO_TRUST_MODELS*/
-static void menu_showphoto (KBNODE keyblock);
+static void menu_showphoto (ctrl_t ctrl, kbnode_t keyblock);
 
 static int update_trust = 0;
 
@@ -339,8 +339,8 @@ sig_comparison (const void *av, const void *bv)
   int ndatab;
   int i;
 
-  assert (an->pkt->pkttype == PKT_SIGNATURE);
-  assert (bn->pkt->pkttype == PKT_SIGNATURE);
+  log_assert (an->pkt->pkttype == PKT_SIGNATURE);
+  log_assert (bn->pkt->pkttype == PKT_SIGNATURE);
 
   a = an->pkt->pkt.signature;
   b = bn->pkt->pkt.signature;
@@ -351,8 +351,9 @@ sig_comparison (const void *av, const void *bv)
     return 1;
 
   ndataa = pubkey_get_nsig (a->pubkey_algo);
-  ndatab = pubkey_get_nsig (a->pubkey_algo);
-  assert (ndataa == ndatab);
+  ndatab = pubkey_get_nsig (b->pubkey_algo);
+  if (ndataa != ndatab)
+    return (ndataa < ndatab)? -1 : 1;
 
   for (i = 0; i < ndataa; i ++)
     {
@@ -399,7 +400,7 @@ check_all_keysigs (KBNODE kb, int only_selected, int only_selfsigs)
   int missing_selfsig = 0;
   int modified = 0;
 
-  assert (kb->pkt->pkttype == PKT_PUBLIC_KEY);
+  log_assert (kb->pkt->pkttype == PKT_PUBLIC_KEY);
   pk = kb->pkt->pkt.public_key;
 
   /* First we look for duplicates.  */
@@ -431,17 +432,17 @@ check_all_keysigs (KBNODE kb, int only_selected, int only_selfsigs)
         sigs[i] = n;
         i ++;
       }
-    assert (i == nsigs);
+    log_assert (i == nsigs);
 
     qsort (sigs, nsigs, sizeof (sigs[0]), sig_comparison);
 
     last_i = 0;
     for (i = 1; i < nsigs; i ++)
       {
-        assert (sigs[last_i]);
-        assert (sigs[last_i]->pkt->pkttype == PKT_SIGNATURE);
-        assert (sigs[i]);
-        assert (sigs[i]->pkt->pkttype == PKT_SIGNATURE);
+        log_assert (sigs[last_i]);
+        log_assert (sigs[last_i]->pkt->pkttype == PKT_SIGNATURE);
+        log_assert (sigs[i]);
+        log_assert (sigs[i]->pkt->pkttype == PKT_SIGNATURE);
 
         if (sig_comparison (&sigs[last_i], &sigs[i]) == 0)
           /* They are the same.  Kill the latter.  */
@@ -450,8 +451,10 @@ check_all_keysigs (KBNODE kb, int only_selected, int only_selfsigs)
               {
                 PKT_signature *sig = sigs[i]->pkt->pkt.signature;
 
-                log_debug ("Signature appears multiple times, deleting duplicate:\n");
-                log_debug ("  sig: class 0x%x, issuer: %s, timestamp: %s (%lld), digest: %02x %02x\n",
+                log_debug ("Signature appears multiple times, "
+                           "deleting duplicate:\n");
+                log_debug ("  sig: class 0x%x, issuer: %s,"
+                           " timestamp: %s (%lld), digest: %02x %02x\n",
                            sig->sig_class, keystr (sig->keyid),
                            isotimestamp (sig->timestamp),
                            (long long) sig->timestamp,
@@ -519,7 +522,7 @@ check_all_keysigs (KBNODE kb, int only_selected, int only_selfsigs)
       switch (p->pkttype)
         {
         case PKT_PUBLIC_KEY:
-          assert (p->pkt.public_key == pk);
+          log_assert (p->pkt.public_key == pk);
           if (only_selected && ! (n->flag & NODFLG_SELKEY))
             {
               current_component = NULL;
@@ -569,7 +572,8 @@ check_all_keysigs (KBNODE kb, int only_selected, int only_selfsigs)
 
           sig = n->pkt->pkt.signature;
 
-          pending_desc = xasprintf ("  sig: class: 0x%x, issuer: %s, timestamp: %s (%lld), digest: %02x %02x",
+          pending_desc = xasprintf ("  sig: class: 0x%x, issuer: %s,"
+                                    " timestamp: %s (%lld), digest: %02x %02x",
                                     sig->sig_class,
                                     keystr (sig->keyid),
                                     isotimestamp (sig->timestamp),
@@ -595,8 +599,9 @@ check_all_keysigs (KBNODE kb, int only_selected, int only_selfsigs)
                     {
                       if (pending_desc)
                         log_debug ("%s", pending_desc);
-                      log_debug ("    Can't check signature allegedly issued by %s: %s\n",
-                                keystr (sig->keyid), gpg_strerror (err));
+                      log_debug ("    Can't check signature allegedly"
+                                 " issued by %s: %s\n",
+                                 keystr (sig->keyid), gpg_strerror (err));
                     }
                   missing_issuer ++;
                   break;
@@ -607,7 +612,8 @@ check_all_keysigs (KBNODE kb, int only_selected, int only_selfsigs)
             {
               if (DBG_PACKET && pending_desc)
                 log_debug ("%s", pending_desc);
-              tty_printf (_("can't check signature with unsupported public-key algorithm (%d): %s.\n"),
+              tty_printf (_("can't check signature with unsupported"
+                            " public-key algorithm (%d): %s.\n"),
                           sig->pubkey_algo, gpg_strerror (err));
               break;
             }
@@ -615,7 +621,8 @@ check_all_keysigs (KBNODE kb, int only_selected, int only_selfsigs)
             {
               if (DBG_PACKET && pending_desc)
                 log_debug ("%s", pending_desc);
-              tty_printf (_("can't check signature with unsupported message-digest algorithm %d: %s.\n"),
+              tty_printf (_("can't check signature with unsupported"
+                            " message-digest algorithm %d: %s.\n"),
                           sig->digest_algo, gpg_strerror (err));
               break;
             }
@@ -658,14 +665,15 @@ check_all_keysigs (KBNODE kb, int only_selected, int only_selfsigs)
             }
           else if (n2)
             {
-              assert (n2->pkt->pkttype == PKT_USER_ID
-                      || n2->pkt->pkttype == PKT_PUBLIC_KEY
-                      || n2->pkt->pkttype == PKT_PUBLIC_SUBKEY);
+              log_assert (n2->pkt->pkttype == PKT_USER_ID
+                          || n2->pkt->pkttype == PKT_PUBLIC_KEY
+                          || n2->pkt->pkttype == PKT_PUBLIC_SUBKEY);
 
               if (DBG_PACKET)
                 {
                   log_debug ("%s", pending_desc);
-                  log_debug ("    Good signature out of order!  (Over %s (%d) '%s')\n",
+                  log_debug ("    Good signature out of order!"
+                             "  (Over %s (%d) '%s')\n",
                              n2->pkt->pkttype == PKT_USER_ID
                              ? "user id"
                              : n2->pkt->pkttype == PKT_PUBLIC_SUBKEY
@@ -681,7 +689,7 @@ check_all_keysigs (KBNODE kb, int only_selected, int only_selfsigs)
                  after n2.  */
 
               /* Unlink the signature.  */
-              assert (n_prevp);
+              log_assert (n_prevp);
               *n_prevp = n->next;
 
               /* Insert the sig immediately after the component.  */
@@ -907,7 +915,8 @@ check_all_keysigs (KBNODE kb, int only_selected, int only_selfsigs)
                           reordered), reordered);
 
   if (only_selfsigs && (bad_signature || reordered))
-    tty_printf (_("Warning: errors found and only checked self-signatures, run 'check' to check all signatures.\n"));
+    tty_printf (_("Warning: errors found and only checked self-signatures,"
+                  " run '%s' to check all signatures.\n"), "check");
 
   return modified;
 }
@@ -990,7 +999,8 @@ trustsig_prompt (byte * trust_value, byte * trust_depth, char **regexp)
   tty_printf ("\n");
 
   tty_printf (_("Please enter the depth of this trust signature.\n"
-               "A depth greater than 1 allows the key you are signing to make\n"
+               "A depth greater than 1 allows the key you are"
+                " signing to make\n"
                "trust signatures on your behalf.\n"));
   tty_printf ("\n");
 
@@ -1577,7 +1587,7 @@ sign_uids (ctrl_t ctrl, estream_t fp,
              PKT_signature *sig;
              struct sign_attrib attrib;
 
-             assert (primary_pk);
+             log_assert (primary_pk);
              memset (&attrib, 0, sizeof attrib);
              attrib.non_exportable = local;
              attrib.non_revocable = nonrevocable;
@@ -1682,7 +1692,7 @@ change_passphrase (ctrl_t ctrl, kbnode_t keyblock)
           err = hexkeygrip_from_pk (pk, &hexgrip);
           if (err)
             goto leave;
-          err = agent_get_keyinfo (ctrl, hexgrip, &serialno);
+          err = agent_get_keyinfo (ctrl, hexgrip, &serialno, NULL);
           if (!err && serialno)
             ; /* Key on card.  */
           else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
@@ -1720,7 +1730,8 @@ change_passphrase (ctrl_t ctrl, kbnode_t keyblock)
             goto leave;
 
           desc = gpg_format_keydesc (pk, FORMAT_KEYDESC_NORMAL, 1);
-          err = agent_passwd (ctrl, hexgrip, desc, &cache_nonce, &passwd_nonce);
+          err = agent_passwd (ctrl, hexgrip, desc, 0,
+                              &cache_nonce, &passwd_nonce);
           xfree (desc);
 
           if (err)
@@ -2015,7 +2026,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
      and run the stale check as early as possible.  Note, that for
      non- W32 platforms it is run indirectly trough a call to
      get_validity ().  */
-  check_trustdb_stale ();
+  check_trustdb_stale (ctrl);
 #endif
 
   /* Get the public key */
@@ -2200,8 +2211,9 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
          break;
 
        case cmdCHECK:
-         check_all_keysigs (keyblock, count_selected_uids (keyblock),
-                             !strcmp (arg_string, "selfsig"));
+         if (check_all_keysigs (keyblock, count_selected_uids (keyblock),
+                                 !strcmp (arg_string, "selfsig")))
+            modified = 1;
          break;
 
        case cmdSIGN:
@@ -2287,7 +2299,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
          photo = 1;
          /* fall through */
        case cmdADDUID:
-         if (menu_adduid (keyblock, photo, arg_string, NULL))
+         if (menu_adduid (ctrl, keyblock, photo, arg_string, NULL))
            {
              update_trust = 1;
              redisplay = 1;
@@ -2340,7 +2352,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
          break;
 
        case cmdADDKEY:
-         if (!generate_subkeypair (ctrl, keyblock))
+         if (!generate_subkeypair (ctrl, keyblock, NULL, NULL, NULL))
            {
              redisplay = 1;
              modified = 1;
@@ -2416,7 +2428,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
             else if (*arg_string == '~')
               fname = make_filename (arg_string, NULL);
             else
-              fname = make_filename (opt.homedir, arg_string, NULL);
+              fname = make_filename (gnupg_homedir (), arg_string, NULL);
 
            /* Open that file.  */
            a = iobuf_open (fname);
@@ -2529,7 +2541,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
                       n1 > 1 ? _("Really revoke all selected user IDs? (y/N) ")
                      :        _("Really revoke this user ID? (y/N) ")))
              {
-               if (menu_revuid (keyblock))
+               if (menu_revuid (ctrl, keyblock))
                  {
                    modified = 1;
                    redisplay = 1;
@@ -2623,7 +2635,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
 
          show_key_with_all_names (ctrl, NULL, keyblock, 0, 0, 0, 1, 0, 0);
          tty_printf ("\n");
-         if (edit_ownertrust (find_kbnode (keyblock,
+         if (edit_ownertrust (ctrl, find_kbnode (keyblock,
                                            PKT_PUBLIC_KEY)->pkt->pkt.
                               public_key, 1))
            {
@@ -2639,8 +2651,8 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
        case cmdPREF:
          {
            int count = count_selected_uids (keyblock);
-           assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
-           show_names (NULL, keyblock, keyblock->pkt->pkt.public_key,
+           log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
+           show_names (ctrl, NULL, keyblock, keyblock->pkt->pkt.public_key,
                        count ? NODFLG_SELUID : 0, 1);
          }
          break;
@@ -2648,8 +2660,8 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
        case cmdSHOWPREF:
          {
            int count = count_selected_uids (keyblock);
-           assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
-           show_names (NULL, keyblock, keyblock->pkt->pkt.public_key,
+           log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
+           show_names (ctrl, NULL, keyblock, keyblock->pkt->pkt.public_key,
                        count ? NODFLG_SELUID : 0, 2);
          }
          break;
@@ -2725,7 +2737,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
 #endif /*!NO_TRUST_MODELS*/
 
        case cmdSHOWPHOTO:
-         menu_showphoto (keyblock);
+         menu_showphoto (ctrl, keyblock);
          break;
 
        case cmdCLEAN:
@@ -2855,7 +2867,7 @@ keyedit_quick_adduid (ctrl_t ctrl, const char *username, const char *newuid)
 
 #ifdef HAVE_W32_SYSTEM
   /* See keyedit_menu for why we need this.  */
-  check_trustdb_stale ();
+  check_trustdb_stale (ctrl);
 #endif
 
   /* Search the key; we don't want the whole getkey stuff here.  */
@@ -2906,7 +2918,7 @@ keyedit_quick_adduid (ctrl_t ctrl, const char *username, const char *newuid)
 
   fix_keyblock (&keyblock);
 
-  if (menu_adduid (keyblock, 0, NULL, uidstring))
+  if (menu_adduid (ctrl, keyblock, 0, NULL, uidstring))
     {
       err = keydb_update_keyblock (kdbhd, keyblock);
       if (err)
@@ -2926,6 +2938,75 @@ keyedit_quick_adduid (ctrl_t ctrl, const char *username, const char *newuid)
 }
 
 
+/* Find a keyblock by fingerprint because only this uniquely
+ * identifies a key and may thus be used to select a key for
+ * unattended subkey creation os key signing.  */
+static gpg_error_t
+find_by_primary_fpr (ctrl_t ctrl, const char *fpr,
+                     kbnode_t *r_keyblock, KEYDB_HANDLE *r_kdbhd)
+{
+  gpg_error_t err;
+  kbnode_t keyblock = NULL;
+  KEYDB_HANDLE kdbhd = NULL;
+  KEYDB_SEARCH_DESC desc;
+  byte fprbin[MAX_FINGERPRINT_LEN];
+  size_t fprlen;
+
+  *r_keyblock = NULL;
+  *r_kdbhd = NULL;
+
+  if (classify_user_id (fpr, &desc, 1)
+      || !(desc.mode == KEYDB_SEARCH_MODE_FPR
+           || desc.mode == KEYDB_SEARCH_MODE_FPR16
+           || desc.mode == KEYDB_SEARCH_MODE_FPR20))
+    {
+      log_error (_("\"%s\" is not a fingerprint\n"), fpr);
+      err = gpg_error (GPG_ERR_INV_NAME);
+      goto leave;
+    }
+  err = get_pubkey_byname (ctrl, NULL, NULL, fpr, &keyblock, &kdbhd, 1, 1);
+  if (err)
+    {
+      log_error (_("key \"%s\" not found: %s\n"), fpr, gpg_strerror (err));
+      goto leave;
+    }
+
+  /* Check that the primary fingerprint has been given. */
+  fingerprint_from_pk (keyblock->pkt->pkt.public_key, fprbin, &fprlen);
+  if (fprlen == 16 && desc.mode == KEYDB_SEARCH_MODE_FPR16
+      && !memcmp (fprbin, desc.u.fpr, 16))
+    ;
+  else if (fprlen == 16 && desc.mode == KEYDB_SEARCH_MODE_FPR
+           && !memcmp (fprbin, desc.u.fpr, 16)
+           && !desc.u.fpr[16]
+           && !desc.u.fpr[17]
+           && !desc.u.fpr[18]
+           && !desc.u.fpr[19])
+    ;
+  else if (fprlen == 20 && (desc.mode == KEYDB_SEARCH_MODE_FPR20
+                            || desc.mode == KEYDB_SEARCH_MODE_FPR)
+           && !memcmp (fprbin, desc.u.fpr, 20))
+    ;
+  else
+    {
+      log_error (_("\"%s\" is not the primary fingerprint\n"), fpr);
+      err = gpg_error (GPG_ERR_INV_NAME);
+      goto leave;
+    }
+
+  *r_keyblock = keyblock;
+  keyblock = NULL;
+  *r_kdbhd = kdbhd;
+  kdbhd = NULL;
+  err = 0;
+
+ leave:
+  release_kbnode (keyblock);
+  keydb_release (kdbhd);
+  return err;
+}
+
+
 /* Unattended key signing function.  If the key specifified by FPR is
    available and FPR is the primary fingerprint all user ids of the
    key are signed using the default signing key.  If UIDS is an empty
@@ -2940,7 +3021,6 @@ keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
   kbnode_t keyblock = NULL;
   KEYDB_HANDLE kdbhd = NULL;
   int modified = 0;
-  KEYDB_SEARCH_DESC desc;
   PKT_public_key *pk;
   kbnode_t node;
   strlist_t sl;
@@ -2948,53 +3028,14 @@ keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
 
 #ifdef HAVE_W32_SYSTEM
   /* See keyedit_menu for why we need this.  */
-  check_trustdb_stale ();
+  check_trustdb_stale (ctrl);
 #endif
 
   /* We require a fingerprint because only this uniquely identifies a
      key and may thus be used to select a key for unattended key
      signing.  */
-  if (classify_user_id (fpr, &desc, 1)
-      || !(desc.mode == KEYDB_SEARCH_MODE_FPR
-           || desc.mode == KEYDB_SEARCH_MODE_FPR16
-           || desc.mode == KEYDB_SEARCH_MODE_FPR20))
-    {
-      log_error (_("\"%s\" is not a fingerprint\n"), fpr);
-      goto leave;
-    }
-  err = get_pubkey_byname (ctrl, NULL, NULL, fpr, &keyblock, &kdbhd, 1, 1);
-  if (err)
-    {
-      log_error (_("key \"%s\" not found: %s\n"), fpr, gpg_strerror (err));
-      goto leave;
-    }
-
-  /* Check that the primary fingerprint has been given. */
-  {
-    byte fprbin[MAX_FINGERPRINT_LEN];
-    size_t fprlen;
-
-    fingerprint_from_pk (keyblock->pkt->pkt.public_key, fprbin, &fprlen);
-    if (fprlen == 16 && desc.mode == KEYDB_SEARCH_MODE_FPR16
-        && !memcmp (fprbin, desc.u.fpr, 16))
-      ;
-    else if (fprlen == 16 && desc.mode == KEYDB_SEARCH_MODE_FPR
-             && !memcmp (fprbin, desc.u.fpr, 16)
-             && !desc.u.fpr[16]
-             && !desc.u.fpr[17]
-             && !desc.u.fpr[18]
-             && !desc.u.fpr[19])
-      ;
-    else if (fprlen == 20 && (desc.mode == KEYDB_SEARCH_MODE_FPR20
-                              || desc.mode == KEYDB_SEARCH_MODE_FPR)
-             && !memcmp (fprbin, desc.u.fpr, 20))
-      ;
-    else
-      {
-        log_error (_("\"%s\" is not the primary fingerprint\n"), fpr);
-        goto leave;
-      }
-  }
+  if (find_by_primary_fpr (ctrl, fpr, &keyblock, &kdbhd))
+    goto leave;
 
   if (fix_keyblock (&keyblock))
     modified++;
@@ -3120,6 +3161,67 @@ keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
 }
 
 
+/* Unattended subkey creation function.
+ *
+ */
+void
+keyedit_quick_addkey (ctrl_t ctrl, const char *fpr, const char *algostr,
+                      const char *usagestr, const char *expirestr)
+{
+  gpg_error_t err;
+  kbnode_t keyblock;
+  KEYDB_HANDLE kdbhd;
+  int modified = 0;
+  PKT_public_key *pk;
+
+#ifdef HAVE_W32_SYSTEM
+  /* See keyedit_menu for why we need this.  */
+  check_trustdb_stale (ctrl);
+#endif
+
+  /* We require a fingerprint because only this uniquely identifies a
+   * key and may thus be used to select a key for unattended subkey
+   * creation.  */
+  if (find_by_primary_fpr (ctrl, fpr, &keyblock, &kdbhd))
+    goto leave;
+
+  if (fix_keyblock (&keyblock))
+    modified++;
+
+  pk = keyblock->pkt->pkt.public_key;
+  if (pk->flags.revoked)
+    {
+      if (!opt.verbose)
+        show_key_with_all_names (ctrl, es_stdout, keyblock, 0, 0, 0, 0, 0, 1);
+      log_error ("%s%s", _("Key is revoked."), "\n");
+      goto leave;
+    }
+
+  /* Create the subkey.  Noet that the called function already prints
+   * an error message. */
+  if (!generate_subkeypair (ctrl, keyblock, algostr, usagestr, expirestr))
+    modified = 1;
+  es_fflush (es_stdout);
+
+  /* Store.  */
+  if (modified)
+    {
+      err = keydb_update_keyblock (kdbhd, keyblock);
+      if (err)
+        {
+          log_error (_("update failed: %s\n"), gpg_strerror (err));
+          goto leave;
+        }
+    }
+  else
+    log_info (_("Key not changed so no update needed.\n"));
+
+ leave:
+  release_kbnode (keyblock);
+  keydb_release (kdbhd);
+}
+
+
 \f
 static void
 tty_print_notations (int indent, PKT_signature * sig)
@@ -3363,7 +3465,7 @@ show_key_with_all_names_colon (ctrl_t ctrl, estream_t fp, kbnode_t keyblock)
            es_putc ('e', fp);
          else if (!(opt.fast_list_mode || opt.no_expensive_trust_checks))
            {
-             int trust = get_validity_info (pk, NULL);
+             int trust = get_validity_info (ctrl, pk, NULL);
              if (trust == 'u')
                ulti_hack = 1;
              es_putc (trust, fp);
@@ -3422,7 +3524,7 @@ show_key_with_all_names_colon (ctrl_t ctrl, estream_t fp, kbnode_t keyblock)
              int uid_validity;
 
              if (primary && !ulti_hack)
-               uid_validity = get_validity_info (primary, uid);
+               uid_validity = get_validity_info (ctrl, primary, uid);
              else
                uid_validity = 'u';
              es_fprintf (fp, "%c::::::::", uid_validity);
@@ -3476,7 +3578,7 @@ show_key_with_all_names_colon (ctrl_t ctrl, estream_t fp, kbnode_t keyblock)
            {
 #ifdef USE_TOFU
              enum tofu_policy policy;
-             if (! tofu_get_policy (primary, uid, &policy)
+             if (! tofu_get_policy (ctrl, primary, uid, &policy)
                  && policy != TOFU_POLICY_NONE)
                es_fprintf (fp, "%s", tofu_policy_str (policy));
 #endif /*USE_TOFU*/
@@ -3489,8 +3591,8 @@ show_key_with_all_names_colon (ctrl_t ctrl, estream_t fp, kbnode_t keyblock)
 
 
 static void
-show_names (estream_t fp,
-            KBNODE keyblock, PKT_public_key * pk, unsigned int flag,
+show_names (ctrl_t ctrl, estream_t fp,
+            kbnode_t keyblock, PKT_public_key * pk, unsigned int flag,
            int with_prefs)
 {
   KBNODE node;
@@ -3505,7 +3607,7 @@ show_names (estream_t fp,
          if (!flag || (flag && (node->flag & flag)))
            {
              if (!(flag & NODFLG_MARK_A) && pk)
-               tty_fprintf (fp, "%s ", uid_trust_string_fixed (pk, uid));
+               tty_fprintf (fp, "%s ", uid_trust_string_fixed (ctrl, pk, uid));
 
              if (flag & NODFLG_MARK_A)
                tty_fprintf (fp, "     ");
@@ -3592,12 +3694,12 @@ show_key_with_all_names (ctrl_t ctrl, estream_t fp,
               * output */
              static int did_warn = 0;
 
-             trust = get_validity_string (pk, NULL);
+             trust = get_validity_string (ctrl, pk, NULL);
              otrust = get_ownertrust_string (pk);
 
              /* Show a warning once */
              if (!did_warn
-                 && (get_validity (pk, NULL, NULL, 0)
+                 && (get_validity (ctrl, pk, NULL, NULL, 0)
                      & TRUST_FLAG_PENDING_CHECK))
                {
                  did_warn = 1;
@@ -3664,7 +3766,7 @@ show_key_with_all_names (ctrl_t ctrl, estream_t fp,
                 have_seckey = 0;
               }
             else
-              have_seckey = !agent_get_keyinfo (ctrl, hexgrip, &serialno);
+              have_seckey = !agent_get_keyinfo (ctrl, hexgrip, &serialno, NULL);
             xfree (hexgrip);
           }
 
@@ -3784,7 +3886,7 @@ show_key_with_all_names (ctrl_t ctrl, estream_t fp,
        }
     }
 
-  show_names (fp,
+  show_names (ctrl, fp,
               keyblock, primary, only_marked ? NODFLG_MARK_A : 0, with_prefs);
 
   if (do_warn && !nowarn)
@@ -4029,8 +4131,8 @@ subkey_expire_warning (kbnode_t keyblock)
  * user id.
  */
 static int
-menu_adduid (kbnode_t pub_keyblock, int photo, const char *photo_name,
-             const char *uidstring)
+menu_adduid (ctrl_t ctrl, kbnode_t pub_keyblock,
+             int photo, const char *photo_name, const char *uidstring)
 {
   PKT_user_id *uid;
   PKT_public_key *pk = NULL;
@@ -4052,7 +4154,7 @@ menu_adduid (kbnode_t pub_keyblock, int photo, const char *photo_name,
     }
   if (!node) /* No subkey.  */
     pub_where = NULL;
-  assert (pk);
+  log_assert (pk);
 
   if (photo)
     {
@@ -4092,7 +4194,7 @@ menu_adduid (kbnode_t pub_keyblock, int photo, const char *photo_name,
            }
        }
 
-      uid = generate_photo_id (pk, photo_name);
+      uid = generate_photo_id (ctrl, pk, photo_name);
     }
   else
     uid = generate_user_id (pub_keyblock, uidstring);
@@ -4349,7 +4451,7 @@ menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive)
   size_t fprlen;
   int rc;
 
-  assert (pub_keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
+  log_assert (pub_keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
 
   pk = pub_keyblock->pkt->pkt.public_key;
 
@@ -4736,7 +4838,7 @@ menu_backsign (KBNODE pub_keyblock)
   KBNODE node;
   u32 timestamp;
 
-  assert (pub_keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
+  log_assert (pub_keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
 
   merge_keys_and_selfsig (pub_keyblock);
   main_pk = pub_keyblock->pkt->pkt.public_key;
@@ -5485,7 +5587,7 @@ menu_select_uid_namehash (KBNODE keyblock, const char *namehash)
   KBNODE node;
   int i;
 
-  assert (strlen (namehash) == NAMEHASH_LEN * 2);
+  log_assert (strlen (namehash) == NAMEHASH_LEN * 2);
 
   for (i = 0; i < NAMEHASH_LEN; i++)
     hash[i] = hextobyte (&namehash[i * 2]);
@@ -5819,7 +5921,7 @@ menu_revsig (KBNODE keyblock)
   int rc, any, skip = 1, all = !count_selected_uids (keyblock);
   struct revocation_reason_info *reason = NULL;
 
-  assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
+  log_assert (keyblock->pkt->pkttype == PKT_PUBLIC_KEY);
 
   /* First check whether we have any signatures at all.  */
   any = 0;
@@ -5960,7 +6062,7 @@ reloop:                   /* (must use this, because we are modifing the list) */
          || node->pkt->pkttype != PKT_SIGNATURE)
        continue;
       unode = find_prev_kbnode (keyblock, node, PKT_USER_ID);
-      assert (unode);          /* we already checked this */
+      log_assert (unode); /* we already checked this */
 
       memset (&attrib, 0, sizeof attrib);
       attrib.reason = reason;
@@ -6007,7 +6109,7 @@ reloop:                   /* (must use this, because we are modifing the list) */
 /* Revoke a user ID (i.e. revoke a user ID selfsig).  Return true if
    keyblock changed.  */
 static int
-menu_revuid (KBNODE pub_keyblock)
+menu_revuid (ctrl_t ctrl, kbnode_t pub_keyblock)
 {
   PKT_public_key *pk = pub_keyblock->pkt->pkt.public_key;
   KBNODE node;
@@ -6088,7 +6190,7 @@ menu_revuid (KBNODE pub_keyblock)
                /* If the trustdb has an entry for this key+uid then the
                   trustdb needs an update. */
                if (!update_trust
-                   && (get_validity (pk, uid, NULL, 0) & TRUST_MASK) >=
+                   && (get_validity (ctrl, pk, uid, NULL, 0) & TRUST_MASK) >=
                    TRUST_UNDEFINED)
                  update_trust = 1;
 #endif /*!NO_TRUST_MODELS*/
@@ -6250,7 +6352,7 @@ enable_disable_key (KBNODE keyblock, int disable)
 
 
 static void
-menu_showphoto (KBNODE keyblock)
+menu_showphoto (ctrl_t ctrl, kbnode_t keyblock)
 {
   KBNODE node;
   int select_all = !count_selected_uids (keyblock);
@@ -6287,7 +6389,7 @@ menu_showphoto (KBNODE keyblock)
                                    "key %s (uid %d)\n"),
                                  image_type_to_string (type, 1),
                                  (ulong) size, keystr_from_pk (pk), count);
-                     show_photos (&uid->attribs[i], 1, pk, uid);
+                     show_photos (ctrl, &uid->attribs[i], 1, pk, uid);
                    }
                }
            }