From 0209f12d27d29f3aedc09b228bd289305851c75d Mon Sep 17 00:00:00 2001 From: Guus Sliepen Date: Sat, 10 Jan 2015 23:00:51 +0100 Subject: [PATCH] Correctly estimate the initial MTU for legacy packets. --- src/cipher.h | 1 + src/net_packet.c | 19 +++++++++++++++++++ src/openssl/cipher.c | 7 +++++++ 3 files changed, 27 insertions(+) diff --git a/src/cipher.h b/src/cipher.h index f194c0dc..3f98c18f 100644 --- a/src/cipher.h +++ b/src/cipher.h @@ -33,6 +33,7 @@ extern cipher_t *cipher_open_by_nid(int) __attribute__ ((__malloc__)); extern cipher_t *cipher_open_blowfish_ofb(void) __attribute__ ((__malloc__)); extern void cipher_close(cipher_t *); extern size_t cipher_keylength(const cipher_t *); +extern size_t cipher_blocksize(const cipher_t *); extern void cipher_get_key(const cipher_t *, void *); extern bool cipher_set_key(cipher_t *, void *, bool) __attribute__ ((__warn_unused_result__)); extern bool cipher_set_key_from_rsa(cipher_t *, void *, size_t, bool) __attribute__ ((__warn_unused_result__)); diff --git a/src/net_packet.c b/src/net_packet.c index 37535c17..8bf399f1 100644 --- a/src/net_packet.c +++ b/src/net_packet.c @@ -929,6 +929,25 @@ static length_t choose_initial_maxmtu(node_t *n) { mtu -= SPTPS_DATAGRAM_OVERHEAD; if((n->options >> 24) >= 4) mtu -= sizeof(node_id_t) + sizeof(node_id_t); + } else { + mtu -= digest_length(n->outdigest); + + /* Now it's tricky. We use CBC mode, so the length of the + encrypted payload must be a multiple of the blocksize. The + sequence number is also part of the encrypted payload, so we + must account for it after correcting for the blocksize. + Furthermore, the padding in the last block must be at least + 1 byte. */ + + length_t blocksize = cipher_blocksize(n->outcipher); + + if(blocksize > 1) { + mtu /= blocksize; + mtu *= blocksize; + mtu--; + } + + mtu -= 4; // seqno } if (mtu < 512) { diff --git a/src/openssl/cipher.c b/src/openssl/cipher.c index 9b39a288..04aee27e 100644 --- a/src/openssl/cipher.c +++ b/src/openssl/cipher.c @@ -79,6 +79,13 @@ size_t cipher_keylength(const cipher_t *cipher) { return cipher->cipher->key_len + cipher->cipher->iv_len; } +size_t cipher_blocksize(const cipher_t *cipher) { + if(!cipher || !cipher->cipher) + return 1; + + return cipher->cipher->block_size; +} + bool cipher_set_key(cipher_t *cipher, void *key, bool encrypt) { bool result;