Merge branch 'STABLE-BRANCH-2-2' into master
[gnupg.git] / g10 / keyedit.c
index cfbbed7..2cb9bb2 100644 (file)
@@ -1,7 +1,7 @@
 /* keyedit.c - Edit properties of a key
  * Copyright (C) 1998-2010 Free Software Foundation, Inc.
 /* keyedit.c - Edit properties of a key
  * Copyright (C) 1998-2010 Free Software Foundation, Inc.
- * Copyright (C) 1998-2015 Werner Koch
- * Copyright (C) 2015 g10 Code GmbH
+ * Copyright (C) 1998-2017 Werner Koch
+ * Copyright (C) 2015, 2016 g10 Code GmbH
  *
  * This file is part of GnuPG.
  *
  *
  * This file is part of GnuPG.
  *
@@ -16,7 +16,7 @@
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * GNU General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
  */
 
 #include <config.h>
  */
 
 #include <config.h>
@@ -24,7 +24,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
 #include <stdlib.h>
 #include <string.h>
 #include <errno.h>
-#include <assert.h>
 #include <ctype.h>
 #ifdef HAVE_LIBREADLINE
 # define GNUPG_LIBREADLINE_H_INCLUDED
 #include <ctype.h>
 #ifdef HAVE_LIBREADLINE
 # define GNUPG_LIBREADLINE_H_INCLUDED
 #include "gpg.h"
 #include "options.h"
 #include "packet.h"
 #include "gpg.h"
 #include "options.h"
 #include "packet.h"
-#include "status.h"
-#include "iobuf.h"
+#include "../common/status.h"
+#include "../common/iobuf.h"
 #include "keydb.h"
 #include "photoid.h"
 #include "keydb.h"
 #include "photoid.h"
-#include "util.h"
+#include "../common/util.h"
 #include "main.h"
 #include "trustdb.h"
 #include "filter.h"
 #include "main.h"
 #include "trustdb.h"
 #include "filter.h"
-#include "ttyio.h"
-#include "status.h"
-#include "i18n.h"
+#include "../common/ttyio.h"
+#include "../common/status.h"
+#include "../common/i18n.h"
 #include "keyserver-internal.h"
 #include "call-agent.h"
 #include "keyserver-internal.h"
 #include "call-agent.h"
-#include "host2net.h"
+#include "../common/host2net.h"
 #include "tofu.h"
 #include "tofu.h"
+#include "key-check.h"
+#include "keyedit.h"
 
 static void show_prefs (PKT_user_id * uid, PKT_signature * selfsig,
                        int verbose);
 
 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,
                                     int with_revoker, int with_fpr,
                                     int with_subkeys, int with_prefs,
                                      int nowarn);
                        unsigned int flag, int with_prefs);
 static void show_key_with_all_names (ctrl_t ctrl, estream_t fp,
                                      KBNODE keyblock, int only_marked,
                                     int with_revoker, int with_fpr,
                                     int with_subkeys, int with_prefs,
                                      int nowarn);
-static void show_key_and_fingerprint (kbnode_t keyblock, int with_subkeys);
+static void show_key_and_fingerprint (ctrl_t ctrl,
+                                      kbnode_t keyblock, int with_subkeys);
 static void show_key_and_grip (kbnode_t keyblock);
 static void subkey_expire_warning (kbnode_t keyblock);
 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 void menu_deluid (KBNODE pub_keyblock);
-static int menu_delsig (KBNODE pub_keyblock);
-static int menu_clean (KBNODE keyblock, int self_only);
+static int menu_delsig (ctrl_t ctrl, kbnode_t pub_keyblock);
+static int menu_clean (ctrl_t ctrl, kbnode_t keyblock, int self_only);
 static void menu_delkey (KBNODE pub_keyblock);
 static int menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive);
 static void menu_delkey (KBNODE pub_keyblock);
 static int menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive);
-static int menu_expire (KBNODE pub_keyblock);
-static int menu_backsign (KBNODE pub_keyblock);
-static int menu_set_primary_uid (KBNODE pub_keyblock);
-static int menu_set_preferences (KBNODE pub_keyblock);
-static int menu_set_keyserver_url (const char *url, KBNODE pub_keyblock);
-static int menu_set_notation (const char *string, KBNODE pub_keyblock);
+static gpg_error_t menu_expire (ctrl_t ctrl, kbnode_t pub_keyblock,
+                                int unattended, u32 newexpiration);
+static int menu_changeusage (ctrl_t ctrl, kbnode_t keyblock);
+static int menu_backsign (ctrl_t ctrl, kbnode_t pub_keyblock);
+static int menu_set_primary_uid (ctrl_t ctrl, kbnode_t pub_keyblock);
+static int menu_set_preferences (ctrl_t ctrl, kbnode_t pub_keyblock);
+static int menu_set_keyserver_url (ctrl_t ctrl,
+                                   const char *url, kbnode_t pub_keyblock);
+static int menu_set_notation (ctrl_t ctrl,
+                              const char *string, kbnode_t pub_keyblock);
 static int menu_select_uid (KBNODE keyblock, int idx);
 static int menu_select_uid_namehash (KBNODE keyblock, const char *namehash);
 static int menu_select_key (KBNODE keyblock, int idx, char *p);
 static int menu_select_uid (KBNODE keyblock, int idx);
 static int menu_select_uid_namehash (KBNODE keyblock, const char *namehash);
 static int menu_select_key (KBNODE keyblock, int idx, char *p);
@@ -84,30 +91,22 @@ static int count_keys_with_flag (KBNODE keyblock, unsigned flag);
 static int count_selected_uids (KBNODE keyblock);
 static int real_uids_left (KBNODE keyblock);
 static int count_selected_keys (KBNODE keyblock);
 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_revkey (KBNODE pub_keyblock);
-static int menu_revsubkey (KBNODE pub_keyblock);
+static int menu_revsig (ctrl_t ctrl, kbnode_t keyblock);
+static int menu_revuid (ctrl_t ctrl, kbnode_t keyblock);
+static int core_revuid (ctrl_t ctrl, kbnode_t keyblock, KBNODE node,
+                        const struct revocation_reason_info *reason,
+                        int *modified);
+static int menu_revkey (ctrl_t ctrl, kbnode_t pub_keyblock);
+static int menu_revsubkey (ctrl_t ctrl, kbnode_t pub_keyblock);
 #ifndef NO_TRUST_MODELS
 #ifndef NO_TRUST_MODELS
-static int enable_disable_key (KBNODE keyblock, int disable);
+static int enable_disable_key (ctrl_t ctrl, kbnode_t keyblock, int disable);
 #endif /*!NO_TRUST_MODELS*/
 #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;
 
 #define CONTROL_D ('D' - 'A' + 1)
 
 
 static int update_trust = 0;
 
 #define CONTROL_D ('D' - 'A' + 1)
 
