aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNeal H. Walfield <[email protected]>2016-10-13 10:44:59 +0000
committerNeal H. Walfield <[email protected]>2016-10-13 10:44:59 +0000
commit4c0389f8eb19ae7dfd9c5d784a629b386d93cc5c (patch)
treede7bab354ce89648d13551ff6d7faac989760e0d
parentg10: Still check if the key is an UTK or cross signed in batch mode. (diff)
downloadgnupg-4c0389f8eb19ae7dfd9c5d784a629b386d93cc5c.tar.gz
gnupg-4c0389f8eb19ae7dfd9c5d784a629b386d93cc5c.zip
g10: Be more careful when checking cross signatures.
* g10/tofu.c (cross_sigs): When checking cross signatures, only consider the signatures on the specified user id. * tests/openpgp/tofu.scm: Add test for the above. * tests/openpgp/tofu/cross-sigs/ 1938C3A0E4674B6C217AC0B987DB2814EC38277E-1.gpg: New file. * tests/openpgp/tofu/cross-sigs/ 1938C3A0E4674B6C217AC0B987DB2814EC38277E-1.txt: New file. * tests/openpgp/tofu/cross-sigs/ 1938C3A0E4674B6C217AC0B987DB2814EC38277E-2.gpg: New file. * tests/openpgp/tofu/cross-sigs/ 1938C3A0E4674B6C217AC0B987DB2814EC38277E-2.txt: New file. * tests/openpgp/tofu/cross-sigs/ 1938C3A0E4674B6C217AC0B987DB2814EC38277E-3.txt: New file. * tests/openpgp/tofu/cross-sigs/ 1938C3A0E4674B6C217AC0B987DB2814EC38277E-secret.gpg: New file. * tests/openpgp/tofu/cross-sigs/ DC463A16E42F03240D76E8BA8B48C6BD871C2247-1.gpg: New file. * tests/openpgp/tofu/cross-sigs/ DC463A16E42F03240D76E8BA8B48C6BD871C2247-1.txt: New file. * tests/openpgp/tofu/cross-sigs/ DC463A16E42F03240D76E8BA8B48C6BD871C2247-2.gpg: New file. * tests/openpgp/tofu/cross-sigs/ DC463A16E42F03240D76E8BA8B48C6BD871C2247-2.txt: New file. * tests/openpgp/tofu/cross-sigs/ DC463A16E42F03240D76E8BA8B48C6BD871C2247-3.gpg: New file. * tests/openpgp/tofu/cross-sigs/ DC463A16E42F03240D76E8BA8B48C6BD871C2247-3.txt: New file. * tests/openpgp/tofu/cross-sigs/ DC463A16E42F03240D76E8BA8B48C6BD871C2247-4.gpg: New file. * tests/openpgp/tofu/cross-sigs/ DC463A16E42F03240D76E8BA8B48C6BD871C2247-secret.gpg: New file. * tests/openpgp/tofu/cross-sigs/README: New file. -- Signed-off-by: Neal H. Walfield
-rw-r--r--g10/tofu.c28
-rwxr-xr-xtests/openpgp/tofu.scm73
-rw-r--r--tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-1.gpgbin0 -> 1171 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-1.txtbin0 -> 321 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-2.gpgbin0 -> 1458 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-2.txtbin0 -> 334 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-3.txtbin0 -> 334 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-secret.gpgbin0 -> 2473 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-1.gpgbin0 -> 1173 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-1.txtbin0 -> 321 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-2.gpgbin0 -> 1460 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-2.txtbin0 -> 333 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-3.gpgbin0 -> 1800 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-3.txtbin0 -> 334 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-4.gpgbin0 -> 2087 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-secret.gpgbin0 -> 2475 bytes
-rw-r--r--tests/openpgp/tofu/cross-sigs/README79
17 files changed, 178 insertions, 2 deletions
diff --git a/g10/tofu.c b/g10/tofu.c
index 8184c6f98..dcee6e70f 100644
--- a/g10/tofu.c
+++ b/g10/tofu.c
@@ -1211,7 +1211,7 @@ format_conflict_msg_part1 (int policy, strlist_t conflict_set,
/* Return 1 if A signed B and B signed A. */
static int
-cross_sigs (kbnode_t a, kbnode_t b)
+cross_sigs (const char *email, kbnode_t a, kbnode_t b)
{
int i;
@@ -1240,12 +1240,36 @@ cross_sigs (kbnode_t a, kbnode_t b)
u32 *signer_kid = pk_main_keyid (signer_pk);
kbnode_t n;
+ int saw_email = 0;
+
/* Iterate over SIGNEE's keyblock and see if there is a valid
signature from SIGNER. */
for (n = signee; n; n = n->next)
{
PKT_signature *sig;
+ if (n->pkt->pkttype == PKT_USER_ID)
+ {
+ if (saw_email)
+ /* We're done: we've processed all signatures on the
+ user id. */
+ break;
+ else
+ {
+ /* See if this is the matching user id. */
+ PKT_user_id *user_id = n->pkt->pkt.user_id;
+ char *email2 = email_from_user_id (user_id->name);
+
+ if (strcmp (email, email2) == 0)
+ saw_email = 1;
+
+ xfree (email2);
+ }
+ }
+
+ if (! saw_email)
+ continue;
+
if (n->pkt->pkttype != PKT_SIGNATURE)
continue;
@@ -1974,7 +1998,7 @@ build_conflict_set (tofu_dbs_t dbs, const char *fingerprint, const char *email)
for (j = i + 1; j < conflict_set_count; j ++)
/* Be careful: we might not have a key block for a key. */
- if (kb_all[i] && kb_all[j] && cross_sigs (kb_all[i], kb_all[j]))
+ if (kb_all[i] && kb_all[j] && cross_sigs (email, kb_all[i], kb_all[j]))
die[j] = 1;
}
diff --git a/tests/openpgp/tofu.scm b/tests/openpgp/tofu.scm
index e514ddfd1..96f7abe7a 100755
--- a/tests/openpgp/tofu.scm
+++ b/tests/openpgp/tofu.scm
@@ -159,3 +159,76 @@
(checkpolicy "BC15C85A" "ask")
(checkpolicy "2183839A" "bad")
(checkpolicy "EE37CF96" "ask")
+
+
+
+;; Check that we detect the following attack:
+;;
+;; Alice and Bob each have a key and cross sign them. Bob then adds a
+;; new user id, "Alice". TOFU should now detect a conflict, because
+;; Alice only signed Bob's "Bob" user id.
+
+(display "Checking cross sigs...\n")
+(define GPG `(,(tool 'gpg) --no-permission-warning
+ --faked-system-time=1476304861))
+
+;; Carefully remove the TOFU db.
+(catch '() (unlink (string-append GNUPGHOME "/tofu.db")))
+
+(define DIR "tofu/cross-sigs")
+;; The test keys.
+(define KEYA "1938C3A0E4674B6C217AC0B987DB2814EC38277E")
+(define KEYB "DC463A16E42F03240D76E8BA8B48C6BD871C2247")
+
+(define (verify-messages)
+ (for-each
+ (lambda (key)
+ (for-each
+ (lambda (i)
+ (let ((fn (in-srcdir DIR (string-append key "-" i ".txt"))))
+ (call-check `(,@GPG --trust-model=tofu --verify ,fn))))
+ (list "1" "2")))
+ (list KEYA KEYB)))
+
+;; Import the public keys.
+(display " > Two keys. ")
+(call-check `(,@GPG --import ,(in-srcdir DIR (string-append KEYA "-1.gpg"))))
+(call-check `(,@GPG --import ,(in-srcdir DIR (string-append KEYB "-1.gpg"))))
+;; Make sure the tofu engine registers the keys.
+(verify-messages)
+(display "<\n")
+
+;; Since their is no conflict, the policy should be auto.
+(checkpolicy KEYA "auto")
+(checkpolicy KEYB "auto")
+
+;; Import the cross sigs.
+(display " > Adding cross signatures. ")
+(call-check `(,@GPG --import ,(in-srcdir DIR (string-append KEYA "-2.gpg"))))
+(call-check `(,@GPG --import ,(in-srcdir DIR (string-append KEYB "-2.gpg"))))
+(verify-messages)
+(display "<\n")
+
+;; There is still no conflict, so the policy shouldn't have changed.
+(checkpolicy KEYA "auto")
+(checkpolicy KEYB "auto")
+
+;; Import the conflicting user id.
+(display " > Adding conflicting user id. ")
+(call-check `(,@GPG --import ,(in-srcdir DIR (string-append KEYB "-3.gpg"))))
+(call-check `(,@GPG --trust-model=tofu
+ --verify ,(in-srcdir DIR (string-append KEYB "-1.txt"))))
+(verify-messages)
+(display "<\n")
+
+(checkpolicy KEYA "ask")
+(checkpolicy KEYB "ask")
+
+;; Import Alice's signature on the conflicting user id.
+(display " > Adding cross signature on user id. ")
+(call-check `(,@GPG --import ,(in-srcdir DIR (string-append KEYB "-4.gpg"))))
+(verify-messages)
+(display "<\n")
+
+(checkpolicy KEYA "auto")
+(checkpolicy KEYB "auto")
diff --git a/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-1.gpg b/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-1.gpg
new file mode 100644
index 000000000..e6becec47
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-1.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-1.txt b/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-1.txt
new file mode 100644
index 000000000..92236be2e
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-1.txt
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-2.gpg b/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-2.gpg
new file mode 100644
index 000000000..d26bd541d
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-2.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-2.txt b/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-2.txt
new file mode 100644
index 000000000..b4013d364
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-2.txt
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-3.txt b/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-3.txt
new file mode 100644
index 000000000..9b2d49d10
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-3.txt
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-secret.gpg b/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-secret.gpg
new file mode 100644
index 000000000..1839e3a3e
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/1938C3A0E4674B6C217AC0B987DB2814EC38277E-secret.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-1.gpg b/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-1.gpg
new file mode 100644
index 000000000..f706f7037
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-1.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-1.txt b/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-1.txt
new file mode 100644
index 000000000..0bdc1fc52
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-1.txt
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-2.gpg b/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-2.gpg
new file mode 100644
index 000000000..0b2485feb
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-2.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-2.txt b/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-2.txt
new file mode 100644
index 000000000..4d3aaaa44
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-2.txt
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-3.gpg b/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-3.gpg
new file mode 100644
index 000000000..eb2c43532
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-3.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-3.txt b/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-3.txt
new file mode 100644
index 000000000..9b2d49d10
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-3.txt
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-4.gpg b/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-4.gpg
new file mode 100644
index 000000000..9c98ec114
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-4.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-secret.gpg b/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-secret.gpg
new file mode 100644
index 000000000..a87c61b4f
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/DC463A16E42F03240D76E8BA8B48C6BD871C2247-secret.gpg
Binary files differ
diff --git a/tests/openpgp/tofu/cross-sigs/README b/tests/openpgp/tofu/cross-sigs/README
new file mode 100644
index 000000000..439962bd7
--- /dev/null
+++ b/tests/openpgp/tofu/cross-sigs/README
@@ -0,0 +1,79 @@
+# How I generate the keys and messages to verify:
+
+# Generate and export two non-conflicting keys.
+gpg --quick-gen-key 'Spy Cow <[email protected]>'
+gpg --quick-gen-key 'Spy R. Cow <[email protected]>'
+
+KEYIDA=1938C3A0E4674B6C217AC0B987DB2814EC38277E
+KEYIDB=DC463A16E42F03240D76E8BA8B48C6BD871C2247
+
+for KEYID in $KEYIDA $KEYIDB
+do
+ gpg --export $KEYID > tofu-$KEYID.gpg
+ gpg --export-secret-keys $KEYID > tofu-$KEYID-secret.gpg
+done
+
+# Sign some data.
+echo foo | gpg --default-key $KEYIDA -s > tofu-$KEYIDA-1.txt
+echo foo | gpg --default-key $KEYIDB -s > tofu-$KEYIDB-1.txt
+
+# Again, but with an issuer.
+echo foo | gpg --default-key "<[email protected]>" -s > tofu-$KEYIDA-2.txt
+echo foo | gpg --default-key "<[email protected]>" -s > tofu-$KEYIDB-2.txt
+
+# Have A sign B and vice versa.
+gpg --default-key $KEYIDA --quick-sign $KEYIDB
+gpg --default-key $KEYIDB --quick-sign $KEYIDA
+
+gpg --export $KEYIDA > tofu-$KEYIDA-2.gpg
+gpg --export $KEYIDB > tofu-$KEYIDB-2.gpg
+
+# Cause A and B to conflict.
+gpg --quick-adduid $KEYIDB 'Spy R. Cow <[email protected]>'
+gpg --export $KEYIDB > tofu-$KEYIDB-3.gpg
+
+echo foo | gpg --default-key "<[email protected]>" -s > tofu-$KEYIDA-3.txt
+echo foo | gpg --default-key "<[email protected]>" -s > tofu-$KEYIDB-3.txt
+
+# Have A sign B's conflicting user id.
+gpg --default-key $KEYIDA --quick-sign $KEYIDB
+gpg --export $KEYIDB > tofu-$KEYIDB-4.gpg
+
+exit 0
+
+# In a new directory (so the keys are not ultimately trusted).
+
+D=~/neal/work/gpg/test
+echo 'trust-model tofu+pgp' > gpg.conf
+gpg --import $D/tofu-$KEYIDA.gpg
+gpg --import $D/tofu-$KEYIDB.gpg
+gpg -k
+
+gpg --verify $D/tofu-$KEYIDA-1.txt
+gpg --verify $D/tofu-$KEYIDB-1.txt
+# With an issuer.
+gpg --verify $D/tofu-$KEYIDA-2.txt
+gpg --verify $D/tofu-$KEYIDB-2.txt
+
+# Import the cross signatures.
+gpg --import $D/tofu-$KEYIDA-2.gpg
+gpg --import $D/tofu-$KEYIDB-2.gpg
+gpg -k
+
+gpg --verify $D/tofu-$KEYIDA-1.txt
+gpg --verify $D/tofu-$KEYIDB-1.txt
+# With an issuer.
+gpg --verify $D/tofu-$KEYIDA-2.txt
+gpg --verify $D/tofu-$KEYIDB-2.txt
+
+
+gpg --status-fd=1 --batch --verify $D/tofu-$KEYIDA-3.txt | grep TRUST_UNDEFINED
+gpg --status-fd=1 --batch --verify $D/tofu-$KEYIDB-3.txt | grep TRUST_UNDEFINED
+
+# Import the conflicting user id.
+gpg --import $D/tofu-$KEYIDB-3.gpg
+gpg -k
+
+# Import the cross signature, which should remove the conflict.
+gpg --import $D/tofu-$KEYIDB-4.gpg
+gpg -k