[git] GnuPG - branch, master, updated. gnupg-2.1.21-55-g9b12b45

by Justus Winter cvs at cvs.gnupg.org
Wed Jun 14 09:44:28 CEST 2017


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "The GNU Privacy Guard".

The branch, master has been updated
       via  9b12b45aa5e67d4d422bf75a3879df1d52dbe67f (commit)
       via  404fa8211b6188a0abe83ef43a4b44d528c0b035 (commit)
       via  8095d16b3ef6b5f01ec351824855708149f1c1c3 (commit)
      from  15d2a009931f44a60b9df6325f837add208459d6 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 9b12b45aa5e67d4d422bf75a3879df1d52dbe67f
Author: Justus Winter <justus at g10code.com>
Date:   Tue Jun 13 15:35:01 2017 +0200

    gpg: Check and fix keys on import.
    
    * doc/gpg.texi: Document the new import option.
    * g10/gpg.c (main): Make the new option default to yes.
    * g10/import.c (parse_import_options): Parse the new option.
    (import_one): Act on the new option.
    * g10/options.h (IMPORT_REPAIR_KEYS): New macro.
    
    GnuPG-bug-id: 2236
    Signed-off-by: Justus Winter <justus at g10code.com>

diff --git a/doc/gpg.texi b/doc/gpg.texi
index c128254..1933ad8 100644
--- a/doc/gpg.texi
+++ b/doc/gpg.texi
@@ -2304,6 +2304,10 @@ opposite meaning. The options are:
   on the keyring. This option is the same as running the @option{--edit-key}
   command "clean" after import. Defaults to no.
 
+  @item repair-keys.  After import, fix various problems with the
+  keys.  For example, this reorders signatures, and strips duplicate
+  signatures.  Defaults to yes.
+
   @item import-minimal
   Import the smallest key possible. This removes all signatures except
   the most recent self-signature on each user ID. This option is the
diff --git a/g10/gpg.c b/g10/gpg.c
index d777d13..d129769 100644
--- a/g10/gpg.c
+++ b/g10/gpg.c
@@ -2353,9 +2353,10 @@ main (int argc, char **argv)
     opt.max_cert_depth = 5;
     opt.escape_from = 1;
     opt.flags.require_cross_cert = 1;
-    opt.import_options = 0;
+    opt.import_options = IMPORT_REPAIR_KEYS;
     opt.export_options = EXPORT_ATTRIBUTES;
-    opt.keyserver_options.import_options = IMPORT_REPAIR_PKS_SUBKEY_BUG;
+    opt.keyserver_options.import_options = (IMPORT_REPAIR_KEYS
+					    | IMPORT_REPAIR_PKS_SUBKEY_BUG);
     opt.keyserver_options.export_options = EXPORT_ATTRIBUTES;
     opt.keyserver_options.options = KEYSERVER_HONOR_PKA_RECORD;
     opt.verify_options = (LIST_SHOW_UID_VALIDITY
diff --git a/g10/import.c b/g10/import.c
index d9d658b..491609d 100644
--- a/g10/import.c
+++ b/g10/import.c
@@ -40,6 +40,7 @@
 #include "../common/membuf.h"
 #include "../common/init.h"
 #include "../common/mbox-util.h"
+#include "key-check.h"
 
 
 struct import_stats_s
@@ -179,6 +180,9 @@ parse_import_options(char *str,unsigned int *options,int noisy)
        N_("assume the GnuPG key backup format")},
       {"import-restore", IMPORT_RESTORE, NULL, NULL},
 
+      {"repair-keys", IMPORT_REPAIR_KEYS, NULL,
+       N_("repair keys on import")},
+
       /* Aliases for backward compatibility */
       {"allow-local-sigs",IMPORT_LOCAL_SIGS,NULL,NULL},
       {"repair-hkp-subkey-bug",IMPORT_REPAIR_PKS_SUBKEY_BUG,NULL,NULL},
@@ -1482,6 +1486,9 @@ import_one (ctrl_t ctrl,
     log_info (_("key %s: PKS subkey corruption repaired\n"),
               keystr_from_pk(pk));
 
+  if ((options & IMPORT_REPAIR_KEYS))
+    key_check_all_keysigs (ctrl, keyblock, 0, 0);
+
   if (chk_self_sigs (ctrl, keyblock, keyid, &non_self))
     return 0;  /* Invalid keyblock - error already printed.  */
 
diff --git a/g10/options.h b/g10/options.h
index 8d1d93e..98417d7 100644
--- a/g10/options.h
+++ b/g10/options.h
@@ -346,6 +346,7 @@ EXTERN_UNLESS_MAIN_MODULE int memory_stat_debug_mode;
 #define IMPORT_KEEP_OWNERTTRUST          (1<<8)
 #define IMPORT_EXPORT                    (1<<9)
 #define IMPORT_RESTORE                   (1<<10)
+#define IMPORT_REPAIR_KEYS               (1<<11)
 
 #define EXPORT_LOCAL_SIGS                (1<<0)
 #define EXPORT_ATTRIBUTES                (1<<1)

commit 404fa8211b6188a0abe83ef43a4b44d528c0b035
Author: Justus Winter <justus at g10code.com>
Date:   Tue Jun 13 15:34:03 2017 +0200

    gpg: Refactor key checking and fixing.
    
    * g10/Makefile.am (gpg_sources): Add new files.
    * g10/gpgcompose.c (keyedit_print_one_sig): New stub.
    * g10/keyedit.c (sig_comparison): Move to new module.
    (check_all_keysigs): Likewise.
    (fix_keyblock): Adapt callsite.
    (keyedit_menu): Likewise.
    * g10/key-check.c: New file.
    * g10/key-check.h: Likewise.
    
    GnuPG-bug-id: 2236
    Signed-off-by: Justus Winter <justus at g10code.com>

diff --git a/g10/Makefile.am b/g10/Makefile.am
index 9994ea1..d5c92f8 100644
--- a/g10/Makefile.am
+++ b/g10/Makefile.am
@@ -150,7 +150,8 @@ gpg_sources = server.c          \
 	      call-agent.c call-agent.h \
 	      trust.c $(trust_source) $(tofu_source) \
 	      $(card_source) \
-	      exec.c exec.h
+	      exec.c exec.h \
+	      key-check.c key-check.h
 
 gpg_SOURCES  = gpg.c \
 	keyedit.c keyedit.h	\
diff --git a/g10/gpgcompose.c b/g10/gpgcompose.c
index 8e29c2f..f38d755 100644
--- a/g10/gpgcompose.c
+++ b/g10/gpgcompose.c
@@ -3063,3 +3063,21 @@ show_basic_key_info (ctrl_t ctrl, KBNODE keyblock)
   (void)ctrl;
   (void) keyblock;
 }