-#define NODFLG_BADSIG (1<<0)   /* Bad signature.  */
-#define NODFLG_NOKEY  (1<<1)   /* No public key.  */
-#define NODFLG_SIGERR (1<<2)   /* Other sig error.  */
-
-#define NODFLG_MARK_A (1<<4)   /* Temporary mark.  */
-#define NODFLG_DELSIG (1<<5)   /* To be deleted.  */
-
-#define NODFLG_SELUID (1<<8)   /* Indicate the selected userid. */
-#define NODFLG_SELKEY (1<<9)   /* Indicate the selected key.  */
-#define NODFLG_SELSIG (1<<10)  /* Indicate a selected signature.  */
-
 struct sign_attrib
 {
   int non_exportable, non_revocable;
 struct sign_attrib
 {
   int non_exportable, non_revocable;
@@ -121,7 +120,7 @@ struct sign_attrib
 /* TODO: Fix duplicated code between here and the check-sigs/list-sigs
    code in keylist.c. */
 static int
 /* TODO: Fix duplicated code between here and the check-sigs/list-sigs
    code in keylist.c. */
 static int
-print_and_check_one_sig_colon (KBNODE keyblock, KBNODE node,
+print_and_check_one_sig_colon (ctrl_t ctrl, kbnode_t keyblock, kbnode_t node,
                               int *inv_sigs, int *no_key, int *oth_err,
                               int *is_selfsig, int print_without_key)
 {
                               int *inv_sigs, int *no_key, int *oth_err,
                               int *is_selfsig, int print_without_key)
 {
@@ -131,7 +130,7 @@ print_and_check_one_sig_colon (KBNODE keyblock, KBNODE node,
   /* TODO: Make sure a cached sig record here still has the pk that
      issued it.  See also keylist.c:list_keyblock_print */
 
   /* TODO: Make sure a cached sig record here still has the pk that
      issued it.  See also keylist.c:list_keyblock_print */
 
-  rc = check_key_signature (keyblock, node, is_selfsig);
+  rc = check_key_signature (ctrl, keyblock, node, is_selfsig);
   switch (gpg_err_code (rc))
     {
     case 0:
   switch (gpg_err_code (rc))
     {
     case 0:
@@ -188,24 +187,24 @@ print_and_check_one_sig_colon (KBNODE keyblock, KBNODE node,
 
 
 /*
 
 
 /*
- * Print information about a signature, check it and return true if
- * the signature is okay.  NODE must be a signature packet.  With
- * EXTENDED set all possible signature list options will always be
- * printed.
+ * Print information about a signature (rc is its status), check it
+ * and return true if the signature is okay.  NODE must be a signature
+ * packet.  With EXTENDED set all possible signature list options will
+ * always be printed.
  */
  */
-static int
-print_and_check_one_sig (KBNODE keyblock, KBNODE node,
-                        int *inv_sigs, int *no_key, int *oth_err,
-                        int *is_selfsig, int print_without_key, int extended)
+int
+keyedit_print_one_sig (ctrl_t ctrl, estream_t fp,
+                       int rc, kbnode_t keyblock, kbnode_t node,
+                      int *inv_sigs, int *no_key, int *oth_err,
+                      int is_selfsig, int print_without_key, int extended)
 {
   PKT_signature *sig = node->pkt->pkt.signature;
 {
   PKT_signature *sig = node->pkt->pkt.signature;
-  int rc, sigrc;
+  int sigrc;
   int is_rev = sig->sig_class == 0x30;
 
   /* TODO: Make sure a cached sig record here still has the pk that
      issued it.  See also keylist.c:list_keyblock_print */
 
   int is_rev = sig->sig_class == 0x30;
 
   /* TODO: Make sure a cached sig record here still has the pk that
      issued it.  See also keylist.c:list_keyblock_print */
 
-  rc = check_key_signature (keyblock, node, is_selfsig);
   switch (gpg_err_code (rc))
     {
     case 0:
   switch (gpg_err_code (rc))
     {
     case 0:
@@ -234,7 +233,7 @@ print_and_check_one_sig (KBNODE keyblock, KBNODE node,
     }
   if (sigrc != '?' || print_without_key)
     {
     }
   if (sigrc != '?' || print_without_key)
     {
-      tty_printf ("%s%c%c %c%c%c%c%c%c %s %s",
+      tty_fprintf (fp, "%s%c%c %c%c%c%c%c%c %s %s",
                  is_rev ? "rev" : "sig", sigrc,
                  (sig->sig_class - 0x10 > 0 &&
                   sig->sig_class - 0x10 <
                  is_rev ? "rev" : "sig", sigrc,
                  (sig->sig_class - 0x10 > 0 &&
                   sig->sig_class - 0x10 <
@@ -250,38 +249,41 @@ print_and_check_one_sig (KBNODE keyblock, KBNODE node,
                   keystr (sig->keyid),
                  datestr_from_sig (sig));
       if ((opt.list_options & LIST_SHOW_SIG_EXPIRE) || extended )
                   keystr (sig->keyid),
                  datestr_from_sig (sig));
       if ((opt.list_options & LIST_SHOW_SIG_EXPIRE) || extended )
-       tty_printf (" %s", expirestr_from_sig (sig));
-      tty_printf ("  ");
+       tty_fprintf (fp, " %s", expirestr_from_sig (sig));
+      tty_fprintf (fp, "  ");
       if (sigrc == '%')
       if (sigrc == '%')
-       tty_printf ("[%s] ", gpg_strerror (rc));
+       tty_fprintf (fp, "[%s] ", gpg_strerror (rc));
       else if (sigrc == '?')
        ;
       else if (sigrc == '?')
        ;
-      else if (*is_selfsig)
+      else if (is_selfsig)
        {
        {
-         tty_printf (is_rev ? _("[revocation]") : _("[self-signature]"));
+         tty_fprintf (fp, is_rev ? _("[revocation]") : _("[self-signature]"));
           if (extended && sig->flags.chosen_selfsig)
           if (extended && sig->flags.chosen_selfsig)
-            tty_printf ("*");
+            tty_fprintf (fp, "*");
        }
       else
        {
          size_t n;
        }
       else
        {
          size_t n;
-         char *p = get_user_id (sig->keyid, &n);
-         tty_print_utf8_string2 (NULL, p, n,
+         char *p = get_user_id (ctrl, sig->keyid, &n);
+         tty_print_utf8_string2 (fp, p, n,
                                  opt.screen_columns - keystrlen () - 26 -
                                  ((opt.
                                    list_options & LIST_SHOW_SIG_EXPIRE) ? 11
                                   : 0));
          xfree (p);
        }
                                  opt.screen_columns - keystrlen () - 26 -
                                  ((opt.
                                    list_options & LIST_SHOW_SIG_EXPIRE) ? 11
                                   : 0));
          xfree (p);
        }
-      tty_printf ("\n");
+      if (fp == log_get_stream ())
+        log_printf ("\n");
+      else
+        tty_fprintf (fp, "\n");
 
       if (sig->flags.policy_url
           && ((opt.list_options & LIST_SHOW_POLICY_URLS) || extended))
 
       if (sig->flags.policy_url
           && ((opt.list_options & LIST_SHOW_POLICY_URLS) || extended))
-       show_policy_url (sig, 3, 0);
+       show_policy_url (sig, 3, (!fp? -1 : fp == log_get_stream ()? 1 : 0));
 
       if (sig->flags.notation
           && ((opt.list_options & LIST_SHOW_NOTATIONS) || extended))
 
       if (sig->flags.notation
           && ((opt.list_options & LIST_SHOW_NOTATIONS) || extended))
-       show_notation (sig, 3, 0,
+       show_notation (sig, 3, (!fp? -1 : fp == log_get_stream ()? 1 : 0),
                       ((opt.
                         list_options & LIST_SHOW_STD_NOTATIONS) ? 1 : 0) +
                       ((opt.
                       ((opt.
                         list_options & LIST_SHOW_STD_NOTATIONS) ? 1 : 0) +
                       ((opt.
@@ -289,7 +291,7 @@ print_and_check_one_sig (KBNODE keyblock, KBNODE node,
 
       if (sig->flags.pref_ks
           && ((opt.list_options & LIST_SHOW_KEYSERVER_URLS) || extended))
 
       if (sig->flags.pref_ks
           && ((opt.list_options & LIST_SHOW_KEYSERVER_URLS) || extended))
-       show_keyserver_url (sig, 3, 0);
+       show_keyserver_url (sig, 3, (!fp? -1 : fp == log_get_stream ()? 1 : 0));
 
       if (extended)
         {
 
       if (extended)
         {
@@ -298,12 +300,12 @@ print_and_check_one_sig (KBNODE keyblock, KBNODE node,
 
           s = parse_sig_subpkt (sig->hashed, SIGSUBPKT_PRIMARY_UID, NULL);
           if (s && *s)
 
           s = parse_sig_subpkt (sig->hashed, SIGSUBPKT_PRIMARY_UID, NULL);
           if (s && *s)
-            tty_printf ("             [primary]\n");
+            tty_fprintf (fp, "             [primary]\n");
 
           s = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL);
           if (s && buf32_to_u32 (s))
 
           s = parse_sig_subpkt (sig->hashed, SIGSUBPKT_KEY_EXPIRE, NULL);
           if (s && buf32_to_u32 (s))
-            tty_printf ("             [expires: %s]\n",
-                        isotimestamp (pk->timestamp + buf32_to_u32 (s)));
+            tty_fprintf (fp, "             [expires: %s]\n",
+                         isotimestamp (pk->timestamp + buf32_to_u32 (s)));
         }
     }
 
         }
     }
 
@@ -311,90 +313,17 @@ print_and_check_one_sig (KBNODE keyblock, KBNODE node,
 }
 
 
 }
 
 
-
-/*
- * Check the keysigs and set the flags to indicate errors.
- * Returns true if error found.
- */
 static int
 static int
-check_all_keysigs (KBNODE keyblock, int only_selected, int only_selfsigs)
+print_and_check_one_sig (ctrl_t ctrl, kbnode_t keyblock, kbnode_t node,
+                        int *inv_sigs, int *no_key, int *oth_err,
+                        int *is_selfsig, int print_without_key, int extended)
 {
 {
-  KBNODE kbctx;
-  KBNODE node;
-  int inv_sigs = 0;
-  int no_key = 0;
-  int oth_err = 0;
-  int has_selfsig = 0;
-  int mis_selfsig = 0;
-  int selected = !only_selected;
-  int anyuid = 0;
-  u32 keyid[2];
-
-  for (kbctx = NULL; (node = walk_kbnode (keyblock, &kbctx, 0));)
-    {
-      if (node->pkt->pkttype == PKT_PUBLIC_KEY)
-        {
-          if (only_selfsigs)
-            keyid_from_pk (node->pkt->pkt.public_key, keyid);
-        }
-      else if (node->pkt->pkttype == PKT_USER_ID)
-       {
-         PKT_user_id *uid = node->pkt->pkt.user_id;
+  int rc;
 
 
-         if (only_selected)
-           selected = (node->flag & NODFLG_SELUID);
-         if (selected)
-           {
-             tty_printf ("uid  ");
-             tty_print_utf8_string (uid->name, uid->len);
-             tty_printf ("\n");
-             if (anyuid && !has_selfsig)
-               mis_selfsig++;
-             has_selfsig = 0;
-             anyuid = 1;
-           }
-       }
-      else if (selected && node->pkt->pkttype == PKT_SIGNATURE
-              && ((node->pkt->pkt.signature->sig_class & ~3) == 0x10
-                  || node->pkt->pkt.signature->sig_class == 0x30))
-       {
-         int selfsig;
-          PKT_signature *sig = node->pkt->pkt.signature;
-
-          if (only_selfsigs
-              && !(keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]))
-            ;  /* Not a selfsig but we want only selfsigs - skip.  */
-         else if (print_and_check_one_sig (keyblock, node, &inv_sigs,
-                                            &no_key, &oth_err, &selfsig,
-                                            0, only_selfsigs))
-           {
-             if (selfsig)
-               has_selfsig = 1;
-           }
-         /* Hmmm: should we update the trustdb here? */
-       }
-    }
-  if (!has_selfsig)
-    mis_selfsig++;
-  if (inv_sigs == 1)
-    tty_printf (_("1 bad signature\n"));
-  else if (inv_sigs)
-    tty_printf (_("%d bad signatures\n"), inv_sigs);
-  if (no_key == 1)
-    tty_printf (_("1 signature not checked due to a missing key\n"));
-  else if (no_key)
-    tty_printf (_("%d signatures not checked due to missing keys\n"), no_key);
-  if (oth_err == 1)
-    tty_printf (_("1 signature not checked due to an error\n"));
-  else if (oth_err)
-    tty_printf (_("%d signatures not checked due to errors\n"), oth_err);
-  if (mis_selfsig == 1)
-    tty_printf (_("1 user ID without valid self-signature detected\n"));
-  else if (mis_selfsig)
-    tty_printf (_("%d user IDs without valid self-signatures detected\n"),
-               mis_selfsig);
-
-  return inv_sigs || no_key || oth_err || mis_selfsig;
+  rc = check_key_signature (ctrl, keyblock, node, is_selfsig);
+  return keyedit_print_one_sig (ctrl, NULL, rc,
+                               keyblock, node, inv_sigs, no_key, oth_err,
+                               *is_selfsig, print_without_key, extended);
 }
 
 
 }
 
 
@@ -475,7 +404,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"
   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");
 
                "trust signatures on your behalf.\n"));
   tty_printf ("\n");
 
@@ -540,7 +470,7 @@ trustsig_prompt (byte * trust_value, byte * trust_depth, char **regexp)
 
 
 /*
 
 
 /*
- * Loop over all LOCUSR and and sign the uids after asking.  If no
+ * Loop over all LOCUSR and sign the uids after asking.  If no
  * user id is marked, all user ids will be signed; if some user_ids
  * are marked only those will be signed.  If QUICK is true the
  * function won't ask the user and use sensible defaults.
  * user id is marked, all user ids will be signed; if some user_ids
  * are marked only those will be signed.  If QUICK is true the
  * function won't ask the user and use sensible defaults.
@@ -624,7 +554,7 @@ sign_uids (ctrl_t ctrl, estream_t fp,
                       uidnode->flag &= ~NODFLG_MARK_A;
                       uidnode = NULL;
                     }
                       uidnode->flag &= ~NODFLG_MARK_A;
                       uidnode = NULL;
                     }
-                 else if (uidnode->pkt->pkt.user_id->is_revoked)
+                 else if (uidnode->pkt->pkt.user_id->flags.revoked)
                    {
                      tty_fprintf (fp, _("User ID \"%s\" is revoked."), user);
 
                    {
                      tty_fprintf (fp, _("User ID \"%s\" is revoked."), user);
 
@@ -652,7 +582,7 @@ sign_uids (ctrl_t ctrl, estream_t fp,
                          tty_fprintf (fp, _("  Unable to sign.\n"));
                        }
                    }
                          tty_fprintf (fp, _("  Unable to sign.\n"));
                        }
                    }
-                 else if (uidnode->pkt->pkt.user_id->is_expired)
+                 else if (uidnode->pkt->pkt.user_id->flags.expired)
                    {
                      tty_fprintf (fp, _("User ID \"%s\" is expired."), user);
 
                    {
                      tty_fprintf (fp, _("User ID \"%s\" is expired."), user);
 
@@ -810,7 +740,7 @@ sign_uids (ctrl_t ctrl, estream_t fp,
                    }
 
                  /* Fixme: see whether there is a revocation in which
                    }
 
                  /* Fixme: see whether there is a revocation in which
-                  * case we should allow to sign it again. */
+                  * case we should allow signing it again. */
                  if (!node->pkt->pkt.signature->flags.exportable && local)
                    tty_fprintf ( fp,
                        _("\"%s\" was already locally signed by key %s\n"),
                  if (!node->pkt->pkt.signature->flags.exportable && local)
                    tty_fprintf ( fp,
                        _("\"%s\" was already locally signed by key %s\n"),
@@ -856,6 +786,14 @@ sign_uids (ctrl_t ctrl, estream_t fp,
 
       if (primary_pk->expiredate && !selfsig)
        {
 
       if (primary_pk->expiredate && !selfsig)
        {
+          /* Static analyzer note: A claim that PRIMARY_PK might be
+             NULL is not correct because it set from the public key
+             packet which is always the first packet in a keyblock and
+             parsed in the above loop over the keyblock.  In case the
+             keyblock has no packets at all and thus the loop was not
+             entered the above count_uids_with_flag would have
+             detected this case.  */
+
          u32 now = make_timestamp ();
 
          if (primary_pk->expiredate <= now)
          u32 now = make_timestamp ();
 
          if (primary_pk->expiredate <= now)
@@ -969,7 +907,7 @@ sign_uids (ctrl_t ctrl, estream_t fp,
 
       if (!quick)
         {
 
       if (!quick)
         {
-          p = get_user_id_native (sk_keyid);
+          p = get_user_id_native (ctrl, sk_keyid);
           tty_fprintf (fp,
                    _("Are you sure that you want to sign this key with your\n"
                      "key \"%s\" (%s)\n"), p, keystr_from_pk (pk));
           tty_fprintf (fp,
                    _("Are you sure that you want to sign this key with your\n"
                      "key \"%s\" (%s)\n"), p, keystr_from_pk (pk));
@@ -1041,7 +979,7 @@ sign_uids (ctrl_t ctrl, estream_t fp,
        continue;
 
       /* Now we can sign the user ids.  */
        continue;
 
       /* Now we can sign the user ids.  */
-    reloop:  /* (Must use this, because we are modifing the list.)  */
+    reloop:  /* (Must use this, because we are modifying the list.)  */
       primary_pk = NULL;
       for (node = keyblock; node; node = node->next)
        {
       primary_pk = NULL;
       for (node = keyblock; node; node = node->next)
        {
@@ -1054,7 +992,7 @@ sign_uids (ctrl_t ctrl, estream_t fp,
              PKT_signature *sig;
              struct sign_attrib attrib;
 
              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;
              memset (&attrib, 0, sizeof attrib);
              attrib.non_exportable = local;
              attrib.non_revocable = nonrevocable;
@@ -1069,7 +1007,7 @@ sign_uids (ctrl_t ctrl, estream_t fp,
               * exportable.  */
 
              if (selfsig)
               * exportable.  */
 
              if (selfsig)
-               rc = make_keysig_packet (&sig, primary_pk,
+               rc = make_keysig_packet (ctrl, &sig, primary_pk,
                                         node->pkt->pkt.user_id,
                                         NULL,
                                         pk,
                                         node->pkt->pkt.user_id,
                                         NULL,
                                         pk,
@@ -1077,7 +1015,7 @@ sign_uids (ctrl_t ctrl, estream_t fp,
                                         keygen_add_std_prefs, primary_pk,
                                          NULL);
              else
                                         keygen_add_std_prefs, primary_pk,
                                          NULL);
              else
-               rc = make_keysig_packet (&sig, primary_pk,
+               rc = make_keysig_packet (ctrl, &sig, primary_pk,
                                         node->pkt->pkt.user_id,
                                         NULL,
                                         pk,
                                         node->pkt->pkt.user_id,
                                         NULL,
                                         pk,
@@ -1159,7 +1097,7 @@ change_passphrase (ctrl_t ctrl, kbnode_t keyblock)
           err = hexkeygrip_from_pk (pk, &hexgrip);
           if (err)
             goto leave;
           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)
           if (!err && serialno)
             ; /* Key on card.  */
           else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
@@ -1181,7 +1119,7 @@ change_passphrase (ctrl_t ctrl, kbnode_t keyblock)
     }
 
   /* Change the passphrase for all keys.  */
     }
 
   /* Change the passphrase for all keys.  */
-  for (any = 0, node = keyblock; node; node = node->next)
+  for (node = keyblock; node; node = node->next)
     {
       if (node->pkt->pkttype == PKT_PUBLIC_KEY
          || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
     {
       if (node->pkt->pkttype == PKT_PUBLIC_KEY
          || node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
@@ -1196,14 +1134,17 @@ change_passphrase (ctrl_t ctrl, kbnode_t keyblock)
           if (err)
             goto leave;
 
           if (err)
             goto leave;
 
-          desc = gpg_format_keydesc (pk, FORMAT_KEYDESC_NORMAL, 1);
-          err = agent_passwd (ctrl, hexgrip, desc, &cache_nonce, &passwd_nonce);
+          /* Note that when using --dry-run we don't change the
+           * passphrase but merely verify the current passphrase.  */
+          desc = gpg_format_keydesc (ctrl, pk, FORMAT_KEYDESC_NORMAL, 1);
+          err = agent_passwd (ctrl, hexgrip, desc, !!opt.dry_run,
+                              &cache_nonce, &passwd_nonce);
           xfree (desc);
 
           if (err)
             log_log ((gpg_err_code (err) == GPG_ERR_CANCELED
                       || gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
           xfree (desc);
 
           if (err)
             log_log ((gpg_err_code (err) == GPG_ERR_CANCELED
                       || gpg_err_code (err) == GPG_ERR_FULLY_CANCELED)
-                     ? GPGRT_LOG_INFO : GPGRT_LOG_ERROR,
+                     ? GPGRT_LOGLVL_INFO : GPGRT_LOGLVL_ERROR,
                      _("key %s: error changing passphrase: %s\n"),
                        keystr_with_sub (keyid, subid),
                        gpg_strerror (err));
                      _("key %s: error changing passphrase: %s\n"),
                        keystr_with_sub (keyid, subid),
                        gpg_strerror (err));
@@ -1221,70 +1162,22 @@ change_passphrase (ctrl_t ctrl, kbnode_t keyblock)
 
 
 \f
 
 
 \f
-/*
- * There are some keys out (due to a bug in gnupg), where the sequence
- * of the packets is wrong.  This function fixes that.
- * Returns: true if the keyblock has been fixed.
- *
- * Note:  This function does not work if there is more than one user ID.
- */
-static int
-fix_key_signature_order (KBNODE keyblock)
-{
-  KBNODE node, last, subkey;
-  int fixed = 0;
-
-  /* Locate key signatures of class 0x10..0x13 behind sub key packets.  */
-  for (subkey = last = NULL, node = keyblock; node;
-       last = node, node = node->next)
-    {
-      switch (node->pkt->pkttype)
-       {
-       case PKT_PUBLIC_SUBKEY:
-       case PKT_SECRET_SUBKEY:
-         if (!subkey)
-           subkey = last; /* Actually it is the one before the subkey.  */
-         break;
-       case PKT_SIGNATURE:
-         if (subkey)
-           {
-             PKT_signature *sig = node->pkt->pkt.signature;
-             if (sig->sig_class >= 0x10 && sig->sig_class <= 0x13)
-               {
-                 log_info (_("moving a key signature to the correct place\n"));
-                 last->next = node->next;
-                 node->next = subkey->next;
-                 subkey->next = node;
-                 node = last;
-                 fixed = 1;
-               }
-           }
-         break;
-       default:
-         break;
-       }
-    }
-
-  return fixed;
-}
-
-
 /* Fix various problems in the keyblock.  Returns true if the keyblock
    was changed.  Note that a pointer to the keyblock must be given and
    the function may change it (i.e. replacing the first node).  */
 static int
 /* Fix various problems in the keyblock.  Returns true if the keyblock
    was changed.  Note that a pointer to the keyblock must be given and
    the function may change it (i.e. replacing the first node).  */
 static int
-fix_keyblock (kbnode_t *keyblockp)
+fix_keyblock (ctrl_t ctrl, kbnode_t *keyblockp)
 {
   int changed = 0;
 
 {
   int changed = 0;
 
-  if (fix_key_signature_order (*keyblockp))
-    changed++;
   if (collapse_uids (keyblockp))
     changed++;
   if (collapse_uids (keyblockp))
     changed++;
+  if (key_check_all_keysigs (ctrl, 1, *keyblockp, 0, 1))
+    changed++;
   reorder_keyblock (*keyblockp);
   /* If we modified the keyblock, make sure the flags are right. */
   if (changed)
   reorder_keyblock (*keyblockp);
   /* If we modified the keyblock, make sure the flags are right. */
   if (changed)
-    merge_keys_and_selfsig (*keyblockp);
+    merge_keys_and_selfsig (ctrl, *keyblockp);
 
   return changed;
 }
 
   return changed;
 }
@@ -1332,10 +1225,8 @@ parse_sign_type (const char *str, int *localsig, int *nonrevokesig,
 
 /* Need an SK for this command */
 #define KEYEDIT_NEED_SK 1
 
 /* Need an SK for this command */
 #define KEYEDIT_NEED_SK 1
-/* Cannot be viewing the SK for this command */
-#define KEYEDIT_NOT_SK  2
-/* Must be viewing the SK for this command */
-#define KEYEDIT_ONLY_SK 4
+/* Need an SUB KEY for this command */
+#define KEYEDIT_NEED_SUBSK 2
 /* Match the tail of the string */
 #define KEYEDIT_TAIL_MATCH 8
 
 /* Match the tail of the string */
 #define KEYEDIT_TAIL_MATCH 8
 
@@ -1346,13 +1237,13 @@ enum cmdids
   cmdREVSIG, cmdREVKEY, cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG,
   cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY,
   cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
   cmdREVSIG, cmdREVKEY, cmdREVUID, cmdDELSIG, cmdPRIMARY, cmdDEBUG,
   cmdSAVE, cmdADDUID, cmdADDPHOTO, cmdDELUID, cmdADDKEY, cmdDELKEY,
   cmdADDREVOKER, cmdTOGGLE, cmdSELKEY, cmdPASSWD, cmdTRUST, cmdPREF,
-  cmdEXPIRE, cmdBACKSIGN,
+  cmdEXPIRE, cmdCHANGEUSAGE, cmdBACKSIGN,
 #ifndef NO_TRUST_MODELS
   cmdENABLEKEY, cmdDISABLEKEY,
 #endif /*!NO_TRUST_MODELS*/
   cmdSHOWPREF,
   cmdSETPREF, cmdPREFKS, cmdNOTATION, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST,
 #ifndef NO_TRUST_MODELS
   cmdENABLEKEY, cmdDISABLEKEY,
 #endif /*!NO_TRUST_MODELS*/
   cmdSHOWPREF,
   cmdSETPREF, cmdPREFKS, cmdNOTATION, cmdINVCMD, cmdSHOWPHOTO, cmdUPDTRUST,
-  cmdCHKTRUST, cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD, cmdCHECKBKUPKEY,
+  cmdCHKTRUST, cmdADDCARDKEY, cmdKEYTOCARD, cmdBKUPTOCARD,
   cmdCLEAN, cmdMINIMIZE, cmdGRIP, cmdNOP
 };
 
   cmdCLEAN, cmdMINIMIZE, cmdGRIP, cmdNOP
 };
 
@@ -1377,11 +1268,12 @@ static struct
   { "key", cmdSELKEY, 0, N_("select subkey N")},
   { "check", cmdCHECK, 0, N_("check signatures")},
   { "c", cmdCHECK, 0, NULL},
   { "key", cmdSELKEY, 0, N_("select subkey N")},
   { "check", cmdCHECK, 0, N_("check signatures")},
   { "c", cmdCHECK, 0, NULL},
-  { "cross-certify", cmdBACKSIGN, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL},
-  { "backsign", cmdBACKSIGN, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL},
-  { "sign", cmdSIGN, KEYEDIT_NOT_SK | KEYEDIT_TAIL_MATCH,
+  { "change-usage", cmdCHANGEUSAGE, KEYEDIT_NEED_SK, NULL},
+  { "cross-certify", cmdBACKSIGN, KEYEDIT_NEED_SK, NULL},
+  { "backsign", cmdBACKSIGN,  KEYEDIT_NEED_SK, NULL},
+  { "sign", cmdSIGN,  KEYEDIT_TAIL_MATCH,
     N_("sign selected user IDs [* see below for related commands]")},
     N_("sign selected user IDs [* see below for related commands]")},
-  { "s", cmdSIGN, KEYEDIT_NOT_SK, NULL},
+  { "s", cmdSIGN, 0, NULL},
     /* "lsign" and friends will never match since "sign" comes first
        and it is a tail match.  They are just here so they show up in
        the help menu. */
     /* "lsign" and friends will never match since "sign" comes first
        and it is a tail match.  They are just here so they show up in
        the help menu. */
@@ -1390,63 +1282,62 @@ static struct
   { "nrsign", cmdNOP, 0,
     N_("sign selected user IDs with a non-revocable signature")},
   { "debug", cmdDEBUG, 0, NULL},
   { "nrsign", cmdNOP, 0,
     N_("sign selected user IDs with a non-revocable signature")},
   { "debug", cmdDEBUG, 0, NULL},
-  { "adduid", cmdADDUID, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, N_("add a user ID")},
-  { "addphoto", cmdADDPHOTO, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
+  { "adduid", cmdADDUID,  KEYEDIT_NEED_SK, N_("add a user ID")},
+  { "addphoto", cmdADDPHOTO,  KEYEDIT_NEED_SK,
     N_("add a photo ID")},
     N_("add a photo ID")},
-  { "deluid", cmdDELUID, KEYEDIT_NOT_SK, N_("delete selected user IDs")},
+  { "deluid", cmdDELUID, 0, N_("delete selected user IDs")},
     /* delphoto is really deluid in disguise */
     /* delphoto is really deluid in disguise */
-  { "delphoto", cmdDELUID, KEYEDIT_NOT_SK, NULL},
-  { "addkey", cmdADDKEY, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, N_("add a subkey")},
+  { "delphoto", cmdDELUID, 0, NULL},
+  { "addkey", cmdADDKEY,  KEYEDIT_NEED_SK, N_("add a subkey")},
 #ifdef ENABLE_CARD_SUPPORT
 #ifdef ENABLE_CARD_SUPPORT
-  { "addcardkey", cmdADDCARDKEY, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
+  { "addcardkey", cmdADDCARDKEY,  KEYEDIT_NEED_SK,
     N_("add a key to a smartcard")},
     N_("add a key to a smartcard")},
-  { "keytocard", cmdKEYTOCARD, KEYEDIT_NEED_SK | KEYEDIT_ONLY_SK,
+  { "keytocard", cmdKEYTOCARD, KEYEDIT_NEED_SK | KEYEDIT_NEED_SUBSK,
     N_("move a key to a smartcard")},
     N_("move a key to a smartcard")},
-  { "bkuptocard", cmdBKUPTOCARD, KEYEDIT_NEED_SK | KEYEDIT_ONLY_SK,
+  { "bkuptocard", cmdBKUPTOCARD, KEYEDIT_NEED_SK | KEYEDIT_NEED_SUBSK,
     N_("move a backup key to a smartcard")},
     N_("move a backup key to a smartcard")},
-  { "checkbkupkey", cmdCHECKBKUPKEY, KEYEDIT_NEED_SK | KEYEDIT_ONLY_SK, NULL},
 #endif /*ENABLE_CARD_SUPPORT */
 #endif /*ENABLE_CARD_SUPPORT */
-  { "delkey", cmdDELKEY, KEYEDIT_NOT_SK, N_("delete selected subkeys")},
-  { "addrevoker", cmdADDREVOKER, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
+  { "delkey", cmdDELKEY, 0, N_("delete selected subkeys")},
+  { "addrevoker", cmdADDREVOKER,  KEYEDIT_NEED_SK,
     N_("add a revocation key")},
     N_("add a revocation key")},
-  { "delsig", cmdDELSIG, KEYEDIT_NOT_SK,
+  { "delsig", cmdDELSIG, 0,
     N_("delete signatures from the selected user IDs")},
     N_("delete signatures from the selected user IDs")},
-  { "expire", cmdEXPIRE, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
+  { "expire", cmdEXPIRE,  KEYEDIT_NEED_SK | KEYEDIT_NEED_SUBSK,
     N_("change the expiration date for the key or selected subkeys")},
     N_("change the expiration date for the key or selected subkeys")},
-  { "primary", cmdPRIMARY, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
+  { "primary", cmdPRIMARY,  KEYEDIT_NEED_SK,
     N_("flag the selected user ID as primary")},
   { "toggle", cmdTOGGLE, KEYEDIT_NEED_SK, NULL},  /* Dummy command.  */
   { "t", cmdTOGGLE, KEYEDIT_NEED_SK, NULL},
     N_("flag the selected user ID as primary")},
   { "toggle", cmdTOGGLE, KEYEDIT_NEED_SK, NULL},  /* Dummy command.  */
   { "t", cmdTOGGLE, KEYEDIT_NEED_SK, NULL},
-  { "pref", cmdPREF, KEYEDIT_NOT_SK, N_("list preferences (expert)")},
-  { "showpref", cmdSHOWPREF, KEYEDIT_NOT_SK, N_("list preferences (verbose)")},
-  { "setpref", cmdSETPREF, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
+  { "pref", cmdPREF, 0, N_("list preferences (expert)")},
+  { "showpref", cmdSHOWPREF, 0, N_("list preferences (verbose)")},
+  { "setpref", cmdSETPREF,  KEYEDIT_NEED_SK,
     N_("set preference list for the selected user IDs")},
     N_("set preference list for the selected user IDs")},
-  { "updpref", cmdSETPREF, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL},
-  { "keyserver", cmdPREFKS, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
+  { "updpref", cmdSETPREF,  KEYEDIT_NEED_SK, NULL},
+  { "keyserver", cmdPREFKS,  KEYEDIT_NEED_SK,
     N_("set the preferred keyserver URL for the selected user IDs")},
     N_("set the preferred keyserver URL for the selected user IDs")},
-  { "notation", cmdNOTATION, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
+  { "notation", cmdNOTATION,  KEYEDIT_NEED_SK,
     N_("set a notation for the selected user IDs")},
     N_("set a notation for the selected user IDs")},
-  { "passwd", cmdPASSWD, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
+  { "passwd", cmdPASSWD,  KEYEDIT_NEED_SK | KEYEDIT_NEED_SUBSK,
     N_("change the passphrase")},
     N_("change the passphrase")},
-  { "password", cmdPASSWD, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL},
+  { "password", cmdPASSWD,  KEYEDIT_NEED_SK | KEYEDIT_NEED_SUBSK, NULL},
 #ifndef NO_TRUST_MODELS
 #ifndef NO_TRUST_MODELS
-  { "trust", cmdTRUST, KEYEDIT_NOT_SK, N_("change the ownertrust")},
+  { "trust", cmdTRUST, 0, N_("change the ownertrust")},
 #endif /*!NO_TRUST_MODELS*/
 #endif /*!NO_TRUST_MODELS*/
-  { "revsig", cmdREVSIG, KEYEDIT_NOT_SK,
+  { "revsig", cmdREVSIG, 0,
     N_("revoke signatures on the selected user IDs")},
     N_("revoke signatures on the selected user IDs")},
-  { "revuid", cmdREVUID, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
+  { "revuid", cmdREVUID,  KEYEDIT_NEED_SK,
     N_("revoke selected user IDs")},
     N_("revoke selected user IDs")},
-  { "revphoto", cmdREVUID, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK, NULL},
-  { "revkey", cmdREVKEY, KEYEDIT_NOT_SK | KEYEDIT_NEED_SK,
+  { "revphoto", cmdREVUID,  KEYEDIT_NEED_SK, NULL},
+  { "revkey", cmdREVKEY,  KEYEDIT_NEED_SK,
     N_("revoke key or selected subkeys")},
 #ifndef NO_TRUST_MODELS
     N_("revoke key or selected subkeys")},
 #ifndef NO_TRUST_MODELS
-  { "enable", cmdENABLEKEY, KEYEDIT_NOT_SK, N_("enable key")},
-  { "disable", cmdDISABLEKEY, KEYEDIT_NOT_SK, N_("disable key")},
+  { "enable", cmdENABLEKEY, 0, N_("enable key")},
+  { "disable", cmdDISABLEKEY, 0, N_("disable key")},
 #endif /*!NO_TRUST_MODELS*/
   { "showphoto", cmdSHOWPHOTO, 0, N_("show selected photo IDs")},
 #endif /*!NO_TRUST_MODELS*/
   { "showphoto", cmdSHOWPHOTO, 0, N_("show selected photo IDs")},
-  { "clean", cmdCLEAN, KEYEDIT_NOT_SK,
+  { "clean", cmdCLEAN, 0,
     N_("compact unusable user IDs and remove unusable signatures from key")},
     N_("compact unusable user IDs and remove unusable signatures from key")},
-  { "minimize", cmdMINIMIZE, KEYEDIT_NOT_SK,
+  { "minimize", cmdMINIMIZE, 0,
     N_("compact unusable user IDs and remove all signatures from key")},
 
   { NULL, cmdNONE, 0, NULL}
     N_("compact unusable user IDs and remove all signatures from key")},
 
   { NULL, cmdNONE, 0, NULL}
@@ -1515,6 +1406,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
   KBNODE keyblock = NULL;
   KEYDB_HANDLE kdbhd = NULL;
   int have_seckey = 0;
   KBNODE keyblock = NULL;
   KEYDB_HANDLE kdbhd = NULL;
   int have_seckey = 0;
+  int have_anyseckey = 0;
   char *answer = NULL;
   int redisplay = 1;
   int modified = 0;
   char *answer = NULL;
   int redisplay = 1;
   int modified = 0;
@@ -1540,7 +1432,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 ().  */
      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 */
 #endif
 
   /* Get the public key */
@@ -1551,15 +1443,24 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
       goto leave;
     }
 
       goto leave;
     }
 
-  if (fix_keyblock (&keyblock))
+  if (fix_keyblock (ctrl, &keyblock))
     modified++;
 
   /* See whether we have a matching secret key.  */
   if (seckey_check)
     {
     modified++;
 
   /* See whether we have a matching secret key.  */
   if (seckey_check)
     {
-      have_seckey = !agent_probe_any_secret_key (ctrl, keyblock);
+      have_anyseckey = !agent_probe_any_secret_key (ctrl, keyblock);
+      if (have_anyseckey
+          && !agent_probe_secret_key (ctrl, keyblock->pkt->pkt.public_key))
+        {
+          /* The primary key is also available.   */
+          have_seckey = 1;
+        }
+
       if (have_seckey && !quiet)
       if (have_seckey && !quiet)
-       tty_printf (_("Secret key is available.\n"));
+        tty_printf (_("Secret key is available.\n"));
+      else if (have_anyseckey && !quiet)
+        tty_printf (_("Secret subkeys are available.\n"));
     }
 
   /* Main command loop.  */
     }
 
   /* Main command loop.  */
@@ -1657,12 +1558,14 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
              else if (!ascii_strcasecmp (answer, cmds[i].name))
                break;
            }
              else if (!ascii_strcasecmp (answer, cmds[i].name))
                break;
            }
-         if ((cmds[i].flags & KEYEDIT_NEED_SK) && !have_seckey)
+         if ((cmds[i].flags & (KEYEDIT_NEED_SK|KEYEDIT_NEED_SUBSK))
+              && !(((cmds[i].flags & KEYEDIT_NEED_SK) && have_seckey)
+                   || ((cmds[i].flags & KEYEDIT_NEED_SUBSK) && have_anyseckey)))
            {
              tty_printf (_("Need the secret key to do this.\n"));
              cmd = cmdNOP;
            }
            {
              tty_printf (_("Need the secret key to do this.\n"));
              cmd = cmdNOP;
            }
-         else
+          else
            cmd = cmds[i].id;
        }
 
            cmd = cmds[i].id;
        }
 
@@ -1672,7 +1575,9 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
        case cmdHELP:
          for (i = 0; cmds[i].name; i++)
            {
        case cmdHELP:
          for (i = 0; cmds[i].name; i++)
            {
-             if ((cmds[i].flags & KEYEDIT_NEED_SK) && !have_seckey)
+              if ((cmds[i].flags & (KEYEDIT_NEED_SK|KEYEDIT_NEED_SUBSK))
+                  && !(((cmds[i].flags & KEYEDIT_NEED_SK) && have_seckey)
+                       ||((cmds[i].flags&KEYEDIT_NEED_SUBSK)&&have_anyseckey)))
                ; /* Skip those item if we do not have the secret key.  */
              else if (cmds[i].desc)
                tty_printf ("%-11s %s\n", cmds[i].name, _(cmds[i].desc));
                ; /* Skip those item if we do not have the secret key.  */
              else if (cmds[i].desc)
                tty_printf ("%-11s %s\n", cmds[i].name, _(cmds[i].desc));
@@ -1694,7 +1599,8 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
 
        case cmdFPR:
          show_key_and_fingerprint
 
        case cmdFPR:
          show_key_and_fingerprint
-            (keyblock, (*arg_string == '*'
+            (ctrl,
+             keyblock, (*arg_string == '*'
                         && (!arg_string[1] || spacep (arg_string + 1))));
          break;
 
                         && (!arg_string[1] || spacep (arg_string + 1))));
          break;
 
@@ -1725,8 +1631,10 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
          break;
 
        case cmdCHECK:
          break;
 
        case cmdCHECK:
-         check_all_keysigs (keyblock, count_selected_uids (keyblock),
-                             !strcmp (arg_string, "selfsig"));
+         if (key_check_all_keysigs (ctrl, -1, keyblock,
+                                    count_selected_uids (keyblock),
+                                    !strcmp (arg_string, "selfsig")))
+            modified = 1;
          break;
 
        case cmdSIGN:
          break;
 
        case cmdSIGN:
@@ -1758,11 +1666,11 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
                 if (opt.only_sign_text_ids)
                   result = cpr_get_answer_is_yes
                     ("keyedit.sign_all.okay",
                 if (opt.only_sign_text_ids)
                   result = cpr_get_answer_is_yes
                     ("keyedit.sign_all.okay",
-                     _("Really sign all user IDs? (y/N) "));
+                     _("Really sign all text user IDs? (y/N) "));
                 else
                   result = cpr_get_answer_is_yes
                     ("keyedit.sign_all.okay",
                 else
                   result = cpr_get_answer_is_yes
                     ("keyedit.sign_all.okay",
-                     _("Really sign all text user IDs? (y/N) "));
+                     _("Really sign all user IDs? (y/N) "));
 
                 if (! result)
                   {
 
                 if (! result)
                   {
@@ -1806,18 +1714,18 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
          if (RFC2440)
            {
              tty_printf (_("This command is not allowed while in %s mode.\n"),
          if (RFC2440)
            {
              tty_printf (_("This command is not allowed while in %s mode.\n"),
-                         compliance_option_string ());
+                         gnupg_compliance_option_string (opt.compliance));
              break;
            }
          photo = 1;
          /* fall through */
        case cmdADDUID:
              break;
            }
          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;
              modified = 1;
            {
              update_trust = 1;
              redisplay = 1;
              modified = 1;
-             merge_keys_and_selfsig (keyblock);
+             merge_keys_and_selfsig (ctrl, keyblock);
            }
          break;
 
            }
          break;
 
@@ -1855,7 +1763,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
                 if (!opt.expert)
                   tty_printf (_("(Use the '%s' command.)\n"), "uid");
               }
                 if (!opt.expert)
                   tty_printf (_("(Use the '%s' command.)\n"), "uid");
               }
-           else if (menu_delsig (keyblock))
+           else if (menu_delsig (ctrl, keyblock))
              {
                /* No redisplay here, because it may scroll away some
                 * of the status output of this command.  */
              {
                /* No redisplay here, because it may scroll away some
                 * of the status output of this command.  */
@@ -1865,21 +1773,21 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
          break;
 
        case cmdADDKEY:
          break;
 
        case cmdADDKEY:
-         if (!generate_subkeypair (ctrl, keyblock))
+         if (!generate_subkeypair (ctrl, keyblock, NULL, NULL, NULL))
            {
              redisplay = 1;
              modified = 1;
            {
              redisplay = 1;
              modified = 1;
-             merge_keys_and_selfsig (keyblock);
+             merge_keys_and_selfsig (ctrl, keyblock);
            }
          break;
 
 #ifdef ENABLE_CARD_SUPPORT
        case cmdADDCARDKEY:
            }
          break;
 
 #ifdef ENABLE_CARD_SUPPORT
        case cmdADDCARDKEY:
-         if (!card_generate_subkey (keyblock))
+         if (!card_generate_subkey (ctrl, keyblock))
            {
              redisplay = 1;
              modified = 1;
            {
              redisplay = 1;
              modified = 1;
-             merge_keys_and_selfsig (keyblock);
+             merge_keys_and_selfsig (ctrl, keyblock);
            }
          break;
 
            }
          break;
 
@@ -1921,7 +1829,6 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
          break;
 
        case cmdBKUPTOCARD:
          break;
 
        case cmdBKUPTOCARD:
-       case cmdCHECKBKUPKEY:
          {
            /* Ask for a filename, check whether this is really a
               backup key as generated by the card generation, parse
          {
            /* Ask for a filename, check whether this is really a
               backup key as generated by the card generation, parse
@@ -1930,6 +1837,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
            char *fname;
            PACKET *pkt;
            IOBUF a;
            char *fname;
            PACKET *pkt;
            IOBUF a;
+            struct parse_packet_ctx_s parsectx;
 
             if (!*arg_string)
              {
 
             if (!*arg_string)
              {
@@ -1942,7 +1850,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
             else if (*arg_string == '~')
               fname = make_filename (arg_string, NULL);
             else
             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);
 
            /* Open that file.  */
            a = iobuf_open (fname);
@@ -1963,8 +1871,10 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
            /* Parse and check that file.  */
            pkt = xmalloc (sizeof *pkt);
            init_packet (pkt);
            /* Parse and check that file.  */
            pkt = xmalloc (sizeof *pkt);
            init_packet (pkt);
-           err = parse_packet (a, pkt);
-           iobuf_close (a);
+            init_parse_packet (&parsectx, a);
+           err = parse_packet (&parsectx, pkt);
+           deinit_parse_packet (&parsectx);
+            iobuf_close (a);
            iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char *) fname);
            if (!err && pkt->pkttype != PKT_SECRET_KEY
                && pkt->pkttype != PKT_SECRET_SUBKEY)
            iobuf_ioctl (NULL, IOBUF_IOCTL_INVALIDATE_CACHE, 0, (char *) fname);
            if (!err && pkt->pkttype != PKT_SECRET_KEY
                && pkt->pkttype != PKT_SECRET_SUBKEY)
@@ -1974,7 +1884,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
                 tty_printf (_("Error reading backup key from '%s': %s\n"),
                             fname, gpg_strerror (err));
                 xfree (fname);
                 tty_printf (_("Error reading backup key from '%s': %s\n"),
                             fname, gpg_strerror (err));
                 xfree (fname);
-                free_packet (pkt);
+                free_packet (pkt, NULL);
                 xfree (pkt);
                 break;
               }
                 xfree (pkt);
                 break;
               }
@@ -1982,47 +1892,21 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
            xfree (fname);
            node = new_kbnode (pkt);
 
            xfree (fname);
            node = new_kbnode (pkt);
 
-           if (cmd == cmdCHECKBKUPKEY)
-             {
-               log_debug ("FIXME: This needs to be changed\n");
-               /* PKT_public_key *sk = node->pkt->pkt.secret_key; */
-               /* switch (is_secret_key_protected (sk)) */
-               /*   { */
-               /*   case 0:    /\* Not protected. *\/ */
-               /*     tty_printf (_("This key is not protected.\n")); */
-               /*     break; */
-               /*   case -1: */
-               /*     log_error (_("unknown key protection algorithm\n")); */
-               /*     break; */
-               /*   default: */
-               /*     if (sk->protect.s2k.mode == 1001) */
-               /*       tty_printf (_("Secret parts of key" */
-               /*                  " are not available.\n")); */
-               /*     if (sk->protect.s2k.mode == 1002) */
-               /*       tty_printf (_("Secret parts of key" */
-               /*                  " are stored on-card.\n")); */
-                   /* else */
-                   /*   check_secret_key (sk, 0); */
-                 /* } */
-             }
-           else                /* Store it.  */
-              {
-                /* We need to transfer it to gpg-agent.  */
-                err = transfer_secret_keys (ctrl, NULL, node, 1);
+            /* Transfer it to gpg-agent which handles secret keys.  */
+            err = transfer_secret_keys (ctrl, NULL, node, 1, 1);
 
 
-                /* Then, treat the pkt as a public key to call
-                   card_store_subkey.  */
-                pkt->pkttype = PKT_PUBLIC_KEY;
+            /* Treat the pkt as a public key.  */
+            pkt->pkttype = PKT_PUBLIC_KEY;
 
 
-                if (card_store_subkey (node, 0))
-                  {
-                    redisplay = 1;
-                    sec_shadowing = 1;
-                  }
+            /* Ask gpg-agent to store the secret key to card.  */
+            if (card_store_subkey (node, 0))
+              {
+                redisplay = 1;
+                sec_shadowing = 1;
               }
             release_kbnode (node);
               }
             release_kbnode (node);
-         }
-         break;
+          }
+          break;
 
 #endif /* ENABLE_CARD_SUPPORT */
 
 
 #endif /* ENABLE_CARD_SUPPORT */
 
@@ -2061,7 +1945,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
              {
                redisplay = 1;
                modified = 1;
              {
                redisplay = 1;
                modified = 1;
-               merge_keys_and_selfsig (keyblock);
+               merge_keys_and_selfsig (ctrl, keyblock);
              }
          }
          break;
              }
          }
          break;
@@ -2081,7 +1965,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) ")))
              {
                       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;
                  {
                    modified = 1;
                    redisplay = 1;
@@ -2100,7 +1984,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
                                           _("Do you really want to revoke"
                                             " the entire key? (y/N) ")))
                  {
                                           _("Do you really want to revoke"
                                             " the entire key? (y/N) ")))
                  {
-                   if (menu_revkey (keyblock))
+                   if (menu_revkey (ctrl, keyblock))
                      modified = 1;
 
                    redisplay = 1;
                      modified = 1;
 
                    redisplay = 1;
@@ -2113,29 +1997,38 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
                                            : _("Do you really want to revoke"
                                                " this subkey? (y/N) ")))
              {
                                            : _("Do you really want to revoke"
                                                " this subkey? (y/N) ")))
              {
-               if (menu_revsubkey (keyblock))
+               if (menu_revsubkey (ctrl, keyblock))
                  modified = 1;
 
                redisplay = 1;
              }
 
            if (modified)
                  modified = 1;
 
                redisplay = 1;
              }
 
            if (modified)
-             merge_keys_and_selfsig (keyblock);
+             merge_keys_and_selfsig (ctrl, keyblock);
          }
          break;
 
        case cmdEXPIRE:
          }
          break;
 
        case cmdEXPIRE:
-         if (menu_expire (keyblock))
+         if (gpg_err_code (menu_expire (ctrl, keyblock, 0, 0)) == GPG_ERR_TRUE)
            {
            {
-             merge_keys_and_selfsig (keyblock);
+             merge_keys_and_selfsig (ctrl, keyblock);
               run_subkey_warnings = 1;
              modified = 1;
              redisplay = 1;
            }
          break;
 
               run_subkey_warnings = 1;
              modified = 1;
              redisplay = 1;
            }
          break;
 
+       case cmdCHANGEUSAGE:
+         if (menu_changeusage (ctrl, keyblock))
+           {
+             merge_keys_and_selfsig (ctrl, keyblock);
+             modified = 1;
+             redisplay = 1;
+           }
+         break;
+
        case cmdBACKSIGN:
        case cmdBACKSIGN:
-         if (menu_backsign (keyblock))
+         if (menu_backsign (ctrl, keyblock))
            {
              modified = 1;
              redisplay = 1;
            {
              modified = 1;
              redisplay = 1;
@@ -2143,9 +2036,9 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
          break;
 
        case cmdPRIMARY:
          break;
 
        case cmdPRIMARY:
-         if (menu_set_primary_uid (keyblock))
+         if (menu_set_primary_uid (ctrl, keyblock))
            {
            {
-             merge_keys_and_selfsig (keyblock);
+             merge_keys_and_selfsig (ctrl, keyblock);
              modified = 1;
              redisplay = 1;
            }
              modified = 1;
              redisplay = 1;
            }
@@ -2166,7 +2059,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");
 
          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))
            {
                                            PKT_PUBLIC_KEY)->pkt->pkt.
                               public_key, 1))
            {
@@ -2182,8 +2075,8 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
        case cmdPREF:
          {
            int count = count_selected_uids (keyblock);
        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;
                        count ? NODFLG_SELUID : 0, 1);
          }
          break;
@@ -2191,8 +2084,8 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
        case cmdSHOWPREF:
          {
            int count = count_selected_uids (keyblock);
        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;
                        count ? NODFLG_SELUID : 0, 2);
          }
          break;
@@ -2215,9 +2108,9 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
                    " for the selected user IDs? (y/N) ")
                  : _("Really update the preferences? (y/N) ")))
              {
                    " for the selected user IDs? (y/N) ")
                  : _("Really update the preferences? (y/N) ")))
              {
-               if (menu_set_preferences (keyblock))
+               if (menu_set_preferences (ctrl, keyblock))
                  {
                  {
-                   merge_keys_and_selfsig (keyblock);
+                   merge_keys_and_selfsig (ctrl, keyblock);
                    modified = 1;
                    redisplay = 1;
                  }
                    modified = 1;
                    redisplay = 1;
                  }
@@ -2226,20 +2119,20 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
          break;
 
        case cmdPREFKS:
          break;
 
        case cmdPREFKS:
-         if (menu_set_keyserver_url (*arg_string ? arg_string : NULL,
+         if (menu_set_keyserver_url (ctrl, *arg_string ? arg_string : NULL,
                                      keyblock))
            {
                                      keyblock))
            {
-             merge_keys_and_selfsig (keyblock);
+             merge_keys_and_selfsig (ctrl, keyblock);
              modified = 1;
              redisplay = 1;
            }
          break;
 
        case cmdNOTATION:
              modified = 1;
              redisplay = 1;
            }
          break;
 
        case cmdNOTATION:
-         if (menu_set_notation (*arg_string ? arg_string : NULL,
+         if (menu_set_notation (ctrl, *arg_string ? arg_string : NULL,
                                 keyblock))
            {
                                 keyblock))
            {
-             merge_keys_and_selfsig (keyblock);
+             merge_keys_and_selfsig (ctrl, keyblock);
              modified = 1;
              redisplay = 1;
            }
              modified = 1;
              redisplay = 1;
            }
@@ -2249,7 +2142,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
          break;
 
        case cmdREVSIG:
          break;
 
        case cmdREVSIG:
-         if (menu_revsig (keyblock))
+         if (menu_revsig (ctrl, keyblock))
            {
              redisplay = 1;
              modified = 1;
            {
              redisplay = 1;
              modified = 1;
@@ -2259,7 +2152,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
 #ifndef NO_TRUST_MODELS
        case cmdENABLEKEY:
        case cmdDISABLEKEY:
 #ifndef NO_TRUST_MODELS
        case cmdENABLEKEY:
        case cmdDISABLEKEY:
-         if (enable_disable_key (keyblock, cmd == cmdDISABLEKEY))
+         if (enable_disable_key (ctrl, keyblock, cmd == cmdDISABLEKEY))
            {
              redisplay = 1;
              modified = 1;
            {
              redisplay = 1;
              modified = 1;
@@ -2268,16 +2161,16 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
 #endif /*!NO_TRUST_MODELS*/
 
        case cmdSHOWPHOTO:
 #endif /*!NO_TRUST_MODELS*/
 
        case cmdSHOWPHOTO:
-         menu_showphoto (keyblock);
+         menu_showphoto (ctrl, keyblock);
          break;
 
        case cmdCLEAN:
          break;
 
        case cmdCLEAN:
-         if (menu_clean (keyblock, 0))
+         if (menu_clean (ctrl, keyblock, 0))
            redisplay = modified = 1;
          break;
 
        case cmdMINIMIZE:
            redisplay = modified = 1;
          break;
 
        case cmdMINIMIZE:
-         if (menu_clean (keyblock, 1))
+         if (menu_clean (ctrl, keyblock, 1))
            redisplay = modified = 1;
          break;
 
            redisplay = modified = 1;
          break;
 
@@ -2295,11 +2188,11 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
                goto leave;
              break;
            }
                goto leave;
              break;
            }
-         /* fall thru */
+         /* fall through */
        case cmdSAVE:
          if (modified)
            {
        case cmdSAVE:
          if (modified)
            {
-              err = keydb_update_keyblock (kdbhd, keyblock);
+              err = keydb_update_keyblock (ctrl, kdbhd, keyblock);
               if (err)
                 {
                   log_error (_("update failed: %s\n"), gpg_strerror (err));
               if (err)
                 {
                   log_error (_("update failed: %s\n"), gpg_strerror (err));
@@ -2322,7 +2215,7 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
 
          if (update_trust)
            {
 
          if (update_trust)
            {
-             revalidation_mark ();
+             revalidation_mark (ctrl);
              update_trust = 0;
            }
          goto leave;
              update_trust = 0;
            }
          goto leave;
@@ -2376,35 +2269,27 @@ leave:
 }
 
 
 }
 
 
-/* Unattended adding of a new keyid.  USERNAME specifies the
-   key. NEWUID is the new user id to add to the key.  */
-void
-keyedit_quick_adduid (ctrl_t ctrl, const char *username, const char *newuid)
+/* Helper for quick commands to find the keyblock for USERNAME.
+ * Returns on success the key database handle at R_KDBHD and the
+ * keyblock at R_KEYBLOCK.  */
+static gpg_error_t
+quick_find_keyblock (ctrl_t ctrl, const char *username,
+                     KEYDB_HANDLE *r_kdbhd, kbnode_t *r_keyblock)
 {
   gpg_error_t err;
   KEYDB_HANDLE kdbhd = NULL;
 {
   gpg_error_t err;
   KEYDB_HANDLE kdbhd = NULL;
-  KEYDB_SEARCH_DESC desc;
   kbnode_t keyblock = NULL;
   kbnode_t keyblock = NULL;
+  KEYDB_SEARCH_DESC desc;
   kbnode_t node;
   kbnode_t node;
-  char *uidstring = NULL;
 
 
-  uidstring = xstrdup (newuid);
-  trim_spaces (uidstring);
-  if (!*uidstring)
-    {
-      log_error ("%s\n", gpg_strerror (GPG_ERR_INV_USER_ID));
-      goto leave;
-    }
-
-#ifdef HAVE_W32_SYSTEM
-  /* See keyedit_menu for why we need this.  */
-  check_trustdb_stale ();
-#endif
+  *r_kdbhd = NULL;
+  *r_keyblock = NULL;
 
   /* Search the key; we don't want the whole getkey stuff here.  */
   kdbhd = keydb_new ();
   if (!kdbhd)
     {
 
   /* Search the key; we don't want the whole getkey stuff here.  */
   kdbhd = keydb_new ();
   if (!kdbhd)
     {
+      /* Note that keydb_new has already used log_error.  */
       err = gpg_error_from_syserror ();
       goto leave;
     }
       err = gpg_error_from_syserror ();
       goto leave;
     }
@@ -2433,25 +2318,68 @@ keyedit_quick_adduid (ctrl_t ctrl, const char *username, const char *newuid)
 
       if (!err)
         {
 
       if (!err)
         {
-          /* We require the secret primary key to add a UID.  */
+          /* We require the secret primary key to set the primary UID.  */
           node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
           node = find_kbnode (keyblock, PKT_PUBLIC_KEY);
-          if (!node)
-            BUG ();
+          log_assert (node);
           err = agent_probe_secret_key (ctrl, node->pkt->pkt.public_key);
         }
     }
           err = agent_probe_secret_key (ctrl, node->pkt->pkt.public_key);
         }
     }
+  else if (gpg_err_code (err) == GPG_ERR_NOT_FOUND)
+    err = gpg_error (GPG_ERR_NO_PUBKEY);
+
   if (err)
     {
   if (err)
     {
-      log_error (_("secret key \"%s\" not found: %s\n"),
+      log_error (_("key \"%s\" not found: %s\n"),
                  username, gpg_strerror (err));
       goto leave;
     }
 
                  username, gpg_strerror (err));
       goto leave;
     }
 
-  fix_keyblock (&keyblock);
+  fix_keyblock (ctrl, &keyblock);
+  merge_keys_and_selfsig (ctrl, keyblock);
+
+  *r_keyblock = keyblock;
+  keyblock = NULL;
+  *r_kdbhd = kdbhd;
+  kdbhd = NULL;
+
+ leave:
+  release_kbnode (keyblock);
+  keydb_release (kdbhd);
+  return err;
+}
+
+
+/* Unattended adding of a new keyid.  USERNAME specifies the
+   key. NEWUID is the new user id to add to the key.  */
+void
+keyedit_quick_adduid (ctrl_t ctrl, const char *username, const char *newuid)
+{
+  gpg_error_t err;
+  KEYDB_HANDLE kdbhd = NULL;
+  kbnode_t keyblock = NULL;
+  char *uidstring = NULL;
+
+  uidstring = xstrdup (newuid);
+  trim_spaces (uidstring);
+  if (!*uidstring)
+    {
+      log_error ("%s\n", gpg_strerror (GPG_ERR_INV_USER_ID));
+      goto leave;
+    }
+
+#ifdef HAVE_W32_SYSTEM
+  /* See keyedit_menu for why we need this.  */
+  check_trustdb_stale (ctrl);
+#endif
+
+  /* Search the key; we don't want the whole getkey stuff here.  */
+  err = quick_find_keyblock (ctrl, username, &kdbhd, &keyblock);
+  if (err)
+    goto leave;
 
 
-  if (menu_adduid (keyblock, 0, NULL, uidstring))
+  if (menu_adduid (ctrl, keyblock, 0, NULL, uidstring))
     {
     {
-      err = keydb_update_keyblock (kdbhd, keyblock);
+      err = keydb_update_keyblock (ctrl, kdbhd, keyblock);
       if (err)
         {
           log_error (_("update failed: %s\n"), gpg_strerror (err));
       if (err)
         {
           log_error (_("update failed: %s\n"), gpg_strerror (err));
@@ -2459,7 +2387,7 @@ keyedit_quick_adduid (ctrl_t ctrl, const char *username, const char *newuid)
         }
 
       if (update_trust)
         }
 
       if (update_trust)
-        revalidation_mark ();
+        revalidation_mark (ctrl);
     }
 
  leave:
     }
 
  leave:
@@ -2469,13 +2397,229 @@ keyedit_quick_adduid (ctrl_t ctrl, const char *username, const char *newuid)
 }
 
 
 }
 
 
+/* Unattended revocation of a keyid.  USERNAME specifies the
+   key. UIDTOREV is the user id revoke from the key.  */
+void
+keyedit_quick_revuid (ctrl_t ctrl, const char *username, const char *uidtorev)
+{
+  gpg_error_t err;
+  KEYDB_HANDLE kdbhd = NULL;
+  kbnode_t keyblock = NULL;
+  kbnode_t node;
+  int modified = 0;
+  size_t revlen;
+  size_t valid_uids;
+
+#ifdef HAVE_W32_SYSTEM
+  /* See keyedit_menu for why we need this.  */
+  check_trustdb_stale (ctrl);
+#endif
+
+  /* Search the key; we don't want the whole getkey stuff here.  */
+  err = quick_find_keyblock (ctrl, username, &kdbhd, &keyblock);
+  if (err)
+    goto leave;
+
+  /* Too make sure that we do not revoke the last valid UID, we first
+     count how many valid UIDs there are.  */
+  valid_uids = 0;
+  for (node = keyblock; node; node = node->next)
+    valid_uids += (node->pkt->pkttype == PKT_USER_ID
+                   && !node->pkt->pkt.user_id->flags.revoked
+                   && !node->pkt->pkt.user_id->flags.expired);
+
+  /* Find the right UID. */
+  revlen = strlen (uidtorev);
+  for (node = keyblock; node; node = node->next)
+    {
+      if (node->pkt->pkttype == PKT_USER_ID
+          && revlen == node->pkt->pkt.user_id->len
+          && !memcmp (node->pkt->pkt.user_id->name, uidtorev, revlen))
+        {
+          struct revocation_reason_info *reason;
+
+          /* Make sure that we do not revoke the last valid UID.  */
+          if (valid_uids == 1
+              && ! node->pkt->pkt.user_id->flags.revoked
+              && ! node->pkt->pkt.user_id->flags.expired)
+            {
+              log_error (_("cannot revoke the last valid user ID.\n"));
+              err = gpg_error (GPG_ERR_INV_USER_ID);
+              goto leave;
+            }
+
+          reason = get_default_uid_revocation_reason ();
+          err = core_revuid (ctrl, keyblock, node, reason, &modified);
+          release_revocation_reason_info (reason);
+          if (err)
+            goto leave;
+          err = keydb_update_keyblock (ctrl, kdbhd, keyblock);
+          if (err)
+            {
+              log_error (_("update failed: %s\n"), gpg_strerror (err));
+              goto leave;
+            }
+
+          revalidation_mark (ctrl);
+          goto leave;
+        }
+    }
+  err = gpg_error (GPG_ERR_NO_USER_ID);
+
+
+ leave:
+  if (err)
+    {
+      log_error (_("revoking the user ID failed: %s\n"), gpg_strerror (err));
+      write_status_error ("keyedit.revoke.uid", err);
+    }
+  release_kbnode (keyblock);
+  keydb_release (kdbhd);
+}
+
+
+/* Unattended setting of the primary uid.  USERNAME specifies the key.
+   PRIMARYUID is the user id which shall be primary.  */
+void
+keyedit_quick_set_primary (ctrl_t ctrl, const char *username,
+                           const char *primaryuid)
+{
+  gpg_error_t err;
+  KEYDB_HANDLE kdbhd = NULL;
+  kbnode_t keyblock = NULL;
+  kbnode_t node;
+  size_t primaryuidlen;
+  int any;
+
+#ifdef HAVE_W32_SYSTEM
+  /* See keyedit_menu for why we need this.  */
+  check_trustdb_stale (ctrl);
+#endif
+
+  err = quick_find_keyblock (ctrl, username, &kdbhd, &keyblock);
+  if (err)
+    goto leave;
+
+  /* Find and mark the UID - we mark only the first valid one. */
+  primaryuidlen = strlen (primaryuid);
+  any = 0;
+  for (node = keyblock; node; node = node->next)
+    {
+      if (node->pkt->pkttype == PKT_USER_ID
+          && !any
+          && !node->pkt->pkt.user_id->flags.revoked
+          && !node->pkt->pkt.user_id->flags.expired
+          && primaryuidlen == node->pkt->pkt.user_id->len
+          && !memcmp (node->pkt->pkt.user_id->name, primaryuid, primaryuidlen))
+        {
+          node->flag |= NODFLG_SELUID;
+          any = 1;
+        }
+      else
+        node->flag &= ~NODFLG_SELUID;
+    }
+
+  if (!any)
+    err = gpg_error (GPG_ERR_NO_USER_ID);
+  else if (menu_set_primary_uid (ctrl, keyblock))
+    {
+      merge_keys_and_selfsig (ctrl, keyblock);
+      err = keydb_update_keyblock (ctrl, kdbhd, keyblock);
+      if (err)
+        {
+          log_error (_("update failed: %s\n"), gpg_strerror (err));
+          goto leave;
+        }
+      revalidation_mark (ctrl);
+    }
+  else
+    err = gpg_error (GPG_ERR_GENERAL);
+
+  if (err)
+    log_error (_("setting the primary user ID failed: %s\n"),
+               gpg_strerror (err));
+
+ leave:
+  release_kbnode (keyblock);
+  keydb_release (kdbhd);
+}
+
+
+/* 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
 /* Unattended key signing function.  If the key specifified by FPR is
-   availabale and FPR is the primary fingerprint all user ids of the
-   user ids of the key are signed using the default signing key.  If
-   UIDS is an empty list all usable UIDs are signed, if it is not
-   empty, only those user ids matching one of the entries of the loist
-   are signed.  With LOCAL being true kthe signatures are marked as
-   non-exportable.  */
+   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
+   list all usable UIDs are signed, if it is not empty, only those
+   user ids matching one of the entries of the list are signed.  With
+   LOCAL being true the signatures are marked as non-exportable.  */
 void
 keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
                     strlist_t locusr, int local)
 void
 keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
                     strlist_t locusr, int local)
@@ -2484,7 +2628,6 @@ keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
   kbnode_t keyblock = NULL;
   KEYDB_HANDLE kdbhd = NULL;
   int modified = 0;
   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;
   PKT_public_key *pk;
   kbnode_t node;
   strlist_t sl;
@@ -2492,130 +2635,352 @@ keyedit_quick_sign (ctrl_t ctrl, const char *fpr, strlist_t uids,
 
 #ifdef HAVE_W32_SYSTEM
   /* See keyedit_menu for why we need this.  */
 
 #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.  */
 #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))
+  if (find_by_primary_fpr (ctrl, fpr, &keyblock, &kdbhd))
+    goto leave;
+
+  if (fix_keyblock (ctrl, &keyblock))
+    modified++;
+
+  /* Give some info in verbose.  */
+  if (opt.verbose)
     {
     {
-      log_error (_("\"%s\" is not a fingerprint\n"), fpr);
+      show_key_with_all_names (ctrl, es_stdout, keyblock, 0,
+                               1/*with_revoker*/, 1/*with_fingerprint*/,
+                               0, 0, 1);
+      es_fflush (es_stdout);
+    }
+
+  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."), _("  Unable to sign.\n"));
       goto leave;
     }
       goto leave;
     }
-  err = get_pubkey_byname (ctrl, NULL, NULL, fpr, &keyblock, &kdbhd, 1, 1);
-  if (err)
+
+  /* Set the flags according to the UIDS list.  Fixme: We may want to
+     use classify_user_id along with dedicated compare functions so
+     that we match the same way as in the key lookup. */
+  any = 0;
+  menu_select_uid (keyblock, 0);   /* Better clear the flags first. */
+  for (sl=uids; sl; sl = sl->next)
     {
     {
-      log_error (_("key \"%s\" not found: %s\n"), fpr, gpg_strerror (err));
+      const char *name = sl->d;
+      int count = 0;
+
+      sl->flags &= ~(1|2);  /* Clear flags used for error reporting.  */
+
+      for (node = keyblock; node; node = node->next)
+        {
+          if (node->pkt->pkttype == PKT_USER_ID)
+            {
+              PKT_user_id *uid = node->pkt->pkt.user_id;
+
+              if (uid->attrib_data)
+                ;
+              else if (*name == '='
+                       && strlen (name+1) == uid->len
+                       && !memcmp (uid->name, name + 1, uid->len))
+                { /* Exact match - we don't do a check for ambiguity
+                   * in this case.  */
+                  node->flag |= NODFLG_SELUID;
+                  if (any != -1)
+                    {
+                      sl->flags |= 1;  /* Report as found.  */
+                      any = 1;
+                    }
+                }
+              else if (ascii_memistr (uid->name, uid->len,
+                                      *name == '*'? name+1:name))
+                {
+                  node->flag |= NODFLG_SELUID;
+                  if (any != -1)
+                    {
+                      sl->flags |= 1;  /* Report as found.  */
+                      any = 1;
+                    }
+                  count++;
+                }
+            }
+        }
+
+      if (count > 1)
+        {
+          any = -1;        /* Force failure at end.  */
+          sl->flags |= 2;  /* Report as ambiguous.  */
+        }
+    }
+
+  /* Check whether all given user ids were found.  */
+  for (sl=uids; sl; sl = sl->next)
+    if (!(sl->flags & 1))
+      any = -1;  /* That user id was not found.  */
+
+  /* Print an error if there was a problem with the user ids.  */
+  if (uids && any < 1)
+    {
+      if (!opt.verbose)
+        show_key_with_all_names (ctrl, es_stdout, keyblock, 0, 0, 0, 0, 0, 1);
+      es_fflush (es_stdout);
+      for (sl=uids; sl; sl = sl->next)
+        {
+          if ((sl->flags & 2))
+            log_info (_("Invalid user ID '%s': %s\n"),
+                      sl->d, gpg_strerror (GPG_ERR_AMBIGUOUS_NAME));
+          else if (!(sl->flags & 1))
+            log_info (_("Invalid user ID '%s': %s\n"),
+                      sl->d, gpg_strerror (GPG_ERR_NOT_FOUND));
+        }
+      log_error ("%s  %s", _("No matching user IDs."), _("Nothing to sign.\n"));
+      goto leave;
+    }
+
+  /* Sign. */
+  sign_uids (ctrl, es_stdout, keyblock, locusr, &modified, local, 0, 0, 0, 1);
+  es_fflush (es_stdout);
+
+  if (modified)
+    {
+      err = keydb_update_keyblock (ctrl, 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"));
+
+  if (update_trust)
+    revalidation_mark (ctrl);
+
+
+ leave:
+  release_kbnode (keyblock);
+  keydb_release (kdbhd);
+}
+
+
+/* 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 (ctrl, &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;
     }
 
       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;
-      }
-  }
+  /* Create the subkey.  Note 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 (ctrl, 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);
+}
+
+
+/* Unattended expiration setting function for the main key.  If
+ * SUBKEYFPRS is not NULL and SUBKEYSFPRS[0] is neither NULL, it is
+ * expected to be an array of fingerprints for subkeys to change. It
+ * may also be an array which just one item "*" to indicate that all
+ * keys shall be set to that expiration date.
+ */
+void
+keyedit_quick_set_expire (ctrl_t ctrl, const char *fpr, const char *expirestr,
+                          char **subkeyfprs)
+{
+  gpg_error_t err;
+  kbnode_t keyblock, node;
+  KEYDB_HANDLE kdbhd;
+  int modified = 0;
+  PKT_public_key *pk;
+  u32 expire;
+  int primary_only = 0;
+  int idx;
+
+#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
+   * expiration setting.  */
+  err = find_by_primary_fpr (ctrl, fpr, &keyblock, &kdbhd);
+  if (err)
+    goto leave;
 
 
-  if (fix_keyblock (&keyblock))
+  if (fix_keyblock (ctrl, &keyblock))
     modified++;
 
     modified++;
 
-  /* Give some info in verbose.  */
-  if (opt.verbose)
-    {
-      show_key_with_all_names (ctrl, es_stdout, keyblock, 0,
-                               1/*with_revoker*/, 1/*with_fingerprint*/,
-                               0, 0, 1);
-      es_fflush (es_stdout);
-    }
-
   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);
   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."), _("  Unable to sign.\n"));
+      log_error ("%s%s", _("Key is revoked."), "\n");
+      err = gpg_error (GPG_ERR_CERT_REVOKED);
       goto leave;
     }
 
       goto leave;
     }
 
-  /* Set the flags according to the UIDS list.  Fixme: We may want to
-     use classify_user_id along with dedicated compare functions so
-     that we match the same way as in the key lookup. */
-  any = 0;
-  menu_select_uid (keyblock, 0);   /* Better clear the flags first. */
-  for (sl=uids; sl; sl = sl->next)
+  expire = parse_expire_string (expirestr);
+  if (expire == (u32)-1 )
     {
     {
+      log_error (_("'%s' is not a valid expiration time\n"), expirestr);
+      err = gpg_error (GPG_ERR_INV_VALUE);
+      goto leave;
+    }
+  if (expire)
+    expire += make_timestamp ();
+
+  /* Check whether a subkey's expiration time shall be changed or the
+   * expiration time of all keys.  */
+  if (!subkeyfprs || !subkeyfprs[0])
+    primary_only = 1;
+  else if ( !strcmp (subkeyfprs[0], "*") && !subkeyfprs[1])
+    {
+      /* Change all subkeys keys which have not been revoked and are
+       * not yet expired.  */
+      merge_keys_and_selfsig (ctrl, keyblock);
       for (node = keyblock; node; node = node->next)
         {
       for (node = keyblock; node; node = node->next)
         {
-          if (node->pkt->pkttype == PKT_USER_ID)
+          if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+              && (pk = node->pkt->pkt.public_key)
+              && !pk->flags.revoked
+              && !pk->has_expired)
+            node->flag |= NODFLG_SELKEY;
+        }
+    }
+  else
+    {
+      /* Change specified subkeys.  */
+      KEYDB_SEARCH_DESC desc;
+      byte fprbin[MAX_FINGERPRINT_LEN];
+      size_t fprlen;
+
+      err = 0;
+      merge_keys_and_selfsig (ctrl, keyblock);
+      for (idx=0; subkeyfprs[idx]; idx++)
+        {
+          int any = 0;
+
+          /* Parse the fingerprint.  */
+          if (classify_user_id (subkeyfprs[idx], &desc, 1)
+              || !(desc.mode == KEYDB_SEARCH_MODE_FPR
+                   || desc.mode == KEYDB_SEARCH_MODE_FPR20))
             {
             {
-              PKT_user_id *uid = node->pkt->pkt.user_id;
+              log_error (_("\"%s\" is not a proper fingerprint\n"),
+                         subkeyfprs[idx] );
+              if (!err)
+                err = gpg_error (GPG_ERR_INV_NAME);
+              continue;
+            }
 
 
-              if (!uid->attrib_data
-                  && ascii_memistr (uid->name, uid->len, sl->d))
+          /* Set the flag for the matching non revoked subkey.  */
+          for (node = keyblock; node; node = node->next)
+            {
+              if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY
+                  && (pk = node->pkt->pkt.public_key)
+                  && !pk->flags.revoked )
                 {
                 {
-                  node->flag |= NODFLG_SELUID;
-                  any = 1;
+                  fingerprint_from_pk (pk, fprbin, &fprlen);
+                  if (fprlen == 20 && !memcmp (fprbin, desc.u.fpr, 20))
+                    {
+                      node->flag |= NODFLG_SELKEY;
+                      any = 1;
+                    }
                 }
             }
                 }
             }
+          if (!any)
+            {
+              log_error (_("subkey \"%s\" not found\n"), subkeyfprs[idx]);
+              if (!err)
+                err = gpg_error (GPG_ERR_NOT_FOUND);
+            }
         }
         }
-    }
 
 
-  if (uids && !any)
-    {
-      if (!opt.verbose)
-        show_key_with_all_names (ctrl, es_stdout, keyblock, 0, 0, 0, 0, 0, 1);
-      es_fflush (es_stdout);
-      log_error ("%s  %s", _("No matching user IDs."), _("Nothing to sign.\n"));
-      goto leave;
+      if (err)
+        goto leave;
     }
 
     }
 
-  /* Sign. */
-  sign_uids (ctrl, es_stdout, keyblock, locusr, &modified, local, 0, 0, 0, 1);
+  /* Set the new expiration date.  */
+  err = menu_expire (ctrl, keyblock, primary_only? 1 : 2, expire);
+  if (gpg_err_code (err) == GPG_ERR_TRUE)
+    modified = 1;
+  else if (err)
+    goto leave;
   es_fflush (es_stdout);
 
   es_fflush (es_stdout);
 
+  /* Store.  */
   if (modified)
     {
   if (modified)
     {
-      err = keydb_update_keyblock (kdbhd, keyblock);
+      err = keydb_update_keyblock (ctrl, kdbhd, keyblock);
       if (err)
         {
           log_error (_("update failed: %s\n"), gpg_strerror (err));
           goto leave;
         }
       if (err)
         {
           log_error (_("update failed: %s\n"), gpg_strerror (err));
           goto leave;
         }
+      if (update_trust)
+        revalidation_mark (ctrl);
     }
   else
     log_info (_("Key not changed so no update needed.\n"));
 
     }
   else
     log_info (_("Key not changed so no update needed.\n"));
 
-  if (update_trust)
-    revalidation_mark ();
-
-
  leave:
   release_kbnode (keyblock);
   keydb_release (kdbhd);
  leave:
   release_kbnode (keyblock);
   keydb_release (kdbhd);
+  if (err)
+    write_status_error ("set_expire", err);
 }
 
 
 }
 
 
@@ -2701,6 +3066,23 @@ show_prefs (PKT_user_id * uid, PKT_signature * selfsig, int verbose)
          tty_printf ("%s", openpgp_cipher_algo_name (CIPHER_ALGO_3DES));
        }
       tty_printf ("\n     ");
          tty_printf ("%s", openpgp_cipher_algo_name (CIPHER_ALGO_3DES));
        }
       tty_printf ("\n     ");
+      tty_printf (_("AEAD: "));
+      for (i = any = 0; prefs[i].type; i++)
+       {
+         if (prefs[i].type == PREFTYPE_AEAD)
+           {
+             if (any)
+               tty_printf (", ");
+             any = 1;
+             /* We don't want to display strings for experimental algos */
+             if (!openpgp_aead_test_algo (prefs[i].value)
+                 && prefs[i].value < 100)
+               tty_printf ("%s", openpgp_aead_algo_name (prefs[i].value));
+             else
+               tty_printf ("[%d]", prefs[i].value);
+           }
+       }
+      tty_printf ("\n     ");
       tty_printf (_("Digest: "));
       for (i = any = 0; prefs[i].type; i++)
        {
       tty_printf (_("Digest: "));
       for (i = any = 0; prefs[i].type; i++)
        {
@@ -2755,7 +3137,7 @@ show_prefs (PKT_user_id * uid, PKT_signature * selfsig, int verbose)
            }
          tty_printf ("%s", compress_algo_to_string (COMPRESS_ALGO_NONE));
        }
            }
          tty_printf ("%s", compress_algo_to_string (COMPRESS_ALGO_NONE));
        }
-      if (uid->flags.mdc || !uid->flags.ks_modify)
+      if (uid->flags.mdc || uid->flags.aead || !uid->flags.ks_modify)
        {
          tty_printf ("\n     ");
          tty_printf (_("Features: "));
        {
          tty_printf ("\n     ");
          tty_printf (_("Features: "));
@@ -2765,6 +3147,12 @@ show_prefs (PKT_user_id * uid, PKT_signature * selfsig, int verbose)
              tty_printf ("MDC");
              any = 1;
            }
              tty_printf ("MDC");
              any = 1;
            }
+         if (!uid->flags.aead)
+           {
+             if (any)
+               tty_printf (", ");
+             tty_printf ("AEAD");
+           }
          if (!uid->flags.ks_modify)
            {
              if (any)
          if (!uid->flags.ks_modify)
            {
              if (any)
@@ -2803,12 +3191,15 @@ show_prefs (PKT_user_id * uid, PKT_signature * selfsig, int verbose)
       for (i = 0; prefs[i].type; i++)
        {
          tty_printf (" %c%d", prefs[i].type == PREFTYPE_SYM ? 'S' :
       for (i = 0; prefs[i].type; i++)
        {
          tty_printf (" %c%d", prefs[i].type == PREFTYPE_SYM ? 'S' :
+                     prefs[i].type == PREFTYPE_AEAD ? 'A' :
                      prefs[i].type == PREFTYPE_HASH ? 'H' :
                      prefs[i].type == PREFTYPE_ZIP ? 'Z' : '?',
                      prefs[i].value);
        }
       if (uid->flags.mdc)
        tty_printf (" [mdc]");
                      prefs[i].type == PREFTYPE_HASH ? 'H' :
                      prefs[i].type == PREFTYPE_ZIP ? 'Z' : '?',
                      prefs[i].value);
        }
       if (uid->flags.mdc)
        tty_printf (" [mdc]");
+      if (uid->flags.aead)
+       tty_printf (" [aead]");
       if (!uid->flags.ks_modify)
        tty_printf (" [no-ks-modify]");
       tty_printf ("\n");
       if (!uid->flags.ks_modify)
        tty_printf (" [no-ks-modify]");
       tty_printf ("\n");
@@ -2862,7 +3253,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))
            {
            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, keyblock, pk, NULL);
              if (trust == 'u')
                ulti_hack = 1;
              es_putc (trust, fp);
              if (trust == 'u')
                ulti_hack = 1;
              es_putc (trust, fp);
@@ -2875,7 +3266,7 @@ show_key_with_all_names_colon (ctrl_t ctrl, estream_t fp, kbnode_t keyblock)
                       (ulong) pk->timestamp, (ulong) pk->expiredate);
          if (node->pkt->pkttype == PKT_PUBLIC_KEY
              && !(opt.fast_list_mode || opt.no_expensive_trust_checks))
                       (ulong) pk->timestamp, (ulong) pk->expiredate);
          if (node->pkt->pkttype == PKT_PUBLIC_KEY
              && !(opt.fast_list_mode || opt.no_expensive_trust_checks))
