diff --git a/include/mbedtls/aes.h b/include/mbedtls/aes.h index 0f430a8fe..6990be0ee 100644 --- a/include/mbedtls/aes.h +++ b/include/mbedtls/aes.h @@ -172,7 +172,8 @@ void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ); *
  • 256 bits
  • * * \return \c 0 on success. - * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH or + * #MBEDTLS_ERR_PLATFORM_FAULT_DETECTED on failure. */ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits ); @@ -190,7 +191,8 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, *
  • 256 bits
  • * * \return \c 0 on success. - * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH or + * #MBEDTLS_ERR_PLATFORM_FAULT_DETECTED on failure. */ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits ); @@ -602,6 +604,7 @@ int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, * \param output The output (ciphertext) block. * * \return \c 0 on success. + * \return #MBEDTLS_ERR_PLATFORM_FAULT_DETECTED in case of error. */ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, const unsigned char input[16], @@ -617,6 +620,7 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, * \param output The output (plaintext) block. * * \return \c 0 on success. + * \return #MBEDTLS_ERR_PLATFORM_FAULT_DETECTED in case of error. */ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, const unsigned char input[16], diff --git a/library/aes.c b/library/aes.c index 57332e57b..cdbcba49d 100644 --- a/library/aes.c +++ b/library/aes.c @@ -522,6 +522,9 @@ static void aes_gen_tables( void ) * -4 high bit = table to use, 0x10 for SCA CM data, otherwise real data * -4 low bits = not used * + * Return Number of additional AES rounds + * + * Example of the control bytes: * 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| @@ -530,7 +533,7 @@ static void aes_gen_tables( void ) * | 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 ) +static int aes_sca_cm_data_randomize( uint8_t *tbl, uint8_t tbl_len ) { int i, is_even_pos; #if AES_SCA_CM_ROUNDS != 0 @@ -600,6 +603,8 @@ static void aes_sca_cm_data_randomize( uint8_t *tbl, uint8_t tbl_len ) } } } + + return( AES_SCA_CM_ROUNDS ); } #if defined(MBEDTLS_AES_FEWER_TABLES) @@ -673,7 +678,9 @@ void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ) int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits ) { - unsigned int i; + unsigned int j = 0; + volatile unsigned int i = 0; + volatile int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED; uint32_t *RK; AES_VALIDATE_RET( ctx != NULL ); @@ -712,9 +719,9 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) ); #endif - for( i = 0; i < ( keybits >> 5 ); i++ ) + for( j = 0; j < ( keybits >> 5 ); j++ ) { - GET_UINT32_LE( RK[i], key, i << 2 ); + GET_UINT32_LE( RK[j], key, j << 2 ); } switch( ctx->nr ) @@ -781,7 +788,20 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, #endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ } - return( 0 ); + ret = 0; + + /* Validate execution path */ + if( ( j == keybits >> 5 ) && ( ( ctx->nr == 10 && i == 10 ) +#if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) + || ( ctx->nr == 12 && i == 8 ) + || ( ctx->nr == 14 && i == 7 ) +#endif + ) ) + { + return ret; + } + + return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED ); } #endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */ @@ -799,7 +819,8 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; #else /* */ - int i, j, ret; + volatile unsigned int i = 0, j = 0; + volatile int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED; mbedtls_aes_context cty; uint32_t *RK; uint32_t *SK; @@ -830,6 +851,8 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, { mbedtls_aesni_inverse_key( (unsigned char *) ctx->rk, (const unsigned char *) cty.rk, ctx->nr ); + i = 0; + j = 4; goto exit; } #endif @@ -860,7 +883,19 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, exit: mbedtls_aes_free( &cty ); - return( ret ); + if( ret != 0 ) + { + return( ret ); + } + else if( ( i == 0 ) && ( j == 4 ) ) + { + return( ret ); + } + else + { + return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED ); + } + #endif /* MBEDTLS_AES_ONLY_ENCRYPT */ } @@ -1012,6 +1047,7 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, 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 + 2; + volatile int flow_control; // control bytes for AES rounds, reserve based on max ctx->nr uint8_t round_ctrl_table[ 14 - 1 + AES_SCA_CM_ROUNDS + 2 + 2]; @@ -1027,7 +1063,8 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, #endif // Get randomized AES calculation control bytes - aes_sca_cm_data_randomize( round_ctrl_table, round_ctrl_table_len ); + flow_control = aes_sca_cm_data_randomize( round_ctrl_table, + round_ctrl_table_len ); for( i = 0; i < 4; i++ ) { @@ -1035,8 +1072,9 @@ 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 - 4 + j ] >> 4]; + aes_data_table[round_ctrl_table[ round_ctrl_table_len - 2 + j ] >> 4]; aes_data_ptr->xy_values[i] ^= *aes_data_ptr->rk_ptr++; + flow_control++; } } @@ -1055,6 +1093,7 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, aes_data_ptr->xy_values[5 - offset], aes_data_ptr->xy_values[6 - offset], aes_data_ptr->xy_values[7 - offset] ); + flow_control++; } for( j = 0; j < start_fin_loops; j++ ) @@ -1069,14 +1108,23 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, aes_data_ptr->xy_values[5], aes_data_ptr->xy_values[6], aes_data_ptr->xy_values[7] ); + flow_control++; } for( i = 0; i < 4; i++ ) { PUT_UINT32_LE( aes_data_real.xy_values[i], output, ( i * 4 ) ); + flow_control++; } - return( 0 ); + if( flow_control == ( AES_SCA_CM_ROUNDS + ( 4 * start_fin_loops ) + + ctx->nr - 1 + AES_SCA_CM_ROUNDS + start_fin_loops + 4 ) ) + { + /* Validate control path due possible fault injection */ + return 0; + } + + return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED ); } #endif /* !MBEDTLS_AES_ENCRYPT_ALT */ @@ -1160,6 +1208,7 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, 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 + 2; // control bytes for AES rounds, reserve based on max ctx->nr + volatile int flow_control; uint8_t round_ctrl_table[ 14 - 1 + AES_SCA_CM_ROUNDS + 2 + 2 ]; aes_data_real.rk_ptr = ctx->rk; @@ -1174,7 +1223,8 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, #endif // Get randomized AES calculation control bytes - aes_sca_cm_data_randomize( round_ctrl_table, round_ctrl_table_len ); + flow_control = aes_sca_cm_data_randomize( round_ctrl_table, + round_ctrl_table_len ); for( i = 0; i < 4; i++ ) { @@ -1184,6 +1234,7 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, aes_data_ptr = aes_data_table[round_ctrl_table[ round_ctrl_table_len - 4 + j ] >> 4]; aes_data_ptr->xy_values[i] ^= *aes_data_ptr->rk_ptr++; + flow_control++; } } @@ -1202,6 +1253,7 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, aes_data_ptr->xy_values[5 - offset], aes_data_ptr->xy_values[6 - offset], aes_data_ptr->xy_values[7 - offset] ); + flow_control++; } for( j = 0; j < start_fin_loops; j++ ) @@ -1216,14 +1268,23 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, aes_data_ptr->xy_values[5], aes_data_ptr->xy_values[6], aes_data_ptr->xy_values[7] ); + flow_control++; } for( i = 0; i < 4; i++ ) { PUT_UINT32_LE( aes_data_real.xy_values[i], output, ( i * 4 ) ); + flow_control++; } - return( 0 ); + if( flow_control == ( AES_SCA_CM_ROUNDS + ( 4 * start_fin_loops ) + + ctx->nr - 1 + AES_SCA_CM_ROUNDS + start_fin_loops + 4 ) ) + { + /* Validate control path due possible fault injection */ + return 0; + } + + return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED ); } #endif /* !MBEDTLS_AES_ONLY_ENCRYPT */ #endif /* !MBEDTLS_AES_DECRYPT_ALT */ @@ -1274,6 +1335,7 @@ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, // } #endif + #if defined(MBEDTLS_AES_ONLY_ENCRYPT) return( mbedtls_internal_aes_encrypt( ctx, input, output ) ); #else /* MBEDTLS_AES_ONLY_ENCRYPT */