+
+int
+keyedit_print_one_sig (ctrl_t ctrl, 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)
+{
+  (void) ctrl;
+  (void) rc;
+  (void) keyblock;
+  (void) node;
+  (void) inv_sigs;
+  (void) no_key;
+  (void) oth_err;
+  (void) is_selfsig;
+  (void) print_without_key;
+  (void) extended;
+  return 0;
+}
diff --git a/g10/key-check.c b/g10/key-check.c
new file mode 100644
index 0000000..a22394d
--- /dev/null
+++ b/g10/key-check.c
@@ -0,0 +1,640 @@
+/* key-check.c - Detect and fix various problems with keys
+ * Copyright (C) 1998-2010 Free Software Foundation, Inc.
+ * Copyright (C) 1998-2017 Werner Koch
+ * Copyright (C) 2015-2017 g10 Code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include "gpg.h"
+#include "options.h"
+#include "packet.h"
+#include "keydb.h"
+#include "main.h"
+#include "../common/ttyio.h"
+#include "../common/i18n.h"
+#include "keyedit.h"
+
+#include "key-check.h"
+
+/* Order two signatures.  The actual ordering isn't important.  Our
+   goal is to ensure that identical signatures occur together.  */
+static int
+sig_comparison (const void *av, const void *bv)
+{
+  const KBNODE an = *(const KBNODE *) av;
+  const KBNODE bn = *(const KBNODE *) bv;
+  const PKT_signature *a;
+  const PKT_signature *b;
+  int ndataa;
+  int ndatab;
+  int i;
+
+  log_assert (an->pkt->pkttype == PKT_SIGNATURE);
+  log_assert (bn->pkt->pkttype == PKT_SIGNATURE);
+
+  a = an->pkt->pkt.signature;
+  b = bn->pkt->pkt.signature;
+
+  if (a->digest_algo < b->digest_algo)
+    return -1;
+  if (a->digest_algo > b->digest_algo)
+    return 1;
+
+  ndataa = pubkey_get_nsig (a->pubkey_algo);
+  ndatab = pubkey_get_nsig (b->pubkey_algo);
+  if (ndataa != ndatab)
+    return (ndataa < ndatab)? -1 : 1;
+
+  for (i = 0; i < ndataa; i ++)
+    {
+      int c = gcry_mpi_cmp (a->data[i], b->data[i]);
+      if (c != 0)
+        return c;
+    }
+
+  /* Okay, they are equal.  */
+  return 0;
+}
+
+/* Perform a few sanity checks on a keyblock is okay and possibly
+   repair some damage.  Concretely:
+
+     - Detect duplicate signatures and remove them.
+
+     - Detect out of order signatures and relocate them (e.g., a sig
+       over user id X located under subkey Y).
+
+   Note: this function does not remove signatures that don't belong or
+   components that are not signed!  (Although it would be trivial to
+   do so.)
+
+   If ONLY_SELFSIGS is true, then this function only reorders self
+   signatures (it still checks all signatures for duplicates,
+   however).
+
+   Returns 1 if the keyblock was modified, 0 otherwise.  */
+int
+key_check_all_keysigs (ctrl_t ctrl, kbnode_t kb,
+                       int only_selected, int only_selfsigs)
+{
+  gpg_error_t err;
+  PKT_public_key *pk;
+  KBNODE n, n_next, *n_prevp, n2;
+  char *pending_desc = NULL;
+  PKT_public_key *issuer;
+  KBNODE last_printed_component;
+  KBNODE current_component = NULL;
+  int dups = 0;
+  int missing_issuer = 0;
+  int reordered = 0;
+  int bad_signature = 0;
+  int missing_selfsig = 0;
+  int modified = 0;
+
+  log_assert (kb->pkt->pkttype == PKT_PUBLIC_KEY);
+  pk = kb->pkt->pkt.public_key;
+
+  /* First we look for duplicates.  */
+  {
+    int nsigs;
+    kbnode_t *sigs;
+    int i;
+    int last_i;
+
+    /* Count the sigs.  */
+    for (nsigs = 0, n = kb; n; n = n->next)
+      {
+        if (is_deleted_kbnode (n))
+          continue;
+        else if (n->pkt->pkttype == PKT_SIGNATURE)
+          nsigs ++;
+      }
+
+    if (!nsigs)
+      return 0; /* No signatures at all.  */
+
+    /* Add them all to the SIGS array.  */
+    sigs = xtrycalloc (nsigs, sizeof *sigs);
+    if (!sigs)
+      {
+        log_error (_("error allocating memory: %s\n"),
+                   gpg_strerror (gpg_error_from_syserror ()));
+        return 0;
+      }
+
+    i = 0;
+    for (n = kb; n; n = n->next)
+      {
+        if (is_deleted_kbnode (n))
+          continue;
+
+        if (n->pkt->pkttype != PKT_SIGNATURE)
+          continue;
+
+        sigs[i] = n;
+        i ++;
+      }
+    log_assert (i == nsigs);
+
+    qsort (sigs, nsigs, sizeof (sigs[0]), sig_comparison);
+
+    last_i = 0;
+    for (i = 1; i < nsigs; i ++)
+      {
+        log_assert (sigs[last_i]);
+        log_assert (sigs[last_i]->pkt->pkttype == PKT_SIGNATURE);
+        log_assert (sigs[i]);
+        log_assert (sigs[i]->pkt->pkttype == PKT_SIGNATURE);
+
+        if (sig_comparison (&sigs[last_i], &sigs[i]) == 0)
+          /* They are the same.  Kill the latter.  */
+          {
+            if (DBG_PACKET)
+              {
+                PKT_signature *sig = sigs[i]->pkt->pkt.signature;
+
+                log_debug ("Signature appears multiple times, "
+                           "deleting duplicate:\n");
+                log_debug ("  sig: class 0x%x, issuer: %s,"
+                           " timestamp: %s (%lld), digest: %02x %02x\n",
+                           sig->sig_class, keystr (sig->keyid),
+                           isotimestamp (sig->timestamp),
+                           (long long) sig->timestamp,
+                           sig->digest_start[0], sig->digest_start[1]);
+              }
+
+            /* Remove sigs[i] from the keyblock.  */
+            {
+              KBNODE z, *prevp;
+              int to_kill = last_i;
+              last_i = i;
+
+              for (prevp = &kb, z = kb; z; prevp = &z->next, z = z->next)
+                if (z == sigs[to_kill])
+                  break;
+
+              *prevp = sigs[to_kill]->next;
+
+              sigs[to_kill]->next = NULL;
+              release_kbnode (sigs[to_kill]);
+              sigs[to_kill] = NULL;
+
+              dups ++;
+              modified = 1;
+            }
+          }
+        else
+          last_i = i;
+      }
+
+    xfree (sigs);
+  }
+
+  /* Make sure the sigs occur after the component (public key, subkey,
+     user id) that they sign.  */
+  issuer = NULL;
+  last_printed_component = NULL;
+  for (n_prevp = &kb, n = kb;
+       n;
+       /* If we moved n, then n_prevp is need valid.  */
+       n_prevp = (n->next == n_next ? &n->next : n_prevp), n = n_next)
+    {
+      PACKET *p;
+      int processed_current_component;
+      PKT_signature *sig;
+      int rc;
+      int dump_sig_params = 0;
+
+      n_next = n->next;
+
+      if (is_deleted_kbnode (n))
+        continue;
+
+      p = n->pkt;
+
+      if (issuer && issuer != pk)
+        {
+          free_public_key (issuer);
+          issuer = NULL;
+        }
+
+      xfree (pending_desc);
+      pending_desc = NULL;
+
+      switch (p->pkttype)
+        {
+        case PKT_PUBLIC_KEY:
+          log_assert (p->pkt.public_key == pk);
+          if (only_selected && ! (n->flag & NODFLG_SELKEY))
+            {
+              current_component = NULL;
+              break;
+            }
+
+          if (DBG_PACKET)
+            log_debug ("public key %s: timestamp: %s (%lld)\n",
+                       pk_keyid_str (pk),
+                       isotimestamp (pk->timestamp),
+                       (long long) pk->timestamp);
+          current_component = n;
+          break;
+        case PKT_PUBLIC_SUBKEY:
+          if (only_selected && ! (n->flag & NODFLG_SELKEY))
+            {
+              current_component = NULL;
+              break;
+            }
+
+          if (DBG_PACKET)
+            log_debug ("subkey %s: timestamp: %s (%lld)\n",
+                       pk_keyid_str (p->pkt.public_key),
+                       isotimestamp (p->pkt.public_key->timestamp),
+                       (long long) p->pkt.public_key->timestamp);
+          current_component = n;
+          break;
+        case PKT_USER_ID:
+          if (only_selected && ! (n->flag & NODFLG_SELUID))
+            {
+              current_component = NULL;
+              break;
+            }
+
+          if (DBG_PACKET)
+            log_debug ("user id: %s\n",
+                       p->pkt.user_id->attrib_data
+                       ? "[ photo id ]"
+                       : p->pkt.user_id->name);
+          current_component = n;
+          break;
+        case PKT_SIGNATURE:
+          if (! current_component)
+            /* The current component is not selected, don't check the
+               sigs under it.  */
+            break;
+
+          sig = n->pkt->pkt.signature;
+
+          pending_desc = xasprintf ("  sig: class: 0x%x, issuer: %s,"
+                                    " timestamp: %s (%lld), digest: %02x %02x",
+                                    sig->sig_class,
+                                    keystr (sig->keyid),
+                                    isotimestamp (sig->timestamp),
+                                    (long long) sig->timestamp,
+                                    sig->digest_start[0], sig->digest_start[1]);
+
+
+          if (keyid_cmp (pk_keyid (pk), sig->keyid) == 0)
+            issuer = pk;
+          else /* Issuer is a different key.  */
+            {
+              if (only_selfsigs)
+                continue;
+
+              issuer = xmalloc (sizeof (*issuer));
+              err = get_pubkey (ctrl, issuer, sig->keyid);
+              if (err)
+                {
+                  xfree (issuer);
+                  issuer = NULL;
+                  if (DBG_PACKET)
+                    {
+                      if (pending_desc)
+                        log_debug ("%s", pending_desc);
+                      log_debug ("    Can't check signature allegedly"
+                                 " issued by %s: %s\n",
+                                 keystr (sig->keyid), gpg_strerror (err));
+                    }
+                  missing_issuer ++;
+                  break;
+                }
+            }
+
+          if ((err = openpgp_pk_test_algo (sig->pubkey_algo)))
+            {
+              if (DBG_PACKET && pending_desc)
+                log_debug ("%s", pending_desc);
+              tty_printf (_("can't check signature with unsupported"
+                            " public-key algorithm (%d): %s.\n"),
+                          sig->pubkey_algo, gpg_strerror (err));
+              break;
+            }
+          if ((err = openpgp_md_test_algo (sig->digest_algo)))
+            {
+              if (DBG_PACKET && pending_desc)
+                log_debug ("%s", pending_desc);
+              tty_printf (_("can't check signature with unsupported"
+                            " message-digest algorithm %d: %s.\n"),
+                          sig->digest_algo, gpg_strerror (err));
+              break;
+            }
+
+          /* We iterate over the keyblock.  Most likely, the matching
+             component is the current component so always try that
+             first.  */
+          processed_current_component = 0;
+          for (n2 = current_component;
+               n2;
+               n2 = (processed_current_component ? n2->next : kb),
+                 processed_current_component = 1)
+            if (is_deleted_kbnode (n2))
+              continue;
+            else if (processed_current_component && n2 == current_component)
+              /* Don't process it twice.  */
+              continue;
+            else
+              {
+                err = check_signature_over_key_or_uid (ctrl,
+                                                       issuer, sig, kb, n2->pkt,
+                                                       NULL, NULL);
+                if (! err)
+                  break;
+              }
+
+          /* n/sig is a signature and n2 is the component (public key,
+             subkey or user id) that it signs, if any.
+             current_component is that component that it appears to
+             apply to (according to the ordering).  */
+
+          if (current_component == n2)
+            {
+              if (DBG_PACKET)
+                {
+                  log_debug ("%s", pending_desc);
+                  log_debug ("    Good signature over last key or uid!\n");
+                }
+
+              rc = 0;
+            }
+          else if (n2)
+            {
+              log_assert (n2->pkt->pkttype == PKT_USER_ID
+                          || n2->pkt->pkttype == PKT_PUBLIC_KEY
+                          || n2->pkt->pkttype == PKT_PUBLIC_SUBKEY);
+
+              if (DBG_PACKET)
+                {
+                  log_debug ("%s", pending_desc);
+                  log_debug ("    Good signature out of order!"
+                             "  (Over %s (%d) '%s')\n",
+                             n2->pkt->pkttype == PKT_USER_ID
+                             ? "user id"
+                             : n2->pkt->pkttype == PKT_PUBLIC_SUBKEY
+                             ? "subkey"
+                             : "primary key",
+                             n2->pkt->pkttype,
+                             n2->pkt->pkttype == PKT_USER_ID
+                             ? n2->pkt->pkt.user_id->name
+                             : pk_keyid_str (n2->pkt->pkt.public_key));
+                }
+
+              /* Reorder the packets: move the signature n to be just
+                 after n2.  */
+
+              /* Unlink the signature.  */
+              log_assert (n_prevp);
+              *n_prevp = n->next;
+
+              /* Insert the sig immediately after the component.  */
+              n->next = n2->next;
+              n2->next = n;
+
+              reordered ++;
+              modified = 1;
+
+              rc = 0;
+            }
+          else
+            {
+              if (DBG_PACKET)
+                {
+                  log_debug ("%s", pending_desc);
+                  log_debug ("    Bad signature.\n");
+                }
+
+              if (DBG_PACKET)
+                dump_sig_params = 1;
+
+              bad_signature ++;
+
+              rc = GPG_ERR_BAD_SIGNATURE;
+            }
+
+          /* We don't cache the result here, because we haven't
+             completely checked that the signature is legitimate.  For
+             instance, if we have a revocation certificate on Alice's
+             key signed by Bob, the signature may be good, but we
+             haven't checked that Bob is a designated revoker.  */
+          /* cache_sig_result (sig, rc); */
+
+          {
+            int has_selfsig = 0;
+            if (! rc && issuer == pk)
+              {
+                if (n2->pkt->pkttype == PKT_PUBLIC_KEY
+                    && (/* Direct key signature.  */
+                        sig->sig_class == 0x1f
+                        /* Key revocation signature.  */
+                        || sig->sig_class == 0x20))
+                  has_selfsig = 1;
+                if (n2->pkt->pkttype == PKT_PUBLIC_SUBKEY
+                    && (/* Subkey binding sig.  */
+                        sig->sig_class == 0x18
+                        /* Subkey revocation sig.  */
+                        || sig->sig_class == 0x28))
+                  has_selfsig = 1;
+                if (n2->pkt->pkttype == PKT_USER_ID
+                    && (/* Certification sigs.  */
+                        sig->sig_class == 0x10
+                        || sig->sig_class == 0x11
+                        || sig->sig_class == 0x12
+                        || sig->sig_class == 0x13
+                        /* Certification revocation sig.  */
+                        || sig->sig_class == 0x30))
+                  has_selfsig = 1;
+              }
+
+            if ((n2 && n2 != last_printed_component)
+                || (! n2 && last_printed_component != current_component))
+              {
+                int is_reordered = n2 && n2 != current_component;
+                if (n2)
+                  last_printed_component = n2;
+                else
+                  last_printed_component = current_component;
+
+                if (!modified)
+                  ;
+                else if (last_printed_component->pkt->pkttype == PKT_USER_ID)
+                  {
+                    tty_printf ("uid  ");
+                    tty_print_utf8_string (last_printed_component
+                                           ->pkt->pkt.user_id->name,
+                                           last_printed_component
+                                           ->pkt->pkt.user_id->len);
+                  }
+                else if (last_printed_component->pkt->pkttype
+                         == PKT_PUBLIC_KEY)
+                  tty_printf ("pub  %s",
+                              pk_keyid_str (last_printed_component
+                                            ->pkt->pkt.public_key));
+                else
+                  tty_printf ("sub  %s",
+                              pk_keyid_str (last_printed_component
+                                            ->pkt->pkt.public_key));
+
+                if (modified)
+                  {
+                    if (is_reordered)
+                      tty_printf (_(" (reordered signatures follow)"));
+                    tty_printf ("\n");
+                  }
+              }
+
+            if (modified)
+              keyedit_print_one_sig (ctrl, rc, kb, n, NULL, NULL, NULL,
+				     has_selfsig, 0, only_selfsigs);
+          }
+
+          if (dump_sig_params)
+            {
+              int i;
+
+              for (i = 0; i < pubkey_get_nsig (sig->pubkey_algo); i ++)
+                {
+                  char buffer[1024];
+                  size_t len;
+                  char *printable;
+                  gcry_mpi_print (GCRYMPI_FMT_USG,
+                                  buffer, sizeof (buffer), &len,
+                                  sig->data[i]);
+                  printable = bin2hex (buffer, len, NULL);
+                  log_info ("        %d: %s\n", i, printable);
+                  xfree (printable);
+                }
+            }
+          break;
+        default:
+          if (DBG_PACKET)
+            log_debug ("unhandled packet: %d\n", p->pkttype);
+          break;
+        }
+    }
+
+  xfree (pending_desc);
+  pending_desc = NULL;
+
+  if (issuer != pk)
+    free_public_key (issuer);
+  issuer = NULL;
+
+  /* Identify keys / uids that don't have a self-sig.  */
+  {
+    int has_selfsig = 0;
+    PACKET *p;
+    PKT_signature *sig;
+
+    current_component = NULL;
+    for (n = kb; n; n = n->next)
+      {
+        if (is_deleted_kbnode (n))
+          continue;
+
+        p = n->pkt;
+
+        switch (p->pkttype)
+          {
+          case PKT_PUBLIC_KEY:
+          case PKT_PUBLIC_SUBKEY:
+          case PKT_USER_ID:
+            if (current_component && ! has_selfsig)
+              missing_selfsig ++;
+            current_component = n;
+            has_selfsig = 0;
+            break;
+
+          case PKT_SIGNATURE:
+            if (! current_component || has_selfsig)
+              break;
+
+            sig = n->pkt->pkt.signature;
+
+            if (! (sig->flags.checked && sig->flags.valid))
+              break;
+
+            if (keyid_cmp (pk_keyid (pk), sig->keyid) != 0)
+              /* Different issuer, couldn't be a self-sig.  */
+              break;
+
+            if (current_component->pkt->pkttype == PKT_PUBLIC_KEY
+                && (/* Direct key signature.  */
+                    sig->sig_class == 0x1f
+                    /* Key revocation signature.  */
+                    || sig->sig_class == 0x20))
+              has_selfsig = 1;
+            if (current_component->pkt->pkttype == PKT_PUBLIC_SUBKEY
+                && (/* Subkey binding sig.  */
+                    sig->sig_class == 0x18
+                    /* Subkey revocation sig.  */
+                    || sig->sig_class == 0x28))
+              has_selfsig = 1;
+            if (current_component->pkt->pkttype == PKT_USER_ID
+                && (/* Certification sigs.  */
+                    sig->sig_class == 0x10
+                    || sig->sig_class == 0x11
+                    || sig->sig_class == 0x12
+                    || sig->sig_class == 0x13
+                    /* Certification revocation sig.  */
+                    || sig->sig_class == 0x30))
+              has_selfsig = 1;
+
+            break;
+
+          default:
+            if (current_component && ! has_selfsig)
+              missing_selfsig ++;
+            current_component = NULL;
+          }
+      }
+  }
+
+  if (dups || missing_issuer || bad_signature || reordered)
+    tty_printf (_("key %s:\n"), pk_keyid_str (pk));
+
+  if (dups)
+    tty_printf (ngettext ("%d duplicate signature removed\n",
+                          "%d duplicate signatures removed\n", dups), dups);
+  if (missing_issuer)
+    tty_printf (ngettext ("%d signature not checked due to a missing key\n",
+                          "%d signatures not checked due to missing keys\n",
+                          missing_issuer), missing_issuer);
+  if (bad_signature)
+    tty_printf (ngettext ("%d bad signature\n",
+                          "%d bad signatures\n",
+                          bad_signature), bad_signature);
+  if (reordered)
+    tty_printf (ngettext ("%d signature reordered\n",
+                          "%d signatures reordered\n",
+                          reordered), reordered);
+
+  if (only_selfsigs && (bad_signature || reordered))
+    tty_printf (_("Warning: errors found and only checked self-signatures,"
+                  " run '%s' to check all signatures.\n"), "check");
+
+  return modified;
+}
diff --git a/g10/key-check.h b/g10/key-check.h
new file mode 100644
index 0000000..3e4dd10
--- /dev/null
+++ b/g10/key-check.h
@@ -0,0 +1,28 @@
+/* key-check.h - Detect and fix various problems with keys
+ * Copyright (C) 2017 g10 Code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef GNUPG_G10_PACKET_TOOLS_H
+#define GNUPG_G10_PACKET_TOOLS_H
+
+#include "gpg.h"
+
+int key_check_all_keysigs (ctrl_t ctrl, kbnode_t kb,
+			   int only_selected, int only_selfsigs);
+
+#endif	/* GNUPG_G10_PACKET_TOOLS_H */
diff --git a/g10/keyedit.c b/g10/keyedit.c
index 30cf012..29fe466 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -48,6 +48,7 @@
 #include "call-agent.h"
 #include "../common/host2net.h"
 #include "tofu.h"