-           es_putc (get_ownertrust_info (pk), fp);
+           es_putc (get_ownertrust_info (ctrl, pk, 0), fp);
          es_putc (':', fp);
          es_putc (':', fp);
          es_putc (':', fp);
          es_putc (':', fp);
          es_putc (':', fp);
          es_putc (':', fp);
@@ -2890,7 +3281,7 @@ show_key_with_all_names_colon (ctrl_t ctrl, estream_t fp, kbnode_t keyblock)
            es_putc ('a', fp);
          es_putc ('\n', fp);
 
            es_putc ('a', fp);
          es_putc ('\n', fp);
 
-         print_fingerprint (fp, pk, 0);
+         print_fingerprint (ctrl, fp, pk, 0);
          print_revokers (fp, pk);
        }
     }
          print_revokers (fp, pk);
        }
     }
@@ -2910,9 +3301,9 @@ show_key_with_all_names_colon (ctrl_t ctrl, estream_t fp, kbnode_t keyblock)
          else
            es_fputs ("uid:", fp);
 
          else
            es_fputs ("uid:", fp);
 
-         if (uid->is_revoked)
+         if (uid->flags.revoked)
            es_fputs ("r::::::::", fp);
            es_fputs ("r::::::::", fp);
-         else if (uid->is_expired)
+         else if (uid->flags.expired)
            es_fputs ("e::::::::", fp);
          else if (opt.fast_list_mode || opt.no_expensive_trust_checks)
            es_fputs ("::::::::", fp);
            es_fputs ("e::::::::", fp);
          else if (opt.fast_list_mode || opt.no_expensive_trust_checks)
            es_fputs ("::::::::", fp);
