From 5cb4b310571d9ff273e95e99379c95ac387c0ce6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Tue, 25 Nov 2014 17:41:50 +0100 Subject: [PATCH] Fix missing bound check --- ChangeLog | 4 ++++ include/polarssl/ctr_drbg.h | 4 ++++ library/ctr_drbg.c | 8 ++++++++ 3 files changed, 16 insertions(+) diff --git a/ChangeLog b/ChangeLog index 89c87e057..8370738b4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -9,6 +9,10 @@ Features * Add support for Extended Master Secret (draft-ietf-tls-session-hash) * Add support for Encrypt-then-MAC (RFC 7366) +Bugfix + * Stack buffer overflow if ctr_drbg_update() is called with too large + add_len (found by Jean-Philippe Aumasson) (not triggerable remotely). + = PolarSSL 1.3.9 released 2014-10-20 Security * Lowest common hash was selected from signature_algorithms extension in diff --git a/include/polarssl/ctr_drbg.h b/include/polarssl/ctr_drbg.h index bebbfe931..de696dc23 100644 --- a/include/polarssl/ctr_drbg.h +++ b/include/polarssl/ctr_drbg.h @@ -188,6 +188,10 @@ int ctr_drbg_reseed( ctr_drbg_context *ctx, * \param ctx CTR_DRBG context * \param additional Additional data to update state with * \param add_len Length of additional data + * + * \note If add_len is greater than CTR_DRBG_MAX_SEED_INPUT, + * only the first CTR_DRBG_MAX_SEED_INPUT bytes are used, + * the remaining ones are silently discarded. */ void ctr_drbg_update( ctr_drbg_context *ctx, const unsigned char *additional, size_t add_len ); diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c index 96ee4f162..91e061567 100644 --- a/library/ctr_drbg.c +++ b/library/ctr_drbg.c @@ -137,6 +137,9 @@ static int block_cipher_df( unsigned char *output, int i, j; size_t buf_len, use_len; + if( data_len > CTR_DRBG_MAX_SEED_INPUT ) + return( POLARSSL_ERR_CTR_DRBG_INPUT_TOO_BIG ); + memset( buf, 0, CTR_DRBG_MAX_SEED_INPUT + CTR_DRBG_BLOCKSIZE + 16 ); aes_init( &aes_ctx ); @@ -256,6 +259,11 @@ void ctr_drbg_update( ctr_drbg_context *ctx, if( add_len > 0 ) { + /* MAX_INPUT would be more logical here, but we have to match + * block_cipher_df()'s limits since we can't propagate errors */ + if( add_len > CTR_DRBG_MAX_SEED_INPUT ) + add_len = CTR_DRBG_MAX_SEED_INPUT; + block_cipher_df( add_input, additional, add_len ); ctr_drbg_update_internal( ctx, add_input ); }