Merge remote-tracking branch 'upstream/pr/2983' into baremetal
* upstream/pr/2983:
Fix mbedtls_strerror to work with all wanted codes
diff --git a/configs/baremetal.h b/configs/baremetal.h
index 3d0fac5..5294351 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. */
diff --git a/configs/baremetal_test.h b/configs/baremetal_test.h
index 7a03777..97c6425 100644
--- a/configs/baremetal_test.h
+++ b/configs/baremetal_test.h
@@ -48,7 +48,4 @@
#undef MBEDTLS_NO_PLATFORM_ENTROPY
-#undef MBEDTLS_ENTROPY_MAX_SOURCES
-#define MBEDTLS_ENTROPY_MAX_SOURCES 3
-
#endif /* MBEDTLS_BAREMETAL_USER_CONFIG_H */
diff --git a/include/mbedtls/aes.h b/include/mbedtls/aes.h
index 0f430a8..6990be0 100644
--- a/include/mbedtls/aes.h
+++ b/include/mbedtls/aes.h
@@ -172,7 +172,8 @@
* <li>256 bits</li></ul>
*
* \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 @@
* <li>256 bits</li></ul>
*
* \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 @@
* \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 @@
* \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/include/mbedtls/config.h b/include/mbedtls/config.h
index dbb84b4..0f65133 100644
--- a/include/mbedtls/config.h
+++ b/include/mbedtls/config.h
@@ -635,6 +635,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 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 ~100 bytes.
+ * The performance loss is ~50% with 128 bit AES.
+ *
+ * This option is dependent of \c MBEDTLS_ENTROPY_HARDWARE_ALT.
+ *
+ */
+//#define MBEDTLS_AES_SCA_COUNTERMEASURES
+
+/**
* \def MBEDTLS_CAMELLIA_SMALL_MEMORY
*
* Use less ROM for the Camellia implementation (saves about 768 bytes).
diff --git a/include/mbedtls/platform_util.h b/include/mbedtls/platform_util.h
index e20f1c3..fa9f326 100644
--- a/include/mbedtls/platform_util.h
+++ b/include/mbedtls/platform_util.h
@@ -239,11 +239,18 @@
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/aes.c b/library/aes.c
index 243c4ec..c96f29e 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -85,6 +85,21 @@
}
#endif
+/*
+ * Data structure for AES round data
+ */
+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;
+
+#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,101 @@
#endif /* MBEDTLS_AES_ROM_TABLES */
+/**
+ * Randomize positions when to use AES SCA countermeasures.
+ * Each byte indicates one AES round as follows:
+ * 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 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
+ *
+ * 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|
+ *
+ * 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 int 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
+
+ mbedtls_platform_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++ )
+ {
+ is_unique_number = 0;
+ do
+ {
+ 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; // fake data
+ }
+ } 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 );
+ 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 - 4; i++ )
+ {
+ if( tbl[i] == 0 )
+ {
+ if( is_even_pos == 1 )
+ {
+ tbl[i] = 0x04; // real data, offset 4
+ is_even_pos = 0;
+ }
+ else
+ {
+ tbl[i] = 0x00; // real data, offset 0
+ is_even_pos = 1;
+ }
+ }
+ }
+
+ return( AES_SCA_CM_ROUNDS );
+}
+
#if defined(MBEDTLS_AES_FEWER_TABLES)
#define ROTL8(x) ( (uint32_t)( ( x ) << 8 ) + (uint32_t)( ( x ) >> 24 ) )
@@ -568,8 +678,12 @@
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits )
{
- unsigned int i;
+ unsigned int j = 0;
+ unsigned int flow_ctrl = 0;
+ volatile unsigned int i = 0;
+ volatile int ret = MBEDTLS_ERR_PLATFORM_FAULT_DETECTED;
uint32_t *RK;
+ uint32_t offset = 0;
AES_VALIDATE_RET( ctx != NULL );
AES_VALIDATE_RET( key != NULL );
@@ -607,9 +721,19 @@
return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) );
#endif
- for( i = 0; i < ( keybits >> 5 ); i++ )
+ mbedtls_platform_memset( RK, 0, ( keybits >> 5 ) * 4 );
+ offset = mbedtls_platform_random_in_range( keybits >> 5 );
+
+ for( j = offset; j < ( keybits >> 5 ); j++ )
{
- GET_UINT32_LE( RK[i], key, i << 2 );
+ GET_UINT32_LE( RK[j], key, j << 2 );
+ flow_ctrl++;
+ }
+
+ for( j = 0; j < offset; j++ )
+ {
+ GET_UINT32_LE( RK[j], key, j << 2 );
+ flow_ctrl++;
}
switch( ctx->nr )
@@ -676,7 +800,20 @@
#endif /* !MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */
}
- return( 0 );
+ ret = 0;
+
+ /* Validate execution path */
+ if( ( flow_ctrl == 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 */
@@ -694,7 +831,8 @@
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;
@@ -725,6 +863,8 @@
{
mbedtls_aesni_inverse_key( (unsigned char *) ctx->rk,
(const unsigned char *) cty.rk, ctx->nr );
+ i = 0;
+ j = 4;
goto exit;
}
#endif
@@ -755,7 +895,19 @@
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 */
}
@@ -838,110 +990,174 @@
#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 ); \
- } 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 ); \
- } 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] )
{
- int i;
- uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+ 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 + 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];
- RK = ctx->rk;
+ aes_data_real.rk_ptr = ctx->rk;
+ aes_data_table[0] = &aes_data_real;
- 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++;
+#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
- for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
+ // Get randomized AES calculation control bytes
+ flow_control = aes_sca_cm_data_randomize( round_ctrl_table,
+ round_ctrl_table_len );
+
+ mbedtls_platform_memset( aes_data_real.xy_values, 0, 16 );
+ offset = mbedtls_platform_random_in_range( 4 );
+
+ for( i = offset; i < 4; i++ )
{
- AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
- AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+ GET_UINT32_LE( aes_data_real.xy_values[i], input, ( i * 4 ) );
}
- AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+ for( i = 0; i < offset; i++ )
+ {
+ GET_UINT32_LE( aes_data_real.xy_values[i], input, ( i * 4 ) );
+ }
- 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 );
+ for( i = 0; i < 4; i++ )
+ {
+ 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++;
+ flow_control++;
+ }
+ }
- 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 );
+ 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;
- 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 );
+ 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],
+ aes_data_ptr->xy_values[7 - offset] );
+ flow_control++;
+ }
- 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 );
+ 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,
+ &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] );
+ flow_control++;
+ }
- PUT_UINT32_LE( X0, output, 0 );
- PUT_UINT32_LE( X1, output, 4 );
- PUT_UINT32_LE( X2, output, 8 );
- PUT_UINT32_LE( X3, output, 12 );
+ mbedtls_platform_memset( output, 0, 16 );
+ offset = mbedtls_platform_random_in_range( 4 );
- return( 0 );
+ for( i = offset; i < 4; i++ )
+ {
+ PUT_UINT32_LE( aes_data_real.xy_values[i], output, ( i * 4 ) );
+ flow_control++;
+ }
+
+ for( i = 0; i < offset; i++ )
+ {
+ PUT_UINT32_LE( aes_data_real.xy_values[i], output, ( i * 4 ) );
+ flow_control++;
+ }
+
+ 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 */
@@ -960,58 +1176,148 @@
#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] )
{
- int i;
- uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3;
+ 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 + 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 ];
- RK = ctx->rk;
+ aes_data_real.rk_ptr = ctx->rk;
+ aes_data_table[0] = &aes_data_real;
- 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++;
+#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
- for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- )
+ // Get randomized AES calculation control bytes
+ flow_control = aes_sca_cm_data_randomize( round_ctrl_table,
+ round_ctrl_table_len );
+
+ for( i = 0; i < 4; i++ )
{
- AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
- AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 );
+ 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 - 4 + j ] >> 4];
+ aes_data_ptr->xy_values[i] ^= *aes_data_ptr->rk_ptr++;
+ flow_control++;
+ }
}
- AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 );
+ 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;
- 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 );
+ 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],
+ aes_data_ptr->xy_values[7 - offset] );
+ flow_control++;
+ }
- 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 );
+ 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,
+ &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] );
+ flow_control++;
+ }
- 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 );
+ for( i = 0; i < 4; i++ )
+ {
+ PUT_UINT32_LE( aes_data_real.xy_values[i], output, ( i * 4 ) );
+ flow_control++;
+ }
- 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 );
+ 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;
+ }
- PUT_UINT32_LE( X0, output, 0 );
- PUT_UINT32_LE( X1, output, 4 );
- PUT_UINT32_LE( X2, output, 8 );
- PUT_UINT32_LE( X3, output, 12 );
-
- return( 0 );
+ return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED );
}
#endif /* !MBEDTLS_AES_ONLY_ENCRYPT */
#endif /* !MBEDTLS_AES_DECRYPT_ALT */
@@ -1062,6 +1368,7 @@
//
}
#endif
+
#if defined(MBEDTLS_AES_ONLY_ENCRYPT)
return( mbedtls_internal_aes_encrypt( ctx, input, output ) );
#else /* MBEDTLS_AES_ONLY_ENCRYPT */
@@ -1480,7 +1787,7 @@
n = *nc_off;
- if ( n > 0x0F )
+ if( n > 0x0F )
return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
while( length-- )
diff --git a/library/entropy.c b/library/entropy.c
index b4d1f29..6656ee8 100644
--- a/library/entropy.c
+++ b/library/entropy.c
@@ -273,7 +273,7 @@
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 @@
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 27276a8..caa5e17 100644
--- a/library/pk.c
+++ b/library/pk.c
@@ -597,7 +597,7 @@
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 @@
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 16867aa..2c22b3c 100644
--- a/library/platform_util.c
+++ b/library/platform_util.c
@@ -45,6 +45,9 @@
#include <stddef.h>
#include <string.h>
+/* 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 @@
#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/sha256.c b/library/sha256.c
index 785e28b..4dcec89 100644
--- a/library/sha256.c
+++ b/library/sha256.c
@@ -196,11 +196,23 @@
A[i] = ctx->state[i];
#if defined(MBEDTLS_SHA256_SMALLER)
+ {
+ uint32_t offset = mbedtls_platform_random_in_range(16);
+ mbedtls_platform_memset( W, 0, sizeof( W ) );
+
+ for( i = offset; i < 16; i++ )
+ {
+ W[i] = (uint32_t)mbedtls_platform_get_uint32_be( &data[4 * i] );
+ }
+ for( i = 0; i < offset; i++ )
+ {
+ W[i] = (uint32_t)mbedtls_platform_get_uint32_be( &data[4 * i] );
+ }
+ }
+
for( i = 0; i < 64; i++ )
{
- if( i < 16 )
- W[i] = (uint32_t)mbedtls_platform_get_uint32_be( &data[4 * i] );
- else
+ if( i >= 16 )
R( i );
P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] );
@@ -323,6 +335,7 @@
int ret, s_pos, o_pos;
uint32_t used;
uint32_t high, low;
+ uint32_t offset = 0;
SHA256_VALIDATE_RET( ctx != NULL );
SHA256_VALIDATE_RET( (unsigned char *)output != NULL );
@@ -366,11 +379,15 @@
/*
* Output final state
*/
+ offset = mbedtls_platform_random_in_range(7);
- for( s_pos = 0, o_pos = 0; s_pos < 7; s_pos++, o_pos += 4 )
+ mbedtls_platform_memset( output, 0, 32 );
+
+ for( s_pos = offset, o_pos = offset * 4; s_pos < 7;
+ s_pos++, o_pos += 4 )
{
(void)mbedtls_platform_put_uint32_be( &output[o_pos],
- ctx->state[s_pos] );
+ ctx->state[s_pos] );
}
#if !defined(MBEDTLS_SHA256_NO_SHA224)
@@ -378,6 +395,11 @@
#endif
(void)mbedtls_platform_put_uint32_be( &output[28], ctx->state[7] );
+ for( s_pos = 0, o_pos = 0; s_pos < (int)offset; s_pos++, o_pos += 4 )
+ {
+ (void)mbedtls_platform_put_uint32_be( &output[o_pos],
+ ctx->state[s_pos] );
+ }
return( 0 );
}
diff --git a/library/ssl_cli.c b/library/ssl_cli.c
index 479554d..3c59923 100644
--- a/library/ssl_cli.c
+++ b/library/ssl_cli.c
@@ -717,7 +717,7 @@
( 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 @@
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 @@
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 @@
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 92d1da0..bab8f00 100644
--- a/library/ssl_srv.c
+++ b/library/ssl_srv.c
@@ -4064,7 +4064,7 @@
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 @@
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 19bdc90..1d5503b 100644
--- a/library/ssl_tls.c
+++ b/library/ssl_tls.c
@@ -791,8 +791,8 @@
return( MBEDTLS_ERR_SSL_BAD_INPUT_DATA );
nb = strlen( label );
- mbedtls_platform_memcpy( tmp + md_len, label, nb );
- mbedtls_platform_memcpy( tmp + md_len + nb, random, rlen );
+ (void)mbedtls_platform_memcpy( tmp + md_len, label, nb );
+ (void)mbedtls_platform_memcpy( tmp + md_len + nb, random, rlen );
nb += rlen;
/*
@@ -801,19 +801,28 @@
if ( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 )
return( ret );
- mbedtls_md_hmac_starts( &md_ctx, secret, slen );
- mbedtls_md_hmac_update( &md_ctx, tmp + md_len, nb );
- mbedtls_md_hmac_finish( &md_ctx, tmp );
+ if ( ( ret = mbedtls_md_hmac_starts( &md_ctx, secret, slen ) ) != 0 )
+ return( ret );
+ if ( ( ret = mbedtls_md_hmac_update( &md_ctx, tmp + md_len, nb ) ) != 0 )
+ return( ret );
+ if ( ( ret = mbedtls_md_hmac_finish( &md_ctx, tmp ) ) != 0 )
+ return( ret );
for( i = 0; i < dlen; i += md_len )
{
- mbedtls_md_hmac_reset ( &md_ctx );
- mbedtls_md_hmac_update( &md_ctx, tmp, md_len + nb );
- mbedtls_md_hmac_finish( &md_ctx, h_i );
+ if ( ( ret = mbedtls_md_hmac_reset ( &md_ctx ) ) != 0 )
+ return( ret );
+ if ( ( ret = mbedtls_md_hmac_update( &md_ctx, tmp, md_len + nb ) ) != 0 )
+ return( ret );
+ if ( ( ret = mbedtls_md_hmac_finish( &md_ctx, h_i ) ) != 0 )
+ return( ret );
- mbedtls_md_hmac_reset ( &md_ctx );
- mbedtls_md_hmac_update( &md_ctx, tmp, md_len );
- mbedtls_md_hmac_finish( &md_ctx, tmp );
+ if ( ( ret = mbedtls_md_hmac_reset ( &md_ctx ) ) != 0 )
+ return( ret );
+ if ( ( ret = mbedtls_md_hmac_update( &md_ctx, tmp, md_len ) ) != 0 )
+ return( ret );
+ if ( ( ret = mbedtls_md_hmac_finish( &md_ctx, tmp ) ) != 0 )
+ return( ret );
k = ( i + md_len > dlen ) ? dlen % md_len : md_len;
@@ -823,8 +832,8 @@
mbedtls_md_free( &md_ctx );
- mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
- mbedtls_platform_zeroize( h_i, sizeof( h_i ) );
+ (void)mbedtls_platform_zeroize( tmp, sizeof( tmp ) );
+ (void)mbedtls_platform_zeroize( h_i, sizeof( h_i ) );
return( 0 );
}
@@ -1929,7 +1938,7 @@
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;
@@ -2011,7 +2020,7 @@
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;
@@ -2054,7 +2063,7 @@
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;
@@ -2085,7 +2094,7 @@
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;
@@ -2114,7 +2123,7 @@
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;
@@ -7346,7 +7355,7 @@
if( verify_ret == 0 )
{
- mbedtls_platform_enforce_volatile_reads();
+ mbedtls_platform_random_delay();
if( verify_ret == 0 )
{
flow_counter++;
@@ -7436,7 +7445,7 @@
( 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 ) )
@@ -7502,7 +7511,7 @@
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 )
@@ -7989,7 +7998,7 @@
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)
@@ -8010,7 +8019,7 @@
#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 */
@@ -8027,7 +8036,7 @@
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;
@@ -8048,7 +8057,7 @@
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 )
@@ -11119,6 +11128,9 @@
mbedtls_platform_memcpy( buf, ssl->in_offt, n );
ssl->in_msglen -= n;
+ // clear incoming data after it's copied to buffer
+ mbedtls_platform_memset(ssl->in_offt, 0, n);
+
if( ssl->in_msglen == 0 )
{
/* all bytes consumed */
diff --git a/library/version_features.c b/library/version_features.c
index 7a97d38..6882830 100644
--- a/library/version_features.c
+++ b/library/version_features.c
@@ -270,6 +270,9 @@
#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 */
diff --git a/library/x509_crt.c b/library/x509_crt.c
index fd3fa1a..af8f1d6 100644
--- a/library/x509_crt.c
+++ b/library/x509_crt.c
@@ -3043,7 +3043,7 @@
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 @@
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 @@
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/programs/ssl/query_config.c b/programs/ssl/query_config.c
index fd2bc90..315065b 100644
--- a/programs/ssl/query_config.c
+++ b/programs/ssl/query_config.c
@@ -762,6 +762,14 @@
}
#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 )
{
diff --git a/scripts/config.pl b/scripts/config.pl
index ff522b6..2519623 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_USE_TINYCRYPT
MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH
MBEDTLS_AES_ONLY_ENCRYPT
+MBEDTLS_AES_SCA_COUNTERMEASURES
_ALT\s*$
);
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index 42ef32d..0ea4ae8 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -1294,6 +1294,16 @@
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
diff --git a/tests/suites/helpers.function b/tests/suites/helpers.function
index 43426f5..4b53da7 100644
--- a/tests/suites/helpers.function
+++ b/tests/suites/helpers.function
@@ -32,6 +32,8 @@
#include "tinycrypt/ecc.h"
#endif /* MBEDTLS_USE_TINYCRYPT */
+#include "mbedtls/entropy.h"
+
#ifdef _MSC_VER
#include <basetsd.h>
typedef UINT8 uint8_t;
@@ -300,6 +302,10 @@
#define ENTROPY_HAVE_STRONG
#endif
+/* Set flag if number of entropy sources is more than 2 */
+#if ( MBEDTLS_ENTROPY_MAX_SOURCES > 2 )
+#define ENTROPY_SOURCE_COUNT_MORE_THAN_TWO
+#endif
/*----------------------------------------------------------------------------*/
/* Helper Functions */
diff --git a/tests/suites/test_suite_entropy.function b/tests/suites/test_suite_entropy.function
index cf19732..0442973 100644
--- a/tests/suites/test_suite_entropy.function
+++ b/tests/suites/test_suite_entropy.function
@@ -193,7 +193,7 @@
}
/* END_CASE */
-/* BEGIN_CASE */
+/* BEGIN_CASE depends_on:ENTROPY_SOURCE_COUNT_MORE_THAN_TWO */
void entropy_source_fail( char * path )
{
mbedtls_entropy_context ctx;
@@ -225,7 +225,7 @@
}
/* END_CASE */
-/* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG */
+/* BEGIN_CASE depends_on:ENTROPY_HAVE_STRONG:ENTROPY_SOURCE_COUNT_MORE_THAN_TWO */
void entropy_threshold( int threshold, int chunk_size, int result )
{
mbedtls_entropy_context ctx;
diff --git a/tinycrypt/ecc.c b/tinycrypt/ecc.c
index a0333b0..c6c722a 100644
--- a/tinycrypt/ecc.c
+++ b/tinycrypt/ecc.c
@@ -168,7 +168,7 @@
}
/* i should be 32 */
- mbedtls_platform_enforce_volatile_reads();
+ mbedtls_platform_random_delay();
diff |= (unsigned char) i ^ 32;
return diff;
@@ -296,7 +296,7 @@
}
/* i should be -1 now */
- mbedtls_platform_enforce_volatile_reads();
+ mbedtls_platform_random_delay();
diff |= i ^ -1;
return diff;
@@ -1015,13 +1015,10 @@
static uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
uECC_word_t *k1)
{
-
- wordcount_t num_n_words = NUM_ECC_WORDS;
bitcount_t num_n_bits = NUM_ECC_BITS;
uECC_word_t carry = uECC_vli_add(k0, k, curve_n) ||
- (num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) &&
- uECC_vli_testBit(k0, num_n_bits));
+ uECC_vli_testBit(k0, num_n_bits);
uECC_vli_add(k1, k0, curve_n);
@@ -1046,7 +1043,7 @@
if (problem != 0) {
return UECC_FAULT_DETECTED;
}
- mbedtls_platform_enforce_volatile_reads();
+ mbedtls_platform_random_delay();
if (problem != 0) {
return UECC_FAULT_DETECTED;
}
@@ -1058,7 +1055,7 @@
/* 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;
@@ -1088,7 +1085,7 @@
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;
@@ -1101,7 +1098,7 @@
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;
@@ -1198,7 +1195,7 @@
/* 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 ca071f8..660c5e9 100644
--- a/tinycrypt/ecc_dsa.c
+++ b/tinycrypt/ecc_dsa.c
@@ -72,10 +72,6 @@
unsigned bits_size)
{
unsigned num_n_bytes = BITS_TO_BYTES(NUM_ECC_BITS);
- unsigned num_n_words = BITS_TO_WORDS(NUM_ECC_BITS);
- int shift;
- uECC_word_t carry;
- uECC_word_t *ptr;
if (bits_size > num_n_bytes) {
bits_size = num_n_bytes;
@@ -83,22 +79,6 @@
uECC_vli_clear(native);
uECC_vli_bytesToNative(native, bits, bits_size);
- if (bits_size * 8 <= (unsigned)NUM_ECC_BITS) {
- return;
- }
- shift = bits_size * 8 - NUM_ECC_BITS;
- carry = 0;
- ptr = native + num_n_words;
- while (ptr-- > native) {
- uECC_word_t temp = *ptr;
- *ptr = (temp >> shift) | carry;
- carry = temp << (uECC_WORD_BITS - shift);
- }
-
- /* Reduce mod curve_n */
- if (uECC_vli_cmp_unsafe(curve_n, native) != 1) {
- uECC_vli_sub(native, native, curve_n);
- }
}
int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
@@ -299,7 +279,7 @@
/* 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;
}