From 9b75305d6a77383ddcacea46106aac55513d4a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 28 Sep 2015 13:48:04 +0200 Subject: [PATCH] Fix potential buffer overflow in mpi_read_string() Found by Guido Vranken. Two possible integer overflows (during << 2 or addition in BITS_TO_LIMB()) could result in far too few memory to be allocated, then overflowing the buffer in the subsequent for loop. Both integer overflows happen when slen is close to or greater than SIZE_T_MAX >> 2 (ie 2^30 on a 32 bit system). Note: one could also avoid those overflows by changing BITS_TO_LIMB(s << 2) to CHARS_TO_LIMB(s >> 1) but the solution implemented looks more robust with respect to future code changes. --- ChangeLog | 5 +++++ library/bignum.c | 9 +++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/ChangeLog b/ChangeLog index b496e0213..0f8d4b844 100644 --- a/ChangeLog +++ b/ChangeLog @@ -6,6 +6,11 @@ Security * Fix stack buffer overflow in pkcs12 decryption (used by mbedtls_pk_parse_key(file)() when the password is > 129 bytes. Found by Guido Vranken. Not triggerable remotely. + * Fix potential buffer overflow in mbedtls_mpi_read_string(). + Found by Guido Vranken. Not exploitable remotely in the context of TLS, + but might be in other uses. On 32 bit machines, requires reading a string + of close to or larger than 1GB to exploit; on 64 bit machines, would require + reading a string of close to or larger than 2^62 bytes. = Version 1.2.16 released 2015-09-17 diff --git a/library/bignum.c b/library/bignum.c index bbadd01ce..9544dc991 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -34,6 +34,7 @@ #include "polarssl/bignum.h" #include "polarssl/bn_mul.h" +#include #include /* Implementation that should never be optimized out by the compiler */ @@ -47,9 +48,10 @@ static void polarssl_zeroize( void *v, size_t n ) { /* * Convert between bits/chars and number of limbs + * Divide first in order to avoid potential overflows */ -#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL) -#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL) +#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) +#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) /* * Initialize one MPI @@ -287,6 +289,9 @@ int mpi_read_string( mpi *X, int radix, const char *s ) if( radix == 16 ) { + if( slen > SIZE_T_MAX >> 2 ) + return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); + n = BITS_TO_LIMBS( slen << 2 ); MPI_CHK( mpi_grow( X, n ) );