chiark / gitweb /
xdh.c: New module defining elliptic curve Diffie--Hellman functions.
authorMark Wooding <mdw@distorted.org.uk>
Fri, 28 Apr 2017 21:51:36 +0000 (22:51 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 8 Dec 2019 00:38:42 +0000 (00:38 +0000)
This provides X25519 and X448 as premade Diffie--Hellman closures.  They
should be used directly rather than applied to arguments.

Signed-off-by: Mark Wooding <mdw@distorted.org.uk>
Subdir.sd.mk
magic.h
modules.c
secnet-wireshark.lua
secnet.8
secnet.h
xdh.c [new file with mode: 0644]

index b4aba8a32a46668d25d297a7f42bfdc4f3e25264..ee2045722eec033ef6e7adbac0aa17804b059341 100644 (file)
@@ -49,7 +49,7 @@ TARGETS:=secnet
 OBJECTS:=secnet.o util.o conffile.yy.o conffile.tab.o conffile.o modules.o \
        resolver.o random.o udp.o site.o transform-cbcmac.o transform-eax.o \
        comm-common.o polypath.o privcache.o pubkeys.o pubkeys.yy.o \
-       netlink.o rsa.o dh.o serpent.o serpentbe.o \
+       netlink.o rsa.o dh.o xdh.o serpent.o serpentbe.o \
        f25519.o x25519.o fgoldi.o x448.o \
        md5.o sha512.o tun.o slip.o sha1.o ipaddr.o log.o \
        process.o osdep.o @LIBOBJS@ \
diff --git a/magic.h b/magic.h
index 9c071c0d3d07896a703c15f5545d76ffa895b27d..ca613cb2de36b8a7201b8b7ba5c93e31ab2b8da7 100644 (file)
--- a/magic.h
+++ b/magic.h
 #define CAPAB_BIT_SERPENT256CBC         8
 #define CAPAB_BIT_EAXSERPENT            9
 #define CAPAB_BIT_TRADZP              10
+#define CAPAB_BIT_X25519              11
+#define CAPAB_BIT_X448                12
 #define CAPAB_BIT_EXPLICIT_TRANSFORM_DH 15
 #define CAPAB_BIT_MAX                  31
 
index 191724b51fd8907a391694a4f665579f763587d8..e9009e1f44f60123c5e796f419ecbe54221347f1 100644 (file)
--- a/modules.c
+++ b/modules.c
@@ -33,6 +33,7 @@ void init_builtin_modules(dict_t *dict)
     netlink_module(dict);
     rsa_module(dict);
     dh_module(dict);
+    xdh_module(dict);
     md5_module(dict);
     slip_module(dict);
     tun_module(dict);
index 2a6761d12c7876279efb1fc69e0915e633462fd1..b9c42b8b748b2b290ea34fb4410b5c17a9db2381 100644 (file)
@@ -226,6 +226,10 @@ local CAPTAB = {
          desc = "Serpent256-EAX transform" },
   [10] = { name = "tradzp", kind = "dhgroup",
           desc = "Traditional Z_p Diffie--Hellman key agreement" },
+  [11] = { name = "x25519", kind = "dhgroup",
+          desc = "X25519 elliptic curve Diffie--Hellman key agreement" },
+  [12] = { name = "x448", kind = "dhgroup",
+          desc = "X448 elliptic curve Diffie--Hellman key agreement" },
   [31] = { name = "mobile-priority", kind = "early",
           desc = "Mobile site takes priority in case of MSG1 crossing" }
 }
index d93acc1e4ce45458f675447e40e5a55663c1e37f..b6a84957119e0768413579291a6451103b17d802 100644 (file)
--- a/secnet.8
+++ b/secnet.8
@@ -340,6 +340,36 @@ The default capability number is 10.
 .PP
 A \fIdh closure\fR defines a group to be used for key exchange.
 
