From 5b45524c5114065f26adfdfb04eb664afaf1e433 Mon Sep 17 00:00:00 2001
From: thorkill <thkr@hannover.ccc.de>
Date: Fri, 28 Apr 2017 10:21:13 +0200
Subject: [PATCH] Added sanity check for the keylength to prevent
 heap-buffer-overflow in chacha_keysetup()

---
 src/chacha-poly1305/chacha-poly1305.c | 7 +++++--
 src/chacha-poly1305/chacha-poly1305.h | 2 +-
 src/sptps.c                           | 8 ++++----
 3 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/src/chacha-poly1305/chacha-poly1305.c b/src/chacha-poly1305/chacha-poly1305.c
index bd5cb2c4..bc5fc2be 100644
--- a/src/chacha-poly1305/chacha-poly1305.c
+++ b/src/chacha-poly1305/chacha-poly1305.c
@@ -13,7 +13,7 @@ struct chacha_poly1305_ctx {
 
 chacha_poly1305_ctx_t *chacha_poly1305_init(void)
 {
-	chacha_poly1305_ctx_t *ctx = xzalloc(sizeof *ctx);
+	chacha_poly1305_ctx_t *ctx = (chacha_poly1305_ctx_t *)xzalloc(sizeof *ctx);
 	return ctx;
 }
 
@@ -22,8 +22,11 @@ void chacha_poly1305_exit(chacha_poly1305_ctx_t *ctx)
 	free(ctx);
 }
 
-bool chacha_poly1305_set_key(chacha_poly1305_ctx_t *ctx, const void *key)
+bool chacha_poly1305_set_key(chacha_poly1305_ctx_t *ctx, const void *key, size_t keylen)
 {
+	if (keylen < CHACHA_POLY1305_KEYLEN)
+		return false;
+
 	chacha_keysetup(&ctx->main_ctx, key, 256);
 	chacha_keysetup(&ctx->header_ctx, key + 32, 256);
 	return true;
diff --git a/src/chacha-poly1305/chacha-poly1305.h b/src/chacha-poly1305/chacha-poly1305.h
index af7eaf5e..6f74f0bd 100644
--- a/src/chacha-poly1305/chacha-poly1305.h
+++ b/src/chacha-poly1305/chacha-poly1305.h
@@ -7,7 +7,7 @@ typedef struct chacha_poly1305_ctx chacha_poly1305_ctx_t;
 
 extern chacha_poly1305_ctx_t *chacha_poly1305_init(void);
 extern void chacha_poly1305_exit(chacha_poly1305_ctx_t *);
-extern bool chacha_poly1305_set_key(chacha_poly1305_ctx_t *ctx, const void *key);
+extern bool chacha_poly1305_set_key(chacha_poly1305_ctx_t *ctx, const void *key, size_t);
 
 extern bool chacha_poly1305_encrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *outdata, size_t *outlen);
 extern bool chacha_poly1305_decrypt(chacha_poly1305_ctx_t *ctx, uint64_t seqnr, const void *indata, size_t inlen, void *outdata, size_t *outlen);
diff --git a/src/sptps.c b/src/sptps.c
index 56e24397..dfac4fff 100644
--- a/src/sptps.c
+++ b/src/sptps.c
@@ -248,10 +248,10 @@ static bool receive_ack(sptps_t *s, const char *data, uint16_t len) {
 		return error(s, EIO, "Invalid ACK record length");
 
 	if(s->initiator) {
-		if(!chacha_poly1305_set_key(s->incipher, s->key))
+		if(!chacha_poly1305_set_key(s->incipher, s->key, 2 * CHACHA_POLY1305_KEYLEN))
 			return error(s, EINVAL, "Failed to set counter");
 	} else {
-		if(!chacha_poly1305_set_key(s->incipher, s->key + CHACHA_POLY1305_KEYLEN))
+		if(!chacha_poly1305_set_key(s->incipher, s->key + CHACHA_POLY1305_KEYLEN, 2 * CHACHA_POLY1305_KEYLEN))
 			return error(s, EINVAL, "Failed to set counter");
 	}
 
@@ -334,10 +334,10 @@ static bool receive_sig(sptps_t *s, const char *data, uint16_t len) {
 
 	// TODO: only set new keys after ACK has been set/received
 	if(s->initiator) {
-		if(!chacha_poly1305_set_key(s->outcipher, s->key + CHACHA_POLY1305_KEYLEN))
+		if(!chacha_poly1305_set_key(s->outcipher, s->key + CHACHA_POLY1305_KEYLEN, 2 * CHACHA_POLY1305_KEYLEN))
 			return error(s, EINVAL, "Failed to set key");
 	} else {
-		if(!chacha_poly1305_set_key(s->outcipher, s->key))
+		if(!chacha_poly1305_set_key(s->outcipher, s->key, 2 * CHACHA_POLY1305_KEYLEN))
 			return error(s, EINVAL, "Failed to set key");
 	}