chiark / gitweb /
server/, keys/: Support Bernstein's X25519 and Hamburg's X448 algorithms.
authorMark Wooding <mdw@distorted.org.uk>
Thu, 26 May 2016 08:26:09 +0000 (09:26 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Sun, 14 May 2017 17:19:09 +0000 (18:19 +0100)
keys/tripe-keys.conf.5.in
keys/tripe-keys.in
keys/tripe-keys.master
server/dh.c
server/tests.at
server/tripe.8.in
server/tripe.h
t/keyring-alpha

index ab4c9e1..4fc0485 100644 (file)
@@ -148,7 +148,7 @@ or
 .B ec
 (elliptic curves).  The default is
 .BR dh .
-.ne 7
+.ne 9
 .TP
 .I kx-genalg
 Key generation algorithm name to pass to
@@ -166,9 +166,11 @@ kx kx-genalg
 _
 dh     dh
 ec     ec
+x25519 x25519
+x448   x448
 _
 .TE
-.ne 7
+.ne 9
 .TP
 .I kx-param-genalg
 Key generation algorithm name to pass to
@@ -186,9 +188,11 @@ kx kx-param-genalg
 _
 dh     dh-param
 ec     ec-param
+x25519 empty
+x448   empty
 _
 .TE
-.ne 7
+.ne 9
 .TP
 .I kx-param
 Options to pass to
@@ -205,8 +209,11 @@ kx kx-param
 _
 dh     \-LS \-b3072 \-B256
 ec     \-Cnist-p256
+x25519 \fInone
+x448   \fInone
 _
 .TE
+.ne 9
 .TP
 .I kx-attrs
 Additional attributes to set on the parameters
@@ -214,8 +221,22 @@ Additional attributes to set on the parameters
 as
 .IB key = value
 pairs separated by spaces.
-Default is
-.BR serialization=constlen .
+Default depends on
+.I kx
+as follows.
+.TS
+center;
+| ci | ci |
+| lb | lb |.
+_
+kx     kx-attrs
+_
+dh     serialization=constlen
+ec     serialization=constlen
+x25519 \fIempty
+x448   \fIempty
+_
+.TE
 .TP
 .I kx-expire
 Expiry time for generated keys.  Default is
@@ -278,7 +299,7 @@ iiv rijndael-cbc
 naclbox        chacha20
 _
 .TE
-.ne 7
+.ne 8
 .TP
 .I sig
 Signature scheme to use.  Must be one of those recognized by
@@ -295,6 +316,8 @@ kx  sig
 _
 dh     dsa
 ec     ecdsa
+x25519 ed25519
+x448   ed448
 _
 .TE
 .ne 12
index 62b62b6..cfa740b 100644 (file)
@@ -239,12 +239,21 @@ def conf_defaults():
                ('upload-hook', ': run upload hook'),
                ('kx', 'dh'),
                ('kx-genalg', lambda: {'dh': 'dh',
-                                      'ec': 'ec'}[conf['kx']]),
+                                      'ec': 'ec',
+                                      'x25519': 'x25519',
+                                      'x448': 'x448'}[conf['kx']]),
                ('kx-param-genalg', lambda: {'dh': 'dh-param',
-                                            'ec': 'ec-param'}[conf['kx']]),
+                                            'ec': 'ec-param',
+                                            'x25519': 'empty',
+                                            'x448': 'empty'}[conf['kx']]),
                ('kx-param', lambda: {'dh': '-LS -b3072 -B256',
-                                     'ec': '-Cnist-p256'}[conf['kx']]),
-               ('kx-attrs', 'serialization=constlen'),
+                                     'ec': '-Cnist-p256',
+                                     'x25519': '',
+                                     'x448': ''}[conf['kx']]),
+               ('kx-attrs', lambda: {'dh': 'serialization=constlen',
+                                     'ec': 'serialization=constlen',
+                                     'x25519': '',
+                                     'x448': ''}[conf['kx']]),
                ('kx-expire', 'now + 1 year'),
                ('kx-warn-days', '28'),
                ('bulk', 'iiv'),
@@ -259,7 +268,10 @@ def conf_defaults():
                                  or '%s-hmac/%d' %
                                       (conf['hash'],
                                        C.gchashes[conf['hash']].hashsz * 4)),
