commit c068ba6ba9eb642e238f2a88007a5ae04ad9c95b
parent d05cd9b2a746d2f235804c1ac84c79c829d1e9f9
Author: sin <sin@2f30.org>
Date: Tue, 12 Apr 2016 11:32:23 +0100
factor out crypto code
Diffstat:
M | Makefile | | | 4 | ++-- |
A | crypto.c | | | 81 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | stun.c | | | 72 | +++++++++++++----------------------------------------------------------- |
M | 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 *);