hw crypto: activated hardware acceleration for esp32s2beta

Activated AES, RSA and SHA hardware acceleration for esp32s2 and enabled related unit tests.

Updated with changes made for ESP32 from 0a04034, 961f59f and caea288.

Added performance targets for esp32s2beta

Closes IDF-757
This commit is contained in:
Marius Vikhammer 2019-11-06 11:07:16 +08:00
parent 3b52eddf6b
commit c63684cf6c
21 changed files with 748 additions and 157 deletions

View file

@ -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]")

View file

@ -0,0 +1,108 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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");
}

View file

@ -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

View file

@ -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.

View file

@ -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 );
}

View file

@ -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) );

View file

@ -15,12 +15,18 @@
#include <string.h>
#include <stdio.h>
#include <assert.h>
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/sha.h"
#elif CONFIG_IDF_TARGET_ESP32S2BETA
#include "esp32s2beta/sha.h"
#endif
#include <mbedtls/sha1.h>
#include <mbedtls/sha256.h>
#include <mbedtls/sha512.h>
#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

View file

@ -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 ) {

View file

@ -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 ) {

View file

@ -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)
{

View file

@ -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;

View file

@ -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:
* <ul><li>256 bits (each of key1 and key2 is a 128-bit key)</li>
* <li>512 bits (each of key1 and key2 is a 256-bit key)</li></ul>
*
* \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

View file

@ -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;

View file

@ -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");

View file

@ -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 };

View file

@ -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];

View file

@ -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);
}

View file

@ -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]")
{
{

View file

@ -453,7 +453,7 @@ UT_034:
UT_035:
extends: .unit_test_template
parallel: 19
parallel: 20
tags:
- ESP32S2BETA_IDF
- UT_T1_1

View file

@ -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

View file

@ -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