From 8bef87ee5ee1b835298337ec3eaa8e85dbcc063e Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Fri, 30 Oct 2020 12:18:21 +0100 Subject: [PATCH 1/9] Add basic shuffling and masking to CCM operations Signed-off-by: Andrzej Kurek --- library/ccm.c | 54 +++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 50 insertions(+), 4 deletions(-) diff --git a/library/ccm.c b/library/ccm.c index 750ec9e98..edd7b8f8d 100644 --- a/library/ccm.c +++ b/library/ccm.c @@ -113,6 +113,41 @@ void mbedtls_ccm_free( mbedtls_ccm_context *ctx ) mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) ); } +/* Durstenfeld's version of Fisher-Yates shuffle */ +static void mbedtls_generate_permutation( unsigned char* table, size_t size ) +{ + size_t i, j; + + for( i = 0; i < size; i++ ) + { + table[i] = (unsigned char) i; + } + + if( size < 2 ) + { + return; + } + + for( i = size - 1; i > 0; i-- ) + { + unsigned char tmp; + j = mbedtls_platform_random_uint32() % ( i + 1 ); + tmp = table[i]; + table[i] = table[j]; + table[j] = tmp; + } +} + +static void mbedtls_generate_masks( unsigned char* table, size_t size ) +{ + size_t i; + + for( i = 0; i < size; i++ ) + { + table[i] = mbedtls_platform_random_uint32() % ( 256 ); + } +} + /* * Macros for common operations. * Results in smaller compiled code than static inline functions. @@ -123,8 +158,11 @@ void mbedtls_ccm_free( mbedtls_ccm_context *ctx ) * (Always using b as the source helps the compiler optimise a bit better.) */ #define UPDATE_CBC_MAC \ + mbedtls_generate_permutation( perm_table, 16 ); \ for( i = 0; i < 16; i++ ) \ - y[i] ^= b[i]; \ + { \ + y[perm_table[i]] ^= b[perm_table[i]]; \ + } \ \ if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \ return( ret ); @@ -134,17 +172,23 @@ void mbedtls_ccm_free( mbedtls_ccm_context *ctx ) * Warning: using b for temporary storage! src and dst must not be b! * This avoids allocating one more 16 bytes buffer while allowing src == dst. */ -#define CTR_CRYPT( dst, src, len ) \ +#define CTR_CRYPT( dst, src, len ) \ do \ { \ + mbedtls_generate_permutation( perm_table, len ); \ + mbedtls_generate_masks( mask_table, len ); \ if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, ctr, \ 16, b, &olen ) ) != 0 ) \ { \ return( ret ); \ } \ \ - for( i = 0; i < (len); i++ ) \ - (dst)[i] = (src)[i] ^ b[i]; \ + for( i = 0; i < len; i++ ) \ + { \ + (dst)[perm_table[i]] = (src)[perm_table[i]] ^ mask_table[perm_table[i]];\ + (dst)[perm_table[i]] ^= b[perm_table[i]]; \ + (dst)[perm_table[i]] ^= mask_table[perm_table[i]]; \ + } \ } while( 0 ) /* @@ -163,6 +207,8 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, unsigned char b[16]; unsigned char y[16]; unsigned char ctr[16]; + unsigned char perm_table[16]; + unsigned char mask_table[16]; const unsigned char *src; unsigned char *dst; From 0fa427b0279da33e6b725429925437b5c0bdb794 Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Fri, 30 Oct 2020 14:41:12 +0100 Subject: [PATCH 2/9] ccm: add masking to the UPDATE_CBC_MAC macro Signed-off-by: Andrzej Kurek --- library/ccm.c | 55 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 14 deletions(-) diff --git a/library/ccm.c b/library/ccm.c index edd7b8f8d..d785866f2 100644 --- a/library/ccm.c +++ b/library/ccm.c @@ -156,17 +156,33 @@ static void mbedtls_generate_masks( unsigned char* table, size_t size ) /* * Update the CBC-MAC state in y using a block in b * (Always using b as the source helps the compiler optimise a bit better.) + * Initial b masking happens outside of this macro due to various sources of it. */ #define UPDATE_CBC_MAC \ - mbedtls_generate_permutation( perm_table, 16 ); \ for( i = 0; i < 16; i++ ) \ { \ y[perm_table[i]] ^= b[perm_table[i]]; \ + y[perm_table[i]] ^= mask_table[perm_table[i]]; \ } \ \ if( ( ret = mbedtls_cipher_update( &ctx->cipher_ctx, y, 16, y, &olen ) ) != 0 ) \ return( ret ); +/* + * Copy src to dst starting at a random offset, while masking the whole dst buffer. + */ +#define COPY_MASK( dst, src, mask, len_src, len_dst ) \ + do \ + { \ + unsigned j, offset = mbedtls_platform_random_uint32() % 256; \ + for( i = 0; i < len_src; i++ ) \ + { \ + j = (i + offset) % len_src; \ + (dst)[j] = (src)[j] ^ (mask)[j]; \ + } \ + for( ; i < len_dst; i++ ) \ + (dst)[i] ^= (mask)[i]; \ + } while( 0 ) /* * Encrypt or decrypt a partial block with CTR * Warning: using b for temporary storage! src and dst must not be b! @@ -243,15 +259,16 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, * 5 .. 3 (t - 2) / 2 * 2 .. 0 q - 1 */ - b[0] = 0; - b[0] |= ( add_len > 0 ) << 6; - b[0] |= ( ( tag_len - 2 ) / 2 ) << 3; - b[0] |= q - 1; - - mbedtls_platform_memcpy( b + 1, iv, iv_len ); + mbedtls_generate_masks( mask_table, 16 ); + mbedtls_generate_permutation( perm_table, 16 ); + b[0] = (unsigned char) ( ( ( add_len > 0 ) << 6 ) | + ( ( ( tag_len - 2 ) / 2 ) << 3 ) | + ( q - 1 ) ) ^ mask_table[0]; + for( i = 0; i < iv_len; i++ ) + b[i+1] = iv[i] ^ mask_table[i+1]; for( i = 0, len_left = length; i < q; i++, len_left >>= 8 ) - b[15-i] = (unsigned char)( len_left & 0xFF ); + b[15-i] = (unsigned char)( ( len_left & 0xFF ) ) ^ mask_table[15-i]; if( len_left > 0 ) return( MBEDTLS_ERR_CCM_BAD_INPUT ); @@ -271,12 +288,16 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, len_left = add_len; src = add; + mbedtls_generate_masks( mask_table, 16 ); + mbedtls_generate_permutation( perm_table, 16 ); mbedtls_platform_memset( b, 0, 16 ); - b[0] = (unsigned char)( ( add_len >> 8 ) & 0xFF ); - b[1] = (unsigned char)( ( add_len ) & 0xFF ); + b[0] = (unsigned char)( ( ( add_len >> 8 ) & 0xFF ) ^ mask_table[0] ); + b[1] = (unsigned char)( ( ( add_len ) & 0xFF ) ^ mask_table[1] ); use_len = len_left < 16 - 2 ? len_left : 16 - 2; - mbedtls_platform_memcpy( b + 2, src, use_len ); + + COPY_MASK( b+2, src, mask_table+2, use_len, 14 ); + len_left -= use_len; src += use_len; @@ -284,10 +305,12 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, while( len_left > 0 ) { + mbedtls_generate_masks( mask_table, 16 ); + mbedtls_generate_permutation( perm_table, 16 ); use_len = len_left > 16 ? 16 : len_left; mbedtls_platform_memset( b, 0, 16 ); - mbedtls_platform_memcpy( b, src, use_len ); + COPY_MASK( b, src, mask_table, use_len, 16); UPDATE_CBC_MAC; len_left -= use_len; @@ -326,8 +349,10 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, if( mode == CCM_ENCRYPT ) { + mbedtls_generate_masks( mask_table, 16 ); + mbedtls_generate_permutation( perm_table, 16 ); mbedtls_platform_memset( b, 0, 16 ); - mbedtls_platform_memcpy( b, src, use_len ); + COPY_MASK( b, src, mask_table, use_len, 16 ); UPDATE_CBC_MAC; } @@ -335,8 +360,10 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, if( mode == CCM_DECRYPT ) { + mbedtls_generate_masks( mask_table, 16 ); + mbedtls_generate_permutation( perm_table, 16 ); mbedtls_platform_memset( b, 0, 16 ); - mbedtls_platform_memcpy( b, dst, use_len ); + COPY_MASK( b, dst, mask_table, use_len, 16 ); UPDATE_CBC_MAC; } From a138c0a0b09482454617595a4e12b1ca78b1f890 Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Mon, 2 Nov 2020 15:53:39 +0100 Subject: [PATCH 3/9] Move size checks outside of mbedtls_platform_random_in_range Update the documentation to mention that calling it with zero as an argument will result in an undefined behavior. Signed-off-by: Andrzej Kurek --- include/mbedtls/platform_util.h | 4 +- library/platform_util.c | 103 +++++++++++++++----------------- 2 files changed, 51 insertions(+), 56 deletions(-) diff --git a/include/mbedtls/platform_util.h b/include/mbedtls/platform_util.h index e0bd08c36..4999500ce 100644 --- a/include/mbedtls/platform_util.h +++ b/include/mbedtls/platform_util.h @@ -276,9 +276,9 @@ uint32_t mbedtls_platform_random_uint32( void ); * cryptographically secure RNG, but provide an RNG for utility * functions. * - * \note If the given range is [0, 0), 0 is returned. - * * \param num Max-value for the generated random number, exclusive. + * Must be greater than zero, otherwise an undefined behavior + * will occur on "num % 0". * The generated number will be on range [0, num). * * \return The generated random number. diff --git a/library/platform_util.c b/library/platform_util.c index 15309aa7e..19ba7b976 100644 --- a/library/platform_util.c +++ b/library/platform_util.c @@ -119,43 +119,45 @@ void *mbedtls_platform_zeroize( void *buf, size_t len ) void *mbedtls_platform_memset( void *ptr, int value, size_t num ) { - size_t i, start_offset; + size_t i, start_offset = 0; volatile size_t flow_counter = 0; volatile char *b = ptr; char rnd_data; - - start_offset = (size_t) mbedtls_platform_random_in_range( (uint32_t) num ); - rnd_data = (char) mbedtls_platform_random_in_range( 256 ); - - /* Perform a memset operations with random data and start from a random - * location */ - for( i = start_offset; i < num; ++i ) + if( num > 0 ) { - b[i] = rnd_data; - flow_counter++; - } + start_offset = (size_t) mbedtls_platform_random_in_range( (uint32_t) num ); - /* Start from a random location with target data */ - for( i = start_offset; i < num; ++i ) - { - b[i] = value; - flow_counter++; - } + rnd_data = (char) mbedtls_platform_random_in_range( 256 ); - /* Second memset operation with random data */ - for( i = 0; i < start_offset; ++i ) - { - b[i] = rnd_data; - flow_counter++; - } + /* Perform a memset operations with random data and start from a random + * location */ + for( i = start_offset; i < num; ++i ) + { + b[i] = rnd_data; + flow_counter++; + } - /* Finish memset operation with correct data */ - for( i = 0; i < start_offset; ++i ) - { - b[i] = value; - flow_counter++; - } + /* Start from a random location with target data */ + for( i = start_offset; i < num; ++i ) + { + b[i] = value; + flow_counter++; + } + /* Second memset operation with random data */ + for( i = 0; i < start_offset; ++i ) + { + b[i] = rnd_data; + flow_counter++; + } + + /* Finish memset operation with correct data */ + for( i = 0; i < start_offset; ++i ) + { + b[i] = value; + flow_counter++; + } + } /* check the correct number of iterations */ if( flow_counter == 2 * num ) { @@ -165,6 +167,7 @@ void *mbedtls_platform_memset( void *ptr, int value, size_t num ) return ptr; } } + return NULL; } @@ -245,22 +248,25 @@ int mbedtls_platform_memequal( const void *buf1, const void *buf2, size_t num ) /* Start from a random location and check the correct number of iterations */ size_t i, flow_counter = 0; - size_t start_offset = (size_t) mbedtls_platform_random_in_range( (uint32_t) num ); - - for( i = start_offset; i < num; i++ ) + size_t start_offset = 0; + if( num > 0 ) { - unsigned char x = A[i], y = B[i]; - flow_counter++; - diff |= x ^ y; - } + start_offset = (size_t) mbedtls_platform_random_in_range( (uint32_t) num ); - for( i = 0; i < start_offset; i++ ) - { - unsigned char x = A[i], y = B[i]; - flow_counter++; - diff |= x ^ y; - } + for( i = start_offset; i < num; i++ ) + { + unsigned char x = A[i], y = B[i]; + flow_counter++; + diff |= x ^ y; + } + for( i = 0; i < start_offset; i++ ) + { + unsigned char x = A[i], y = B[i]; + flow_counter++; + diff |= x ^ y; + } + } /* Return 0 only when diff is 0 and flow_counter is equal to num */ return( (int) diff | (int) ( flow_counter ^ num ) ); } @@ -340,18 +346,7 @@ void mbedtls_platform_random_buf( uint8_t *buf, size_t len ) uint32_t mbedtls_platform_random_in_range( uint32_t num ) { - uint32_t result; - - if( num <= 1 ) - { - result = 0; - } - else - { - result = mbedtls_platform_random_uint32() % num; - } - - return( result ); + return mbedtls_platform_random_uint32() % num; } void mbedtls_platform_random_delay( void ) From 18c60aaca100f265bed82dd3fe49d98f3cd0f207 Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Tue, 17 Nov 2020 12:16:42 +0100 Subject: [PATCH 4/9] ccm: use random_in_range instead of duplicating its functionality Signed-off-by: Andrzej Kurek --- library/ccm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/ccm.c b/library/ccm.c index d785866f2..6d3776066 100644 --- a/library/ccm.c +++ b/library/ccm.c @@ -131,7 +131,7 @@ static void mbedtls_generate_permutation( unsigned char* table, size_t size ) for( i = size - 1; i > 0; i-- ) { unsigned char tmp; - j = mbedtls_platform_random_uint32() % ( i + 1 ); + j = mbedtls_platform_random_in_range( (uint32_t) i + 1 ); tmp = table[i]; table[i] = table[j]; table[j] = tmp; @@ -144,7 +144,7 @@ static void mbedtls_generate_masks( unsigned char* table, size_t size ) for( i = 0; i < size; i++ ) { - table[i] = mbedtls_platform_random_uint32() % ( 256 ); + table[i] = mbedtls_platform_random_in_range( 256 ); } } @@ -174,7 +174,7 @@ static void mbedtls_generate_masks( unsigned char* table, size_t size ) #define COPY_MASK( dst, src, mask, len_src, len_dst ) \ do \ { \ - unsigned j, offset = mbedtls_platform_random_uint32() % 256; \ + unsigned j, offset = mbedtls_platform_random_in_range( 256 ); \ for( i = 0; i < len_src; i++ ) \ { \ j = (i + offset) % len_src; \ From c5b0c6e8ae91507147a62f78a43aea24341846f7 Mon Sep 17 00:00:00 2001 From: Shelly Liberman Date: Thu, 19 Nov 2020 19:58:40 +0200 Subject: [PATCH 5/9] fix uninitialized variables Signed-off-by: Shelly Liberman --- library/ssl_tls.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index b0dabf2dd..f6244dcf2 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -933,8 +933,8 @@ int tls_prf_generic( mbedtls_md_type_t md_type, { size_t nb; size_t i, j, k, md_len; - unsigned char tmp[128]; - unsigned char h_i[MBEDTLS_MD_MAX_SIZE]; + unsigned char tmp[128] = {0}; + unsigned char h_i[MBEDTLS_MD_MAX_SIZE] = {0}; mbedtls_md_handle_t md_info; mbedtls_md_context_t md_ctx; int ret; From b89cf99a5770aeb2fe841b04303d24028c3bacc9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Teppo=20J=C3=A4rvelin?= Date: Wed, 25 Nov 2020 10:42:27 +0200 Subject: [PATCH 6/9] Fix possible memory leak when MBEDTLS_SSL_VARIABLE_BUFFER_LENGTH is defined MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Teppo Järvelin --- library/ssl_tls.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/ssl_tls.c b/library/ssl_tls.c index b0dabf2dd..1f878b71f 100644 --- a/library/ssl_tls.c +++ b/library/ssl_tls.c @@ -12709,6 +12709,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) #endif mbedtls_platform_zeroize( ssl->out_buf, out_buf_len ); mbedtls_free( ssl->out_buf ); + ssl->out_buf = NULL; } if( ssl->in_buf != NULL ) @@ -12720,6 +12721,7 @@ void mbedtls_ssl_free( mbedtls_ssl_context *ssl ) #endif mbedtls_platform_zeroize( ssl->in_buf, in_buf_len ); mbedtls_free( ssl->in_buf ); + ssl->in_buf = NULL; } #if defined(MBEDTLS_ZLIB_SUPPORT) From 142f09fb96b3dc228bbbea92906813f41e292064 Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Wed, 4 Nov 2020 13:20:24 +0100 Subject: [PATCH 7/9] ccm: zeroize buffers before and after usage Signed-off-by: Andrzej Kurek --- library/ccm.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/library/ccm.c b/library/ccm.c index 87fe16dd8..aa15af2ea 100644 --- a/library/ccm.c +++ b/library/ccm.c @@ -246,6 +246,10 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, if( add_len > 0xFF00 ) return( MBEDTLS_ERR_CCM_BAD_INPUT ); + mbedtls_platform_zeroize( b, 16 ); + mbedtls_platform_zeroize( y, 16 ); + mbedtls_platform_zeroize( ctr, 16 ); + q = (uint_fast8_t) (16 - 1 - iv_len); /* @@ -390,6 +394,10 @@ static int ccm_auth_crypt( mbedtls_ccm_context *ctx, int mode, size_t length, CTR_CRYPT( y, y, 16 ); mbedtls_platform_memcpy( tag, y, tag_len ); + mbedtls_platform_zeroize( b, 16 ); + mbedtls_platform_zeroize( y, 16 ); + mbedtls_platform_zeroize( ctr, 16 ); + return( ret ); } From 7f81c86a0dc491a05e0d7872e0f9f5f6b7377c14 Mon Sep 17 00:00:00 2001 From: Andrzej Kurek Date: Tue, 17 Nov 2020 14:22:39 +0100 Subject: [PATCH 8/9] Add a callback for platform faults in platform_util.c Signed-off-by: Andrzej Kurek --- include/mbedtls/config.h | 12 ++++++++++++ library/platform_util.c | 9 ++++++++- library/version_features.c | 3 +++ programs/ssl/query_config.c | 8 ++++++++ scripts/config.pl | 1 + 5 files changed, 32 insertions(+), 1 deletion(-) diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 0e539be51..dce8f48e8 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -2951,6 +2951,18 @@ */ //#define MBEDTLS_MEMORY_BUFFER_ALLOC_C +/** + * \def MBEDTLS_PLATFORM_FAULT_CALLBACKS + * + * Uncomment to provide your own alternate implementation for mbedtls_platform_fault(), + * used in library/platform_util.c to signal a fault injection in either + * mbedtls_platform_memcpy or mbedtls_platform_memset. + * + * You will need to provide a header "platform_fault.h" and an implementation at + * compile time. + */ +//#define MBEDTLS_PLATFORM_FAULT_CALLBACKS + /** * \def MBEDTLS_NET_C * diff --git a/library/platform_util.c b/library/platform_util.c index 19ba7b976..ecfdb84d1 100644 --- a/library/platform_util.c +++ b/library/platform_util.c @@ -48,6 +48,12 @@ #include "mbedtls/entropy_poll.h" #endif +#if defined(MBEDTLS_PLATFORM_FAULT_CALLBACKS) +#include "platform_fault.h" +#else +static void mbedtls_platform_fault(){} +#endif + #include #include @@ -167,7 +173,7 @@ void *mbedtls_platform_memset( void *ptr, int value, size_t num ) return ptr; } } - + mbedtls_platform_fault(); return NULL; } @@ -207,6 +213,7 @@ void *mbedtls_platform_memcpy( void *dst, const void *src, size_t num ) return dst; } } + mbedtls_platform_fault(); return NULL; } diff --git a/library/version_features.c b/library/version_features.c index b0e16375d..8044dc91d 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -729,6 +729,9 @@ static const char *features[] = { #if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) "MBEDTLS_MEMORY_BUFFER_ALLOC_C", #endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ +#if defined(MBEDTLS_PLATFORM_FAULT_CALLBACKS) + "MBEDTLS_PLATFORM_FAULT_CALLBACKS", +#endif /* MBEDTLS_PLATFORM_FAULT_CALLBACKS */ #if defined(MBEDTLS_NET_C) "MBEDTLS_NET_C", #endif /* MBEDTLS_NET_C */ diff --git a/programs/ssl/query_config.c b/programs/ssl/query_config.c index bc6499dac..e86fdb5ec 100644 --- a/programs/ssl/query_config.c +++ b/programs/ssl/query_config.c @@ -1986,6 +1986,14 @@ int query_config( const char *config ) } #endif /* MBEDTLS_MEMORY_BUFFER_ALLOC_C */ +#if defined(MBEDTLS_PLATFORM_FAULT_CALLBACKS) + if( strcmp( "MBEDTLS_PLATFORM_FAULT_CALLBACKS", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_PLATFORM_FAULT_CALLBACKS ); + return( 0 ); + } +#endif /* MBEDTLS_PLATFORM_FAULT_CALLBACKS */ + #if defined(MBEDTLS_NET_C) if( strcmp( "MBEDTLS_NET_C", config ) == 0 ) { diff --git a/scripts/config.pl b/scripts/config.pl index 0a65ef438..82d711362 100755 --- a/scripts/config.pl +++ b/scripts/config.pl @@ -146,6 +146,7 @@ MBEDTLS_CTR_DRBG_USE_128_BIT_KEY MBEDTLS_SSL_TRANSFORM_OPTIMIZE_CIPHERS MBEDTLS_VALIDATE_SSL_KEYS_INTEGRITY MBEDTLS_OPTIMIZE_TINYCRYPT_ASM +MBEDTLS_PLATFORM_FAULT_CALLBACKS _ALT\s*$ ); From cdebcfe1a3444eb57c1c691255da108336f4b754 Mon Sep 17 00:00:00 2001 From: Shelly Liberman Date: Tue, 17 Nov 2020 11:33:25 +0200 Subject: [PATCH 9/9] aes boolean masking Signed-off-by: Shelly Liberman --- configs/baremetal.h | 1 + include/mbedtls/aes.h | 6 +- include/mbedtls/config.h | 19 ++ library/aes.c | 393 ++++++++++++++++++++++++++++++++++-- library/version_features.c | 3 + programs/ssl/query_config.c | 8 + scripts/config.pl | 2 + 7 files changed, 410 insertions(+), 22 deletions(-) diff --git a/configs/baremetal.h b/configs/baremetal.h index 7a2bd0ffe..e497c355d 100644 --- a/configs/baremetal.h +++ b/configs/baremetal.h @@ -42,6 +42,7 @@ #define MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH #define MBEDTLS_AES_ONLY_ENCRYPT #define MBEDTLS_AES_SCA_COUNTERMEASURES +#define MBEDTLS_AES_128_BIT_MASKED #define MBEDTLS_CCM_C /* Asymmetric crypto: Single-curve ECC only. */ diff --git a/include/mbedtls/aes.h b/include/mbedtls/aes.h index b410b5ad4..18c50bb9c 100644 --- a/include/mbedtls/aes.h +++ b/include/mbedtls/aes.h @@ -83,6 +83,10 @@ extern "C" { /** * \brief The AES context-type definition. */ + +//#if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) +#define AES_128_EXPANDED_KEY_SIZE_IN_WORDS 44 +//#endif typedef struct mbedtls_aes_context { int nr; /*!< The number of rounds. */ @@ -94,7 +98,7 @@ typedef struct mbedtls_aes_context uint32_t hash; /*!< hash of the set key */ #endif #if defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) && !defined(MBEDTLS_PADLOCK_C) - uint32_t buf[44]; /*!< Unaligned data buffer */ + uint32_t buf[AES_128_EXPANDED_KEY_SIZE_IN_WORDS]; /*!< Unaligned data buffer for expanded key only */ #else /* MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH */ uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can hold 32 extra Bytes, which can be used for diff --git a/include/mbedtls/config.h b/include/mbedtls/config.h index 0e539be51..af8aa0d06 100644 --- a/include/mbedtls/config.h +++ b/include/mbedtls/config.h @@ -654,6 +654,25 @@ */ //#define MBEDTLS_AES_SCA_COUNTERMEASURES +/** + * \def MBEDTLS_AES_128_BIT_MASKED + * + * Requires MBEDTLS_AES_SCA_COUNTERMEASURES + * + * Add boolean masking against possible combined side-channel-attack fault injection attacks. + * + * Uncommenting this macro adds data, key and Sbox masking additionally to dummy rounds + * + * Tradeoff: + * Uncommenting this macro does not increase codesize in MBEDTLS_AES_ROM_TABLES configuration. + * Uncommenting this macro increases codesize in AES RAM tables configuration by ~1k. + * The performance loss is ~50% with 128 bit AES encrypt. + * + * This option is dependent of \c MBEDTLS_ENTROPY_HARDWARE_ALT. + * + */ +//#define MBEDTLS_AES_128_BIT_MASKED + /** * \def MBEDTLS_FI_COUNTERMEASURES * diff --git a/library/aes.c b/library/aes.c index f7a48984b..53c614661 100644 --- a/library/aes.c +++ b/library/aes.c @@ -91,11 +91,25 @@ typedef struct { uint32_t *rk_ptr; /* Round Key */ uint32_t xy_values[8]; /* X0, X1, X2, X3, Y0, Y1, Y2, Y3 */ +#if defined(MBEDTLS_AES_128_BIT_MASKED) + uint32_t round; +#endif } aes_r_data_t; #if defined(MBEDTLS_AES_SCA_COUNTERMEASURES) /* Number of additional AES dummy rounds added for SCA countermeasures */ #define AES_SCA_CM_ROUNDS 5 + +#if defined (MBEDTLS_AES_128_BIT_MASKED) + +#define Nb (4) /* number of columns (32-bit words) comprising the state */ +#define Nk (4) /* number of 32-bit words comprising the key */ +#define Nr (10) /* number of rounds */ + +// state - array holding the intermediate results during aes operation. +typedef uint8_t masked_state_t[4][4]; + +#endif #endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ #if defined(MBEDTLS_PADLOCK_C) && \ @@ -143,6 +157,8 @@ static const unsigned char FSb[256] = 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 }; + +#if !defined(MBEDTLS_AES_128_BIT_MASKED) /* * Forward tables */ @@ -234,6 +250,8 @@ static const uint32_t FT3[256] = { FT }; #endif /* !MBEDTLS_AES_FEWER_TABLES */ #undef FT +#endif //ifndef MBEDTLS_AES_128_BIT_MASKED + #if !defined(MBEDTLS_AES_ONLY_ENCRYPT) /* @@ -274,6 +292,7 @@ static const unsigned char RSb[256] = 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D }; + #endif /* !MBEDTLS_AES_ONLY_ENCRYPT */ /* @@ -386,7 +405,9 @@ static const uint32_t RCON[10] = * Forward S-box & tables */ static unsigned char FSb[256]; +#if !defined(MBEDTLS_AES_128_BIT_MASKED) static uint32_t FT0[256]; +#endif #if !defined(MBEDTLS_AES_FEWER_TABLES) static uint32_t FT1[256]; static uint32_t FT2[256]; @@ -398,6 +419,7 @@ static uint32_t FT3[256]; */ #if !defined(MBEDTLS_AES_ONLY_ENCRYPT) static unsigned char RSb[256]; + static uint32_t RT0[256]; #if !defined(MBEDTLS_AES_FEWER_TABLES) static uint32_t RT1[256]; @@ -414,15 +436,20 @@ static uint32_t RCON[10]; /* * Tables generation code */ -#define ROTL8(x) ( ( (x) << 8 ) & 0xFFFFFFFF ) | ( (x) >> 24 ) #define XTIME(x) ( ( (x) << 1 ) ^ ( ( (x) & 0x80 ) ? 0x1B : 0x00 ) ) +#if !defined(MBEDTLS_AES_128_BIT_MASKED) +#define ROTL8(x) ( ( (x) << 8 ) & 0xFFFFFFFF ) | ( (x) >> 24 ) #define MUL(x,y) ( ( (x) && (y) ) ? pow[(log[(x)]+log[(y)]) % 255] : 0 ) +#endif static int aes_init_done = 0; static void aes_gen_tables( void ) { - int i, x, y, z; + int i, x, y; +#if !defined(MBEDTLS_AES_128_BIT_MASKED) + int z; +#endif int pow[256]; int log[256]; @@ -468,7 +495,7 @@ static void aes_gen_tables( void ) RSb[x] = (unsigned char) i; #endif } - +#if !defined(MBEDTLS_AES_128_BIT_MASKED) /* * generate the forward and reverse tables */ @@ -504,6 +531,8 @@ static void aes_gen_tables( void ) #endif /* !MBEDTLS_AES_FEWER_TABLES */ #endif /* !MBEDTLS_AES_ONLY_ENCRYPT */ } + +#endif //MBEDTLS_AES_128_BIT_MASKED } #undef ROTL8 @@ -611,6 +640,7 @@ static int aes_sca_cm_data_randomize( uint8_t *tbl, int tbl_len ) } #endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ +#if !defined(MBEDTLS_AES_128_BIT_MASKED) #if defined(MBEDTLS_AES_FEWER_TABLES) #define ROTL8(x) ( (uint32_t)( ( x ) << 8 ) + (uint32_t)( ( x ) >> 24 ) ) @@ -640,6 +670,7 @@ static int aes_sca_cm_data_randomize( uint8_t *tbl, int tbl_len ) #define AES_FT3(idx) FT3[idx] #endif /* MBEDTLS_AES_FEWER_TABLES */ +#endif void mbedtls_aes_init( mbedtls_aes_context *ctx ) { @@ -690,6 +721,8 @@ static void mbedtls_generate_fake_key( unsigned int keybits, mbedtls_aes_context /* * AES key schedule (encryption) */ + + #if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits ) @@ -700,7 +733,6 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, 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 ); (void) ret; @@ -731,6 +763,7 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); else #endif + ctx->rk = RK = ctx->buf; #if defined(MBEDTLS_AES_SCA_COUNTERMEASURES) mbedtls_generate_fake_key( keybits, ctx ); @@ -757,11 +790,10 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, GET_UINT32_LE( RK[j], key, j << 2 ); flow_ctrl++; } - + switch( ctx->nr ) { case 10: - for( i = 0; i < 10; i++, RK += 4 ) { RK[4] = RK[0] ^ RCON[i] ^ @@ -773,7 +805,7 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, RK[5] = RK[1] ^ RK[4]; RK[6] = RK[2] ^ RK[5]; RK[7] = RK[3] ^ RK[6]; - } + } break; #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH) case 12: @@ -1026,6 +1058,263 @@ int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, #if !defined(MBEDTLS_AES_ENCRYPT_ALT) #if defined(MBEDTLS_AES_SCA_COUNTERMEASURES) + +#if defined(MBEDTLS_AES_128_BIT_MASKED) + +static uint8_t xtime(uint8_t x) +{ + return ((x << 1) ^ (((x >> 7) & 1) * 0x1b)); +} + +static int sub_bytes_masked(uint32_t *data, uint8_t sbox_masked[256]) +{ + volatile unsigned int i; + + for (i = 0; i < 4; i++) { + data[i] = ( (uint32_t) sbox_masked[ ( data[i] ) & 0xFF ] ) ^ + ( (uint32_t) sbox_masked[ ( data[i] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) sbox_masked[ ( data[i] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) sbox_masked[ ( data[i] >> 24 ) & 0xFF ] << 24 ); + } + + if (i == 4){ + return 0; + } + + return MBEDTLS_ERR_PLATFORM_FAULT_DETECTED; +} + +static int mix_columns(uint8_t *s) +{ + masked_state_t *state = (masked_state_t *) s; + volatile unsigned int i = 0; + uint8_t Tmp, Tm, t; + + for (i = 0; i < 4; ++i) + { + t = (*state)[i][0]; + Tmp = (*state)[i][0] ^ (*state)[i][1] ^ (*state)[i][2] ^ (*state)[i][3]; + Tm = (*state)[i][0] ^ (*state)[i][1]; + Tm = xtime(Tm); + (*state)[i][0] ^= Tm ^ Tmp; + Tm = (*state)[i][1] ^ (*state)[i][2]; + Tm = xtime(Tm); + (*state)[i][1] ^= Tm ^ Tmp; + Tm = (*state)[i][2] ^ (*state)[i][3]; + Tm = xtime(Tm); + (*state)[i][2] ^= Tm ^ Tmp; + Tm = (*state)[i][3] ^ t; + Tm = xtime(Tm); + (*state)[i][3] ^= Tm ^ Tmp; + } + + if (i == 4) { + return 0; + } + + return MBEDTLS_ERR_PLATFORM_FAULT_DETECTED; +} + +static void shift_rows(uint8_t *s) +{ + uint8_t temp; + masked_state_t *state = (masked_state_t *) s; + // Rotate first row 1 columns to left + temp = (*state)[0][1]; + (*state)[0][1] = (*state)[1][1]; + (*state)[1][1] = (*state)[2][1]; + (*state)[2][1] = (*state)[3][1]; + (*state)[3][1] = temp; + + // Rotate second row 2 columns to left + temp = (*state)[0][2]; + (*state)[0][2] = (*state)[2][2]; + (*state)[2][2] = temp; + + temp = (*state)[1][2]; + (*state)[1][2] = (*state)[3][2]; + (*state)[3][2] = temp; + + // Rotate third row 3 columns to left + temp = (*state)[0][3]; + (*state)[0][3] = (*state)[3][3]; + (*state)[3][3] = (*state)[2][3]; + (*state)[2][3] = (*state)[1][3]; + (*state)[1][3] = temp; + +} + +#define mul_02(num) ( (num << 1) ^ (0x11b & -(num >> 7)) ) +#define mul_03(num) ( mul_02(num) ^ num ) + +static void calcMixColmask(uint32_t mask[10]) +{ + mask[6] = mul_02(mask[0]) ^ mul_03(mask[1]) ^ mask[2] ^ mask[3]; + mask[7] = mask[0] ^ mul_02(mask[1]) ^ mul_03(mask[2]) ^ mask[3]; + mask[8] = mask[0] ^ mask[1] ^ mul_02(mask[2]) ^ mul_03(mask[3]); + mask[9] = mul_03(mask[0]) ^ mask[1] ^ mask[2] ^ mul_02(mask[3]); +} + +//Calculate the the invSbox to change from Mask m to Mask m' +static int calcSboxMasked(uint32_t mask[10], uint8_t sbox_masked[256]) +{ + volatile unsigned int i = 0; + + for ( i = 0; i < 256; i++ ) + { + sbox_masked[i ^ mask[4]] = FSb[i] ^ mask[5]; + } + if (i == 256) { + return 0; + } + + return MBEDTLS_ERR_PLATFORM_FAULT_DETECTED; +} + +static int remask(uint32_t *data, uint32_t m1, uint32_t m2, uint32_t m3, uint32_t m4, uint32_t m5, uint32_t m6, uint32_t m7, uint32_t m8) +{ + + volatile unsigned int i = 0; + + for ( i = 0; i < 4; i++) + { + data[i] = data[i] ^ ( (m1^m5) ); + data[i] = data[i] ^ ( (m2^m6) << 8 ); + data[i] = data[i] ^ ( (m3^m7) << 16 ); + data[i] = data[i] ^ ( (m4^m8) << 24 ); + } + + if (i == 4) { + return 0; + } + + return MBEDTLS_ERR_PLATFORM_FAULT_DETECTED; +} + + +static int init_masking_encrypt(const uint8_t *rk, uint8_t *rk_masked, uint32_t mask[10], uint8_t sbox_masked[256] ) +{ + volatile int flow_control = 0; + unsigned int i = 0; + + mbedtls_platform_memcpy(rk_masked, rk, AES_128_EXPANDED_KEY_SIZE_IN_WORDS*4); + + + //Randomly generate the masks: m1 m2 m3 m4 m m' + for (i = 0; i < 6; i++) + { + mask[i] = mbedtls_platform_random_in_range( 0xFF ); + flow_control++; + } + + //Calculate m1',m2',m3',m4' + calcMixColmask(mask); + flow_control++; + + //Calculate the masked Sbox + if (calcSboxMasked(mask, sbox_masked) == 0){ + flow_control++; + } + +#define MASK_INIT_CONTROL 19 + //Init masked key + if (remask( (uint32_t *)&rk_masked[(Nr * Nb * 4)], 0, 0, 0, 0, mask[5], mask[5], mask[5], mask[5]) == 0) { + flow_control++; + } + + + // Mask change from M1',M2',M3',M4' to M + for (i = 0; i < Nr; i++) + { + if ( remask( (uint32_t *)&rk_masked[( i * Nb * 4 )], mask[6], mask[7], mask[8], mask[9], mask[4], mask[4], mask[4], mask[4]) == 0 ) + flow_control++; + } + + if( flow_control == MASK_INIT_CONTROL ) { + mbedtls_platform_random_delay(); + if( flow_control == MASK_INIT_CONTROL ) { + return MASK_INIT_CONTROL; + } + } + + return MBEDTLS_ERR_PLATFORM_FAULT_DETECTED; +} + +static int add_rk_masked(uint32_t round, uint32_t *data, const uint32_t * rk_masked) +{ + volatile unsigned int i; + unsigned int offset = round*4; + for( i = 0; i < 4; i++ ) + { + data[i] ^= rk_masked[offset + i] ; + } + + if (i == 4) { + return 0; + } + return MBEDTLS_ERR_PLATFORM_FAULT_DETECTED; +} + + +static int aes_masked_round(uint32_t *data, uint32_t *key, uint32_t round, uint32_t mask[10], uint8_t sbox_masked[256]) +{ + volatile uint32_t flow_control = 0; + +// Mask changes from M to M' + if ( sub_bytes_masked(data, sbox_masked) == 0 ) + flow_control++; + + //No impact on mask + shift_rows((uint8_t *)data); + + //Change mask from M' to + // M1 for first row + // M2 for second row + // M3 for third row + // M4 for fourth row + if ( remask(data, mask[0], mask[1], mask[2], mask[3], mask[5], mask[5], mask[5], mask[5]) == 0) + flow_control++; + + // Masks change from M1,M2,M3,M4 to M1',M2',M3',M4' + if ( mix_columns((uint8_t *)data) == 0) + flow_control++; + + // Add the First round key to the state before starting the rounds. + // Masks change from M1',M2',M3',M4' to M + if ( add_rk_masked(round,data, key) == 0 ) + flow_control++; + + if ( flow_control == 4 ) + return 0; + + return MBEDTLS_ERR_PLATFORM_FAULT_DETECTED; +} + +static int aes_masked_round_final( uint32_t *data, uint32_t *key, uint8_t sbox_masked[256] ) +{ + volatile uint32_t flow_control = 0; + + if ( sub_bytes_masked(data, sbox_masked) == 0 ) + flow_control++; + + shift_rows((uint8_t *)data); + + // Mask are removed by the last addroundkey + // From M' to 0 + if( add_rk_masked(Nr, data, key) == 0) + flow_control++; + + if ( flow_control == 2 ) + return 0; + + return MBEDTLS_ERR_PLATFORM_FAULT_DETECTED; +} +#define MASKING_FLOW_CONTORL (MASK_INIT_CONTROL + 2) //2 comes from initial data remask of real and fake data + +#else // end of MBEDTLS_AES_128_BIT_MASKED + +#define MASKING_FLOW_CONTORL 0 + 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 ) @@ -1053,10 +1342,12 @@ static uint32_t *aes_fround( uint32_t *R, 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 ) ^ @@ -1077,22 +1368,30 @@ static void aes_fround_final( uint32_t *R, ( (uint32_t) FSb[ ( (Y1) >> 16 ) & 0xFF ] << 16 ) ^ ( (uint32_t) FSb[ ( (Y2) >> 24 ) & 0xFF ] << 24 ); } +#endif // MBEDTLS_AES_128_BIT_MASKED + int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) { int i, tindex, offset, stop_mark, dummy_rounds; - aes_r_data_t aes_data_real; // real data - aes_r_data_t aes_data_fake; // fake data + aes_r_data_t aes_data_real = {0}; // real data + aes_r_data_t aes_data_fake = {0}; // fake data aes_r_data_t *aes_data_ptr; // pointer to real or fake data - aes_r_data_t *aes_data_table[2]; // pointers to real and fake data + aes_r_data_t *aes_data_table[2] = {0}; // pointers to real and fake data int round_ctrl_table_len = ctx->nr + 2 + AES_SCA_CM_ROUNDS; - volatile int flow_control; + volatile int flow_control = 0; // control bytes for AES calculation rounds, // reserve based on max rounds + dummy rounds + 2 (for initial key addition) uint8_t round_ctrl_table[( 14 + AES_SCA_CM_ROUNDS + 2 )]; +#if defined MBEDTLS_AES_128_BIT_MASKED + uint32_t rk_masked[AES_128_EXPANDED_KEY_SIZE_IN_WORDS] = {0}; + static uint8_t sbox_masked[256] = {0}; + uint32_t mask[10] = {0}; +#endif + #if defined(MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY) unsigned key_bytes = 0; uint32_t check_hash = 0; @@ -1108,7 +1407,14 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, check_hash = mbedtls_hash( ctx->rk, key_bytes ); #endif - aes_data_real.rk_ptr = ctx->rk; +#if defined (MBEDTLS_AES_128_BIT_MASKED) + //Flow control should be MASK_INIT_CONTROL and it will be checked as a part last flow control verification + flow_control = init_masking_encrypt((uint8_t*)ctx->rk, (uint8_t*)rk_masked, mask, sbox_masked); + aes_data_real.rk_ptr = &rk_masked[0]; +#else + aes_data_real.rk_ptr = ctx->rk; +#endif + aes_data_fake.rk_ptr = ctx->frk; aes_data_table[0] = &aes_data_real; @@ -1117,7 +1423,7 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, // Get AES calculation control bytes dummy_rounds = aes_sca_cm_data_randomize( round_ctrl_table, round_ctrl_table_len ); - flow_control = dummy_rounds; + flow_control += dummy_rounds; // SCA countermeasure, safely clear the aes_data_real.xy_values mbedtls_platform_memset( aes_data_real.xy_values, 0, 16 ); @@ -1134,21 +1440,39 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, flow_control++; } while( ( i = ( i + 1 ) % 4 ) != offset ); +#if defined (MBEDTLS_AES_128_BIT_MASKED) + //Plain text masked with m1',m2',m3',m4' + if (remask( &aes_data_real.xy_values[0], mask[6], mask[7], mask[8], mask[9], 0, 0, 0, 0) == 0) + flow_control++; + + if (remask( &aes_data_fake.xy_values[0], mask[6], mask[7], mask[8], mask[9], 0, 0, 0, 0) == 0) + flow_control++; + +#endif + tindex = 0; do { // Get pointer to the real or fake data aes_data_ptr = aes_data_table[round_ctrl_table[tindex] >> 4]; stop_mark = round_ctrl_table[tindex] & 0x03; - + // initial round key addition +#if defined (MBEDTLS_AES_128_BIT_MASKED) + if ( add_rk_masked(0, &aes_data_ptr->xy_values[0], aes_data_ptr->rk_ptr) == 0) + flow_control++; + aes_data_ptr->round = 1; +#else for( i = 0; i < 4; i++ ) { aes_data_ptr->xy_values[i] ^= *aes_data_ptr->rk_ptr++; } - tindex++; flow_control++; +#endif + + tindex++; } while( stop_mark == 0 ); + // Calculate AES rounds (9, 11 or 13 rounds) + dummy rounds do @@ -1157,7 +1481,12 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, aes_data_ptr = aes_data_table[round_ctrl_table[tindex] >> 4]; offset = round_ctrl_table[tindex] & 0x04; stop_mark = round_ctrl_table[tindex] & 0x03; - +#if defined (MBEDTLS_AES_128_BIT_MASKED) + if (aes_masked_round( &aes_data_ptr->xy_values[0], aes_data_ptr->rk_ptr, + aes_data_ptr->round, mask, sbox_masked) == 0) + flow_control++; + aes_data_ptr->round ++; +#else 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], @@ -1167,8 +1496,10 @@ 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] ); - tindex++; flow_control++; +#endif + tindex++; + } while( stop_mark == 0 ); // Calculate final AES round + dummy rounds @@ -1176,6 +1507,13 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, { aes_data_ptr = aes_data_table[round_ctrl_table[tindex] >> 4]; stop_mark = round_ctrl_table[tindex] & 0x03; +#if defined (MBEDTLS_AES_128_BIT_MASKED) + if ( aes_masked_round_final( &aes_data_ptr->xy_values[0], + aes_data_ptr->rk_ptr, sbox_masked ) == 0) + flow_control++; + //Cleanup the masked key + mbedtls_platform_memset(rk_masked, 0, sizeof(rk_masked)); +#else aes_fround_final( aes_data_ptr->rk_ptr, &aes_data_ptr->xy_values[0], &aes_data_ptr->xy_values[1], @@ -1186,9 +1524,11 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, aes_data_ptr->xy_values[6], aes_data_ptr->xy_values[7] ); flow_control++; +#endif tindex++; } while( stop_mark == 0 ); + // SCA countermeasure, safely clear the output mbedtls_platform_memset( output, 0, 16 ); @@ -1202,8 +1542,11 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, flow_control++; } while( ( i = ( i + 1 ) % 4 ) != offset ); +#if defined (MBEDTLS_AES_128_BIT_MASKED) + mbedtls_platform_memset(rk_masked, 0, sizeof(rk_masked)); +#endif /* Double negation is used to silence an "extraneous parentheses" warning */ - if( ! ( flow_control != tindex + dummy_rounds + 8 ) + if( ! ( flow_control != tindex + dummy_rounds + MASKING_FLOW_CONTORL + 8 ) #if defined(MBEDTLS_VALIDATE_AES_KEYS_INTEGRITY) && check_hash == ctx->hash #endif @@ -1217,9 +1560,17 @@ int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, return 0; } } - + // Clear the output in case of a FI mbedtls_platform_memset( output, 0, 16 ); + mbedtls_platform_memset( aes_data_real.xy_values, 0, 16 ); + mbedtls_platform_memset (aes_data_table, 0, sizeof(aes_data_table)); +#if defined (MBEDTLS_AES_128_BIT_MASKED) + //Clear masked key, masked sbox and mask in case of a FI + mbedtls_platform_memset(rk_masked, 0, sizeof(rk_masked)); + mbedtls_platform_memset(mask, 0, sizeof(mask)); + mbedtls_platform_memset(sbox_masked, 0, sizeof(sbox_masked)); +#endif return( MBEDTLS_ERR_PLATFORM_FAULT_DETECTED ); } @@ -1334,7 +1685,7 @@ void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, #if !defined(MBEDTLS_AES_ONLY_ENCRYPT) #if defined(MBEDTLS_AES_SCA_COUNTERMEASURES) -static uint32_t *aes_rround( uint32_t *R, +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 ) { @@ -1621,9 +1972,9 @@ int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, return( 0 ); } +#endif /* !MBEDTLS_AES_ONLY_ENCRYPT */ #endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ -#endif /* !MBEDTLS_AES_ONLY_ENCRYPT */ #endif /* !MBEDTLS_AES_DECRYPT_ALT */ #if !defined(MBEDTLS_DEPRECATED_REMOVED) diff --git a/library/version_features.c b/library/version_features.c index b0e16375d..b8f1d263d 100644 --- a/library/version_features.c +++ b/library/version_features.c @@ -276,6 +276,9 @@ static const char *features[] = { #if defined(MBEDTLS_FI_COUNTERMEASURES) "MBEDTLS_FI_COUNTERMEASURES", #endif /* MBEDTLS_FI_COUNTERMEASURES */ +#if defined(MBEDTLS_AES_128_BIT_MASKED) + "MBEDTLS_AES_128_BIT_MASKED", +#endif /* MBEDTLS_AES_128_BIT_MASKED */ #if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) "MBEDTLS_CAMELLIA_SMALL_MEMORY", #endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ diff --git a/programs/ssl/query_config.c b/programs/ssl/query_config.c index bc6499dac..ecf951ed6 100644 --- a/programs/ssl/query_config.c +++ b/programs/ssl/query_config.c @@ -770,6 +770,14 @@ int query_config( const char *config ) } #endif /* MBEDTLS_AES_SCA_COUNTERMEASURES */ +#if defined(MBEDTLS_AES_128_BIT_MASKED) + if( strcmp( "MBEDTLS_AES_128_BIT_MASKED", config ) == 0 ) + { + MACRO_EXPANSION_TO_STR( MBEDTLS_AES_128_BIT_MASKED ); + return( 0 ); + } +#endif /* MBEDTLS_AES_128_BIT_MASKED */ + #if defined(MBEDTLS_FI_COUNTERMEASURES) if( strcmp( "MBEDTLS_FI_COUNTERMEASURES", config ) == 0 ) { diff --git a/scripts/config.pl b/scripts/config.pl index 0a65ef438..fce736662 100755 --- a/scripts/config.pl +++ b/scripts/config.pl @@ -60,6 +60,7 @@ # MBEDTLS_SSL_TRANSFORM_OPTIMIZE_CIPHERS # MBEDTLS_VALIDATE_SSL_KEYS_INTEGRITY # MBEDTLS_OPTIMIZE_TINYCRYPT_ASM +# MBEDTLS_AES_128_BIT_MASKED # and any symbol beginning _ALT # # The baremetal configuration excludes options that require a library or @@ -146,6 +147,7 @@ MBEDTLS_CTR_DRBG_USE_128_BIT_KEY MBEDTLS_SSL_TRANSFORM_OPTIMIZE_CIPHERS MBEDTLS_VALIDATE_SSL_KEYS_INTEGRITY MBEDTLS_OPTIMIZE_TINYCRYPT_ASM +MBEDTLS_AES_128_BIT_MASKED _ALT\s*$ );