@@ -2921,7 +3312,7 @@ show_key_with_all_names_colon (ctrl_t ctrl, estream_t fp, kbnode_t keyblock)
              int uid_validity;
 
              if (primary && !ulti_hack)
              int uid_validity;
 
              if (primary && !ulti_hack)
-               uid_validity = get_validity_info (primary, uid);
+               uid_validity = get_validity_info (ctrl, keyblock, primary, uid);
              else
                uid_validity = 'u';
              es_fprintf (fp, "%c::::::::", uid_validity);
              else
                uid_validity = 'u';
              es_fprintf (fp, "%c::::::::", uid_validity);
@@ -2954,17 +3345,19 @@ show_key_with_all_names_colon (ctrl_t ctrl, estream_t fp, kbnode_t keyblock)
                }
              if (uid->flags.mdc)
                es_fputs (",mdc", fp);
                }
              if (uid->flags.mdc)
                es_fputs (",mdc", fp);
+             if (uid->flags.aead)
+               es_fputs (",aead", fp);
              if (!uid->flags.ks_modify)
                es_fputs (",no-ks-modify", fp);
            }
          es_putc (':', fp);
          /* flags */
          es_fprintf (fp, "%d,", i);
              if (!uid->flags.ks_modify)
                es_fputs (",no-ks-modify", fp);
            }
          es_putc (':', fp);
          /* flags */
          es_fprintf (fp, "%d,", i);
