stun

simple point to point tunnel
git clone git://git.2f30.org/stun
Log | Files | Refs | README

commit ce49b50087db948799ab4ac752a917517a704f06
parent 5a92ce669539b031d2b93ca79271b23babc21761
Author: sin <sin@2f30.org>
Date:   Wed, 22 Mar 2017 12:17:40 +0000

Switch to libsodium

Diffstat:
Mauth.c | 4++--
Mconfig.mk | 4++--
Mcrypto.c | 87+++++++++++++++++++++++++------------------------------------------------------
Mnetpkt.c | 23+++++++++++------------
Mstun.8 | 10+---------
Mstun.c | 24+++---------------------
Mstun.h | 23+++++++++++------------
Mtunnel.c | 2+-
8 files changed, 58 insertions(+), 119 deletions(-)

diff --git a/auth.c b/auth.c @@ -12,7 +12,7 @@ int challenge(int netfd) { unsigned char buf[sizeof(uint64_t)]; - size_t outlen; + unsigned long long outlen; struct pollfd pfd[1]; uint64_t n, reply; int ret; @@ -54,7 +54,7 @@ int response(int netfd) { unsigned char buf[sizeof(uint64_t)]; - size_t outlen; + unsigned long long outlen; struct pollfd pfd[1]; uint64_t reply; int ret; diff --git a/config.mk b/config.mk @@ -8,11 +8,11 @@ LIB = /usr/local/lib # BSD CFLAGS = -std=c99 -Wall -I$(INC) -LDLIBS = -L$(LIB) -lcrypto +LDLIBS = -L$(LIB) -lsodium EXTRAOBJ = dev_bsd.o # Linux #CFLAGS = -std=c99 -Wall -I$(INC) #CPPFLAGS = -D_XOPEN_SOURCE=700 -D_GNU_SOURCE -#LDLIBS = -L$(LIB) -lcrypto -lbsd +#LDLIBS = -L$(LIB) -lsodium -lbsd #EXTRAOBJ = dev_linux.o diff --git a/crypto.c b/crypto.c @@ -1,90 +1,57 @@ #include <string.h> -#include <openssl/evp.h> +#include <sodium.h> #include "stun.h" -static EVP_AEAD_CTX ectx, dctx; -static const EVP_AEAD *aead; -static unsigned char key[EVP_MAX_KEY_LENGTH]; - -static struct cipher { - const char *name; - const EVP_AEAD *(*aeadfn)(void); -} ciphers[] = { - { "aes-128-gcm", EVP_aead_aes_128_gcm }, - { "aes-256-gcm", EVP_aead_aes_256_gcm }, - { "chacha20-poly1305", EVP_aead_chacha20_poly1305 }, - { NULL, NULL } -}; +static unsigned char salt[crypto_pwhash_SALTBYTES]; +static unsigned char key[crypto_aead_chacha20poly1305_IETF_KEYBYTES]; void -listciphers(void) +cryptoinit(void) { - struct cipher *cp; - - for (cp = ciphers; cp->name; cp++) - puts(cp->name); -} - -void -setcipher(char *name) -{ - struct cipher *cp; - - for (cp = ciphers; cp->name; cp++) { - if (strcmp(cp->name, name) == 0) { - aead = (*cp->aeadfn)(); - return; - } - } - fatalx("unknown cipher: %s", name); + if (sodium_init() == -1) + fatalx("failed to initialize crypto engine"); } void derivekey(char *pw) { - if (!PKCS5_PBKDF2_HMAC_SHA1(pw, strlen(pw), NULL, 0, NROUNDS, - EVP_AEAD_key_length(aead), key)) - fatalx("PKCS5_PBKDF2_HMAC_SHA1 failed"); -} - -void -cryptoinit(void) -{ - if (!EVP_AEAD_CTX_init(&ectx, aead, key, EVP_AEAD_key_length(aead), - EVP_AEAD_DEFAULT_TAG_LENGTH, NULL) || - !EVP_AEAD_CTX_init(&dctx, aead, key, EVP_AEAD_key_length(aead), - EVP_AEAD_DEFAULT_TAG_LENGTH, NULL)) - fatalx("EVP_AEAD_CTX_init failed"); + memset(salt, 0, sizeof(salt)); /* XXX */ + if (crypto_pwhash(key, sizeof(key), pw, strlen(pw), salt, + crypto_pwhash_OPSLIMIT_INTERACTIVE, + crypto_pwhash_MEMLIMIT_INTERACTIVE, + crypto_pwhash_ALG_DEFAULT) != 0) + fatalx("failed to derive key"); } size_t cryptononcelen(void) { - return EVP_AEAD_nonce_length(aead); + return crypto_aead_chacha20poly1305_IETF_NPUBBYTES; } size_t cryptotaglen(void) { - return EVP_AEAD_max_tag_len(aead); + return crypto_aead_chacha20poly1305_ietf_ABYTES; } -int -cryptoseal(unsigned char *out, size_t *outlen, size_t maxoutlen, - const unsigned char *nonce, size_t noncelen, const unsigned char *in, - size_t inlen, const unsigned char *ad, size_t adlen) +int cryptoseal(unsigned char *c, unsigned long long *clen, + const unsigned char *m, unsigned long long mlen, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *npub) { - return EVP_AEAD_CTX_seal(&ectx, out, outlen, maxoutlen, nonce, noncelen, - in, inlen, ad, adlen); + return crypto_aead_chacha20poly1305_ietf_encrypt(c, clen, m, mlen, + ad, adlen, NULL, + npub, key); } -int -cryptoopen(unsigned char *out, size_t *outlen, size_t maxoutlen, - const unsigned char *nonce, size_t noncelen, const unsigned char *in, - size_t inlen, const unsigned char *ad, size_t adlen) +int cryptoopen(unsigned char *m, unsigned long long *mlen, + const unsigned char *c, unsigned long long clen, + const unsigned char *ad, unsigned long long adlen, + const unsigned char *npub) { - return EVP_AEAD_CTX_open(&dctx, out, outlen, maxoutlen, nonce, noncelen, - in, inlen, ad, adlen); + return crypto_aead_chacha20poly1305_ietf_decrypt(m, mlen, NULL, c, clen, + ad, adlen, npub, key); } diff --git a/netpkt.c b/netpkt.c @@ -42,10 +42,11 @@ static size_t taglen; static int rxstate; int -netwrite(int fd, unsigned char *pt, size_t ptlen, size_t *outlen) +netwrite(int fd, unsigned char *pt, unsigned long long ptlen, + unsigned long long *outlen) { unsigned char *p = wbuf; - size_t buflen = noncelen + HDRLEN + ptlen + taglen; + unsigned long long buflen = noncelen + HDRLEN + ptlen + taglen; int n, total = 0; if (buflen > maxbuflen) { @@ -55,13 +56,11 @@ netwrite(int fd, unsigned char *pt, size_t ptlen, size_t *outlen) arc4random_buf(wbuf, noncelen); pack16(&wbuf[noncelen], ptlen); - if (!cryptoseal(&wbuf[noncelen + HDRLEN], outlen, - ptlen + taglen, wbuf, noncelen, - pt, ptlen, &wbuf[noncelen], HDRLEN)) { + if (cryptoseal(&wbuf[noncelen + HDRLEN], outlen, + pt, ptlen, &wbuf[noncelen], HDRLEN, wbuf) != 0) { logwarnx("cryptoseal failed"); return -1; } - *outlen = ptlen; /* spin until all data is written */ while (buflen > 0) { @@ -80,9 +79,10 @@ netwrite(int fd, unsigned char *pt, size_t ptlen, size_t *outlen) } int -netread(int fd, unsigned char *pt, size_t ptlen, size_t *outlen) +netread(int fd, unsigned char *pt, unsigned long long ptlen, + unsigned long long *outlen) { - size_t buflen = noncelen + HDRLEN + ptlen + taglen; + unsigned long long buflen = noncelen + HDRLEN + ptlen + taglen; int n, ctlen; if (buflen > maxbuflen) { @@ -142,10 +142,9 @@ netread(int fd, unsigned char *pt, size_t ptlen, size_t *outlen) break; case RXDECRYPT: rxstate = RXINITIAL; - if (!cryptoopen(pt, outlen, ptlen, rbuf, noncelen, - &rbuf[noncelen + HDRLEN], - rbuftotal - noncelen - HDRLEN, - &rbuf[noncelen], HDRLEN)) { + if (cryptoopen(pt, outlen, &rbuf[noncelen + HDRLEN], + rbuftotal - noncelen - HDRLEN, + &rbuf[noncelen], HDRLEN, rbuf) != 0) { logwarnx("cryptoopen failed"); return PKTPARTIAL; } diff --git a/stun.8 b/stun.8 @@ -1,4 +1,4 @@ -.Dd April 21, 2016 +.Dd March 22, 2017 .Dt STUN 8 .Os .Sh NAME @@ -12,7 +12,6 @@ .Op Fl b Ar address .Op Fl p Ar port .Op Fl t Ar devtype -.Op Fl c Ar cipher .Op Fl u Ar user .Ar interface .Nm stun @@ -21,7 +20,6 @@ .Fl h Ar host .Op Fl p Ar port .Op Fl t Ar devtype -.Op Fl c Ar cipher .Op Fl u Ar user .Ar interface .Sh DESCRIPTION @@ -59,12 +57,6 @@ Connect to specified Select the tunnel .Ar device type . The two available device types are TUN and TAP. The default is TUN. -.It Fl c Ar cipher -Select the given -.Ar cipher . -If the argument is ? then -.Nm -will list the available ciphers. The default cipher is chacha20-poly1305. .It Fl u Ar user Drop privileges to the specified .Ar user . diff --git a/stun.c b/stun.c @@ -9,15 +9,6 @@ * connected to the server at any time. Routing between clients is handled * by the networking stack on the server side. * - * stun supports multiple AEAD ciphers: - * - * aes-128-gcm - * aes-256-gcm - * chacha20-poly1305 - * - * The default cipher is chacha20-poly1305. The key is derived with - * PBKDF. - * * When a client connects there is a mutual challenge-response phase * as shown below: * @@ -54,7 +45,6 @@ char *argv0; char *bindaddr; char *host; char *port = DEFPORT; -char *cipher = DEFCIPHER; int devtype = TUNDEV; int aftype = AF_INET; int sflag; @@ -62,8 +52,8 @@ int sflag; void usage(void) { - fprintf(stderr, "usage: stun [-46] [-d] -s [-b address] [-p port] [-t devtype] [-c cipher] [-u user] interface\n"); - fprintf(stderr, " stun [-46] [-d] -h host [-p port] [-t devtype] [-c cipher] [-u user] interface\n"); + fprintf(stderr, "usage: stun [-46] [-d] -s [-b address] [-p port] [-t devtype] [-u user] interface\n"); + fprintf(stderr, " stun [-46] [-d] -h host [-p port] [-t devtype] [-u user] interface\n"); exit(1); } @@ -106,13 +96,6 @@ main(int argc, char *argv[]) else usage(); break; - case 'c': - cipher = EARGF(usage()); - if (strcmp(cipher, "?") == 0) { - listciphers(); - return 0; - } - break; case 'u': user = EARGF(usage()); break; @@ -140,9 +123,8 @@ main(int argc, char *argv[]) /* initialize crypto engine */ if (!(pw = getenv("STUNPW"))) fatalx("STUNPW is not set"); - setcipher(cipher); - derivekey(pw); cryptoinit(); + derivekey(pw); memset(pw, 0, strlen(pw)); /* initialize networking engine */ diff --git a/stun.h b/stun.h @@ -10,7 +10,6 @@ #define MAXPAYLOADLEN 1404 #define NROUNDS 100000 #define DEFPORT "12080" -#define DEFCIPHER "chacha20-poly1305" enum { PKTFAILED, @@ -39,18 +38,18 @@ int response(int); int clientconnect(char *, char *); /* crypto.c */ -void listciphers(void); -void setcipher(char *); -void derivekey(char *); void cryptoinit(void); +void derivekey(char *); size_t cryptononcelen(void); size_t cryptotaglen(void); -int cryptoseal(unsigned char *, size_t *, size_t, const unsigned char *, - size_t, const unsigned char *, size_t, const unsigned char *, - size_t); -int cryptoopen(unsigned char *, size_t *, size_t, const unsigned char *, - size_t, const unsigned char *, size_t, const unsigned char *, - size_t); +int cryptoseal(unsigned char *, unsigned long long *, + const unsigned char *, unsigned long long, + const unsigned char *, unsigned long long, + const unsigned char *); +int cryptoopen(unsigned char *, unsigned long long *, + const unsigned char *, unsigned long long, + const unsigned char *, unsigned long long, + const unsigned char *); /* dev_*.c */ int devopen(char *); @@ -67,8 +66,8 @@ void fatal(char *, ...); void fatalx(char *, ...); /* netpkt.c */ -int netwrite(int, unsigned char *, size_t, size_t *); -int netread(int, unsigned char *, size_t, size_t *); +int netwrite(int, unsigned char *, unsigned long long, unsigned long long *); +int netread(int, unsigned char *, unsigned long long, unsigned long long *); void netreset(void); void netinit(void); diff --git a/tunnel.c b/tunnel.c @@ -6,7 +6,7 @@ int tunnel(int netfd, int devfd) { unsigned char buf[MAXPAYLOADLEN]; - size_t outlen; + unsigned long long outlen; struct pollfd pfd[2]; int n;