warp-vpn

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

commit a277455f7772361c9a3f4a68c33fe539f7435267
parent fdcdd2572d4476996b65742a8cce502a321bea0c
Author: sin <sin@2f30.org>
Date:   Wed, 30 Mar 2016 09:12:36 +0100

Switch to aes-256-gcm

Diffstat:
Mstun.c | 64++++++++++++++++++++++++++++++++++++++++++++++++----------------
1 file changed, 48 insertions(+), 16 deletions(-)

diff --git a/stun.c b/stun.c @@ -22,7 +22,7 @@ * The sender verifies that the correct response was received. * * All communication is encrypted using a pre-shared symmetric key, currently - * using aes-256-cbc hashed with sha512. + * using aes-256-gcm hashed with sha512. * * All tunneled traffic is encapsulated inside the TCP payload. * The packet format is shown below: @@ -80,9 +80,10 @@ #define RECONNECTTIMEO 60 /* in seconds */ #define HDRLEN 2 #define IVLEN 16 +#define TAGLEN 16 #define PKTLENMASK 0xfff #define BADPKT 0x8000 -#define MTU 1424 +#define MTU 1400 enum { TUNDEV, @@ -167,7 +168,7 @@ prepkey(unsigned char *pw, int pwlen) { int ret, nrounds = 5; - ret = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha512(), + ret = EVP_BytesToKey(EVP_aes_256_gcm(), EVP_sha512(), NULL, pw, pwlen, nrounds, aeskey, NULL); if (ret != 32) logerr("wrong key size %d", ret); @@ -184,31 +185,56 @@ aesinit(EVP_CIPHER_CTX *ectx, EVP_CIPHER_CTX *dctx) int aesenc(EVP_CIPHER_CTX *ctx, unsigned char *ct, unsigned char *pt, int plen, - unsigned char *key, unsigned char *iv) + unsigned char *key, unsigned char *iv, unsigned char *tag, int taglen) { int clen, flen; - if (EVP_EncryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv) != 1) + if (EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) != 1) logerr("EVP_EncryptInit_ex failed"); + + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, IVLEN, NULL) != 1) + logerr("EVP_CTRL_GCM_SET_IVLEN failed"); + + if (EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv) != 1) + logerr("EVP_EncryptInit_ex failed"); + if (EVP_EncryptUpdate(ctx, ct, &clen, pt, plen) != 1) logerr("EVP_EncryptUpdate failed"); + if (EVP_EncryptFinal_ex(ctx, ct + clen, &flen) != 1) logerr("EVP_EncryptFinal_ex failed"); + + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, TAGLEN, tag) != 1) + logerr("EVP_CTRL_GCM_GET_TAG failed"); + return clen + flen; } int aesdec(EVP_CIPHER_CTX *ctx, unsigned char *pt, unsigned char *ct, int clen, - unsigned char *key, unsigned char *iv) + unsigned char *key, unsigned char *iv, unsigned char *tag, int taglen) { int plen, flen; - if (EVP_DecryptInit_ex(ctx, EVP_aes_256_cbc(), NULL, key, iv) != 1) + if (EVP_DecryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL) != 1) + logerr("EVP_DecryptInit_ex failed"); + + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_IVLEN, IVLEN, NULL) != 1) + logerr("EVP_CTRL_GCM_SET_IVLEN failed"); + + if (EVP_DecryptInit_ex(ctx, NULL, NULL, key, iv) != 1) logerr("EVP_DecryptInit_ex failed"); + if (EVP_DecryptUpdate(ctx, pt, &plen, ct, clen) != 1) logerr("EVP_DecryptUpdate failed"); + + if (EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_SET_TAG, TAGLEN, tag) != 1) + logerr("EVP_CTRL_GCM_SET_TAG failed"); + + /* if this fails, someone has tampered with the packet in transit */ if (EVP_DecryptFinal_ex(ctx, pt + plen, &flen) != 1) - logerr("EVP_DecryptFinal_ex failed"); + return -1; + return plen + flen; } @@ -429,17 +455,17 @@ int writenet(int fd, unsigned char *pt, int len) { unsigned char payload[MTU + AES_BLOCK_SIZE]; - unsigned char hdr[HDRLEN]; - unsigned char iv[IVLEN]; - unsigned char pkt[sizeof(hdr) + sizeof(payload) + sizeof(iv)]; + unsigned char hdr[HDRLEN], iv[IVLEN], tag[TAGLEN]; + unsigned char pkt[sizeof(hdr) + sizeof(payload) + sizeof(iv) + sizeof(tag)]; arc4random_buf(iv, IVLEN); - len = aesenc(&ectx, payload, pt, len, aeskey, iv); + len = aesenc(&ectx, payload, pt, len, aeskey, iv, tag, TAGLEN); pack16(hdr, len); memcpy(pkt, hdr, HDRLEN); memcpy(&pkt[HDRLEN], iv, IVLEN); memcpy(&pkt[HDRLEN + IVLEN], payload, len); - len += IVLEN + HDRLEN; + memcpy(&pkt[HDRLEN + IVLEN + len], tag, TAGLEN); + len += IVLEN + HDRLEN + TAGLEN; return writeall(fd, pkt, len); } @@ -447,8 +473,7 @@ int readnet(int fd, unsigned char *pt, int len) { unsigned char payload[MTU + AES_BLOCK_SIZE]; - unsigned char hdr[HDRLEN]; - unsigned char iv[IVLEN]; + unsigned char hdr[HDRLEN], iv[IVLEN], tag[TAGLEN]; int n, pktlen; /* read packet length */ @@ -484,7 +509,14 @@ readnet(int fd, unsigned char *pt, int len) if (n <= 0) return n; - pktlen = aesdec(&dctx, pt, payload, pktlen, aeskey, iv); + /* read tag */ + n = readall(fd, tag, TAGLEN); + if (n <= 0) + return n; + + pktlen = aesdec(&dctx, pt, payload, pktlen, aeskey, iv, tag, TAGLEN); + if (pktlen < 0) + return BADPKT; return pktlen; }