warp-vpn

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

commit c6b3fd2a78e9cc9e5eee4716e18aaef3ffa19b83
parent b9d8180a2c7cb92d95eb33c5104d53e6a1dda337
Author: sin <sin@2f30.org>
Date:   Thu, 24 Mar 2016 16:53:41 +0000

fix crypto

Diffstat:
Mstun.c | 115++++++++++++++++++++++++++++++++++++++-----------------------------------------
1 file changed, 55 insertions(+), 60 deletions(-)

diff --git a/stun.c b/stun.c @@ -52,6 +52,7 @@ enum { }; EVP_CIPHER_CTX enc, dec; +unsigned char aeskey[32], aesiv[32]; char *argv0; char *host; char *port = "12080"; @@ -110,73 +111,60 @@ logerr(char *msg, ...) } int -aesinit(unsigned char *pw, int pwlen, EVP_CIPHER_CTX *ectx, EVP_CIPHER_CTX *dctx) +padto(int len, int blocksize) +{ + return len + blocksize - (len & (blocksize - 1)); +} + +int +prepkey(unsigned char *pw, int pwlen) { - unsigned char key[32], iv[32]; int ret, nrounds = 5; ret = EVP_BytesToKey(EVP_aes_256_cbc(), EVP_sha1(), - NULL, pw, pwlen, nrounds, key, iv); + NULL, pw, pwlen, nrounds, aeskey, aesiv); if (ret != 32) logerr("wrong key size: %d", ret); - EVP_CIPHER_CTX_init(ectx); - EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, key, iv); - EVP_CIPHER_CTX_init(dctx); - EVP_DecryptInit_ex(dctx, EVP_aes_256_cbc(), NULL, key, iv); return 0; } int -aesenc(EVP_CIPHER_CTX *ectx, unsigned char *ciphertext, - unsigned char *plaintext, int len) +aesinit(EVP_CIPHER_CTX *ectx, EVP_CIPHER_CTX *dctx) { - int clen = len + AES_BLOCK_SIZE, flen = 0; - - EVP_EncryptInit_ex(ectx, NULL, NULL, NULL, NULL); - EVP_EncryptUpdate(ectx, ciphertext, &clen, plaintext, len); - EVP_EncryptFinal_ex(ectx, ciphertext + clen, &flen); - return clen + flen; + EVP_CIPHER_CTX_init(ectx); + EVP_CIPHER_CTX_init(dctx); + EVP_EncryptInit_ex(ectx, EVP_aes_256_cbc(), NULL, aeskey, aesiv); + EVP_DecryptInit_ex(dctx, EVP_aes_256_cbc(), NULL, aeskey, aesiv); + EVP_CIPHER_CTX_set_padding(ectx, 0); + EVP_CIPHER_CTX_set_padding(dctx, 0); + return 0; } -int -aesdec(EVP_CIPHER_CTX *ectx, unsigned char *plaintext, - unsigned char *ciphertext, int len) +void +aesterm(EVP_CIPHER_CTX *ectx, EVP_CIPHER_CTX *dctx) { - int plen = len, flen = 0; - - EVP_DecryptInit_ex(ectx, NULL, NULL, NULL, NULL); - EVP_DecryptUpdate(ectx, plaintext, &plen, ciphertext, len); - EVP_DecryptFinal_ex(ectx, plaintext + plen, &flen); - return plen + flen; + EVP_CIPHER_CTX_cleanup(ectx); + EVP_CIPHER_CTX_cleanup(dctx); } -/* useful for debugging purposes */ -#if defined(NOCRYPTO) -#define aesinit dummyinit -#define aesenc dummyenc -#define aesdec dummydec -#endif - int -dummyinit(unsigned char *pw, int pwlen, EVP_CIPHER_CTX *ectx, EVP_CIPHER_CTX *dctx) +aesenc(EVP_CIPHER_CTX *ectx, unsigned char *ciphertext, + unsigned char *plaintext, int len) { - return 0; -} + int clen = len + AES_BLOCK_SIZE; -int -dummyenc(EVP_CIPHER_CTX *ectx, unsigned char *ciphertext, - unsigned char *plaintext, int len) -{ - memcpy(ciphertext, plaintext, len); - return len; + EVP_EncryptUpdate(ectx, ciphertext, &clen, plaintext, len); + return clen; } int -dummydec(EVP_CIPHER_CTX *ectx, unsigned char *plaintext, - unsigned char *ciphertext, int len) +aesdec(EVP_CIPHER_CTX *dctx, unsigned char *plaintext, + unsigned char *ciphertext, int len) { - memcpy(plaintext, ciphertext, len); - return len; + int plen = len; + + EVP_DecryptUpdate(dctx, plaintext, &plen, ciphertext, len); + return plen; } #if defined(__linux__) @@ -367,12 +355,11 @@ int writenet(int fd, unsigned char *buf, int len) { unsigned char encbuf[MTU + AES_BLOCK_SIZE + HDRLEN]; - int pktlen; - pktlen = aesenc(&enc, &encbuf[HDRLEN], buf, len); - pack16(encbuf, pktlen); - pktlen += HDRLEN; - return writeall(fd, encbuf, pktlen); + aesenc(&enc, &encbuf[HDRLEN], buf, padto(len, AES_BLOCK_SIZE)); + pack16(encbuf, len); + len = padto(len, AES_BLOCK_SIZE) + HDRLEN; + return writeall(fd, encbuf, len); } int @@ -402,20 +389,21 @@ readnet(int fd, unsigned char *buf, int len) unsigned char decbuf[MTU + AES_BLOCK_SIZE]; unsigned char encbuf[MTU + AES_BLOCK_SIZE]; unsigned char hdr[HDRLEN]; - int n, pktlen; + int n, pktlen, paddedlen; n = readall(fd, hdr, sizeof(hdr)); if (n <= 0) return n; pktlen = unpack16(hdr); - if (pktlen < 0 || pktlen > MTU + AES_BLOCK_SIZE) { - logwarn("bogus payload length: %d", pktlen); + paddedlen = padto(pktlen, AES_BLOCK_SIZE); + if (paddedlen < 0 || paddedlen > MTU + AES_BLOCK_SIZE) { + logwarn("bogus payload length: %d", paddedlen); return -1; } - n = readall(fd, encbuf, pktlen); + n = readall(fd, encbuf, paddedlen); if (n <= 0) return n; - pktlen = aesdec(&dec, decbuf, encbuf, pktlen); + aesdec(&dec, decbuf, encbuf, paddedlen); memcpy(buf, decbuf, pktlen); return pktlen; } @@ -567,23 +555,27 @@ serversetup(int devfd) setsockopt(netfd, IPPROTO_TCP, TCP_NODELAY, (int []){1}, sizeof(int)); + aesinit(&enc, &dec); /* challenge client */ ret = challenge(netfd); if (ret < 0) { + aesterm(&enc, &dec); close(netfd); - logwarn("challenge-response failed"); + logwarn("server -> client challenge failed"); continue; } /* respond to client's challenge */ ret = response(netfd); if (ret < 0) { + aesterm(&enc, &dec); close(netfd); - logwarn("challenge-response failed"); + logwarn("server -> client response failed"); continue; } tunnel(netfd, devfd); + aesterm(&enc, &dec); close(netfd); if (debug) logdbg("remote peer disconnected: %s", @@ -624,19 +616,22 @@ clientsetup(int devfd) setsockopt(netfd, IPPROTO_TCP, TCP_NODELAY, (int []){1}, sizeof(int)); + aesinit(&enc, &dec); /* respond to server's challenge */ ret = response(netfd); if (ret < 0) { + aesterm(&enc, &dec); close(netfd); - logwarn("challenge-response failed"); + logwarn("client -> server response failed"); return -1; } /* challenge server */ ret = challenge(netfd); if (ret < 0) { + aesterm(&enc, &dec); close(netfd); - logwarn("challenge-response failed"); + logwarn("client -> server challenge failed"); return -1; } @@ -644,6 +639,7 @@ clientsetup(int devfd) logdbg("connected to %s:%s", host, port); ret = tunnel(netfd, devfd); logwarn("connection to %s:%s dropped", host, port); + aesterm(&enc, &dec); close(netfd); return ret; } @@ -732,8 +728,7 @@ main(int argc, char *argv[]) pw = getenv("STUNPW"); if (!pw) logerr("STUNPW is not set"); - if (aesinit((unsigned char *)pw, strlen(pw), &enc, &dec) < 0) - logerr("couldn't initialize AES cipher"); + prepkey(pw, strlen(pw)); explicit_bzero(pw, strlen(pw)); if (sflag)