-               ('sig', lambda: {'dh': 'dsa', 'ec': 'ecdsa'}[conf['kx']]),
+               ('sig', lambda: {'dh': 'dsa',
+                                'ec': 'ecdsa',
+                                'x25519': 'ed25519',
+                                'x448': 'ed448'}[conf['kx']]),
                ('sig-fresh', 'always'),
                ('sig-genalg', lambda: {'kcdsa': 'dh',
                                        'dsa': 'dsa',
index 121bd91..8e16524 100644 (file)
 ###--------------------------------------------------------------------------
 ### Crypto parameters.
 
-## The key-exchange type.  May be `dh' or `ec'.
+## The key-exchange type.  May be `dh', `ec', `x25519', or `x448'.
 # kx = dh
 
 ## Key-generation parameters for key exchange group.
 # kx-param = -LS -b3072 -B256
 # kx-param = -Pnist-p256
+# kx-param =
 
 ## Expiry time for peer key-exchange keys.
 # kx-expire = now + 1 year
index 314da5e..5c27a07 100644 (file)
@@ -639,6 +639,172 @@ static const char *ecdh_gestr(const dhgrp *gg, const dhge *YY)
 static void ecdh_freege(const dhgrp *gg, dhge *YY)
   { ecdh_ge *Y = (ecdh_ge *)YY; EC_DESTROY(&Y->Q); DESTROY(Y); }
 
+/*----- The X25519 and similar groups -------------------------------------*/
+
+#define XDHS(_)                                                                \
+  _(x25519, X25519, "curve25519", 252, 255)                            \
+  _(x448, X448, "ed448-goldilocks", 446, 448)
+
+#ifdef NTRACE
+#  define XDHTRACE(xdh, XDH, gname)
+#else
+
+   static const char *binstr(const octet *p, size_t sz)
+   {
+     char *q;
+
+     for (q = (char *)buf_u; sz--; p++, q += 2) sprintf(q, "%02x", *p);
+     return ((const char *)buf_u);
+   }
+
+#  define XDHTRACE(xdh, XDH, gname)                                    \
+     static void xdh##_tracegrp(const dhgrp *g)                                \
+       { trace(T_CRYPTO, "crypto: group type `" gname "'"); }          \
+                                                                       \
+     static const char *xdh##_scstr(const dhgrp *g, const dhsc *xx)    \
+     {                                                                 \
+       const xdh##_sc *x = (const xdh##_sc *)xx;                       \
+       return (binstr(x->x, XDH##_KEYSZ));                             \
+     }                                                                 \
+                                                                       \
+     static const char *xdh##_gestr(const dhgrp *g, const dhge *YY)    \
+     {                                                                 \
+       const xdh##_ge *Y = (const xdh##_ge *)YY;                       \
+       return (binstr(Y->X, XDH##_PUBSZ));                             \
+     }
+#endif
+
+#define XDHDEF(xdh, XDH, gname, groupbits, fieldbits)                  \
+                                                                       \
+  typedef struct xdh##_sc { octet x[XDH##_KEYSZ]; } xdh##_sc;          \
+  typedef struct xdh##_ge { octet X[XDH##_PUBSZ]; } xdh##_ge;          \
+                                                                       \
+  XDHTRACE(xdh, XDH, gname)                                            \
+                                                                       \
+  static dhsc *xdh##_bintosc(const key_bin *b)                         \
+  {                                                                    \
+    xdh##_sc *x;                                                       \
+                                                                       \
+    if (b->sz != XDH##_KEYSZ) return (0);                              \
+    x = CREATE(xdh##_sc);                                              \
+    memcpy(x->x, b->k, XDH##_KEYSZ);                                   \
+    return ((dhsc *)x);                                                        \
+  }                                                                    \
+                                                                       \
+  static dhge *xdh##_bintoge(const key_bin *b)                         \
+  {                                                                    \
+    xdh##_ge *Y;                                                       \
+                                                                       \
+    if (b->sz != XDH##_PUBSZ) return (0);                              \
+    Y = CREATE(xdh##_ge);                                              \
+    memcpy(Y->X, b->k, XDH##_PUBSZ);                                   \
+    return ((dhge *)Y);                                                        \
+  }                                                                    \
+                                                                       \
+  KLOAD(xdh, xdh, XDH,                                                 \
+       { kd->grp = CREATE(dhgrp); kd->grp->scsz = 32; },               \
+       { if ((kd->k = xdh##_bintosc(&p.priv)) == 0) {                  \
+           a_format(e, "bad-private-key", A_END);                      \
+           goto fail;                                                  \
+         }                                                             \
+       },                                                              \
+       { if ((kd->K = xdh##_bintoge(&p.pub)) == 0) {                   \
+           a_format(e, "bad-public-vector", A_END);                    \
+           goto fail;                                                  \
+         }                                                             \
+       })                                                              \
+                                                                       \
+  static const char *xdh##_checkgrp(const dhgrp *g)                    \
+    { return (0); }                                                    \
+                                                                       \
+  static void xdh##_grpinfo(const dhgrp *g, admin *adm)                        \
+  {                                                                    \
+    a_info(adm,                                                                \
+          "kx-group=" gname,                                           \
+          "kx-group-order-bits=%d", (groupbits),                       \
+          "kx-group-elt-bits=%d", (fieldbits),                         \
+          A_END);                                                      \
+  }                                                                    \
+                                                                       \
+  static int xdh##_samegrpp(const dhgrp *g, const dhgrp *hh)           \
+    { return (1); }                                                    \
+                                                                       \
+  static void xdh##_freegrp(dhgrp *g)                                  \
+    { DESTROY(g); }                                                    \
+                                                                       \
+  static dhsc *xdh##_ldsc(const dhgrp *g, const void *p, size_t sz)    \
+  {                                                                    \
+    xdh##_sc *x;                                                       \
+    if (sz != XDH##_KEYSZ) return (0);                                 \
+    x = CREATE(xdh##_sc);                                              \
+    memcpy(x->x, p, XDH##_KEYSZ);                                      \
+    return ((dhsc *)x);                                                        \
+  }                                                                    \
+                                                                       \
+  static int xdh##_stsc(const dhgrp *g, void *p, size_t sz,            \
+                       const dhsc *xx)                                 \
+  {                                                                    \
+    const xdh##_sc *x = (const xdh##_sc *)xx;                          \
+    if (sz != XDH##_KEYSZ) return (-1);                                        \
+    memcpy(p, x->x, XDH##_KEYSZ);                                      \
+    return (0);                                                                \
+  }                                                                    \
+                                                                       \
+  static dhsc *xdh##_randsc(const dhgrp *g)                            \
+  {                                                                    \
+    xdh##_sc *x = CREATE(xdh##_sc);                                    \
+    rand_get(RAND_GLOBAL, x->x, XDH##_KEYSZ);                          \
+    return ((dhsc *)x);                                                        \
+  }                                                                    \
+                                                                       \
+  static void xdh##_freesc(const dhgrp *g, dhsc *xx)                   \
+    { xdh##_sc *x = (xdh##_sc *)xx; DESTROY(x); }                      \
+                                                                       \
+  static dhge *xdh##_ldge(const dhgrp *g, buf *b, int fmt)             \
+  {                                                                    \
+    xdh##_ge *Y;                                                       \
+    const octet *p;                                                    \
+                                                                       \
+    if ((p = buf_get(b, XDH##_PUBSZ)) == 0) return (0);                        \
+    Y = CREATE(xdh##_ge); memcpy(Y->X, p, XDH##_PUBSZ);                        \
+    return ((dhge *)Y);                                                        \
+  }                                                                    \
+                                                                       \
+  static int xdh##_stge(const dhgrp *g, buf *b,                                \
+                       const dhge *YY, int fmt)                        \
+  {                                                                    \
+    const xdh##_ge *Y = (const xdh##_ge *)YY;                          \
+    return (buf_put(b, Y->X, XDH##_PUBSZ));                            \
+  }                                                                    \
+                                                                       \
+  static int xdh##_checkge(const dhgrp *g, const dhge *YY)             \
+    { return (0); }                                                    \
+                                                                       \
+  static int xdh##_eq(const dhgrp *g, const dhge *YY, const dhge *ZZ)  \
+  {                                                                    \
+    const xdh##_ge                                                     \
+      *Y = (const xdh##_ge *)YY, *Z = (const xdh##_ge *)ZZ;            \
+    return (ct_memeq(Y->X, Z->X, XDH##_PUBSZ));                                \
+  }                                                                    \
+                                                                       \
+  static dhge *xdh##_mul(const dhgrp *g,                               \
+                        const dhsc *xx, const dhge *YY)                \
+  {                                                                    \
+    const xdh##_sc *x = (const xdh##_sc *)xx;                          \
+    const xdh##_ge *Y = (const xdh##_ge *)YY;                          \
+    xdh##_ge *Z = CREATE(xdh##_ge);                                    \
+                                                                       \
+    xdh(Z->X, x->x, Y ? Y->X : xdh##_base);                            \
+    return ((dhge *)Z);                                                        \
+  }                                                                    \
+                                                                       \
+  static void xdh##_freege(const dhgrp *g, dhge *YY)                   \
+    { xdh##_ge *Y = (xdh##_ge *)YY; DESTROY(Y); }
+
+XDHS(XDHDEF)
+
+#undef XDHDEF
+
 /*----- Diffie--Hellman group table ---------------------------------------*/
 
 const dhops dhtab[] = {
@@ -657,6 +823,10 @@ const dhops dhtab[] = {
   DH("dh", intdh)
   DH("ec", ecdh)
 
+#define XDHDH(xdh, XDH, gname, groupbits, fieldbits) DH(#xdh, xdh)
+  XDHS(XDHDH)
+#undef XDHDH
+
 #undef DH
 
   { 0 }
index 88b9d16..f3f7c2e 100644 (file)
@@ -586,10 +586,10 @@ WITH_3TRIPES([alice], [bob], [carol], [-nslip -Tmx],
   for p in $princs; do TRIPECTL -d$p RELOAD; done
 
   AT_DATA([algs-alpha], [dnl
-kx-group=ec kx-group-order-bits=256 kx-group-elt-bits=512
+kx-group=curve25519 kx-group-order-bits=252 kx-group-elt-bits=255
 hash=sha256 mgf=sha256-mgf hash-sz=32
 bulk-transform=naclbox bulk-overhead=20
-cipher=salsa20 cipher-keysz=32
+cipher=chacha20 cipher-keysz=32
 mac=poly1305 mac-tagsz=16
 cipher-data-limit=2147483648
 ])
index c19ee57..9b3be60 100644 (file)
@@ -349,6 +349,69 @@ key add \-aec \-pparam \-talice \e
        \-e"now + 1 year" tripe
 .VE
 .RE
+.sv -1
+.TP
+.B x25519
+.RS
+Use Bernstein's X25519 Diffie\(enHellman function.
+This is technically a variant on
+the general elliptic curve Diffie\(enHellman
+available through the
+.B ec
+setting,
+but carefully designed and heavily optimized.
+.PP
+To create
+.B x25519
+keys,
+say something like
+.VS
+key add \-aempty \-eforever \e
+       \-tparam tripe\-param kx-group=x25519
+.VE
+to construct a parameters key
+(see
+.BR key (1)
+for details);
+and create the private keys by
+.VS
+key add \-ax25519 \-pparam \-talice \e
+       \-e"now + 1 year" tripe
+.VE
+.RE
+.sv -1
+.TP
+.B x448
+.RS
+Use Hamburg's X448 Diffie\(enHellman function.
+Like
+.B x25519
+above,
+this is technically a variant on
+the general elliptic curve Diffie\(enHellman
+available through the
+.B ec
+setting,
+but carefully designed and heavily optimized.
+.PP
+To create
+.B x448
+keys,
+say something like
+.VS
+key add \-aempty \-eforever \e
+       \-tparam tripe\-param kx-group=x448
+.VE
+to construct a parameters key
+(see
+.BR key (1)
+for details);
+and create the private keys by
+.VS
+key add \-ax448 \-pparam \-talice \e
+       \-e"now + 1 year" tripe
+.VE
+.RE
 Note that the
 .BR tripe-keys (8)
 program provides a rather more convenient means for generating and
index ad2c0bd..56cd0b4 100644 (file)
 #include <catacomb/ec.h>
 #include <catacomb/ec-raw.h>
 #include <catacomb/ec-keys.h>
+#include <catacomb/x25519.h>
+#include <catacomb/x448.h>
 
 #include "priv.h"
 #include "protocol.h"
index ef20b68..321bc09 100644 (file)
@@ -1,5 +1,5 @@
-65604204:tripe-ec:bob struct:[p=ec,public:0x6df064afcdc923160114d2919f014bcef1051bf5cb3071194088a10be4f0c992,0xea0f0b538cb3ad46d07d9b83eff95458b691bdfbf09188ccd7b0758bebd8f107,private=struct:[x=integer,private,burn:26559628286452801356420934030260728558957937100654818426187327519091722521190],curve=string,shared:nist%2dp256] forever forever bulk=naclbox&hash=sha256
-b10d3366:tripe-ec-param struct:[curve=string,shared:nist%2dp256] forever forever bulk=naclbox&hash=sha256
-1aac2ad7:tripe-ec:bob-new struct:[p=ec,public:0xebf0cb581592dc6244a47e9d2e6bc79f76ecb9e5f6e34d69f9f0d07eab188351,0xa6ec5ff761242a0eef1565fd7a6604dbab7b4a0552226b60f2359bccd3e80f48,private=struct:[x=integer,private,burn:15276384741843750980963471236080551062792600396841148726840678168354415102951],curve=string,shared:nist%2dp256] forever forever bulk=naclbox&hash=sha256
-ec1faca7:tripe-ec:alice struct:[p=ec,public:0xa886b00e1457196c1fd91f11a94cf4a081169602c5e2b576d4182eca470ec253,0xb0fa9a01d4205c912d97c4b4c8d8c5e0af869bd7cdef2139aff7579ca590b4c2,private=struct:[x=integer,private,burn:27337377592101678962721737273774069706724348359128065055711824790983665511674],curve=string,shared:nist%2dp256] forever forever bulk=naclbox&hash=sha256
-73bad30f:tripe-ec:carol struct:[p=ec,public:0xac7b854c5e38a74a005a8940cfe7e9cac692bfb12316de782167632b38ced9fc,0xc4467936d15ba07f4ca5e6a7bbf2afb526dec70de0f0ad78f74010e0998a66cd,private=struct:[x=integer,private,burn:62821717637637708743367607162182045550925703241285672642684065475493697147942],curve=string,shared:nist%2dp256] forever forever bulk=naclbox&hash=sha256
+6f825e20:tripe-x25519:bob struct:[pub=binary,public:r+C4uNU0b06HsBunjoYEuzrij92jZi81/jPaQWjMAG4=,private=struct:[priv=binary,private,burn:jxcgIQSi6Otuvfl0Xd8JXL3p5mNFyuMKxCm4e1Zu2Us=]] forever forever hash=sha256&cipher=chacha20&bulk=naclbox
+03349b54:tripe-x25519:bob-new struct:[pub=binary,public:T1Xkv+kA2inWUsoF1HMhQV9l7FFUVAuqJaIfSIbo/wY=,private=struct:[priv=binary,private,burn:yYvE82HsJlk3wOSi1gXJL0laeo1f+Af4u+fjIzU7Hoo=]] forever forever hash=sha256&cipher=chacha20&bulk=naclbox
+abff7e38:tripe-x25519-param string,shared:%3cempty%3e forever forever hash=sha256&cipher=chacha20&bulk=naclbox
+fbf10a4e:tripe-x25519:alice struct:[pub=binary,public:n27vXTI/1lyxTlx3iDPAYfuhuRrGTc5/ohJfFsvQRl8=,private=struct:[priv=binary,private,burn:9OsXq+xPsDeAujcy6+tLBTyfXuqBYhrKazWzR/6cH5w=]] forever forever hash=sha256&cipher=chacha20&bulk=naclbox
+4c758f1e:tripe-x25519:carol struct:[pub=binary,public:yi7XVssUkQePU/1ybS6XkwrqvXqWaN04XboBj/r+jmA=,private=struct:[priv=binary,private,burn:++CCD35eVRUPsML4B4rT4n+QiUpBcQbdO5+WF82b/Bk=]] forever forever hash=sha256&cipher=chacha20&bulk=naclbox