diff --git a/include/mbedtls/platform_util.h b/include/mbedtls/platform_util.h index e20f1c32e..fa9f3269c 100644 --- a/include/mbedtls/platform_util.h +++ b/include/mbedtls/platform_util.h @@ -239,11 +239,18 @@ int mbedtls_platform_memcmp( const void *buf1, const void *buf2, size_t num ); uint32_t mbedtls_platform_random_in_range( size_t num ); /** - * \brief This function does nothing, but can be inserted between - * successive reads to a volatile local variable to prevent - * compilers from optimizing them away. + * \brief Random delay function. + * + * Function implements a random delay by incrementing a local + * variable randomized number of times (busy-looping). + * + * Duration of the delay is random as number of variable increments + * is randomized. + * + * \note Currently the function is dependent of hardware providing an + * rng with MBEDTLS_ENTROPY_HARDWARE_ALT. */ -void mbedtls_platform_enforce_volatile_reads( void ); +void mbedtls_platform_random_delay( void ); #if defined(MBEDTLS_HAVE_TIME_DATE) /** diff --git a/library/entropy.c b/library/entropy.c index b4d1f2921..6656ee86b 100644 --- a/library/entropy.c +++ b/library/entropy.c @@ -273,7 +273,7 @@ static int entropy_gather_internal( mbedtls_entropy_context *ctx ) volatile int strong_fi = ctx->source[i].strong; if( strong_fi == MBEDTLS_ENTROPY_SOURCE_STRONG ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( strong_fi == MBEDTLS_ENTROPY_SOURCE_STRONG ) have_one_strong_fi = MBEDTLS_ENTROPY_SOURCE_STRONG; @@ -305,7 +305,7 @@ cleanup: if( have_one_strong_fi == MBEDTLS_ENTROPY_SOURCE_STRONG ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( have_one_strong_fi == MBEDTLS_ENTROPY_SOURCE_STRONG ) { return( ret ); diff --git a/library/pk.c b/library/pk.c index 27276a829..caa5e17d0 100644 --- a/library/pk.c +++ b/library/pk.c @@ -597,7 +597,7 @@ static int uecc_eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, if( ret_fi == UECC_SUCCESS ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( ret_fi == UECC_SUCCESS ) return( 0 ); else @@ -1553,7 +1553,7 @@ int mbedtls_pk_verify_restartable( mbedtls_pk_context *ctx, if( verify_ret == 0 ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( verify_ret == 0 ) { return( verify_ret ); diff --git a/library/platform_util.c b/library/platform_util.c index 16867aad6..2c22b3c64 100644 --- a/library/platform_util.c +++ b/library/platform_util.c @@ -45,6 +45,9 @@ #include #include +/* Max number of loops for mbedtls_platform_random_delay */ +#define MAX_RAND_DELAY 100 + #if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) /* * This implementation should never be optimized out by the compiler @@ -165,13 +168,32 @@ uint32_t mbedtls_platform_random_in_range( size_t num ) #endif } -/* Some compilers (armcc 5 for example) optimize away successive reads from a - * volatile local variable (which we use as a counter-measure to fault - * injection attacks), unless there is a call to an external function between - * them. This functions doesn't need to do anything, it just needs to be - * in another compilation unit. So here's a function that does nothing. */ -void mbedtls_platform_enforce_volatile_reads( void ) +void mbedtls_platform_random_delay( void ) { +#if !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + return; +#else + size_t rn_1, rn_2, rn_3; + volatile size_t i = 0; + uint8_t shift; + + rn_1 = mbedtls_platform_random_in_range( MAX_RAND_DELAY ); + rn_2 = mbedtls_platform_random_in_range( 0xffffffff ) + 1; + rn_3 = mbedtls_platform_random_in_range( 0xffffffff ) + 1; + + do + { + i++; + shift = rn_2 & 0x07; + if ( i % 2 ) + rn_2 = (uint32_t)( rn_2 >> shift | rn_2 << ( 32 - shift ) ); + else + rn_3 = (uint32_t)( rn_3 << shift | rn_3 >> ( 32 - shift ) ); + rn_2 ^= rn_3; + } while( i < rn_1 || rn_2 == 0 || rn_3 == 0 ); + + return; +#endif /* !MBEDTLS_ENTROPY_HARDWARE_ALT */ } #if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_PLATFORM_GMTIME_R_ALT) diff --git a/library/ssl_cli.c b/library/ssl_cli.c index 479554d78..3c5992328 100644 --- a/library/ssl_cli.c +++ b/library/ssl_cli.c @@ -717,7 +717,7 @@ static int ssl_generate_random( mbedtls_ssl_context *ssl ) ( mbedtls_ssl_conf_get_prng( ssl->conf ), p, 28 ); if( ret == 0 ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( ret == 0 ) { ssl->handshake->hello_random_set = MBEDTLS_SSL_FI_FLAG_SET; @@ -2369,7 +2369,7 @@ static int ssl_rsa_generate_partial_pms( mbedtls_ssl_context *ssl, if( ret == 0 ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( ret == 0 ) { ssl->handshake->premaster_generated = MBEDTLS_SSL_FI_FLAG_SET; @@ -2442,7 +2442,7 @@ static int ssl_rsa_encrypt_partial_pms( mbedtls_ssl_context *ssl, if( ret == 0 ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( ret == 0 ) { ssl->handshake->premaster_generated = MBEDTLS_SSL_FI_FLAG_SET; @@ -3071,7 +3071,7 @@ static int ssl_in_server_key_exchange_parse( mbedtls_ssl_context *ssl, if( ret == 0 ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( ret == 0 ) { diff --git a/library/ssl_srv.c b/library/ssl_srv.c index 92d1da016..bab8f00d7 100644 --- a/library/ssl_srv.c +++ b/library/ssl_srv.c @@ -4064,7 +4064,7 @@ static int ssl_parse_encrypted_pms( mbedtls_ssl_context *ssl, if( pmscounter == ssl->handshake->pmslen ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( pmscounter == ssl->handshake->pmslen ) { ssl->handshake->premaster_generated = MBEDTLS_SSL_FI_FLAG_SET; @@ -4651,7 +4651,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl ) if( ret == 0 ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( ret == 0 ) { diff --git a/library/ssl_tls.c b/library/ssl_tls.c index 165cd8596..1d5503b9b 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -1938,7 +1938,7 @@ int mbedtls_ssl_derive_keys( mbedtls_ssl_context *ssl ) ssl ); if( ret == 0 ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( ret == 0 ) { ssl->handshake->key_derivation_done = MBEDTLS_SSL_FI_FLAG_SET; @@ -2020,7 +2020,7 @@ int mbedtls_ssl_build_pms( mbedtls_ssl_context *ssl ) mbedtls_ssl_conf_get_prng( ssl->conf ) ); if( ret == 0 ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( ret == 0 ) { ssl->handshake->premaster_generated = MBEDTLS_SSL_FI_FLAG_SET; @@ -2063,7 +2063,7 @@ int mbedtls_ssl_build_pms( mbedtls_ssl_context *ssl ) mbedtls_ssl_conf_get_prng( ssl->conf ) ); if( ret == 0 ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( ret == 0 ) { ssl->handshake->premaster_generated = MBEDTLS_SSL_FI_FLAG_SET; @@ -2094,7 +2094,7 @@ int mbedtls_ssl_build_pms( mbedtls_ssl_context *ssl ) mbedtls_ssl_suite_get_key_exchange( ciphersuite_info ) ); if( ret == 0 ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( ret == 0 ) { ssl->handshake->premaster_generated = MBEDTLS_SSL_FI_FLAG_SET; @@ -2123,7 +2123,7 @@ int mbedtls_ssl_build_pms( mbedtls_ssl_context *ssl ) mbedtls_ssl_conf_get_prng( ssl->conf ) ); if( ret == 0 ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( ret == 0 ) { ssl->handshake->premaster_generated = MBEDTLS_SSL_FI_FLAG_SET; @@ -7355,7 +7355,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl, if( verify_ret == 0 ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( verify_ret == 0 ) { flow_counter++; @@ -7445,7 +7445,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl, ( verify_ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED || verify_ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( authmode == MBEDTLS_SSL_VERIFY_OPTIONAL && ( verify_ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED || verify_ret == MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE ) ) @@ -7511,7 +7511,7 @@ static int ssl_parse_certificate_verify( mbedtls_ssl_context *ssl, flow_counter == 4 ) #endif { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( verify_ret == 0 && #if defined(MBEDTLS_ECP_C) || defined(MBEDTLS_USE_TINYCRYPT) flow_counter == 5 ) @@ -7998,7 +7998,7 @@ int mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ) 1 ) #endif { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( authmode == MBEDTLS_SSL_VERIFY_NONE || authmode == MBEDTLS_SSL_VERIFY_OPTIONAL || #if defined(MBEDTLS_KEY_EXCHANGE__WITH_CERT__ENABLED) @@ -8019,7 +8019,7 @@ int mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ) #if !defined(MBEDTLS_SSL_NO_SESSION_RESUMPTION) if( ssl->handshake->resume == MBEDTLS_SSL_FI_FLAG_SET ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( ssl->handshake->resume == MBEDTLS_SSL_FI_FLAG_SET ) { /* When doing session resume, no premaster or peer authentication */ @@ -8036,7 +8036,7 @@ int mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ) if( ssl->handshake->peer_authenticated == MBEDTLS_SSL_FI_FLAG_SET ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( ssl->handshake->peer_authenticated == MBEDTLS_SSL_FI_FLAG_SET ) { ret = 0; @@ -8057,7 +8057,7 @@ int mbedtls_ssl_handshake_wrapup( mbedtls_ssl_context *ssl ) ssl->handshake->key_derivation_done == MBEDTLS_SSL_FI_FLAG_SET && ssl->handshake->premaster_generated == MBEDTLS_SSL_FI_FLAG_SET ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( ssl->handshake->hello_random_set == MBEDTLS_SSL_FI_FLAG_SET && ssl->handshake->key_derivation_done == MBEDTLS_SSL_FI_FLAG_SET && ssl->handshake->premaster_generated == MBEDTLS_SSL_FI_FLAG_SET ) diff --git a/library/x509_crt.c b/library/x509_crt.c index fd3fa1a04..af8f1d67f 100644 --- a/library/x509_crt.c +++ b/library/x509_crt.c @@ -3043,7 +3043,7 @@ check_signature: if( ret_fi == 0 ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( ret_fi == 0 ) signature_is_good = X509_SIGNATURE_IS_GOOD; } @@ -3549,7 +3549,7 @@ find_parent: if( signature_is_good_fi != X509_SIGNATURE_IS_GOOD ) *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED | X509_BADCERT_FI_EXTRA; - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( signature_is_good_fi != X509_SIGNATURE_IS_GOOD ) *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED | X509_BADCERT_FI_EXTRA; @@ -3861,7 +3861,7 @@ exit: flags_fi = *flags; if( flags_fi == 0 ) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if( flags_fi == 0 ) return( 0 ); } diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c index 0447cbac1..c6c722a95 100644 --- a/tinycrypt/ecc.c +++ b/tinycrypt/ecc.c @@ -168,7 +168,7 @@ static int uECC_check_curve_integrity(void) } /* i should be 32 */ - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); diff |= (unsigned char) i ^ 32; return diff; @@ -296,7 +296,7 @@ uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right) } /* i should be -1 now */ - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); diff |= i ^ -1; return diff; @@ -1043,7 +1043,7 @@ int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point, if (problem != 0) { return UECC_FAULT_DETECTED; } - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if (problem != 0) { return UECC_FAULT_DETECTED; } @@ -1055,7 +1055,7 @@ int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point, /* invalid input, can happen without fault */ return UECC_FAILURE; } - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if (problem != 0) { /* failure on second check means fault, though */ return UECC_FAULT_DETECTED; @@ -1085,7 +1085,7 @@ int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point, r = UECC_FAULT_DETECTED; goto clear_and_out; } - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if (problem != 0) { r = UECC_FAULT_DETECTED; goto clear_and_out; @@ -1098,7 +1098,7 @@ int EccPoint_mult_safer(uECC_word_t * result, const uECC_word_t * point, r = UECC_FAULT_DETECTED; goto clear_and_out; } - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if (problem != 0) { r = UECC_FAULT_DETECTED; goto clear_and_out; @@ -1195,7 +1195,7 @@ int uECC_valid_point(const uECC_word_t *point) /* Make sure that y^2 == x^3 + ax + b */ diff = uECC_vli_equal(tmp1, tmp2); if (diff == 0) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if (diff == 0) { return 0; } diff --git a/tinycrypt/ecc_dsa.c b/tinycrypt/ecc_dsa.c index 8fa850944..660c5e9fa 100644 --- a/tinycrypt/ecc_dsa.c +++ b/tinycrypt/ecc_dsa.c @@ -279,7 +279,7 @@ int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash, /* Accept only if v == r. */ diff = uECC_vli_equal(rx, r); if (diff == 0) { - mbedtls_platform_enforce_volatile_reads(); + mbedtls_platform_random_delay(); if (diff == 0) { return UECC_SUCCESS; }