+.SS x25519
+.PP
+\fBx25519
+.PP
+A premade \fIdh closure\fR
+which uses Daniel Bernstein's X25519 key-exchange function.
+This uses an elliptic curve called Curve25519,
+defined over a 255-bit field.
+The function is fast and very well-studied.
+.PP
+A \fIdh closure\fR defines a group to be used for key exchange.
+The
+.B x25519
+Diffie\(enHellman group always uses capability number 24.
+
+.SS x448
+.PP
+\fBx448
+.PP
+A premade \fIdh closure\fR
+which uses Mike Hamburg's X448 key-exchange function.
+This uses an elliptic curve called Ed448-Goldilocks,
+defined over a 448-bit field.
+The function is unusually quick and fairly well studied.
+.PP
+A \fIdh closure\fR defines a group to be used for key exchange.
+The
+.B x448
+Diffie\(enHellman group always uses capability number 25.
+
 .SS logfile
 \fBlogfile(\fIDICT\fB)\fR => \fIlog closure\fR
 .PP
index 5d0d8fe371e499f41b064c9ca285ded95f8ce16b..64cbefa96f78e81031757fd5b217bbd37f4d7419 100644 (file)
--- a/secnet.h
+++ b/secnet.h
@@ -389,6 +389,7 @@ extern init_module transform_cbcmac_module;
 extern init_module netlink_module;
 extern init_module rsa_module;
 extern init_module dh_module;
+extern init_module xdh_module;
 extern init_module md5_module;
 extern init_module slip_module;
 extern init_module tun_module;
diff --git a/xdh.c b/xdh.c
new file mode 100644 (file)
index 0000000..5795f43
--- /dev/null
+++ b/xdh.c
@@ -0,0 +1,105 @@
+/*
+ * xdh.c: x-coordinate-only Montgomery-ladder elliptic-curve Diffie--Hellman
+ */
+/*
+ * This file is Free Software.  It was originally written for secnet.
+ *
+ * Copyright 2017 Mark Wooding
+ *
+ * You may redistribute secnet as a whole and/or modify it under the
+ * terms of the GNU General Public License as published by the Free
+ * Software Foundation; either version 3, or (at your option) any
+ * later version.
+ *
+ * You may redistribute this file and/or modify it under the terms of
+ * the GNU General Public License as published by the Free Software
+ * Foundation; either version 2, or (at your option) any later
+ * version.
+ *
+ * This software 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 software; if not, see
+ * https://www.gnu.org/licenses/gpl.html.
+ */
+
+#include <stdio.h>
+#include <limits.h>
+
+#include "secnet.h"
+#include "magic.h"
+#include "util.h"
+
+#include "x25519.h"
+#include "x448.h"
+
+#define XDH_MAXSZ 64
+
+typedef void xdh_fn(uint8_t *z, const uint8_t *k, const uint8_t *x);
+
+struct xdh {
+    closure_t cl;
+    struct dh_if ops;
+    xdh_fn *fn;
+    const uint8_t *base;
+};
+
+static int32_t xdh_makepublic(void *sst, void *pub, int32_t publen,
+                             uint8_t *k, int32_t klen)
+{
+    struct xdh *st = sst;
+
+    assert(klen == st->ops.secret_len);
+    assert(publen >= st->ops.public_len);
+    st->fn(pub, k, st->base);
+    return st->ops.public_len;
+}
+
+static bool_t xdh_makeshared(void *sst,
+                            uint8_t *k, int32_t klen,
+                            const void *pub, int32_t publen,
+                            uint8_t *z, int32_t zlen)
+{
+    struct xdh *st = sst;
+
+    assert(klen == st->ops.secret_len);
+    assert(zlen >= st->ops.shared_len);
+    if (publen != st->ops.public_len) {
+       Message(M_ERR,
+               "xdh_makeshared: incoming public point has wrong length");
+       return False;
+    }
+    st->fn(z, k, pub);
+    return (True);
+}
+
+static void make_xdh_closure(dict_t *dict, const char *name, xdh_fn *fn,
+                            const uint8_t *base, size_t sz, int cap)
+{
+    struct xdh *st;
+
+    NEW(st);
+    st->cl.description = name;
+    st->cl.type = CL_DH;
+    st->cl.apply = 0;
+    st->cl.interface = &st->ops;
+    st->ops.st = st;
+    st->ops.makepublic = xdh_makepublic;
+    st->ops.makeshared = xdh_makeshared;
+    st->ops.secret_len = st->ops.public_len = st->ops.shared_len = sz;
+    st->ops.capab_bit = cap;
+    st->fn = fn;
+    st->base = base;
+    dict_add(dict, name, new_closure(&st->cl));
+}
+
+void xdh_module(dict_t *dict)
+{
+    make_xdh_closure(dict, "x25519", x25519, x25519_base,
+                    X25519_PUBSZ, CAPAB_BIT_X25519);
+    make_xdh_closure(dict, "x448", x448, x448_base,
+                    X448_PUBSZ, CAPAB_BIT_X448);
+}