From e66ca3bbf36332bca6a97f6bca2a5883f5f32387 Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 20 Jun 2018 00:11:45 +0200 Subject: [PATCH] psa_export_key: zero out potential garbage in the output buffer In psa_export_key, ensure that each byte of the output buffer either contains its original value, is zero, or is part of the actual output. Specifically, don't risk having partial output on error, and don't leave extra data at the end of the buffer when exporting an asymmetric key. Test that exporting to a previously zeroed buffer leaves the buffer zeroed outside the actual output if any. --- library/psa_crypto.c | 5 +++++ tests/suites/test_suite_psa_crypto.function | 24 +++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/library/psa_crypto.c b/library/psa_crypto.c index c552b5331..8e7aeefa2 100644 --- a/library/psa_crypto.c +++ b/library/psa_crypto.c @@ -628,17 +628,22 @@ static psa_status_t psa_internal_export_key( psa_key_slot_t key, else ret = mbedtls_pk_write_key_der( &pk, data, data_size ); if( ret < 0 ) + { + memset( data, 0, data_size ); return( mbedtls_to_psa_error( ret ) ); + } /* The mbedtls_pk_xxx functions write to the end of the buffer. * Move the data to the beginning and erase remaining data * at the original location. */ if( 2 * (size_t) ret <= data_size ) { memcpy( data, data + data_size - ret, ret ); + memset( data + data_size - ret, 0, ret ); } else if( (size_t) ret < data_size ) { memmove( data, data + data_size - ret, ret ); + memset( data + ret, 0, data_size - ret ); } *data_length = ret; return( PSA_SUCCESS ); diff --git a/tests/suites/test_suite_psa_crypto.function b/tests/suites/test_suite_psa_crypto.function index c1d0e149a..958637560 100644 --- a/tests/suites/test_suite_psa_crypto.function +++ b/tests/suites/test_suite_psa_crypto.function @@ -7,6 +7,25 @@ #else #define PSA_CRYPTO_TEST_SIZE_T_RANGE( x ) 1 #endif + +/** Test if a buffer is not all-bits zero. + * + * \param buffer Pointer to the beginning of the buffer. + * \param size Size of the buffer in bytes. + * + * \return 0 if the buffer is all-bits-zero. + * \return A nonzero value otherwise. + */ +int mem_is_nonzero( void *buffer, size_t size ) +{ + size_t i; + for( i = 0; i < size; i++ ) + { + if( ( (unsigned char *) buffer )[i] != 0 ) + return( i + 1 ); + } + return( 0 ); +} /* END_HEADER */ /* BEGIN_DEPENDENCIES @@ -106,8 +125,13 @@ void import_export( data_t *data, exported, export_size, &exported_length ); TEST_ASSERT( status == (psa_status_t) expected_export_status ); + TEST_ASSERT( ! mem_is_nonzero( exported + exported_length, + export_size - exported_length ) ); if( status != PSA_SUCCESS ) + { + TEST_ASSERT( exported_length == 0 ); goto destroy; + } if( canonical_input ) {