diff --git a/ChangeLog b/ChangeLog index d58409089..cb0ba22e4 100644 --- a/ChangeLog +++ b/ChangeLog @@ -15,6 +15,9 @@ Security on crafted PEM input data. Found an fix provided by Guid Vranken. Not triggerable remotely in TLS. Triggerable remotely if you accept PEM data from an untrusted source. + * Fix possible heap buffer overflow in base64_encode() when the input + buffer is 512MB or larger on 32-bit platforms. + Found by Guido Vranken. Not trigerrable remotely in TLS. = Version 1.2.16 released 2015-09-17 diff --git a/include/polarssl/base64.h b/include/polarssl/base64.h index db95cb1de..8b772dfdd 100644 --- a/include/polarssl/base64.h +++ b/include/polarssl/base64.h @@ -25,6 +25,7 @@ #define POLARSSL_BASE64_H #include +#include #define POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL -0x002A /**< Output buffer too small. */ #define POLARSSL_ERR_BASE64_INVALID_CHARACTER -0x002C /**< Invalid character in input. */ @@ -44,6 +45,8 @@ extern "C" { * \return 0 if successful, or POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL. * *dlen is always updated to reflect the amount * of data that has (or would have) been written. + * If that length cannot be represented, then no data is + * written to the buffer and *dlen is set to SIZE_T_MAX. * * \note Call this function with *dlen = 0 to obtain the * required buffer size in *dlen diff --git a/library/base64.c b/library/base64.c index dba4c231c..c492cc0c7 100644 --- a/library/base64.c +++ b/library/base64.c @@ -77,15 +77,16 @@ int base64_encode( unsigned char *dst, size_t *dlen, return( 0 ); } - n = (slen << 3) / 6; + n = slen / 3 + ( slen % 3 != 0 ); - switch( (slen << 3) - (n * 6) ) + if( n > ( SIZE_T_MAX - 1 ) / 4 ) { - case 2: n += 3; break; - case 4: n += 2; break; - default: break; + *dlen = SIZE_T_MAX; + return( POLARSSL_ERR_BASE64_BUFFER_TOO_SMALL ); } + n *= 4; + if( *dlen < n + 1 ) { *dlen = n + 1;