diff --git a/ChangeLog b/ChangeLog index 55e4e7ffd..1a85af29a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,8 @@ Security * Fix unsafe bounds check in ssl_parse_client_psk_identity() when adding 64kB to the address of the SSL buffer wraps around. * Tighten should-be-constant-time memcmp against compiler optimizations. + * Ensure that buffers are cleared after use if they contain sensitive data. + Changes were introduced in multiple places in the library. Bugfix * Fix memory leak in ssl_set_hostname() when called multiple times. diff --git a/library/bignum.c b/library/bignum.c index 4829d916b..e4a8dece5 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -1880,6 +1880,8 @@ int mpi_fill_random( mpi *X, size_t size, MPI_CHK( mpi_read_binary( X, buf, size ) ); cleanup: + polarssl_zeroize( buf, sizeof( buf ) ); + return( ret ); } diff --git a/library/ctr_drbg.c b/library/ctr_drbg.c index 7b315e888..f66064ff4 100644 --- a/library/ctr_drbg.c +++ b/library/ctr_drbg.c @@ -402,20 +402,20 @@ int ctr_drbg_write_seed_file( ctr_drbg_context *ctx, const char *path ) goto exit; if( fwrite( buf, 1, CTR_DRBG_MAX_INPUT, f ) != CTR_DRBG_MAX_INPUT ) - { ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR; - goto exit; - } - - ret = 0; + else + ret = 0; exit: + polarssl_zeroize( buf, sizeof( buf ) ); + fclose( f ); return( ret ); } int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path ) { + int ret = 0; FILE *f; size_t n; unsigned char buf[ CTR_DRBG_MAX_INPUT ]; @@ -434,14 +434,16 @@ int ctr_drbg_update_seed_file( ctr_drbg_context *ctx, const char *path ) } if( fread( buf, 1, n, f ) != n ) - { - fclose( f ); - return( POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR ); - } + ret = POLARSSL_ERR_CTR_DRBG_FILE_IO_ERROR; + else + ctr_drbg_update( ctx, buf, n ); fclose( f ); - ctr_drbg_update( ctx, buf, n ); + polarssl_zeroize( buf, sizeof( buf ) ); + + if( ret != 0 ) + return( ret ); return( ctr_drbg_write_seed_file( ctx, path ) ); } diff --git a/library/dhm.c b/library/dhm.c index 48fba2a73..582eec77a 100644 --- a/library/dhm.c +++ b/library/dhm.c @@ -532,7 +532,10 @@ static int load_file( const char *path, unsigned char **buf, size_t *n ) if( fread( *buf, 1, *n, f ) != *n ) { fclose( f ); + + polarssl_zeroize( *buf, *n + 1 ); polarssl_free( *buf ); + return( POLARSSL_ERR_DHM_FILE_IO_ERROR ); } diff --git a/library/entropy.c b/library/entropy.c index c6f44df3b..2cd4ce1e2 100644 --- a/library/entropy.c +++ b/library/entropy.c @@ -166,6 +166,8 @@ static int entropy_update( entropy_context *ctx, unsigned char source_id, sha256_update( &ctx->accumulator, p, use_len ); #endif + polarssl_zeroize( tmp, sizeof( tmp ) ); + return( 0 ); } @@ -194,13 +196,11 @@ int entropy_update_manual( entropy_context *ctx, */ static int entropy_gather_internal( entropy_context *ctx ) { - int ret, i; + int ret = POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED; + int i; unsigned char buf[ENTROPY_MAX_GATHER]; size_t olen; - if( ctx->source_count == 0 ) - return( POLARSSL_ERR_ENTROPY_NO_SOURCES_DEFINED ); - /* * Run through our entropy sources */ @@ -210,7 +210,7 @@ static int entropy_gather_internal( entropy_context *ctx ) if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, buf, ENTROPY_MAX_GATHER, &olen ) ) != 0 ) { - return( ret ); + goto cleanup; } /* @@ -223,7 +223,10 @@ static int entropy_gather_internal( entropy_context *ctx ) } } - return( 0 ); +cleanup: + polarssl_zeroize( buf, sizeof( buf ) ); + + return( ret ); } /* @@ -324,6 +327,8 @@ int entropy_func( void *data, unsigned char *output, size_t len ) ret = 0; exit: + polarssl_zeroize( buf, sizeof( buf ) ); + #if defined(POLARSSL_THREADING_C) if( polarssl_mutex_unlock( &ctx->mutex ) != 0 ) return( POLARSSL_ERR_THREADING_MUTEX_ERROR ); @@ -354,12 +359,15 @@ int entropy_write_seed_file( entropy_context *ctx, const char *path ) ret = 0; exit: + polarssl_zeroize( buf, sizeof( buf ) ); + fclose( f ); return( ret ); } int entropy_update_seed_file( entropy_context *ctx, const char *path ) { + int ret = 0; FILE *f; size_t n; unsigned char buf[ ENTROPY_MAX_SEED_SIZE ]; @@ -375,14 +383,16 @@ int entropy_update_seed_file( entropy_context *ctx, const char *path ) n = ENTROPY_MAX_SEED_SIZE; if( fread( buf, 1, n, f ) != n ) - { - fclose( f ); - return( POLARSSL_ERR_ENTROPY_FILE_IO_ERROR ); - } + ret = POLARSSL_ERR_ENTROPY_FILE_IO_ERROR; + else + ret = entropy_update_manual( ctx, buf, n ); fclose( f ); - entropy_update_manual( ctx, buf, n ); + polarssl_zeroize( buf, sizeof( buf ) ); + + if( ret != 0 ) + return( ret ); return( entropy_write_seed_file( ctx, path ) ); } diff --git a/library/hmac_drbg.c b/library/hmac_drbg.c index c7904d069..eece38997 100644 --- a/library/hmac_drbg.c +++ b/library/hmac_drbg.c @@ -342,11 +342,14 @@ int hmac_drbg_write_seed_file( hmac_drbg_context *ctx, const char *path ) exit: fclose( f ); + polarssl_zeroize( buf, sizeof( buf ) ); + return( ret ); } int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path ) { + int ret = 0; FILE *f; size_t n; unsigned char buf[ POLARSSL_HMAC_DRBG_MAX_INPUT ]; @@ -365,14 +368,16 @@ int hmac_drbg_update_seed_file( hmac_drbg_context *ctx, const char *path ) } if( fread( buf, 1, n, f ) != n ) - { - fclose( f ); - return( POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR ); - } + ret = POLARSSL_ERR_HMAC_DRBG_FILE_IO_ERROR; + else + hmac_drbg_update( ctx, buf, n ); fclose( f ); - hmac_drbg_update( ctx, buf, n ); + polarssl_zeroize( buf, sizeof( buf ) ); + + if( ret != 0 ) + return( ret ); return( hmac_drbg_write_seed_file( ctx, path ) ); } diff --git a/library/md2.c b/library/md2.c index 2ac7eba61..2d6123f12 100644 --- a/library/md2.c +++ b/library/md2.c @@ -217,6 +217,7 @@ void md2( const unsigned char *input, size_t ilen, unsigned char output[16] ) */ int md2_file( const char *path, unsigned char output[16] ) { + int ret = 0; FILE *f; size_t n; md2_context ctx; @@ -231,17 +232,16 @@ int md2_file( const char *path, unsigned char output[16] ) while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) md2_update( &ctx, buf, n ); - md2_finish( &ctx, output ); - md2_free( &ctx ); - if( ferror( f ) != 0 ) - { - fclose( f ); - return( POLARSSL_ERR_MD2_FILE_IO_ERROR ); - } + ret = POLARSSL_ERR_MD2_FILE_IO_ERROR; + else + md2_finish( &ctx, output ); + md2_free( &ctx ); + polarssl_zeroize( buf, sizeof( buf ) ); fclose( f ); - return( 0 ); + + return( ret ); } #endif /* POLARSSL_FS_IO */ diff --git a/library/md4.c b/library/md4.c index 8754d2f52..9c4a9b80a 100644 --- a/library/md4.c +++ b/library/md4.c @@ -313,6 +313,7 @@ void md4( const unsigned char *input, size_t ilen, unsigned char output[16] ) */ int md4_file( const char *path, unsigned char output[16] ) { + int ret = 0; FILE *f; size_t n; md4_context ctx; @@ -327,17 +328,16 @@ int md4_file( const char *path, unsigned char output[16] ) while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) md4_update( &ctx, buf, n ); - md4_finish( &ctx, output ); - md4_free( &ctx ); - if( ferror( f ) != 0 ) - { - fclose( f ); - return( POLARSSL_ERR_MD4_FILE_IO_ERROR ); - } + ret = POLARSSL_ERR_MD4_FILE_IO_ERROR; + else + md4_finish( &ctx, output ); + md4_free( &ctx ); + polarssl_zeroize( buf, sizeof( buf ) ); fclose( f ); - return( 0 ); + + return( ret ); } #endif /* POLARSSL_FS_IO */ diff --git a/library/md5.c b/library/md5.c index 8c7ed1fc3..4a0f25191 100644 --- a/library/md5.c +++ b/library/md5.c @@ -330,6 +330,7 @@ void md5( const unsigned char *input, size_t ilen, unsigned char output[16] ) */ int md5_file( const char *path, unsigned char output[16] ) { + int ret = 0; FILE *f; size_t n; md5_context ctx; @@ -344,17 +345,16 @@ int md5_file( const char *path, unsigned char output[16] ) while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) md5_update( &ctx, buf, n ); - md5_finish( &ctx, output ); - md5_free( &ctx ); - if( ferror( f ) != 0 ) - { - fclose( f ); - return( POLARSSL_ERR_MD5_FILE_IO_ERROR ); - } + ret = POLARSSL_ERR_MD5_FILE_IO_ERROR; + else + md5_finish( &ctx, output ); + md5_free( &ctx ); + polarssl_zeroize( buf, sizeof( buf ) ); fclose( f ); - return( 0 ); + + return( ret ); } #endif /* POLARSSL_FS_IO */ diff --git a/library/pem.c b/library/pem.c index b2c16c292..789a92d51 100644 --- a/library/pem.c +++ b/library/pem.c @@ -333,6 +333,7 @@ int pem_read_buffer( pem_context *ctx, const char *header, const char *footer, if( ( ret = base64_decode( buf, &len, s1, s2 - s1 ) ) != 0 ) { + polarssl_zeroize( buf, len ); polarssl_free( buf ); return( POLARSSL_ERR_PEM_INVALID_DATA + ret ); } @@ -343,6 +344,7 @@ int pem_read_buffer( pem_context *ctx, const char *header, const char *footer, ( defined(POLARSSL_DES_C) || defined(POLARSSL_AES_C) ) if( pwd == NULL ) { + polarssl_zeroize( buf, len ); polarssl_free( buf ); return( POLARSSL_ERR_PEM_PASSWORD_REQUIRED ); } @@ -371,10 +373,12 @@ int pem_read_buffer( pem_context *ctx, const char *header, const char *footer, */ if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) { + polarssl_zeroize( buf, len ); polarssl_free( buf ); return( POLARSSL_ERR_PEM_PASSWORD_MISMATCH ); } #else + polarssl_zeroize( buf, len ); polarssl_free( buf ); return( POLARSSL_ERR_PEM_FEATURE_UNAVAILABLE ); #endif /* POLARSSL_MD5_C && POLARSSL_CIPHER_MODE_CBC && diff --git a/library/pkparse.c b/library/pkparse.c index 6fb0dd50d..0c8fb8343 100644 --- a/library/pkparse.c +++ b/library/pkparse.c @@ -98,7 +98,10 @@ int pk_load_file( const char *path, unsigned char **buf, size_t *n ) if( fread( *buf, 1, *n, f ) != *n ) { fclose( f ); + + polarssl_zeroize( *buf, *n ); polarssl_free( *buf ); + return( POLARSSL_ERR_PK_FILE_IO_ERROR ); } diff --git a/library/ripemd160.c b/library/ripemd160.c index 2c196f42b..7b5d02e2e 100644 --- a/library/ripemd160.c +++ b/library/ripemd160.c @@ -388,6 +388,7 @@ void ripemd160( const unsigned char *input, size_t ilen, */ int ripemd160_file( const char *path, unsigned char output[20] ) { + int ret = 0; FILE *f; size_t n; ripemd160_context ctx; @@ -402,17 +403,16 @@ int ripemd160_file( const char *path, unsigned char output[20] ) while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) ripemd160_update( &ctx, buf, n ); - ripemd160_finish( &ctx, output ); - ripemd160_free( &ctx ); - if( ferror( f ) != 0 ) - { - fclose( f ); - return( POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR ); - } + ret = POLARSSL_ERR_RIPEMD160_FILE_IO_ERROR; + else + ripemd160_finish( &ctx, output ); + ripemd160_free( &ctx ); + polarssl_zeroize( buf, sizeof( buf ) ); fclose( f ); - return( 0 ); + + return( ret ); } #endif /* POLARSSL_FS_IO */ diff --git a/library/sha1.c b/library/sha1.c index 44de8727e..a5a235b64 100644 --- a/library/sha1.c +++ b/library/sha1.c @@ -363,6 +363,7 @@ void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) */ int sha1_file( const char *path, unsigned char output[20] ) { + int ret = 0; FILE *f; size_t n; sha1_context ctx; @@ -377,17 +378,16 @@ int sha1_file( const char *path, unsigned char output[20] ) while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) sha1_update( &ctx, buf, n ); - sha1_finish( &ctx, output ); - sha1_free( &ctx ); - if( ferror( f ) != 0 ) - { - fclose( f ); - return( POLARSSL_ERR_SHA1_FILE_IO_ERROR ); - } + ret = POLARSSL_ERR_SHA1_FILE_IO_ERROR; + else + sha1_finish( &ctx, output ); + sha1_free( &ctx ); + polarssl_zeroize( buf, sizeof( buf ) ); fclose( f ); - return( 0 ); + + return( ret ); } #endif /* POLARSSL_FS_IO */ diff --git a/library/sha256.c b/library/sha256.c index 674fdf25e..caae79f9b 100644 --- a/library/sha256.c +++ b/library/sha256.c @@ -366,6 +366,7 @@ void sha256( const unsigned char *input, size_t ilen, */ int sha256_file( const char *path, unsigned char output[32], int is224 ) { + int ret = 0; FILE *f; size_t n; sha256_context ctx; @@ -380,17 +381,16 @@ int sha256_file( const char *path, unsigned char output[32], int is224 ) while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) sha256_update( &ctx, buf, n ); - sha256_finish( &ctx, output ); - sha256_free( &ctx ); - if( ferror( f ) != 0 ) - { - fclose( f ); - return( POLARSSL_ERR_SHA256_FILE_IO_ERROR ); - } + ret = POLARSSL_ERR_SHA256_FILE_IO_ERROR; + else + sha256_finish( &ctx, output ); + sha256_free( &ctx ); + polarssl_zeroize( buf, sizeof( buf ) ); fclose( f ); - return( 0 ); + + return( ret ); } #endif /* POLARSSL_FS_IO */ diff --git a/library/sha512.c b/library/sha512.c index bd607e0ca..5e51f7f0b 100644 --- a/library/sha512.c +++ b/library/sha512.c @@ -370,6 +370,7 @@ void sha512( const unsigned char *input, size_t ilen, */ int sha512_file( const char *path, unsigned char output[64], int is384 ) { + int ret = 0; FILE *f; size_t n; sha512_context ctx; @@ -384,17 +385,16 @@ int sha512_file( const char *path, unsigned char output[64], int is384 ) while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) sha512_update( &ctx, buf, n ); - sha512_finish( &ctx, output ); - sha512_free( &ctx ); - if( ferror( f ) != 0 ) - { - fclose( f ); - return( POLARSSL_ERR_SHA512_FILE_IO_ERROR ); - } + ret = POLARSSL_ERR_SHA512_FILE_IO_ERROR; + else + sha512_finish( &ctx, output ); + sha512_free( &ctx ); + polarssl_zeroize( buf, sizeof( buf ) ); fclose( f ); - return( 0 ); + + return( ret ); } #endif /* POLARSSL_FS_IO */ diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 54867da97..eaf50be28 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -4140,12 +4140,19 @@ int ssl_set_psk( ssl_context *ssl, const unsigned char *psk, size_t psk_len, return( POLARSSL_ERR_SSL_BAD_INPUT_DATA ); } - if( ssl->psk != NULL || ssl->psk_identity != NULL ) + if( ssl->psk != NULL ) { + polarssl_zeroize( ssl->psk, ssl->psk_len ); + polarssl_free( ssl->psk ); - polarssl_free( ssl->psk_identity ); ssl->psk = NULL; + ssl->psk_len = 0; + } + if( ssl->psk_identity != NULL ) + { + polarssl_free( ssl->psk_identity ); ssl->psk_identity = NULL; + ssl->psk_identity_len = 0; } if( ( ssl->psk = polarssl_malloc( psk_len ) ) == NULL ||