From ec65415b231bc9a0fd5c72ab16d98153ae426177 Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Wed, 21 Feb 2018 19:19:50 +0100 Subject: contrib: embedded-wg-library: add key generation functions --- contrib/examples/embeddable-wg-library/test.c | 6 +- contrib/examples/embeddable-wg-library/wireguard.c | 198 +++++++++++++++++++++ contrib/examples/embeddable-wg-library/wireguard.h | 3 + 3 files changed, 205 insertions(+), 2 deletions(-) (limited to 'contrib/examples/embeddable-wg-library') diff --git a/contrib/examples/embeddable-wg-library/test.c b/contrib/examples/embeddable-wg-library/test.c index aad24de..8d4aae3 100644 --- a/contrib/examples/embeddable-wg-library/test.c +++ b/contrib/examples/embeddable-wg-library/test.c @@ -50,9 +50,11 @@ int main(int argc, char *argv[]) .first_peer = &new_peer, .last_peer = &new_peer }; + wg_key temp_private_key; - wg_key_from_base64(new_device.private_key, "SFLKy56SOiFoAvQDSCBRrH/nyYonuAQnyr/JTQRPDlU="); - wg_key_from_base64(new_peer.public_key, "aNoLvvCfgbtTf4f2Eb/CWVNvIc5AJt/4C4pKrxMUZlM="); + wg_generate_private_key(temp_private_key); + wg_generate_public_key(new_peer.public_key, temp_private_key); + wg_generate_private_key(new_device.private_key); if (wg_add_device(new_device.name) < 0) { perror("Unable to add device"); diff --git a/contrib/examples/embeddable-wg-library/wireguard.c b/contrib/examples/embeddable-wg-library/wireguard.c index 692d285..a713567 100644 --- a/contrib/examples/embeddable-wg-library/wireguard.c +++ b/contrib/examples/embeddable-wg-library/wireguard.c @@ -19,6 +19,8 @@ #include #include #include +#include +#include #include "wireguard.h" @@ -1575,3 +1577,199 @@ int wg_key_from_base64(wg_key key, const wg_key_b64_string base64) out: return -errno; } + +typedef int64_t fe[16]; + +static __attribute__((noinline)) void memzero_explicit(void *s, size_t count) +{ + memset(s, 0, count); + __asm__ __volatile__("": :"r"(s) :"memory"); +} + +static void carry(fe o) +{ + int i; + int64_t c; + + for (i = 0; i < 16; ++i) { + o[i] += (1LL << 16); + c = o[i] >> 16; + o[(i + 1) * (i < 15)] += c - 1 + 37 * (c - 1) * (i == 15); + o[i] -= c << 16; + } + + memzero_explicit(&c, sizeof(c)); +} + +static void cswap(fe p, fe q, int b) +{ + int i; + int64_t t, c = ~(b - 1); + + for (i = 0; i < 16; ++i) { + t = c & (p[i] ^ q[i]); + p[i] ^= t; + q[i] ^= t; + } + + memzero_explicit(&t, sizeof(t)); + memzero_explicit(&c, sizeof(c)); + memzero_explicit(&b, sizeof(b)); +} + +static void pack(uint8_t *o, const fe n) +{ + int i, j, b; + fe m, t; + + memcpy(t, n, sizeof(t)); + carry(t); + carry(t); + carry(t); + for (j = 0; j < 2; ++j) { + m[0] = t[0] - 0xffed; + for (i = 1; i < 15; ++i) { + m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1); + m[i - 1] &= 0xffff; + } + m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1); + b = (m[15] >> 16) & 1; + m[14] &= 0xffff; + cswap(t, m, 1 - b); + } + for (i = 0; i < 16; ++i) { + o[2 * i] = t[i] & 0xff; + o[2 * i + 1] = t[i] >> 8; + } + + memzero_explicit(m, sizeof(m)); + memzero_explicit(t, sizeof(t)); + memzero_explicit(&b, sizeof(b)); +} + +static void add(fe o, const fe a, const fe b) +{ + int i; + + for (i = 0; i < 16; ++i) + o[i] = a[i] + b[i]; +} + +static void subtract(fe o, const fe a, const fe b) +{ + int i; + + for (i = 0; i < 16; ++i) + o[i] = a[i] - b[i]; +} + +static void multmod(fe o, const fe a, const fe b) +{ + int i, j; + int64_t t[31] = { 0 }; + + for (i = 0; i < 16; ++i) { + for (j = 0; j < 16; ++j) + t[i + j] += a[i] * b[j]; + } + for (i = 0; i < 15; ++i) + t[i] += 38 * t[i + 16]; + memcpy(o, t, sizeof(fe)); + carry(o); + carry(o); + + memzero_explicit(t, sizeof(t)); +} + +static void invert(fe o, const fe i) +{ + fe c; + int a; + + memcpy(c, i, sizeof(c)); + for (a = 253; a >= 0; --a) { + multmod(c, c, c); + if (a != 2 && a != 4) + multmod(c, c, i); + } + memcpy(o, c, sizeof(fe)); + + memzero_explicit(c, sizeof(c)); +} + +static void normalize_key(uint8_t *z) +{ + z[31] = (z[31] & 127) | 64; + z[0] &= 248; +} + +void wg_generate_public_key(wg_key public_key, const wg_key private_key) +{ + int i, r; + uint8_t z[32]; + fe a = { 1 }, b = { 9 }, c = { 0 }, d = { 1 }, e, f; + + memcpy(z, private_key, sizeof(z)); + normalize_key(z); + + for (i = 254; i >= 0; --i) { + r = (z[i >> 3] >> (i & 7)) & 1; + cswap(a, b, r); + cswap(c, d, r); + add(e, a, c); + subtract(a, a, c); + add(c, b, d); + subtract(b, b, d); + multmod(d, e, e); + multmod(f, a, a); + multmod(a, c, a); + multmod(c, b, e); + add(e, a, c); + subtract(a, a, c); + multmod(b, a, a); + subtract(c, d, f); + multmod(a, c, (const fe){ 0xdb41, 1 }); + add(a, a, d); + multmod(c, c, a); + multmod(a, d, f); + multmod(d, b, (const fe){ 9 }); + multmod(b, e, e); + cswap(a, b, r); + cswap(c, d, r); + } + invert(c, c); + multmod(a, a, c); + pack(public_key, a); + + memzero_explicit(&r, sizeof(r)); + memzero_explicit(z, sizeof(z)); + memzero_explicit(a, sizeof(a)); + memzero_explicit(b, sizeof(b)); + memzero_explicit(c, sizeof(c)); + memzero_explicit(d, sizeof(d)); + memzero_explicit(e, sizeof(e)); + memzero_explicit(f, sizeof(f)); +} + +void wg_generate_private_key(wg_key private_key) +{ + wg_generate_preshared_key(private_key); + normalize_key(private_key); +} + +void wg_generate_preshared_key(wg_key preshared_key) +{ + ssize_t ret; + int fd; + +#if defined(__NR_getrandom) + ret = syscall(__NR_getrandom, preshared_key, sizeof(wg_key), 0); + if (ret == sizeof(wg_key)) + return; +#endif + fd = open("/dev/urandom", O_RDONLY); + assert(fd >= 0); + ret = read(fd, preshared_key, sizeof(wg_key)); + close(fd); + assert(ret == sizeof(wg_key)); +} diff --git a/contrib/examples/embeddable-wg-library/wireguard.h b/contrib/examples/embeddable-wg-library/wireguard.h index 350de7d..53d9d5d 100644 --- a/contrib/examples/embeddable-wg-library/wireguard.h +++ b/contrib/examples/embeddable-wg-library/wireguard.h @@ -90,5 +90,8 @@ char *wg_list_device_names(void); /* first\0second\0third\0forth\0last\0\0 */ void wg_key_to_base64(wg_key_b64_string base64, const wg_key key); int wg_key_from_base64(wg_key key, const wg_key_b64_string base64); bool wg_key_is_zero(const wg_key key); +void wg_generate_public_key(wg_key public_key, const wg_key private_key); +void wg_generate_private_key(wg_key private_key); +void wg_generate_preshared_key(wg_key preshared_key); #endif -- cgit v1.2.3-59-g8ed1b