Merge branch 'bugfix/dport_protect_crypto' into 'master'
add protection for crypto registers in DPORT See merge request !928
This commit is contained in:
commit
a25eb825e1
16 changed files with 440 additions and 240 deletions
|
@ -69,22 +69,24 @@ static BaseType_t oldInterruptLevel[2];
|
|||
void IRAM_ATTR esp_dport_access_stall_other_cpu_start(void)
|
||||
{
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
int cpu_id = xPortGetCoreID();
|
||||
|
||||
if (dport_core_state[0] == DPORT_CORE_STATE_IDLE
|
||||
|| dport_core_state[1] == DPORT_CORE_STATE_IDLE) {
|
||||
|| dport_core_state[1] == DPORT_CORE_STATE_IDLE) {
|
||||
return;
|
||||
}
|
||||
|
||||
BaseType_t intLvl = portENTER_CRITICAL_NESTED();
|
||||
|
||||
int cpu_id = xPortGetCoreID();
|
||||
|
||||
#ifdef DPORT_ACCESS_BENCHMARK
|
||||
ccount_start[cpu_id] = XTHAL_GET_CCOUNT();
|
||||
#endif
|
||||
BaseType_t intLvl=portENTER_CRITICAL_NESTED();
|
||||
oldInterruptLevel[cpu_id]=intLvl;
|
||||
|
||||
if (dport_access_ref[cpu_id] == 0) {
|
||||
portENTER_CRITICAL_ISR(&g_dport_mux);
|
||||
|
||||
oldInterruptLevel[cpu_id]=intLvl;
|
||||
|
||||
dport_access_start[cpu_id] = 0;
|
||||
dport_access_end[cpu_id] = 0;
|
||||
|
||||
|
@ -100,6 +102,11 @@ void IRAM_ATTR esp_dport_access_stall_other_cpu_start(void)
|
|||
}
|
||||
|
||||
dport_access_ref[cpu_id]++;
|
||||
|
||||
if (dport_access_ref[cpu_id] > 1) {
|
||||
/* Interrupts are already disabled by the parent, we're nested here. */
|
||||
portEXIT_CRITICAL_NESTED(intLvl);
|
||||
}
|
||||
#endif /* CONFIG_FREERTOS_UNICORE */
|
||||
}
|
||||
|
||||
|
@ -124,9 +131,9 @@ void IRAM_ATTR esp_dport_access_stall_other_cpu_end(void)
|
|||
dport_access_end[cpu_id] = 1;
|
||||
|
||||
portEXIT_CRITICAL_ISR(&g_dport_mux);
|
||||
}
|
||||
|
||||
portEXIT_CRITICAL_NESTED(oldInterruptLevel[cpu_id]);
|
||||
portEXIT_CRITICAL_NESTED(oldInterruptLevel[cpu_id]);
|
||||
}
|
||||
|
||||
#ifdef DPORT_ACCESS_BENCHMARK
|
||||
ccount_end[cpu_id] = XTHAL_GET_CCOUNT();
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
* Based on mbedTLS FIPS-197 compliant version.
|
||||
*
|
||||
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
|
||||
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd
|
||||
* Additions Copyright (C) 2016-2017, Espressif Systems (Shanghai) PTE Ltd
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
|
@ -26,35 +26,60 @@
|
|||
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "mbedtls/aes.h"
|
||||
#include "hwcrypto/aes.h"
|
||||
#include "rom/aes.h"
|
||||
#include "soc/dport_reg.h"
|
||||
#include "soc/hwcrypto_reg.h"
|
||||
#include <sys/lock.h>
|
||||
|
||||
static _lock_t aes_lock;
|
||||
#include <freertos/FreeRTOS.h>
|
||||
|
||||
#include "soc/cpu.h"
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
/* AES uses a spinlock mux not a lock as the underlying block operation
|
||||
only takes 208 cycles (to write key & compute block), +600 cycles
|
||||
for DPORT protection but +3400 cycles again if you use a full sized lock.
|
||||
|
||||
For CBC, CFB, etc. this may mean that interrupts are disabled for a longer
|
||||
period of time for bigger lengths. However at the moment this has to happen
|
||||
anyway due to DPORT protection...
|
||||
*/
|
||||
static portMUX_TYPE aes_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
void esp_aes_acquire_hardware( void )
|
||||
{
|
||||
/* newlib locks lazy initialize on ESP-IDF */
|
||||
_lock_acquire(&aes_lock);
|
||||
/* Enable AES hardware */
|
||||
DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES);
|
||||
/* Clear reset on digital signature & secure boot units,
|
||||
otherwise AES unit is held in reset also. */
|
||||
DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG,
|
||||
DPORT_PERI_EN_AES
|
||||
| DPORT_PERI_EN_DIGITAL_SIGNATURE
|
||||
| DPORT_PERI_EN_SECUREBOOT);
|
||||
portENTER_CRITICAL(&aes_spinlock);
|
||||
|
||||
DPORT_STALL_OTHER_CPU_START();
|
||||
{
|
||||
/* Enable AES hardware */
|
||||
_DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES);
|
||||
/* Clear reset on digital signature & secure boot units,
|
||||
otherwise AES unit is held in reset also. */
|
||||
_DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG,
|
||||
DPORT_PERI_EN_AES
|
||||
| DPORT_PERI_EN_DIGITAL_SIGNATURE
|
||||
| DPORT_PERI_EN_SECUREBOOT);
|
||||
}
|
||||
DPORT_STALL_OTHER_CPU_END();
|
||||
}
|
||||
|
||||
void esp_aes_release_hardware( void )
|
||||
{
|
||||
/* Disable AES hardware */
|
||||
DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_AES);
|
||||
/* Don't return other units to reset, as this pulls
|
||||
reset on RSA & SHA units, respectively. */
|
||||
DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES);
|
||||
_lock_release(&aes_lock);
|
||||
DPORT_STALL_OTHER_CPU_START();
|
||||
{
|
||||
/* Disable AES hardware */
|
||||
_DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_AES);
|
||||
/* Don't return other units to reset, as this pulls
|
||||
reset on RSA & SHA units, respectively. */
|
||||
_DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES);
|
||||
}
|
||||
DPORT_STALL_OTHER_CPU_END();
|
||||
|
||||
portEXIT_CRITICAL(&aes_spinlock);
|
||||
}
|
||||
|
||||
void esp_aes_init( esp_aes_context *ctx )
|
||||
|
@ -71,55 +96,18 @@ void esp_aes_free( esp_aes_context *ctx )
|
|||
bzero( ctx, sizeof( esp_aes_context ) );
|
||||
}
|
||||
|
||||
/* Translate number of bits to an AES_BITS enum */
|
||||
static int keybits_to_aesbits(unsigned int keybits)
|
||||
{
|
||||
switch (keybits) {
|
||||
case 128:
|
||||
return AES128;
|
||||
case 192:
|
||||
return AES192;
|
||||
break;
|
||||
case 256:
|
||||
return AES256;
|
||||
default:
|
||||
return ( ERR_ESP_AES_INVALID_KEY_LENGTH );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* AES key schedule (encryption)
|
||||
* AES key schedule (same for encryption or decryption, as hardware handles schedule)
|
||||
*
|
||||
*/
|
||||
int esp_aes_setkey_enc( esp_aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keybits )
|
||||
int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keybits )
|
||||
{
|
||||
uint16_t keybytes = keybits / 8;
|
||||
int aesbits = keybits_to_aesbits(keybits);
|
||||
if (aesbits < 0) {
|
||||
return aesbits;
|
||||
if (keybits != 128 && keybits != 192 && keybits != 256) {
|
||||
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
}
|
||||
ctx->enc.aesbits = aesbits;
|
||||
bzero(ctx->enc.key, sizeof(ctx->enc.key));
|
||||
memcpy(ctx->enc.key, key, keybytes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* AES key schedule (decryption)
|
||||
*
|
||||
*/
|
||||
int esp_aes_setkey_dec( esp_aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keybits )
|
||||
{
|
||||
uint16_t keybytes = keybits / 8;
|
||||
int aesbits = keybits_to_aesbits(keybits);
|
||||
if (aesbits < 0) {
|
||||
return aesbits;
|
||||
}
|
||||
ctx->dec.aesbits = aesbits;
|
||||
bzero(ctx->dec.key, sizeof(ctx->dec.key));
|
||||
memcpy(ctx->dec.key, key, keybytes);
|
||||
ctx->key_bytes = keybits / 8;
|
||||
memcpy(ctx->key, key, ctx->key_bytes);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -127,16 +115,41 @@ int esp_aes_setkey_dec( esp_aes_context *ctx, const unsigned char *key,
|
|||
* Helper function to copy key from esp_aes_context buffer
|
||||
* to hardware key registers.
|
||||
*
|
||||
* Only call when protected by esp_aes_acquire_hardware().
|
||||
* Call only while holding esp_aes_acquire_hardware().
|
||||
*/
|
||||
static inline int esp_aes_setkey_hardware( esp_aes_context *ctx, int mode)
|
||||
static inline void esp_aes_setkey_hardware( esp_aes_context *ctx, int mode)
|
||||
{
|
||||
if ( mode == ESP_AES_ENCRYPT ) {
|
||||
ets_aes_setkey_enc(ctx->enc.key, ctx->enc.aesbits);
|
||||
} else {
|
||||
ets_aes_setkey_dec(ctx->dec.key, ctx->dec.aesbits);
|
||||
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);
|
||||
DPORT_REG_WRITE(AES_MODE_REG, mode_reg_base + ((ctx->key_bytes / 8) - 2));
|
||||
}
|
||||
|
||||
/* 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)
|
||||
{
|
||||
const uint32_t *input_words = (const uint32_t *)input;
|
||||
uint32_t *output_words = (uint32_t *)output;
|
||||
uint32_t *mem_block = (uint32_t *)AES_TEXT_BASE;
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
mem_block[i] = input_words[i];
|
||||
}
|
||||
return 0;
|
||||
|
||||
DPORT_REG_WRITE(AES_START_REG, 1);
|
||||
|
||||
DPORT_STALL_OTHER_CPU_START();
|
||||
{
|
||||
while (_DPORT_REG_READ(AES_IDLE_REG) != 1) { }
|
||||
for (int i = 0; i < 4; i++) {
|
||||
output_words[i] = mem_block[i];
|
||||
}
|
||||
}
|
||||
DPORT_STALL_OTHER_CPU_END();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -148,7 +161,7 @@ void esp_aes_encrypt( esp_aes_context *ctx,
|
|||
{
|
||||
esp_aes_acquire_hardware();
|
||||
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
|
||||
ets_aes_crypt(input, output);
|
||||
esp_aes_block(input, output);
|
||||
esp_aes_release_hardware();
|
||||
}
|
||||
|
||||
|
@ -162,7 +175,7 @@ void esp_aes_decrypt( esp_aes_context *ctx,
|
|||
{
|
||||
esp_aes_acquire_hardware();
|
||||
esp_aes_setkey_hardware(ctx, ESP_AES_DECRYPT);
|
||||
ets_aes_crypt(input, output);
|
||||
esp_aes_block(input, output);
|
||||
esp_aes_release_hardware();
|
||||
}
|
||||
|
||||
|
@ -177,8 +190,9 @@ int esp_aes_crypt_ecb( esp_aes_context *ctx,
|
|||
{
|
||||
esp_aes_acquire_hardware();
|
||||
esp_aes_setkey_hardware(ctx, mode);
|
||||
ets_aes_crypt(input, output);
|
||||
esp_aes_block(input, output);
|
||||
esp_aes_release_hardware();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -194,6 +208,9 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
|
|||
unsigned char *output )
|
||||
{
|
||||
int i;
|
||||
uint32_t *output_words = (uint32_t *)output;
|
||||
const uint32_t *input_words = (const uint32_t *)input;
|
||||
uint32_t *iv_words = (uint32_t *)iv;
|
||||
unsigned char temp[16];
|
||||
|
||||
if ( length % 16 ) {
|
||||
|
@ -201,34 +218,36 @@ int esp_aes_crypt_cbc( esp_aes_context *ctx,
|
|||
}
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
|
||||
esp_aes_setkey_hardware(ctx, mode);
|
||||
|
||||
if ( mode == ESP_AES_DECRYPT ) {
|
||||
while ( length > 0 ) {
|
||||
memcpy( temp, input, 16 );
|
||||
ets_aes_crypt(input, output);
|
||||
memcpy(temp, input_words, 16);
|
||||
esp_aes_block(input_words, output_words);
|
||||
|
||||
for ( i = 0; i < 16; i++ ) {
|
||||
output[i] = (unsigned char)( output[i] ^ iv[i] );
|
||||
for ( i = 0; i < 4; i++ ) {
|
||||
output_words[i] = output_words[i] ^ iv_words[i];
|
||||
}
|
||||
|
||||
memcpy( iv, temp, 16 );
|
||||
memcpy( iv_words, temp, 16 );
|
||||
|
||||
input += 16;
|
||||
output += 16;
|
||||
input_words += 4;
|
||||
output_words += 4;
|
||||
length -= 16;
|
||||
}
|
||||
} else {
|
||||
} else { // ESP_AES_ENCRYPT
|
||||
while ( length > 0 ) {
|
||||
for ( i = 0; i < 16; i++ ) {
|
||||
output[i] = (unsigned char)( input[i] ^ iv[i] );
|
||||
|
||||
for ( i = 0; i < 4; i++ ) {
|
||||
output_words[i] = input_words[i] ^ iv_words[i];
|
||||
}
|
||||
|
||||
ets_aes_crypt(output, output);
|
||||
memcpy( iv, output, 16 );
|
||||
esp_aes_block(output_words, output_words);
|
||||
memcpy( iv_words, output_words, 16 );
|
||||
|
||||
input += 16;
|
||||
output += 16;
|
||||
input_words += 4;
|
||||
output_words += 4;
|
||||
length -= 16;
|
||||
}
|
||||
}
|
||||
|
@ -253,12 +272,13 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
|
|||
size_t n = *iv_off;
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
|
||||
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
|
||||
|
||||
if ( mode == ESP_AES_DECRYPT ) {
|
||||
while ( length-- ) {
|
||||
if ( n == 0 ) {
|
||||
ets_aes_crypt(iv, iv );
|
||||
esp_aes_block(iv, iv );
|
||||
}
|
||||
|
||||
c = *input++;
|
||||
|
@ -270,7 +290,7 @@ int esp_aes_crypt_cfb128( esp_aes_context *ctx,
|
|||
} else {
|
||||
while ( length-- ) {
|
||||
if ( n == 0 ) {
|
||||
ets_aes_crypt(iv, iv );
|
||||
esp_aes_block(iv, iv );
|
||||
}
|
||||
|
||||
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
|
||||
|
@ -300,11 +320,12 @@ int esp_aes_crypt_cfb8( esp_aes_context *ctx,
|
|||
unsigned char ov[17];
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
|
||||
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
|
||||
|
||||
while ( length-- ) {
|
||||
memcpy( ov, iv, 16 );
|
||||
ets_aes_crypt(iv, iv);
|
||||
esp_aes_block(iv, iv);
|
||||
|
||||
if ( mode == ESP_AES_DECRYPT ) {
|
||||
ov[16] = *input;
|
||||
|
@ -339,11 +360,12 @@ int esp_aes_crypt_ctr( esp_aes_context *ctx,
|
|||
size_t n = *nc_off;
|
||||
|
||||
esp_aes_acquire_hardware();
|
||||
|
||||
esp_aes_setkey_hardware(ctx, ESP_AES_ENCRYPT);
|
||||
|
||||
while ( length-- ) {
|
||||
if ( n == 0 ) {
|
||||
ets_aes_crypt(nonce_counter, stream_block);
|
||||
esp_aes_block(nonce_counter, stream_block);
|
||||
|
||||
for ( i = 16; i > 0; i-- )
|
||||
if ( ++nonce_counter[i - 1] != 0 ) {
|
||||
|
|
|
@ -159,19 +159,23 @@ static void esp_sha_lock_engine_inner(sha_engine_state *engine)
|
|||
_lock_acquire(&state_change_lock);
|
||||
|
||||
if (sha_engines_all_idle()) {
|
||||
/* Enable SHA hardware */
|
||||
DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA);
|
||||
/* also clear reset on secure boot, otherwise SHA is held in reset */
|
||||
DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG,
|
||||
DPORT_PERI_EN_SHA
|
||||
| DPORT_PERI_EN_SECUREBOOT);
|
||||
ets_sha_enable();
|
||||
DPORT_STALL_OTHER_CPU_START();
|
||||
{
|
||||
/* Enable SHA hardware */
|
||||
_DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA);
|
||||
/* also clear reset on secure boot, otherwise SHA is held in reset */
|
||||
_DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG,
|
||||
DPORT_PERI_EN_SHA
|
||||
| DPORT_PERI_EN_SECUREBOOT);
|
||||
ets_sha_enable();
|
||||
}
|
||||
DPORT_STALL_OTHER_CPU_END();
|
||||
}
|
||||
|
||||
_lock_release(&state_change_lock);
|
||||
|
||||
assert( !engine->in_use && "in_use flag should be cleared" );
|
||||
engine->in_use = true;
|
||||
|
||||
_lock_release(&state_change_lock);
|
||||
}
|
||||
|
||||
|
||||
|
@ -187,8 +191,12 @@ void esp_sha_unlock_engine(esp_sha_type sha_type)
|
|||
if (sha_engines_all_idle()) {
|
||||
/* Disable SHA hardware */
|
||||
/* Don't assert reset on secure boot, otherwise AES is held in reset */
|
||||
DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_SHA);
|
||||
DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA);
|
||||
DPORT_STALL_OTHER_CPU_START();
|
||||
{
|
||||
_DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_SHA);
|
||||
_DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA);
|
||||
}
|
||||
DPORT_STALL_OTHER_CPU_END();
|
||||
}
|
||||
|
||||
_lock_release(&state_change_lock);
|
||||
|
@ -198,10 +206,16 @@ void esp_sha_unlock_engine(esp_sha_type sha_type)
|
|||
|
||||
void esp_sha_wait_idle(void)
|
||||
{
|
||||
while(REG_READ(SHA_1_BUSY_REG) == 1) {}
|
||||
while(REG_READ(SHA_256_BUSY_REG) == 1) {}
|
||||
while(REG_READ(SHA_384_BUSY_REG) == 1) {}
|
||||
while(REG_READ(SHA_512_BUSY_REG) == 1) {}
|
||||
DPORT_STALL_OTHER_CPU_START();
|
||||
while(1) {
|
||||
if(_DPORT_REG_READ(SHA_1_BUSY_REG) == 0
|
||||
&& _DPORT_REG_READ(SHA_256_BUSY_REG) == 0
|
||||
&& _DPORT_REG_READ(SHA_384_BUSY_REG) == 0
|
||||
&& _DPORT_REG_READ(SHA_512_BUSY_REG) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
DPORT_STALL_OTHER_CPU_END();
|
||||
}
|
||||
|
||||
void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state)
|
||||
|
@ -211,23 +225,26 @@ void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state)
|
|||
|
||||
esp_sha_lock_memory_block();
|
||||
|
||||
esp_sha_wait_idle();
|
||||
DPORT_STALL_OTHER_CPU_START(); // This block reads from DPORT memory (reg_addr_buf)
|
||||
{
|
||||
esp_sha_wait_idle();
|
||||
|
||||
REG_WRITE(SHA_LOAD_REG(sha_type), 1);
|
||||
while(REG_READ(SHA_BUSY_REG(sha_type)) == 1) { }
|
||||
_DPORT_REG_WRITE(SHA_LOAD_REG(sha_type), 1);
|
||||
while(_DPORT_REG_READ(SHA_BUSY_REG(sha_type)) == 1) { }
|
||||
|
||||
uint32_t *digest_state_words = (uint32_t *)digest_state;
|
||||
uint32_t *reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE);
|
||||
if(sha_type == SHA2_384 || sha_type == SHA2_512) {
|
||||
/* for these ciphers using 64-bit states, swap each pair of words */
|
||||
for(int i = 0; i < sha_length(sha_type)/4; i += 2) {
|
||||
digest_state_words[i+1] = reg_addr_buf[i];
|
||||
digest_state_words[i]= reg_addr_buf[i+1];
|
||||
uint32_t *digest_state_words = (uint32_t *)digest_state;
|
||||
uint32_t *reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE);
|
||||
if(sha_type == SHA2_384 || sha_type == SHA2_512) {
|
||||
/* for these ciphers using 64-bit states, swap each pair of words */
|
||||
for(int i = 0; i < sha_length(sha_type)/4; i += 2) {
|
||||
digest_state_words[i+1] = reg_addr_buf[i];
|
||||
digest_state_words[i]= reg_addr_buf[i+1];
|
||||
}
|
||||
} else {
|
||||
memcpy(digest_state_words, reg_addr_buf, sha_length(sha_type));
|
||||
}
|
||||
} else {
|
||||
memcpy(digest_state_words, reg_addr_buf, sha_length(sha_type));
|
||||
}
|
||||
asm volatile ("memw");
|
||||
DPORT_STALL_OTHER_CPU_END();
|
||||
|
||||
esp_sha_unlock_memory_block();
|
||||
}
|
||||
|
@ -250,9 +267,9 @@ void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_
|
|||
asm volatile ("memw");
|
||||
|
||||
if(is_first_block) {
|
||||
REG_WRITE(SHA_START_REG(sha_type), 1);
|
||||
DPORT_REG_WRITE(SHA_START_REG(sha_type), 1);
|
||||
} else {
|
||||
REG_WRITE(SHA_CONTINUE_REG(sha_type), 1);
|
||||
DPORT_REG_WRITE(SHA_CONTINUE_REG(sha_type), 1);
|
||||
}
|
||||
|
||||
esp_sha_unlock_memory_block();
|
||||
|
@ -275,14 +292,23 @@ void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, uns
|
|||
size_t chunk_len = (ilen > block_len) ? block_len : ilen;
|
||||
esp_sha_lock_memory_block();
|
||||
esp_sha_wait_idle();
|
||||
ets_sha_update(&ctx, sha_type, input, chunk_len * 8);
|
||||
DPORT_STALL_OTHER_CPU_START();
|
||||
{
|
||||
// This SHA ROM function reads DPORT regs
|
||||
ets_sha_update(&ctx, sha_type, input, chunk_len * 8);
|
||||
}
|
||||
DPORT_STALL_OTHER_CPU_END();
|
||||
esp_sha_unlock_memory_block();
|
||||
input += chunk_len;
|
||||
ilen -= chunk_len;
|
||||
}
|
||||
esp_sha_lock_memory_block();
|
||||
esp_sha_wait_idle();
|
||||
ets_sha_finish(&ctx, sha_type, output);
|
||||
DPORT_STALL_OTHER_CPU_START();
|
||||
{
|
||||
ets_sha_finish(&ctx, sha_type, output);
|
||||
}
|
||||
DPORT_STALL_OTHER_CPU_END();
|
||||
esp_sha_unlock_memory_block();
|
||||
|
||||
esp_sha_unlock_engine(sha_type);
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <sdkconfig.h>
|
||||
|
||||
#ifndef _ESP_DPORT_ACCESS_H_
|
||||
#define _ESP_DPORT_ACCESS_H_
|
||||
|
||||
|
|
|
@ -38,11 +38,6 @@ extern "C" {
|
|||
#define ERR_ESP_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
|
||||
#define ERR_ESP_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
|
||||
|
||||
typedef struct {
|
||||
enum AES_BITS aesbits;
|
||||
uint8_t key[32];
|
||||
} key_context, KEY_CTX;
|
||||
|
||||
/**
|
||||
* \brief AES context structure
|
||||
*
|
||||
|
@ -52,10 +47,8 @@ typedef struct {
|
|||
* generating an extra round key
|
||||
*/
|
||||
typedef struct {
|
||||
int nr; /*!< number of rounds */
|
||||
uint32_t *rk; /*!< AES round keys */
|
||||
KEY_CTX enc;
|
||||
KEY_CTX dec;
|
||||
uint8_t key_bytes;
|
||||
uint8_t key[32];
|
||||
} esp_aes_context;
|
||||
|
||||
/**
|
||||
|
@ -94,7 +87,7 @@ void esp_aes_init( esp_aes_context *ctx );
|
|||
void esp_aes_free( esp_aes_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief AES key schedule (encryption)
|
||||
* \brief AES set key schedule (encryption or decryption)
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
* \param key encryption key
|
||||
|
@ -102,18 +95,7 @@ void esp_aes_free( esp_aes_context *ctx );
|
|||
*
|
||||
* \return 0 if successful, or ERR_AES_INVALID_KEY_LENGTH
|
||||
*/
|
||||
int esp_aes_setkey_enc( esp_aes_context *ctx, const unsigned char *key, unsigned int keybits );
|
||||
|
||||
/**
|
||||
* \brief AES key schedule (decryption)
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
* \param key decryption key
|
||||
* \param keybits must be 128, 192 or 256
|
||||
*
|
||||
* \return 0 if successful, or ERR_AES_INVALID_KEY_LENGTH
|
||||
*/
|
||||
int esp_aes_setkey_dec( esp_aes_context *ctx, const unsigned char *key, unsigned int keybits );
|
||||
int esp_aes_setkey( esp_aes_context *ctx, const unsigned char *key, unsigned int keybits );
|
||||
|
||||
/**
|
||||
* \brief AES-ECB block encryption/decryption
|
||||
|
|
|
@ -31,26 +31,18 @@ config MBEDTLS_DEBUG
|
|||
at runtime in order to enable mbedTLS debug output via the ESP
|
||||
log mechanism.
|
||||
|
||||
config MBEDTLS_UNSAFE_ACCELERATION
|
||||
bool "Allow buggy hardware acceleration features"
|
||||
depends on !FREERTOS_UNICORE
|
||||
default n
|
||||
help
|
||||
A bug currently prevents dual cores & crypto hardware acceleration from being used together.
|
||||
|
||||
Enable this option to allow hardware acceleration anyhow (note that invalid results or crashes may occur.)
|
||||
|
||||
config MBEDTLS_HARDWARE_AES
|
||||
bool "Enable hardware AES acceleration"
|
||||
depends on MBEDTLS_UNSAFE_ACCELERATION || FREERTOS_UNICORE
|
||||
default y
|
||||
help
|
||||
Enable hardware accelerated AES encryption & decryption.
|
||||
|
||||
Note that if the ESP32 CPU is running at 240MHz, hardware AES does not
|
||||
offer any speed boost over software AES.
|
||||
|
||||
config MBEDTLS_HARDWARE_MPI
|
||||
bool "Enable hardware MPI (bignum) acceleration"
|
||||
depends on MBEDTLS_UNSAFE_ACCELERATION || FREERTOS_UNICORE
|
||||
default y
|
||||
default n
|
||||
help
|
||||
Enable hardware accelerated multiple precision integer operations.
|
||||
|
||||
|
@ -62,7 +54,7 @@ config MBEDTLS_HARDWARE_MPI
|
|||
config MBEDTLS_MPI_USE_INTERRUPT
|
||||
bool "Use interrupt for MPI operations"
|
||||
depends on MBEDTLS_HARDWARE_MPI
|
||||
default y
|
||||
default n
|
||||
help
|
||||
Use an interrupt to coordinate MPI operations.
|
||||
|
||||
|
@ -71,16 +63,18 @@ config MBEDTLS_MPI_USE_INTERRUPT
|
|||
|
||||
config MBEDTLS_HARDWARE_SHA
|
||||
bool "Enable hardware SHA acceleration"
|
||||
depends on MBEDTLS_UNSAFE_ACCELERATION || FREERTOS_UNICORE
|
||||
default y
|
||||
default n
|
||||
help
|
||||
Enable hardware accelerated SHA1, SHA256, SHA384 & SHA512 in mbedTLS.
|
||||
|
||||
Due to a hardware limitation, hardware acceleration is only
|
||||
guaranteed if SHA digests are calculated one at a time. If more
|
||||
than one SHA digest is calculated at the same time, only will
|
||||
than one SHA digest is calculated at the same time, one will
|
||||
be calculated fully in hardware and the rest will be calculated
|
||||
(at least partially calculated) in software.
|
||||
(at least partially calculated) in software. This happens automatically.
|
||||
|
||||
SHA hardware acceleration is faster than software in some situations but
|
||||
slower in others. You should benchmark to find the best setting for you.
|
||||
|
||||
config MBEDTLS_HAVE_TIME
|
||||
bool "Enable mbedtls time"
|
||||
|
|
|
@ -52,7 +52,7 @@ static SemaphoreHandle_t op_complete_sem;
|
|||
static IRAM_ATTR void rsa_complete_isr(void *arg)
|
||||
{
|
||||
BaseType_t higher_woken;
|
||||
REG_WRITE(RSA_INTERRUPT_REG, 1);
|
||||
DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1);
|
||||
xSemaphoreGiveFromISR(op_complete_sem, &higher_woken);
|
||||
if (higher_woken) {
|
||||
portYIELD_FROM_ISR();
|
||||
|
@ -76,16 +76,19 @@ void esp_mpi_acquire_hardware( void )
|
|||
/* newlib locks lazy initialize on ESP-IDF */
|
||||
_lock_acquire(&mpi_lock);
|
||||
|
||||
DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA);
|
||||
/* also clear reset on digital signature, otherwise RSA is held in reset */
|
||||
DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG,
|
||||
DPORT_PERI_EN_RSA
|
||||
| DPORT_PERI_EN_DIGITAL_SIGNATURE);
|
||||
DPORT_STALL_OTHER_CPU_START();
|
||||
{
|
||||
_DPORT_REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA);
|
||||
/* also clear reset on digital signature, otherwise RSA is held in reset */
|
||||
_DPORT_REG_CLR_BIT(DPORT_PERI_RST_EN_REG,
|
||||
DPORT_PERI_EN_RSA
|
||||
| DPORT_PERI_EN_DIGITAL_SIGNATURE);
|
||||
|
||||
DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
|
||||
|
||||
while(REG_READ(RSA_CLEAN_REG) != 1);
|
||||
_DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
|
||||
}
|
||||
DPORT_STALL_OTHER_CPU_END();
|
||||
|
||||
while(DPORT_REG_READ(RSA_CLEAN_REG) != 1);
|
||||
// Note: from enabling RSA clock to here takes about 1.3us
|
||||
|
||||
#ifdef CONFIG_MBEDTLS_MPI_USE_INTERRUPT
|
||||
|
@ -95,11 +98,15 @@ void esp_mpi_acquire_hardware( void )
|
|||
|
||||
void esp_mpi_release_hardware( void )
|
||||
{
|
||||
DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
|
||||
DPORT_STALL_OTHER_CPU_START();
|
||||
{
|
||||
_DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
|
||||
|
||||
/* don't reset digital signature unit, as this resets AES also */
|
||||
DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_RSA);
|
||||
DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA);
|
||||
/* don't reset digital signature unit, as this resets AES also */
|
||||
_DPORT_REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_RSA);
|
||||
_DPORT_REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA);
|
||||
}
|
||||
DPORT_STALL_OTHER_CPU_END();
|
||||
|
||||
_lock_release(&mpi_lock);
|
||||
}
|
||||
|
@ -139,6 +146,9 @@ static inline size_t bits_to_hardware_words(size_t num_bits)
|
|||
|
||||
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)
|
||||
{
|
||||
|
@ -146,10 +156,14 @@ static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, s
|
|||
uint32_t copy_words = num_words < mpi->n ? num_words : mpi->n;
|
||||
|
||||
/* Copy MPI data to memory block registers */
|
||||
memcpy(pbase, mpi->p, copy_words * 4);
|
||||
for (int i = 0; i < copy_words; i++) {
|
||||
pbase[i] = mpi->p[i];
|
||||
}
|
||||
|
||||
/* Zero any remaining memory block data */
|
||||
bzero(pbase + copy_words, (num_words - copy_words) * 4);
|
||||
for (int i = copy_words; i < num_words; i++) {
|
||||
pbase[i] = 0;
|
||||
}
|
||||
|
||||
/* Note: not executing memw here, can do it before we start a bignum operation */
|
||||
}
|
||||
|
@ -159,6 +173,8 @@ static inline void mpi_to_mem_block(uint32_t mem_base, const mbedtls_mpi *mpi, s
|
|||
Reads num_words words from block.
|
||||
|
||||
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)
|
||||
{
|
||||
|
@ -167,7 +183,13 @@ static inline int mem_block_to_mpi(mbedtls_mpi *x, uint32_t mem_base, int num_wo
|
|||
MBEDTLS_MPI_CHK( mbedtls_mpi_grow(x, num_words) );
|
||||
|
||||
/* Copy data from memory block registers */
|
||||
memcpy(x->p, (uint32_t *)mem_base, num_words * 4);
|
||||
DPORT_STALL_OTHER_CPU_START();
|
||||
{
|
||||
for (size_t i = 0; i < num_words; ++i) {
|
||||
x->p[i] = _DPORT_REG_READ(mem_base + i * 4);
|
||||
}
|
||||
}
|
||||
DPORT_STALL_OTHER_CPU_END();
|
||||
|
||||
/* Zero any remaining limbs in the bignum, if the buffer is bigger
|
||||
than num_words */
|
||||
|
@ -236,32 +258,44 @@ static int calculate_rinv(mbedtls_mpi *Rinv, const mbedtls_mpi *M, int num_words
|
|||
}
|
||||
|
||||
|
||||
/* Execute RSA operation. op_reg specifies which 'START' register
|
||||
/* 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 execute_op(uint32_t op_reg)
|
||||
static inline void start_op(uint32_t op_reg)
|
||||
{
|
||||
/* Clear interrupt status */
|
||||
REG_WRITE(RSA_INTERRUPT_REG, 1);
|
||||
DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1);
|
||||
|
||||
/* Note: above REG_WRITE includes a memw, so we know any writes
|
||||
to the memory blocks are also complete. */
|
||||
|
||||
REG_WRITE(op_reg, 1);
|
||||
DPORT_REG_WRITE(op_reg, 1);
|
||||
}
|
||||
|
||||
/* 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, REG_READ(RSA_INTERRUPT_REG));
|
||||
op_reg, DPORT_REG_READ(RSA_INTERRUPT_REG));
|
||||
abort(); /* indicates a fundamental problem with driver */
|
||||
}
|
||||
#else
|
||||
while(REG_READ(RSA_INTERRUPT_REG) != 1)
|
||||
while(DPORT_REG_READ(RSA_INTERRUPT_REG) != 1)
|
||||
{ }
|
||||
#endif
|
||||
|
||||
/* clear the interrupt */
|
||||
REG_WRITE(RSA_INTERRUPT_REG, 1);
|
||||
DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* Sub-stages of modulo multiplication/exponentiation operations */
|
||||
|
@ -285,20 +319,24 @@ int esp_mpi_mul_mpi_mod(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi
|
|||
|
||||
esp_mpi_acquire_hardware();
|
||||
|
||||
/* (As the following are all writes to DPORT memory, no DPORT_STALL_OTHER_CPU_START is required.) */
|
||||
|
||||
/* 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_X_BLOCK_BASE, X, num_words);
|
||||
mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, &Rinv, num_words);
|
||||
REG_WRITE(RSA_M_DASH_REG, (uint32_t)Mprime);
|
||||
DPORT_REG_WRITE(RSA_M_DASH_REG, (uint32_t)Mprime);
|
||||
|
||||
/* "mode" register loaded with number of 512-bit blocks, minus 1 */
|
||||
REG_WRITE(RSA_MULT_MODE_REG, (num_words / 16) - 1);
|
||||
DPORT_REG_WRITE(RSA_MULT_MODE_REG, (num_words / 16) - 1);
|
||||
|
||||
/* Execute first stage montgomery multiplication */
|
||||
execute_op(RSA_MULT_START_REG);
|
||||
start_op(RSA_MULT_START_REG);
|
||||
|
||||
wait_op_complete(RSA_MULT_START_REG);
|
||||
|
||||
/* execute second stage */
|
||||
MBEDTLS_MPI_CHK( modular_multiply_finish(Z, X, Y, num_words) );
|
||||
ret = modular_multiply_finish(Z, X, Y, num_words);
|
||||
|
||||
esp_mpi_release_hardware();
|
||||
|
||||
|
@ -364,20 +402,23 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi* Z, const mbedtls_mpi* X, const mbedtls_mpi
|
|||
|
||||
esp_mpi_acquire_hardware();
|
||||
|
||||
/* (As the following are all writes to DPORT memory, no DPORT_STALL_OTHER_CPU_START is required.) */
|
||||
|
||||
/* "mode" register loaded with number of 512-bit blocks, minus 1 */
|
||||
REG_WRITE(RSA_MODEXP_MODE_REG, (num_words / 16) - 1);
|
||||
DPORT_REG_WRITE(RSA_MODEXP_MODE_REG, (num_words / 16) - 1);
|
||||
|
||||
/* Load M, X, Rinv, M-prime (M-prime is mod 2^32) */
|
||||
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_M_BLOCK_BASE, M, num_words);
|
||||
mpi_to_mem_block(RSA_MEM_RB_BLOCK_BASE, Rinv, num_words);
|
||||
REG_WRITE(RSA_M_DASH_REG, Mprime);
|
||||
DPORT_REG_WRITE(RSA_M_DASH_REG, Mprime);
|
||||
|
||||
execute_op(RSA_START_MODEXP_REG);
|
||||
start_op(RSA_START_MODEXP_REG);
|
||||
|
||||
wait_op_complete(RSA_START_MODEXP_REG);
|
||||
|
||||
ret = mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, num_words);
|
||||
|
||||
esp_mpi_release_hardware();
|
||||
|
||||
cleanup:
|
||||
|
@ -405,11 +446,14 @@ int mbedtls_mpi_exp_mod( mbedtls_mpi* Z, const mbedtls_mpi* X, const mbedtls_mpi
|
|||
*/
|
||||
static int modular_multiply_finish(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y, size_t num_words)
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
|
||||
/* Load Y to X input memory block, rerun */
|
||||
mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, Y, num_words);
|
||||
|
||||
execute_op(RSA_MULT_START_REG);
|
||||
start_op(RSA_MULT_START_REG);
|
||||
|
||||
wait_op_complete(RSA_MULT_START_REG);
|
||||
|
||||
/* Read result into Z */
|
||||
ret = mem_block_to_mpi(Z, RSA_MEM_Z_BLOCK_BASE, num_words);
|
||||
|
@ -427,7 +471,7 @@ static int mpi_mult_mpi_overlong(mbedtls_mpi *Z, const mbedtls_mpi *X, const mbe
|
|||
/* Z = X * Y */
|
||||
int mbedtls_mpi_mul_mpi( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi *Y )
|
||||
{
|
||||
int ret;
|
||||
int ret = 0;
|
||||
size_t bits_x, bits_y, words_x, words_y, words_mult, words_z;
|
||||
|
||||
/* Count words needed for X & Y in hardware */
|
||||
|
@ -502,14 +546,16 @@ int mbedtls_mpi_mul_mpi( mbedtls_mpi *Z, const mbedtls_mpi *X, const mbedtls_mpi
|
|||
This is OK for now because zeroing is done by hardware when we do esp_mpi_acquire_hardware().
|
||||
*/
|
||||
|
||||
REG_WRITE(RSA_M_DASH_REG, 0);
|
||||
DPORT_REG_WRITE(RSA_M_DASH_REG, 0);
|
||||
|
||||
/* "mode" register loaded with number of 512-bit blocks in result,
|
||||
plus 7 (for range 9-12). (this is ((N~ / 32) - 1) + 8))
|
||||
*/
|
||||
REG_WRITE(RSA_MULT_MODE_REG, (words_z / 16) + 7);
|
||||
DPORT_REG_WRITE(RSA_MULT_MODE_REG, (words_z / 16) + 7);
|
||||
|
||||
execute_op(RSA_MULT_START_REG);
|
||||
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);
|
||||
|
@ -547,31 +593,32 @@ static int mpi_mult_mpi_failover_mod_mult(mbedtls_mpi *Z, const mbedtls_mpi *X,
|
|||
|
||||
/* M = 2^num_words - 1, so block is entirely FF */
|
||||
for(int i = 0; i < num_words; i++) {
|
||||
REG_WRITE(RSA_MEM_M_BLOCK_BASE + i * 4, UINT32_MAX);
|
||||
DPORT_REG_WRITE(RSA_MEM_M_BLOCK_BASE + i * 4, UINT32_MAX);
|
||||
}
|
||||
/* Mprime = 1 */
|
||||
REG_WRITE(RSA_M_DASH_REG, 1);
|
||||
DPORT_REG_WRITE(RSA_M_DASH_REG, 1);
|
||||
|
||||
/* "mode" register loaded with number of 512-bit blocks, minus 1 */
|
||||
REG_WRITE(RSA_MULT_MODE_REG, (num_words / 16) - 1);
|
||||
DPORT_REG_WRITE(RSA_MULT_MODE_REG, (num_words / 16) - 1);
|
||||
|
||||
/* Load X */
|
||||
mpi_to_mem_block(RSA_MEM_X_BLOCK_BASE, X, num_words);
|
||||
|
||||
/* Rinv = 1 */
|
||||
REG_WRITE(RSA_MEM_RB_BLOCK_BASE, 1);
|
||||
DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE, 1);
|
||||
for(int i = 1; i < num_words; i++) {
|
||||
REG_WRITE(RSA_MEM_RB_BLOCK_BASE + i * 4, 0);
|
||||
DPORT_REG_WRITE(RSA_MEM_RB_BLOCK_BASE + i * 4, 0);
|
||||
}
|
||||
|
||||
execute_op(RSA_MULT_START_REG);
|
||||
start_op(RSA_MULT_START_REG);
|
||||
|
||||
wait_op_complete(RSA_MULT_START_REG);
|
||||
|
||||
/* finish the modular multiplication */
|
||||
MBEDTLS_MPI_CHK( modular_multiply_finish(Z, X, Y, num_words) );
|
||||
ret = modular_multiply_finish(Z, X, Y, num_words);
|
||||
|
||||
esp_mpi_release_hardware();
|
||||
|
||||
cleanup:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -594,7 +641,7 @@ static int mpi_mult_mpi_failover_mod_mult(mbedtls_mpi *Z, const mbedtls_mpi *X,
|
|||
*/
|
||||
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)
|
||||
{
|
||||
int ret;
|
||||
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) */
|
||||
|
|
|
@ -34,8 +34,8 @@ typedef esp_aes_context mbedtls_aes_context;
|
|||
|
||||
#define mbedtls_aes_init esp_aes_init
|
||||
#define mbedtls_aes_free esp_aes_free
|
||||
#define mbedtls_aes_setkey_enc esp_aes_setkey_enc
|
||||
#define mbedtls_aes_setkey_dec esp_aes_setkey_dec
|
||||
#define mbedtls_aes_setkey_enc esp_aes_setkey
|
||||
#define mbedtls_aes_setkey_dec esp_aes_setkey
|
||||
#define mbedtls_aes_crypt_ecb esp_aes_crypt_ecb
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
||||
#define mbedtls_aes_crypt_cbc esp_aes_crypt_cbc
|
||||
|
|
55
components/mbedtls/test/test_apb_dport_access.c
Normal file
55
components/mbedtls/test/test_apb_dport_access.c
Normal file
|
@ -0,0 +1,55 @@
|
|||
/* Implementation of utility functions to verify
|
||||
unit tests aren't performing SMP-unsafe DPORT reads.
|
||||
*/
|
||||
|
||||
#include "unity.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "freertos/task.h"
|
||||
#include "soc/uart_reg.h"
|
||||
#include "test_apb_dport_access.h"
|
||||
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
|
||||
static void apb_access_loop_task(void *ignore);
|
||||
|
||||
static volatile bool apb_access_corrupt;
|
||||
static TaskHandle_t apb_task_handle;
|
||||
|
||||
void start_apb_access_loop()
|
||||
{
|
||||
apb_access_corrupt = false;
|
||||
xTaskCreatePinnedToCore(apb_access_loop_task, "accessAPB", 2048, NULL,
|
||||
UNITY_FREERTOS_PRIORITY - 1,
|
||||
&apb_task_handle, !UNITY_FREERTOS_CPU);
|
||||
}
|
||||
|
||||
void verify_apb_access_loop()
|
||||
{
|
||||
vTaskDelete(apb_task_handle);
|
||||
apb_task_handle = NULL;
|
||||
TEST_ASSERT_FALSE(apb_access_corrupt);
|
||||
printf("Verified no APB corruption from operations\n");
|
||||
}
|
||||
|
||||
static void apb_access_loop_task(void *ignore)
|
||||
{
|
||||
uint32_t initial = REG_READ(UART_DATE_REG(0));
|
||||
while(1) {
|
||||
if (REG_READ(UART_DATE_REG(0)) != initial) {
|
||||
apb_access_corrupt = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#else /*CONFIG_FREERTOS_UNICORE */
|
||||
|
||||
void start_apb_access_loop()
|
||||
{
|
||||
}
|
||||
|
||||
void verify_apb_access_loop()
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
18
components/mbedtls/test/test_apb_dport_access.h
Normal file
18
components/mbedtls/test/test_apb_dport_access.h
Normal file
|
@ -0,0 +1,18 @@
|
|||
/* Utility functions to test that APB access is still safe
|
||||
while the other CPU performs some set of DPORT accesses
|
||||
|
||||
(see ECO 3.10 and the standalone esp32 test_dport.c for more).
|
||||
*/
|
||||
|
||||
/* start_apb_access_loop() starts a task reading from APB in a loop on the non-Unity-test CPU.
|
||||
|
||||
Call this before doing something which involes DPORT reads.
|
||||
|
||||
Does nothing in unicore mode.
|
||||
*/
|
||||
void start_apb_access_loop();
|
||||
|
||||
/* verify_apb_access_loop() kills the task started by start_apb_access_loop()
|
||||
and verifies that none of the APB reads were corrupted by unsafe DPORT reads.
|
||||
*/
|
||||
void verify_apb_access_loop();
|
|
@ -20,19 +20,26 @@
|
|||
#include "freertos/semphr.h"
|
||||
#include "unity.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "test_apb_dport_access.h"
|
||||
|
||||
TEST_CASE("mbedtls AES self-tests", "[aes]")
|
||||
{
|
||||
start_apb_access_loop();
|
||||
TEST_ASSERT_FALSE_MESSAGE(mbedtls_aes_self_test(1), "AES self-tests should pass.");
|
||||
verify_apb_access_loop();
|
||||
}
|
||||
|
||||
TEST_CASE("mbedtls MPI self-tests", "[bignum]")
|
||||
{
|
||||
start_apb_access_loop();
|
||||
TEST_ASSERT_FALSE_MESSAGE(mbedtls_mpi_self_test(1), "MPI self-tests should pass.");
|
||||
verify_apb_access_loop();
|
||||
}
|
||||
|
||||
TEST_CASE("mbedtls RSA self-tests", "[bignum]")
|
||||
{
|
||||
start_apb_access_loop();
|
||||
TEST_ASSERT_FALSE_MESSAGE(mbedtls_rsa_self_test(1), "RSA self-tests should pass.");
|
||||
verify_apb_access_loop();
|
||||
}
|
||||
|
||||
|
|
|
@ -13,13 +13,16 @@
|
|||
#include "freertos/semphr.h"
|
||||
#include "unity.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "test_apb_dport_access.h"
|
||||
|
||||
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.");
|
||||
TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha256_self_test(1), "SHA256 self-tests should pass.");
|
||||
TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha512_self_test(1), "SHA512 self-tests should pass.");
|
||||
TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha512_self_test(1), "SHA512 self-tests should pass.");
|
||||
verify_apb_access_loop();
|
||||
}
|
||||
|
||||
static const unsigned char *one_hundred_as = (unsigned char *)
|
||||
|
@ -116,13 +119,15 @@ static void tskRunSHA256Test(void *pvParameters)
|
|||
vTaskDelete(NULL);
|
||||
}
|
||||
|
||||
TEST_CASE("mbedtls SHA multithreading", "[mbedtls][ignore]")
|
||||
#define SHA_TASK_STACK_SIZE (10*1024)
|
||||
|
||||
TEST_CASE("mbedtls SHA multithreading", "[mbedtls]")
|
||||
{
|
||||
done_sem = xSemaphoreCreateCounting(4, 0);
|
||||
xTaskCreate(tskRunSHA1Test, "SHA1Task1", 8192, NULL, 3, NULL);
|
||||
xTaskCreate(tskRunSHA1Test, "SHA1Task2", 8192, NULL, 3, NULL);
|
||||
xTaskCreate(tskRunSHA256Test, "SHA256Task1", 8192, NULL, 3, NULL);
|
||||
xTaskCreate(tskRunSHA256Test, "SHA256Task2", 8192, NULL, 3, NULL);
|
||||
xTaskCreate(tskRunSHA1Test, "SHA1Task1", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
|
||||
xTaskCreate(tskRunSHA1Test, "SHA1Task2", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
|
||||
xTaskCreate(tskRunSHA256Test, "SHA256Task1", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
|
||||
xTaskCreate(tskRunSHA256Test, "SHA256Task2", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
|
||||
|
||||
for(int i = 0; i < 4; i++) {
|
||||
if(!xSemaphoreTake(done_sem, 10000/portTICK_PERIOD_MS)) {
|
||||
|
@ -162,14 +167,10 @@ void tskRunSHASelftests(void *param)
|
|||
TEST_CASE("mbedtls SHA self-tests multithreaded", "[mbedtls]")
|
||||
{
|
||||
done_sem = xSemaphoreCreateCounting(2, 0);
|
||||
xTaskCreate(tskRunSHASelftests, "SHASelftests1", 8192, NULL, 3, NULL);
|
||||
xTaskCreate(tskRunSHASelftests, "SHASelftests2", 8192, NULL, 3, NULL);
|
||||
xTaskCreate(tskRunSHASelftests, "SHASelftests1", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
|
||||
xTaskCreate(tskRunSHASelftests, "SHASelftests2", SHA_TASK_STACK_SIZE, NULL, 3, NULL);
|
||||
|
||||
#ifdef CONFIG_MBEDTLS_HARDWARE_SHA
|
||||
const int TIMEOUT_MS = 12000;
|
||||
#else
|
||||
const int TIMEOUT_MS = 20000; // Soft-only SHA may need a little longer
|
||||
#endif
|
||||
const int TIMEOUT_MS = 20000;
|
||||
|
||||
for(int i = 0; i < 2; i++) {
|
||||
if(!xSemaphoreTake(done_sem, TIMEOUT_MS/portTICK_PERIOD_MS)) {
|
||||
|
|
|
@ -25,14 +25,21 @@ extern "C" {
|
|||
|
||||
//Registers Operation {{
|
||||
|
||||
//Register read macros with an underscore prefix access DPORT memory directly. In IDF apps, use the non-underscore versions to be SMP-safe.
|
||||
// The _DPORT_xxx register read macros access DPORT memory directly (as opposed to
|
||||
// DPORT_REG_READ which applies SMP-safe protections).
|
||||
//
|
||||
// Use DPORT_REG_READ versions to be SMP-safe in IDF apps. If you want to
|
||||
// make a sequence of DPORT reads, use DPORT_STALL_OTHER_CPU_START() macro
|
||||
// explicitly and then use _DPORT_REG_READ macro while other CPU is stalled.
|
||||
//
|
||||
// _DPORT_REG_WRITE & DPORT_REG_WRITE are equivalent.
|
||||
#define _DPORT_REG_READ(_r) (*(volatile uint32_t *)(_r))
|
||||
#define _DPORT_REG_WRITE(_r, _v) (*(volatile uint32_t *)(_r)) = (_v)
|
||||
|
||||
//write value to register
|
||||
// Write value to DPORT register (does not require protecting)
|
||||
#define DPORT_REG_WRITE(_r, _v) _DPORT_REG_WRITE((_r), (_v))
|
||||
|
||||
//read value from register
|
||||
// Read value from register, SMP-safe version.
|
||||
static inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg)
|
||||
{
|
||||
uint32_t val;
|
||||
|
@ -83,6 +90,8 @@ static inline uint32_t IRAM_ATTR DPORT_REG_READ(uint32_t reg)
|
|||
//Register read macros with an underscore prefix access DPORT memory directly. In IDF apps, use the non-underscore versions to be SMP-safe.
|
||||
#define _DPORT_READ_PERI_REG(addr) (*((volatile uint32_t *)(addr)))
|
||||
#define _DPORT_WRITE_PERI_REG(addr, val) (*((volatile uint32_t *)(addr))) = (uint32_t)(val)
|
||||
#define _DPORT_REG_SET_BIT(_r, _b) _DPORT_REG_WRITE((_r), (_DPORT_REG_READ(_r)|(_b)))
|
||||
#define _DPORT_REG_CLR_BIT(_r, _b) _DPORT_REG_WRITE((_r), (_DPORT_REG_READ(_r) & (~(_b))))
|
||||
|
||||
//read value from register
|
||||
static inline uint32_t IRAM_ATTR DPORT_READ_PERI_REG(uint32_t addr)
|
||||
|
|
|
@ -57,4 +57,12 @@
|
|||
#define SHA_512_LOAD_REG ((DR_REG_SHA_BASE) + 0xb8)
|
||||
#define SHA_512_BUSY_REG ((DR_REG_SHA_BASE) + 0xbc)
|
||||
|
||||
/* AES acceleration registers */
|
||||
#define AES_START_REG ((DR_REG_AES_BASE) + 0x00)
|
||||
#define AES_IDLE_REG ((DR_REG_AES_BASE) + 0x04)
|
||||
#define AES_MODE_REG ((DR_REG_AES_BASE) + 0x08)
|
||||
#define AES_KEY_BASE ((DR_REG_AES_BASE) + 0x10)
|
||||
#define AES_TEXT_BASE ((DR_REG_AES_BASE) + 0x30)
|
||||
#define AES_ENDIAN ((DR_REG_AES_BASE) + 0x40)
|
||||
|
||||
#endif
|
||||
|
|
|
@ -69,9 +69,10 @@
|
|||
#define SOC_RTC_DATA_HIGH 0x50002000
|
||||
|
||||
#define DR_REG_DPORT_BASE 0x3ff00000
|
||||
#define DR_REG_DPORT_END 0x3ff00FFC
|
||||
#define DR_REG_AES_BASE 0x3ff01000
|
||||
#define DR_REG_RSA_BASE 0x3ff02000
|
||||
#define DR_REG_SHA_BASE 0x3ff03000
|
||||
#define DR_REG_DPORT_END 0x3ff03FFC
|
||||
#define DR_REG_UART_BASE 0x3ff40000
|
||||
#define DR_REG_SPI1_BASE 0x3ff42000
|
||||
#define DR_REG_SPI0_BASE 0x3ff43000
|
||||
|
|
|
@ -19,7 +19,6 @@ CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y
|
|||
# CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG is not set
|
||||
# CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE is not set
|
||||
CONFIG_LOG_BOOTLOADER_LEVEL=2
|
||||
# CONFIG_BOOTLOADER_LTO is not set
|
||||
|
||||
#
|
||||
# Security features
|
||||
|
@ -174,6 +173,11 @@ CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=0
|
|||
# CONFIG_ESP32_XTAL_FREQ_26 is not set
|
||||
CONFIG_ESP32_XTAL_FREQ_AUTO=y
|
||||
CONFIG_ESP32_XTAL_FREQ=0
|
||||
# CONFIG_NO_BLOBS is not set
|
||||
|
||||
#
|
||||
# Wi-Fi
|
||||
#
|
||||
CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10
|
||||
CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=0
|
||||
# CONFIG_ESP32_WIFI_STATIC_TX_BUFFER is not set
|
||||
|
@ -181,8 +185,9 @@ CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y
|
|||
CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1
|
||||
CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32
|
||||
CONFIG_ESP32_WIFI_AMPDU_ENABLED=y
|
||||
CONFIG_ESP32_WIFI_TX_BA_WIN=6
|
||||
CONFIG_ESP32_WIFI_RX_BA_WIN=6
|
||||
CONFIG_ESP32_WIFI_NVS_ENABLED=y
|
||||
CONFIG_PHY_ENABLED=y
|
||||
|
||||
#
|
||||
# PHY
|
||||
|
@ -280,10 +285,16 @@ CONFIG_TCP_SYNMAXRTX=6
|
|||
CONFIG_TCP_MSS=1436
|
||||
CONFIG_TCP_SND_BUF_DEFAULT=5744
|
||||
CONFIG_TCP_WND_DEFAULT=5744
|
||||
CONFIG_TCP_RECVMBOX_SIZE=6
|
||||
CONFIG_TCP_QUEUE_OOSEQ=y
|
||||
CONFIG_TCP_OVERSIZE_MSS=y
|
||||
# CONFIG_TCP_OVERSIZE_QUARTER_MSS is not set
|
||||
# CONFIG_TCP_OVERSIZE_DISABLE is not set
|
||||
|
||||
#
|
||||
# UDP
|
||||
#
|
||||
CONFIG_UDP_RECVMBOX_SIZE=6
|
||||
# CONFIG_LWIP_DHCP_DOES_ARP_CHECK is not set
|
||||
CONFIG_TCPIP_TASK_STACK_SIZE=2048
|
||||
# CONFIG_PPP_SUPPORT is not set
|
||||
|
@ -299,7 +310,10 @@ CONFIG_TCPIP_TASK_STACK_SIZE=2048
|
|||
#
|
||||
CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384
|
||||
# CONFIG_MBEDTLS_DEBUG is not set
|
||||
# CONFIG_MBEDTLS_UNSAFE_ACCELERATION is not set
|
||||
CONFIG_MBEDTLS_HARDWARE_AES=y
|
||||
CONFIG_MBEDTLS_HARDWARE_MPI=y
|
||||
CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y
|
||||
CONFIG_MBEDTLS_HARDWARE_SHA=y
|
||||
CONFIG_MBEDTLS_HAVE_TIME=y
|
||||
# CONFIG_MBEDTLS_HAVE_TIME_DATE is not set
|
||||
|
||||
|
@ -315,3 +329,10 @@ CONFIG_OPENSSL_ASSERT_DO_NOTHING=y
|
|||
#
|
||||
# CONFIG_SPI_FLASH_ENABLE_COUNTERS is not set
|
||||
CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y
|
||||
|
||||
#
|
||||
# Wear Levelling
|
||||
#
|
||||
# CONFIG_WL_SECTOR_SIZE_512 is not set
|
||||
CONFIG_WL_SECTOR_SIZE_4096=y
|
||||
CONFIG_WL_SECTOR_SIZE=4096
|
||||
|
|
Loading…
Reference in a new issue