-         if (uid->is_primary)
+         if (uid->flags.primary)
            es_putc ('p', fp);
            es_putc ('p', fp);
-         if (uid->is_revoked)
+         if (uid->flags.revoked)
            es_putc ('r', fp);
            es_putc ('r', fp);
-         if (uid->is_expired)
+         if (uid->flags.expired)
            es_putc ('e', fp);
          if ((node->flag & NODFLG_SELUID))
            es_putc ('s', fp);
            es_putc ('e', fp);
          if ((node->flag & NODFLG_SELUID))
            es_putc ('s', fp);
@@ -2975,7 +3368,7 @@ show_key_with_all_names_colon (ctrl_t ctrl, estream_t fp, kbnode_t keyblock)
            {
 #ifdef USE_TOFU
              enum tofu_policy policy;
            {
 #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*/
                  && policy != TOFU_POLICY_NONE)
                es_fprintf (fp, "%s", tofu_policy_str (policy));
 #endif /*USE_TOFU*/
@@ -2988,8 +3381,8 @@ show_key_with_all_names_colon (ctrl_t ctrl, estream_t fp, kbnode_t keyblock)
 
 
 static void
 
 
 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;
            int with_prefs)
 {
   KBNODE node;
@@ -3004,13 +3397,13 @@ show_names (estream_t fp,
          if (!flag || (flag && (node->flag & flag)))
            {
              if (!(flag & NODFLG_MARK_A) && pk)
          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, "     ");
              else if (node->flag & NODFLG_SELUID)
                tty_fprintf (fp, "(%d)* ", i);
 
              if (flag & NODFLG_MARK_A)
                tty_fprintf (fp, "     ");
              else if (node->flag & NODFLG_SELUID)
                tty_fprintf (fp, "(%d)* ", i);
-             else if (uid->is_primary)
+             else if (uid->flags.primary)
                tty_fprintf (fp, "(%d). ", i);
              else
                tty_fprintf (fp, "(%d)  ", i);
                tty_fprintf (fp, "(%d). ", i);
              else
                tty_fprintf (fp, "(%d)  ", i);
@@ -3091,12 +3484,12 @@ show_key_with_all_names (ctrl_t ctrl, estream_t fp,
               * output */
              static int did_warn = 0;
 
               * output */
              static int did_warn = 0;
 
-             trust = get_validity_string (pk, NULL);
-             otrust = get_ownertrust_string (pk);
+             trust = get_validity_string (ctrl, pk, NULL);
+             otrust = get_ownertrust_string (ctrl, pk, 0);
 
              /* Show a warning once */
              if (!did_warn
 
              /* Show a warning once */
              if (!did_warn
-                 && (get_validity (pk, NULL, NULL, 0)
+                 && (get_validity (ctrl, keyblock, pk, NULL, NULL, 0)
                      & TRUST_FLAG_PENDING_CHECK))
                {
                  did_warn = 1;
                      & TRUST_FLAG_PENDING_CHECK))
                {
                  did_warn = 1;
@@ -3108,7 +3501,7 @@ show_key_with_all_names (ctrl_t ctrl, estream_t fp,
 
          if (pk->flags.revoked)
            {
 
          if (pk->flags.revoked)
            {
-             char *user = get_user_id_string_native (pk->revoked.keyid);
+             char *user = get_user_id_string_native (ctrl, pk->revoked.keyid);
               tty_fprintf (fp,
                            _("The following key was revoked on"
                             " %s by %s key %s\n"),
               tty_fprintf (fp,
                            _("The following key was revoked on"
                             " %s by %s key %s\n"),
@@ -3129,10 +3522,10 @@ show_key_with_all_names (ctrl_t ctrl, estream_t fp,
                    const char *algo;
 
                    algo = gcry_pk_algo_name (pk->revkey[i].algid);
                    const char *algo;
 
                    algo = gcry_pk_algo_name (pk->revkey[i].algid);
-                   keyid_from_fingerprint (pk->revkey[i].fpr,
+                   keyid_from_fingerprint (ctrl, pk->revkey[i].fpr,
                                            MAX_FINGERPRINT_LEN, r_keyid);
 
                                            MAX_FINGERPRINT_LEN, r_keyid);
 
-                   user = get_user_id_string_native (r_keyid);
+                   user = get_user_id_string_native (ctrl, r_keyid);
                    tty_fprintf (fp,
                                  _("This key may be revoked by %s key %s"),
                                  algo ? algo : "?", user);
                    tty_fprintf (fp,
                                  _("This key may be revoked by %s key %s"),
                                  algo ? algo : "?", user);
@@ -3163,7 +3556,7 @@ show_key_with_all_names (ctrl_t ctrl, estream_t fp,
                 have_seckey = 0;
               }
             else
                 have_seckey = 0;
               }
             else
-              have_seckey = !agent_get_keyinfo (ctrl, hexgrip, &serialno);
+              have_seckey = !agent_get_keyinfo (ctrl, hexgrip, &serialno, NULL);
             xfree (hexgrip);
           }
 
             xfree (hexgrip);
           }
 
@@ -3217,7 +3610,7 @@ show_key_with_all_names (ctrl_t ctrl, estream_t fp,
               && pk->seckey_info->is_protected
               && pk->seckey_info->s2k.mode == 1002)
            {
               && pk->seckey_info->is_protected
               && pk->seckey_info->s2k.mode == 1002)
            {
-              /* FIXME: Check wether this code path is still used.  */
+              /* FIXME: Check whether this code path is still used.  */
              tty_fprintf (fp, "%*s%s", opt.legacy_list_mode? 21:5, "",
                            _("card-no: "));
              if (pk->seckey_info->ivlen == 16
              tty_fprintf (fp, "%*s%s", opt.legacy_list_mode? 21:5, "",
                            _("card-no: "));
              if (pk->seckey_info->ivlen == 16
@@ -3266,7 +3659,7 @@ show_key_with_all_names (ctrl_t ctrl, estream_t fp,
                  tty_fprintf (fp, "\n");
                }
              if (node->pkt->pkttype == PKT_PUBLIC_KEY
                  tty_fprintf (fp, "\n");
                }
              if (node->pkt->pkttype == PKT_PUBLIC_KEY
-                 && (get_ownertrust (pk) & TRUST_FLAG_DISABLED))
+                 && (get_ownertrust (ctrl, pk) & TRUST_FLAG_DISABLED))
                {
                  tty_fprintf (fp, "*** ");
                  tty_fprintf (fp, _("This key has been disabled"));
                {
                  tty_fprintf (fp, "*** ");
                  tty_fprintf (fp, _("This key has been disabled"));
@@ -3277,13 +3670,13 @@ show_key_with_all_names (ctrl_t ctrl, estream_t fp,
          if ((node->pkt->pkttype == PKT_PUBLIC_KEY
                || node->pkt->pkttype == PKT_SECRET_KEY) && with_fpr)
            {
          if ((node->pkt->pkttype == PKT_PUBLIC_KEY
                || node->pkt->pkttype == PKT_SECRET_KEY) && with_fpr)
            {
-              print_fingerprint (fp, pk, 2);
+              print_fingerprint (ctrl, fp, pk, 2);
              tty_fprintf (fp, "\n");
            }
        }
     }
 
              tty_fprintf (fp, "\n");
            }
        }
     }
 
-  show_names (fp,
+  show_names (ctrl, fp,
               keyblock, primary, only_marked ? NODFLG_MARK_A : 0, with_prefs);
 
   if (do_warn && !nowarn)
               keyblock, primary, only_marked ? NODFLG_MARK_A : 0, with_prefs);
 
   if (do_warn && !nowarn)
@@ -3302,7 +3695,7 @@ show_key_with_all_names (ctrl_t ctrl, estream_t fp,
    secret keys and thus the printing of "pub" vs. "sec" does only
    depend on the packet type and not by checking with gpg-agent.  */
 void
    secret keys and thus the printing of "pub" vs. "sec" does only
    depend on the packet type and not by checking with gpg-agent.  */
 void
-show_basic_key_info (KBNODE keyblock)
+show_basic_key_info (ctrl_t ctrl, kbnode_t keyblock)
 {
   KBNODE node;
   int i;
 {
   KBNODE node;
   int i;
@@ -3328,7 +3721,7 @@ show_basic_key_info (KBNODE keyblock)
          tty_printf ("  ");
          tty_printf (_("expires: %s"), expirestr_from_pk (pk));
          tty_printf ("\n");
          tty_printf ("  ");
          tty_printf (_("expires: %s"), expirestr_from_pk (pk));
          tty_printf ("\n");
-         print_fingerprint (NULL, pk, 3);
+         print_fingerprint (ctrl, NULL, pk, 3);
          tty_printf ("\n");
        }
     }
          tty_printf ("\n");
        }
     }
@@ -3342,9 +3735,9 @@ show_basic_key_info (KBNODE keyblock)
          ++i;
 
          tty_printf ("     ");
          ++i;
 
          tty_printf ("     ");
-         if (uid->is_revoked)
+         if (uid->flags.revoked)
            tty_printf ("[%s] ", _("revoked"));
            tty_printf ("[%s] ", _("revoked"));
-         else if (uid->is_expired)
+         else if (uid->flags.expired)
            tty_printf ("[%s] ", _("expired"));
          tty_print_utf8_string (uid->name, uid->len);
          tty_printf ("\n");
            tty_printf ("[%s] ", _("expired"));
          tty_print_utf8_string (uid->name, uid->len);
          tty_printf ("\n");
@@ -3354,7 +3747,7 @@ show_basic_key_info (KBNODE keyblock)
 
 
 static void
 
 
 static void
-show_key_and_fingerprint (kbnode_t keyblock, int with_subkeys)
+show_key_and_fingerprint (ctrl_t ctrl, kbnode_t keyblock, int with_subkeys)
 {
   kbnode_t node;
   PKT_public_key *pk = NULL;
 {
   kbnode_t node;
   PKT_public_key *pk = NULL;
@@ -3379,7 +3772,7 @@ show_key_and_fingerprint (kbnode_t keyblock, int with_subkeys)
     }
   tty_printf ("\n");
   if (pk)
     }
   tty_printf ("\n");
   if (pk)
-    print_fingerprint (NULL, pk, 2);
+    print_fingerprint (ctrl, NULL, pk, 2);
   if (with_subkeys)
     {
       for (node = keyblock; node; node = node->next)
   if (with_subkeys)
     {
       for (node = keyblock; node; node = node->next)
@@ -3393,7 +3786,7 @@ show_key_and_fingerprint (kbnode_t keyblock, int with_subkeys)
                           datestr_from_pk (pk),
                           usagestr_from_pk (pk, 0));
 
                           datestr_from_pk (pk),
                           usagestr_from_pk (pk, 0));
 
-              print_fingerprint (NULL, pk, 4);
+              print_fingerprint (ctrl, NULL, pk, 4);
             }
         }
     }
             }
         }
     }
@@ -3452,7 +3845,7 @@ no_primary_warning (KBNODE keyblock)
        {
          uid_count++;
 
        {
          uid_count++;
 
-         if (node->pkt->pkt.user_id->is_primary == 2)
+         if (node->pkt->pkt.user_id->flags.primary == 2)
            {
              have_primary = 1;
              break;
            {
              have_primary = 1;
              break;
@@ -3528,8 +3921,8 @@ subkey_expire_warning (kbnode_t keyblock)
  * user id.
  */
 static int
  * 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;
 {
   PKT_user_id *uid;
   PKT_public_key *pk = NULL;
@@ -3551,7 +3944,7 @@ menu_adduid (kbnode_t pub_keyblock, int photo, const char *photo_name,
     }
   if (!node) /* No subkey.  */
     pub_where = NULL;
     }
   if (!node) /* No subkey.  */
     pub_where = NULL;
-  assert (pk);
+  log_assert (pk);
 
   if (photo)
     {
 
   if (photo)
     {
@@ -3591,18 +3984,21 @@ 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);
   if (!uid)
     {
       if (uidstring)
     }
   else
     uid = generate_user_id (pub_keyblock, uidstring);
   if (!uid)
     {
       if (uidstring)
-        log_error ("%s", _("Such a user ID already exists on this key!\n"));
+        {
+          write_status_error ("adduid", gpg_error (304));
+          log_error ("%s", _("Such a user ID already exists on this key!\n"));
+        }
       return 0;
     }
 
       return 0;
     }
 
-  err = make_keysig_packet (&sig, pk, uid, NULL, pk, 0x13, 0, 0, 0,
+  err = make_keysig_packet (ctrl, &sig, pk, uid, NULL, pk, 0x13, 0, 0, 0,
                             keygen_add_std_prefs, pk, NULL);
   if (err)
     {
                             keygen_add_std_prefs, pk, NULL);
   if (err)
     {
@@ -3623,7 +4019,7 @@ menu_adduid (kbnode_t pub_keyblock, int photo, const char *photo_name,
     add_kbnode (pub_keyblock, node);
   pkt = xmalloc_clear (sizeof *pkt);
   pkt->pkttype = PKT_SIGNATURE;
     add_kbnode (pub_keyblock, node);
   pkt = xmalloc_clear (sizeof *pkt);
   pkt->pkttype = PKT_SIGNATURE;
-  pkt->pkt.signature = copy_signature (NULL, sig);
+  pkt->pkt.signature = sig;
   if (pub_where)
     insert_kbnode (node, new_kbnode (pkt), 0);
   else
   if (pub_where)
     insert_kbnode (node, new_kbnode (pkt), 0);
   else
@@ -3650,7 +4046,7 @@ menu_deluid (KBNODE pub_keyblock)
            {
              /* Only cause a trust update if we delete a
                 non-revoked user id */
            {
              /* Only cause a trust update if we delete a
                 non-revoked user id */
-             if (!node->pkt->pkt.user_id->is_revoked)
+             if (!node->pkt->pkt.user_id->flags.revoked)
                update_trust = 1;
              delete_kbnode (node);
            }
                update_trust = 1;
              delete_kbnode (node);
            }
@@ -3665,7 +4061,7 @@ menu_deluid (KBNODE pub_keyblock)
 
 
 static int
 
 
 static int
-menu_delsig (KBNODE pub_keyblock)
+menu_delsig (ctrl_t ctrl, kbnode_t pub_keyblock)
 {
   KBNODE node;
   PKT_user_id *uid = NULL;
 {
   KBNODE node;
   PKT_user_id *uid = NULL;
@@ -3687,11 +4083,11 @@ menu_delsig (KBNODE pub_keyblock)
 
          okay = inv_sig = no_key = other_err = 0;
          if (opt.with_colons)
 
          okay = inv_sig = no_key = other_err = 0;
          if (opt.with_colons)
-           valid = print_and_check_one_sig_colon (pub_keyblock, node,
+           valid = print_and_check_one_sig_colon (ctrl, pub_keyblock, node,
                                                   &inv_sig, &no_key,
                                                   &other_err, &selfsig, 1);
          else
                                                   &inv_sig, &no_key,
                                                   &other_err, &selfsig, 1);
          else
-           valid = print_and_check_one_sig (pub_keyblock, node,
+           valid = print_and_check_one_sig (ctrl, pub_keyblock, node,
                                             &inv_sig, &no_key, &other_err,
                                             &selfsig, 1, 0);
 
                                             &inv_sig, &no_key, &other_err,
                                             &selfsig, 1, 0);
 
@@ -3736,8 +4132,8 @@ menu_delsig (KBNODE pub_keyblock)
   if (changed)
     {
       commit_kbnode (&pub_keyblock);
   if (changed)
     {
       commit_kbnode (&pub_keyblock);
-      tty_printf (changed == 1 ? _("Deleted %d signature.\n")
-                 : _("Deleted %d signatures.\n"), changed);
+      tty_printf (ngettext("Deleted %d signature.\n",
+                           "Deleted %d signatures.\n", changed), changed);
     }
   else
     tty_printf (_("Nothing deleted.\n"));
     }
   else
     tty_printf (_("Nothing deleted.\n"));
@@ -3747,7 +4143,7 @@ menu_delsig (KBNODE pub_keyblock)
 
 
 static int
 
 
 static int
-menu_clean (KBNODE keyblock, int self_only)
+menu_clean (ctrl_t ctrl, kbnode_t keyblock, int self_only)
 {
   KBNODE uidnode;
   int modified = 0, select_all = !count_selected_uids (keyblock);
 {
   KBNODE uidnode;
   int modified = 0, select_all = !count_selected_uids (keyblock);
@@ -3764,15 +4160,15 @@ menu_clean (KBNODE keyblock, int self_only)
                                       uidnode->pkt->pkt.user_id->len,
                                       0);
 
                                       uidnode->pkt->pkt.user_id->len,
                                       0);
 
-         clean_one_uid (keyblock, uidnode, opt.verbose, self_only, &uids,
+         clean_one_uid (ctrl, keyblock, uidnode, opt.verbose, self_only, &uids,
                         &sigs);
          if (uids)
            {
              const char *reason;
 
                         &sigs);
          if (uids)
            {
              const char *reason;
 
-             if (uidnode->pkt->pkt.user_id->is_revoked)
+             if (uidnode->pkt->pkt.user_id->flags.revoked)
                reason = _("revoked");
                reason = _("revoked");
-             else if (uidnode->pkt->pkt.user_id->is_expired)
+             else if (uidnode->pkt->pkt.user_id->flags.expired)
                reason = _("expired");
              else
                reason = _("invalid");
                reason = _("expired");
              else
                reason = _("invalid");
@@ -3783,11 +4179,9 @@ menu_clean (KBNODE keyblock, int self_only)
            }
          else if (sigs)
            {
            }
          else if (sigs)
            {
-             tty_printf (sigs == 1 ?
-                         _("User ID \"%s\": %d signature removed\n") :
-                         _("User ID \"%s\": %d signatures removed\n"),
-                         user, sigs);
-
+             tty_printf (ngettext("User ID \"%s\": %d signature removed\n",
+                                   "User ID \"%s\": %d signatures removed\n",
+                                   sigs), user, sigs);
              modified = 1;
            }
          else
              modified = 1;
            }
          else
@@ -3850,7 +4244,7 @@ menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive)
   size_t fprlen;
   int rc;
 
   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;
 
 
   pk = pub_keyblock->pkt->pkt.public_key;
 
@@ -3956,8 +4350,7 @@ menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive)
                  log_error (_("this key has already been designated "
                               "as a revoker\n"));
 
                  log_error (_("this key has already been designated "
                               "as a revoker\n"));
 
-                 sprintf (buf, "%08lX%08lX",
-                          (ulong) pk->keyid[0], (ulong) pk->keyid[1]);
+                  format_keyid (pk_keyid (pk), KF_LONG, buf, sizeof (buf));
                  write_status_text (STATUS_ALREADY_SIGNED, buf);
 
                  break;
                  write_status_text (STATUS_ALREADY_SIGNED, buf);
 
                  break;
@@ -3968,8 +4361,8 @@ menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive)
            continue;
        }
 
            continue;
        }
 
-      print_pubkey_info (NULL, revoker_pk);
-      print_fingerprint (NULL, revoker_pk, 2);
+      print_pubkey_info (ctrl, NULL, revoker_pk);
+      print_fingerprint (ctrl, NULL, revoker_pk, 2);
       tty_printf ("\n");
 
       tty_printf (_("WARNING: appointing a key as a designated revoker "
       tty_printf ("\n");
 
       tty_printf (_("WARNING: appointing a key as a designated revoker "
@@ -3987,7 +4380,7 @@ menu_addrevoker (ctrl_t ctrl, kbnode_t pub_keyblock, int sensitive)
       break;
     }
 
       break;
     }
 
-  rc = make_keysig_packet (&sig, pk, NULL, NULL, pk, 0x1F, 0, 0, 0,
+  rc = make_keysig_packet (ctrl, &sig, pk, NULL, NULL, pk, 0x1F, 0, 0, 0,
                           keygen_add_revkey, &revkey, NULL);
   if (rc)
     {
                           keygen_add_revkey, &revkey, NULL);
   if (rc)
     {
@@ -4013,36 +4406,55 @@ fail:
 }
 
 
 }
 
 
-static int
-menu_expire (KBNODE pub_keyblock)
+/* With FORCE_MAINKEY cleared this function handles the interactive
+ * menu option "expire".  With UNATTENDED set to 1 this function only
+ * sets the expiration date of the primary key to NEWEXPIRATION and
+ * avoid all interactivity; with a value of 2 only the flagged subkeys
+ * are set to NEWEXPIRATION.  Returns 0 if nothing was done,
+ * GPG_ERR_TRUE if the key was modified, or any other error code. */
+static gpg_error_t
+menu_expire (ctrl_t ctrl, kbnode_t pub_keyblock,
+             int unattended, u32 newexpiration)
 {
 {
-  int n1, signumber, rc;
+  int signumber, rc;
   u32 expiredate;
   u32 expiredate;
-  int mainkey = 0;
+  int only_mainkey;  /* Set if only the mainkey is to be updated.  */
   PKT_public_key *main_pk, *sub_pk;
   PKT_user_id *uid;
   PKT_public_key *main_pk, *sub_pk;
   PKT_user_id *uid;
-  KBNODE node;
+  kbnode_t node;
   u32 keyid[2];
 
   u32 keyid[2];
 
-  n1 = count_selected_keys (pub_keyblock);
-  if (n1 > 1)
+  if (unattended)
     {
     {
-      if (!cpr_get_answer_is_yes
-          ("keyedit.expire_multiple_subkeys.okay",
-           _("Are you sure you want to change the"
-             " expiration time for multiple subkeys? (y/N) ")))
-       return 0;
+      only_mainkey = (unattended == 1);
+      expiredate = newexpiration;
     }
     }
-  else if (n1)
-    tty_printf (_("Changing expiration time for a subkey.\n"));
   else
     {
   else
     {
-      tty_printf (_("Changing expiration time for the primary key.\n"));
-      mainkey = 1;
-      no_primary_warning (pub_keyblock);
+      int n1;
+
+      only_mainkey = 0;
+      n1 = count_selected_keys (pub_keyblock);
+      if (n1 > 1)
+        {
+          if (!cpr_get_answer_is_yes
+              ("keyedit.expire_multiple_subkeys.okay",
+               _("Are you sure you want to change the"
+                 " expiration time for multiple subkeys? (y/N) ")))
+            return gpg_error (GPG_ERR_CANCELED);;
+        }
+      else if (n1)
+        tty_printf (_("Changing expiration time for a subkey.\n"));
+      else
+        {
+          tty_printf (_("Changing expiration time for the primary key.\n"));
+          only_mainkey = 1;
+          no_primary_warning (pub_keyblock);
+        }
+
+      expiredate = ask_expiredate ();
     }
 
     }
 
-  expiredate = ask_expiredate ();
 
   /* Now we can actually change the self-signature(s) */
   main_pk = sub_pk = NULL;
 
   /* Now we can actually change the self-signature(s) */
   main_pk = sub_pk = NULL;
@@ -4058,8 +4470,10 @@ menu_expire (KBNODE pub_keyblock)
        }
       else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
        {
        }
       else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
        {
-          if (node->flag & NODFLG_SELKEY)
+          if ((node->flag & NODFLG_SELKEY) && unattended != 1)
             {
             {
+              /* The flag is set and we do not want to set the
+               * expiration date only for the main key.  */
               sub_pk = node->pkt->pkt.public_key;
               sub_pk->expiredate = expiredate;
             }
               sub_pk = node->pkt->pkt.public_key;
               sub_pk->expiredate = expiredate;
             }
@@ -4069,13 +4483,14 @@ menu_expire (KBNODE pub_keyblock)
       else if (node->pkt->pkttype == PKT_USER_ID)
        uid = node->pkt->pkt.user_id;
       else if (main_pk && node->pkt->pkttype == PKT_SIGNATURE
       else if (node->pkt->pkttype == PKT_USER_ID)
        uid = node->pkt->pkt.user_id;
       else if (main_pk && node->pkt->pkttype == PKT_SIGNATURE
-              && (mainkey || sub_pk))
+              && (only_mainkey || sub_pk))
        {
          PKT_signature *sig = node->pkt->pkt.signature;
        {
          PKT_signature *sig = node->pkt->pkt.signature;
+
          if (keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
          if (keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
-             && ((mainkey && uid
+             && ((only_mainkey && uid
                   && uid->created && (sig->sig_class & ~3) == 0x10)
                   && uid->created && (sig->sig_class & ~3) == 0x10)
-                 || (!mainkey && sig->sig_class == 0x18))
+                 || (!only_mainkey && sig->sig_class == 0x18))
              && sig->flags.chosen_selfsig)
            {
              /* This is a self-signature which is to be replaced.  */
              && sig->flags.chosen_selfsig)
            {
              /* This is a self-signature which is to be replaced.  */
@@ -4084,34 +4499,38 @@ menu_expire (KBNODE pub_keyblock)
 
              signumber++;
 
 
              signumber++;
 
-             if ((mainkey && main_pk->version < 4)
-                 || (!mainkey && sub_pk->version < 4))
+             if ((only_mainkey && main_pk->version < 4)
+                 || (!only_mainkey && sub_pk->version < 4))
                {
                  log_info
                     (_("You can't change the expiration date of a v3 key\n"));
                {
                  log_info
                     (_("You can't change the expiration date of a v3 key\n"));
-                 return 0;
+                 return gpg_error (GPG_ERR_LEGACY_KEY);
                }
 
                }
 
-             if (mainkey)
-               rc = update_keysig_packet (&newsig, sig, main_pk, uid, NULL,
+             if (only_mainkey)
+               rc = update_keysig_packet (ctrl,
+                                           &newsig, sig, main_pk, uid, NULL,
                                           main_pk, keygen_add_key_expire,
                                           main_pk);
              else
                rc =
                                           main_pk, keygen_add_key_expire,
                                           main_pk);
              else
                rc =
-                 update_keysig_packet (&newsig, sig, main_pk, NULL, sub_pk,
+                 update_keysig_packet (ctrl,
+                                        &newsig, sig, main_pk, NULL, sub_pk,
                                        main_pk, keygen_add_key_expire, sub_pk);
              if (rc)
                {
                  log_error ("make_keysig_packet failed: %s\n",
                             gpg_strerror (rc));
                                        main_pk, keygen_add_key_expire, sub_pk);
              if (rc)
                {
                  log_error ("make_keysig_packet failed: %s\n",
                             gpg_strerror (rc));
-                 return 0;
+                  if (gpg_err_code (rc) == GPG_ERR_TRUE)
+                    rc = GPG_ERR_GENERAL;
+                 return rc;
                }
 
              /* Replace the packet.  */
              newpkt = xmalloc_clear (sizeof *newpkt);
              newpkt->pkttype = PKT_SIGNATURE;
              newpkt->pkt.signature = newsig;
                }
 
              /* Replace the packet.  */
              newpkt = xmalloc_clear (sizeof *newpkt);
              newpkt->pkttype = PKT_SIGNATURE;
              newpkt->pkt.signature = newsig;
-             free_packet (node->pkt);
+             free_packet (node->pkt, NULL);
              xfree (node->pkt);
              node->pkt = newpkt;
              sub_pk = NULL;
              xfree (node->pkt);
              node->pkt = newpkt;
              sub_pk = NULL;
@@ -4120,21 +4539,129 @@ menu_expire (KBNODE pub_keyblock)
     }
 
   update_trust = 1;
     }
 
   update_trust = 1;
+  return gpg_error (GPG_ERR_TRUE);
+}
+
+
+/* Change the capability of a selected key.  This command should only
+ * be used to rectify badly created keys and as such is not suggested
+ * for general use.  */
+static int
+menu_changeusage (ctrl_t ctrl, kbnode_t keyblock)
+{
+  int n1, rc;
+  int mainkey = 0;
+  PKT_public_key *main_pk, *sub_pk;
+  PKT_user_id *uid;
+  kbnode_t node;
+  u32 keyid[2];
+
+  n1 = count_selected_keys (keyblock);
+  if (n1 > 1)
+    {
+      tty_printf (_("You must select exactly one key.\n"));
+      return 0;
+    }
+  else if (n1)
+    tty_printf ("Changing usage of a subkey.\n");
+  else
+    {
+      tty_printf ("Changing usage of the primary key.\n");
+      mainkey = 1;
+    }
+
+  /* Now we can actually change the self-signature(s) */
+  main_pk = sub_pk = NULL;
+  uid = NULL;
+  for (node = keyblock; node; node = node->next)
+    {
+      if (node->pkt->pkttype == PKT_PUBLIC_KEY)
+       {
+         main_pk = node->pkt->pkt.public_key;
+         keyid_from_pk (main_pk, keyid);
+       }
+      else if (node->pkt->pkttype == PKT_PUBLIC_SUBKEY)
+       {
+          if (node->flag & NODFLG_SELKEY)
+            sub_pk = node->pkt->pkt.public_key;
+          else
+            sub_pk = NULL;
+       }
+      else if (node->pkt->pkttype == PKT_USER_ID)
+       uid = node->pkt->pkt.user_id;
+      else if (main_pk && node->pkt->pkttype == PKT_SIGNATURE
+              && (mainkey || sub_pk))
+       {
+         PKT_signature *sig = node->pkt->pkt.signature;
+         if (keyid[0] == sig->keyid[0] && keyid[1] == sig->keyid[1]
+             && ((mainkey && uid
+                  && uid->created && (sig->sig_class & ~3) == 0x10)
+                 || (!mainkey && sig->sig_class == 0x18))
+             && sig->flags.chosen_selfsig)
+           {
+             /* This is the self-signature which is to be replaced.  */
+             PKT_signature *newsig;
+             PACKET *newpkt;
+
+             if ((mainkey && main_pk->version < 4)
+                 || (!mainkey && sub_pk->version < 4))
+               {
+                 log_info ("You can't change the capabilities of a v3 key\n");
+                 return 0;
+               }
+
+              if (mainkey)
+                main_pk->pubkey_usage = ask_key_flags (main_pk->pubkey_algo, 0,
+                                                       main_pk->pubkey_usage);
+              else
+                sub_pk->pubkey_usage  = ask_key_flags (sub_pk->pubkey_algo, 1,
+                                                       sub_pk->pubkey_usage);
+
+             if (mainkey)
+               rc = update_keysig_packet (ctrl,
+                                           &newsig, sig, main_pk, uid, NULL,
+                                          main_pk, keygen_add_key_flags,
+                                          main_pk);
+             else
+               rc =
+                 update_keysig_packet (ctrl,
+                                        &newsig, sig, main_pk, NULL, sub_pk,
+                                       main_pk, keygen_add_key_flags, sub_pk);
+             if (rc)
+               {
+                 log_error ("make_keysig_packet failed: %s\n",
+                            gpg_strerror (rc));
+                 return 0;
+               }
+
+             /* Replace the packet.  */
+             newpkt = xmalloc_clear (sizeof *newpkt);
+             newpkt->pkttype = PKT_SIGNATURE;
+             newpkt->pkt.signature = newsig;
+             free_packet (node->pkt, NULL);
+             xfree (node->pkt);
+             node->pkt = newpkt;
+             sub_pk = NULL;
+              break;
+           }
+       }
+    }
+
   return 1;
 }
 
 
 static int
   return 1;
 }
 
 
 static int
-menu_backsign (KBNODE pub_keyblock)
+menu_backsign (ctrl_t ctrl, kbnode_t pub_keyblock)
 {
   int rc, modified = 0;
   PKT_public_key *main_pk;
   KBNODE node;
   u32 timestamp;
 
 {
   int rc, modified = 0;
   PKT_public_key *main_pk;
   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);
+  merge_keys_and_selfsig (ctrl, pub_keyblock);
   main_pk = pub_keyblock->pkt->pkt.public_key;
   keyid_from_pk (main_pk, NULL);
 
   main_pk = pub_keyblock->pkt->pkt.public_key;
   keyid_from_pk (main_pk, NULL);
 
@@ -4194,14 +4721,16 @@ menu_backsign (KBNODE pub_keyblock)
 
       /* Now we can get to work.  */
 
 
       /* Now we can get to work.  */
 
-      rc = make_backsig (sig_pk->pkt->pkt.signature, main_pk, sub_pk, sub_pk,
+      rc = make_backsig (ctrl,
+                         sig_pk->pkt->pkt.signature, main_pk, sub_pk, sub_pk,
                         timestamp, NULL);
       if (!rc)
        {
          PKT_signature *newsig;
          PACKET *newpkt;
 
                         timestamp, NULL);
       if (!rc)
        {
          PKT_signature *newsig;
          PACKET *newpkt;
 
-         rc = update_keysig_packet (&newsig, sig_pk->pkt->pkt.signature,
+         rc = update_keysig_packet (ctrl,
+                                     &newsig, sig_pk->pkt->pkt.signature,
                                      main_pk, NULL, sub_pk, main_pk,
                                      NULL, NULL);
          if (!rc)
                                      main_pk, NULL, sub_pk, main_pk,
                                      NULL, NULL);
          if (!rc)
@@ -4210,7 +4739,7 @@ menu_backsign (KBNODE pub_keyblock)
              newpkt = xmalloc_clear (sizeof (*newpkt));
              newpkt->pkttype = PKT_SIGNATURE;
              newpkt->pkt.signature = newsig;
              newpkt = xmalloc_clear (sizeof (*newpkt));
              newpkt->pkttype = PKT_SIGNATURE;
              newpkt->pkt.signature = newsig;
-             free_packet (sig_pk->pkt);
+             free_packet (sig_pk->pkt, NULL);
              xfree (sig_pk->pkt);
              sig_pk->pkt = newpkt;
 
              xfree (sig_pk->pkt);
              sig_pk->pkt = newpkt;
 
@@ -4257,14 +4786,14 @@ change_primary_uid_cb (PKT_signature * sig, void *opaque)
 
 /*
  * Set the primary uid flag for the selected UID.  We will also reset
 
 /*
  * Set the primary uid flag for the selected UID.  We will also reset
- * all other primary uid flags.  For this to work with have to update
+ * all other primary uid flags.  For this to work we have to update
  * all the signature timestamps.  If we would do this with the current
  * all the signature timestamps.  If we would do this with the current
- * time, we lose quite a lot of information, so we use a kludge to
+ * time, we lose quite a lot of information, so we use a kludge to
  * do this: Just increment the timestamp by one second which is
  * sufficient to updated a signature during import.
  */
 static int
  * do this: Just increment the timestamp by one second which is
  * sufficient to updated a signature during import.
  */
 static int
-menu_set_primary_uid (KBNODE pub_keyblock)
+menu_set_primary_uid (ctrl_t ctrl, kbnode_t pub_keyblock)
 {
   PKT_public_key *main_pk;
   PKT_user_id *uid;
 {
   PKT_public_key *main_pk;
   PKT_user_id *uid;
@@ -4353,7 +4882,7 @@ menu_set_primary_uid (KBNODE pub_keyblock)
 
                  if (action)
                    {
 
                  if (action)
                    {
-                     int rc = update_keysig_packet (&newsig, sig,
+                     int rc = update_keysig_packet (ctrl, &newsig, sig,
                                                     main_pk, uid, NULL,
                                                     main_pk,
                                                     change_primary_uid_cb,
                                                     main_pk, uid, NULL,
                                                     main_pk,
                                                     change_primary_uid_cb,
@@ -4368,7 +4897,7 @@ menu_set_primary_uid (KBNODE pub_keyblock)
                      newpkt = xmalloc_clear (sizeof *newpkt);
                      newpkt->pkttype = PKT_SIGNATURE;
                      newpkt->pkt.signature = newsig;
                      newpkt = xmalloc_clear (sizeof *newpkt);
                      newpkt->pkttype = PKT_SIGNATURE;
                      newpkt->pkt.signature = newsig;
-                     free_packet (node->pkt);
+                     free_packet (node->pkt, NULL);
                      xfree (node->pkt);
                      node->pkt = newpkt;
                      modified = 1;
                      xfree (node->pkt);
                      node->pkt = newpkt;
                      modified = 1;
@@ -4386,7 +4915,7 @@ menu_set_primary_uid (KBNODE pub_keyblock)
  * Set preferences to new values for the selected user IDs
  */
 static int
  * Set preferences to new values for the selected user IDs
  */
 static int
-menu_set_preferences (KBNODE pub_keyblock)
+menu_set_preferences (ctrl_t ctrl, kbnode_t pub_keyblock)
 {
   PKT_public_key *main_pk;
   PKT_user_id *uid;
 {
   PKT_public_key *main_pk;
   PKT_user_id *uid;
@@ -4444,7 +4973,7 @@ menu_set_preferences (KBNODE pub_keyblock)
                  PACKET *newpkt;
                  int rc;
 
                  PACKET *newpkt;
                  int rc;
 
-                 rc = update_keysig_packet (&newsig, sig,
+                 rc = update_keysig_packet (ctrl, &newsig, sig,
                                             main_pk, uid, NULL, main_pk,
                                              keygen_upd_std_prefs, NULL);
                  if (rc)
                                             main_pk, uid, NULL, main_pk,
                                              keygen_upd_std_prefs, NULL);
                  if (rc)
@@ -4457,7 +4986,7 @@ menu_set_preferences (KBNODE pub_keyblock)
                  newpkt = xmalloc_clear (sizeof *newpkt);
                  newpkt->pkttype = PKT_SIGNATURE;
                  newpkt->pkt.signature = newsig;
                  newpkt = xmalloc_clear (sizeof *newpkt);
                  newpkt->pkttype = PKT_SIGNATURE;
                  newpkt->pkt.signature = newsig;
-                 free_packet (node->pkt);
+                 free_packet (node->pkt, NULL);
                  xfree (node->pkt);
                  node->pkt = newpkt;
                  modified = 1;
                  xfree (node->pkt);
                  node->pkt = newpkt;
                  modified = 1;
@@ -4471,7 +5000,7 @@ menu_set_preferences (KBNODE pub_keyblock)
 
 
 static int
 
 
 static int
-menu_set_keyserver_url (const char *url, KBNODE pub_keyblock)
+menu_set_keyserver_url (ctrl_t ctrl, const char *url, kbnode_t pub_keyblock)
 {
   PKT_public_key *main_pk;
   PKT_user_id *uid;
 {
   PKT_public_key *main_pk;
   PKT_user_id *uid;
@@ -4578,7 +5107,7 @@ menu_set_keyserver_url (const char *url, KBNODE pub_keyblock)
                      continue;
                    }
 
                      continue;
                    }
 
-                 rc = update_keysig_packet (&newsig, sig,
+                 rc = update_keysig_packet (ctrl, &newsig, sig,
                                             main_pk, uid, NULL,
                                             main_pk,
                                             keygen_add_keyserver_url, uri);
                                             main_pk, uid, NULL,
                                             main_pk,
                                             keygen_add_keyserver_url, uri);
@@ -4593,7 +5122,7 @@ menu_set_keyserver_url (const char *url, KBNODE pub_keyblock)
                  newpkt = xmalloc_clear (sizeof *newpkt);
                  newpkt->pkttype = PKT_SIGNATURE;
                  newpkt->pkt.signature = newsig;
                  newpkt = xmalloc_clear (sizeof *newpkt);
                  newpkt->pkttype = PKT_SIGNATURE;
                  newpkt->pkt.signature = newsig;
-                 free_packet (node->pkt);
+                 free_packet (node->pkt, NULL);
                  xfree (node->pkt);
                  node->pkt = newpkt;
                  modified = 1;
                  xfree (node->pkt);
                  node->pkt = newpkt;
                  modified = 1;
@@ -4608,8 +5137,9 @@ menu_set_keyserver_url (const char *url, KBNODE pub_keyblock)
   return modified;
 }
 
   return modified;
 }
 
+
 static int
 static int
-menu_set_notation (const char *string, KBNODE pub_keyblock)
+menu_set_notation (ctrl_t ctrl, const char *string, KBNODE pub_keyblock)
 {
   PKT_public_key *main_pk;
   PKT_user_id *uid;
 {
   PKT_public_key *main_pk;
   PKT_user_id *uid;
@@ -4777,7 +5307,7 @@ menu_set_notation (const char *string, KBNODE pub_keyblock)
                                                  _("Proceed? (y/N) "))))
                    continue;
 
                                                  _("Proceed? (y/N) "))))
                    continue;
 
-                 rc = update_keysig_packet (&newsig, sig,
+                 rc = update_keysig_packet (ctrl, &newsig, sig,
                                             main_pk, uid, NULL,
                                             main_pk,
                                             keygen_add_notations, notation);
                                             main_pk, uid, NULL,
                                             main_pk,
                                             keygen_add_notations, notation);
@@ -4794,7 +5324,7 @@ menu_set_notation (const char *string, KBNODE pub_keyblock)
                  newpkt = xmalloc_clear (sizeof *newpkt);
                  newpkt->pkttype = PKT_SIGNATURE;
                  newpkt->pkt.signature = newsig;
                  newpkt = xmalloc_clear (sizeof *newpkt);
                  newpkt->pkttype = PKT_SIGNATURE;
                  newpkt->pkt.signature = newsig;
-                 free_packet (node->pkt);
+                 free_packet (node->pkt, NULL);
                  xfree (node->pkt);
                  node->pkt = newpkt;
                  modified = 1;
                  xfree (node->pkt);
                  node->pkt = newpkt;
                  modified = 1;
@@ -4881,7 +5411,7 @@ menu_select_uid_namehash (KBNODE keyblock, const char *namehash)
   KBNODE node;
   int i;
 
   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]);
 
   for (i = 0; i < NAMEHASH_LEN; i++)
     hash[i] = hextobyte (&namehash[i * 2]);
@@ -5136,7 +5666,7 @@ real_uids_left (KBNODE keyblock)
  * flag bit MARK_A is set on the signature and the user ID.
  */
 static void
  * flag bit MARK_A is set on the signature and the user ID.
  */
 static void
-ask_revoke_sig (KBNODE keyblock, KBNODE node)
+ask_revoke_sig (ctrl_t ctrl, kbnode_t keyblock, kbnode_t node)
 {
   int doit = 0;
   PKT_user_id *uid;
 {
   int doit = 0;
   PKT_user_id *uid;
@@ -5163,8 +5693,8 @@ ask_revoke_sig (KBNODE keyblock, KBNODE node)
 
       es_printf ("\n");
 
 
       es_printf ("\n");
 
-      print_and_check_one_sig_colon (keyblock, node, NULL, NULL, NULL, NULL,
-                                    1);
+      print_and_check_one_sig_colon (ctrl, keyblock, node,
+                                     NULL, NULL, NULL, NULL, 1);
     }
   else
     {
     }
   else
     {
@@ -5206,7 +5736,7 @@ ask_revoke_sig (KBNODE keyblock, KBNODE node)
  * Return: True when the keyblock has changed.
  */
 static int
  * Return: True when the keyblock has changed.
  */
 static int
-menu_revsig (KBNODE keyblock)
+menu_revsig (ctrl_t ctrl, kbnode_t keyblock)
 {
   PKT_signature *sig;
   PKT_public_key *primary_pk;
 {
   PKT_signature *sig;
   PKT_public_key *primary_pk;
@@ -5215,7 +5745,7 @@ menu_revsig (KBNODE keyblock)
   int rc, any, skip = 1, all = !count_selected_uids (keyblock);
   struct revocation_reason_info *reason = NULL;
 
   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;
 
   /* First check whether we have any signatures at all.  */
   any = 0;
@@ -5298,7 +5828,7 @@ menu_revsig (KBNODE keyblock)
     {
       if (!(node->flag & NODFLG_SELSIG))
        continue;
     {
       if (!(node->flag & NODFLG_SELSIG))
        continue;
-      ask_revoke_sig (keyblock, node);
+      ask_revoke_sig (ctrl, keyblock, node);
     }
 
   /* present selected */
     }
 
   /* present selected */
@@ -5343,7 +5873,7 @@ menu_revsig (KBNODE keyblock)
     }
 
   /* now we can sign the user ids */
     }
 
   /* now we can sign the user ids */
-reloop:                        /* (must use this, because we are modifing the list) */
+reloop:                        /* (must use this, because we are modifying the list) */
   primary_pk = keyblock->pkt->pkt.public_key;
   for (node = keyblock; node; node = node->next)
     {
   primary_pk = keyblock->pkt->pkt.public_key;
   for (node = keyblock; node; node = node->next)
     {
@@ -5356,7 +5886,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);
          || 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;
 
       memset (&attrib, 0, sizeof attrib);
       attrib.reason = reason;
@@ -5364,13 +5894,13 @@ reloop:                 /* (must use this, because we are modifing the list) */
 
       node->flag &= ~NODFLG_MARK_A;
       signerkey = xmalloc_secure_clear (sizeof *signerkey);
 
       node->flag &= ~NODFLG_MARK_A;
       signerkey = xmalloc_secure_clear (sizeof *signerkey);
-      if (get_seckey (signerkey, node->pkt->pkt.signature->keyid))
+      if (get_seckey (ctrl, signerkey, node->pkt->pkt.signature->keyid))
        {
          log_info (_("no secret key\n"));
           free_public_key (signerkey);
          continue;
        }
        {
          log_info (_("no secret key\n"));
           free_public_key (signerkey);
          continue;
        }
-      rc = make_keysig_packet (&sig, primary_pk,
+      rc = make_keysig_packet (ctrl, &sig, primary_pk,
                               unode->pkt->pkt.user_id,
                               NULL, signerkey, 0x30, 0, 0, 0,
                                sign_mk_attrib, &attrib, NULL);
                               unode->pkt->pkt.user_id,
                               NULL, signerkey, 0x30, 0, 0, 0,
                                sign_mk_attrib, &attrib, NULL);
@@ -5387,7 +5917,7 @@ reloop:                   /* (must use this, because we are modifing the list) */
       /* Are we revoking our own uid? */
       if (primary_pk->keyid[0] == sig->keyid[0] &&
          primary_pk->keyid[1] == sig->keyid[1])
       /* Are we revoking our own uid? */
       if (primary_pk->keyid[0] == sig->keyid[0] &&
          primary_pk->keyid[1] == sig->keyid[1])
-       unode->pkt->pkt.user_id->is_revoked = 1;
+       unode->pkt->pkt.user_id->flags.revoked = 1;
       pkt = xmalloc_clear (sizeof *pkt);
       pkt->pkttype = PKT_SIGNATURE;
       pkt->pkt.signature = sig;
       pkt = xmalloc_clear (sizeof *pkt);
       pkt->pkttype = PKT_SIGNATURE;
       pkt->pkt.signature = sig;
@@ -5400,16 +5930,107 @@ reloop:                        /* (must use this, because we are modifing the list) */
 }
 
 
 }
 
 
+/* return 0 if revocation of NODE (which must be a User ID) was
+   successful, non-zero if there was an error.  *modified will be set
+   to 1 if a change was made. */
+static int
+core_revuid (ctrl_t ctrl, kbnode_t keyblock, KBNODE node,
+             const struct revocation_reason_info *reason, int *modified)
+{
+  PKT_public_key *pk = keyblock->pkt->pkt.public_key;
+  gpg_error_t rc;
+
+  if (node->pkt->pkttype != PKT_USER_ID)
+    {
+      rc = gpg_error (GPG_ERR_NO_USER_ID);
+      write_status_error ("keysig", rc);
+      log_error (_("tried to revoke a non-user ID: %s\n"), gpg_strerror (rc));
+      return 1;
+    }
+  else
+    {
+      PKT_user_id *uid = node->pkt->pkt.user_id;
+
+      if (uid->flags.revoked)
+        {
+          char *user = utf8_to_native (uid->name, uid->len, 0);
+          log_info (_("user ID \"%s\" is already revoked\n"), user);
+          xfree (user);
+        }
+      else
+        {
+          PACKET *pkt;
+          PKT_signature *sig;
+          struct sign_attrib attrib;
+          u32 timestamp = make_timestamp ();
+
+          if (uid->created >= timestamp)
+            {
+              /* Okay, this is a problem.  The user ID selfsig was
+                 created in the future, so we need to warn the user and
+                 set our revocation timestamp one second after that so
+                 everything comes out clean. */
+
+              log_info (_("WARNING: a user ID signature is dated %d"
+                          " seconds in the future\n"),
+                        uid->created - timestamp);
+
+              timestamp = uid->created + 1;
+            }
+
+          memset (&attrib, 0, sizeof attrib);
+          /* should not need to cast away const here; but
+             revocation_reason_build_cb needs to take a non-const
+             void* in order to meet the function signtuare for the
+             mksubpkt argument to make_keysig_packet */
+          attrib.reason = (struct revocation_reason_info *)reason;
+
+          rc = make_keysig_packet (ctrl, &sig, pk, uid, NULL, pk, 0x30, 0,
+                                   timestamp, 0,
+                                   sign_mk_attrib, &attrib, NULL);
+          if (rc)
+            {
+              write_status_error ("keysig", rc);
+              log_error (_("signing failed: %s\n"), gpg_strerror (rc));
+              return 1;
+            }
+          else
+            {
+              pkt = xmalloc_clear (sizeof *pkt);
+              pkt->pkttype = PKT_SIGNATURE;
+              pkt->pkt.signature = sig;
+              insert_kbnode (node, new_kbnode (pkt), 0);
+
+#ifndef NO_TRUST_MODELS
+              /* If the trustdb has an entry for this key+uid then the
+                 trustdb needs an update. */
+              if (!update_trust
+                  && ((get_validity (ctrl, keyblock, pk, uid, NULL, 0)
+                       & TRUST_MASK)
+                      >= TRUST_UNDEFINED))
+                update_trust = 1;
+#endif /*!NO_TRUST_MODELS*/
+
+              node->pkt->pkt.user_id->flags.revoked = 1;
+              if (modified)
+                *modified = 1;
+            }
+        }
+      return 0;
+    }
+}
+
 /* Revoke a user ID (i.e. revoke a user ID selfsig).  Return true if
    keyblock changed.  */
 static int
 /* 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;
   int changed = 0;
   int rc;
   struct revocation_reason_info *reason = NULL;
 {
   PKT_public_key *pk = pub_keyblock->pkt->pkt.public_key;
   KBNODE node;
   int changed = 0;
   int rc;
   struct revocation_reason_info *reason = NULL;
+  size_t valid_uids;
 
   /* Note that this is correct as per the RFCs, but nevertheless
      somewhat meaningless in the real world.  1991 did define the 0x30
 
   /* Note that this is correct as per the RFCs, but nevertheless
      somewhat meaningless in the real world.  1991 did define the 0x30
@@ -5426,75 +6047,39 @@ menu_revuid (KBNODE pub_keyblock)
          goto leave;
       }
 
          goto leave;
       }
 
- reloop: /* (better this way because we are modifing the keyring) */
+  /* Too make sure that we do not revoke the last valid UID, we first
+     count how many valid UIDs there are.  */
+  valid_uids = 0;
+  for (node = pub_keyblock; node; node = node->next)
+    valid_uids +=
+      node->pkt->pkttype == PKT_USER_ID
+      && ! node->pkt->pkt.user_id->flags.revoked
+      && ! node->pkt->pkt.user_id->flags.expired;
+
+ reloop: /* (better this way because we are modifying the keyring) */
   for (node = pub_keyblock; node; node = node->next)
     if (node->pkt->pkttype == PKT_USER_ID && (node->flag & NODFLG_SELUID))
       {
   for (node = pub_keyblock; node; node = node->next)
     if (node->pkt->pkttype == PKT_USER_ID && (node->flag & NODFLG_SELUID))
       {
-       PKT_user_id *uid = node->pkt->pkt.user_id;
-
-       if (uid->is_revoked)
-         {
-           char *user = utf8_to_native (uid->name, uid->len, 0);
-           log_info (_("user ID \"%s\" is already revoked\n"), user);
-           xfree (user);
-         }
-       else
-         {
-           PACKET *pkt;
-           PKT_signature *sig;
-           struct sign_attrib attrib;
-           u32 timestamp = make_timestamp ();
+        int modified = 0;
 
 
-           if (uid->created >= timestamp)
-             {
-               /* Okay, this is a problem.  The user ID selfsig was
-                  created in the future, so we need to warn the user and
-                  set our revocation timestamp one second after that so
-                  everything comes out clean. */
-
-               log_info (_("WARNING: a user ID signature is dated %d"
-                           " seconds in the future\n"),
-                         uid->created - timestamp);
-
-               timestamp = uid->created + 1;
-             }
-
-           memset (&attrib, 0, sizeof attrib);
-           attrib.reason = reason;
+        /* Make sure that we do not revoke the last valid UID.  */
+        if (valid_uids == 1
+            && ! node->pkt->pkt.user_id->flags.revoked
+            && ! node->pkt->pkt.user_id->flags.expired)
+          {
+            log_error (_("Cannot revoke the last valid user ID.\n"));
+            goto leave;
+          }
 
 
+        rc = core_revuid (ctrl, pub_keyblock, node, reason, &modified);
+        if (rc)
+          goto leave;
+        if (modified)
+          {
            node->flag &= ~NODFLG_SELUID;
            node->flag &= ~NODFLG_SELUID;
-
-           rc = make_keysig_packet (&sig, pk, uid, NULL, pk, 0x30, 0,
-                                    timestamp, 0,
-                                    sign_mk_attrib, &attrib, NULL);
-           if (rc)
-             {
-                write_status_error ("keysig", rc);
-               log_error (_("signing failed: %s\n"), gpg_strerror (rc));
-               goto leave;
-             }
-           else
-             {
-               pkt = xmalloc_clear (sizeof *pkt);
-               pkt->pkttype = PKT_SIGNATURE;
-               pkt->pkt.signature = sig;
-               insert_kbnode (node, new_kbnode (pkt), 0);
-
-#ifndef NO_TRUST_MODELS
-               /* 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) >=
-                   TRUST_UNDEFINED)
-                 update_trust = 1;
-#endif /*!NO_TRUST_MODELS*/
-
-               changed = 1;
-               node->pkt->pkt.user_id->is_revoked = 1;
-
-               goto reloop;
-             }
-         }
+            changed = 1;
+            goto reloop;
+          }
       }
 
   if (changed)
       }
 
   if (changed)
@@ -5510,7 +6095,7 @@ leave:
  * Revoke the whole key.
  */
 static int
  * Revoke the whole key.
  */
 static int
-menu_revkey (KBNODE pub_keyblock)
+menu_revkey (ctrl_t ctrl, kbnode_t pub_keyblock)
 {
   PKT_public_key *pk = pub_keyblock->pkt->pkt.public_key;
   int rc, changed = 0;
 {
   PKT_public_key *pk = pub_keyblock->pkt->pkt.public_key;
   int rc, changed = 0;
@@ -5529,7 +6114,7 @@ menu_revkey (KBNODE pub_keyblock)
   if (!reason)
     return 0;
 
   if (!reason)
     return 0;
 
-  rc = make_keysig_packet (&sig, pk, NULL, NULL, pk,
+  rc = make_keysig_packet (ctrl, &sig, pk, NULL, NULL, pk,
                           0x20, 0, 0, 0,
                           revocation_reason_build_cb, reason, NULL);
   if (rc)
                           0x20, 0, 0, 0,
                           revocation_reason_build_cb, reason, NULL);
   if (rc)
@@ -5556,7 +6141,7 @@ menu_revkey (KBNODE pub_keyblock)
 
 
 static int
 
 
 static int
-menu_revsubkey (KBNODE pub_keyblock)
+menu_revsubkey (ctrl_t ctrl, kbnode_t pub_keyblock)
 {
   PKT_public_key *mainpk;
   KBNODE node;
 {
   PKT_public_key *mainpk;
   KBNODE node;
@@ -5568,7 +6153,7 @@ menu_revsubkey (KBNODE pub_keyblock)
   if (!reason)
       return 0; /* User decided to cancel.  */
 
   if (!reason)
       return 0; /* User decided to cancel.  */
 
- reloop: /* (better this way because we are modifing the keyring) */
+ reloop: /* (better this way because we are modifying the keyring) */
   mainpk = pub_keyblock->pkt->pkt.public_key;
   for (node = pub_keyblock; node; node = node->next)
     {
   mainpk = pub_keyblock->pkt->pkt.public_key;
   for (node = pub_keyblock; node; node = node->next)
     {
@@ -5591,7 +6176,7 @@ menu_revsubkey (KBNODE pub_keyblock)
          attrib.reason = reason;
 
          node->flag &= ~NODFLG_SELKEY;
          attrib.reason = reason;
 
          node->flag &= ~NODFLG_SELKEY;
-         rc = make_keysig_packet (&sig, mainpk, NULL, subpk, mainpk,
+         rc = make_keysig_packet (ctrl, &sig, mainpk, NULL, subpk, mainpk,
                                   0x28, 0, 0, 0, sign_mk_attrib, &attrib,
                                    NULL);
          if (rc)
                                   0x28, 0, 0, 0, sign_mk_attrib, &attrib,
                                    NULL);
          if (rc)
@@ -5627,26 +6212,26 @@ menu_revsubkey (KBNODE pub_keyblock)
    not worth adding extra complexity to change. -ds */
 #ifndef NO_TRUST_MODELS
 static int
    not worth adding extra complexity to change. -ds */
 #ifndef NO_TRUST_MODELS
 static int
-enable_disable_key (KBNODE keyblock, int disable)
+enable_disable_key (ctrl_t ctrl, kbnode_t keyblock, int disable)
 {
   PKT_public_key *pk =
     find_kbnode (keyblock, PKT_PUBLIC_KEY)->pkt->pkt.public_key;
   unsigned int trust, newtrust;
 
 {
   PKT_public_key *pk =
     find_kbnode (keyblock, PKT_PUBLIC_KEY)->pkt->pkt.public_key;
   unsigned int trust, newtrust;
 
-  trust = newtrust = get_ownertrust (pk);
+  trust = newtrust = get_ownertrust (ctrl, pk);
   newtrust &= ~TRUST_FLAG_DISABLED;
   if (disable)
     newtrust |= TRUST_FLAG_DISABLED;
   if (trust == newtrust)
     return 0;                  /* already in that state */
   newtrust &= ~TRUST_FLAG_DISABLED;
   if (disable)
     newtrust |= TRUST_FLAG_DISABLED;
   if (trust == newtrust)
     return 0;                  /* already in that state */
-  update_ownertrust (pk, newtrust);
+  update_ownertrust (ctrl, pk, newtrust);
   return 0;
 }
 #endif /*!NO_TRUST_MODELS*/
 
 
 static void
   return 0;
 }
 #endif /*!NO_TRUST_MODELS*/
 
 
 static void
-menu_showphoto (KBNODE keyblock)
+menu_showphoto (ctrl_t ctrl, kbnode_t keyblock)
 {
   KBNODE node;
   int select_all = !count_selected_uids (keyblock);
 {
   KBNODE node;
   int select_all = !count_selected_uids (keyblock);
@@ -5683,7 +6268,7 @@ menu_showphoto (KBNODE keyblock)
                                    "key %s (uid %d)\n"),
                                  image_type_to_string (type, 1),
                                  (ulong) size, keystr_from_pk (pk), count);
                                    "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);
                    }
                }
            }
                    }
                }
            }