diff --git a/features/mbedtls/targets/TARGET_STM/md5_alt.c b/features/mbedtls/targets/TARGET_STM/md5_alt.c index 1d3918e957..e6fd97dc14 100644 --- a/features/mbedtls/targets/TARGET_STM/md5_alt.c +++ b/features/mbedtls/targets/TARGET_STM/md5_alt.c @@ -17,7 +17,7 @@ * limitations under the License. * */ - +#if defined(MBEDTLS_MD5_C) #include "mbedtls/md5.h" #if defined(MBEDTLS_MD5_ALT) @@ -28,6 +28,28 @@ static void mbedtls_zeroize( void *v, size_t n ) { volatile unsigned char *p = v; while( n-- ) *p++ = 0; } +static void st_md5_restore_hw_context(mbedtls_md5_context *ctx) +{ + uint32_t i; + /* allow multi-instance of HASH use: save context for HASH HW module CR */ + HASH->STR = ctx->ctx_save_str; + HASH->CR = (ctx->ctx_save_cr | HASH_CR_INIT); + for (i=0;i<38;i++) { + HASH->CSR[i] = ctx->ctx_save_csr[i]; + } +} + +static void st_md5_save_hw_context(mbedtls_md5_context *ctx) +{ + uint32_t i; + /* allow multi-instance of HASH use: restore context for HASH HW module CR */ + ctx->ctx_save_cr = HASH->CR; + ctx->ctx_save_str = HASH->STR; + for (i=0;i<38;i++) { + ctx->ctx_save_csr[i] = HASH->CSR[i]; + } +} + void mbedtls_md5_init( mbedtls_md5_context *ctx ) { mbedtls_zeroize( ctx, sizeof( mbedtls_md5_context ) ); @@ -41,13 +63,6 @@ void mbedtls_md5_free( mbedtls_md5_context *ctx ) { if( ctx == NULL ) return; - - /* Force the HASH Periheral Clock Reset */ - __HAL_RCC_HASH_FORCE_RESET(); - - /* Release the HASH Periheral Clock Reset */ - __HAL_RCC_HASH_RELEASE_RESET(); - mbedtls_zeroize( ctx, sizeof( mbedtls_md5_context ) ); } @@ -60,65 +75,84 @@ void mbedtls_md5_clone( mbedtls_md5_context *dst, void mbedtls_md5_starts( mbedtls_md5_context *ctx ) { /* HASH IP initialization */ - HAL_HASH_DeInit(&ctx->hhash_md5); + if (HAL_HASH_DeInit(&ctx->hhash_md5) != 0) { + // error found to be returned + return; + } /* HASH Configuration */ ctx->hhash_md5.Init.DataType = HASH_DATATYPE_8B; - if (HAL_HASH_Init(&ctx->hhash_md5) == HAL_ERROR) { + if (HAL_HASH_Init(&ctx->hhash_md5) != 0) { // return error code return; } + st_md5_save_hw_context(ctx); } -void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[MBEDTLS_MD5_BLOCK_SIZE] ) +void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[ST_MD5_BLOCK_SIZE] ) { - HAL_HASH_MD5_Accumulate(&ctx->hhash_md5, (uint8_t *)data, MBEDTLS_MD5_BLOCK_SIZE); + st_md5_restore_hw_context(ctx); + if (HAL_HASH_MD5_Accumulate(&ctx->hhash_md5, (uint8_t *)data, ST_MD5_BLOCK_SIZE) != 0) { + return; // Return error code here + } + st_md5_save_hw_context(ctx); } void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen ) { size_t currentlen = ilen; - // store mechanism to handle MBEDTLS_MD5_BLOCK_SIZE bytes per MBEDTLS_MD5_BLOCK_SIZE bytes + st_md5_restore_hw_context(ctx); + + // store mechanism to accumulate ST_MD5_BLOCK_SIZE bytes (512 bits) in the HW if (currentlen == 0){ // only change HW status is size if 0 - if(ctx->hhash_md5.Phase == HAL_HASH_PHASE_READY) - { + if(ctx->hhash_md5.Phase == HAL_HASH_PHASE_READY) { /* Select the MD5 mode and reset the HASH processor core, so that the HASH will be ready to compute the message digest of a new message */ HASH->CR |= HASH_ALGOSELECTION_MD5 | HASH_CR_INIT; } ctx->hhash_md5.Phase = HAL_HASH_PHASE_PROCESS; - } else if (currentlen < (MBEDTLS_MD5_BLOCK_SIZE-ctx->sbuf_len)) { + } else if (currentlen < (ST_MD5_BLOCK_SIZE - ctx->sbuf_len)) { // only buffurize memcpy(ctx->sbuf+ctx->sbuf_len, input, currentlen); ctx->sbuf_len += currentlen; } else { // fill buffer and process it - memcpy(ctx->sbuf + ctx->sbuf_len, input, (MBEDTLS_MD5_BLOCK_SIZE-ctx->sbuf_len)); - currentlen -= (MBEDTLS_MD5_BLOCK_SIZE-ctx->sbuf_len); + memcpy(ctx->sbuf + ctx->sbuf_len, input, (ST_MD5_BLOCK_SIZE - ctx->sbuf_len)); + currentlen -= (ST_MD5_BLOCK_SIZE - ctx->sbuf_len); mbedtls_md5_process(ctx, ctx->sbuf); - // now process every input as long as it is %4 bytes - size_t iter = currentlen / 4; - HAL_HASH_MD5_Accumulate(&ctx->hhash_md5, (uint8_t *)(input+MBEDTLS_MD5_BLOCK_SIZE-ctx->sbuf_len), (iter*4)); - // sbuf is now fully accumulated, now copy 1 / 2 or 3 remaining bytes - ctx->sbuf_len = currentlen % 4; + // Process every input as long as it is %64 bytes, ie 512 bits + size_t iter = currentlen / ST_MD5_BLOCK_SIZE; + if (iter !=0) { + if (HAL_HASH_MD5_Accumulate(&ctx->hhash_md5, (uint8_t *)(input + ST_MD5_BLOCK_SIZE - ctx->sbuf_len), (iter * ST_MD5_BLOCK_SIZE)) != 0) { + return; // Return error code here + } + } + // sbuf is completely accumulated, now copy up to 63 remaining bytes + ctx->sbuf_len = currentlen % ST_MD5_BLOCK_SIZE; if (ctx->sbuf_len !=0) { - memcpy(ctx->sbuf, input+iter, ctx->sbuf_len); + memcpy(ctx->sbuf, input + ilen - ctx->sbuf_len, ctx->sbuf_len); } } + st_md5_save_hw_context(ctx); } void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ) { + st_md5_restore_hw_context(ctx); if (ctx->sbuf_len > 0) { - HAL_HASH_MD5_Accumulate(&ctx->hhash_md5, ctx->sbuf, ctx->sbuf_len); + if (HAL_HASH_MD5_Accumulate(&ctx->hhash_md5, ctx->sbuf, ctx->sbuf_len) != 0) { + return; // Return error code here + } } - mbedtls_zeroize( ctx->sbuf, MBEDTLS_MD5_BLOCK_SIZE); + mbedtls_zeroize( ctx->sbuf, ST_MD5_BLOCK_SIZE); ctx->sbuf_len = 0; __HAL_HASH_START_DIGEST(); if (HAL_HASH_MD5_Finish(&ctx->hhash_md5, output, 10)) { // error code to be returned } + st_md5_save_hw_context(ctx); } #endif /* MBEDTLS_MD5_ALT */ +#endif /* MBEDTLS_MD5_C */ diff --git a/features/mbedtls/targets/TARGET_STM/md5_alt.h b/features/mbedtls/targets/TARGET_STM/md5_alt.h index 5c8daf9679..8c07747dfd 100644 --- a/features/mbedtls/targets/TARGET_STM/md5_alt.h +++ b/features/mbedtls/targets/TARGET_STM/md5_alt.h @@ -31,19 +31,22 @@ extern "C" { #endif -#define MBEDTLS_MD5_BLOCK_SIZE (64) // must be a multiple of 4 +#define ST_MD5_BLOCK_SIZE ((size_t)(64)) // HW handles 512 bits, ie 64 bytes /** * \brief MD5 context structure - * \note HAL_HASH_MD5_Accumulate cannot handle less than 4 bytes, unless it is the last call to the function - * A MBEDTLS_MD5_BLOCK_SIZE bytes buffer is used to save values and handle the processing - * MBEDTLS_MD5_BLOCK_SIZE bytes per MBEDTLS_MD5_BLOCK_SIZE bytes + * \note HAL_HASH_MD5_Accumulate will accumulate 512 bits packets, unless it is the last call to the function + * A ST_MD5_BLOCK_SIZE bytes buffer is used to save values and handle the processing + * ST_MD5_BLOCK_SIZE bytes per ST_MD5_BLOCK_SIZE bytes * If MD5_finish is called and sbuf_len>0, the remaining bytes are accumulated prior to the call to HAL_HASH_MD5_Finish */ typedef struct { - HASH_HandleTypeDef hhash_md5;/*!< ST HAL HASH struct */ - unsigned char sbuf[MBEDTLS_MD5_BLOCK_SIZE]; /*!< MBEDTLS_MD5_BLOCK_SIZE buffer to store values so that algorithm is caled once the buffer is filled */ - unsigned char sbuf_len; /*!< number of bytes to be processed in sbuf */ + HASH_HandleTypeDef hhash_md5;/*!< ST HAL HASH struct */ + unsigned char sbuf[ST_MD5_BLOCK_SIZE]; /*!< MBEDTLS_MD5_BLOCK_SIZE buffer to store values so that algorithm is caled once the buffer is filled */ + unsigned char sbuf_len; /*!< number of bytes to be processed in sbuf */ + uint32_t ctx_save_cr; + uint32_t ctx_save_str; + uint32_t ctx_save_csr[38]; } mbedtls_md5_context; @@ -95,7 +98,7 @@ void mbedtls_md5_update( mbedtls_md5_context *ctx, const unsigned char *input, s void mbedtls_md5_finish( mbedtls_md5_context *ctx, unsigned char output[16] ); /* Internal use */ -void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[64] ); +void mbedtls_md5_process( mbedtls_md5_context *ctx, const unsigned char data[ST_MD5_BLOCK_SIZE] ); #ifdef __cplusplus }