From f93d55e3ce4e230a9518431927388e5e1c885911 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Fri, 11 Oct 2019 11:15:57 +0300 Subject: [PATCH 01/14] Add SCA countermeasures to AES calculation - 3 additional dummy AES rounds calculated with random data for each AES encryption/decryption - additional rounds can be occur in any point in sequence of rounds --- library/aes.c | 364 +++++++++++++++++++++++++++++++++++++------------- 1 file changed, 272 insertions(+), 92 deletions(-) diff --git a/library/aes.c b/library/aes.c index 243c4ec7c..9361edbf3 100644 --- a/library/aes.c +++ b/library/aes.c @@ -407,6 +407,24 @@ static uint32_t RCON[10]; static int aes_init_done = 0; +/* + * SCA CM table position check + */ +#define SCA_CM_TBL_MATCH(tbl, n) ( tbl[0] == ( n ) || \ + tbl[1] == ( n ) || \ + tbl[2] == ( n ) ) + +/* + * SCA CM always true check + */ +#define SCA_CM_ALWAYS_TRUE(tbl, n) ( tbl[0] != ( n ) || \ + tbl[1] != ( n ) || \ + tbl[2] != tbl[0] ) +/* + * Number of SCA CM dummy rounds. + */ +#define SCA_CM_DUMMY_ROUND_COUNT 3 + static void aes_gen_tables( void ) { int i, x, y, z; @@ -527,6 +545,42 @@ static void aes_gen_tables( void ) #endif /* MBEDTLS_AES_FEWER_TABLES */ +// TODO, replace with proper flagging + +#if /* defined(AES_128_SCA_CM) &&*/ defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +#define AES_SCA_COUNTERMEASURES +#endif + +#if defined(AES_SCA_COUNTERMEASURES) +static void aes_sca_rand_tbl_fill(uint8_t *tbl, uint8_t tbl_len, uint8_t max_num) +{ + int i, j, is_unique_number; + uint8_t *cur_num; + uint8_t num; + + cur_num = tbl; + + for ( i = 0; i < tbl_len; i++ ) + { + do { + is_unique_number = 1; + num = mbedtls_platform_random_in_range( max_num + 1 ); + + for ( j = 0; j < i; j++ ) + { + if (num == tbl[j]) + { + is_unique_number = 0; + break; + } + } + } while ( is_unique_number == 0 ); + + *cur_num++ = num; + } +} +#endif + void mbedtls_aes_init( mbedtls_aes_context *ctx ) { AES_VALIDATE( ctx != NULL ); @@ -838,52 +892,99 @@ int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, #endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ -#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ - do \ - { \ - (X0) = *RK++ ^ AES_FT0( ( (Y0) ) & 0xFF ) ^ \ - AES_FT1( ( (Y1) >> 8 ) & 0xFF ) ^ \ - AES_FT2( ( (Y2) >> 16 ) & 0xFF ) ^ \ - AES_FT3( ( (Y3) >> 24 ) & 0xFF ); \ - \ - (X1) = *RK++ ^ AES_FT0( ( (Y1) ) & 0xFF ) ^ \ - AES_FT1( ( (Y2) >> 8 ) & 0xFF ) ^ \ - AES_FT2( ( (Y3) >> 16 ) & 0xFF ) ^ \ - AES_FT3( ( (Y0) >> 24 ) & 0xFF ); \ - \ - (X2) = *RK++ ^ AES_FT0( ( (Y2) ) & 0xFF ) ^ \ - AES_FT1( ( (Y3) >> 8 ) & 0xFF ) ^ \ - AES_FT2( ( (Y0) >> 16 ) & 0xFF ) ^ \ - AES_FT3( ( (Y1) >> 24 ) & 0xFF ); \ - \ - (X3) = *RK++ ^ AES_FT0( ( (Y3) ) & 0xFF ) ^ \ - AES_FT1( ( (Y0) >> 8 ) & 0xFF ) ^ \ - AES_FT2( ( (Y1) >> 16 ) & 0xFF ) ^ \ - AES_FT3( ( (Y2) >> 24 ) & 0xFF ); \ +#define AES_FROUND(R,X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + do \ + { \ + (X0) = *(R)++ ^ AES_FT0( ( (Y0) ) & 0xFF ) ^ \ + AES_FT1( ( (Y1) >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( (Y2) >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( (Y3) >> 24 ) & 0xFF ); \ + \ + (X1) = *(R)++ ^ AES_FT0( ( (Y1) ) & 0xFF ) ^ \ + AES_FT1( ( (Y2) >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( (Y3) >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( (Y0) >> 24 ) & 0xFF ); \ + \ + (X2) = *(R)++ ^ AES_FT0( ( (Y2) ) & 0xFF ) ^ \ + AES_FT1( ( (Y3) >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( (Y0) >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( (Y1) >> 24 ) & 0xFF ); \ + \ + (X3) = *(R)++ ^ AES_FT0( ( (Y3) ) & 0xFF ) ^ \ + AES_FT1( ( (Y0) >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( (Y1) >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( (Y2) >> 24 ) & 0xFF ); \ } while( 0 ) -#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ - do \ - { \ - (X0) = *RK++ ^ AES_RT0( ( (Y0) ) & 0xFF ) ^ \ - AES_RT1( ( (Y3) >> 8 ) & 0xFF ) ^ \ - AES_RT2( ( (Y2) >> 16 ) & 0xFF ) ^ \ - AES_RT3( ( (Y1) >> 24 ) & 0xFF ); \ - \ - (X1) = *RK++ ^ AES_RT0( ( (Y1) ) & 0xFF ) ^ \ - AES_RT1( ( (Y0) >> 8 ) & 0xFF ) ^ \ - AES_RT2( ( (Y3) >> 16 ) & 0xFF ) ^ \ - AES_RT3( ( (Y2) >> 24 ) & 0xFF ); \ - \ - (X2) = *RK++ ^ AES_RT0( ( (Y2) ) & 0xFF ) ^ \ - AES_RT1( ( (Y1) >> 8 ) & 0xFF ) ^ \ - AES_RT2( ( (Y0) >> 16 ) & 0xFF ) ^ \ - AES_RT3( ( (Y3) >> 24 ) & 0xFF ); \ - \ - (X3) = *RK++ ^ AES_RT0( ( (Y3) ) & 0xFF ) ^ \ - AES_RT1( ( (Y2) >> 8 ) & 0xFF ) ^ \ - AES_RT2( ( (Y1) >> 16 ) & 0xFF ) ^ \ - AES_RT3( ( (Y0) >> 24 ) & 0xFF ); \ +#define AES_FROUND_F(R,X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + do { \ + (X0) = *(R)++ ^ ( (uint32_t) FSb[ ( (Y0) ) & 0xFF ] ) ^ \ + ( (uint32_t) FSb[ ( (Y1) >> 8 ) & 0xFF ] << 8 ) ^ \ + ( (uint32_t) FSb[ ( (Y2) >> 16 ) & 0xFF ] << 16 ) ^ \ + ( (uint32_t) FSb[ ( (Y3) >> 24 ) & 0xFF ] << 24 ); \ + \ + (X1) = *(R)++ ^ ( (uint32_t) FSb[ ( (Y1) ) & 0xFF ] ) ^ \ + ( (uint32_t) FSb[ ( (Y2) >> 8 ) & 0xFF ] << 8 ) ^ \ + ( (uint32_t) FSb[ ( (Y3) >> 16 ) & 0xFF ] << 16 ) ^ \ + ( (uint32_t) FSb[ ( (Y0) >> 24 ) & 0xFF ] << 24 ); \ + \ + (X2) = *(R)++ ^ ( (uint32_t) FSb[ ( (Y2) ) & 0xFF ] ) ^ \ + ( (uint32_t) FSb[ ( (Y3) >> 8 ) & 0xFF ] << 8 ) ^ \ + ( (uint32_t) FSb[ ( (Y0) >> 16 ) & 0xFF ] << 16 ) ^ \ + ( (uint32_t) FSb[ ( (Y1) >> 24 ) & 0xFF ] << 24 ); \ + \ + (X3) = *(R)++ ^ ( (uint32_t) FSb[ ( (Y3) ) & 0xFF ] ) ^ \ + ( (uint32_t) FSb[ ( (Y0) >> 8 ) & 0xFF ] << 8 ) ^ \ + ( (uint32_t) FSb[ ( (Y1) >> 16 ) & 0xFF ] << 16 ) ^ \ + ( (uint32_t) FSb[ ( (Y2) >> 24 ) & 0xFF ] << 24 ); \ + } while ( 0 ) + +#define AES_RROUND(R,X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + do \ + { \ + (X0) = *(R)++ ^ AES_RT0( ( (Y0) ) & 0xFF ) ^ \ + AES_RT1( ( (Y3) >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( (Y2) >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( (Y1) >> 24 ) & 0xFF ); \ + \ + (X1) = *(R)++ ^ AES_RT0( ( (Y1) ) & 0xFF ) ^ \ + AES_RT1( ( (Y0) >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( (Y3) >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( (Y2) >> 24 ) & 0xFF ); \ + \ + (X2) = *(R)++ ^ AES_RT0( ( (Y2) ) & 0xFF ) ^ \ + AES_RT1( ( (Y1) >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( (Y0) >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( (Y3) >> 24 ) & 0xFF ); \ + \ + (X3) = *(R)++ ^ AES_RT0( ( (Y3) ) & 0xFF ) ^ \ + AES_RT1( ( (Y2) >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( (Y1) >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( (Y0) >> 24 ) & 0xFF ); \ + } while( 0 ) + +#define AES_RROUND_F(R,X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + do \ + { \ + (X0) = *(R)++ ^ ( (uint32_t) RSb[ ( (Y0) ) & 0xFF ] ) ^ \ + ( (uint32_t) RSb[ ( (Y3) >> 8 ) & 0xFF ] << 8 ) ^ \ + ( (uint32_t) RSb[ ( (Y2) >> 16 ) & 0xFF ] << 16 ) ^ \ + ( (uint32_t) RSb[ ( (Y1) >> 24 ) & 0xFF ] << 24 ); \ + \ + (X1) = *(R)++ ^ ( (uint32_t) RSb[ ( (Y1) ) & 0xFF ] ) ^ \ + ( (uint32_t) RSb[ ( (Y0) >> 8 ) & 0xFF ] << 8 ) ^ \ + ( (uint32_t) RSb[ ( (Y3) >> 16 ) & 0xFF ] << 16 ) ^ \ + ( (uint32_t) RSb[ ( (Y2) >> 24 ) & 0xFF ] << 24 ); \ + \ + (X2) = *(R)++ ^ ( (uint32_t) RSb[ ( (Y2) ) & 0xFF ] ) ^ \ + ( (uint32_t) RSb[ ( (Y1) >> 8 ) & 0xFF ] << 8 ) ^ \ + ( (uint32_t) RSb[ ( (Y0) >> 16 ) & 0xFF ] << 16 ) ^ \ + ( (uint32_t) RSb[ ( (Y3) >> 24 ) & 0xFF ] << 24 ); \ + \ + (X3) = *(R)++ ^ ( (uint32_t) RSb[ ( (Y3) ) & 0xFF ] ) ^ \ + ( (uint32_t) RSb[ ( (Y2) >> 8 ) & 0xFF ] << 8 ) ^ \ + ( (uint32_t) RSb[ ( (Y1) >> 16 ) & 0xFF ] << 16 ) ^ \ + ( (uint32_t) RSb[ ( (Y0) >> 24 ) & 0xFF ] << 24 ); \ } while( 0 ) /* @@ -895,10 +996,34 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, unsigned char output[16] ) { int i; - uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + uint32_t *RK, X0, X1, X2, X3, Y0 = 0, Y1 = 0, Y2 = 0, Y3 = 0; + +#ifdef AES_SCA_COUNTERMEASURES + uint32_t *RK_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA; + uint8_t sca_cm_pos_tbl[SCA_CM_DUMMY_ROUND_COUNT]; // position for SCA countermeasure dummy rounds, not in any order + + aes_sca_rand_tbl_fill(sca_cm_pos_tbl, SCA_CM_DUMMY_ROUND_COUNT, ctx->nr); + + X0_SCA = mbedtls_platform_random_in_range( 0xffffffff ); + X1_SCA = mbedtls_platform_random_in_range( 0xffffffff ); + X2_SCA = mbedtls_platform_random_in_range( 0xffffffff ); + X3_SCA = mbedtls_platform_random_in_range( 0xffffffff ); +#endif /* AES_SCA_COUNTERMEASURES */ RK = ctx->rk; +#ifdef AES_SCA_COUNTERMEASURES + RK_SCA = RK; + + if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, ctx->nr ) ) + { + /* LE conversions to Xn, Xn_SCA randomized */ + GET_UINT32_LE( X0, input, 0 ); X0_SCA ^= *RK_SCA++; + GET_UINT32_LE( X1, input, 4 ); X1_SCA ^= *RK_SCA++; + GET_UINT32_LE( X2, input, 8 ); X2_SCA ^= *RK_SCA++; + GET_UINT32_LE( X3, input, 12 ); X3_SCA ^= *RK_SCA++; + } +#endif /* AES_SCA_COUNTERMEASURES */ GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; @@ -906,35 +1031,47 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) { - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); +#ifdef AES_SCA_COUNTERMEASURES + // Would random delay before each round be necessary? + // + if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, i * 2 ) ) + AES_FROUND( RK_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA, + X0_SCA, X1_SCA, X2_SCA, X3_SCA ); + + if ( SCA_CM_ALWAYS_TRUE( sca_cm_pos_tbl, i* 2 ) ) + AES_FROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, i * 2 + 1 ) ) + AES_FROUND( RK_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA, + Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA); + + if ( SCA_CM_ALWAYS_TRUE( sca_cm_pos_tbl, i * 2 + 1 ) ) + AES_FROUND( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); +#else /* AES_SCA_COUNTERMEASURES */ + AES_FROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_FROUND( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); +#endif /* AES_SCA_COUNTERMEASURES */ } - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); +#ifdef AES_SCA_COUNTERMEASURES + if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, 1 ) ) + AES_FROUND( RK_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA, + X0_SCA, X1_SCA, X2_SCA, X3_SCA ); - X0 = *RK++ ^ \ - ( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + if ( SCA_CM_ALWAYS_TRUE ( sca_cm_pos_tbl, 1 ) ) + AES_FROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - X1 = *RK++ ^ \ - ( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); + if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, 0 ) ) + AES_FROUND_F( RK_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA, + Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA ); - X2 = *RK++ ^ \ - ( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + if ( SCA_CM_ALWAYS_TRUE ( sca_cm_pos_tbl, 0 ) ) + AES_FROUND_F( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); - X3 = *RK++ ^ \ - ( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); +#else + AES_FROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_FROUND_F( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); +#endif PUT_UINT32_LE( X0, output, 0 ); PUT_UINT32_LE( X1, output, 4 ); @@ -965,46 +1102,89 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, unsigned char output[16] ) { int i; - uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + uint32_t *RK, X0, X1, X2, X3, Y0 = 0, Y1 = 0, Y2 = 0, Y3 = 0; + +#ifdef AES_SCA_COUNTERMEASURES + uint32_t *RK_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA; + uint8_t sca_cm_pos_tbl[SCA_CM_DUMMY_ROUND_COUNT]; // position for SCA countermeasure dummy rounds, not in any order + + aes_sca_rand_tbl_fill(sca_cm_pos_tbl, SCA_CM_DUMMY_ROUND_COUNT, ctx->nr); + + X0_SCA = mbedtls_platform_random_in_range( 0xffffffff ); + X1_SCA = mbedtls_platform_random_in_range( 0xffffffff ); + X2_SCA = mbedtls_platform_random_in_range( 0xffffffff ); + X3_SCA = mbedtls_platform_random_in_range( 0xffffffff ); +#endif /* AES_SCA_COUNTERMEASURES */ RK = ctx->rk; +#ifdef AES_SCA_COUNTERMEASURES + RK_SCA = RK; + if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, ctx->nr ) ) + { + GET_UINT32_LE( X0, input, 0 ); X0_SCA ^= *RK_SCA++; + GET_UINT32_LE( X1, input, 4 ); X1_SCA ^= *RK_SCA++; + GET_UINT32_LE( X2, input, 8 ); X2_SCA ^= *RK_SCA++; + GET_UINT32_LE( X3, input, 12 ); X3_SCA ^= *RK_SCA++; + } + + if ( SCA_CM_ALWAYS_TRUE( sca_cm_pos_tbl, ctx->nr ) ) + { + GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; + GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; + GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; + GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; + } +#else /* AES_SCA_COUNTERMEASURES */ GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; +#endif /* AES_SCA_COUNTERMEASURES */ for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) { - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); +#ifdef AES_SCA_COUNTERMEASURES + // Would random delay before each round be necessary? + // + if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, i * 2 ) ) + AES_RROUND( RK_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA, + X0_SCA, X1_SCA, X2_SCA, X3_SCA ); + + if ( SCA_CM_ALWAYS_TRUE( sca_cm_pos_tbl, i* 2 ) ) + AES_RROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, i * 2 + 1 ) ) + AES_RROUND( RK_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA, + Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA); + + if ( SCA_CM_ALWAYS_TRUE( sca_cm_pos_tbl, i * 2 + 1 ) ) + AES_RROUND( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); +#else /* AES_SCA_COUNTERMEASURES */ + AES_RROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_RROUND( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); +#endif /* AES_SCA_COUNTERMEASURES */ } - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); +#ifdef AES_SCA_COUNTERMEASURES + if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, 1 ) ) + AES_RROUND( RK_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA, + X0_SCA, X1_SCA, X2_SCA, X3_SCA ); - X0 = *RK++ ^ \ - ( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^ - ( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + if ( SCA_CM_ALWAYS_TRUE ( sca_cm_pos_tbl, 1 ) ) + AES_RROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - X1 = *RK++ ^ \ - ( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^ - ( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); + if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, 0 ) ) + AES_RROUND_F( RK_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA, + Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA ); - X2 = *RK++ ^ \ - ( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^ - ( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + if ( SCA_CM_ALWAYS_TRUE ( sca_cm_pos_tbl, 0 ) ) + AES_RROUND_F( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); - X3 = *RK++ ^ \ - ( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^ - ( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); +#else /* AES_SCA_COUNTERMEASURES */ + AES_RROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_RROUND_F( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); +#endif /* AES_SCA_COUNTERMEASURES */ PUT_UINT32_LE( X0, output, 0 ); PUT_UINT32_LE( X1, output, 4 ); From 430ac1311299402992c967466a9c69b1124127da Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 14 Oct 2019 10:42:28 +0300 Subject: [PATCH 02/14] Add config and test for AES SCA countermeasures - Add configuration for AES_SCA_COUNTERMEASURES to config.h. By default the feature is disabled. - Add AES_SCA_COUNTERMEASURES configuration check to check_config.h - Add AES_SCA_COUNTERMEASURES test to all.sh --- include/mbedtls/check_config.h | 4 ++ include/mbedtls/config.h | 17 +++++++ library/aes.c | 83 ++++++++++++++++------------------ tests/scripts/all.sh | 10 ++++ 4 files changed, 71 insertions(+), 43 deletions(-) diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index fe9c5945e..40647d570 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -70,6 +70,10 @@ #error "MBEDTLS_AESNI_C defined, but not all prerequisites" #endif +#if defined(MBEDTLS_AES_SCA_COUNTERMEASURES) && !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +#error "MBEDTLS_AES_SCA_COUNTERMEASURES defined, but not all prerequisites" +#endif + #if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) #error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" #endif diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 87012dab5..1a2de9aad 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -634,6 +634,23 @@ */ //#define MBEDTLS_AES_ONLY_ENCRYPT +/** + * \def MBEDTLS_AES_SCA_COUNTERMEASURES + * + * Add countermeasures against possible side-channel-attack to AES calculation. + * + * Uncommenting this macro adds three additional calculation rounds to AES + * calculation. Additional rounds are using random data and can occur in any + * AES calculation round. + * + * Tradeoff: Uncommenting this increases ROM footprint by ~800 bytes. + * The performance loss is 3/11= 27% with 128 bit AES. + * + * This option is dependent of \c MBEDTLS_ENTROPY_HARDWARE_ALT. + * + */ +//#define MBEDTLS_AES_SCA_COUNTERMEASURES + /** * \def MBEDTLS_CAMELLIA_SMALL_MEMORY * diff --git a/library/aes.c b/library/aes.c index 9361edbf3..d9a57a15a 100644 --- a/library/aes.c +++ b/library/aes.c @@ -407,24 +407,6 @@ static uint32_t RCON[10]; static int aes_init_done = 0; -/* - * SCA CM table position check - */ -#define SCA_CM_TBL_MATCH(tbl, n) ( tbl[0] == ( n ) || \ - tbl[1] == ( n ) || \ - tbl[2] == ( n ) ) - -/* - * SCA CM always true check - */ -#define SCA_CM_ALWAYS_TRUE(tbl, n) ( tbl[0] != ( n ) || \ - tbl[1] != ( n ) || \ - tbl[2] != tbl[0] ) -/* - * Number of SCA CM dummy rounds. - */ -#define SCA_CM_DUMMY_ROUND_COUNT 3 - static void aes_gen_tables( void ) { int i, x, y, z; @@ -545,13 +527,28 @@ static void aes_gen_tables( void ) #endif /* MBEDTLS_AES_FEWER_TABLES */ -// TODO, replace with proper flagging +#if defined(MBEDTLS_AES_SCA_COUNTERMEASURES) +/* + * SCA CM table position check + */ +#define SCA_CM_TBL_MATCH(tbl, n) ( tbl[0] == ( n ) || \ + tbl[1] == ( n ) || \ + tbl[2] == ( n ) ) -#if /* defined(AES_128_SCA_CM) &&*/ defined(MBEDTLS_ENTROPY_HARDWARE_ALT) -#define AES_SCA_COUNTERMEASURES -#endif +/* + * SCA CM always true check + */ +#define SCA_CM_ALWAYS_TRUE(tbl, n) ( tbl[0] != ( n ) || \ + tbl[1] != ( n ) || \ + tbl[2] != tbl[0] ) +/* + * Number of SCA CM dummy rounds. + */ +#define SCA_CM_DUMMY_ROUND_COUNT 3 -#if defined(AES_SCA_COUNTERMEASURES) +#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ + +#if defined(MBEDTLS_AES_SCA_COUNTERMEASURES) static void aes_sca_rand_tbl_fill(uint8_t *tbl, uint8_t tbl_len, uint8_t max_num) { int i, j, is_unique_number; @@ -579,7 +576,7 @@ static void aes_sca_rand_tbl_fill(uint8_t *tbl, uint8_t tbl_len, uint8_t max_num *cur_num++ = num; } } -#endif +#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ void mbedtls_aes_init( mbedtls_aes_context *ctx ) { @@ -998,7 +995,7 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, int i; uint32_t *RK, X0, X1, X2, X3, Y0 = 0, Y1 = 0, Y2 = 0, Y3 = 0; -#ifdef AES_SCA_COUNTERMEASURES +#ifdef MBEDTLS_AES_SCA_COUNTERMEASURES uint32_t *RK_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA; uint8_t sca_cm_pos_tbl[SCA_CM_DUMMY_ROUND_COUNT]; // position for SCA countermeasure dummy rounds, not in any order @@ -1008,11 +1005,11 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, X1_SCA = mbedtls_platform_random_in_range( 0xffffffff ); X2_SCA = mbedtls_platform_random_in_range( 0xffffffff ); X3_SCA = mbedtls_platform_random_in_range( 0xffffffff ); -#endif /* AES_SCA_COUNTERMEASURES */ +#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ RK = ctx->rk; -#ifdef AES_SCA_COUNTERMEASURES +#ifdef MBEDTLS_AES_SCA_COUNTERMEASURES RK_SCA = RK; if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, ctx->nr ) ) @@ -1023,7 +1020,7 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, GET_UINT32_LE( X2, input, 8 ); X2_SCA ^= *RK_SCA++; GET_UINT32_LE( X3, input, 12 ); X3_SCA ^= *RK_SCA++; } -#endif /* AES_SCA_COUNTERMEASURES */ +#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; @@ -1031,7 +1028,7 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) { -#ifdef AES_SCA_COUNTERMEASURES +#ifdef MBEDTLS_AES_SCA_COUNTERMEASURES // Would random delay before each round be necessary? // if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, i * 2 ) ) @@ -1047,13 +1044,13 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, if ( SCA_CM_ALWAYS_TRUE( sca_cm_pos_tbl, i * 2 + 1 ) ) AES_FROUND( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); -#else /* AES_SCA_COUNTERMEASURES */ +#else /* MBEDTLS_AES_SCA_COUNTERMEASURES */ AES_FROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); AES_FROUND( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); -#endif /* AES_SCA_COUNTERMEASURES */ +#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ } -#ifdef AES_SCA_COUNTERMEASURES +#ifdef MBEDTLS_AES_SCA_COUNTERMEASURES if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, 1 ) ) AES_FROUND( RK_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA ); @@ -1104,7 +1101,7 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, int i; uint32_t *RK, X0, X1, X2, X3, Y0 = 0, Y1 = 0, Y2 = 0, Y3 = 0; -#ifdef AES_SCA_COUNTERMEASURES +#ifdef MBEDTLS_AES_SCA_COUNTERMEASURES uint32_t *RK_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA; uint8_t sca_cm_pos_tbl[SCA_CM_DUMMY_ROUND_COUNT]; // position for SCA countermeasure dummy rounds, not in any order @@ -1114,11 +1111,11 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, X1_SCA = mbedtls_platform_random_in_range( 0xffffffff ); X2_SCA = mbedtls_platform_random_in_range( 0xffffffff ); X3_SCA = mbedtls_platform_random_in_range( 0xffffffff ); -#endif /* AES_SCA_COUNTERMEASURES */ +#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ RK = ctx->rk; -#ifdef AES_SCA_COUNTERMEASURES +#ifdef MBEDTLS_AES_SCA_COUNTERMEASURES RK_SCA = RK; if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, ctx->nr ) ) { @@ -1135,16 +1132,16 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; } -#else /* AES_SCA_COUNTERMEASURES */ +#else /* MBEDTLS_AES_SCA_COUNTERMEASURES */ GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; -#endif /* AES_SCA_COUNTERMEASURES */ +#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) { -#ifdef AES_SCA_COUNTERMEASURES +#ifdef MBEDTLS_AES_SCA_COUNTERMEASURES // Would random delay before each round be necessary? // if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, i * 2 ) ) @@ -1160,13 +1157,13 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, if ( SCA_CM_ALWAYS_TRUE( sca_cm_pos_tbl, i * 2 + 1 ) ) AES_RROUND( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); -#else /* AES_SCA_COUNTERMEASURES */ +#else /* MBEDTLS_AES_SCA_COUNTERMEASURES */ AES_RROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); AES_RROUND( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); -#endif /* AES_SCA_COUNTERMEASURES */ +#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ } -#ifdef AES_SCA_COUNTERMEASURES +#ifdef MBEDTLS_AES_SCA_COUNTERMEASURES if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, 1 ) ) AES_RROUND( RK_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA ); @@ -1181,10 +1178,10 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, if ( SCA_CM_ALWAYS_TRUE ( sca_cm_pos_tbl, 0 ) ) AES_RROUND_F( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); -#else /* AES_SCA_COUNTERMEASURES */ +#else /* MBEDTLS_AES_SCA_COUNTERMEASURES */ AES_RROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); AES_RROUND_F( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); -#endif /* AES_SCA_COUNTERMEASURES */ +#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ PUT_UINT32_LE( X0, output, 0 ); PUT_UINT32_LE( X1, output, 4 ); diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 42ef32d0d..0ea4ae818 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -1294,6 +1294,16 @@ component_test_aes_fewer_tables_and_rom_tables () { make test } +component_test_aes_sca_countermeasures () { + msg "build: default config + MBEDTLS_AES_SCA_COUNTERMEASURES + MBEDTLS_ENTROPY_HARDWARE_ALT + !MBEDTLS_AESNI_C" + scripts/config.pl set MBEDTLS_AES_SCA_COUNTERMEASURES + scripts/config.pl set MBEDTLS_ENTROPY_HARDWARE_ALT + scripts/config.pl unset MBEDTLS_AESNI_C + + msg "test: AES SCA countermeasures" + make test +} + component_test_make_shared () { msg "build/test: make shared" # ~ 40s make SHARED=1 all check From 45a475f293f7fedd83f7c96efd782cab78ce9e22 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 14 Oct 2019 12:31:50 +0300 Subject: [PATCH 03/14] Follow Mbed TLS coding style --- library/aes.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/library/aes.c b/library/aes.c index d9a57a15a..76838480b 100644 --- a/library/aes.c +++ b/library/aes.c @@ -549,7 +549,7 @@ static void aes_gen_tables( void ) #endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ #if defined(MBEDTLS_AES_SCA_COUNTERMEASURES) -static void aes_sca_rand_tbl_fill(uint8_t *tbl, uint8_t tbl_len, uint8_t max_num) +static void aes_sca_rand_tbl_fill( uint8_t *tbl, uint8_t tbl_len, uint8_t max_num ) { int i, j, is_unique_number; uint8_t *cur_num; @@ -565,7 +565,7 @@ static void aes_sca_rand_tbl_fill(uint8_t *tbl, uint8_t tbl_len, uint8_t max_num for ( j = 0; j < i; j++ ) { - if (num == tbl[j]) + if ( num == tbl[j] ) { is_unique_number = 0; break; @@ -999,7 +999,7 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, uint32_t *RK_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA; uint8_t sca_cm_pos_tbl[SCA_CM_DUMMY_ROUND_COUNT]; // position for SCA countermeasure dummy rounds, not in any order - aes_sca_rand_tbl_fill(sca_cm_pos_tbl, SCA_CM_DUMMY_ROUND_COUNT, ctx->nr); + aes_sca_rand_tbl_fill( sca_cm_pos_tbl, SCA_CM_DUMMY_ROUND_COUNT, ctx->nr ); X0_SCA = mbedtls_platform_random_in_range( 0xffffffff ); X1_SCA = mbedtls_platform_random_in_range( 0xffffffff ); @@ -1105,7 +1105,7 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, uint32_t *RK_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA; uint8_t sca_cm_pos_tbl[SCA_CM_DUMMY_ROUND_COUNT]; // position for SCA countermeasure dummy rounds, not in any order - aes_sca_rand_tbl_fill(sca_cm_pos_tbl, SCA_CM_DUMMY_ROUND_COUNT, ctx->nr); + aes_sca_rand_tbl_fill( sca_cm_pos_tbl, SCA_CM_DUMMY_ROUND_COUNT, ctx->nr ); X0_SCA = mbedtls_platform_random_in_range( 0xffffffff ); X1_SCA = mbedtls_platform_random_in_range( 0xffffffff ); From 2231138c188db9f675056bcd8df0ffee421a92be Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 14 Oct 2019 15:18:27 +0300 Subject: [PATCH 04/14] Disable AES SCA countermeasures from full config Disable AES SCA countermeasures from full config. Otherwise check_config will break the builds due inproper configuration. --- scripts/config.pl | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/config.pl b/scripts/config.pl index ff522b623..2519623cd 100755 --- a/scripts/config.pl +++ b/scripts/config.pl @@ -53,6 +53,7 @@ # MBEDTLS_NO_64BIT_MULTIPLICATION # MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH # MBEDTLS_AES_ONLY_ENCRYPT +# MBEDTLS_AES_SCA_COUNTERMEASURES # and any symbol beginning _ALT # @@ -130,6 +131,7 @@ MBEDTLS_NO_64BIT_MULTIPLICATION MBEDTLS_USE_TINYCRYPT MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH MBEDTLS_AES_ONLY_ENCRYPT +MBEDTLS_AES_SCA_COUNTERMEASURES _ALT\s*$ ); From 43980a09e02811fb30188f01c3163040d8670c9d Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 14 Oct 2019 15:37:31 +0300 Subject: [PATCH 05/14] Add AES SCA countermeasures to query_config Add MBEDTLS_AES_SCA_COUNTERMEASURES flag to query_config so that flag value can be queried. --- programs/ssl/query_config.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/programs/ssl/query_config.c b/programs/ssl/query_config.c index fd2bc903b..315065be4 100644 --- a/programs/ssl/query_config.c +++ b/programs/ssl/query_config.c @@ -762,6 +762,14 @@ int query_config( const char *config ) } #endif /* MBEDTLS_AES_ONLY_ENCRYPT */ +#if defined(MBEDTLS_AES_SCA_COUNTERMEASURES) + if( strcmp( "MBEDTLS_AES_SCA_COUNTERMEASURES", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_AES_SCA_COUNTERMEASURES ); + return( 0 ); + } +#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ + #if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) if( strcmp( "MBEDTLS_CAMELLIA_SMALL_MEMORY", config ) == 0 ) { From b2be92e2c7e9fd65895065cbf75cdaaec8bd81da Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Mon, 14 Oct 2019 16:36:29 +0300 Subject: [PATCH 06/14] Update AES SCA flag to version_features.c --- library/version_features.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/version_features.c b/library/version_features.c index 7a97d38f8..6882830b0 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -270,6 +270,9 @@ static const char *features[] = { #if defined(MBEDTLS_AES_ONLY_ENCRYPT) "MBEDTLS_AES_ONLY_ENCRYPT", #endif /* MBEDTLS_AES_ONLY_ENCRYPT */ +#if defined(MBEDTLS_AES_SCA_COUNTERMEASURES) + "MBEDTLS_AES_SCA_COUNTERMEASURES", +#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ #if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) "MBEDTLS_CAMELLIA_SMALL_MEMORY", #endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ From 172836a28153b0d72a6a38c1463b7111ab9f2398 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Thu, 28 Nov 2019 13:34:13 +0200 Subject: [PATCH 07/14] Rework AES countermeasures implementation Use control bytes to instruct AES calculation rounds. Each calculation round has a control byte that indicates what data (real/fake) is used and if any offset is required for AES data positions. First and last AES calculation round are calculated with SCA CM data included. The calculation order is randomized by the control bytes. Calculations between the first and last rounds contains 3 SCA CMs in randomized positions. --- library/aes.c | 515 +++++++++++++++++++++++++------------------------- 1 file changed, 262 insertions(+), 253 deletions(-) diff --git a/library/aes.c b/library/aes.c index 76838480b..4dacd6417 100644 --- a/library/aes.c +++ b/library/aes.c @@ -85,6 +85,21 @@ } #endif +/* + * Data structure for AES round data + */ +typedef struct _aes_r_data_s { + uint32_t *rk_ptr; /* Round Key */ + uint32_t xy_values[8]; /* X0, X1, X2, X3, Y0, U1, Y2, Y3 */ +} aes_r_data_t; + +#if defined(MBEDTLS_AES_SCA_COUNTERMEASURES) +/* Number of additional AES calculation rounds added for SCA CM */ +#define AES_SCA_CM_ROUNDS 3 +#else /* MBEDTLS_AES_SCA_COUNTERMEASURES */ +#define AES_SCA_CM_ROUNDS 0 +#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ + #if defined(MBEDTLS_PADLOCK_C) && \ ( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) ) static int aes_padlock_ace = -1; @@ -497,6 +512,81 @@ static void aes_gen_tables( void ) #endif /* MBEDTLS_AES_ROM_TABLES */ +/** + * Randomize positions when to use AES SCA countermeasures. + * Each byte indicates one AES round as follows: + * first ( tbl_len - 2 ) bytes are reserved for AES rounds + * -4 high bit = table to use 0x10 for SCA CM data, 0 otherwise + * -4 low bits = offset based on order, 4 for even position, 0 otherwise + * Last 2 bytes for first/final round calculation + * -4 high bit = table to use, 0x10 for SCA CM data, otherwise real data + * -4 low bits = not used + * + */ +static void aes_sca_cm_data_randomize( uint8_t *tbl, uint8_t tbl_len ) +{ + int i, is_even_pos; +#if AES_SCA_CM_ROUNDS != 0 + int is_unique_number; + int num; +#endif + + memset( tbl, 0, tbl_len ); + +#if AES_SCA_CM_ROUNDS != 0 + // Randomize SCA CM positions to tbl + for ( i = 0; i < AES_SCA_CM_ROUNDS; i++ ) + { + do { + is_unique_number = 1; +/* TODO - Use proper random. This is now ONLY FOR TESTING as mbedtls_platform_random_in_range is alwyays returning 0 */ + num = /* mbedtls_platform_random_in_range( tbl_len - 1 ) */rand() % (tbl_len - 2); + + if ( tbl[num] == 0 ) + { + is_unique_number = 0; + tbl[num] = 0x10; + } + } while ( is_unique_number == 1 ); + } + + // Fill start/final round control data + if ( AES_SCA_CM_ROUNDS != 0 ) + { + num = /* mbedtls_platform_random_in_range( tbl_len - 1 ) */rand() % 0xff; + if ( ( num % 2 ) == 0 ) + { + tbl[tbl_len - 2] = 0x10; + tbl[tbl_len - 1] = 0x0; + } + else + { + tbl[tbl_len - 2] = 0x00; + tbl[tbl_len - 1] = 0x10; + } + } +#endif /* AES_SCA_CM_ROUNDS != 0 */ + + // Fill real AES round data to the remaining places + is_even_pos = 1; + for ( i = 0; i < tbl_len - 2; i++ ) + { + if ( tbl[i] == 0 ) + { + if ( is_even_pos == 1 ) + { + tbl[i] = 0x04; // real data, offset 0 + is_even_pos = 0; + } + else + { + tbl[i] = 0x00; // real data, offset 0 + is_even_pos = 1; + } + } + } +} + #if defined(MBEDTLS_AES_FEWER_TABLES) #define ROTL8(x) ( (uint32_t)( ( x ) << 8 ) + (uint32_t)( ( x ) >> 24 ) ) @@ -527,57 +617,6 @@ static void aes_gen_tables( void ) #endif /* MBEDTLS_AES_FEWER_TABLES */ -#if defined(MBEDTLS_AES_SCA_COUNTERMEASURES) -/* - * SCA CM table position check - */ -#define SCA_CM_TBL_MATCH(tbl, n) ( tbl[0] == ( n ) || \ - tbl[1] == ( n ) || \ - tbl[2] == ( n ) ) - -/* - * SCA CM always true check - */ -#define SCA_CM_ALWAYS_TRUE(tbl, n) ( tbl[0] != ( n ) || \ - tbl[1] != ( n ) || \ - tbl[2] != tbl[0] ) -/* - * Number of SCA CM dummy rounds. - */ -#define SCA_CM_DUMMY_ROUND_COUNT 3 - -#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ - -#if defined(MBEDTLS_AES_SCA_COUNTERMEASURES) -static void aes_sca_rand_tbl_fill( uint8_t *tbl, uint8_t tbl_len, uint8_t max_num ) -{ - int i, j, is_unique_number; - uint8_t *cur_num; - uint8_t num; - - cur_num = tbl; - - for ( i = 0; i < tbl_len; i++ ) - { - do { - is_unique_number = 1; - num = mbedtls_platform_random_in_range( max_num + 1 ); - - for ( j = 0; j < i; j++ ) - { - if ( num == tbl[j] ) - { - is_unique_number = 0; - break; - } - } - } while ( is_unique_number == 0 ); - - *cur_num++ = num; - } -} -#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ - void mbedtls_aes_init( mbedtls_aes_context *ctx ) { AES_VALIDATE( ctx != NULL ); @@ -889,28 +928,28 @@ int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, #endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ -#define AES_FROUND(R,X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ - do \ - { \ - (X0) = *(R)++ ^ AES_FT0( ( (Y0) ) & 0xFF ) ^ \ - AES_FT1( ( (Y1) >> 8 ) & 0xFF ) ^ \ - AES_FT2( ( (Y2) >> 16 ) & 0xFF ) ^ \ - AES_FT3( ( (Y3) >> 24 ) & 0xFF ); \ - \ - (X1) = *(R)++ ^ AES_FT0( ( (Y1) ) & 0xFF ) ^ \ - AES_FT1( ( (Y2) >> 8 ) & 0xFF ) ^ \ - AES_FT2( ( (Y3) >> 16 ) & 0xFF ) ^ \ - AES_FT3( ( (Y0) >> 24 ) & 0xFF ); \ - \ - (X2) = *(R)++ ^ AES_FT0( ( (Y2) ) & 0xFF ) ^ \ - AES_FT1( ( (Y3) >> 8 ) & 0xFF ) ^ \ - AES_FT2( ( (Y0) >> 16 ) & 0xFF ) ^ \ - AES_FT3( ( (Y1) >> 24 ) & 0xFF ); \ - \ - (X3) = *(R)++ ^ AES_FT0( ( (Y3) ) & 0xFF ) ^ \ - AES_FT1( ( (Y0) >> 8 ) & 0xFF ) ^ \ - AES_FT2( ( (Y1) >> 16 ) & 0xFF ) ^ \ - AES_FT3( ( (Y2) >> 24 ) & 0xFF ); \ +#define AES_FROUND(R,X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + do \ + { \ + (X0) = *(R)++ ^ AES_FT0( ( (Y0) ) & 0xFF ) ^ \ + AES_FT1( ( (Y1) >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( (Y2) >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( (Y3) >> 24 ) & 0xFF ); \ + \ + (X1) = *(R)++ ^ AES_FT0( ( (Y1) ) & 0xFF ) ^ \ + AES_FT1( ( (Y2) >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( (Y3) >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( (Y0) >> 24 ) & 0xFF ); \ + \ + (X2) = *(R)++ ^ AES_FT0( ( (Y2) ) & 0xFF ) ^ \ + AES_FT1( ( (Y3) >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( (Y0) >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( (Y1) >> 24 ) & 0xFF ); \ + \ + (X3) = *(R)++ ^ AES_FT0( ( (Y3) ) & 0xFF ) ^ \ + AES_FT1( ( (Y0) >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( (Y1) >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( (Y2) >> 24 ) & 0xFF ); \ } while( 0 ) #define AES_FROUND_F(R,X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ @@ -936,33 +975,34 @@ int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, ( (uint32_t) FSb[ ( (Y2) >> 24 ) & 0xFF ] << 24 ); \ } while ( 0 ) -#define AES_RROUND(R,X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ - do \ - { \ - (X0) = *(R)++ ^ AES_RT0( ( (Y0) ) & 0xFF ) ^ \ - AES_RT1( ( (Y3) >> 8 ) & 0xFF ) ^ \ - AES_RT2( ( (Y2) >> 16 ) & 0xFF ) ^ \ - AES_RT3( ( (Y1) >> 24 ) & 0xFF ); \ - \ - (X1) = *(R)++ ^ AES_RT0( ( (Y1) ) & 0xFF ) ^ \ - AES_RT1( ( (Y0) >> 8 ) & 0xFF ) ^ \ - AES_RT2( ( (Y3) >> 16 ) & 0xFF ) ^ \ - AES_RT3( ( (Y2) >> 24 ) & 0xFF ); \ - \ - (X2) = *(R)++ ^ AES_RT0( ( (Y2) ) & 0xFF ) ^ \ - AES_RT1( ( (Y1) >> 8 ) & 0xFF ) ^ \ - AES_RT2( ( (Y0) >> 16 ) & 0xFF ) ^ \ - AES_RT3( ( (Y3) >> 24 ) & 0xFF ); \ - \ - (X3) = *(R)++ ^ AES_RT0( ( (Y3) ) & 0xFF ) ^ \ - AES_RT1( ( (Y2) >> 8 ) & 0xFF ) ^ \ - AES_RT2( ( (Y1) >> 16 ) & 0xFF ) ^ \ - AES_RT3( ( (Y0) >> 24 ) & 0xFF ); \ + +#define AES_RROUND(R,X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + do \ + { \ + (X0) = *(R)++ ^ AES_RT0( ( (Y0) ) & 0xFF ) ^ \ + AES_RT1( ( (Y3) >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( (Y2) >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( (Y1) >> 24 ) & 0xFF ); \ + \ + (X1) = *(R)++ ^ AES_RT0( ( (Y1) ) & 0xFF ) ^ \ + AES_RT1( ( (Y0) >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( (Y3) >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( (Y2) >> 24 ) & 0xFF ); \ + \ + (X2) = *(R)++ ^ AES_RT0( ( (Y2) ) & 0xFF ) ^ \ + AES_RT1( ( (Y1) >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( (Y0) >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( (Y3) >> 24 ) & 0xFF ); \ + \ + (X3) = *(R)++ ^ AES_RT0( ( (Y3) ) & 0xFF ) ^ \ + AES_RT1( ( (Y2) >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( (Y1) >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( (Y0) >> 24 ) & 0xFF ); \ } while( 0 ) -#define AES_RROUND_F(R,X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ - do \ - { \ +#define AES_RROUND_F(R,X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ + do \ + { \ (X0) = *(R)++ ^ ( (uint32_t) RSb[ ( (Y0) ) & 0xFF ] ) ^ \ ( (uint32_t) RSb[ ( (Y3) >> 8 ) & 0xFF ] << 8 ) ^ \ ( (uint32_t) RSb[ ( (Y2) >> 16 ) & 0xFF ] << 16 ) ^ \ @@ -992,88 +1032,76 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) { - int i; - uint32_t *RK, X0, X1, X2, X3, Y0 = 0, Y1 = 0, Y2 = 0, Y3 = 0; + int i, j, offset, start_fin_loops = 1; + aes_r_data_t aes_data_real; // real data +#if AES_SCA_CM_ROUNDS != 0 + aes_r_data_t aes_data_fake; // fake data +#endif /* AES_SCA_CM_ROUNDS != 0 */ + aes_r_data_t *aes_data_ptr; // pointer to aes_data_real or aes_data_fake + aes_r_data_t *aes_data_table[2]; // pointers to real and fake data + int round_ctrl_table_len = ctx->nr - 1 + AES_SCA_CM_ROUNDS + 2; + // control bytes for AES rounds, reserve based on max ctx->nr + uint8_t round_ctrl_table[ 14 - 1 + AES_SCA_CM_ROUNDS + 2 ]; -#ifdef MBEDTLS_AES_SCA_COUNTERMEASURES - uint32_t *RK_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA; - uint8_t sca_cm_pos_tbl[SCA_CM_DUMMY_ROUND_COUNT]; // position for SCA countermeasure dummy rounds, not in any order + aes_data_real.rk_ptr = ctx->rk; + aes_data_table[0] = &aes_data_real; - aes_sca_rand_tbl_fill( sca_cm_pos_tbl, SCA_CM_DUMMY_ROUND_COUNT, ctx->nr ); - - X0_SCA = mbedtls_platform_random_in_range( 0xffffffff ); - X1_SCA = mbedtls_platform_random_in_range( 0xffffffff ); - X2_SCA = mbedtls_platform_random_in_range( 0xffffffff ); - X3_SCA = mbedtls_platform_random_in_range( 0xffffffff ); -#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ - - RK = ctx->rk; - -#ifdef MBEDTLS_AES_SCA_COUNTERMEASURES - RK_SCA = RK; - - if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, ctx->nr ) ) - { - /* LE conversions to Xn, Xn_SCA randomized */ - GET_UINT32_LE( X0, input, 0 ); X0_SCA ^= *RK_SCA++; - GET_UINT32_LE( X1, input, 4 ); X1_SCA ^= *RK_SCA++; - GET_UINT32_LE( X2, input, 8 ); X2_SCA ^= *RK_SCA++; - GET_UINT32_LE( X3, input, 12 ); X3_SCA ^= *RK_SCA++; - } -#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ - GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; - GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; - GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; - GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; - - for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) - { -#ifdef MBEDTLS_AES_SCA_COUNTERMEASURES - // Would random delay before each round be necessary? - // - if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, i * 2 ) ) - AES_FROUND( RK_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA, - X0_SCA, X1_SCA, X2_SCA, X3_SCA ); - - if ( SCA_CM_ALWAYS_TRUE( sca_cm_pos_tbl, i* 2 ) ) - AES_FROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - - if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, i * 2 + 1 ) ) - AES_FROUND( RK_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA, - Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA); - - if ( SCA_CM_ALWAYS_TRUE( sca_cm_pos_tbl, i * 2 + 1 ) ) - AES_FROUND( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); -#else /* MBEDTLS_AES_SCA_COUNTERMEASURES */ - AES_FROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - AES_FROUND( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); -#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ - } - -#ifdef MBEDTLS_AES_SCA_COUNTERMEASURES - if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, 1 ) ) - AES_FROUND( RK_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA, - X0_SCA, X1_SCA, X2_SCA, X3_SCA ); - - if ( SCA_CM_ALWAYS_TRUE ( sca_cm_pos_tbl, 1 ) ) - AES_FROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - - if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, 0 ) ) - AES_FROUND_F( RK_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA, - Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA ); - - if ( SCA_CM_ALWAYS_TRUE ( sca_cm_pos_tbl, 0 ) ) - AES_FROUND_F( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); - -#else - AES_FROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - AES_FROUND_F( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); +#if AES_SCA_CM_ROUNDS != 0 + aes_data_table[1] = &aes_data_fake; + aes_data_fake.rk_ptr = ctx->rk; + start_fin_loops = 2; + for (i = 0; i < 4; i++ ) + aes_data_fake.xy_values[i] = mbedtls_platform_random_in_range( 0xffffffff ); #endif - PUT_UINT32_LE( X0, output, 0 ); - PUT_UINT32_LE( X1, output, 4 ); - PUT_UINT32_LE( X2, output, 8 ); - PUT_UINT32_LE( X3, output, 12 ); + // Get randomized AES calculation control bytes + aes_sca_cm_data_randomize( round_ctrl_table, round_ctrl_table_len ); + + for (i = 0; i < 4; i++ ) + { + GET_UINT32_LE( aes_data_real.xy_values[i], input, ( i * 4 ) ); + for (j = 0; j < start_fin_loops; j++ ) + { + aes_data_ptr = aes_data_table[round_ctrl_table[ round_ctrl_table_len - 2 + j ] >> 4]; + aes_data_ptr->xy_values[i] ^= *aes_data_ptr->rk_ptr++; + } + } + + for( i = 0; i < ( ctx->nr - 1 + AES_SCA_CM_ROUNDS ); i++ ) + { + // Read AES control data + aes_data_ptr = aes_data_table[round_ctrl_table[i] >> 4]; + offset = round_ctrl_table[i] & 0x0f; + + AES_FROUND( aes_data_ptr->rk_ptr, + aes_data_ptr->xy_values[0 + offset], + aes_data_ptr->xy_values[1 + offset], + aes_data_ptr->xy_values[2 + offset], + aes_data_ptr->xy_values[3 + offset], + aes_data_ptr->xy_values[4 - offset], + aes_data_ptr->xy_values[5 - offset], + aes_data_ptr->xy_values[6 - offset], + aes_data_ptr->xy_values[7 - offset] ); + } + + for ( j = 0; j < start_fin_loops; j++ ) + { + aes_data_ptr = aes_data_table[round_ctrl_table[ i + j ] >> 4]; + AES_FROUND_F( aes_data_ptr->rk_ptr, + aes_data_ptr->xy_values[0], + aes_data_ptr->xy_values[1], + aes_data_ptr->xy_values[2], + aes_data_ptr->xy_values[3], + aes_data_ptr->xy_values[4], + aes_data_ptr->xy_values[5], + aes_data_ptr->xy_values[6], + aes_data_ptr->xy_values[7] ); + } + + for ( i = 0; i < 4; i++ ) + { + PUT_UINT32_LE( aes_data_real.xy_values[i], output, ( i * 4 ) ); + } return( 0 ); } @@ -1098,95 +1126,76 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) { - int i; - uint32_t *RK, X0, X1, X2, X3, Y0 = 0, Y1 = 0, Y2 = 0, Y3 = 0; + int i, j, offset, start_fin_loops = 1; + aes_r_data_t aes_data_real; // real data +#if AES_SCA_CM_ROUNDS != 0 + aes_r_data_t aes_data_fake; // fake data +#endif /* AES_SCA_CM_ROUNDS != 0 */ + aes_r_data_t *aes_data_ptr; // pointer to aes_data_real or aes_data_fake + aes_r_data_t *aes_data_table[2]; // pointers to real and fake data + int round_ctrl_table_len = ctx->nr - 1 + AES_SCA_CM_ROUNDS + 2; + // control bytes for AES rounds, reserve based on max ctx->nr + uint8_t round_ctrl_table[ 14 - 1 + AES_SCA_CM_ROUNDS + 2 ]; -#ifdef MBEDTLS_AES_SCA_COUNTERMEASURES - uint32_t *RK_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA; - uint8_t sca_cm_pos_tbl[SCA_CM_DUMMY_ROUND_COUNT]; // position for SCA countermeasure dummy rounds, not in any order + aes_data_real.rk_ptr = ctx->rk; + aes_data_table[0] = &aes_data_real; - aes_sca_rand_tbl_fill( sca_cm_pos_tbl, SCA_CM_DUMMY_ROUND_COUNT, ctx->nr ); +#if AES_SCA_CM_ROUNDS != 0 + aes_data_table[1] = &aes_data_fake; + aes_data_fake.rk_ptr = ctx->rk; + start_fin_loops = 2; + for (i = 0; i < 4; i++ ) + aes_data_fake.xy_values[i] = mbedtls_platform_random_in_range( 0xffffffff ); +#endif - X0_SCA = mbedtls_platform_random_in_range( 0xffffffff ); - X1_SCA = mbedtls_platform_random_in_range( 0xffffffff ); - X2_SCA = mbedtls_platform_random_in_range( 0xffffffff ); - X3_SCA = mbedtls_platform_random_in_range( 0xffffffff ); -#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ + // Get randomized AES calculation control bytes + aes_sca_cm_data_randomize( round_ctrl_table, round_ctrl_table_len ); - RK = ctx->rk; - -#ifdef MBEDTLS_AES_SCA_COUNTERMEASURES - RK_SCA = RK; - if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, ctx->nr ) ) + for (i = 0; i < 4; i++ ) { - GET_UINT32_LE( X0, input, 0 ); X0_SCA ^= *RK_SCA++; - GET_UINT32_LE( X1, input, 4 ); X1_SCA ^= *RK_SCA++; - GET_UINT32_LE( X2, input, 8 ); X2_SCA ^= *RK_SCA++; - GET_UINT32_LE( X3, input, 12 ); X3_SCA ^= *RK_SCA++; + GET_UINT32_LE( aes_data_real.xy_values[i], input, ( i * 4 ) ); + for (j = 0; j < start_fin_loops; j++ ) + { + aes_data_ptr = aes_data_table[round_ctrl_table[ round_ctrl_table_len - 2 + j ] >> 4]; + aes_data_ptr->xy_values[i] ^= *aes_data_ptr->rk_ptr++; + } } - if ( SCA_CM_ALWAYS_TRUE( sca_cm_pos_tbl, ctx->nr ) ) + for( i = 0; i < ( ctx->nr - 1 + AES_SCA_CM_ROUNDS ); i++ ) { - GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; - GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; - GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; - GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; - } -#else /* MBEDTLS_AES_SCA_COUNTERMEASURES */ - GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; - GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; - GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; - GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; -#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ + // Read AES control data + aes_data_ptr = aes_data_table[round_ctrl_table[i] >> 4]; + offset = round_ctrl_table[i] & 0x0f; - for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) - { -#ifdef MBEDTLS_AES_SCA_COUNTERMEASURES - // Would random delay before each round be necessary? - // - if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, i * 2 ) ) - AES_RROUND( RK_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA, - X0_SCA, X1_SCA, X2_SCA, X3_SCA ); - - if ( SCA_CM_ALWAYS_TRUE( sca_cm_pos_tbl, i* 2 ) ) - AES_RROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - - if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, i * 2 + 1 ) ) - AES_RROUND( RK_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA, - Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA); - - if ( SCA_CM_ALWAYS_TRUE( sca_cm_pos_tbl, i * 2 + 1 ) ) - AES_RROUND( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); -#else /* MBEDTLS_AES_SCA_COUNTERMEASURES */ - AES_RROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - AES_RROUND( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); -#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ + AES_RROUND( aes_data_ptr->rk_ptr, + aes_data_ptr->xy_values[0 + offset], + aes_data_ptr->xy_values[1 + offset], + aes_data_ptr->xy_values[2 + offset], + aes_data_ptr->xy_values[3 + offset], + aes_data_ptr->xy_values[4 - offset], + aes_data_ptr->xy_values[5 - offset], + aes_data_ptr->xy_values[6 - offset], + aes_data_ptr->xy_values[7 - offset] ); } -#ifdef MBEDTLS_AES_SCA_COUNTERMEASURES - if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, 1 ) ) - AES_RROUND( RK_SCA, Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA, - X0_SCA, X1_SCA, X2_SCA, X3_SCA ); + for ( j = 0; j < start_fin_loops; j++ ) + { + aes_data_ptr = aes_data_table[round_ctrl_table[ i + j ] >> 4]; + AES_RROUND_F( aes_data_ptr->rk_ptr, + aes_data_ptr->xy_values[0], + aes_data_ptr->xy_values[1], + aes_data_ptr->xy_values[2], + aes_data_ptr->xy_values[3], + aes_data_ptr->xy_values[4], + aes_data_ptr->xy_values[5], + aes_data_ptr->xy_values[6], + aes_data_ptr->xy_values[7] ); + } - if ( SCA_CM_ALWAYS_TRUE ( sca_cm_pos_tbl, 1 ) ) - AES_RROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - - if ( SCA_CM_TBL_MATCH( sca_cm_pos_tbl, 0 ) ) - AES_RROUND_F( RK_SCA, X0_SCA, X1_SCA, X2_SCA, X3_SCA, - Y0_SCA, Y1_SCA, Y2_SCA, Y3_SCA ); - - if ( SCA_CM_ALWAYS_TRUE ( sca_cm_pos_tbl, 0 ) ) - AES_RROUND_F( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); - -#else /* MBEDTLS_AES_SCA_COUNTERMEASURES */ - AES_RROUND( RK, Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - AES_RROUND_F( RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); -#endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ - - PUT_UINT32_LE( X0, output, 0 ); - PUT_UINT32_LE( X1, output, 4 ); - PUT_UINT32_LE( X2, output, 8 ); - PUT_UINT32_LE( X3, output, 12 ); + for ( i = 0; i < 4; i++ ) + { + PUT_UINT32_LE( aes_data_real.xy_values[i], output, ( i * 4 ) ); + } return( 0 ); } From c3532c233906d956ca56affd75c19d65df7a2350 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Fri, 29 Nov 2019 15:07:11 +0200 Subject: [PATCH 08/14] Improve SCA CM AES performance SCA CM implementation caused AES performance drop. For example AES-CCM-128 calculation speed was dropped from 240 KB/s to 111 KB/s. (-54%), Similarily AES-CBC-128 calculation speed was dropped from 536 KB/s to 237 KB/s (-56%). Use functions instead of macros to reduce code indirections and therefore increase performance. Now the performance is 163 KB/s for AES-CCM-128 (-32%) and 348 KB/s for AES-CBC-128 (-35%). When SCA countermeasures are activated the performance is as follows: 122 KB/s for AES-CCM-128 (-49%) and 258 KB/s for AES-CBC-128 (-52%) compared to the original AES implementation. --- library/aes.c | 241 ++++++++++++++++++++++++++------------------------ 1 file changed, 125 insertions(+), 116 deletions(-) diff --git a/library/aes.c b/library/aes.c index 4dacd6417..9c5c1697a 100644 --- a/library/aes.c +++ b/library/aes.c @@ -928,106 +928,63 @@ int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, #endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ -#define AES_FROUND(R,X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ - do \ - { \ - (X0) = *(R)++ ^ AES_FT0( ( (Y0) ) & 0xFF ) ^ \ - AES_FT1( ( (Y1) >> 8 ) & 0xFF ) ^ \ - AES_FT2( ( (Y2) >> 16 ) & 0xFF ) ^ \ - AES_FT3( ( (Y3) >> 24 ) & 0xFF ); \ - \ - (X1) = *(R)++ ^ AES_FT0( ( (Y1) ) & 0xFF ) ^ \ - AES_FT1( ( (Y2) >> 8 ) & 0xFF ) ^ \ - AES_FT2( ( (Y3) >> 16 ) & 0xFF ) ^ \ - AES_FT3( ( (Y0) >> 24 ) & 0xFF ); \ - \ - (X2) = *(R)++ ^ AES_FT0( ( (Y2) ) & 0xFF ) ^ \ - AES_FT1( ( (Y3) >> 8 ) & 0xFF ) ^ \ - AES_FT2( ( (Y0) >> 16 ) & 0xFF ) ^ \ - AES_FT3( ( (Y1) >> 24 ) & 0xFF ); \ - \ - (X3) = *(R)++ ^ AES_FT0( ( (Y3) ) & 0xFF ) ^ \ - AES_FT1( ( (Y0) >> 8 ) & 0xFF ) ^ \ - AES_FT2( ( (Y1) >> 16 ) & 0xFF ) ^ \ - AES_FT3( ( (Y2) >> 24 ) & 0xFF ); \ - } while( 0 ) - -#define AES_FROUND_F(R,X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ - do { \ - (X0) = *(R)++ ^ ( (uint32_t) FSb[ ( (Y0) ) & 0xFF ] ) ^ \ - ( (uint32_t) FSb[ ( (Y1) >> 8 ) & 0xFF ] << 8 ) ^ \ - ( (uint32_t) FSb[ ( (Y2) >> 16 ) & 0xFF ] << 16 ) ^ \ - ( (uint32_t) FSb[ ( (Y3) >> 24 ) & 0xFF ] << 24 ); \ - \ - (X1) = *(R)++ ^ ( (uint32_t) FSb[ ( (Y1) ) & 0xFF ] ) ^ \ - ( (uint32_t) FSb[ ( (Y2) >> 8 ) & 0xFF ] << 8 ) ^ \ - ( (uint32_t) FSb[ ( (Y3) >> 16 ) & 0xFF ] << 16 ) ^ \ - ( (uint32_t) FSb[ ( (Y0) >> 24 ) & 0xFF ] << 24 ); \ - \ - (X2) = *(R)++ ^ ( (uint32_t) FSb[ ( (Y2) ) & 0xFF ] ) ^ \ - ( (uint32_t) FSb[ ( (Y3) >> 8 ) & 0xFF ] << 8 ) ^ \ - ( (uint32_t) FSb[ ( (Y0) >> 16 ) & 0xFF ] << 16 ) ^ \ - ( (uint32_t) FSb[ ( (Y1) >> 24 ) & 0xFF ] << 24 ); \ - \ - (X3) = *(R)++ ^ ( (uint32_t) FSb[ ( (Y3) ) & 0xFF ] ) ^ \ - ( (uint32_t) FSb[ ( (Y0) >> 8 ) & 0xFF ] << 8 ) ^ \ - ( (uint32_t) FSb[ ( (Y1) >> 16 ) & 0xFF ] << 16 ) ^ \ - ( (uint32_t) FSb[ ( (Y2) >> 24 ) & 0xFF ] << 24 ); \ - } while ( 0 ) - - -#define AES_RROUND(R,X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ - do \ - { \ - (X0) = *(R)++ ^ AES_RT0( ( (Y0) ) & 0xFF ) ^ \ - AES_RT1( ( (Y3) >> 8 ) & 0xFF ) ^ \ - AES_RT2( ( (Y2) >> 16 ) & 0xFF ) ^ \ - AES_RT3( ( (Y1) >> 24 ) & 0xFF ); \ - \ - (X1) = *(R)++ ^ AES_RT0( ( (Y1) ) & 0xFF ) ^ \ - AES_RT1( ( (Y0) >> 8 ) & 0xFF ) ^ \ - AES_RT2( ( (Y3) >> 16 ) & 0xFF ) ^ \ - AES_RT3( ( (Y2) >> 24 ) & 0xFF ); \ - \ - (X2) = *(R)++ ^ AES_RT0( ( (Y2) ) & 0xFF ) ^ \ - AES_RT1( ( (Y1) >> 8 ) & 0xFF ) ^ \ - AES_RT2( ( (Y0) >> 16 ) & 0xFF ) ^ \ - AES_RT3( ( (Y3) >> 24 ) & 0xFF ); \ - \ - (X3) = *(R)++ ^ AES_RT0( ( (Y3) ) & 0xFF ) ^ \ - AES_RT1( ( (Y2) >> 8 ) & 0xFF ) ^ \ - AES_RT2( ( (Y1) >> 16 ) & 0xFF ) ^ \ - AES_RT3( ( (Y0) >> 24 ) & 0xFF ); \ - } while( 0 ) - -#define AES_RROUND_F(R,X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ - do \ - { \ - (X0) = *(R)++ ^ ( (uint32_t) RSb[ ( (Y0) ) & 0xFF ] ) ^ \ - ( (uint32_t) RSb[ ( (Y3) >> 8 ) & 0xFF ] << 8 ) ^ \ - ( (uint32_t) RSb[ ( (Y2) >> 16 ) & 0xFF ] << 16 ) ^ \ - ( (uint32_t) RSb[ ( (Y1) >> 24 ) & 0xFF ] << 24 ); \ - \ - (X1) = *(R)++ ^ ( (uint32_t) RSb[ ( (Y1) ) & 0xFF ] ) ^ \ - ( (uint32_t) RSb[ ( (Y0) >> 8 ) & 0xFF ] << 8 ) ^ \ - ( (uint32_t) RSb[ ( (Y3) >> 16 ) & 0xFF ] << 16 ) ^ \ - ( (uint32_t) RSb[ ( (Y2) >> 24 ) & 0xFF ] << 24 ); \ - \ - (X2) = *(R)++ ^ ( (uint32_t) RSb[ ( (Y2) ) & 0xFF ] ) ^ \ - ( (uint32_t) RSb[ ( (Y1) >> 8 ) & 0xFF ] << 8 ) ^ \ - ( (uint32_t) RSb[ ( (Y0) >> 16 ) & 0xFF ] << 16 ) ^ \ - ( (uint32_t) RSb[ ( (Y3) >> 24 ) & 0xFF ] << 24 ); \ - \ - (X3) = *(R)++ ^ ( (uint32_t) RSb[ ( (Y3) ) & 0xFF ] ) ^ \ - ( (uint32_t) RSb[ ( (Y2) >> 8 ) & 0xFF ] << 8 ) ^ \ - ( (uint32_t) RSb[ ( (Y1) >> 16 ) & 0xFF ] << 16 ) ^ \ - ( (uint32_t) RSb[ ( (Y0) >> 24 ) & 0xFF ] << 24 ); \ - } while( 0 ) - /* * AES-ECB block encryption */ #if !defined(MBEDTLS_AES_ENCRYPT_ALT) + +static uint32_t *aes_fround( uint32_t *R, + uint32_t *X0, uint32_t *X1, uint32_t *X2, uint32_t *X3, + uint32_t Y0, uint32_t Y1, uint32_t Y2, uint32_t Y3 ) +{ + *X0 = *R++ ^ AES_FT0( ( Y0 ) & 0xFF ) ^ + AES_FT1( ( Y1 >> 8 ) & 0xFF ) ^ + AES_FT2( ( Y2 >> 16 ) & 0xFF ) ^ + AES_FT3( ( Y3 >> 24 ) & 0xFF ); + + *X1 = *R++ ^ AES_FT0( ( Y1 ) & 0xFF ) ^ + AES_FT1( ( Y2 >> 8 ) & 0xFF ) ^ + AES_FT2( ( Y3 >> 16 ) & 0xFF ) ^ + AES_FT3( ( Y0 >> 24 ) & 0xFF ); + + *X2 = *R++ ^ AES_FT0( ( Y2 ) & 0xFF ) ^ + AES_FT1( ( Y3 >> 8 ) & 0xFF ) ^ + AES_FT2( ( Y0 >> 16 ) & 0xFF ) ^ + AES_FT3( ( Y1 >> 24 ) & 0xFF ); + + *X3 = *R++ ^ AES_FT0( ( Y3 ) & 0xFF ) ^ + AES_FT1( ( Y0 >> 8 ) & 0xFF ) ^ + AES_FT2( ( Y1 >> 16 ) & 0xFF ) ^ + AES_FT3( ( Y2 >> 24 ) & 0xFF ); + + return R; +} + +static void aes_fround_final( uint32_t *R, + uint32_t *X0, uint32_t *X1, uint32_t *X2, uint32_t *X3, + uint32_t Y0, uint32_t Y1, uint32_t Y2, uint32_t Y3 ) +{ + *X0 = *R++ ^ ( (uint32_t) FSb[ ( (Y0) ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( (Y1) >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( (Y2) >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( (Y3) >> 24 ) & 0xFF ] << 24 ); + + *X1 = *R++ ^ ( (uint32_t) FSb[ ( (Y1) ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( (Y2) >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( (Y3) >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( (Y0) >> 24 ) & 0xFF ] << 24 ); + + *X2 = *R++ ^ ( (uint32_t) FSb[ ( (Y2) ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( (Y3) >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( (Y0) >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( (Y1) >> 24 ) & 0xFF ] << 24 ); + + *X3 = *R++ ^ ( (uint32_t) FSb[ ( (Y3) ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( (Y0) >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( (Y1) >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( (Y2) >> 24 ) & 0xFF ] << 24 ); +} + int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) @@ -1073,11 +1030,11 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, aes_data_ptr = aes_data_table[round_ctrl_table[i] >> 4]; offset = round_ctrl_table[i] & 0x0f; - AES_FROUND( aes_data_ptr->rk_ptr, - aes_data_ptr->xy_values[0 + offset], - aes_data_ptr->xy_values[1 + offset], - aes_data_ptr->xy_values[2 + offset], - aes_data_ptr->xy_values[3 + offset], + aes_data_ptr->rk_ptr = aes_fround( aes_data_ptr->rk_ptr, + &aes_data_ptr->xy_values[0 + offset], + &aes_data_ptr->xy_values[1 + offset], + &aes_data_ptr->xy_values[2 + offset], + &aes_data_ptr->xy_values[3 + offset], aes_data_ptr->xy_values[4 - offset], aes_data_ptr->xy_values[5 - offset], aes_data_ptr->xy_values[6 - offset], @@ -1087,11 +1044,11 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, for ( j = 0; j < start_fin_loops; j++ ) { aes_data_ptr = aes_data_table[round_ctrl_table[ i + j ] >> 4]; - AES_FROUND_F( aes_data_ptr->rk_ptr, - aes_data_ptr->xy_values[0], - aes_data_ptr->xy_values[1], - aes_data_ptr->xy_values[2], - aes_data_ptr->xy_values[3], + aes_fround_final( aes_data_ptr->rk_ptr, + &aes_data_ptr->xy_values[0], + &aes_data_ptr->xy_values[1], + &aes_data_ptr->xy_values[2], + &aes_data_ptr->xy_values[3], aes_data_ptr->xy_values[4], aes_data_ptr->xy_values[5], aes_data_ptr->xy_values[6], @@ -1122,6 +1079,58 @@ void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, #if !defined(MBEDTLS_AES_DECRYPT_ALT) #if !defined(MBEDTLS_AES_ONLY_ENCRYPT) + +static uint32_t *aes_rround( uint32_t *R, + uint32_t *X0, uint32_t *X1, uint32_t *X2, uint32_t *X3, + uint32_t Y0, uint32_t Y1, uint32_t Y2, uint32_t Y3 ) +{ + *X0 = *R++ ^ AES_RT0( ( Y0 ) & 0xFF ) ^ + AES_RT1( ( Y3 >> 8 ) & 0xFF ) ^ + AES_RT2( ( Y2 >> 16 ) & 0xFF ) ^ + AES_RT3( ( Y1 >> 24 ) & 0xFF ); + + *X1 = *R++ ^ AES_RT0( ( Y1 ) & 0xFF ) ^ + AES_RT1( ( Y0 >> 8 ) & 0xFF ) ^ + AES_RT2( ( Y3 >> 16 ) & 0xFF ) ^ + AES_RT3( ( Y2 >> 24 ) & 0xFF ); + + *X2 = *R++ ^ AES_RT0( ( Y2 ) & 0xFF ) ^ + AES_RT1( ( Y1 >> 8 ) & 0xFF ) ^ + AES_RT2( ( Y0 >> 16 ) & 0xFF ) ^ + AES_RT3( ( Y3 >> 24 ) & 0xFF ); + + *X3 = *R++ ^ AES_RT0( ( Y3 ) & 0xFF ) ^ + AES_RT1( ( Y2 >> 8 ) & 0xFF ) ^ + AES_RT2( ( Y1 >> 16 ) & 0xFF ) ^ + AES_RT3( ( Y0 >> 24 ) & 0xFF ); + return R; +} + +static void aes_rround_final( uint32_t *R, + uint32_t *X0, uint32_t *X1, uint32_t *X2, uint32_t *X3, + uint32_t Y0, uint32_t Y1, uint32_t Y2, uint32_t Y3 ) +{ + *X0 = *R++ ^ ( (uint32_t) RSb[ ( (Y0) ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( (Y3) >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( (Y2) >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( (Y1) >> 24 ) & 0xFF ] << 24 ); + + *X1 = *R++ ^ ( (uint32_t) RSb[ ( (Y1) ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( (Y0) >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( (Y3) >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( (Y2) >> 24 ) & 0xFF ] << 24 ); + + *X2 = *R++ ^ ( (uint32_t) RSb[ ( (Y2) ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( (Y1) >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( (Y0) >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( (Y3) >> 24 ) & 0xFF ] << 24 ); + + *X3 = *R++ ^ ( (uint32_t) RSb[ ( (Y3) ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( (Y2) >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( (Y1) >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( (Y0) >> 24 ) & 0xFF ] << 24 ); +} + int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) @@ -1167,11 +1176,11 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, aes_data_ptr = aes_data_table[round_ctrl_table[i] >> 4]; offset = round_ctrl_table[i] & 0x0f; - AES_RROUND( aes_data_ptr->rk_ptr, - aes_data_ptr->xy_values[0 + offset], - aes_data_ptr->xy_values[1 + offset], - aes_data_ptr->xy_values[2 + offset], - aes_data_ptr->xy_values[3 + offset], + aes_data_ptr->rk_ptr = aes_rround( aes_data_ptr->rk_ptr, + &aes_data_ptr->xy_values[0 + offset], + &aes_data_ptr->xy_values[1 + offset], + &aes_data_ptr->xy_values[2 + offset], + &aes_data_ptr->xy_values[3 + offset], aes_data_ptr->xy_values[4 - offset], aes_data_ptr->xy_values[5 - offset], aes_data_ptr->xy_values[6 - offset], @@ -1181,11 +1190,11 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, for ( j = 0; j < start_fin_loops; j++ ) { aes_data_ptr = aes_data_table[round_ctrl_table[ i + j ] >> 4]; - AES_RROUND_F( aes_data_ptr->rk_ptr, - aes_data_ptr->xy_values[0], - aes_data_ptr->xy_values[1], - aes_data_ptr->xy_values[2], - aes_data_ptr->xy_values[3], + aes_rround_final( aes_data_ptr->rk_ptr, + &aes_data_ptr->xy_values[0], + &aes_data_ptr->xy_values[1], + &aes_data_ptr->xy_values[2], + &aes_data_ptr->xy_values[3], aes_data_ptr->xy_values[4], aes_data_ptr->xy_values[5], aes_data_ptr->xy_values[6], From 425137a0faaf84a1be03943430a0cea6f88a98f1 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Fri, 29 Nov 2019 15:53:09 +0200 Subject: [PATCH 09/14] Follow Mbed TLS coding style -Fix multiple for clauses -Remove redundant check --- library/aes.c | 51 +++++++++++++++++++++++++-------------------------- 1 file changed, 25 insertions(+), 26 deletions(-) diff --git a/library/aes.c b/library/aes.c index 9c5c1697a..0f3524aa9 100644 --- a/library/aes.c +++ b/library/aes.c @@ -535,7 +535,7 @@ static void aes_sca_cm_data_randomize( uint8_t *tbl, uint8_t tbl_len ) #if AES_SCA_CM_ROUNDS != 0 // Randomize SCA CM positions to tbl - for ( i = 0; i < AES_SCA_CM_ROUNDS; i++ ) + for( i = 0; i < AES_SCA_CM_ROUNDS; i++ ) { do { is_unique_number = 1; @@ -551,25 +551,22 @@ static void aes_sca_cm_data_randomize( uint8_t *tbl, uint8_t tbl_len ) } // Fill start/final round control data - if ( AES_SCA_CM_ROUNDS != 0 ) + num = /* mbedtls_platform_random_in_range( tbl_len - 1 ) */rand() % 0xff; + if ( ( num % 2 ) == 0 ) { - num = /* mbedtls_platform_random_in_range( tbl_len - 1 ) */rand() % 0xff; - if ( ( num % 2 ) == 0 ) - { - tbl[tbl_len - 2] = 0x10; - tbl[tbl_len - 1] = 0x0; - } - else - { - tbl[tbl_len - 2] = 0x00; - tbl[tbl_len - 1] = 0x10; - } + tbl[tbl_len - 2] = 0x10; + tbl[tbl_len - 1] = 0x0; + } + else + { + tbl[tbl_len - 2] = 0x00; + tbl[tbl_len - 1] = 0x10; } #endif /* AES_SCA_CM_ROUNDS != 0 */ // Fill real AES round data to the remaining places is_even_pos = 1; - for ( i = 0; i < tbl_len - 2; i++ ) + for( i = 0; i < tbl_len - 2; i++ ) { if ( tbl[i] == 0 ) { @@ -1007,19 +1004,20 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, aes_data_table[1] = &aes_data_fake; aes_data_fake.rk_ptr = ctx->rk; start_fin_loops = 2; - for (i = 0; i < 4; i++ ) + for( i = 0; i < 4; i++ ) aes_data_fake.xy_values[i] = mbedtls_platform_random_in_range( 0xffffffff ); #endif // Get randomized AES calculation control bytes aes_sca_cm_data_randomize( round_ctrl_table, round_ctrl_table_len ); - for (i = 0; i < 4; i++ ) + for( i = 0; i < 4; i++ ) { GET_UINT32_LE( aes_data_real.xy_values[i], input, ( i * 4 ) ); - for (j = 0; j < start_fin_loops; j++ ) + for( j = 0; j < start_fin_loops; j++ ) { - aes_data_ptr = aes_data_table[round_ctrl_table[ round_ctrl_table_len - 2 + j ] >> 4]; + aes_data_ptr = + aes_data_table[round_ctrl_table[ round_ctrl_table_len - 2 + j ] >> 4]; aes_data_ptr->xy_values[i] ^= *aes_data_ptr->rk_ptr++; } } @@ -1041,7 +1039,7 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, aes_data_ptr->xy_values[7 - offset] ); } - for ( j = 0; j < start_fin_loops; j++ ) + for( j = 0; j < start_fin_loops; j++ ) { aes_data_ptr = aes_data_table[round_ctrl_table[ i + j ] >> 4]; aes_fround_final( aes_data_ptr->rk_ptr, @@ -1055,7 +1053,7 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, aes_data_ptr->xy_values[7] ); } - for ( i = 0; i < 4; i++ ) + for( i = 0; i < 4; i++ ) { PUT_UINT32_LE( aes_data_real.xy_values[i], output, ( i * 4 ) ); } @@ -1153,19 +1151,20 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, aes_data_table[1] = &aes_data_fake; aes_data_fake.rk_ptr = ctx->rk; start_fin_loops = 2; - for (i = 0; i < 4; i++ ) + for( i = 0; i < 4; i++ ) aes_data_fake.xy_values[i] = mbedtls_platform_random_in_range( 0xffffffff ); #endif // Get randomized AES calculation control bytes aes_sca_cm_data_randomize( round_ctrl_table, round_ctrl_table_len ); - for (i = 0; i < 4; i++ ) + for( i = 0; i < 4; i++ ) { GET_UINT32_LE( aes_data_real.xy_values[i], input, ( i * 4 ) ); - for (j = 0; j < start_fin_loops; j++ ) + for( j = 0; j < start_fin_loops; j++ ) { - aes_data_ptr = aes_data_table[round_ctrl_table[ round_ctrl_table_len - 2 + j ] >> 4]; + aes_data_ptr = + aes_data_table[round_ctrl_table[ round_ctrl_table_len - 2 + j ] >> 4]; aes_data_ptr->xy_values[i] ^= *aes_data_ptr->rk_ptr++; } } @@ -1187,7 +1186,7 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, aes_data_ptr->xy_values[7 - offset] ); } - for ( j = 0; j < start_fin_loops; j++ ) + for( j = 0; j < start_fin_loops; j++ ) { aes_data_ptr = aes_data_table[round_ctrl_table[ i + j ] >> 4]; aes_rround_final( aes_data_ptr->rk_ptr, @@ -1201,7 +1200,7 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, aes_data_ptr->xy_values[7] ); } - for ( i = 0; i < 4; i++ ) + for( i = 0; i < 4; i++ ) { PUT_UINT32_LE( aes_data_real.xy_values[i], output, ( i * 4 ) ); } From 7543901b6a471ef354ac19c0444fd94b21110eb7 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Tue, 3 Dec 2019 14:12:10 +0200 Subject: [PATCH 10/14] Follow Mbed TLS coding style Fix remaining if-clauses. --- library/aes.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/library/aes.c b/library/aes.c index 0f3524aa9..909b4c557 100644 --- a/library/aes.c +++ b/library/aes.c @@ -542,7 +542,7 @@ static void aes_sca_cm_data_randomize( uint8_t *tbl, uint8_t tbl_len ) /* TODO - Use proper random. This is now ONLY FOR TESTING as mbedtls_platform_random_in_range is alwyays returning 0 */ num = /* mbedtls_platform_random_in_range( tbl_len - 1 ) */rand() % (tbl_len - 2); - if ( tbl[num] == 0 ) + if( tbl[num] == 0 ) { is_unique_number = 0; tbl[num] = 0x10; @@ -552,7 +552,7 @@ static void aes_sca_cm_data_randomize( uint8_t *tbl, uint8_t tbl_len ) // Fill start/final round control data num = /* mbedtls_platform_random_in_range( tbl_len - 1 ) */rand() % 0xff; - if ( ( num % 2 ) == 0 ) + if( ( num % 2 ) == 0 ) { tbl[tbl_len - 2] = 0x10; tbl[tbl_len - 1] = 0x0; @@ -568,9 +568,9 @@ static void aes_sca_cm_data_randomize( uint8_t *tbl, uint8_t tbl_len ) is_even_pos = 1; for( i = 0; i < tbl_len - 2; i++ ) { - if ( tbl[i] == 0 ) + if( tbl[i] == 0 ) { - if ( is_even_pos == 1 ) + if( is_even_pos == 1 ) { tbl[i] = 0x04; // real data, offset 0 is_even_pos = 0; @@ -1674,7 +1674,7 @@ int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, n = *nc_off; - if ( n > 0x0F ) + if( n > 0x0F ) return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); while( length-- ) From be1bb06acd045d264dd94fdaf02b3405059611f9 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Tue, 3 Dec 2019 14:13:33 +0200 Subject: [PATCH 11/14] Enable AES countermeasures in baremetal config Enable AES countermeasures in baremetal configuration. --- configs/baremetal.h | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/baremetal.h b/configs/baremetal.h index 3d0fac564..52943515e 100644 --- a/configs/baremetal.h +++ b/configs/baremetal.h @@ -41,6 +41,7 @@ #define MBEDTLS_AES_FEWER_TABLES #define MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH #define MBEDTLS_AES_ONLY_ENCRYPT +#define MBEDTLS_AES_SCA_COUNTERMEASURES #define MBEDTLS_CCM_C /* Asymmetric crypto: Single-curve ECC only. */ From 34139ba9fc7f2d8c480bf7787238ad388121b6ff Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Tue, 3 Dec 2019 15:43:27 +0200 Subject: [PATCH 12/14] Updates to AES countermeasures -Update comments regarding flag MBEDTLS_AES_SCA_COUNTERMEASURES -Remove MBEDTLS_AES_SCA_COUNTERMEASURES dependency check -More comments and coding style changes --- include/mbedtls/check_config.h | 4 ---- include/mbedtls/config.h | 6 +++--- library/aes.c | 14 +++++++------- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h index 40647d570..fe9c5945e 100644 --- a/include/mbedtls/check_config.h +++ b/include/mbedtls/check_config.h @@ -70,10 +70,6 @@ #error "MBEDTLS_AESNI_C defined, but not all prerequisites" #endif -#if defined(MBEDTLS_AES_SCA_COUNTERMEASURES) && !defined(MBEDTLS_ENTROPY_HARDWARE_ALT) -#error "MBEDTLS_AES_SCA_COUNTERMEASURES defined, but not all prerequisites" -#endif - #if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) #error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" #endif diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 1a2de9aad..20f18007c 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -639,12 +639,12 @@ * * Add countermeasures against possible side-channel-attack to AES calculation. * - * Uncommenting this macro adds three additional calculation rounds to AES + * Uncommenting this macro adds additional calculation rounds to AES * calculation. Additional rounds are using random data and can occur in any * AES calculation round. * - * Tradeoff: Uncommenting this increases ROM footprint by ~800 bytes. - * The performance loss is 3/11= 27% with 128 bit AES. + * Tradeoff: Uncommenting this increases ROM footprint by ~100 bytes. + * The performance loss is ~50% with 128 bit AES. * * This option is dependent of \c MBEDTLS_ENTROPY_HARDWARE_ALT. * diff --git a/library/aes.c b/library/aes.c index 909b4c557..0ddde52df 100644 --- a/library/aes.c +++ b/library/aes.c @@ -90,7 +90,7 @@ */ typedef struct _aes_r_data_s { uint32_t *rk_ptr; /* Round Key */ - uint32_t xy_values[8]; /* X0, X1, X2, X3, Y0, U1, Y2, Y3 */ + uint32_t xy_values[8]; /* X0, X1, X2, X3, Y0, Y1, Y2, Y3 */ } aes_r_data_t; #if defined(MBEDTLS_AES_SCA_COUNTERMEASURES) @@ -547,20 +547,20 @@ static void aes_sca_cm_data_randomize( uint8_t *tbl, uint8_t tbl_len ) is_unique_number = 0; tbl[num] = 0x10; } - } while ( is_unique_number == 1 ); + } while( is_unique_number == 1 ); } // Fill start/final round control data num = /* mbedtls_platform_random_in_range( tbl_len - 1 ) */rand() % 0xff; if( ( num % 2 ) == 0 ) { - tbl[tbl_len - 2] = 0x10; - tbl[tbl_len - 1] = 0x0; + tbl[tbl_len - 2] = 0x10; // fake data + tbl[tbl_len - 1] = 0x0; // real data } else { - tbl[tbl_len - 2] = 0x00; - tbl[tbl_len - 1] = 0x10; + tbl[tbl_len - 2] = 0x00; // real data + tbl[tbl_len - 1] = 0x10; // fake data } #endif /* AES_SCA_CM_ROUNDS != 0 */ @@ -572,7 +572,7 @@ static void aes_sca_cm_data_randomize( uint8_t *tbl, uint8_t tbl_len ) { if( is_even_pos == 1 ) { - tbl[i] = 0x04; // real data, offset 0 + tbl[i] = 0x04; // real data, offset 4 is_even_pos = 0; } else From f44f7d465a4c16299aaae202fd15621b33a377f8 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Wed, 4 Dec 2019 15:19:50 +0200 Subject: [PATCH 13/14] AES CM review corrections -Use separate control bytes for start and final round to get them randomized separately. -Remove struct name. -Fix comments and follow Mbed TLS coding style. --- library/aes.c | 55 ++++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 22 deletions(-) diff --git a/library/aes.c b/library/aes.c index 0ddde52df..a3199a7b5 100644 --- a/library/aes.c +++ b/library/aes.c @@ -88,7 +88,7 @@ /* * Data structure for AES round data */ -typedef struct _aes_r_data_s { +typedef struct { uint32_t *rk_ptr; /* Round Key */ uint32_t xy_values[8]; /* X0, X1, X2, X3, Y0, Y1, Y2, Y3 */ } aes_r_data_t; @@ -515,13 +515,20 @@ static void aes_gen_tables( void ) /** * Randomize positions when to use AES SCA countermeasures. * Each byte indicates one AES round as follows: - * first ( tbl_len - 2 ) bytes are reserved for AES rounds + * first ( tbl_len - 4 ) bytes are reserved for middle AES rounds: * -4 high bit = table to use 0x10 for SCA CM data, 0 otherwise * -4 low bits = offset based on order, 4 for even position, 0 otherwise - * Last 2 bytes for first/final round calculation + * Last 4 bytes for first(2) and final(2) round calculation * -4 high bit = table to use, 0x10 for SCA CM data, otherwise real data * -4 low bits = not used * + * Control data when only real data (R) is used: + * | R | R | R | R | R | R | R | R | Start | Final | + * |0x04|0x00|0x00|0x04|0x00|0x04|0x00|0x04|0x00|0x00|0x00|0x00| + * + * Control data with 5 (F) dummy rounds and randomized start and final round: + * | R | F | R | F | F | R | R | R | R | R | R | START RF| FINAL FR| + * |0x04|0x10|0x04|0x10|0x10|0x00|0x04|0x00|0x04|0x00|0x04|0x00|0x10|0x10|0x00| */ static void aes_sca_cm_data_randomize( uint8_t *tbl, uint8_t tbl_len ) { @@ -537,10 +544,11 @@ static void aes_sca_cm_data_randomize( uint8_t *tbl, uint8_t tbl_len ) // Randomize SCA CM positions to tbl for( i = 0; i < AES_SCA_CM_ROUNDS; i++ ) { - do { + do + { is_unique_number = 1; /* TODO - Use proper random. This is now ONLY FOR TESTING as mbedtls_platform_random_in_range is alwyays returning 0 */ - num = /* mbedtls_platform_random_in_range( tbl_len - 1 ) */rand() % (tbl_len - 2); + num = /* mbedtls_platform_random_in_range( tbl_len - 4 ) */rand() % (tbl_len - 4); if( tbl[num] == 0 ) { @@ -550,23 +558,26 @@ static void aes_sca_cm_data_randomize( uint8_t *tbl, uint8_t tbl_len ) } while( is_unique_number == 1 ); } - // Fill start/final round control data - num = /* mbedtls_platform_random_in_range( tbl_len - 1 ) */rand() % 0xff; - if( ( num % 2 ) == 0 ) + // randomize control data for start and final round + for( i = 1; i <= 2; i++ ) { - tbl[tbl_len - 2] = 0x10; // fake data - tbl[tbl_len - 1] = 0x0; // real data - } - else - { - tbl[tbl_len - 2] = 0x00; // real data - tbl[tbl_len - 1] = 0x10; // fake data + num = /* mbedtls_platform_random_in_range( 0xff ) */rand() % 0xff; + if( ( num % 2 ) == 0 ) + { + tbl[tbl_len - ( i * 2 - 0 )] = 0x10; // fake data + tbl[tbl_len - ( i * 2 - 1 )] = 0x00; // real data + } + else + { + tbl[tbl_len - ( i * 2 - 0 )] = 0x00; // real data + tbl[tbl_len - ( i * 2 - 1 )] = 0x10; // fake data + } } #endif /* AES_SCA_CM_ROUNDS != 0 */ // Fill real AES round data to the remaining places is_even_pos = 1; - for( i = 0; i < tbl_len - 2; i++ ) + for( i = 0; i < tbl_len - 4; i++ ) { if( tbl[i] == 0 ) { @@ -993,9 +1004,9 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, #endif /* AES_SCA_CM_ROUNDS != 0 */ aes_r_data_t *aes_data_ptr; // pointer to aes_data_real or aes_data_fake aes_r_data_t *aes_data_table[2]; // pointers to real and fake data - int round_ctrl_table_len = ctx->nr - 1 + AES_SCA_CM_ROUNDS + 2; + int round_ctrl_table_len = ctx->nr - 1 + AES_SCA_CM_ROUNDS + 2 + 2; // control bytes for AES rounds, reserve based on max ctx->nr - uint8_t round_ctrl_table[ 14 - 1 + AES_SCA_CM_ROUNDS + 2 ]; + uint8_t round_ctrl_table[ 14 - 1 + AES_SCA_CM_ROUNDS + 2 + 2]; aes_data_real.rk_ptr = ctx->rk; aes_data_table[0] = &aes_data_real; @@ -1017,7 +1028,7 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, for( j = 0; j < start_fin_loops; j++ ) { aes_data_ptr = - aes_data_table[round_ctrl_table[ round_ctrl_table_len - 2 + j ] >> 4]; + aes_data_table[round_ctrl_table[ round_ctrl_table_len - 4 + j ] >> 4]; aes_data_ptr->xy_values[i] ^= *aes_data_ptr->rk_ptr++; } } @@ -1140,9 +1151,9 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, #endif /* AES_SCA_CM_ROUNDS != 0 */ aes_r_data_t *aes_data_ptr; // pointer to aes_data_real or aes_data_fake aes_r_data_t *aes_data_table[2]; // pointers to real and fake data - int round_ctrl_table_len = ctx->nr - 1 + AES_SCA_CM_ROUNDS + 2; + int round_ctrl_table_len = ctx->nr - 1 + AES_SCA_CM_ROUNDS + 2 + 2; // control bytes for AES rounds, reserve based on max ctx->nr - uint8_t round_ctrl_table[ 14 - 1 + AES_SCA_CM_ROUNDS + 2 ]; + uint8_t round_ctrl_table[ 14 - 1 + AES_SCA_CM_ROUNDS + 2 + 2 ]; aes_data_real.rk_ptr = ctx->rk; aes_data_table[0] = &aes_data_real; @@ -1164,7 +1175,7 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, for( j = 0; j < start_fin_loops; j++ ) { aes_data_ptr = - aes_data_table[round_ctrl_table[ round_ctrl_table_len - 2 + j ] >> 4]; + aes_data_table[round_ctrl_table[ round_ctrl_table_len - 4 + j ] >> 4]; aes_data_ptr->xy_values[i] ^= *aes_data_ptr->rk_ptr++; } } From 76deef9fca266004eee4501d9aad1009123a8bd3 Mon Sep 17 00:00:00 2001 From: Arto Kinnunen Date: Thu, 5 Dec 2019 10:10:31 +0200 Subject: [PATCH 14/14] Update AES SCA random number function -Replace usage of rand() with mbedtls_platform_random_in_range() -Prevent for-ever loop by hardcoding SCA countermeasure position in case of used random function is always returning constant number. --- library/aes.c | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/library/aes.c b/library/aes.c index a3199a7b5..57332e57b 100644 --- a/library/aes.c +++ b/library/aes.c @@ -544,24 +544,31 @@ static void aes_sca_cm_data_randomize( uint8_t *tbl, uint8_t tbl_len ) // Randomize SCA CM positions to tbl for( i = 0; i < AES_SCA_CM_ROUNDS; i++ ) { + is_unique_number = 0; do { - is_unique_number = 1; -/* TODO - Use proper random. This is now ONLY FOR TESTING as mbedtls_platform_random_in_range is alwyays returning 0 */ - num = /* mbedtls_platform_random_in_range( tbl_len - 4 ) */rand() % (tbl_len - 4); + is_unique_number++; + num = mbedtls_platform_random_in_range( tbl_len - 4 ); + + if( is_unique_number > 10 ) + { + // prevent forever loop if random returns constant + is_unique_number = 0; + tbl[i] = 0x10; // fake data + } if( tbl[num] == 0 ) { is_unique_number = 0; - tbl[num] = 0x10; + tbl[num] = 0x10; // fake data } - } while( is_unique_number == 1 ); + } while( is_unique_number != 0 ); } // randomize control data for start and final round for( i = 1; i <= 2; i++ ) { - num = /* mbedtls_platform_random_in_range( 0xff ) */rand() % 0xff; + num = mbedtls_platform_random_in_range( 0xff ); if( ( num % 2 ) == 0 ) { tbl[tbl_len - ( i * 2 - 0 )] = 0x10; // fake data