#include "ec-keys.h"
#include "dh.h"
#include "rsa.h"
+#include "x25519.h"
#include "rmd160.h"
#include "blowfish-cbc.h"
ec_decinit, dh_decdoit, dh_enccheck, dh_encdestroy
};
+/* --- X25519 --- */
+
+static kem *x25519_encinit(key *k, void *kd) { return (CREATE(kem)); }
+static void x25519_encdestroy(kem *k) { DESTROY(k); }
+
+static const char *x25519_enccheck(kem *k)
+{
+ x25519_pub *kd = k->kd;
+
+ if (kd->pub.sz != X25519_PUBSZ)
+ return ("incorrect X25519 public key length");
+ return (0);
+}
+
+static int x25519_encdoit(kem *k, dstr *d, ghash *h)
+{
+ octet t[X25519_KEYSZ], z[X25519_OUTSZ];
+ x25519_pub *kd = k->kd;
+
+ rand_get(RAND_GLOBAL, t, sizeof(t));
+ dstr_ensure(d, X25519_PUBSZ);
+ x25519((octet *)d->buf, t, x25519_base);
+ x25519(z, t, kd->pub.k);
+ d->len += X25519_PUBSZ;
+ GH_HASH(h, d->buf, X25519_PUBSZ);
+ GH_HASH(h, z, X25519_OUTSZ);
+ return (0);
+}
+
+static const char *x25519_deccheck(kem *k)
+{
+ x25519_priv *kd = k->kd;
+
+ if (kd->priv.sz != X25519_KEYSZ)
+ return ("incorrect X25519 private key length");
+ if (kd->pub.sz != X25519_PUBSZ)
+ return ("incorrect X25519 public key length");
+ return (0);
+}
+
+static int x25519_decdoit(kem *k, dstr *d, ghash *h)
+{
+ octet z[X25519_OUTSZ];
+ x25519_priv *kd = k->kd;
+ int rc = -1;
+
+ if (d->len != X25519_PUBSZ) goto done;
+ x25519(z, kd->priv.k, (const octet *)d->buf);
+ GH_HASH(h, d->buf, X25519_PUBSZ);
+ GH_HASH(h, z, X25519_OUTSZ);
+ rc = 0;
+done:
+ return (rc);
+}
+
+static const kemops x25519_encops = {
+ x25519_pubfetch, sizeof(x25519_pub),
+ x25519_encinit, x25519_encdoit, x25519_enccheck, x25519_encdestroy
+};
+
+static const kemops x25519_decops = {
+ x25519_privfetch, sizeof(x25519_priv),
+ x25519_encinit, x25519_decdoit, x25519_deccheck, x25519_encdestroy
+};
+
/* --- Symmetric --- */
typedef struct symm_ctx {
{ "dh", &dh_encops, &dh_decops },
{ "bindh", &bindh_encops, &bindh_decops },
{ "ec", &ec_encops, &ec_decops },
+ { "x25519", &x25519_encops, &x25519_decops },
{ "symm", &symm_encops, &symm_decops },
{ 0, 0, 0 }
};