warp-vpn

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

commit c068ba6ba9eb642e238f2a88007a5ae04ad9c95b
parent d05cd9b2a746d2f235804c1ac84c79c829d1e9f9
Author: sin <sin@2f30.org>
Date:   Tue Apr 12 11:32:23 +0100

factor out crypto code

Diffstat:
Makefile | 4++--
crypto.c | 81+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
stun.c | 72+++++++++++++-----------------------------------------------------------
stun.h | 12++++++++++++
4 files changed, 108 insertions(+), 61 deletions(-)
diff --git a/Makefile b/Makefile @@ -1,9 +1,9 @@ include config.mk DISTFILES = Makefile README WHATSNEW UNLICENSE arg.h \ - config.mk dev_bsd.c dev_linux.c log.c stun.8 stun.c \ + config.mk crypto.c dev_bsd.c dev_linux.c log.c stun.8 stun.c \ stun.h util.c -OBJ = $(EXTRAOBJ) log.o stun.o util.o +OBJ = $(EXTRAOBJ) crypto.o log.o stun.o util.o BIN = stun all: $(BIN) diff --git a/crypto.c b/crypto.c @@ -0,0 +1,81 @@ +#include <string.h> + +#include <openssl/evp.h> + +#include "stun.h" + +static EVP_AEAD_CTX ectx, dctx; +static const EVP_AEAD *aead; +static unsigned char key[EVP_MAX_KEY_LENGTH]; + +static void +findcipher(const char *name) +{ + struct { + const char *name; + const EVP_AEAD *(*aeadfn)(void); + } *cp, ciphers[] = { + { "aes-128-gcm", EVP_aead_aes_128_gcm }, + { "aes-256-gcm", EVP_aead_aes_256_gcm }, + { "chacha20-poly1305", EVP_aead_chacha20_poly1305 }, + { "chacha20-poly1305-ietf", EVP_aead_chacha20_poly1305_ietf }, + { NULL, NULL } + }; + + for (cp = ciphers; cp->name; cp++) { + if (strcmp(cp->name, name) == 0) { + aead = (*cp->aeadfn)(); + return; + } + } + logerr("unknown cipher: %s", name); +} + +void +cryptoinit(char *pw) +{ + size_t keylen; + + findcipher(cipher); + keylen = EVP_AEAD_key_length(aead); + if (!PKCS5_PBKDF2_HMAC_SHA1(pw, strlen(pw), NULL, 0, NROUNDS, + keylen, key)) + logerr("PKCS5_PBKDF2_HMAC_SHA1 failed"); + + if (!EVP_AEAD_CTX_init(&ectx, aead, key, keylen, + EVP_AEAD_DEFAULT_TAG_LENGTH, NULL)) + logerr("EVP_AEAD_CTX_init failed"); + if (!EVP_AEAD_CTX_init(&dctx, aead, key, keylen, + EVP_AEAD_DEFAULT_TAG_LENGTH, NULL)) + logerr("EVP_AEAD_CTX_init failed"); +} + +size_t +cryptononcelen(void) +{ + return EVP_AEAD_nonce_length(aead); +} + +size_t +cryptotaglen(void) +{ + return EVP_AEAD_max_tag_len(aead); +} + +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) +{ + return EVP_AEAD_CTX_seal(&ectx, out, outlen, maxoutlen, nonce, noncelen, + in, inlen, ad, adlen); +} + +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) +{ + return EVP_AEAD_CTX_open(&dctx, out, outlen, maxoutlen, nonce, noncelen, + in, inlen, ad, adlen); +} diff --git a/stun.c b/stun.c @@ -62,16 +62,12 @@ #include <time.h> #include <unistd.h> -#include <openssl/evp.h> #if defined(__linux__) #include <bsd/stdlib.h> #endif #include "stun.h" -EVP_AEAD_CTX ectx, dctx; -const EVP_AEAD *aead; -unsigned char key[EVP_MAX_KEY_LENGTH]; char *argv0; char *bindaddr; char *host; @@ -86,8 +82,8 @@ int writenet(int fd, unsigned char *pt, int ptlen) { unsigned char *pkt; - size_t noncelen = EVP_AEAD_nonce_length(aead); - size_t taglen = EVP_AEAD_max_tag_len(aead); + size_t noncelen = cryptononcelen(); + size_t taglen = cryptotaglen(); size_t pktlen = noncelen + HDRLEN + ptlen + taglen; size_t outlen; int n; @@ -97,11 +93,11 @@ writenet(int fd, unsigned char *pt, int ptlen) arc4random_buf(pkt, noncelen); pack16(&pkt[noncelen], ptlen); - if (!EVP_AEAD_CTX_seal(&ectx, &pkt[noncelen + HDRLEN], &outlen, - ptlen + taglen, pkt, noncelen, - pt, ptlen, &pkt[noncelen], HDRLEN)) { + if (!cryptoseal(&pkt[noncelen + HDRLEN], &outlen, + ptlen + taglen, pkt, noncelen, + pt, ptlen, &pkt[noncelen], HDRLEN)) { free(pkt); - logwarn("EVP_AEAD_CTX_seal failed"); + logwarn("cryptoseal failed"); return -1; } @@ -120,8 +116,8 @@ int readnet(int fd, unsigned char *pt, int ptlen) { unsigned char *pkt; - size_t noncelen = EVP_AEAD_nonce_length(aead); - size_t taglen = EVP_AEAD_max_tag_len(aead); + size_t noncelen = cryptononcelen(); + size_t taglen = cryptotaglen(); size_t pktlen = noncelen + HDRLEN + ptlen + taglen; size_t outlen; int n, ctlen; @@ -139,11 +135,11 @@ readnet(int fd, unsigned char *pt, int ptlen) if ((n = readall(fd, &pkt[noncelen + HDRLEN], ctlen + taglen)) <= 0) goto err; - if (!EVP_AEAD_CTX_open(&dctx, pt, &outlen, ptlen, pkt, noncelen, - &pkt[noncelen + HDRLEN], ctlen + taglen, - &pkt[noncelen], HDRLEN)) { + if (!cryptoopen(pt, &outlen, ptlen, pkt, noncelen, + &pkt[noncelen + HDRLEN], ctlen + taglen, + &pkt[noncelen], HDRLEN)) { free(pkt); - logwarn("EVP_AEAD_CTX_open failed"); + logwarn("cryptoopen failed"); return BADPKT; } @@ -376,48 +372,6 @@ err: } void -mapaead(const EVP_AEAD **aead, const char *name) -{ - struct { - const char *name; - const EVP_AEAD *(*aeadfn)(void); - } *cp, ciphers[] = { - { "aes-128-gcm", EVP_aead_aes_128_gcm }, - { "aes-256-gcm", EVP_aead_aes_256_gcm }, - { "chacha20-poly1305", EVP_aead_chacha20_poly1305 }, - { "chacha20-poly1305-ietf", EVP_aead_chacha20_poly1305_ietf }, - { NULL, NULL } - }; - - for (cp = ciphers; cp->name; cp++) { - if (strcmp(cp->name, name) == 0) { - *aead = (*cp->aeadfn)(); - return; - } - } - logerr("unknown cipher: %s", name); -} - -void -aeadinit(char *pw) -{ - size_t keylen; - - mapaead(&aead, cipher); - keylen = EVP_AEAD_key_length(aead); - if (!PKCS5_PBKDF2_HMAC_SHA1(pw, strlen(pw), NULL, 0, NROUNDS, - keylen, key)) - logerr("PKCS5_PBKDF2_HMAC_SHA1 failed"); - - if (!EVP_AEAD_CTX_init(&ectx, aead, key, keylen, - EVP_AEAD_DEFAULT_TAG_LENGTH, NULL)) - logerr("EVP_AEAD_CTX_init failed"); - if (!EVP_AEAD_CTX_init(&dctx, aead, key, keylen, - EVP_AEAD_DEFAULT_TAG_LENGTH, NULL)) - logerr("EVP_AEAD_CTX_init failed"); -} - -void usage(void) { fprintf(stderr, "usage: stun [-df] -s [-b address] [-p port] [-t devtype] [-c cipher] interface\n"); @@ -484,7 +438,7 @@ main(int argc, char *argv[]) if (!(pw = getenv("STUNPW"))) logerr("STUNPW is not set"); - aeadinit(pw); + cryptoinit(pw); bzero(pw, strlen(pw)); if (sflag) diff --git a/stun.h b/stun.h @@ -18,6 +18,18 @@ enum { extern int devtype; extern int debug; extern int foreground; +extern char *cipher; + +/* crypto.c */ +void cryptoinit(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); /* dev_*.c */ int opendev(char *);