From: Guus Sliepen Date: Sat, 29 Oct 2016 17:51:35 +0000 (+0200) Subject: Enforce maximum amount of bytes sent/received on meta-connections. X-Git-Tag: release-1.0.30~5 X-Git-Url: https://git.tinc-vpn.org/git/browse?a=commitdiff_plain;h=42ed8fd4cf3b3e527a38c03d713739fcdc6bf520;p=tinc Enforce maximum amount of bytes sent/received on meta-connections. This is sqrt(2^{block_length_in_bits}). --- diff --git a/src/connection.c b/src/connection.c index fd7ae843..8966d65d 100644 --- a/src/connection.c +++ b/src/connection.c @@ -91,6 +91,8 @@ void free_connection_partially(connection_t *c) { c->outbufstart = 0; c->last_ping_time = 0; c->last_flushed_time = 0; + c->inbudget = 0; + c->outbudget = 0; if(c->inctx) { EVP_CIPHER_CTX_cleanup(c->inctx); diff --git a/src/connection.h b/src/connection.h index d3e9224d..0922fbea 100644 --- a/src/connection.h +++ b/src/connection.h @@ -71,6 +71,8 @@ typedef struct connection_t { const EVP_CIPHER *outcipher; /* Cipher we will use to send data to him */ EVP_CIPHER_CTX *inctx; /* Context of encrypted meta data that will come from him to us */ EVP_CIPHER_CTX *outctx; /* Context of encrypted meta data that will be sent from us to him */ + uint64_t inbudget; /* Encrypted bytes send budget */ + uint64_t outbudget; /* Encrypted bytes receive budget */ char *inkey; /* His symmetric meta key + iv */ char *outkey; /* Our symmetric meta key + iv */ int inkeylength; /* Length of his key + iv */ diff --git a/src/meta.c b/src/meta.c index 06ab96e4..63f565fe 100644 --- a/src/meta.c +++ b/src/meta.c @@ -62,6 +62,14 @@ bool send_meta(connection_t *c, const char *buffer, int length) { /* Add our data to buffer */ if(c->status.encryptout) { + /* Check encryption limits */ + if(length > c->outbudget) { + ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for encryption to %s (%s)", c->name, c->hostname); + return false; + } else { + c->outbudget -= length; + } + result = EVP_EncryptUpdate(c->outctx, (unsigned char *)c->outbuf + c->outbufstart + c->outbuflen, &outlen, (unsigned char *)buffer, length); if(!result || outlen < length) { @@ -175,6 +183,14 @@ bool receive_meta(connection_t *c) { /* Decrypt */ if(c->status.decryptin && !decrypted) { + /* Check decryption limits */ + if(lenin > c->inbudget) { + ifdebug(META) logger(LOG_ERR, "Byte limit exceeded for decryption from %s (%s)", c->name, c->hostname); + return false; + } else { + c->inbudget -= lenin; + } + result = EVP_DecryptUpdate(c->inctx, (unsigned char *)inbuf, &lenout, (unsigned char *)c->buffer + oldlen, lenin); if(!result || lenout != lenin) { logger(LOG_ERR, "Error while decrypting metadata from %s (%s): %s", diff --git a/src/protocol_auth.c b/src/protocol_auth.c index 46b38eb8..ddecbc62 100644 --- a/src/protocol_auth.c +++ b/src/protocol_auth.c @@ -195,6 +195,7 @@ bool send_metakey(connection_t *c) { return false; } + c->outbudget = (uint64_t)4 << EVP_CIPHER_key_length(c->outcipher); c->status.encryptout = true; } @@ -273,6 +274,7 @@ bool metakey_h(connection_t *c) { return false; } + c->inbudget = (uint64_t)4 << EVP_CIPHER_key_length(c->incipher); c->status.decryptin = true; } else { c->incipher = NULL;