summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2018-04-13 11:51:50 +0100
committerJeremy Harris <jgh146exb@wizmail.org>2018-04-13 11:51:50 +0100
commit321ef002e23ff171922075988bcd8e77bae884b7 (patch)
treee175340e36494ba62043d8b6493214215b4b9d1f
parent0f9d3f8ba8cf8b559b74ba9166d8a436498651b4 (diff)
DKIM: add support for the SubjectPublicKeyInfo wrapped form of pubkey
-rw-r--r--doc/doc-docbook/spec.xfpt5
-rw-r--r--doc/doc-txt/ChangeLog4
-rw-r--r--src/src/pdkim/pdkim.c27
-rw-r--r--test/dnszones-src/db.test.ex8
-rw-r--r--test/log/454016
-rw-r--r--test/scripts/4540-DKIM-Ed25519/454036
6 files changed, 87 insertions, 9 deletions
diff --git a/doc/doc-docbook/spec.xfpt b/doc/doc-docbook/spec.xfpt
index d8f1573c9..a35a8bf26 100644
--- a/doc/doc-docbook/spec.xfpt
+++ b/doc/doc-docbook/spec.xfpt
@@ -39067,6 +39067,11 @@ To produce the required public key value for a DNS record:
openssl pkey -outform DER -pubout -in dkim_ed25519.private | tail -c +13 | base64
certtool --load_privkey=dkim_ed25519.private --pubkey_info --outder | tail -c +13 | base64
.endd
+
+Note that the format
+of Ed25519 keys in DNS has not yet been decided; this release supports
+both of the leading candidates at this time, a future release will
+probably drop support for whichever proposal loses
.wen
.option dkim_hash smtp string&!! sha256
diff --git a/doc/doc-txt/ChangeLog b/doc/doc-txt/ChangeLog
index 9fc466365..83a37d515 100644
--- a/doc/doc-txt/ChangeLog
+++ b/doc/doc-txt/ChangeLog
@@ -206,6 +206,10 @@ JH/37 Bug 2255: Revert the disable of the OpenSSL session caching. This
PP/03 Add util/renew-opendmarc-tlds.sh script for safe renewal of public
suffix list.
+JH/38 DKIM: accept Ed25519 pubkeys in SubjectPublicKeyInfo-wrapped form,
+ since the IETF WG has not yet settled on that versus the original
+ "bare" representation.
+
Exim version 4.90
-----------------
diff --git a/src/src/pdkim/pdkim.c b/src/src/pdkim/pdkim.c
index 149cff86c..5688c78a8 100644
--- a/src/src/pdkim/pdkim.c
+++ b/src/src/pdkim/pdkim.c
@@ -80,7 +80,7 @@ const pdkim_hashtype pdkim_hashes[] = {
const uschar * pdkim_keytypes[] = {
[KEYTYPE_RSA] = US"rsa",
#ifdef SIGN_HAVE_ED25519
- [KEYTYPE_ED25519] = US"ed25519", /* Works for 3.6.0 GnuTLS */
+ [KEYTYPE_ED25519] = US"ed25519", /* Works for 3.6.0 GnuTLS, OpenSSL 1.1.1 */
#endif
#ifdef notyet_EC_dkim_extensions /* https://tools.ietf.org/html/draft-srose-dkim-ecc-00 */
@@ -1336,6 +1336,28 @@ return string_from_gstring(hdr);
/* -------------------------------------------------------------------------- */
+/* According to draft-ietf-dcrup-dkim-crypto-07 "keys are 256 bits" (referring
+to DNS, hence the pubkey). Check for more than 32 bytes; if so assume the
+alternate possible representation (still) being discussed: a
+SubjectPublickeyInfo wrapped key - and drop all but the trailing 32-bytes (it
+should be a DER, with exactly 12 leading bytes - but we could accept a BER also,
+which could be any size). We still rely on the crypto library for checking for
+undersize.
+
+When the RFC is published this should be re-addressed. */
+
+static void
+check_bare_ed25519_pubkey(pdkim_pubkey * p)
+{
+int excess = p->key.len - 32;
+if (excess > 0)
+ {
+ DEBUG(D_acl) debug_printf("PDKIM: unexpected pubkey len %lu\n", p->key.len);
+ p->key.data += excess; p->key.len = 32;
+ }
+}
+
+
static pdkim_pubkey *
pdkim_key_from_dns(pdkim_ctx * ctx, pdkim_signature * sig, ev_ctx * vctx,
const uschar ** errstr)
@@ -1408,6 +1430,9 @@ if (sig->keytype < 0)
}
k_ok:
+if (sig->keytype == KEYTYPE_ED25519)
+ check_bare_ed25519_pubkey(p);
+
if ((*errstr = exim_dkim_verify_init(&p->key,
sig->keytype == KEYTYPE_ED25519 ? KEYFMT_ED25519_BARE : KEYFMT_DER,
vctx)))
diff --git a/test/dnszones-src/db.test.ex b/test/dnszones-src/db.test.ex
index b8abd2845..492ee5df8 100644
--- a/test/dnszones-src/db.test.ex
+++ b/test/dnszones-src/db.test.ex
@@ -556,9 +556,15 @@ sel2._domainkey TXT "v=DKIM1; p=MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDXRFf+VhT+
; EC signing, using Ed25519
; - needs GnuTLS 3.6.0 (fedora rawhide has that)
; certtool --generate-privkey --key-type=ed25519 --outfile=dkim_ed25519.private
-; ../src/util/ed25519_privkey_pem_to_pubkey_raw_b64 dkim_ed25519.private
+; certtool --load_privkey=dkim_ed25519.private --pubkey_info --outder | tail -c +13 | base64
sed._domainkey TXT "v=DKIM1; k=ed25519; p=sPs07Vu29FpHT/80UXUcYHFOHifD4o2ZlP2+XUh9g6E="
+; version of the above wrapped in SubjectPublicKeyInfo, in case the WG plumps in that direction
+; certtool --load_privkey=aux-fixed/dkim/dkim_ed25519.private --pubkey_info
+; (and grab the b64 content from between the pem headers)
+
+sedw._domainkey TXT "v=DKIM1; k=ed25519; p=MCowBQYDK2VwAyEAsPs07Vu29FpHT/80UXUcYHFOHifD4o2ZlP2+XUh9g6E="
+
; End
diff --git a/test/log/4540 b/test/log/4540
index 58039465a..7d0c92bd7 100644
--- a/test/log/4540
+++ b/test/log/4540
@@ -5,9 +5,13 @@
1999-03-02 09:44:33 10HmaX-0005vi-00 DKIM: d=test.ex s=sed c=relaxed/relaxed a=ed25519-sha256 b=512 [verification succeeded]
1999-03-02 09:44:33 10HmaX-0005vi-00 Authentication-Results: myhost.test.ex;\n dkim=pass header.d=test.ex header.s=sed header.a=ed25519-sha256
1999-03-02 09:44:33 10HmaX-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss DKIM=test.ex id=E10HmaY-0005vi-00@myhost.test.ex
-1999-03-02 09:44:33 10HmaZ-0005vi-00 signer: kitterman.org bits: 512
-1999-03-02 09:44:33 10HmaZ-0005vi-00 DKIM: d=kitterman.org s=ed25519 c=relaxed/simple a=ed25519-sha256 b=512 i=@kitterman.org t=1517847601 [verification succeeded]
-1999-03-02 09:44:33 10HmaZ-0005vi-00 signer: @kitterman.org bits: 512
-1999-03-02 09:44:33 10HmaZ-0005vi-00 DKIM: d=kitterman.org s=ed25519 c=relaxed/simple a=ed25519-sha256 b=512 i=@kitterman.org t=1517847601 [verification succeeded]
-1999-03-02 09:44:33 10HmaZ-0005vi-00 Authentication-Results: myhost.test.ex;\n dkim=pass header.d=kitterman.org header.i=@kitterman.org header.s=ed25519 header.a=ed25519-sha256
-1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss DKIM=kitterman.org id=example@example.com
+1999-03-02 09:44:33 10HmaZ-0005vi-00 signer: test.ex bits: 512
+1999-03-02 09:44:33 10HmaZ-0005vi-00 DKIM: d=test.ex s=sedw c=relaxed/relaxed a=ed25519-sha256 b=512 [verification succeeded]
+1999-03-02 09:44:33 10HmaZ-0005vi-00 Authentication-Results: myhost.test.ex;\n dkim=pass header.d=test.ex header.s=sedw header.a=ed25519-sha256
+1999-03-02 09:44:33 10HmaZ-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss DKIM=test.ex id=E10HmaY-0005vi-00@myhost.test.ex
+1999-03-02 09:44:33 10HmbA-0005vi-00 signer: kitterman.org bits: 512
+1999-03-02 09:44:33 10HmbA-0005vi-00 DKIM: d=kitterman.org s=ed25519 c=relaxed/simple a=ed25519-sha256 b=512 i=@kitterman.org t=1517847601 [verification succeeded]
+1999-03-02 09:44:33 10HmbA-0005vi-00 signer: @kitterman.org bits: 512
+1999-03-02 09:44:33 10HmbA-0005vi-00 DKIM: d=kitterman.org s=ed25519 c=relaxed/simple a=ed25519-sha256 b=512 i=@kitterman.org t=1517847601 [verification succeeded]
+1999-03-02 09:44:33 10HmbA-0005vi-00 Authentication-Results: myhost.test.ex;\n dkim=pass header.d=kitterman.org header.i=@kitterman.org header.s=ed25519 header.a=ed25519-sha256
+1999-03-02 09:44:33 10HmbA-0005vi-00 <= CALLER@bloggs.com H=(xxx) [127.0.0.1] P=smtp S=sss DKIM=kitterman.org id=example@example.com
diff --git a/test/scripts/4540-DKIM-Ed25519/4540 b/test/scripts/4540-DKIM-Ed25519/4540
index 0be08ea31..504676e7c 100644
--- a/test/scripts/4540-DKIM-Ed25519/4540
+++ b/test/scripts/4540-DKIM-Ed25519/4540
@@ -6,7 +6,7 @@ exim -DSERVER=server -bd -oX PORT_D
# This should pass, only Mail::DKIM::Signer does not handle ed25519-sha256 yet
#
# Mail original (will be)in aux-fixed/4500.msg1.txt
-# Sig generated by: perl aux-fixed/dkim/sign.pl --algorithm=ed255190sha256 \
+# Sig (would be) generated by: perl aux-fixed/dkim/sign.pl --algorithm=ed255190sha256 \
# --method=simple/simple < aux-fixed/4500.msg1.txt
#
# TODO - until we have that we can only test internal consistency,
@@ -44,6 +44,40 @@ QUIT
****
#
#
+# Duplicate of the above, but referencing a pubkey in "wrapped-in-SubjectPublicKeyInfo"
+# format. Should pass also.
+client 127.0.0.1 PORT_D
+??? 220
+HELO xxx
+??? 250
+MAIL FROM:<CALLER@bloggs.com>
+??? 250
+RCPT TO:<a@test.ex>
+??? 250
+DATA
+??? 354
+DKIM-Signature: v=1; a=ed25519-sha256; q=dns/txt; c=relaxed/relaxed; d=test.ex
+ ; s=sedw; h=From:To:Subject; bh=/Ab0giHZitYQbDhFszoqQRUkgqueaX9zatJttIU/plc=;
+ b=g0aVl5sI4fFLWDwXj9SnLgENXg2u8H8kKgK5/bXBZ7DKAImkm2+4tRzz1UOveu/Navis53Bg/C
+ 9nPxsspzb/Dg==;
+Received: from jgh by myhost.test.ex with local (Exim x.yz)
+ envelope-from <jgh@myhost.test.ex>)
+ 1dtXln-0000YP-Hb
+ a@test.ex; Sun, 17 Sep 2017 12:29:51 +0100
+From: nobody@example.com
+Message-Id: <E1dtXln-0000YP-Hb@myhost.test.ex>
+Sender: CALLER_NAME <jgh@myhost.test.ex>
+Date: Sun, 17 Sep 2017 12:29:51 +0100
+
+content
+.
+??? 250
+QUIT
+??? 221
+****
+#
+#
+
# This should pass, an independently-generated sample from Scott Kitterman.
# I don't want to retain this longterm as it hits an external DNS record,
# not under the testsuite.