Espressif HW acceleration update & cleanup

This commit is contained in:
gojimmypi
2022-07-06 09:30:49 -07:00
parent 9a256ca002
commit 8bb6ff8dbb
12 changed files with 994 additions and 373 deletions

View File

@ -1,6 +1,24 @@
#
# Copyright (C) 2014-2022 wolfSSL Inc.
#
# This file is part of wolfSSH.
#
# wolfSSH is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# wolfSSH is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with wolfSSH. If not, see <http://www.gnu.org/licenses/>.
#
#
# cmake for wolfssl
#
#
cmake_minimum_required(VERSION 3.5)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DWOLFSSL_USER_SETTINGS")
@ -12,15 +30,24 @@ set(COMPONENT_SRCDIRS "./src/"
"./wolfcrypt/src/"
"./wolfcrypt/src/port/Espressif/"
"./wolfcrypt/src/port/atmel/"
# "$ENV{IDF_PATH}/components/soc/esp32s3/include/soc"
)
set(COMPONENT_REQUIRES lwip)
# RTOS_IDF_PATH is typically:
# "/Users/{username}/Desktop/esp-idf/components/freertos/include/freertos"
# depending on the environment, we may need to swap backslashes with forward slashes
string(REPLACE "\\" "/" RTOS_IDF_PATH "$ENV{IDF_PATH}/components/freertos/include/freertos")
# ESP-IDF after version 4.4x has a different RTOS directory structure
string(REPLACE "\\" "/" RTOS_IDF_PATH5 "$ENV{IDF_PATH}/components/freertos/FreeRTOS-Kernel/include/freertos")
if(IS_DIRECTORY ${IDF_PATH}/components/freertos/FreeRTOS-Kernel/)
set(COMPONENT_ADD_INCLUDEDIRS
"."
"./include"
"../freertos/FreeRTOS-Kernel/include/freertos"
"${RTOS_IDF_PATH5}"
"${WOLFSSL_ROOT}"
)
else()
@ -28,7 +55,7 @@ else()
set(COMPONENT_ADD_INCLUDEDIRS
"."
"./include"
"../freertos/include/freertos"
"${RTOS_IDF_PATH}"
"${WOLFSSL_ROOT}"
)
endif()
@ -49,3 +76,11 @@ set(COMPONENT_SRCEXCLUDE
)
register_component()
# check to see if there's both a local copy and EDP-IDF copy of the wolfssl components
if( EXISTS "${CMAKE_HOME_DIRECTORY}/components/wolfssl/" AND EXISTS "$ENV{IDF_PATH}/components/wolfssl/" )
message(STATUS "")
message(STATUS "WARNING: Found components/wolfssl in both local project and IDF_PATH")
message(STATUS "")
endif()
# end multiple component check

View File

@ -1,17 +1,37 @@
#
# Component Makefile
#
COMPONENT_ADD_INCLUDEDIRS := . ./include
COMPONENT_ADD_INCLUDEDIRS += ../freertos/include/freertos/
COMPONENT_SRCDIRS := src wolfcrypt/src
COMPONENT_SRCDIRS += wolfcrypt/src/port/Espressif
COMPONENT_SRCDIRS += wolfcrypt/src/port/atmel
CFLAGS +=-DWOLFSSL_USER_SETTINGS
COMPONENT_OBJEXCLUDE := wolfcrypt/src/aes_asm.o
COMPONENT_OBJEXCLUDE += wolfcrypt/src/evp.o
COMPONENT_OBJEXCLUDE += wolfcrypt/src/misc.o
COMPONENT_OBJEXCLUDE += src/bio.o
#
# Copyright (C) 2014-2022 wolfSSL Inc.
#
# This file is part of wolfSSH.
#
# wolfSSH is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.
#
# wolfSSH is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with wolfSSH. If not, see <http://www.gnu.org/licenses/>.
#
#
# Component Makefile
#
COMPONENT_ADD_INCLUDEDIRS := . ./include
COMPONENT_ADD_INCLUDEDIRS += "$ENV{IDF_PATH}/components/freertos/include/freertos"
# COMPONENT_ADD_INCLUDEDIRS += "$ENV{IDF_PATH}/soc/esp32s3/include/soc"
COMPONENT_SRCDIRS := src wolfcrypt/src
COMPONENT_SRCDIRS += wolfcrypt/src/port/Espressif
COMPONENT_SRCDIRS += wolfcrypt/src/port/atmel
CFLAGS +=-DWOLFSSL_USER_SETTINGS
COMPONENT_OBJEXCLUDE := wolfcrypt/src/aes_asm.o
COMPONENT_OBJEXCLUDE += wolfcrypt/src/evp.o
COMPONENT_OBJEXCLUDE += wolfcrypt/src/misc.o
COMPONENT_OBJEXCLUDE += src/bio.o

View File

@ -1,6 +1,6 @@
/* user_settings.h
*
* Copyright (C) 2006-2021 wolfSSL Inc.
* Copyright (C) 2006-2022 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@ -19,22 +19,24 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#undef WOLFSSL_ESPIDF
#undef WOLFSSL_ESPWROOM32
#undef WOLFSSL_ESPWROOM32SE
#undef WOLFSSL_ESPWROOM32
#undef WOLFSSL_ESP8266
#define WOLFSSL_ESPIDF
/*
* choose ONE of these Espressif chips to define:
*
*
* WOLFSSL_ESPWROOM32
* WOLFSSL_ESPWROOM32SE
* WOLFSSL_ESP8266
*
* comment out the others:
*/
#define WOLFSSL_ESPWROOM32
/* #define WOLFSSL_ESPWROOM32SE */
/* #define WOLFSSL_ESP8266 */
/* #define DEBUG_WOLFSSL_VERBOSE */
#define BENCH_EMBEDDED
#define USE_CERT_BUFFERS_2048
@ -88,7 +90,7 @@
/* Define USE_FAST_MATH and SMALL_STACK */
#define ESP32_USE_RSA_PRIMITIVE
/* threshold for performance adjustment for hw primitive use */
/* X bits of G^X mod P greater than */
/* X bits of G^X mod P greater than */
#define EPS_RSA_EXPT_XBTIS 36
/* X and Y of X * Y mod P greater than */
#define ESP_RSA_MULM_BITS 2000

View File

