gpg: Forbid the creation of SHA-1 third-party key signatures.
authorWerner Koch <wk@gnupg.org>
Mon, 11 Nov 2019 10:41:00 +0000 (11:41 +0100)
committerWerner Koch <wk@gnupg.org>
Mon, 11 Nov 2019 10:41:00 +0000 (11:41 +0100)
* g10/sign.c (SIGNHINT_KEYSIG, SIGNHINT_SELFSIG): New.
(do_sign): Add arg signhints and inhibit SHA-1 signatures.  Change
callers to pass 0.
(complete_sig): Add arg signhints and pass on.
(make_keysig_packet, update_keysig_packet): Set signhints.
--

Signed-off-by: Werner Koch <wk@gnupg.org>
g10/sign.c

index 250c0cf..11360b9 100644 (file)
 #define LF "\n"
 #endif
 
+
+/* Bitflags to convey hints on what kind of signayire is created.  */
+#define SIGNHINT_KEYSIG  1
+#define SIGNHINT_SELFSIG 2
+
+
 /* Hack */
 static int recipient_digest_algo;
 
@@ -309,10 +315,12 @@ hash_sigversion_to_magic (gcry_md_hd_t md, const PKT_signature *sig,
 
 
 /* Perform the sign operation.  If CACHE_NONCE is given the agent is
-   advised to use that cached passphrase for the key.  */
+ * advised to use that cached passphrase for the key.  SIGNHINTS has
+ * hints so that we can do some additional checks. */
 static int
 do_sign (ctrl_t ctrl, PKT_public_key *pksk, PKT_signature *sig,
-        gcry_md_hd_t md, int mdalgo, const char *cache_nonce)
+        gcry_md_hd_t md, int mdalgo,
+         const char *cache_nonce, unsigned int signhints)
 {
   gpg_error_t err;
   byte *dp;
@@ -335,6 +343,19 @@ do_sign (ctrl_t ctrl, PKT_public_key *pksk, PKT_signature *sig,
   if (!mdalgo)
     mdalgo = gcry_md_get_algo (md);
 
+  if ((signhints & SIGNHINT_KEYSIG) && !(signhints & SIGNHINT_SELFSIG)
+      && mdalgo == GCRY_MD_SHA1
+      && !opt.flags.allow_weak_key_signatures)
+    {
+      /* We do not allow the creation of third-party key signatures
+       * using SHA-1 because we also reject them when verifying.  Note
+       * that this will render dsa1024 keys unsuitable for such
+       * keysigs and in turn the WoT. */
+      print_sha1_keysig_rejected_note ();
+      err = gpg_error (GPG_ERR_DIGEST_ALGO);
+      goto leave;
+    }
+
   /* Check compliance.  */
   if (! gnupg_digest_is_allowed (opt.compliance, 1, mdalgo))
     {
@@ -431,12 +452,12 @@ do_sign (ctrl_t ctrl, PKT_public_key *pksk, PKT_signature *sig,
 static int
 complete_sig (ctrl_t ctrl,
               PKT_signature *sig, PKT_public_key *pksk, gcry_md_hd_t md,
-              const char *cache_nonce)
+              const char *cache_nonce, unsigned int signhints)
 {
   int rc;
 
   /* if (!(rc = check_secret_key (pksk, 0))) */
-  rc = do_sign (ctrl, pksk, sig, md, 0, cache_nonce);
+  rc = do_sign (ctrl, pksk, sig, md, 0, cache_nonce, signhints);
   return rc;
 }
 
@@ -842,7 +863,7 @@ write_signature_packets (ctrl_t ctrl,
       hash_sigversion_to_magic (md, sig, extrahash);
       gcry_md_final (md);
 
-      rc = do_sign (ctrl, pk, sig, md, hash_for (pk), cache_nonce);
+      rc = do_sign (ctrl, pk, sig, md, hash_for (pk), cache_nonce, 0);
       gcry_md_close (md);
       if (!rc)
         {
@@ -1607,6 +1628,8 @@ make_keysig_packet (ctrl_t ctrl,
   int sigversion;
   int digest_algo;
   gcry_md_hd_t md;
+  u32 pk_keyid[2], pksk_keyid[2];
+  unsigned int signhints;
 
   log_assert ((sigclass >= 0x10 && sigclass <= 0x13) || sigclass == 0x1F
               || sigclass == 0x20 || sigclass == 0x18 || sigclass == 0x19
@@ -1634,6 +1657,12 @@ make_keysig_packet (ctrl_t ctrl,
   else /* Use the default.  */
     digest_algo = DEFAULT_DIGEST_ALGO;
 
+  signhints = SIGNHINT_KEYSIG;
+  keyid_from_pk (pk, pk_keyid);
+  keyid_from_pk (pksk, pksk_keyid);
+  if (pk_keyid[0] == pksk_keyid[0] && pk_keyid[1] == pksk_keyid[1])
+    signhints |= SIGNHINT_SELFSIG;
+
   if (gcry_md_open (&md, digest_algo, 0))
     BUG ();
 
@@ -1676,7 +1705,7 @@ make_keysig_packet (ctrl_t ctrl,
     {
       hash_sigversion_to_magic (md, sig, NULL);
       gcry_md_final (md);
-      rc = complete_sig (ctrl, sig, pksk, md, cache_nonce);
+      rc = complete_sig (ctrl, sig, pksk, md, cache_nonce, signhints);
     }
 
   gcry_md_close (md);
@@ -1712,6 +1741,8 @@ update_keysig_packet (ctrl_t ctrl,
   gpg_error_t rc = 0;
   int digest_algo;
   gcry_md_hd_t md;
+  u32 pk_keyid[2], pksk_keyid[2];
+  unsigned int signhints = 0;
 
   if ((!orig_sig || !pk || !pksk)
       || (orig_sig->sig_class >= 0x10 && orig_sig->sig_class <= 0x13 && !uid)
@@ -1734,6 +1765,12 @@ update_keysig_packet (ctrl_t ctrl,
   else
     digest_algo = orig_sig->digest_algo;
 
+  signhints = SIGNHINT_KEYSIG;
+  keyid_from_pk (pk, pk_keyid);
+  keyid_from_pk (pksk, pksk_keyid);
+  if (pk_keyid[0] == pksk_keyid[0] && pk_keyid[1] == pksk_keyid[1])
+    signhints |= SIGNHINT_SELFSIG;
+
   if (gcry_md_open (&md, digest_algo, 0))
     BUG ();
 
@@ -1787,7 +1824,7 @@ update_keysig_packet (ctrl_t ctrl,
     {
       hash_sigversion_to_magic (md, sig, NULL);
       gcry_md_final (md);
-      rc = complete_sig (ctrl, sig, pksk, md, NULL);
+      rc = complete_sig (ctrl, sig, pksk, md, NULL, signhints);
     }
 
  leave: