commit c6b3fd2a78e9cc9e5eee4716e18aaef3ffa19b83
parent b9d8180a2c7cb92d95eb33c5104d53e6a1dda337
Author: sin <sin@2f30.org>
Date: Thu, 24 Mar 2016 16:53:41 +0000
fix crypto
Diffstat:
M | stun.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)