@ -1,6 +1,6 @@
/* esp32_aes.c
*
* Copyright (C) 2006-2021 wolfSSL Inc.
* Copyright (C) 2006-2022 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@ -19,6 +19,10 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/*
* WOLFSSL_SUCCESS and WOLFSSL_FAILURE values should only
* be used in the ssl layer, not in wolfCrypt
**/
#include <string.h>
#include <stdio.h>
@ -36,13 +40,18 @@
#include "wolfssl/wolfcrypt/port/Espressif/esp32-crypt.h"
static const char* TAG = "wolf_hw_aes";
/* mutex */
static wolfSSL_Mutex aes_mutex;
/* keep track as to whether esp aes is initialized */
static int espaes_CryptHwMutexInit = 0;
/*
* lock hw engine.
* this should be called before using engine.
*
* returns 0 if the hw lock was initialized and mutex lock
*/
static int esp_aes_hw_InUse()
{
@ -50,21 +59,29 @@ static int esp_aes_hw_InUse()
ESP_LOGV(TAG, "enter esp_aes_hw_InUse");
if(espaes_CryptHwMutexInit == 0) {
if (espaes_CryptHwMutexInit == 0) {
ret = esp_CryptHwMutexInit(&aes_mutex);
if(ret == 0){
if (ret == 0) {
/* flag esp aes as initialized */
espaes_CryptHwMutexInit = 1;
} else {
ESP_LOGE(TAG, "aes mutx initialization failed.");
}
else {
ESP_LOGE(TAG, "aes mutex initialization failed.");
return -1;
}
}
else {
/* esp aes has already been initialized */
}
/* lock hardware */
ret = esp_CryptHwMutexLock(&aes_mutex, portMAX_DELAY);
if(ret != 0) {
ESP_LOGE(TAG, "aes engine lock failed.");
return -1;
}
/* Enable AES hardware */
periph_module_enable(PERIPH_AES_MODULE);
@ -92,23 +109,27 @@ static void esp_aes_hw_Leave( void )
*/
static void esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode)
{
int i;
word32 i;
word32 mode_ = 0;
ESP_LOGV(TAG, "enter esp_aes_hw_Set_KeyMode");
ESP_LOGV(TAG, " enter esp_aes_hw_Set_KeyMode");
/* check mode */
if(mode == ESP32_AES_UPDATEKEY_ENCRYPT) {
mode_ = 0;
} else if(mode == ESP32_AES_UPDATEKEY_DECRYPT){
mode_ = 4;
} else {
ESP_LOGE(TAG, "unexpected error.");
return;
}
else {
if (mode == ESP32_AES_UPDATEKEY_DECRYPT) {
mode_ = 4;
}
else {
ESP_LOGE(TAG, " >> unexpected error.");
return;
}
}
/* update key */
for(i=0;i<(ctx->keylen)/sizeof(word32);i++){
for(i=0; i<(ctx->keylen)/sizeof(word32); i++){
DPORT_REG_WRITE(AES_KEY_BASE + (i*4), *(((word32*)ctx->key) + i));
}
@ -127,7 +148,7 @@ static void esp_aes_hw_Set_KeyMode(Aes *ctx, ESP32_AESPROCESS mode)
}
DPORT_REG_WRITE(AES_MODE_REG, mode_);
ESP_LOGV(TAG, "leave esp_aes_hw_Setkey");
ESP_LOGV(TAG, " leave esp_aes_hw_Setkey");
}
/*
@ -181,6 +202,7 @@ int wc_esp32AesEncrypt(Aes *aes, const byte* in, byte* out)
esp_aes_hw_Leave();
return 0;
}
/*
* wc_esp32AesDecrypt
* @brief: a one block decrypt of the input block, into the output block
@ -202,6 +224,7 @@ int wc_esp32AesDecrypt(Aes *aes, const byte* in, byte* out)
esp_aes_hw_Leave();
return 0;
}
/*
* wc_esp32AesCbcEncrypt
* @brief: Encrypts a plain text message from the input buffer, and places the
@ -281,8 +304,9 @@ int wc_esp32AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz)
esp_aes_bk((in + offset), (out + offset));
/* XOR block with IV for CBC */
for (i = 0; i < AES_BLOCK_SIZE; i++)
for (i = 0; i < AES_BLOCK_SIZE; i++) {
(out + offset)[i] ^= iv[i];
}
/* store IV for next block */
XMEMCPY(iv, temp_block, AES_BLOCK_SIZE);

View File

@ -1,6 +1,6 @@
/* esp32_mp.c
*
* Copyright (C) 2006-2021 wolfSSL Inc.
* Copyright (C) 2006-2022 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@ -58,46 +58,91 @@ static wolfSSL_Mutex mp_mutex;
static int espmp_CryptHwMutexInit = 0;
/*
* check if the hw is ready before accessing it
*
* When the RSA Accelerator is released from reset, the register RSA_CLEAN_REG
* reads 0 and an initialization process begins. Hardware initializes the four
* memory blocks by setting them to 0. After initialization is complete,
* RSA_CLEAN_REG reads 1. For this reason, software should query RSA_CLEAN_REG
* after being released from reset, and before writing to any RSA Accelerator
* memory blocks or registers for the first time.
*/
static int esp_mp_hw_wait_clean()
{
word32 timeout = 0;
while(!ESP_TIMEOUT(++timeout) &&
DPORT_REG_READ(RSA_CLEAN_REG) != 1) { }
if(ESP_TIMEOUT(timeout)) {
while(!ESP_TIMEOUT(++timeout) &&
DPORT_REG_READ(RSA_CLEAN_REG) != 1) {
/* wait. expected delay 1 to 2 uS */
}
if (ESP_TIMEOUT(timeout)) {
ESP_LOGE(TAG, "waiting hw ready is timed out.");
return MP_NG;
}
return MP_OKAY;
return MP_OKAY;
}
/*
* lock hw engine.
* this should be called before using engine.
*
* returns 0 if the hw lock was initialized and mutex lock
*
* See Chapter 24:
* https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf
*
* The RSA Accelerator is activated by enabling the corresponding peripheral
* clock, and by clearing the DPORT_RSA_PD bit in the DPORT_RSA_PD_CTRL_REG
* register. This releases the RSA Accelerator from reset.
*
* When the RSA Accelerator is released from reset, the register RSA_CLEAN_REG
* reads 0 and an initialization process begins. Hardware initializes the four
* memory blocks by setting them to 0. After initialization is complete,
* RSA_CLEAN_REG reads 1. For this reason, software should query RSA_CLEAN_REG
* after being released from reset, and before writing to any RSA Accelerator
* memory blocks or registers for the first time.
*/
static int esp_mp_hw_lock()
{
int ret = 0;
if(espmp_CryptHwMutexInit == 0) {
ESP_LOGV(TAG, "enter esp_mp_hw_lock");
if (espmp_CryptHwMutexInit == 0) {
ret = esp_CryptHwMutexInit(&mp_mutex);
if(ret == 0){
if (ret == 0) {
/* flag esp mp as initialized */
espmp_CryptHwMutexInit = 1;
} else {
}
else {
ESP_LOGE(TAG, "mp mutx initialization failed.");
return MP_NG;
}
}
else {
/* esp aes has already been iniitlized */
}
/* lock hardware */
ret = esp_CryptHwMutexLock(&mp_mutex, portMAX_DELAY);
if(ret != 0) {
if (ret != 0) {
ESP_LOGE(TAG, "mp engine lock failed.");
return MP_NG;
}
/* Enable RSA hardware */
periph_module_enable(PERIPH_RSA_MODULE);
/* clear bit to enable hardware operation; (set to disable)
*/
DPORT_REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
/* remionder: wait until RSA_CLEAN_REG reads 1
* see esp_mp_hw_wait_clean()
*/
ESP_LOGV(TAG, "leave esp_mp_hw_lock");
return ret;
}
/*
@ -105,12 +150,17 @@ static int esp_mp_hw_lock()
*/
static void esp_mp_hw_unlock( void )
{
/* set bit to disabled hardware operation; (clear to enable)
*/
DPORT_REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD);
/* Disable RSA hardware */
periph_module_disable(PERIPH_RSA_MODULE);
/* unlock */
esp_CryptHwMutexUnLock(&mp_mutex);
}
/* this is based on an article by Cetin Kaya Koc, A New Algorithm for Inversion*/
/* mod p^k, June 28 2017. */
static int esp_calc_Mdash(mp_int *M, word32 k, mp_digit* md)
@ -126,9 +176,9 @@ static int esp_calc_Mdash(mp_int *M, word32 k, mp_digit* md)
bi = b0;
x = 0;
for(i = 0; i < k; i++) {
for (i = 0; i < k; i++) {
xi = bi % 2;
if(xi < 0){
if (xi < 0) {
xi *= -1;
}
bi = (bi - N * xi) / 2;
@ -138,6 +188,7 @@ static int esp_calc_Mdash(mp_int *M, word32 k, mp_digit* md)
*md = ~x + 1;
return MP_OKAY;
}
/* start hw process */
static void process_start(word32 reg)
{
@ -146,87 +197,100 @@ static void process_start(word32 reg)
/* start process */
DPORT_REG_WRITE(reg, 1);
}
/* wait until done */
static int wait_uitil_done(word32 reg)
{
word32 timeout = 0;
/* wait until done && not timeout */
while(!ESP_TIMEOUT(++timeout) &&
DPORT_REG_READ(reg) != 1) { }
while (!ESP_TIMEOUT(++timeout) &&
DPORT_REG_READ(reg) != 1) {
/* wait */
}
/* clear interrupt */
DPORT_REG_WRITE(RSA_INTERRUPT_REG, 1);
if(ESP_TIMEOUT(timeout)) {
if (ESP_TIMEOUT(timeout)) {
ESP_LOGE(TAG, "rsa operation is timed out.");
return MP_NG;
}
return MP_OKAY;
}
/* read data from memory into mp_init */
static void esp_memblock_to_mpint(word32 mem_address, mp_int* mp, word32 numwords)
static void esp_memblock_to_mpint(word32 mem_address,
mp_int* mp,
word32 numwords)
{
esp_dport_access_read_buffer((uint32_t*)mp->dp, mem_address, numwords);
mp->used = numwords;
}
/* write mp_init into memory block */
/* write mp_init into memory block
*/
static void esp_mpint_to_memblock(word32 mem_address, const mp_int* mp,
const word32 bits,
const word32 hwords)
{
/* init */
word32 i;
word32 len = (bits / 8 + ((bits & 7) != 0 ? 1 : 0));
len = (len+sizeof(word32)-1)/sizeof(word32);
len = (len + sizeof(word32)-1) / sizeof(word32);
for(i=0;i < hwords; i++) {
if(i < len) {
for (i=0; i < hwords; i++) {
if (i < len) {
DPORT_REG_WRITE(mem_address + (i * sizeof(word32)), mp->dp[i]);
} else {
}
else {
DPORT_REG_WRITE(mem_address + (i * sizeof(word32)), 0);
}
}
}
/* return needed hw words. */
/* supported words length */
/* words : {16 , 32, 48, 64, 80, 96, 112, 128} */
/* bits : {512,1024, 1536, 2048, 2560, 3072, 3584, 4096} */
/* return needed hw words.
* supported words length
* words : {16 , 32, 48, 64, 80, 96, 112, 128}
* bits : {512,1024, 1536, 2048, 2560, 3072, 3584, 4096}
*/
static word32 words2hwords(word32 wd)
{
const word32 shit_ = 4;
const word32 bit_shift = 4;
return (((wd + 0xf)>>shit_)<<shit_);
return (((wd + 0xf) >> bit_shift) << bit_shift);
}
/* count the number of words is needed for bits */
static word32 bits2words(word32 bits)
{
/* 32 bits */
const word32 d = sizeof(word32) * WOLFSSL_BIT_SIZE;
return((bits + (d - 1))/d);
return ((bits + (d - 1)) / d);
}
/* get rinv */
static int esp_get_rinv(mp_int *rinv, mp_int *M, word32 exp)
{
int ret = 0;
/* 2^(exp)*/
if((ret = mp_2expt(rinv, exp)) != MP_OKAY) {
if ((ret = mp_2expt(rinv, exp)) != MP_OKAY) {
ESP_LOGE(TAG, "failed to calculate mp_2expt()");
return ret;
}
/* r_inv = R^2 mod M(=P) */
if(ret == 0 && (ret = mp_mod(rinv, M, rinv)) != MP_OKAY){
if (ret == 0 && (ret = mp_mod(rinv, M, rinv)) != MP_OKAY) {
ESP_LOGE(TAG, "failed to calculate mp_mod()");
return ret;
}
return ret;
}
/* Z = X * Y; */
/* Z = X * Y; */
int esp_mp_mul(fp_int* X, fp_int* Y, fp_int* Z)
{
int ret = 0;
@ -268,34 +332,46 @@ int esp_mp_mul(fp_int* X, fp_int* Y, fp_int* Z)
* 9. Release the hw engine
*/
/* lock hw for use */
if((ret = esp_mp_hw_lock()) != MP_OKAY)
if ((ret = esp_mp_hw_lock()) != MP_OKAY) {
return ret;
}
if((ret = esp_mp_hw_wait_clean()) != MP_OKAY){
if((ret = esp_mp_hw_wait_clean()) != MP_OKAY) {
return ret;
}
/* step.1 (2*N/512) => N/256. 512 bits => 16 words */
DPORT_REG_WRITE(RSA_MULT_MODE_REG, (hwWords_sz >> 3) - 1 + 8);
/* step.2 write X, M and r_inv into memory */
esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, X, Xs, hwWords_sz);
esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE,
X,
Xs,
hwWords_sz);
/* Y(let-extend) */
esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE + (hwWords_sz<<2), Y, Ys, hwWords_sz);
esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE + (hwWords_sz<<2),
Y,
Ys,
hwWords_sz);
/* step.3 start process */
process_start(RSA_MULT_START_REG);
/* step.4,5 wait until done */
wait_uitil_done(RSA_INTERRUPT_REG);
ret = wait_uitil_done(RSA_INTERRUPT_REG);
if (ret != MP_OKAY) {
ESP_LOGE(TAG, "wait_uitil_done failed.");
return ret;
}
/* step.6 read the result form MEM_Z */
esp_memblock_to_mpint(RSA_MEM_Z_BLOCK_BASE, Z, BITS_TO_WORDS(Zs));
/* step.7 clear and release hw */
esp_mp_hw_unlock();
Z->sign = (Z->used > 0)? neg : MP_ZPOS;
Z->sign = (Z->used > 0) ? neg : MP_ZPOS;
return ret;
}
/* Z = X * Y (mod M) */
int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z)
{
@ -313,7 +389,7 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z)
mp_digit mp;
/* neg check */
if(X->sign != Y->sign) {
if (X->sign != Y->sign) {
/* X*Y becomes negative */
negcheck = 1;
}
@ -327,7 +403,7 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z)
zwords = bits2words(min(Ms, Xs + Ys));
hwWords_sz = words2hwords(maxWords_sz);
if((hwWords_sz<<5) > ESP_HW_RSAMAX_BIT) {
if ((hwWords_sz << 5) > ESP_HW_RSAMAX_BIT) {
ESP_LOGE(TAG, "exceeds hw maximum bits");
return -2;
}
@ -336,20 +412,20 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z)
* accordingly R^2 = 2^(n*32*2)
*/
ret = mp_init_multi(&tmpZ, &r_inv, NULL, NULL, NULL, NULL);
if(ret == 0 && (ret = esp_get_rinv(&r_inv, M, (hwWords_sz<<6))) != MP_OKAY) {
if (ret == 0 && (ret = esp_get_rinv(&r_inv, M, (hwWords_sz << 6))) != MP_OKAY) {
ESP_LOGE(TAG, "calculate r_inv failed.");
mp_clear(&tmpZ);
mp_clear(&r_inv);
return ret;
}
/* lock hw for use */
if((ret = esp_mp_hw_lock()) != MP_OKAY){
if ((ret = esp_mp_hw_lock()) != MP_OKAY) {
mp_clear(&tmpZ);
mp_clear(&r_inv);
return ret;
}
/* Calculate M' */
if((ret = esp_calc_Mdash(M, 32/* bits */, &mp)) != MP_OKAY) {
if ((ret = esp_calc_Mdash(M, 32/* bits */, &mp)) != MP_OKAY) {
ESP_LOGE(TAG, "failed to calculate M dash");
mp_clear(&tmpZ);
mp_clear(&r_inv);
@ -374,7 +450,7 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z)
* 13. Release the hw engine
*/
if((ret = esp_mp_hw_wait_clean()) != MP_OKAY){
if ((ret = esp_mp_hw_wait_clean()) != MP_OKAY) {
return ret;
}
/* step.1 512 bits => 16 words */
@ -383,8 +459,11 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z)
/* step.2 write X, M and r_inv into memory */
esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, X, Xs, hwWords_sz);
esp_mpint_to_memblock(RSA_MEM_M_BLOCK_BASE, M, Ms, hwWords_sz);
esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE, &r_inv, mp_count_bits(&r_inv),
hwWords_sz);
esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE,
&r_inv,
mp_count_bits(&r_inv),
hwWords_sz);
/* step.3 write M' into memory */
DPORT_REG_WRITE(RSA_M_DASH_REG, mp);
/* step.4 start process */
@ -409,11 +488,11 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z)
/* additional steps */
/* this needs for known issue when Z is greater than M */
if(mp_cmp(&tmpZ, M)==FP_GT) {
/* Z -= M */
mp_sub(&tmpZ, M, &tmpZ);
if (mp_cmp(&tmpZ, M) == FP_GT) {
/* Z -= M */
mp_sub(&tmpZ, M, &tmpZ);
}
if(negcheck) {
if (negcheck) {
mp_sub(M, &tmpZ, &tmpZ);
}
@ -424,7 +503,25 @@ int esp_mp_mulmod(fp_int* X, fp_int* Y, fp_int* M, fp_int* Z)
return ret;
}
/* Z = X^Y mod M */
/* Large Number Modular Exponentiation
*
* Z = X^Y mod M
*
* See Chapter 24:
* https://www.espressif.com/sites/default/files/documentation/esp32_technical_reference_manual_en.pdf
*
* The operation is based on Montgomery multiplication. Aside from the
* arguments X, Y , and M, two additional ones are needed —r and M
.* These arguments are calculated in advance by software.
.*
.* The RSA Accelerator supports operand lengths of N ∈ {512, 1024, 1536, 2048,
.* 2560, 3072, 3584, 4096} bits. The bit length of arguments Z, X, Y , M,
.* and r can be any one from the N set, but all numbers in a calculation must
.* be of the same length. The bit length of M is always 32.
.*
.* Note some DH references may use: Y = (G ^ X) mod P
*/
int esp_mp_exptmod(fp_int* X, fp_int* Y, word32 Ys, fp_int* M, fp_int* Z)
{
int ret = 0;
@ -444,7 +541,7 @@ int esp_mp_exptmod(fp_int* X, fp_int* Y, word32 Ys, fp_int* M, fp_int* Z)
maxWords_sz = bits2words(max(Xs, max(Ys, Ms)));
hwWords_sz = words2hwords(maxWords_sz);
if((hwWords_sz<<5) > ESP_HW_RSAMAX_BIT) {
if ((hwWords_sz << 5) > ESP_HW_RSAMAX_BIT) {
ESP_LOGE(TAG, "exceeds hw maximum bits");
return -2;
}
@ -453,19 +550,19 @@ int esp_mp_exptmod(fp_int* X, fp_int* Y, word32 Ys, fp_int* M, fp_int* Z)
* accordingly R^2 = 2^(n*32*2)
*/
ret = mp_init(&r_inv);
if(ret == 0 && (ret = esp_get_rinv(&r_inv, M, (hwWords_sz<<6))) != MP_OKAY) {
if (ret == 0 && (ret = esp_get_rinv(&r_inv, M, (hwWords_sz << 6))) != MP_OKAY) {
ESP_LOGE(TAG, "calculate r_inv failed.");
mp_clear(&r_inv);
return ret;
}
/* lock and init the hw */
if((ret = esp_mp_hw_lock()) != MP_OKAY) {
if ((ret = esp_mp_hw_lock()) != MP_OKAY) {
mp_clear(&r_inv);
return ret;
}
/* calc M' */
/* if Pm is odd, uses mp_montgomery_setup() */
if((ret = esp_calc_Mdash(M, 32/* bits */, &mp)) != MP_OKAY) {
if ((ret = esp_calc_Mdash(M, 32/* bits */, &mp)) != MP_OKAY) {
ESP_LOGE(TAG, "failed to calculate M dash");
mp_clear(&r_inv);
return -1;
@ -483,7 +580,7 @@ int esp_mp_exptmod(fp_int* X, fp_int* Y, word32 Ys, fp_int* M, fp_int* Z)
* 6. Read the result Z(=Y) from Z_MEM
* 7. Write 1 to INTERRUPT_REG to clear the interrupt.
*/
if((ret = esp_mp_hw_wait_clean()) != MP_OKAY){
if ((ret = esp_mp_hw_wait_clean()) != MP_OKAY) {
return ret;
}
@ -493,8 +590,10 @@ int esp_mp_exptmod(fp_int* X, fp_int* Y, word32 Ys, fp_int* M, fp_int* Z)
esp_mpint_to_memblock(RSA_MEM_X_BLOCK_BASE, X, Xs, hwWords_sz);
esp_mpint_to_memblock(RSA_MEM_Y_BLOCK_BASE, Y, Ys, hwWords_sz);
esp_mpint_to_memblock(RSA_MEM_M_BLOCK_BASE, M, Ms, hwWords_sz);
esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE, &r_inv, mp_count_bits(&r_inv),
hwWords_sz);
esp_mpint_to_memblock(RSA_MEM_Z_BLOCK_BASE,
&r_inv,
mp_count_bits(&r_inv),
hwWords_sz);
/* step.3 write M' into memory */
DPORT_REG_WRITE(RSA_M_DASH_REG, mp);
/* step.4 start process */
@ -512,4 +611,5 @@ int esp_mp_exptmod(fp_int* X, fp_int* Y, word32 Ys, fp_int* M, fp_int* Z)
return ret;
}
#endif /* !NO_RSA || HAVE_ECC */
#endif /* (WOLFSS_ESP32WROOM32_CRYPT) && (NO_WOLFSSL_ESP32WROOM32_CRYPT_RES_PRI)*/

View File

@ -18,23 +18,28 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
#include <string.h>
#include <stdio.h>
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#include <wolfssl/wolfcrypt/settings.h>
/*****************************************************************************/
/* this entire file content is excluded when NO_SHA, NO_SHA256
* or when using WC_SHA384 or WC_SHA512
*/
#if !defined(NO_SHA) || !defined(NO_SHA256) || defined(WC_SHA384) || \
defined(WC_SHA512)
#include "wolfssl/wolfcrypt/logging.h"
/* this entire file content is excluded if not using HW hash acceleration */
#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
/* TODO this may be chip type dependent: add support for others */
#include <hal/clk_gate_ll.h> /* ESP32-WROOM */
#include <wolfssl/wolfcrypt/sha.h>
#include <wolfssl/wolfcrypt/sha256.h>
#include <wolfssl/wolfcrypt/sha512.h>
@ -50,20 +55,29 @@
#endif
static const char* TAG = "wolf_hw_sha";
/* continue register offset */
#define CONTINUE_REG_OFFSET (0x04) /* start_reg + 0x04 */
#ifdef NO_SHA
#define WC_SHA_DIGEST_SIZE 20
#endif
/* mutex */
#if defined(SINGLE_THREADED)
static int InUse = 0;
static int InUse = 0;
#else
static wolfSSL_Mutex sha_mutex;
static int espsha_CryptHwMutexInit = 0;
static wolfSSL_Mutex sha_mutex;
static int espsha_CryptHwMutexInit = 0;
#if defined(DEBUG_WOLFSSL)
static int this_block_num = 0;
#endif
#endif
/*
* determine the digest size, depending on SHA type.
*
* See FIPS PUB 180-4, Instruction Section 1.
*
*
enum SHA_TYPE {
SHA1 = 0,
SHA2_256,
@ -72,43 +86,112 @@ static int espsha_CryptHwMutexInit = 0;
SHA_INVALID = -1,
};
*/
static word32 esp_sha_digest_size(enum SHA_TYPE type)
static word32 wc_esp_sha_digest_size(enum SHA_TYPE type)
{
ESP_LOGV(TAG, "enter esp_sha_digest_size");
ESP_LOGV(TAG, " esp_sha_digest_size");
switch(type){
#ifndef NO_SHA
case SHA1:
return WC_SHA_DIGEST_SIZE;
#endif
#ifndef NO_SHA256
case SHA2_256:
return WC_SHA256_DIGEST_SIZE;
#endif
#ifdef WOLFSSL_SHA384
case SHA2_384:
return WC_SHA384_DIGEST_SIZE;
#endif
#ifdef WOLFSSL_SHA512
case SHA2_512:
return WC_SHA512_DIGEST_SIZE;
#endif
#ifndef NO_SHA
case SHA1: /* typically 20 bytes */
return WC_SHA_DIGEST_SIZE;
#endif
#ifndef NO_SHA256
case SHA2_256: /* typically 32 bytes */
return WC_SHA256_DIGEST_SIZE;
#endif
#ifdef WOLFSSL_SHA384
case SHA2_384:
return WC_SHA384_DIGEST_SIZE;
#endif
#ifdef WOLFSSL_SHA512
case SHA2_512: /* typically 64 bytes */
return WC_SHA512_DIGEST_SIZE;
#endif
default:
ESP_LOGE(TAG, "Bad sha type");
return WC_SHA_DIGEST_SIZE;
}
ESP_LOGV(TAG, "leave esp_sha_digest_size");
/* we never get here, as all the above switches should have a return */
}
/*
* wait until engines becomes idle
* wait until all engines becomes idle
*/
static void esp_wait_until_idle()
static void wc_esp_wait_until_idle()
{
while((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)){ }
while((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)) {
/* do nothing while waiting. */
}
}
/*
* hack alert. there really should have been something implemented
* in periph_ctrl.c to detect ref_counts[periph] depth.
*
* since there is not at this time, we have this brute-force method.
*
* when trying to unwrap an arbitrary depth of peripheral-enable(s),
* we'll check the register upon *enable* to see if we actually did.
*
* Note that enable / disable only occurs when ref_counts[periph] == 0
*
* TODO: check if this works with other ESP32 platforms ESP32-C3, ESP32-S3, etc
*/
int esp_unroll_sha_module_enable(WC_ESP32SHA* ctx)
{
/* if we end up here, there was a prior unexpected fail and
* we need to unroll enables */
int ret = 0; /* assume success unless proven otherwise */
uint32_t this_sha_mask; /* this is the bit-mask for our SHA CLK_EN_REG */
int actual_unroll_count = 0;
int max_unroll_count = 1000; /* never get stuck in a hardware wait loop */
this_sha_mask = periph_ll_get_clk_en_mask(PERIPH_SHA_MODULE);
/* unwind prior calls to THIS ctx. decrement ref_counts[periph] */
/* only when ref_counts[periph] == 0 does something actually happen */
/* once the value we read is a 0 in the DPORT_PERI_CLK_EN_REG bit
* then we have fully unrolled the enables via ref_counts[periph]==0 */
while ((this_sha_mask & *(uint32_t*)DPORT_PERI_CLK_EN_REG) != 0) {
periph_module_disable(PERIPH_SHA_MODULE);
actual_unroll_count++;
ESP_LOGI(TAG, "unroll not yet successful. try #%d",
actual_unroll_count);
/* we'll only try this some unreasonable number of times
* before giving up */
if (actual_unroll_count > max_unroll_count) {
ret = -1; /* failed to unroll */
break;
}
}
if (ret == 0) {
if (ctx->lockDepth != actual_unroll_count) {
/* this could be a warning of wonkiness in RTOS environment.
* we were successful, but not expected depth count*/
ESP_LOGE(TAG, "warning lockDepth mismatch.");
}
ctx->lockDepth = 0;
ctx->mode = ESP32_SHA_INIT;
}
else {
ESP_LOGE(TAG, "Failed to unroll after %d attempts.",
actual_unroll_count);
ctx->mode = ESP32_SHA_SW;
}
return ret;
}
/*
* lock hw engine.
* this should be called before using engine.
@ -119,160 +202,375 @@ int esp_sha_try_hw_lock(WC_ESP32SHA* ctx)
ESP_LOGV(TAG, "enter esp_sha_hw_lock");
/* Init mutex */
if (ctx == NULL) {
ESP_LOGE(TAG, " esp_sha_try_hw_lock called with NULL ctx");
return -1;
}
/* Init mutex
*
* Note that even single thread mode may calculate hashes
* concurrently, so we still need to keep track of the
* engine being busy or not.
**/
#if defined(SINGLE_THREADED)
if(ctx->mode == ESP32_SHA_INIT) {
if(!InUse) {
ctx->mode = ESP32_SHA_HW;
InUse = 1;
} else {
}
else {
ctx->mode = ESP32_SHA_SW;
}
} else {
}
else {
/* this should not happens */
ESP_LOGE(TAG, "unexpected error in esp_sha_try_hw_lock.");
return -1;
}
#else
if(espsha_CryptHwMutexInit == 0){
#else /* not defined(SINGLE_THREADED) */
/*
* there's only one SHA engine for all the hash types
* so when any hash is in use, no others can use it.
* fall back to SW.
**/
/*
* here is some sample code to test the unrolling of sha enables:
*
periph_module_enable(PERIPH_SHA_MODULE);
ctx->lockDepth++;
periph_module_enable(PERIPH_SHA_MODULE);
ctx->lockDepth++;
ctx->mode = ESP32_FAIL_NEED_INIT;
*/
if (espsha_CryptHwMutexInit == 0) {
ESP_LOGV(TAG, "set esp_CryptHwMutexInit");
ret = esp_CryptHwMutexInit(&sha_mutex);
if(ret == 0) {
if (ret == 0) {
espsha_CryptHwMutexInit = 1;
} else {
ESP_LOGE(TAG, " mutex initialization failed.");
}
else {
ESP_LOGE(TAG, " mutex initialization failed. revert to software");
ctx->mode = ESP32_SHA_SW;
return 0;
/* espsha_CryptHwMutexInit is still zero */
return 0; /* success, just not using HW */
}
}
/* check if this sha has been operated as sw or hw, or not yet init */
if(ctx->mode == ESP32_SHA_INIT){
if (ctx->mode == ESP32_SHA_INIT) {
/* try to lock the hw engine */
if(esp_CryptHwMutexLock(&sha_mutex, (TickType_t)0) == 0) {
ctx->mode = ESP32_SHA_HW;
} else {
ESP_LOGI(TAG, "someone used. hw is locked.....");
ESP_LOGI(TAG, "the rest of operation will use sw implementation for this sha");
ctx->mode = ESP32_SHA_SW;
return 0;
ESP_LOGV(TAG, "ESP32_SHA_INIT\n");
/* we don't wait:
* either the engine is free, or we fall back to SW
*/
if (esp_CryptHwMutexLock(&sha_mutex, (TickType_t)0) == 0) {
/* check to see if we had a prior fail and need to unroll enables */
ret = esp_unroll_sha_module_enable(ctx);
ESP_LOGV(TAG, "Hardware Mode, lock depth = %d", ctx->lockDepth);
}
} else {
/* this should not happens */
else {
ESP_LOGI(TAG, ">>>> Hardware in use; Mode REVERT to ESP32_SHA_SW");
ctx->mode = ESP32_SHA_SW;
return 0; /* success, but revert to SW */
}
}
else {
/* this should not happen: called during mode != ESP32_SHA_INIT */
ESP_LOGE(TAG, "unexpected error in esp_sha_try_hw_lock.");
return -1;
}
#endif
/* Enable SHA hardware */
periph_module_enable(PERIPH_SHA_MODULE);
#endif /* not defined(SINGLE_THREADED) */
if (ret == 0) {
ctx->lockDepth++; /* depth for THIS ctx (there could be others!) */
periph_module_enable(PERIPH_SHA_MODULE);
ctx->mode = ESP32_SHA_HW;
}
else {
ESP_LOGI(TAG, ">>>> Other problem; Mode REVERT to ESP32_SHA_SW");
ctx->mode = ESP32_SHA_SW;
}
ESP_LOGV(TAG, "leave esp_sha_hw_lock");
return ret;
}
} /* esp_sha_try_hw_lock */
/*
* release hw engine
* release hw engine. when we don't have it locked, SHA module is DISABLED
*/
void esp_sha_hw_unlock( void )
int esp_sha_hw_unlock(WC_ESP32SHA* ctx)
{
ESP_LOGV(TAG, "enter esp_sha_hw_unlock");
/* Disable AES hardware */
periph_module_disable(PERIPH_SHA_MODULE);
#if defined(SINGLE_THREADED)
InUse = 0;
#else
/* unlock hw engine for next use */
esp_CryptHwMutexUnLock(&sha_mutex);
#endif
#if defined(SINGLE_THREADED)
InUse = 0;
#else
/* unlock hw engine for next use */
esp_CryptHwMutexUnLock(&sha_mutex);
#endif
/* we'll keep track of our lock depth.
* in case of unexpected results, all the periph_module_disable() calls
* and periph_module_disable() need to be unwound.
*
* see ref_counts[periph] in file: periph_ctrl.c */
if (ctx->lockDepth > 0) {
ctx->lockDepth--;
}
else {
ctx->lockDepth = 0;
}
ESP_LOGV(TAG, "leave esp_sha_hw_unlock");
}
return 0;
} /* esp_sha_hw_unlock */
/*
* start sha process by using hw engine
* start sha process by using hw engine.
* assumes register already loaded.
*/
static void esp_sha_start_process(WC_ESP32SHA* sha, word32 address)
static int esp_sha_start_process(WC_ESP32SHA* sha)
{
ESP_LOGV(TAG, "enter esp_sha_start_process");
int ret = 0;
if (sha == NULL) {
return -1;
}
ESP_LOGV(TAG, " enter esp_sha_start_process");
if(sha->isfirstblock){
/* start first message block */
DPORT_REG_WRITE(address, 1);
/* start registers for first message block
* we don't make any relational memory position assumptions.
*/
switch (sha->sha_type) {
case SHA1:
DPORT_REG_WRITE(SHA_1_START_REG, 1);
break;
case SHA2_256:
DPORT_REG_WRITE(SHA_256_START_REG, 1);
break;
#if defined(WOLFSSL_SHA384)
case SHA2_384:
DPORT_REG_WRITE(SHA_384_START_REG, 1);
break;
#endif
#if defined(WOLFSSL_SHA512)
case SHA2_512:
DPORT_REG_WRITE(SHA_512_START_REG, 1);
break;
#endif
default:
sha->mode = ESP32_SHA_FAIL_NEED_UNROLL;
ret = -1;
break;
}
sha->isfirstblock = 0;
} else {
/* CONTINU_REG */
DPORT_REG_WRITE(address + CONTINUE_REG_OFFSET , 1);
ESP_LOGV(TAG, " set sha->isfirstblock = 0");
#if defined(DEBUG_WOLFSSL)
this_block_num = 1; /* one-based counter, just for debug info */
#endif
}
else {
/* continue */
/* continue registers for next message block.
* we don't make any relational memory position assumptions
* for future chip architecture changes.
*/
switch (sha->sha_type) {
case SHA1:
DPORT_REG_WRITE(SHA_1_CONTINUE_REG, 1);
break;
case SHA2_256:
DPORT_REG_WRITE(SHA_256_CONTINUE_REG, 1);
break;
#if defined(WOLFSSL_SHA384)
case SHA2_384:
DPORT_REG_WRITE(SHA_384_CONTINUE_REG, 1);
break;
#endif
#if defined(WOLFSSL_SHA512)
case SHA2_512:
DPORT_REG_WRITE(SHA_512_CONTINUE_REG, 1);
break;
#endif
default:
/* error for unsupported other values */
sha->mode = ESP32_SHA_FAIL_NEED_UNROLL;
ret = -1;
break;
}
#if defined(DEBUG_WOLFSSL)
this_block_num++; /* one-based counter */
ESP_LOGV(TAG, " continue block #%d", this_block_num);
#endif
}
ESP_LOGV(TAG, "leave esp_sha_start_process");
ESP_LOGV(TAG, " leave esp_sha_start_process");
return ret;
}
/*
* process message block
*/
static void esp_process_block(WC_ESP32SHA* ctx, word32 address,
const word32* data, word32 len)
static void wc_esp_process_block(WC_ESP32SHA* ctx, /* see ctx->sha_type */
const word32* data,
word32 len)
{
int i;
ESP_LOGV(TAG, "enter esp_process_block");
int word32_to_save = (len) / (sizeof(word32));
ESP_LOGV(TAG, " enter esp_process_block");
if (word32_to_save > 0x31) {
word32_to_save = 0x31;
ESP_LOGE(TAG, " ERROR esp_process_block len exceeds 0x31 words");
}
/* check if there are any busy engine */
esp_wait_until_idle();
/* load message data into hw */
for(i=0;i<((len)/(sizeof(word32)));++i){
DPORT_REG_WRITE(SHA_TEXT_BASE+(i*sizeof(word32)),*(data+i));
wc_esp_wait_until_idle();
/* load [len] words of message data into hw */
for (i = 0; i < word32_to_save; i++) {
/* by using DPORT_REG_WRITE, we avoid the need
* to call __builtin_bswap32 to address endiness
*
* a useful watch array cast to watch at runtime:
* ((uint32_t[32]) (*(volatile uint32_t *)(SHA_TEXT_BASE)))
*
* Write value to DPORT register (does not require protecting)
*/
DPORT_REG_WRITE(SHA_TEXT_BASE + (i*sizeof(word32)), *(data + i));
/* memw confirmed auto inserted by compiler here */
}
/* notify hw to start process */
esp_sha_start_process(ctx, address);
ESP_LOGV(TAG, "leave esp_process_block");
/* notify hw to start process
* see ctx->sha_type
* reg data does not change until we are ready to read */
esp_sha_start_process(ctx);
ESP_LOGV(TAG, " leave esp_process_block");
}
/*
* retrieve sha digest from memory
*/
static void esp_digest_state(WC_ESP32SHA* ctx, byte* hash, enum SHA_TYPE sha_type)
{
/* registers */
word32 SHA_LOAD_REG = SHA_1_LOAD_REG;
word32 SHA_BUSY_REG = SHA_1_BUSY_REG;
/*
* retrieve sha digest from memory
*/
int wc_esp_digest_state(WC_ESP32SHA* ctx, byte* hash)
{
ESP_LOGV(TAG, "enter esp_digest_state");
/* sanity check */
if(sha_type == SHA_INVALID) {
ESP_LOGE(TAG, "unexpected error. sha_type is invalid.");
return;
if (ctx == NULL) {
return -1;
}
SHA_LOAD_REG += (sha_type << 4);
SHA_BUSY_REG += (sha_type << 4);
/* sanity check */
if (ctx->sha_type == SHA_INVALID) {
ctx->mode = ESP32_SHA_FAIL_NEED_UNROLL;
ESP_LOGE(TAG, "unexpected error. sha_type is invalid.");
return -1;
}
if(ctx->isfirstblock == 1){
/* no hardware use yet. Nothing to do yet */
return ;
if (ctx == NULL) {
return -1;
}
/* wait until idle */
esp_wait_until_idle();
wc_esp_wait_until_idle();
/* each sha_type register is at a different location */
switch (ctx->sha_type) {
case SHA1:
DPORT_REG_WRITE(SHA_1_LOAD_REG, 1);
break;
case SHA2_256:
DPORT_REG_WRITE(SHA_256_LOAD_REG, 1);
break;
#if defined(WOLFSSL_SHA384)
case SHA2_384:
SHA_LOAD_REG = SHA_384_LOAD_REG;
SHA_BUSY_REG = SHA_384_BUSY_REG;
break;
#endif
#if defined(WOLFSSL_SHA512)
case SHA2_512:
DPORT_REG_WRITE(SHA_512_LOAD_REG, 1);
break;
#endif
default:
ctx->mode = ESP32_SHA_FAIL_NEED_UNROLL;
return -1;
break;
}
if(ctx->isfirstblock == 1){
/* no hardware use yet. Nothing to do yet */
return 0;
}
/* LOAD final digest */
DPORT_REG_WRITE(SHA_LOAD_REG, 1);
/* wait until done */
while(DPORT_REG_READ(SHA_BUSY_REG) == 1){ }
esp_dport_access_read_buffer((word32*)(hash), SHA_TEXT_BASE,
esp_sha_digest_size(sha_type)/sizeof(word32));
wc_esp_wait_until_idle();
/* MEMW instructions before volatile memory references to guarantee
* sequential consistency. At least one MEMW should be executed in
* between every load or store to a volatile variable
*/
asm volatile("memw");
/* put result in hash variable.
*
* ALERT - hardware specific. See esp_hw_support\port\esp32\dport_access.c
*
* note we read 4-byte word32's here via DPORT_SEQUENCE_REG_READ
*
* example:
* DPORT_SEQUENCE_REG_READ(address + i * 4);
*/
esp_dport_access_read_buffer(
(word32*)(hash), /* the result will be found in hash upon exit */
SHA_TEXT_BASE, /* there's a fixed reg addy for all SHA */
wc_esp_sha_digest_size(ctx->sha_type) / sizeof(word32) /* # 4-byte */
);
#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
if(sha_type==SHA2_384||sha_type==SHA2_512) {
if (ctx->sha_type == SHA2_384 || ctx->sha_type == SHA2_512) {
word32 i;
word32* pwrd1 = (word32*)(hash);
/* swap value */
for(i = 0; i <WC_SHA512_DIGEST_SIZE/4; i+=2 ) {
pwrd1[i] ^= pwrd1[i+1];
pwrd1[i+1]^= pwrd1[i];
pwrd1[i] ^= pwrd1[i+1];
for (i = 0; i < WC_SHA512_DIGEST_SIZE / 4; i += 2) {
pwrd1[i] ^= pwrd1[i + 1];
pwrd1[i + 1] ^= pwrd1[i];
pwrd1[i] ^= pwrd1[i + 1];
}
}
#endif
ESP_LOGV(TAG, "leave esp_digest_state");
return 0;
}
#ifndef NO_SHA
@ -285,31 +583,26 @@ int esp_sha_process(struct wc_Sha* sha, const byte* data)
ESP_LOGV(TAG, "enter esp_sha_process");
word32 SHA_START_REG = SHA_1_START_REG;
esp_process_block(&sha->ctx, SHA_START_REG, (const word32*)data,
WC_SHA_BLOCK_SIZE);
wc_esp_process_block(&sha->ctx, (const word32*)data, WC_SHA_BLOCK_SIZE);
ESP_LOGV(TAG, "leave esp_sha_process");
return ret;
}
/*
* retrieve sha1 digest
*/
int esp_sha_digest_process(struct wc_Sha* sha, byte blockproc)
int esp_sha_digest_process(struct wc_Sha* sha, byte blockprocess)
{
int ret = 0;
ESP_LOGV(TAG, "enter esp_sha_digest_process");
if(blockproc) {
word32 SHA_START_REG = SHA_1_START_REG;
esp_process_block(&sha->ctx, SHA_START_REG, sha->buffer,
WC_SHA_BLOCK_SIZE);
if (blockprocess) {
wc_esp_process_block(&sha->ctx, sha->buffer, WC_SHA_BLOCK_SIZE);
}
esp_digest_state(&sha->ctx, (byte*)sha->digest, SHA1);
wc_esp_digest_state(&sha->ctx, (byte*)sha->digest);
ESP_LOGV(TAG, "leave esp_sha_digest_process");
@ -321,69 +614,79 @@ int esp_sha_digest_process(struct wc_Sha* sha, byte blockproc)
#ifndef NO_SHA256
/*
* sha256 process
*
* repeatedly call this for [N] blocks of [WC_SHA256_BLOCK_SIZE] bytes of data
*/
int esp_sha256_process(struct wc_Sha256* sha, const byte* data)
{
int ret = 0;
word32 SHA_START_REG = SHA_1_START_REG;
ESP_LOGV(TAG, "enter esp_sha256_process");
ESP_LOGV(TAG, " enter esp_sha256_process");
/* start register offset */
SHA_START_REG += (SHA2_256 << 4);
if ((&sha->ctx)->sha_type == SHA2_256) {
#if defined(DEBUG_WOLFSSL_VERBOSE)
ESP_LOGV(TAG, " confirmed sha type call match");
#endif
}
else {
ret = -1;
ESP_LOGE(TAG, " ERROR sha type call mismatch");
}
esp_process_block(&sha->ctx, SHA_START_REG, (const word32*)data,
WC_SHA256_BLOCK_SIZE);
wc_esp_process_block(&sha->ctx, (const word32*)data, WC_SHA256_BLOCK_SIZE);
ESP_LOGV(TAG, "leave esp_sha256_process");
ESP_LOGV(TAG, " leave esp_sha256_process");
return ret;
}
/*
* retrieve sha256 digest
*
* note that wc_Sha256Final() in sha256.c expects to need to reverse byte
* order, even though we could have returned them in the right order.
*/
int esp_sha256_digest_process(struct wc_Sha256* sha, byte blockproc)
int esp_sha256_digest_process(struct wc_Sha256* sha, byte blockprocess)
{
int ret = 0;
ESP_LOGV(TAG, "enter esp_sha256_digest_process");
if(blockproc) {
word32 SHA_START_REG = SHA_1_START_REG + (SHA2_256 << 4);
if(blockprocess) {
esp_process_block(&sha->ctx, SHA_START_REG, sha->buffer,
WC_SHA256_BLOCK_SIZE);
wc_esp_process_block(&sha->ctx, sha->buffer, WC_SHA256_BLOCK_SIZE);
}
esp_digest_state(&sha->ctx, (byte*)sha->digest, SHA2_256);
wc_esp_digest_state(&sha->ctx, (byte*)sha->digest);
ESP_LOGV(TAG, "leave esp_sha256_digest_process");
return ret;
}
#endif /* NO_SHA256 */
#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
/*
* sha512 proess. this is used for sha384 too.
* sha512 process. this is used for sha384 too.
*/
void esp_sha512_block(struct wc_Sha512* sha, const word32* data, byte isfinal)
{
enum SHA_TYPE sha_type = sha->ctx.sha_type;
word32 SHA_START_REG = SHA_1_START_REG;
ESP_LOGV(TAG, "enter esp_sha512_block");
/* start register offset */
SHA_START_REG += (sha_type << 4);
if(sha->ctx.mode == ESP32_SHA_SW){
ByteReverseWords64(sha->buffer, sha->buffer,
WC_SHA512_BLOCK_SIZE);
if(isfinal){
sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] = sha->hiLen;
sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] = sha->loLen;
if(isfinal) {
sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 2] =
sha->hiLen;
sha->buffer[WC_SHA512_BLOCK_SIZE / sizeof(word64) - 1] =
sha->loLen;
}
} else {
}
else {
ByteReverseWords((word32*)sha->buffer, (word32*)sha->buffer,
WC_SHA512_BLOCK_SIZE);
if(isfinal){
@ -393,7 +696,7 @@ void esp_sha512_block(struct wc_Sha512* sha, const word32* data, byte isfinal)
rotlFixed64(sha->loLen, 32U);
}
esp_process_block(&sha->ctx, SHA_START_REG, data, WC_SHA512_BLOCK_SIZE);
wc_esp_process_block(&sha->ctx, data, WC_SHA512_BLOCK_SIZE);
}
ESP_LOGV(TAG, "leave esp_sha512_block");
}
@ -424,7 +727,7 @@ int esp_sha512_digest_process(struct wc_Sha512* sha, byte blockproc)
esp_sha512_block(sha, data, 1);
}
if(sha->ctx.mode != ESP32_SHA_SW)
esp_digest_state(&sha->ctx, (byte*)sha->digest, sha->ctx.sha_type);
wc_esp_digest_state(&sha->ctx, (byte*)sha->digest);
ESP_LOGV(TAG, "leave esp_sha512_digest_process");
return 0;

View File

@ -1,6 +1,6 @@
/* esp32_util.c
*
* Copyright (C) 2006-2021 wolfSSL Inc.
* Copyright (C) 2006-2022 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@ -26,21 +26,57 @@
#include <wolfssl/wolfcrypt/wc_port.h>
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/logging.h>
/*
* initialize our mutex used to lock hardware access
*
* returns:
* 0 upon success,
* BAD_MUTEX_E for null mutex
* other value from wc_InitMutex()
*
*/
int esp_CryptHwMutexInit(wolfSSL_Mutex* mutex) {
if (mutex == NULL) {
return BAD_MUTEX_E;
}
return wc_InitMutex(mutex);
}
/*
* call the ESP-IDF mutex lock; xSemaphoreTake
*
*/
int esp_CryptHwMutexLock(wolfSSL_Mutex* mutex, TickType_t xBlockTime) {
if (mutex == NULL) {
WOLFSSL_ERROR_MSG("esp_CryptHwMutexLock called with null mutex");
return BAD_MUTEX_E;
}
#ifdef SINGLE_THREADED
return wc_LockMutex(mutex);
return wc_LockMutex(mutex); /* xSemaphoreTake take with portMAX_DELAY */
#else
return ((xSemaphoreTake( *mutex, xBlockTime ) == pdTRUE) ? 0 : BAD_MUTEX_E);
#endif
}
/*
* call the ESP-IDF mutex UNlock; xSemaphoreGive
*
*/
int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex) {
if (mutex == NULL) {
WOLFSSL_ERROR_MSG("esp_CryptHwMutexLock called with null mutex");
return BAD_MUTEX_E;
}
#ifdef SINGLE_THREADED
return wc_UnLockMutex(mutex);
#else
xSemaphoreGive(*mutex);
return 0;
#endif
}
#endif

View File

@ -1,6 +1,6 @@
/* sha.c
*
* Copyright (C) 2006-2021 wolfSSL Inc.
* Copyright (C) 2006-2022 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@ -311,14 +311,15 @@
sha->ctx.isfirstblock = 1;
sha->ctx.sha_type = SHA1;
if(sha->ctx.mode == ESP32_SHA_HW){
sha->ctx.lockDepth = 0;
/* release hw engine */
esp_sha_hw_unlock();
esp_sha_hw_unlock(&(sha->ctx));
}
/* always set mode as INIT
* whether using HW or SW is determined at first call of update()
*/
sha->ctx.mode = ESP32_SHA_INIT;
sha->ctx.lockDepth = 0;
return ret;
}
@ -538,6 +539,7 @@ int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId)
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
sha->ctx.mode = ESP32_SHA_INIT;
sha->ctx.isfirstblock = 1;
sha->ctx.lockDepth = 0; /* keep track of how many times lock is called */
#endif
ret = InitSha(sha);
if (ret != 0)
@ -616,7 +618,8 @@ int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
}
if (sha->ctx.mode == ESP32_SHA_SW) {
ret = XTRANSFORM(sha, (const byte*)local);
} else {
}
else {
esp_sha_process(sha, (const byte*)local);
}
#else
@ -670,7 +673,8 @@ int wc_ShaUpdate(wc_Sha* sha, const byte* data, word32 len)
}
if (sha->ctx.mode == ESP32_SHA_SW){
ret = XTRANSFORM(sha, (const byte*)local32);
} else {
}
else {
esp_sha_process(sha, (const byte*)local32);
}
#else
@ -753,7 +757,8 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash)
}
if (sha->ctx.mode == ESP32_SHA_SW) {
ret = XTRANSFORM(sha, (const byte*)local);
} else {
}
else {
ret = esp_sha_process(sha, (const byte*)local);
}
#else
@ -793,7 +798,8 @@ int wc_ShaFinal(wc_Sha* sha, byte* hash)
}
if (sha->ctx.mode == ESP32_SHA_SW) {
ret = XTRANSFORM(sha, (const byte*)local);
} else {
}
else {
ret = esp_sha_digest_process(sha, 1);
}
#else
@ -886,13 +892,16 @@ int wc_ShaGetHash(wc_Sha* sha, byte* hash)
if(sha->ctx.mode == ESP32_SHA_INIT){
esp_sha_try_hw_lock(&sha->ctx);
}
if(sha->ctx.mode != ESP32_SHA_SW)
if (sha->ctx.mode != ESP32_SHA_SW) {
/* TODO check SW/HW logic */
esp_sha_digest_process(sha, 0);
}
#endif
ret = wc_ShaCopy(sha, &tmpSha);
if (ret == 0) {
ret = wc_ShaFinal(&tmpSha, hash);
/* if HW failed, use SW */
ret = wc_ShaFinal(&tmpSha, hash);
#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
sha->ctx.mode = ESP32_SHA_SW;

View File

@ -1,6 +1,6 @@
/* sha256.c
*
* Copyright (C) 2006-2021 wolfSSL Inc.
* Copyright (C) 2006-2022 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@ -19,7 +19,12 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
*/
/* For more info on the algorithm, see https://tools.ietf.org/html/rfc6234 */
/* For more info on the algorithm, see https://tools.ietf.org/html/rfc6234
*
* For more information on NIST FIPS PUB 180-4, see
* https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
*/
/*
DESCRIPTION
@ -28,7 +33,11 @@ SHA-256 performs processing on message blocks to produce a final hash digest
output. It can be used to hash a message, M, having a length of L bits,
where 0 <= L < 2^64.
Note that in some cases, hardware acceleration may be enabled, depending
on the specific device platform.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
@ -74,6 +83,19 @@ where 0 <= L < 2^64.
#include <wolfssl/wolfcrypt/cryptocb.h>
#endif
/* determine if we are using Espressif SHA hardware acceleration */
#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
/* define a single keyword for simplicity & readability
*
* by default the HW acceleration is on for ESP32-WROOM32
* but individual components can be turned off.
*/
#define WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW
#else
#undef USE_ESP32WROOM32_CRYPT_HASH
#endif
/* fips wrapper calls, user can call direct */
#if defined(HAVE_FIPS) && \
(!defined(HAVE_FIPS_VERSION) || (HAVE_FIPS_VERSION < 2))
@ -694,14 +716,17 @@ static int InitSha256(wc_Sha256* sha256)
return ret;
}
#elif defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
#elif defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
/* HW may fail since there's only one, so we still need SW */
#define NEED_SOFT_SHA256
/*
* soft SHA needs initialization digest, but HW does not.
*/
static int InitSha256(wc_Sha256* sha256)
{
int ret = 0;
int ret = 0; /* zero = success */
if (sha256 == NULL)
return BAD_FUNC_ARG;
@ -725,8 +750,9 @@ static int InitSha256(wc_Sha256* sha256)
sha256->ctx.sha_type = SHA2_256;
if(sha256->ctx.mode == ESP32_SHA_HW) {
/* release hw */
esp_sha_hw_unlock();
esp_sha_hw_unlock(&(sha256->ctx));
}
/* always set mode as INIT
* whether using HW or SW is determined at first call of update()
*/
@ -734,9 +760,13 @@ static int InitSha256(wc_Sha256* sha256)
return ret;
}
/*
* wolfCrypt InitSha256 external wrapper
*/
int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
{
int ret = 0;
int ret = 0; /* zero = success */
if (sha256 == NULL)
return BAD_FUNC_ARG;
@ -744,6 +774,7 @@ static int InitSha256(wc_Sha256* sha256)
XMEMSET(sha256, 0, sizeof(wc_Sha256));
sha256->ctx.mode = ESP32_SHA_INIT;
sha256->ctx.isfirstblock = 1;
sha256->ctx.lockDepth = 0; /* we'll keep track of our own lock depth */
(void)devId;
ret = InitSha256(sha256);
@ -786,7 +817,6 @@ static int InitSha256(wc_Sha256* sha256)
int ret = 0;
if (sha256 == NULL)
return BAD_FUNC_ARG;
ret = InitSha256(sha256);
if (ret != 0)
return ret;
@ -1052,14 +1082,16 @@ static int InitSha256(wc_Sha256* sha256)
}
#endif
#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
if (sha256->ctx.mode == ESP32_SHA_INIT){
#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
if (sha256->ctx.mode == ESP32_SHA_INIT ||
sha256->ctx.mode == ESP32_SHA_FAIL_NEED_UNROLL) {
esp_sha_try_hw_lock(&sha256->ctx);
}
if (sha256->ctx.mode == ESP32_SHA_SW){
if (sha256->ctx.mode == ESP32_SHA_SW) {
ret = XTRANSFORM(sha256, (const byte*)local);
} else {
}
else {
esp_sha256_process(sha256, (const byte*)local);
}
#else
@ -1129,17 +1161,17 @@ static int InitSha256(wc_Sha256* sha256)
}
#endif
#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
if (sha256->ctx.mode == ESP32_SHA_INIT){
esp_sha_try_hw_lock(&sha256->ctx);
}
if (sha256->ctx.mode == ESP32_SHA_SW){
if (sha256->ctx.mode == ESP32_SHA_SW) {
ret = XTRANSFORM(sha256, (const byte*)local32);
} else {
}
else {
esp_sha256_process(sha256, (const byte*)local32);
}
#else
#else
ret = XTRANSFORM(sha256, (const byte*)local32);
#endif
@ -1223,14 +1255,14 @@ static int InitSha256(wc_Sha256* sha256)
}
#endif
#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
if (sha256->ctx.mode == ESP32_SHA_INIT) {
esp_sha_try_hw_lock(&sha256->ctx);
}
if (sha256->ctx.mode == ESP32_SHA_SW) {
ret = XTRANSFORM(sha256, (const byte*)local);
} else {
}
else {
ret = esp_sha256_process(sha256, (const byte*)local);
}
#else
@ -1280,14 +1312,14 @@ static int InitSha256(wc_Sha256* sha256)
}
#endif
#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
if (sha256->ctx.mode == ESP32_SHA_INIT) {
esp_sha_try_hw_lock(&sha256->ctx);
}
if (sha256->ctx.mode == ESP32_SHA_SW) {
ret = XTRANSFORM(sha256, (const byte*)local);
} else {
}
else {
ret = esp_sha256_digest_process(sha256, 1);
}
#else
@ -1385,7 +1417,6 @@ static int InitSha256(wc_Sha256* sha256)
{
if (sha224 == NULL)
return BAD_FUNC_ARG;
(void)devId;
(void)heap;
@ -1848,9 +1879,15 @@ int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash)
if (sha256 == NULL || hash == NULL)
return BAD_FUNC_ARG;
#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
if(sha256->ctx.mode == ESP32_SHA_INIT){
#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
/* ESP32 hardware can only handle only 1 active hardware hashing
* at a time. If the mutex lock is acquired the first time then
* that Sha256 instance has exclusive access to hardware. The
* final or free needs to release the mutex. Operations that
* do not get the lock fallback to software based Sha256 */
if(sha256->ctx.mode == ESP32_SHA_INIT){
esp_sha_try_hw_lock(&sha256->ctx);
}
if(sha256->ctx.mode == ESP32_SHA_HW)
@ -1861,13 +1898,20 @@ int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash)
ret = wc_Sha256Copy(sha256, &tmpSha256);
if (ret == 0) {
ret = wc_Sha256Final(&tmpSha256, hash);
#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
{
sha256->ctx.mode = ESP32_SHA_SW;
}
#endif
wc_Sha256Free(&tmpSha256);
}
#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
/* TODO: Make sure the ESP32 crypto mutex is released (in case final is not
* called */
#endif
return ret;
}
int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
@ -1893,12 +1937,14 @@ int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
#ifdef WOLFSSL_PIC32MZ_HASH
ret = wc_Pic32HashCopy(&src->cache, &dst->cache);
#endif
#if defined(WOLFSSL_ESP32WROOM32_CRYPT) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
dst->ctx.mode = src->ctx.mode;
dst->ctx.isfirstblock = src->ctx.isfirstblock;
dst->ctx.sha_type = src->ctx.sha_type;
#if defined(WOLFSSL_USE_ESP32WROOM32_CRYPT_HASH_HW)
dst->ctx.mode = src->ctx.mode;
dst->ctx.isfirstblock = src->ctx.isfirstblock;
dst->ctx.sha_type = src->ctx.sha_type;
dst->ctx.lockDepth = src->ctx.lockDepth;
#endif
#ifdef WOLFSSL_HASH_FLAGS
dst->flags |= WC_HASH_FLAG_ISCOPY;
#endif

View File

@ -285,7 +285,7 @@ static int InitSha512(wc_Sha512* sha512)
sha512->ctx.isfirstblock = 1;
if(sha512->ctx.mode == ESP32_SHA_HW) {
/* release hw */
esp_sha_hw_unlock();
esp_sha_hw_unlock(&(sha512->ctx));
}
/* always set mode as INIT
* whether using HW or SW is determined at first call of update()
@ -332,7 +332,7 @@ static int InitSha512_224(wc_Sha512* sha512)
sha512->ctx.isfirstblock = 1;
if(sha512->ctx.mode == ESP32_SHA_HW) {
/* release hw */
esp_sha_hw_unlock();
esp_sha_hw_unlock(&(sha512->ctx));
}
/* always set mode as INIT
* whether using HW or SW is determined at first call of update()
@ -381,7 +381,7 @@ static int InitSha512_256(wc_Sha512* sha512)
sha512->ctx.isfirstblock = 1;
if(sha512->ctx.mode == ESP32_SHA_HW) {
/* release hw */
esp_sha_hw_unlock();
esp_sha_hw_unlock(&(sha512->ctx));
}
/* always set mode as INIT
* whether using HW or SW is determined at first call of update()
@ -1310,7 +1310,7 @@ static int InitSha384(wc_Sha384* sha384)
sha384->ctx.isfirstblock = 1;
if(sha384->ctx.mode == ESP32_SHA_HW) {
/* release hw */
esp_sha_hw_unlock();
esp_sha_hw_unlock(&(sha512->ctx));
}
/* always set mode as INIT
* whether using HW or SW is determined at first call of update()

View File

@ -22,39 +22,44 @@
#define __ESP32_CRYPT_H__
#ifdef WOLFSSL_USER_SETTINGS
#include "user_settings.h"
#endif
#include "esp_idf_version.h"
#include "esp_types.h"
#include "esp_log.h"
#ifdef WOLFSSL_ESP32WROOM32_CRYPT_DEBUG
#undef LOG_LOCAL_LEVEL
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#undef LOG_LOCAL_LEVEL
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#else
#undef LOG_LOCAL_LEVEL
#define LOG_LOCAL_LEVEL ESP_LOG_ERROR
#undef LOG_LOCAL_LEVEL
#define LOG_LOCAL_LEVEL ESP_LOG_DEBUG
#endif
#include <freertos/FreeRTOS.h>
#include "soc/dport_reg.h"
#include "soc/hwcrypto_reg.h"
#if ESP_IDF_VERSION_MAJOR < 5
#include "soc/cpu.h"
#include "soc/cpu.h"
#endif
#if ESP_IDF_VERSION_MAJOR >= 5
#include "esp_private/periph_ctrl.h"
#include "esp_private/periph_ctrl.h"
#else
#include "driver/periph_ctrl.h"
#include "driver/periph_ctrl.h"
#endif
#if ESP_IDF_VERSION_MAJOR >= 4
#include <esp32/rom/ets_sys.h>
#include <esp32/rom/ets_sys.h>
#else
#include <rom/ets_sys.h>
#include <rom/ets_sys.h>
#endif
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif
int esp_CryptHwMutexInit(wolfSSL_Mutex* mutex);
@ -63,31 +68,31 @@ int esp_CryptHwMutexUnLock(wolfSSL_Mutex* mutex);
#ifndef NO_AES
#if ESP_IDF_VERSION_MAJOR >= 4
#include "esp32/rom/aes.h"
#else
#include "rom/aes.h"
#endif
#if ESP_IDF_VERSION_MAJOR >= 4
#include "esp32/rom/aes.h"
#else
#include "rom/aes.h"
#endif
typedef enum tagES32_AES_PROCESS {
ESP32_AES_LOCKHW = 1,
ESP32_AES_UPDATEKEY_ENCRYPT = 2,
ESP32_AES_UPDATEKEY_DECRYPT = 3,
ESP32_AES_UNLOCKHW = 4
} ESP32_AESPROCESS;
typedef enum tagES32_AES_PROCESS {
ESP32_AES_LOCKHW = 1,
ESP32_AES_UPDATEKEY_ENCRYPT = 2,
ESP32_AES_UPDATEKEY_DECRYPT = 3,
ESP32_AES_UNLOCKHW = 4
} ESP32_AESPROCESS;
struct Aes;
int wc_esp32AesCbcEncrypt(struct Aes* aes, byte* out, const byte* in, word32 sz);
int wc_esp32AesCbcDecrypt(struct Aes* aes, byte* out, const byte* in, word32 sz);
int wc_esp32AesEncrypt(struct Aes *aes, const byte* in, byte* out);
int wc_esp32AesDecrypt(struct Aes *aes, const byte* in, byte* out);
struct Aes; /* see aes.h */
int wc_esp32AesCbcEncrypt(struct Aes* aes, byte* out, const byte* in, word32 sz);
int wc_esp32AesCbcDecrypt(struct Aes* aes, byte* out, const byte* in, word32 sz);
int wc_esp32AesEncrypt(struct Aes *aes, const byte* in, byte* out);
int wc_esp32AesDecrypt(struct Aes *aes, const byte* in, byte* out);
#endif
#ifdef WOLFSSL_ESP32WROOM32_CRYPT_DEBUG
void wc_esp32TimerStart();
uint64_t wc_esp32elapsedTime();
void wc_esp32TimerStart();
uint64_t wc_esp32elapsedTime();
#endif /* WOLFSSL_ESP32WROOM32_CRYPT_DEBUG */
@ -95,66 +100,107 @@ uint64_t wc_esp32elapsedTime();
defined(WOLFSSL_SHA512)) && \
!defined(NO_WOLFSSL_ESP32WROOM32_CRYPT_HASH)
/* RAW hash function APIs are not implemented with esp32 hardware acceleration*/
#define WOLFSSL_NO_HASH_RAW
#define SHA_CTX ETS_SHAContext
#if ESP_IDF_VERSION_MAJOR >= 4
#include "esp32/rom/sha.h"
#else
#include "rom/sha.h"
#endif
#undef SHA_CTX
/* RAW hash function APIs are not implemented with esp32 hardware acceleration*/
#define WOLFSSL_NO_HASH_RAW
#define SHA_CTX ETS_SHAContext
typedef enum {
ESP32_SHA_INIT = 0,
ESP32_SHA_HW = 1,
ESP32_SHA_SW = 2,
} ESP32_DOSHA;
#if ESP_IDF_VERSION_MAJOR >= 4
#include "esp32/rom/sha.h"
#else
#include "rom/sha.h"
#endif
typedef struct {
byte isfirstblock;
/* 0 , 1 hard, 2 soft */
byte mode;
/* sha_type */
enum SHA_TYPE sha_type;
} WC_ESP32SHA;
#undef SHA_CTX
int esp_sha_try_hw_lock(WC_ESP32SHA* ctx);
void esp_sha_hw_unlock( void );
typedef enum {
ESP32_SHA_INIT = 0,
ESP32_SHA_HW = 1,
ESP32_SHA_SW = 2,
ESP32_SHA_FAIL_NEED_UNROLL = -1
} ESP32_MODE;
struct wc_Sha;
int esp_sha_digest_process(struct wc_Sha* sha, byte bockprocess);
int esp_sha_process(struct wc_Sha* sha, const byte* data);
typedef struct {
byte isfirstblock;
#ifndef NO_SHA256
struct wc_Sha256;
int esp_sha256_digest_process(struct wc_Sha256* sha, byte bockprocess);
int esp_sha256_process(struct wc_Sha256* sha, const byte* data);
#endif
ESP32_MODE mode; /* typically 0 init, 1 HW, 2 SW */
#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
struct wc_Sha512;
int esp_sha512_process(struct wc_Sha512* sha);
int esp_sha512_digest_process(struct wc_Sha512* sha, byte blockproc);
#endif
/* we'll keep track of our own locks.
* actual enable/disable only occurs for ref_counts[periph] == 0 */
int lockDepth; /* see ref_counts[periph] in periph_ctrl.c */
enum SHA_TYPE sha_type;
} WC_ESP32SHA;
int esp_sha_try_hw_lock(WC_ESP32SHA* ctx);
int esp_sha_hw_unlock(WC_ESP32SHA* ctx);
struct wc_Sha;
int esp_sha_digest_process(struct wc_Sha* sha, byte blockprocess);
int esp_sha_process(struct wc_Sha* sha, const byte* data);
#ifndef NO_SHA256
struct wc_Sha256;
int esp_sha256_digest_process(struct wc_Sha256* sha, byte blockprocess);
int esp_sha256_process(struct wc_Sha256* sha, const byte* data);
int esp32_Transform_Sha256_demo(struct wc_Sha256* sha256, const byte* data);
#endif
/* TODO do we really call esp_sha512_process for WOLFSSL_SHA384 ? */
#if defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
struct wc_Sha512;
int esp_sha512_process(struct wc_Sha512* sha);
int esp_sha512_digest_process(struct wc_Sha512* sha, byte blockproc);
#endif
#endif /* NO_SHA && */
#if !defined(NO_RSA) || defined(HAVE_ECC)
#if !defined(ESP_RSA_TIMEOUT_CNT)
#define ESP_RSA_TIMEOUT_CNT 0x249F00
#endif
#if !defined(ESP_RSA_TIMEOUT_CNT)
#define ESP_RSA_TIMEOUT_CNT 0x249F00
#endif
struct fp_int;
int esp_mp_mul(struct fp_int* X, struct fp_int* Y, struct fp_int* Z);
int esp_mp_exptmod(struct fp_int* G, struct fp_int* X, word32 Xbits, struct fp_int* P,
struct fp_int* Y);
int esp_mp_mulmod(struct fp_int* X, struct fp_int* Y, struct fp_int* M,
struct fp_int* Z);
/* operands can be up to 4096 bits long.
* here we store the bits in wolfSSL fp_int struct.
* see wolfCrypt tfm.h
*/
struct fp_int;
/*
* The parameter names in the Espressif implementation are arbitrary.
*
* The wolfSSL names come from DH: Y=G^x mod M (see wolfcrypt/tfm.h)
*
* G=base, X is the private exponent, Y is the public value w
**/
/* Z = (X ^ Y) mod M : Espressif generic notation */
/* Y = (G ^ X) mod P : wolfSSL DH reference notation */
int esp_mp_exptmod(struct fp_int* X, /* G */
struct fp_int* Y, /* X */
word32 Xbits, /* Ys typically = fp_count_bits (X) */
struct fp_int* M, /* P */
struct fp_int* Z); /* Y */
/* Z = X * Y */
int esp_mp_mul(struct fp_int* X,
struct fp_int* Y,
struct fp_int* Z);
/* Z = X * Y (mod M) */
int esp_mp_mulmod(struct fp_int* X,
struct fp_int* Y,
struct fp_int* M,
struct fp_int* Z);
#endif /* NO_RSA || HAVE_ECC*/
/* end c++ wrapper */
#ifdef __cplusplus
}
#endif

View File

@ -1,6 +1,6 @@
/* types.h
*
* Copyright (C) 2006-2021 wolfSSL Inc.
* Copyright (C) 2006-2022 wolfSSL Inc.
*
* This file is part of wolfSSL.
*
@ -714,7 +714,7 @@ typedef struct w64wrapper {
/* In cases when truncation is expected the caller needs*/
/* to check the return value from the function so that */
/* compiler doesn't complain. */
/* xtensa-esp32-elf v8.2.0 warns trancation at */
/* xtensa-esp32-elf v8.2.0 warns truncation at */
/* GetAsnTimeString() */
static WC_INLINE
int _xsnprintf_(char *s, size_t n, const char *format, ...)