From 258bab0b1b31f0da623a74f7fa6f4fe9468cbd34 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 | 2 ++ include/polarssl/ctr_drbg.h | 4 ++++ library/ctr_drbg.c | 8 ++++++++ 3 files changed, 14 insertions(+) diff --git a/ChangeLog b/ChangeLog index 7bb1727b7..7845080b1 100644 --- a/ChangeLog +++ b/ChangeLog @@ -18,6 +18,8 @@ Security Bugfix * Fix potential undefined behaviour in Camellia. * Fix memory leaks in PKCS#5 and PKCS#12. + * Stack buffer overflow if ctr_drbg_update() is called with too large + add_len (found by Jean-Philippe Aumasson) (not triggerable remotely). Changes * Blind RSA private operations even when POLARSSL_RSA_NO_CRT is defined. diff --git a/include/polarssl/ctr_drbg.h b/include/polarssl/ctr_drbg.h index d5459d978..a2f1a6140 100644 --- a/include/polarssl/ctr_drbg.h +++ b/include/polarssl/ctr_drbg.h @@ -154,6 +154,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 1b46f451a..980d95486 100644 --- a/library/ctr_drbg.c +++ b/library/ctr_drbg.c @@ -118,6 +118,9 @@ static int block_cipher_df( unsigned char *output, int i, j, 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 ); /* @@ -233,6 +236,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 ); }