From 361b10d1c4e25816c4f9a16708586b3bae9c1673 Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Fri, 30 Aug 2019 10:42:49 +0100 Subject: [PATCH] Fix SSL context deserialization The SSL context maintains a set of 'out pointers' indicating the address at which to write the header fields of the next outgoing record. Some of these addresses have a static offset from the beginning of the record header, while other offsets can vary depending on the active record encryption mechanism: For example, if an explicit IV is in use, there's an offset between the end of the record header and the beginning of the encrypted data to allow the explicit IV to be placed in between; also, if the DTLS Connection ID (CID) feature is in use, the CID is part of the record header, shifting all subsequent information (length, IV, data) to the back. When setting up an SSL context, the out pointers are initialized according to the identity transform + no CID, and it is important to keep them up to date whenever the record encryption mechanism changes, which is done by the helper function ssl_update_out_pointers(). During context deserialization, updating the out pointers according to the deserialized record transform went missing, leaving the out pointers the initial state. When attemping to encrypt a record in this state, this lead to failure if either a CID or an explicit IV was in use. This wasn't caught in the tests by the bad luck that they didn't use CID, _and_ used the default ciphersuite based on ChaChaPoly, which doesn't have an explicit IV. Changing either of this would have made the existing tests fail. This commit fixes the bug by adding a call to ssl_update_out_pointers() to ssl_context_load() implementing context deserialization. Extending test coverage is left for a separate commit. --- library/ssl_tls.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index e06c06d34b..f4bca87d21 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -11950,6 +11950,10 @@ static int ssl_context_load( mbedtls_ssl_context *ssl, ssl->major_ver = MBEDTLS_SSL_MAJOR_VERSION_3; ssl->minor_ver = MBEDTLS_SSL_MINOR_VERSION_3; + /* Adjust pointers for header fields of outgoing records to + * the given transform, accounting for explicit IV and CID. */ + ssl_update_out_pointers( ssl, ssl->transform ); + #if defined(MBEDTLS_SSL_PROTO_DTLS) ssl->in_epoch = 1; #endif