+#include "key-check.h"
 #include "keyedit.h"
 
 static void show_prefs (PKT_user_id * uid, PKT_signature * selfsig,
@@ -322,615 +323,6 @@ print_and_check_one_sig (ctrl_t ctrl, kbnode_t keyblock, kbnode_t node,
 }
 
 
-
-/* Order two signatures.  The actual ordering isn't important.  Our
-   goal is to ensure that identical signatures occur together.  */
-static int
-sig_comparison (const void *av, const void *bv)
-{
-  const KBNODE an = *(const KBNODE *) av;
-  const KBNODE bn = *(const KBNODE *) bv;
-  const PKT_signature *a;
-  const PKT_signature *b;
-  int ndataa;
-  int ndatab;
-  int i;
-
-  log_assert (an->pkt->pkttype == PKT_SIGNATURE);
-  log_assert (bn->pkt->pkttype == PKT_SIGNATURE);
-
-  a = an->pkt->pkt.signature;
-  b = bn->pkt->pkt.signature;
-
-  if (a->digest_algo < b->digest_algo)
-    return -1;
-  if (a->digest_algo > b->digest_algo)
-    return 1;
-
-  ndataa = pubkey_get_nsig (a->pubkey_algo);
-  ndatab = pubkey_get_nsig (b->pubkey_algo);
-  if (ndataa != ndatab)
-    return (ndataa < ndatab)? -1 : 1;
-
-  for (i = 0; i < ndataa; i ++)
-    {
-      int c = gcry_mpi_cmp (a->data[i], b->data[i]);
-      if (c != 0)
-        return c;
-    }
-
-  /* Okay, they are equal.  */
-  return 0;
-}
-
-/* Perform a few sanity checks on a keyblock is okay and possibly
-   repair some damage.  Concretely:
-
-     - Detect duplicate signatures and remove them.
-
-     - Detect out of order signatures and relocate them (e.g., a sig
-       over user id X located under subkey Y).
-
-   Note: this function does not remove signatures that don't belong or
-   components that are not signed!  (Although it would be trivial to
-   do so.)
-
-   If ONLY_SELFSIGS is true, then this function only reorders self
-   signatures (it still checks all signatures for duplicates,
-   however).
-
-   Returns 1 if the keyblock was modified, 0 otherwise.  */
-static int
-check_all_keysigs (ctrl_t ctrl, kbnode_t kb,
-                   int only_selected, int only_selfsigs)
-{
-  gpg_error_t err;
-  PKT_public_key *pk;
-  KBNODE n, n_next, *n_prevp, n2;
-  char *pending_desc = NULL;
-  PKT_public_key *issuer;
-  KBNODE last_printed_component;
-  KBNODE current_component = NULL;
-  int dups = 0;
-  int missing_issuer = 0;
-  int reordered = 0;
-  int bad_signature = 0;
-  int missing_selfsig = 0;
-  int modified = 0;
-
-  log_assert (kb->pkt->pkttype == PKT_PUBLIC_KEY);
-  pk = kb->pkt->pkt.public_key;
-
-  /* First we look for duplicates.  */
-  {
-    int nsigs;
-    kbnode_t *sigs;
-    int i;
-    int last_i;
-
-    /* Count the sigs.  */
-    for (nsigs = 0, n = kb; n; n = n->next)
-      {
-        if (is_deleted_kbnode (n))
-          continue;
-        else if (n->pkt->pkttype == PKT_SIGNATURE)
-          nsigs ++;
-      }
-
-    if (!nsigs)
-      return 0; /* No signatures at all.  */
-
-    /* Add them all to the SIGS array.  */
-    sigs = xtrycalloc (nsigs, sizeof *sigs);
-    if (!sigs)
-      {
-        log_error (_("error allocating memory: %s\n"),
-                   gpg_strerror (gpg_error_from_syserror ()));
-        return 0;
-      }
-
-    i = 0;
-    for (n = kb; n; n = n->next)
-      {
-        if (is_deleted_kbnode (n))
-          continue;
-
-        if (n->pkt->pkttype != PKT_SIGNATURE)
-          continue;
-
-        sigs[i] = n;
-        i ++;
-      }
-    log_assert (i == nsigs);
-
-    qsort (sigs, nsigs, sizeof (sigs[0]), sig_comparison);
-
-    last_i = 0;
-    for (i = 1; i < nsigs; i ++)
-      {
-        log_assert (sigs[last_i]);
-        log_assert (sigs[last_i]->pkt->pkttype == PKT_SIGNATURE);
-        log_assert (sigs[i]);
-        log_assert (sigs[i]->pkt->pkttype == PKT_SIGNATURE);
-
-        if (sig_comparison (&sigs[last_i], &sigs[i]) == 0)
-          /* They are the same.  Kill the latter.  */
-          {
-            if (DBG_PACKET)
-              {
-                PKT_signature *sig = sigs[i]->pkt->pkt.signature;
-
-                log_debug ("Signature appears multiple times, "
-                           "deleting duplicate:\n");
-                log_debug ("  sig: class 0x%x, issuer: %s,"
-                           " timestamp: %s (%lld), digest: %02x %02x\n",
-                           sig->sig_class, keystr (sig->keyid),
-                           isotimestamp (sig->timestamp),
-                           (long long) sig->timestamp,
-                           sig->digest_start[0], sig->digest_start[1]);
-              }
-
-            /* Remove sigs[i] from the keyblock.  */
-            {
-              KBNODE z, *prevp;
-              int to_kill = last_i;
-              last_i = i;
-
-              for (prevp = &kb, z = kb; z; prevp = &z->next, z = z->next)
-                if (z == sigs[to_kill])
-                  break;
-
-              *prevp = sigs[to_kill]->next;
-
-              sigs[to_kill]->next = NULL;
-              release_kbnode (sigs[to_kill]);
-              sigs[to_kill] = NULL;
-
-              dups ++;
-              modified = 1;
-            }
-          }
-        else
-          last_i = i;
-      }
-
-    xfree (sigs);
-  }
-
-  /* Make sure the sigs occur after the component (public key, subkey,
-     user id) that they sign.  */
-  issuer = NULL;
-  last_printed_component = NULL;
-  for (n_prevp = &kb, n = kb;
-       n;
-       /* If we moved n, then n_prevp is need valid.  */
-       n_prevp = (n->next == n_next ? &n->next : n_prevp), n = n_next)
-    {
-      PACKET *p;
-      int processed_current_component;
-      PKT_signature *sig;
-      int rc;
-      int dump_sig_params = 0;
-
-      n_next = n->next;
-
-      if (is_deleted_kbnode (n))
-        continue;
-
-      p = n->pkt;
-
-      if (issuer && issuer != pk)
-        {
-          free_public_key (issuer);
-          issuer = NULL;
-        }
-
-      xfree (pending_desc);
-      pending_desc = NULL;
-
-      switch (p->pkttype)
-        {
-        case PKT_PUBLIC_KEY:
-          log_assert (p->pkt.public_key == pk);
-          if (only_selected && ! (n->flag & NODFLG_SELKEY))
-            {
-              current_component = NULL;
-              break;
-            }
-
-          if (DBG_PACKET)
-            log_debug ("public key %s: timestamp: %s (%lld)\n",
-                       pk_keyid_str (pk),
-                       isotimestamp (pk->timestamp),
-                       (long long) pk->timestamp);
-          current_component = n;
-          break;
-        case PKT_PUBLIC_SUBKEY:
-          if (only_selected && ! (n->flag & NODFLG_SELKEY))
-            {
-              current_component = NULL;
-              break;
-            }
-
-          if (DBG_PACKET)
-            log_debug ("subkey %s: timestamp: %s (%lld)\n",
-                       pk_keyid_str (p->pkt.public_key),
-                       isotimestamp (p->pkt.public_key->timestamp),
-                       (long long) p->pkt.public_key->timestamp);
-          current_component = n;
-          break;
-        case PKT_USER_ID:
-          if (only_selected && ! (n->flag & NODFLG_SELUID))
-            {
-              current_component = NULL;
-              break;
-            }
-
-          if (DBG_PACKET)
-            log_debug ("user id: %s\n",
-                       p->pkt.user_id->attrib_data
-                       ? "[ photo id ]"
-                       : p->pkt.user_id->name);
-          current_component = n;
-          break;
-        case PKT_SIGNATURE:
-          if (! current_component)
-            /* The current component is not selected, don't check the
-               sigs under it.  */
-            break;
-
-          sig = n->pkt->pkt.signature;
-
-          pending_desc = xasprintf ("  sig: class: 0x%x, issuer: %s,"
-                                    " timestamp: %s (%lld), digest: %02x %02x",
-                                    sig->sig_class,
-                                    keystr (sig->keyid),
-                                    isotimestamp (sig->timestamp),
-                                    (long long) sig->timestamp,
-                                    sig->digest_start[0], sig->digest_start[1]);
-
-
-          if (keyid_cmp (pk_keyid (pk), sig->keyid) == 0)
-            issuer = pk;
-          else /* Issuer is a different key.  */
-            {
-              if (only_selfsigs)
-                continue;
-
-              issuer = xmalloc (sizeof (*issuer));
-              err = get_pubkey (ctrl, issuer, sig->keyid);
-              if (err)
-                {
-                  xfree (issuer);
-                  issuer = NULL;
-                  if (DBG_PACKET)
-                    {
-                      if (pending_desc)
-                        log_debug ("%s", pending_desc);
-                      log_debug ("    Can't check signature allegedly"
-                                 " issued by %s: %s\n",
-                                 keystr (sig->keyid), gpg_strerror (err));
-                    }
-                  missing_issuer ++;
-                  break;
-                }
-            }
-
-          if ((err = openpgp_pk_test_algo (sig->pubkey_algo)))
-            {
-              if (DBG_PACKET && pending_desc)
-                log_debug ("%s", pending_desc);
-              tty_printf (_("can't check signature with unsupported"
-                            " public-key algorithm (%d): %s.\n"),
-                          sig->pubkey_algo, gpg_strerror (err));
-              break;
-            }
-          if ((err = openpgp_md_test_algo (sig->digest_algo)))
-            {
-              if (DBG_PACKET && pending_desc)
-                log_debug ("%s", pending_desc);
-              tty_printf (_("can't check signature with unsupported"
-                            " message-digest algorithm %d: %s.\n"),
-                          sig->digest_algo, gpg_strerror (err));
-              break;
-            }
-
-          /* We iterate over the keyblock.  Most likely, the matching
-             component is the current component so always try that
-             first.  */
-          processed_current_component = 0;
-          for (n2 = current_component;
-               n2;
-               n2 = (processed_current_component ? n2->next : kb),
-                 processed_current_component = 1)
-            if (is_deleted_kbnode (n2))
-              continue;
-            else if (processed_current_component && n2 == current_component)
-              /* Don't process it twice.  */
-              continue;
-            else
-              {
-                err = check_signature_over_key_or_uid (ctrl,
-                                                       issuer, sig, kb, n2->pkt,
-                                                       NULL, NULL);
-                if (! err)
-                  break;
-              }
-
-          /* n/sig is a signature and n2 is the component (public key,
-             subkey or user id) that it signs, if any.
-             current_component is that component that it appears to
-             apply to (according to the ordering).  */
-
-          if (current_component == n2)
-            {
-              if (DBG_PACKET)
-                {
-                  log_debug ("%s", pending_desc);
-                  log_debug ("    Good signature over last key or uid!\n");
-                }
-
-              rc = 0;
-            }
-          else if (n2)
-            {
-              log_assert (n2->pkt->pkttype == PKT_USER_ID
-                          || n2->pkt->pkttype == PKT_PUBLIC_KEY
-                          || n2->pkt->pkttype == PKT_PUBLIC_SUBKEY);
-
-              if (DBG_PACKET)
-                {
-                  log_debug ("%s", pending_desc);
-                  log_debug ("    Good signature out of order!"
-                             "  (Over %s (%d) '%s')\n",
-                             n2->pkt->pkttype == PKT_USER_ID
-                             ? "user id"
-                             : n2->pkt->pkttype == PKT_PUBLIC_SUBKEY
-                             ? "subkey"
-                             : "primary key",
-                             n2->pkt->pkttype,
-                             n2->pkt->pkttype == PKT_USER_ID
-                             ? n2->pkt->pkt.user_id->name
-                             : pk_keyid_str (n2->pkt->pkt.public_key));
-                }
-
-              /* Reorder the packets: move the signature n to be just
-                 after n2.  */
-
-              /* Unlink the signature.  */
-              log_assert (n_prevp);
-              *n_prevp = n->next;
-
-              /* Insert the sig immediately after the component.  */
-              n->next = n2->next;
-              n2->next = n;
-
-              reordered ++;
-              modified = 1;
-
-              rc = 0;
-            }
-          else
-            {
-              if (DBG_PACKET)
-                {
-                  log_debug ("%s", pending_desc);
-                  log_debug ("    Bad signature.\n");
-                }
-
-              if (DBG_PACKET)
-                dump_sig_params = 1;
-
-              bad_signature ++;
-
-              rc = GPG_ERR_BAD_SIGNATURE;
-            }
-
-          /* We don't cache the result here, because we haven't
-             completely checked that the signature is legitimate.  For
-             instance, if we have a revocation certificate on Alice's
-             key signed by Bob, the signature may be good, but we
-             haven't checked that Bob is a designated revoker.  */
-          /* cache_sig_result (sig, rc); */
-
-          {
-            int has_selfsig = 0;
-            if (! rc && issuer == pk)
-              {
-                if (n2->pkt->pkttype == PKT_PUBLIC_KEY
-                    && (/* Direct key signature.  */
-                        sig->sig_class == 0x1f
-                        /* Key revocation signature.  */
-                        || sig->sig_class == 0x20))
-                  has_selfsig = 1;
-                if (n2->pkt->pkttype == PKT_PUBLIC_SUBKEY
-                    && (/* Subkey binding sig.  */
-                        sig->sig_class == 0x18
-                        /* Subkey revocation sig.  */
-                        || sig->sig_class == 0x28))
-                  has_selfsig = 1;
-                if (n2->pkt->pkttype == PKT_USER_ID
-                    && (/* Certification sigs.  */
-                        sig->sig_class == 0x10
-                        || sig->sig_class == 0x11
-                        || sig->sig_class == 0x12
-                        || sig->sig_class == 0x13
-                        /* Certification revocation sig.  */
-                        || sig->sig_class == 0x30))
-                  has_selfsig = 1;
-              }
-
-            if ((n2 && n2 != last_printed_component)
-                || (! n2 && last_printed_component != current_component))
-              {
-                int is_reordered = n2 && n2 != current_component;
-                if (n2)
-                  last_printed_component = n2;
-                else
-                  last_printed_component = current_component;
-
-                if (!modified)
-                  ;
-                else if (last_printed_component->pkt->pkttype == PKT_USER_ID)
-                  {
-                    tty_printf ("uid  ");
-                    tty_print_utf8_string (last_printed_component
-                                           ->pkt->pkt.user_id->name,
-                                           last_printed_component
-                                           ->pkt->pkt.user_id->len);
-                  }
-                else if (last_printed_component->pkt->pkttype
-                         == PKT_PUBLIC_KEY)
-                  tty_printf ("pub  %s",
-                              pk_keyid_str (last_printed_component
-                                            ->pkt->pkt.public_key));
-                else
-                  tty_printf ("sub  %s",
-                              pk_keyid_str (last_printed_component
-                                            ->pkt->pkt.public_key));
-
-                if (modified)
-                  {
-                    if (is_reordered)
-                      tty_printf (_(" (reordered signatures follow)"));
-                    tty_printf ("\n");
-                  }
-              }
-
-            if (modified)
-              keyedit_print_one_sig (ctrl, rc, kb, n, NULL, NULL, NULL,
-				     has_selfsig, 0, only_selfsigs);
-          }
-
-          if (dump_sig_params)
-            {
-              int i;
-
-              for (i = 0; i < pubkey_get_nsig (sig->pubkey_algo); i ++)
-                {
-                  char buffer[1024];
-                  size_t len;
-                  char *printable;
-                  gcry_mpi_print (GCRYMPI_FMT_USG,
-                                  buffer, sizeof (buffer), &len,
-                                  sig->data[i]);
-                  printable = bin2hex (buffer, len, NULL);
-                  log_info ("        %d: %s\n", i, printable);
-                  xfree (printable);
-                }
-            }
-          break;
-        default:
-          if (DBG_PACKET)
-            log_debug ("unhandled packet: %d\n", p->pkttype);
-          break;
-        }
-    }
-
-  xfree (pending_desc);
-  pending_desc = NULL;
-
-  if (issuer != pk)
-    free_public_key (issuer);
-  issuer = NULL;
-
-  /* Identify keys / uids that don't have a self-sig.  */
-  {
-    int has_selfsig = 0;
-    PACKET *p;
-    PKT_signature *sig;
-
-    current_component = NULL;
-    for (n = kb; n; n = n->next)
-      {
-        if (is_deleted_kbnode (n))
-          continue;
-
-        p = n->pkt;
-
-        switch (p->pkttype)
-          {
-          case PKT_PUBLIC_KEY:
-          case PKT_PUBLIC_SUBKEY:
-          case PKT_USER_ID:
-            if (current_component && ! has_selfsig)
-              missing_selfsig ++;
-            current_component = n;
-            has_selfsig = 0;
-            break;
-
-          case PKT_SIGNATURE:
-            if (! current_component || has_selfsig)
-              break;
-
-            sig = n->pkt->pkt.signature;
-
-            if (! (sig->flags.checked && sig->flags.valid))
-              break;
-
-            if (keyid_cmp (pk_keyid (pk), sig->keyid) != 0)
-              /* Different issuer, couldn't be a self-sig.  */
-              break;
-
-            if (current_component->pkt->pkttype == PKT_PUBLIC_KEY
-                && (/* Direct key signature.  */
-                    sig->sig_class == 0x1f
-                    /* Key revocation signature.  */
-                    || sig->sig_class == 0x20))
-              has_selfsig = 1;
-            if (current_component->pkt->pkttype == PKT_PUBLIC_SUBKEY
-                && (/* Subkey binding sig.  */
-                    sig->sig_class == 0x18
-                    /* Subkey revocation sig.  */
-                    || sig->sig_class == 0x28))
-              has_selfsig = 1;
-            if (current_component->pkt->pkttype == PKT_USER_ID
-                && (/* Certification sigs.  */
-                    sig->sig_class == 0x10
-                    || sig->sig_class == 0x11
-                    || sig->sig_class == 0x12
-                    || sig->sig_class == 0x13
-                    /* Certification revocation sig.  */
-                    || sig->sig_class == 0x30))
-              has_selfsig = 1;
-
-            break;
-
-          default:
-            if (current_component && ! has_selfsig)
-              missing_selfsig ++;
-            current_component = NULL;
-          }
-      }
-  }
-
-  if (dups || missing_issuer || bad_signature || reordered)
-    tty_printf (_("key %s:\n"), pk_keyid_str (pk));
-
-  if (dups)
-    tty_printf (ngettext ("%d duplicate signature removed\n",
-                          "%d duplicate signatures removed\n", dups), dups);
-  if (missing_issuer)
-    tty_printf (ngettext ("%d signature not checked due to a missing key\n",
-                          "%d signatures not checked due to missing keys\n",
-                          missing_issuer), missing_issuer);
-  if (bad_signature)
-    tty_printf (ngettext ("%d bad signature\n",
-                          "%d bad signatures\n",
-                          bad_signature), bad_signature);
-  if (reordered)
-    tty_printf (ngettext ("%d signature reordered\n",
-                          "%d signatures reordered\n",
-                          reordered), reordered);
-
-  if (only_selfsigs && (bad_signature || reordered))
-    tty_printf (_("Warning: errors found and only checked self-signatures,"
-                  " run '%s' to check all signatures.\n"), "check");
-
-  return modified;
-}
-
-
 static int
 sign_mk_attrib (PKT_signature * sig, void *opaque)
 {
@@ -1774,7 +1166,7 @@ fix_keyblock (ctrl_t ctrl, kbnode_t *keyblockp)
 
   if (collapse_uids (keyblockp))
     changed++;
-  if (check_all_keysigs (ctrl, *keyblockp, 0, 1))
+  if (key_check_all_keysigs (ctrl, *keyblockp, 0, 1))
     changed++;
   reorder_keyblock (*keyblockp);
   /* If we modified the keyblock, make sure the flags are right. */
@@ -2221,9 +1613,9 @@ keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
 	  break;
 
 	case cmdCHECK:
-	  if (check_all_keysigs (ctrl, keyblock,
-                                 count_selected_uids (keyblock),
-                                 !strcmp (arg_string, "selfsig")))
+	  if (key_check_all_keysigs (ctrl, keyblock,
+				     count_selected_uids (keyblock),
+				     !strcmp (arg_string, "selfsig")))
             modified = 1;
 	  break;
 

commit 8095d16b3ef6b5f01ec351824855708149f1c1c3
Author: Justus Winter <justus at g10code.com>
Date:   Tue Jun 13 15:27:43 2017 +0200

    gpg: Refactor keyedit module.
    
    * g10/Makefile.am (gpg_SOURCES): Add new file.
    * g10/keyedit.c (NODFLG_*): Move flags to the new header file.
    (print_one_sig): Export symbol and rename accordingly.
    (print_and_check_one_sig): Adapt accordingly.
    (check_all_keysigs): Likewise.
    * g10/keyedit.h: New file.
    * g10/main.h: Drop declarations, include new header.
    
    GnuPG-bug-id: 2236
    Signed-off-by: Justus Winter <justus at g10code.com>

diff --git a/g10/Makefile.am b/g10/Makefile.am
index 330d6c5..9994ea1 100644
--- a/g10/Makefile.am
+++ b/g10/Makefile.am
@@ -153,7 +153,7 @@ gpg_sources = server.c          \
 	      exec.c exec.h
 
 gpg_SOURCES  = gpg.c \
-	keyedit.c 	\
+	keyedit.c keyedit.h	\
 	$(gpg_sources)
 
 gpgcompose_SOURCES  = gpgcompose.c  $(gpg_sources)
diff --git a/g10/keyedit.c b/g10/keyedit.c
index 9f6add1..30cf012 100644
--- a/g10/keyedit.c
+++ b/g10/keyedit.c
@@ -48,6 +48,7 @@
 #include "call-agent.h"
 #include "../common/host2net.h"
 #include "tofu.h"
+#include "keyedit.h"
 
 static void show_prefs (PKT_user_id * uid, PKT_signature * selfsig,
 			int verbose);
@@ -105,17 +106,6 @@ 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;
@@ -201,10 +191,10 @@ print_and_check_one_sig_colon (ctrl_t ctrl, kbnode_t keyblock, kbnode_t node,
  * packet.  With EXTENDED set all possible signature list options will
  * always be printed.
  */
-static int
-print_one_sig (ctrl_t ctrl, 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)
+int
+keyedit_print_one_sig (ctrl_t ctrl, 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;
   int sigrc;
@@ -326,9 +316,9 @@ print_and_check_one_sig (ctrl_t ctrl, kbnode_t keyblock, kbnode_t node,
   int rc;
 
   rc = check_key_signature (ctrl, keyblock, node, is_selfsig);
-  return print_one_sig (ctrl, rc,
-                        keyblock, node, inv_sigs, no_key, oth_err,
-                        *is_selfsig, print_without_key, extended);
+  return keyedit_print_one_sig (ctrl, rc,
+				keyblock, node, inv_sigs, no_key, oth_err,
+				*is_selfsig, print_without_key, extended);
 }
 
 
@@ -808,8 +798,8 @@ check_all_keysigs (ctrl_t ctrl, kbnode_t kb,
               }
 
             if (modified)
-              print_one_sig (ctrl, rc, kb, n, NULL, NULL, NULL, has_selfsig,
-                             0, only_selfsigs);
+              keyedit_print_one_sig (ctrl, rc, kb, n, NULL, NULL, NULL,
+				     has_selfsig, 0, only_selfsigs);
           }
 
           if (dump_sig_params)
diff --git a/g10/keyedit.h b/g10/keyedit.h
new file mode 100644
index 0000000..d4c9632
--- /dev/null
+++ b/g10/keyedit.h
@@ -0,0 +1,58 @@
+/* keyedit.h - Edit properties of a key
+ * Copyright (C) 1998-2010 Free Software Foundation, Inc.
+ * Copyright (C) 1998-2017 Werner Koch
+ * Copyright (C) 2015-2017 g10 Code GmbH
+ *
+ * This file is part of GnuPG.
+ *
+ * GnuPG is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * GnuPG is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * 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 <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef GNUPG_G10_KEYEDIT_H
+#define GNUPG_G10_KEYEDIT_H
+
+#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.  */
+
+/*-- keyedit.c --*/
+void keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
+		   strlist_t commands, int quiet, int seckey_check );
+void keyedit_passwd (ctrl_t ctrl, const char *username);
+void keyedit_quick_adduid (ctrl_t ctrl, const char *username,
+                           const char *newuid);
+void keyedit_quick_addkey (ctrl_t ctrl, const char *fpr, const char *algostr,
+                           const char *usagestr, const char *expirestr);
+void keyedit_quick_revuid (ctrl_t ctrl, const char *username,
+                           const char *uidtorev);
+void keyedit_quick_sign (ctrl_t ctrl, const char *fpr,
+                         strlist_t uids, strlist_t locusr, int local);
+void keyedit_quick_set_expire (ctrl_t ctrl,
+                               const char *fpr, const char *expirestr);
+void keyedit_quick_set_primary (ctrl_t ctrl, const char *username,
+                                const char *primaryuid);
+void show_basic_key_info (ctrl_t ctrl, kbnode_t keyblock);
+int keyedit_print_one_sig (ctrl_t ctrl, 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);
+
+#endif	/* GNUPG_G10_KEYEDIT_H */
diff --git a/g10/main.h b/g10/main.h
index 33116d2..dad0fe3 100644
--- a/g10/main.h
+++ b/g10/main.h
@@ -23,6 +23,7 @@
 #include "../common/types.h"
 #include "../common/iobuf.h"
 #include "keydb.h"
+#include "keyedit.h"
 #include "../common/util.h"
 
 /* It could be argued that the default cipher should be 3DES rather
@@ -285,24 +286,6 @@ gpg_error_t check_signature_over_key_or_uid (ctrl_t ctrl,
 gpg_error_t delete_keys (ctrl_t ctrl,
                          strlist_t names, int secret, int allow_both);
 
-/*-- keyedit.c --*/
-void keyedit_menu (ctrl_t ctrl, const char *username, strlist_t locusr,
-		   strlist_t commands, int quiet, int seckey_check );
-void keyedit_passwd (ctrl_t ctrl, const char *username);
-void keyedit_quick_adduid (ctrl_t ctrl, const char *username,
-                           const char *newuid);
-void keyedit_quick_addkey (ctrl_t ctrl, const char *fpr, const char *algostr,
-                           const char *usagestr, const char *expirestr);
-void keyedit_quick_revuid (ctrl_t ctrl, const char *username,
-                           const char *uidtorev);
-void keyedit_quick_sign (ctrl_t ctrl, const char *fpr,
-                         strlist_t uids, strlist_t locusr, int local);
-void keyedit_quick_set_expire (ctrl_t ctrl,
-                               const char *fpr, const char *expirestr);
-void keyedit_quick_set_primary (ctrl_t ctrl, const char *username,
-                                const char *primaryuid);
-void show_basic_key_info (ctrl_t ctrl, kbnode_t keyblock);
-
 /*-- keygen.c --*/
 const char *get_default_pubkey_algo (void);
 u32 parse_expire_string(const char *string);

-----------------------------------------------------------------------

Summary of changes:
 doc/gpg.texi                          |   4 +
 g10/Makefile.am                       |   5 +-
 g10/gpg.c                             |   5 +-
 g10/gpgcompose.c                      |  18 +
 g10/import.c                          |   7 +
 g10/key-check.c                       | 640 +++++++++++++++++++++++++++++++++
 tests/gpgscm/ffi.h => g10/key-check.h |  18 +-
 g10/keyedit.c                         | 644 +---------------------------------
 g10/keyedit.h                         |  58 +++
 g10/main.h                            |  19 +-
 g10/options.h                         |   1 +
 11 files changed, 756 insertions(+), 663 deletions(-)
 create mode 100644 g10/key-check.c
 copy tests/gpgscm/ffi.h => g10/key-check.h (68%)
 create mode 100644 g10/keyedit.h


hooks/post-receive
-- 
The GNU Privacy Guard
http://git.gnupg.org




More information about the Gnupg-commits mailing list