diff --git a/components/esp32/test/test_sha.c b/components/esp32/test/test_sha.c index 641dbab69..47aed427f 100644 --- a/components/esp32/test/test_sha.c +++ b/components/esp32/test/test_sha.c @@ -62,8 +62,8 @@ TEST_CASE("Test esp_sha()", "[hw_crypto]") free(buffer); - TEST_PERFORMANCE_LESS_THAN(ESP32_TIME_SHA1_32KB, "%dus", us_sha1); - TEST_PERFORMANCE_LESS_THAN(ESP32_TIME_SHA512_32KB, "%dus", us_sha512); + TEST_PERFORMANCE_LESS_THAN(TIME_SHA1_32KB, "%dus", us_sha1); + TEST_PERFORMANCE_LESS_THAN(TIME_SHA512_32KB, "%dus", us_sha512); } TEST_CASE("Test esp_sha() function with long input", "[hw_crypto]") diff --git a/components/esp32s2beta/test/test_sha.c b/components/esp32s2beta/test/test_sha.c new file mode 100644 index 000000000..df19a12ff --- /dev/null +++ b/components/esp32s2beta/test/test_sha.c @@ -0,0 +1,108 @@ +#include +#include +#include +#include "esp_types.h" +#include "esp32s2beta/clk.h" +#include "esp_log.h" +#include "esp_timer.h" +#include "esp_heap_caps.h" +#include "idf_performance.h" + +#include "unity.h" +#include "test_utils.h" +#include "mbedtls/sha1.h" +#include "mbedtls/sha256.h" +#include "mbedtls/sha512.h" +#include "esp32s2beta/sha.h" + +/* Note: Most of the SHA functions are called as part of mbedTLS, so +are tested as part of mbedTLS tests. Only esp_sha() is different. +*/ + +#define TAG "sha_test" + +TEST_CASE("Test esp_sha()", "[hw_crypto]") +{ + const size_t BUFFER_SZ = 32 * 1024 + 6; // NB: not an exact multiple of SHA block size + + int64_t begin, end; + uint32_t us_sha1, us_sha512; + uint8_t sha1_result[20] = { 0 }; + uint8_t sha512_result[64] = { 0 }; + void *buffer = heap_caps_malloc(BUFFER_SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL); + TEST_ASSERT_NOT_NULL(buffer); + memset(buffer, 0xEE, BUFFER_SZ); + + const uint8_t sha1_expected[20] = { 0xc7, 0xbb, 0xd3, 0x74, 0xf2, 0xf6, 0x20, 0x86, + 0x61, 0xf4, 0x50, 0xd5, 0xf5, 0x18, 0x44, 0xcc, + 0x7a, 0xb7, 0xa5, 0x4a }; + const uint8_t sha512_expected[64] = { 0xc7, 0x7f, 0xda, 0x8c, 0xb3, 0x58, 0x14, 0x8a, + 0x52, 0x3b, 0x46, 0x04, 0xc0, 0x85, 0xc5, 0xf0, + 0x46, 0x64, 0x14, 0xd5, 0x96, 0x7a, 0xa2, 0x80, + 0x20, 0x9c, 0x04, 0x27, 0x7d, 0x3b, 0xf9, 0x1f, + 0xb2, 0xa3, 0x45, 0x3c, 0xa1, 0x6a, 0x8d, 0xdd, + 0x35, 0x5e, 0x35, 0x57, 0x76, 0x22, 0x74, 0xd8, + 0x1e, 0x07, 0xc6, 0xa2, 0x9e, 0x3b, 0x65, 0x75, + 0x80, 0x7d, 0xe6, 0x6e, 0x47, 0x61, 0x2c, 0x94 }; + + begin = esp_timer_get_time(); + esp_sha(SHA1, buffer, BUFFER_SZ, sha1_result); + end = esp_timer_get_time(); + TEST_ASSERT_EQUAL_HEX8_ARRAY(sha1_expected, sha1_result, sizeof(sha1_expected)); + us_sha1 = end - begin; + ESP_LOGI(TAG, "esp_sha() 32KB SHA1 in %u us", us_sha1); + + begin = esp_timer_get_time(); + esp_sha(SHA2_512, buffer, BUFFER_SZ, sha512_result); + end = esp_timer_get_time(); + TEST_ASSERT_EQUAL_HEX8_ARRAY(sha512_expected, sha512_result, sizeof(sha512_expected)); + + us_sha512 = end - begin; + ESP_LOGI(TAG, "esp_sha() 32KB SHA512 in %u us", us_sha512); + + free(buffer); + + TEST_PERFORMANCE_LESS_THAN(TIME_SHA1_32KB, "%dus", us_sha1); + TEST_PERFORMANCE_LESS_THAN(TIME_SHA512_32KB, "%dus", us_sha512); +} + +TEST_CASE("Test esp_sha() function with long input", "[hw_crypto]") +{ + const void* ptr; + spi_flash_mmap_handle_t handle; + uint8_t sha1_espsha[20] = { 0 }; + uint8_t sha1_mbedtls[20] = { 0 }; + uint8_t sha256_espsha[32] = { 0 }; + uint8_t sha256_mbedtls[32] = { 0 }; + uint8_t sha512_espsha[64] = { 0 }; + uint8_t sha512_mbedtls[64] = { 0 }; + + const size_t LEN = 1024 * 1024; + + /* mmap() 1MB of flash, we don't care what it is really */ + esp_err_t err = spi_flash_mmap(0x0, LEN, SPI_FLASH_MMAP_DATA, &ptr, &handle); + + TEST_ASSERT_EQUAL_HEX32(ESP_OK, err); + TEST_ASSERT_NOT_NULL(ptr); + + /* Compare esp_sha() result to the mbedTLS result, should always be the same */ + + esp_sha(SHA1, ptr, LEN, sha1_espsha); + int r = mbedtls_sha1_ret(ptr, LEN, sha1_mbedtls); + TEST_ASSERT_EQUAL(0, r); + + esp_sha(SHA2_256, ptr, LEN, sha256_espsha); + r = mbedtls_sha256_ret(ptr, LEN, sha256_mbedtls, 0); + TEST_ASSERT_EQUAL(0, r); + + esp_sha(SHA2_512, ptr, LEN, sha512_espsha); + r = mbedtls_sha512_ret(ptr, LEN, sha512_mbedtls, 0); + TEST_ASSERT_EQUAL(0, r); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha1_espsha, sha1_mbedtls, sizeof(sha1_espsha), "SHA1 results should match"); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_espsha, sha256_mbedtls, sizeof(sha256_espsha), "SHA256 results should match"); + + TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_espsha, sha512_mbedtls, sizeof(sha512_espsha), "SHA512 results should match"); +} + diff --git a/components/idf_test/include/idf_performance.h b/components/idf_test/include/idf_performance.h index 6a67e4b5e..19ee6b0fe 100644 --- a/components/idf_test/include/idf_performance.h +++ b/components/idf_test/include/idf_performance.h @@ -22,30 +22,50 @@ // events dispatched per second by event loop library #define IDF_PERFORMANCE_MIN_EVENT_DISPATCH 25000 #define IDF_PERFORMANCE_MIN_EVENT_DISPATCH_PSRAM 21000 -// esp_sha() time to process 32KB of input data from RAM -#define IDF_PERFORMANCE_MAX_ESP32_TIME_SHA1_32KB 5000 -#define IDF_PERFORMANCE_MAX_ESP32_TIME_SHA512_32KB 4500 + +// floating point instructions per divide and per sqrt (configured for worst-case with PSRAM workaround) +#define IDF_PERFORMANCE_MAX_ESP32_CYCLES_PER_DIV 70 +#define IDF_PERFORMANCE_MAX_ESP32_CYCLES_PER_SQRT 140 + +#define IDF_PERFORMANCE_MAX_SPILL_REG_CYCLES 150 +#define IDF_PERFORMANCE_MAX_ISR_ENTER_CYCLES 290 +#define IDF_PERFORMANCE_MAX_ISR_EXIT_CYCLES 565 + +#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_MBSEC_TOHOST_4BIT 13000 +#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_MBSEC_FRHOST_4BIT 13000 +#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_MBSEC_TOHOST_1BIT 4000 +#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_MBSEC_FRHOST_1BIT 4000 +#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_MBSEC_TOHOST_SPI 1000 +#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_MBSEC_FRHOST_SPI 1000 + +#ifdef CONFIG_IDF_TARGET_ESP32 // AES-CBC hardware throughput (accounts for worst-case performance with PSRAM workaround) #define IDF_PERFORMANCE_MIN_AES_CBC_THROUGHPUT_MBSEC 8.2 -// floating point instructions per divide and per sqrt (configured for worst-case with PSRAM workaround) -#define IDF_PERFORMANCE_MAX_ESP32_CYCLES_PER_DIV 70 -#define IDF_PERFORMANCE_MAX_ESP32_CYCLES_PER_SQRT 140 + // SHA256 hardware throughput at 240MHz, threshold set lower than worst case #define IDF_PERFORMANCE_MIN_SHA256_THROUGHPUT_MBSEC 9.0 -#define IDF_PERFORMANCE_MAX_SPILL_REG_CYCLES 150 -#define IDF_PERFORMANCE_MAX_ISR_ENTER_CYCLES 290 -#define IDF_PERFORMANCE_MAX_ISR_EXIT_CYCLES 565 +// esp_sha() time to process 32KB of input data from RAM +#define IDF_PERFORMANCE_MAX_TIME_SHA1_32KB 5000 +#define IDF_PERFORMANCE_MAX_TIME_SHA512_32KB 4500 +#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PUBLIC_OP 19000 +#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PRIVATE_OP 180000 +#define IDF_PERFORMANCE_MAX_RSA_4096KEY_PUBLIC_OP 65000 +#define IDF_PERFORMANCE_MAX_RSA_4096KEY_PRIVATE_OP 850000 -#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PUBLIC_OP 19000 -#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PRIVATE_OP 180000 -#define IDF_PERFORMANCE_MAX_RSA_4096KEY_PUBLIC_OP 65000 -#define IDF_PERFORMANCE_MAX_RSA_4096KEY_PRIVATE_OP 850000 +#elif defined CONFIG_IDF_TARGET_ESP32S2BETA +#define IDF_PERFORMANCE_MIN_AES_CBC_THROUGHPUT_MBSEC 14.4 -#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_MBSEC_TOHOST_4BIT 13000 -#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_MBSEC_FRHOST_4BIT 13000 -#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_MBSEC_TOHOST_1BIT 4000 -#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_MBSEC_FRHOST_1BIT 4000 -#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_MBSEC_TOHOST_SPI 1000 -#define IDF_PERFORMANCE_MIN_SDIO_THROUGHPUT_MBSEC_FRHOST_SPI 1000 +// SHA256 hardware throughput at 240MHz, threshold set lower than worst case +#define IDF_PERFORMANCE_MIN_SHA256_THROUGHPUT_MBSEC 19.8 +// esp_sha() time to process 32KB of input data from RAM +#define IDF_PERFORMANCE_MAX_TIME_SHA1_32KB 1000 +#define IDF_PERFORMANCE_MAX_TIME_SHA512_32KB 900 + +#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PUBLIC_OP 14000 +#define IDF_PERFORMANCE_MAX_RSA_2048KEY_PRIVATE_OP 100000 +#define IDF_PERFORMANCE_MAX_RSA_4096KEY_PUBLIC_OP 60000 +#define IDF_PERFORMANCE_MAX_RSA_4096KEY_PRIVATE_OP 600000 + +#endif //CONFIG_IDF_TARGET_ESP32S2BETA diff --git a/components/mbedtls/Kconfig b/components/mbedtls/Kconfig index 3aaa3dead..646b1d3b8 100644 --- a/components/mbedtls/Kconfig +++ b/components/mbedtls/Kconfig @@ -131,8 +131,6 @@ menu "mbedTLS" config MBEDTLS_HARDWARE_AES bool "Enable hardware AES acceleration" - depends on IDF_TARGET_ESP32 - # ToDo: remove once hardware AES acceleration is supported on esp32s2 default y help Enable hardware accelerated AES encryption & decryption. diff --git a/components/mbedtls/port/esp32s2beta/aes.c b/components/mbedtls/port/esp32s2beta/aes.c index 2740b45a2..6aeec0319 100644 --- a/components/mbedtls/port/esp32s2beta/aes.c +++ b/components/mbedtls/port/esp32s2beta/aes.c @@ -39,6 +39,7 @@ #define AES_BLOCK_BYTES 16 + /* AES uses a spinlock mux not a lock as the underlying block operation only takes a small number of cycles, much less than using a mutex for this. @@ -48,6 +49,11 @@ */ static portMUX_TYPE aes_spinlock = portMUX_INITIALIZER_UNLOCKED; +static inline bool valid_key_length(const esp_aes_context *ctx) +{ + return ctx->key_bytes == 128/8 || ctx->key_bytes == 192/8 || ctx->key_bytes == 256/8; +} + void esp_aes_acquire_hardware( void ) { /* newlib locks lazy initialize on ESP-IDF */ @@ -99,6 +105,7 @@ int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key, } ctx->key_bytes = keybits / 8; memcpy(ctx->key, key, ctx->key_bytes); + ctx->key_in_hardware = 0; return 0; } @@ -113,22 +120,46 @@ static inline void esp_aes_setkey_hardware( esp_aes_context *ctx, int mode) const uint32_t MODE_DECRYPT_BIT = 4; unsigned mode_reg_base = (mode == ESP_AES_ENCRYPT) ? 0 : MODE_DECRYPT_BIT; - memcpy((uint32_t *)AES_KEY_BASE, ctx->key, ctx->key_bytes); + ctx->key_in_hardware = 0; + + for (int i = 0; i < ctx->key_bytes/4; ++i) { + REG_WRITE(AES_KEY_BASE + i * 4, *(((uint32_t *)ctx->key) + i)); + ctx->key_in_hardware += 4; + } + REG_WRITE(AES_MODE_REG, mode_reg_base + ((ctx->key_bytes / 8) - 2)); + + /* Fault injection check: all words of key data should have been written to hardware */ + if (ctx->key_in_hardware < 16 + || ctx->key_in_hardware != ctx->key_bytes) { + abort(); + } } /* Run a single 16 byte block of AES, using the hardware engine. * * Call only while holding esp_aes_acquire_hardware(). */ -static inline void esp_aes_block(const void *input, void *output) +static inline int esp_aes_block(esp_aes_context *ctx, const void *input, void *output) { + /* If no key is written to hardware yet, either the user hasn't called + mbedtls_aes_setkey_enc/mbedtls_aes_setkey_dec - meaning we also don't + know which mode to use - or a fault skipped the + key write to hardware. Treat this as a fatal error and zero the output block. + */ + if (ctx->key_in_hardware != ctx->key_bytes) { + bzero(output, 16); + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + } + memcpy((void *)AES_TEXT_IN_BASE, input, AES_BLOCK_BYTES); REG_WRITE(AES_TRIGGER_REG, 1); while (REG_READ(AES_STATE_REG) != 0) { } memcpy(output, (void *)AES_TEXT_OUT_BASE, AES_BLOCK_BYTES); + + return 0; } /* @@ -138,11 +169,17 @@ int esp_internal_aes_encrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) { + int r; + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + esp_aes_acquire_hardware(); esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT); - esp_aes_block(input, output); + r = esp_aes_block(ctx, input, output); esp_aes_release_hardware(); - return 0; + return r; } void esp_aes_encrypt( esp_aes_context *ctx, @@ -160,11 +197,17 @@ int esp_internal_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) { + int r; + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + esp_aes_acquire_hardware(); esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT); - esp_aes_block(input, output); + r = esp_aes_block(ctx, input, output); esp_aes_release_hardware(); - return 0; + return r; } void esp_aes_decrypt( esp_aes_context *ctx, @@ -183,12 +226,19 @@ int esp_aes_crypt_ecb( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) { + int r; + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; esp_aes_setkey_hardware(ctx, mode); - esp_aes_block(input, output); + r = esp_aes_block(ctx, input, output); esp_aes_release_hardware(); - return 0; + return r; } @@ -211,15 +261,18 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx, if ( length % 16 ) { return ( ERR_ESP_AES_INVALID_INPUT_LENGTH ); } + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } esp_aes_acquire_hardware(); - + ctx->key_in_hardware = 0; esp_aes_setkey_hardware(ctx, mode); if ( mode == ESP_AES_DECRYPT ) { while ( length > 0 ) { memcpy(temp, input_words, 16); - esp_aes_block(input_words, output_words); + esp_aes_block(ctx, input_words, output_words); for ( i = 0; i < 4; i++ ) { output_words[i] = output_words[i] ^ iv_words[i]; @@ -238,7 +291,7 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx, output_words[i] = input_words[i] ^ iv_words[i]; } - esp_aes_block(output_words, output_words); + esp_aes_block(ctx, output_words, output_words); memcpy( iv_words, output_words, 16 ); input_words += 4; @@ -266,14 +319,19 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx, int c; size_t n = *iv_off; + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT); if ( mode == ESP_AES_DECRYPT ) { while ( length-- ) { if ( n == 0 ) { - esp_aes_block(iv, iv ); + esp_aes_block(ctx, iv, iv ); } c = *input++; @@ -285,7 +343,7 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx, } else { while ( length-- ) { if ( n == 0 ) { - esp_aes_block(iv, iv ); + esp_aes_block(ctx, iv, iv ); } iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); @@ -314,13 +372,18 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx, unsigned char c; unsigned char ov[17]; + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT); while ( length-- ) { memcpy( ov, iv, 16 ); - esp_aes_block(iv, iv); + esp_aes_block(ctx, iv, iv); if ( mode == ESP_AES_DECRYPT ) { ov[16] = *input; @@ -354,13 +417,18 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx, int c, i; size_t n = *nc_off; + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT); while ( length-- ) { if ( n == 0 ) { - esp_aes_block(nonce_counter, stream_block); + esp_aes_block(ctx, nonce_counter, stream_block); for ( i = 16; i > 0; i-- ) if ( ++nonce_counter[i - 1] != 0 ) { @@ -379,3 +447,296 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx, return 0; } + +/* + * AES-OFB (Output Feedback Mode) buffer encryption/decryption + */ +int esp_aes_crypt_ofb( esp_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = 0; + size_t n; + + if ( ctx == NULL || iv_off == NULL || iv == NULL || + input == NULL || output == NULL ) { + return MBEDTLS_ERR_AES_BAD_INPUT_DATA; + } + + n = *iv_off; + + if( n > 15 ) { + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); + } + + if (!valid_key_length(ctx)) { + return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + } + + esp_aes_acquire_hardware(); + ctx->key_in_hardware = 0; + + esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT); + + while( length-- ) { + if( n == 0 ) { + esp_aes_block(ctx, iv, iv); + } + *output++ = *input++ ^ iv[n]; + + n = ( n + 1 ) & 0x0F; + } + + *iv_off = n; + + esp_aes_release_hardware(); + + return( ret ); +} + + +/* Below XTS implementation is copied aes.c of mbedtls library. + * When MBEDTLS_AES_ALT is defined mbedtls expects alternate + * definition of XTS functions to be available. Even if this + * could have been avoided, it is done for consistency reason. + */ + +void esp_aes_xts_init( esp_aes_xts_context *ctx ) +{ + esp_aes_init( &ctx->crypt ); + esp_aes_init( &ctx->tweak ); +} + +void esp_aes_xts_free( esp_aes_xts_context *ctx ) +{ + esp_aes_free( &ctx->crypt ); + esp_aes_free( &ctx->tweak ); +} + +static int esp_aes_xts_decode_keys( const unsigned char *key, + unsigned int keybits, + const unsigned char **key1, + unsigned int *key1bits, + const unsigned char **key2, + unsigned int *key2bits ) +{ + const unsigned int half_keybits = keybits / 2; + const unsigned int half_keybytes = half_keybits / 8; + + switch( keybits ) + { + case 256: break; + case 512: break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + + *key1bits = half_keybits; + *key2bits = half_keybits; + *key1 = &key[0]; + *key2 = &key[half_keybytes]; + + return 0; +} + +int esp_aes_xts_setkey_enc( esp_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + ret = esp_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for the encryption mode. */ + ret = esp_aes_setkey( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for encryption. */ + return esp_aes_setkey( &ctx->crypt, key1, key1bits ); +} + +int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + ret = esp_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for encryption. */ + ret = esp_aes_setkey( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for decryption. */ + return esp_aes_setkey( &ctx->crypt, key1, key1bits ); +} + +/* Endianess with 64 bits values */ +#ifndef GET_UINT64_LE +#define GET_UINT64_LE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \ + | ( (uint64_t) (b)[(i) + 6] << 48 ) \ + | ( (uint64_t) (b)[(i) + 5] << 40 ) \ + | ( (uint64_t) (b)[(i) + 4] << 32 ) \ + | ( (uint64_t) (b)[(i) + 3] << 24 ) \ + | ( (uint64_t) (b)[(i) + 2] << 16 ) \ + | ( (uint64_t) (b)[(i) + 1] << 8 ) \ + | ( (uint64_t) (b)[(i) ] ); \ +} +#endif + +#ifndef PUT_UINT64_LE +#define PUT_UINT64_LE(n,b,i) \ +{ \ + (b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) ] = (unsigned char) ( (n) ); \ +} +#endif + +typedef unsigned char esp_be128[16]; + +/* + * GF(2^128) multiplication function + * + * This function multiplies a field element by x in the polynomial field + * representation. It uses 64-bit word operations to gain speed but compensates + * for machine endianess and hence works correctly on both big and little + * endian machines. + */ +static void esp_gf128mul_x_ble( unsigned char r[16], + const unsigned char x[16] ) +{ + uint64_t a, b, ra, rb; + + GET_UINT64_LE( a, x, 0 ); + GET_UINT64_LE( b, x, 8 ); + + ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) ); + rb = ( a >> 63 ) | ( b << 1 ); + + PUT_UINT64_LE( ra, r, 0 ); + PUT_UINT64_LE( rb, r, 8 ); +} + +/* + * AES-XTS buffer encryption/decryption + */ +int esp_aes_crypt_xts( esp_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t blocks = length / 16; + size_t leftover = length % 16; + unsigned char tweak[16]; + unsigned char prev_tweak[16]; + unsigned char tmp[16]; + + /* Sectors must be at least 16 bytes. */ + if( length < 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* NIST SP 80-38E disallows data units larger than 2**20 blocks. */ + if( length > ( 1 << 20 ) * 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* Compute the tweak. */ + ret = esp_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT, + data_unit, tweak ); + if( ret != 0 ) + return( ret ); + + while( blocks-- ) + { + size_t i; + + if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 ) + { + /* We are on the last block in a decrypt operation that has + * leftover bytes, so we need to use the next tweak for this block, + * and this tweak for the lefover bytes. Save the current tweak for + * the leftovers and then update the current tweak for use on this, + * the last full block. */ + memcpy( prev_tweak, tweak, sizeof( tweak ) ); + esp_gf128mul_x_ble( tweak, tweak ); + } + + for( i = 0; i < 16; i++ ) + tmp[i] = input[i] ^ tweak[i]; + + ret = esp_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return( ret ); + + for( i = 0; i < 16; i++ ) + output[i] = tmp[i] ^ tweak[i]; + + /* Update the tweak for the next block. */ + esp_gf128mul_x_ble( tweak, tweak ); + + output += 16; + input += 16; + } + + if( leftover ) + { + /* If we are on the leftover bytes in a decrypt operation, we need to + * use the previous tweak for these bytes (as saved in prev_tweak). */ + unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak; + + /* We are now on the final part of the data unit, which doesn't divide + * evenly by 16. It's time for ciphertext stealing. */ + size_t i; + unsigned char *prev_output = output - 16; + + /* Copy ciphertext bytes from the previous block to our output for each + * byte of cyphertext we won't steal. At the same time, copy the + * remainder of the input for this final round (since the loop bounds + * are the same). */ + for( i = 0; i < leftover; i++ ) + { + output[i] = prev_output[i]; + tmp[i] = input[i] ^ t[i]; + } + + /* Copy ciphertext bytes from the previous block for input in this + * round. */ + for( ; i < 16; i++ ) + tmp[i] = prev_output[i] ^ t[i]; + + ret = esp_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return ret; + + /* Write the result back to the previous block, overriding the previous + * output we copied. */ + for( i = 0; i < 16; i++ ) + prev_output[i] = tmp[i] ^ t[i]; + } + + return( 0 ); +} \ No newline at end of file diff --git a/components/mbedtls/port/esp32s2beta/esp_bignum.c b/components/mbedtls/port/esp32s2beta/esp_bignum.c index 5c74fbc16..af9aec8cd 100644 --- a/components/mbedtls/port/esp32s2beta/esp_bignum.c +++ b/components/mbedtls/port/esp32s2beta/esp_bignum.c @@ -48,28 +48,6 @@ static const __attribute__((unused)) char *TAG = "bignum"; #define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ #define biL (ciL << 3) /* bits in limb */ -#if defined(CONFIG_MBEDTLS_MPI_USE_INTERRUPT) -static SemaphoreHandle_t op_complete_sem; - -static IRAM_ATTR void rsa_complete_isr(void *arg) -{ - BaseType_t higher_woken; - DPORT_REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1); - xSemaphoreGiveFromISR(op_complete_sem, &higher_woken); - if (higher_woken) { - portYIELD_FROM_ISR(); - } -} - -static void rsa_isr_initialise(void) -{ - if (op_complete_sem == NULL) { - op_complete_sem = xSemaphoreCreateBinary(); - esp_intr_alloc(ETS_RSA_INTR_SOURCE, 0, rsa_complete_isr, NULL, NULL); - } -} - -#endif /* CONFIG_MBEDTLS_MPI_USE_INTERRUPT */ static _lock_t mpi_lock; @@ -89,10 +67,6 @@ void esp_mpi_acquire_hardware( void ) while(DPORT_REG_READ(RSA_QUERY_CLEAN_REG) != 1) { } // Note: from enabling RSA clock to here takes about 1.3us - -#ifdef CONFIG_MBEDTLS_MPI_USE_INTERRUPT - rsa_isr_initialise(); -#endif } void esp_mpi_release_hardware( void ) @@ -106,6 +80,13 @@ void esp_mpi_release_hardware( void ) _lock_release(&mpi_lock); } +/* Convert bit count to word count + */ +static inline size_t bits_to_words(size_t bits) +{ + return (bits + 31) / 32; +} + /* Return the number of words actually used to represent an mpi number. @@ -124,9 +105,6 @@ static size_t mpi_words(const mbedtls_mpi *mpi) If num_words is higher than the number of words in the bignum then these additional words will be zeroed in the memory buffer. - - As this function only writes to DPORT memory, no DPORT_STALL_OTHER_CPU_START() - is required. */ static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, size_t num_words) { @@ -152,7 +130,6 @@ static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, s Can return a failure result if fails to grow the MPI result. - Cannot be called inside DPORT_STALL_OTHER_CPU_START() (as may allocate memory). */ static inline int mem_block_to_mpi(mbedtls_mpi *x, uint32_t mem_base, int num_words) { @@ -231,9 +208,6 @@ static int calculate_rinv(mbedtls_mpi *Rinv, const mbedtls_mpi *M, int num_words /* Begin an RSA operation. op_reg specifies which 'START' register to write to. - - Because the only DPORT operations here are writes, - does not need protecting via DPORT_STALL_OTHER_CPU_START(); */ static inline void start_op(uint32_t op_reg) { @@ -247,26 +221,14 @@ static inline void start_op(uint32_t op_reg) } /* Wait for an RSA operation to complete. - - This should NOT be called inside a DPORT_STALL_OTHER_CPU_START(), as it will stall the other CPU for an unacceptably long - period (and - depending on config - may require interrupts enabled). */ static inline void wait_op_complete(uint32_t op_reg) { -#ifdef CONFIG_MBEDTLS_MPI_USE_INTERRUPT - if (!xSemaphoreTake(op_complete_sem, 2000 / portTICK_PERIOD_MS)) { - ESP_LOGE(TAG, "Timed out waiting for RSA operation (op_reg 0x%x int_reg 0x%x)", - op_reg, DPORT_REG_READ(RSA_QUERY_INTERRUPT_REG)); - abort(); /* indicates a fundamental problem with driver */ - } -#else while(DPORT_REG_READ(RSA_QUERY_INTERRUPT_REG) != 1) { } /* clear the interrupt */ DPORT_REG_WRITE(RSA_CLEAR_INTERRUPT_REG, 1); -#endif - } /* Z = (X * Y) mod M @@ -275,12 +237,16 @@ static inline void wait_op_complete(uint32_t op_reg) */ int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, const mbedtls_mpi *M) { + int ret; + size_t y_bits = mbedtls_mpi_bitlen(Y); + size_t x_words = mpi_words(X); + size_t y_words = mpi_words(Y); size_t m_words = mpi_words(M); mbedtls_mpi Rinv; mbedtls_mpi_uint Mprime; - size_t num_words = MAX(MAX(m_words, mpi_words(X)), mpi_words(Y)); + size_t num_words = MAX(MAX(m_words, x_words), y_words); if (num_words * 32 > 4096) { return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; @@ -288,25 +254,31 @@ int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi /* Calculate and load the first stage montgomery multiplication */ mbedtls_mpi_init(&Rinv); - MBEDTLS_MPI_CHK(calculate_rinv(&Rinv, M, m_words)); + MBEDTLS_MPI_CHK(calculate_rinv(&Rinv, M, num_words)); Mprime = modular_inverse(M); esp_mpi_acquire_hardware(); - DPORT_REG_WRITE(RSA_LENGTH_REG, (num_words - 1)); + DPORT_REG_WRITE(RSA_LENGTH_REG, (num_words-1)); DPORT_REG_WRITE(RSA_M_DASH_REG, (uint32_t)Mprime); /* Load M, X, Rinv, Mprime (Mprime is mod 2^32) */ mpi_to_mem_block(RSA_MEM_M_BLOCK_BASE, M, num_words); + mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, &Rinv, num_words); mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words); mpi_to_mem_block(RSA_MEM_Y_BLOCK_BASE, Y, num_words); - mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, &Rinv, num_words); + + /* Enable acceleration options */ + DPORT_REG_WRITE(RSA_CONSTANT_TIME_REG, 0); + DPORT_REG_WRITE(RSA_SEARCH_OPEN_REG, 1); + DPORT_REG_WRITE(RSA_SEARCH_POS_REG, y_bits - 1); /* Execute first stage montgomery multiplication */ start_op(RSA_MOD_MULT_START_REG); - wait_op_complete(RSA_MOD_MULT_START_REG); + DPORT_REG_WRITE(RSA_SEARCH_OPEN_REG, 1); + mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, m_words); esp_mpi_release_hardware(); @@ -329,6 +301,7 @@ int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi int mbedtls_mpi_exp_mod( mbedtls_mpi* Z, const mbedtls_mpi* X, const mbedtls_mpi* Y, const mbedtls_mpi* M, mbedtls_mpi* _Rinv ) { int ret = 0; + size_t y_bits = mbedtls_mpi_bitlen(Y); size_t x_words = mpi_words(X); size_t y_words = mpi_words(Y); size_t m_words = mpi_words(M); @@ -343,6 +316,18 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi* Z, const mbedtls_mpi* X, const mbedtls_mpi */ num_words = MAX(m_words, MAX(x_words, y_words)); + if (mbedtls_mpi_cmp_int(M, 0) <= 0 || (M->p[0] & 1) == 0) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + if (mbedtls_mpi_cmp_int(Y, 0) < 0) { + return MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + } + + if (mbedtls_mpi_cmp_int(Y, 0) == 0) { + return mbedtls_mpi_lset(Z, 1); + } + if (num_words * 32 > 4096) { return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; } @@ -372,20 +357,28 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi* Z, const mbedtls_mpi* X, const mbedtls_mpi mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, Rinv, num_words); DPORT_REG_WRITE(RSA_M_DASH_REG, Mprime); + /* Enable acceleration options */ DPORT_REG_WRITE(RSA_CONSTANT_TIME_REG, 0); DPORT_REG_WRITE(RSA_SEARCH_OPEN_REG, 1); - DPORT_REG_WRITE(RSA_SEARCH_POS_REG, (y_words * 32) - 1); + DPORT_REG_WRITE(RSA_SEARCH_POS_REG, y_bits - 1); start_op(RSA_MODEXP_START_REG); wait_op_complete(RSA_MODEXP_START_REG); DPORT_REG_WRITE(RSA_SEARCH_OPEN_REG, 0); - DPORT_REG_WRITE(RSA_SEARCH_POS_REG, (m_words * 32) - 1); ret = mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, m_words); esp_mpi_release_hardware(); + // Compensate for negative X + if (X->s == -1 && (Y->p[0] & 1) != 0) { + Z->s = -1; + MBEDTLS_MPI_CHK(mbedtls_mpi_add_mpi(Z, M, Z)); + } else { + Z->s = 1; + } + cleanup: if (_Rinv == NULL) { mbedtls_mpi_free(&Rinv_new); @@ -398,23 +391,21 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi* Z, const mbedtls_mpi* X, const mbedtls_mpi #if defined(MBEDTLS_MPI_MUL_MPI_ALT) /* MBEDTLS_MPI_MUL_MPI_ALT */ -static int mpi_mult_mpi_failover_mod_mult(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words); -static int mpi_mult_mpi_overlong(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t Y_bits, size_t words_result); +static int mpi_mult_mpi_failover_mod_mult(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t z_words); +static int mpi_mult_mpi_overlong(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t y_words, size_t z_words); /* Z = X * Y */ int mbedtls_mpi_mul_mpi( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y ) { int ret = 0; - size_t bits_x, bits_y, words_x, words_y, words_mult, words_z; + size_t x_bits = mbedtls_mpi_bitlen(X); + size_t y_bits = mbedtls_mpi_bitlen(Y); + size_t x_words = bits_to_words(x_bits); + size_t y_words = bits_to_words(y_bits); + size_t num_words = MAX(x_words, y_words); + size_t z_words = x_words + y_words; - /* Count words needed for X & Y in hardware */ - bits_x = mbedtls_mpi_bitlen(X); - bits_y = mbedtls_mpi_bitlen(Y); - - words_x = (bits_x + 7) / 8; - words_y = (bits_y + 7) / 8; - - /* Short-circuit eval if either argument is 0 or 1. + /* Short-circuit eval if either argument is 0 or 1. This is needed as the mpi modular division argument will sometimes call in here when one @@ -424,26 +415,21 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi This leaks some timing information, although overall there is a lot less timing variation than a software MPI approach. */ - if (bits_x == 0 || bits_y == 0) { + if (x_bits == 0 || y_bits== 0) { mbedtls_mpi_lset(Z, 0); return 0; } - if (bits_x == 1) { + if (x_bits == 1) { ret = mbedtls_mpi_copy(Z, Y); Z->s *= X->s; return ret; } - if (bits_y == 1) { + if (y_bits == 1) { ret = mbedtls_mpi_copy(Z, X); Z->s *= Y->s; return ret; } - words_mult = (words_x > words_y ? words_x : words_y); - - /* Result Z has to have room for double the larger factor */ - words_z = words_mult * 2; - /* If either factor is over 2048 bits, we can't use the standard hardware multiplier (it assumes result is double longest factor, and result is max 4096 bits.) @@ -451,44 +437,44 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi multiplication doesn't have the same restriction, so result is simply the number of bits in X plus number of bits in in Y.) */ - if (words_mult * 32 > 2048) { - /* Calculate new length of Z */ - words_z = (bits_x + bits_y + 31) / 32; - if (words_z * 32 <= 4096) { + + + + if (num_words * 32 > 2048) { + if (z_words * 32 <= 4096) { /* Note: it's possible to use mpi_mult_mpi_overlong for this case as well, but it's very slightly slower and requires a memory allocation. */ - return mpi_mult_mpi_failover_mod_mult(Z, X, Y, words_z); + return mpi_mult_mpi_failover_mod_mult(Z, X, Y, z_words); } else { /* Still too long for the hardware unit... */ - if(bits_y > bits_x) { - return mpi_mult_mpi_overlong(Z, X, Y, bits_y, words_z); + if(y_words > x_words) { + return mpi_mult_mpi_overlong(Z, X, Y, y_words, z_words); } else { - return mpi_mult_mpi_overlong(Z, Y, X, bits_x, words_z); + return mpi_mult_mpi_overlong(Z, Y, X, x_words, z_words); } } } /* Otherwise, we can use the (faster) multiply hardware unit */ - esp_mpi_acquire_hardware(); /* Copy X (right-extended) & Y (left-extended) to memory block */ - mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, words_mult); - mpi_to_mem_block(RSA_MEM_Z_BLOCK_BASE + words_mult * 4, Y, words_mult); + mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words); + mpi_to_mem_block(RSA_MEM_Z_BLOCK_BASE + num_words * 4, Y, num_words); /* NB: as Y is left-extended, we don't zero the bottom words_mult words of Y block. This is OK for now because zeroing is done by hardware when we do esp_mpi_acquire_hardware(). */ DPORT_REG_WRITE(RSA_M_DASH_REG, 0); - DPORT_REG_WRITE(RSA_LENGTH_REG, (words_z - 1)); + DPORT_REG_WRITE(RSA_LENGTH_REG, (num_words*2 - 1)); start_op(RSA_MULT_START_REG); wait_op_complete(RSA_MULT_START_REG); /* Read back the result */ - ret = mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, words_z); + ret = mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, z_words); Z->s = X->s * Y->s; @@ -501,7 +487,7 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi multiplication to calculate an mbedtls_mpi_mult_mpi result where either A or B are >2048 bits so can't use the standard multiplication method. - Result (A bits + B bits) must still be less than 4096 bits. + Result (number of words, based on A bits + B bits) must still be less than 4096 bits. This case is simpler than the general case modulo multiply of esp_mpi_mul_mpi_mod() because we can control the other arguments: @@ -567,29 +553,28 @@ static int mpi_mult_mpi_failover_mod_mult(mbedtls_mpi *Z, const mbedtls_mpi *X, Note that this function may recurse multiple times, if both X & Y are too long for the hardware multiplication unit. */ -static int mpi_mult_mpi_overlong(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t bits_y, size_t words_result) +static int mpi_mult_mpi_overlong(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t y_words, size_t z_words) { int ret = 0; mbedtls_mpi Ztemp; - const size_t limbs_y = (bits_y + biL - 1) / biL; /* Rather than slicing in two on bits we slice on limbs (32 bit words) */ - const size_t limbs_slice = limbs_y / 2; + const size_t words_slice = y_words / 2; /* Yp holds lower bits of Y (declared to reuse Y's array contents to save on copying) */ const mbedtls_mpi Yp = { .p = Y->p, - .n = limbs_slice, + .n = words_slice, .s = Y->s }; /* Ypp holds upper bits of Y, right shifted (also reuses Y's array contents) */ const mbedtls_mpi Ypp = { - .p = Y->p + limbs_slice, - .n = limbs_y - limbs_slice, + .p = Y->p + words_slice, + .n = y_words - words_slice, .s = Y->s }; mbedtls_mpi_init(&Ztemp); /* Grow Z to result size early, avoid interim allocations */ - mbedtls_mpi_grow(Z, words_result); + mbedtls_mpi_grow(Z, z_words); /* Get result Ztemp = Yp * X (need temporary variable Ztemp) */ MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi(&Ztemp, X, &Yp) ); @@ -598,7 +583,7 @@ static int mpi_mult_mpi_overlong(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbe MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi(Z, X, &Ypp) ); /* Z = Z << b */ - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(Z, limbs_slice * biL) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(Z, words_slice * 32) ); /* Z += Ztemp */ MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi(Z, Z, &Ztemp) ); diff --git a/components/mbedtls/port/esp_sha.c b/components/mbedtls/port/esp_sha.c index 2c40f2c5d..8d2242eff 100644 --- a/components/mbedtls/port/esp_sha.c +++ b/components/mbedtls/port/esp_sha.c @@ -15,12 +15,18 @@ #include #include #include - +#if CONFIG_IDF_TARGET_ESP32 #include "esp32/sha.h" +#elif CONFIG_IDF_TARGET_ESP32S2BETA +#include "esp32s2beta/sha.h" +#endif + #include #include #include + +#if CONFIG_IDF_TARGET_ESP32 void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output) { int ret; @@ -77,3 +83,4 @@ void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, uns } } +#endif diff --git a/components/mbedtls/port/esp_sha1.c b/components/mbedtls/port/esp_sha1.c index ba5231b9c..637009070 100644 --- a/components/mbedtls/port/esp_sha1.c +++ b/components/mbedtls/port/esp_sha1.c @@ -47,7 +47,11 @@ #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ +#if CONFIG_IDF_TARGET_ESP32 #include "esp32/sha.h" +#elif CONFIG_IDF_TARGET_ESP32S2BETA +#include "esp32s2beta/sha.h" +#endif /* Implementation that should never be optimized out by the compiler */ static void mbedtls_zeroize( void *v, size_t n ) { diff --git a/components/mbedtls/port/esp_sha256.c b/components/mbedtls/port/esp_sha256.c index 7a1e2a147..7ec7913b6 100644 --- a/components/mbedtls/port/esp_sha256.c +++ b/components/mbedtls/port/esp_sha256.c @@ -48,7 +48,11 @@ #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ +#if CONFIG_IDF_TARGET_ESP32 #include "esp32/sha.h" +#elif CONFIG_IDF_TARGET_ESP32S2BETA +#include "esp32s2beta/sha.h" +#endif /* Implementation that should never be optimized out by the compiler */ static void mbedtls_zeroize( void *v, size_t n ) { diff --git a/components/mbedtls/port/esp_sha512.c b/components/mbedtls/port/esp_sha512.c index 58cd79097..bd399babf 100644 --- a/components/mbedtls/port/esp_sha512.c +++ b/components/mbedtls/port/esp_sha512.c @@ -54,7 +54,11 @@ #endif /* MBEDTLS_PLATFORM_C */ #endif /* MBEDTLS_SELF_TEST */ +#if CONFIG_IDF_TARGET_ESP32 #include "esp32/sha.h" +#elif CONFIG_IDF_TARGET_ESP32S2BETA +#include "esp32s2beta/sha.h" +#endif inline static esp_sha_type sha_type(const mbedtls_sha512_context *ctx) { diff --git a/components/mbedtls/port/include/aes_alt.h b/components/mbedtls/port/include/aes_alt.h index 993d0689e..411f71049 100644 --- a/components/mbedtls/port/include/aes_alt.h +++ b/components/mbedtls/port/include/aes_alt.h @@ -28,7 +28,11 @@ extern "C" { #endif #if defined(MBEDTLS_AES_ALT) +#if CONFIG_IDF_TARGET_ESP32 #include "esp32/aes.h" +#elif CONFIG_IDF_TARGET_ESP32S2BETA +#include "esp32s2beta/aes.h" +#endif typedef esp_aes_context mbedtls_aes_context; diff --git a/components/mbedtls/port/include/esp32s2beta/aes.h b/components/mbedtls/port/include/esp32s2beta/aes.h index 2c5853322..3a3419bf6 100644 --- a/components/mbedtls/port/include/esp32s2beta/aes.h +++ b/components/mbedtls/port/include/esp32s2beta/aes.h @@ -48,9 +48,21 @@ extern "C" { */ typedef struct { uint8_t key_bytes; + volatile uint8_t key_in_hardware; /* This variable is used for fault injection checks, so marked volatile to avoid optimisation */ uint8_t key[32]; } esp_aes_context; +/** + * \brief The AES XTS context-type definition. + */ +typedef struct +{ + esp_aes_context crypt; /*!< The AES context to use for AES block + encryption or decryption. */ + esp_aes_context tweak; /*!< The AES context used for tweak + computation. */ +} esp_aes_xts_context; + /** * \brief Lock access to AES hardware unit * @@ -86,6 +98,33 @@ void esp_aes_init( esp_aes_context *ctx ); */ void esp_aes_free( esp_aes_context *ctx ); +/* + * \brief This function initializes the specified AES XTS context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES XTS context to initialize. + */ +void esp_aes_xts_init( esp_aes_xts_context *ctx ); + +/** + * \brief This function releases and clears the specified AES XTS context. + * + * \param ctx The AES XTS context to clear. + */ +void esp_aes_xts_free( esp_aes_xts_context *ctx ); + +/** + * \brief AES set key schedule (encryption or decryption) + * + * \param ctx AES context to be initialized + * \param key encryption key + * \param keybits must be 128, 192 or 256 + * + * \return 0 if successful, or ERR_AES_INVALID_KEY_LENGTH + */ + /** * \brief AES set key schedule (encryption or decryption) * @@ -233,6 +272,62 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx, const unsigned char *input, unsigned char *output ); +/** + * \brief This function performs an AES-OFB (Output Feedback Mode) + * encryption or decryption operation. + * + * \param ctx The AES context to use for encryption or decryption. + * It must be initialized and bound to a key. + * \param length The length of the input data. + * \param iv_off The offset in IV (updated after use). + * It must point to a valid \c size_t. + * \param iv The initialization vector (updated after use). + * It must be a readable and writeable buffer of \c 16 Bytes. + * \param input The buffer holding the input data. + * It must be readable and of size \p length Bytes. + * \param output The buffer holding the output data. + * It must be writeable and of size \p length Bytes. + * + * \return \c 0 on success. + */ +int esp_aes_crypt_ofb( esp_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function prepares an XTS context for encryption and + * sets the encryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * \param key The encryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int esp_aes_xts_setkey_enc( esp_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Internal AES block encryption function + * (Only exposed to allow overriding it, + * see AES_ENCRYPT_ALT) + * + * \param ctx AES context + * \param input Plaintext block + * \param output Output (ciphertext) block + */ +int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); + /** * \brief Internal AES block encryption function @@ -262,6 +357,10 @@ int esp_internal_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16 /** Deprecated, see esp_aes_internal_decrypt */ void esp_aes_decrypt( esp_aes_context *ctx, const unsigned char input[16], unsigned char output[16] ) __attribute__((deprecated)); +/** AES-XTS buffer encryption/decryption */ +int esp_aes_crypt_xts( esp_aes_xts_context *ctx, int mode, size_t length, const unsigned char data_unit[16], const unsigned char *input, unsigned char *output ); + + #ifdef __cplusplus } #endif diff --git a/components/mbedtls/test/test_ecp.c b/components/mbedtls/test/test_ecp.c index e6f5602a6..0c8f571db 100644 --- a/components/mbedtls/test/test_ecp.c +++ b/components/mbedtls/test/test_ecp.c @@ -21,7 +21,7 @@ error hex value (mbedTLS uses -N for error codes) */ #define TEST_ASSERT_MBEDTLS_OK(X) TEST_ASSERT_EQUAL_HEX32(0, -(X)) -TEST_CASE_ESP32("mbedtls ECDH Generate Key", "[mbedtls]") +TEST_CASE("mbedtls ECDH Generate Key", "[mbedtls]") { mbedtls_ecdh_context ctx; mbedtls_entropy_context entropy; @@ -48,7 +48,7 @@ TEST_CASE("mbedtls ECP self-tests", "[mbedtls]") TEST_ASSERT_EQUAL(0, mbedtls_ecp_self_test(1)); } -TEST_CASE_ESP32("mbedtls ECP mul w/ koblitz", "[mbedtls]") +TEST_CASE("mbedtls ECP mul w/ koblitz", "[mbedtls]") { /* Test case code via https://github.com/espressif/esp-idf/issues/1556 */ mbedtls_entropy_context ctxEntropy; diff --git a/components/mbedtls/test/test_mbedtls_mpi.c b/components/mbedtls/test/test_mbedtls_mpi.c index 056a1cf14..d30faf3e5 100644 --- a/components/mbedtls/test/test_mbedtls_mpi.c +++ b/components/mbedtls/test/test_mbedtls_mpi.c @@ -165,7 +165,7 @@ static bool test_bignum_modexp(const char *z_str, const char *x_str, const char return fail; } -TEST_CASE_ESP32("test MPI modexp", "[bignum]") +TEST_CASE("test MPI modexp", "[bignum]") { bool test_error = false; printf("Z = (X ^ Y) mod M \n"); diff --git a/components/mbedtls/test/test_mbedtls_sha.c b/components/mbedtls/test/test_mbedtls_sha.c index 8c12b6616..436097f2c 100644 --- a/components/mbedtls/test/test_mbedtls_sha.c +++ b/components/mbedtls/test/test_mbedtls_sha.c @@ -15,7 +15,7 @@ #include "sdkconfig.h" #include "test_apb_dport_access.h" -TEST_CASE_ESP32("mbedtls SHA self-tests", "[mbedtls]") +TEST_CASE("mbedtls SHA self-tests", "[mbedtls]") { start_apb_access_loop(); TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha1_self_test(1), "SHA1 self-tests should pass."); @@ -121,7 +121,7 @@ static void tskRunSHA256Test(void *pvParameters) #define SHA_TASK_STACK_SIZE (10*1024) -TEST_CASE_ESP32("mbedtls SHA multithreading", "[mbedtls]") +TEST_CASE("mbedtls SHA multithreading", "[mbedtls]") { done_sem = xSemaphoreCreateCounting(4, 0); xTaskCreate(tskRunSHA1Test, "SHA1Task1", SHA_TASK_STACK_SIZE, NULL, 3, NULL); @@ -164,13 +164,13 @@ void tskRunSHASelftests(void *param) vTaskDelete(NULL); } -TEST_CASE_ESP32("mbedtls SHA self-tests multithreaded", "[mbedtls]") +TEST_CASE("mbedtls SHA self-tests multithreaded", "[mbedtls]") { done_sem = xSemaphoreCreateCounting(2, 0); xTaskCreate(tskRunSHASelftests, "SHASelftests1", SHA_TASK_STACK_SIZE, NULL, 3, NULL); xTaskCreate(tskRunSHASelftests, "SHASelftests2", SHA_TASK_STACK_SIZE, NULL, 3, NULL); - const int TIMEOUT_MS = 20000; + const int TIMEOUT_MS = 40000; for(int i = 0; i < 2; i++) { if(!xSemaphoreTake(done_sem, TIMEOUT_MS/portTICK_PERIOD_MS)) { @@ -180,7 +180,7 @@ TEST_CASE_ESP32("mbedtls SHA self-tests multithreaded", "[mbedtls]") vSemaphoreDelete(done_sem); } -TEST_CASE_ESP32("mbedtls SHA512 clone", "[mbedtls]") +TEST_CASE("mbedtls SHA512 clone", "[mbedtls]") { mbedtls_sha512_context ctx; mbedtls_sha512_context clone; @@ -205,7 +205,7 @@ TEST_CASE_ESP32("mbedtls SHA512 clone", "[mbedtls]") TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 cloned calculation"); } -TEST_CASE_ESP32("mbedtls SHA384 clone", "[mbedtls]") +TEST_CASE("mbedtls SHA384 clone", "[mbedtls]") { mbedtls_sha512_context ctx; mbedtls_sha512_context clone; @@ -231,7 +231,7 @@ TEST_CASE_ESP32("mbedtls SHA384 clone", "[mbedtls]") } -TEST_CASE_ESP32("mbedtls SHA256 clone", "[mbedtls]") +TEST_CASE("mbedtls SHA256 clone", "[mbedtls]") { mbedtls_sha256_context ctx; mbedtls_sha256_context clone; @@ -276,6 +276,7 @@ static void tskFinaliseSha(void *v_param) vTaskDelete(NULL); } +// No concurrent SHA sessions in esp32s2, only has one engine TEST_CASE_ESP32("mbedtls SHA session passed between tasks" , "[mbedtls]") { finalise_sha_param_t param = { 0 }; diff --git a/components/mbedtls/test/test_sha_perf.c b/components/mbedtls/test/test_sha_perf.c index 9bd609239..1c69af193 100644 --- a/components/mbedtls/test/test_sha_perf.c +++ b/components/mbedtls/test/test_sha_perf.c @@ -11,7 +11,7 @@ #include "test_utils.h" #include "sodium/utils.h" -TEST_CASE_ESP32("mbedtls SHA performance", "[aes]") +TEST_CASE("mbedtls SHA performance", "[aes]") { const unsigned CALLS = 256; const unsigned CALL_SZ = 16*1024; @@ -36,8 +36,8 @@ TEST_CASE_ESP32("mbedtls SHA performance", "[aes]") free(buf); mbedtls_sha256_free(&sha256_ctx); - /* Check the result. Reference value can be calculated using: - * dd if=/dev/zero bs=$((16*1024)) count=256 | tr '\000' '\125' | sha256sum + /* Check the result. Reference value can be calculated using: + * dd if=/dev/zero bs=$((16*1024)) count=256 | tr '\000' '\125' | sha256sum */ const char* expected_hash = "c88df2638fb9699abaad05780fa5e0fdb6058f477069040eac8bed3231286275"; char hash_str[sizeof(sha256) * 2 + 1]; diff --git a/components/protocomm/test/test_protocomm.c b/components/protocomm/test/test_protocomm.c index 1523ddf40..33d547b3d 100644 --- a/components/protocomm/test/test_protocomm.c +++ b/components/protocomm/test/test_protocomm.c @@ -1098,7 +1098,7 @@ static esp_err_t test_security0 (void) return ESP_OK; } -TEST_CASE_ESP32("leak test", "[PROTOCOMM]") +TEST_CASE("leak test", "[PROTOCOMM]") { #ifdef CONFIG_HEAP_TRACING heap_trace_init_standalone(trace_record, NUM_RECORDS); @@ -1144,17 +1144,17 @@ TEST_CASE("security 0 basic test", "[PROTOCOMM]") TEST_ASSERT(test_security0() == ESP_OK); } -TEST_CASE_ESP32("security 1 basic test", "[PROTOCOMM]") +TEST_CASE("security 1 basic test", "[PROTOCOMM]") { TEST_ASSERT(test_security1() == ESP_OK); } -TEST_CASE_ESP32("security 1 no encryption test", "[PROTOCOMM]") +TEST_CASE("security 1 no encryption test", "[PROTOCOMM]") { TEST_ASSERT(test_security1_no_encryption() == ESP_OK); } -TEST_CASE_ESP32("security 1 session overflow test", "[PROTOCOMM]") +TEST_CASE("security 1 session overflow test", "[PROTOCOMM]") { TEST_ASSERT(test_security1_session_overflow() == ESP_OK); } @@ -1164,12 +1164,12 @@ TEST_CASE("security 1 wrong pop test", "[PROTOCOMM]") TEST_ASSERT(test_security1_wrong_pop() == ESP_OK); } -TEST_CASE_ESP32("security 1 insecure client test", "[PROTOCOMM]") +TEST_CASE("security 1 insecure client test", "[PROTOCOMM]") { TEST_ASSERT(test_security1_insecure_client() == ESP_OK); } -TEST_CASE_ESP32("security 1 weak session test", "[PROTOCOMM]") +TEST_CASE("security 1 weak session test", "[PROTOCOMM]") { TEST_ASSERT(test_security1_weak_session() == ESP_OK); } diff --git a/components/wpa_supplicant/test/test_crypto.c b/components/wpa_supplicant/test/test_crypto.c index 344c9daf6..e8f8d05a5 100644 --- a/components/wpa_supplicant/test/test_crypto.c +++ b/components/wpa_supplicant/test/test_crypto.c @@ -23,7 +23,7 @@ #include "mbedtls/ecp.h" typedef struct crypto_bignum crypto_bignum; -TEST_CASE_ESP32("Test crypto lib bignum apis", "[wpa_crypto]") +TEST_CASE("Test crypto lib bignum apis", "[wpa_crypto]") { { diff --git a/tools/ci/config/target-test.yml b/tools/ci/config/target-test.yml index b910be532..69747dab9 100644 --- a/tools/ci/config/target-test.yml +++ b/tools/ci/config/target-test.yml @@ -453,7 +453,7 @@ UT_034: UT_035: extends: .unit_test_template - parallel: 19 + parallel: 20 tags: - ESP32S2BETA_IDF - UT_T1_1 diff --git a/tools/unit-test-app/sdkconfig.defaults b/tools/unit-test-app/sdkconfig.defaults index 832f52e26..3dd326e12 100644 --- a/tools/unit-test-app/sdkconfig.defaults +++ b/tools/unit-test-app/sdkconfig.defaults @@ -11,7 +11,6 @@ CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=y CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=3 CONFIG_FREERTOS_USE_TRACE_FACILITY=y CONFIG_HEAP_POISONING_COMPREHENSIVE=y -CONFIG_MBEDTLS_HARDWARE_SHA=y CONFIG_SPI_FLASH_ENABLE_COUNTERS=y CONFIG_ESP_TASK_WDT=n CONFIG_SPI_FLASH_DANGEROUS_WRITE_FAILS=y diff --git a/tools/unit-test-app/sdkconfig.defaults.esp32s2beta b/tools/unit-test-app/sdkconfig.defaults.esp32s2beta index 74f96509f..92761fb6b 100644 --- a/tools/unit-test-app/sdkconfig.defaults.esp32s2beta +++ b/tools/unit-test-app/sdkconfig.defaults.esp32s2beta @@ -1,5 +1,2 @@ CONFIG_ESP32S2_DEFAULT_CPU_FREQ_240=y CONFIG_ESP32S2_ULP_COPROC_ENABLED=y - -# Hardware MPI disabled, ref. IDF-757 -CONFIG_MBEDTLS_HARDWARE_MPI=n