crypto: SHA and AES accelerator bring up for S2

Brings up, fixes and enables AES and SHA hardware acceleration.

Closes IDF-714
Closes IDF-716
This commit is contained in:
Marius Vikhammer 2020-01-16 14:31:10 +08:00
parent 59381b60c0
commit 37369a8a57
32 changed files with 3687 additions and 1550 deletions

View file

@ -74,14 +74,15 @@ target_sources(mbedtls PRIVATE "${COMPONENT_DIR}/port/mbedtls_debug.c"
target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/esp_hardware.c" target_sources(mbedcrypto PRIVATE "${COMPONENT_DIR}/port/esp_hardware.c"
"${COMPONENT_DIR}/port/esp_mem.c" "${COMPONENT_DIR}/port/esp_mem.c"
"${COMPONENT_DIR}/port/esp_sha.c"
"${COMPONENT_DIR}/port/esp_sha1.c"
"${COMPONENT_DIR}/port/esp_sha256.c"
"${COMPONENT_DIR}/port/esp_sha512.c"
"${COMPONENT_DIR}/port/esp_timing.c" "${COMPONENT_DIR}/port/esp_timing.c"
"${COMPONENT_DIR}/port/esp_sha.c"
"${COMPONENT_DIR}/port/esp_aes_xts.c"
"${COMPONENT_DIR}/port/${idf_target}/esp_bignum.c" "${COMPONENT_DIR}/port/${idf_target}/esp_bignum.c"
"${COMPONENT_DIR}/port/${idf_target}/aes.c" "${COMPONENT_DIR}/port/${idf_target}/aes.c"
"${COMPONENT_DIR}/port/${idf_target}/sha.c") "${COMPONENT_DIR}/port/${idf_target}/sha.c"
"${COMPONENT_DIR}/port/${idf_target}/esp_sha1.c"
"${COMPONENT_DIR}/port/${idf_target}/esp_sha256.c"
"${COMPONENT_DIR}/port/${idf_target}/esp_sha512.c")
foreach(target ${mbedtls_targets}) foreach(target ${mbedtls_targets})
target_compile_definitions(${target} PUBLIC -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h") target_compile_definitions(${target} PUBLIC -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h")

View file

@ -189,13 +189,33 @@ menu "mbedTLS"
config MBEDTLS_HARDWARE_AES config MBEDTLS_HARDWARE_AES
bool "Enable hardware AES acceleration" bool "Enable hardware AES acceleration"
default y default y
depends on !IDF_TARGET_ESP32S2
help help
Enable hardware accelerated AES encryption & decryption. Enable hardware accelerated AES encryption & decryption.
Note that if the ESP32 CPU is running at 240MHz, hardware AES does not Note that if the ESP32 CPU is running at 240MHz, hardware AES does not
offer any speed boost over software AES. offer any speed boost over software AES.
config MBEDTLS_AES_USE_INTERRUPT
bool "Use interrupt for long AES operations"
depends on MBEDTLS_HARDWARE_AES
default y
help
Use an interrupt to coordinate long AES operations.
This allows other code to run on the CPU while an AES operation is pending.
Otherwise the CPU busy-waits.
config MBEDTLS_HARDWARE_GCM
bool "Enable partially hardware accelerated GCM"
#depends on IDF_TARGET_ESP32S2 && MBEDTLS_HARDWARE_AES
depends on 0
default n
help
Enable partially hardware accelerated GCM.
Due to hardware limitations, hardware acceleration currently does not
offer any speed boost over software GCM with hardware accelerated AES operations.
config MBEDTLS_HARDWARE_MPI config MBEDTLS_HARDWARE_MPI
bool "Enable hardware MPI (bignum) acceleration" bool "Enable hardware MPI (bignum) acceleration"
default y default y
@ -211,11 +231,10 @@ menu "mbedTLS"
config MBEDTLS_HARDWARE_SHA config MBEDTLS_HARDWARE_SHA
bool "Enable hardware SHA acceleration" bool "Enable hardware SHA acceleration"
default y default y
depends on !IDF_TARGET_ESP32S2
help help
Enable hardware accelerated SHA1, SHA256, SHA384 & SHA512 in mbedTLS. Enable hardware accelerated SHA1, SHA256, SHA384 & SHA512 in mbedTLS.
Due to a hardware limitation, hardware acceleration is only Due to a hardware limitation, on the ESP32 hardware acceleration is only
guaranteed if SHA digests are calculated one at a time. If more guaranteed if SHA digests are calculated one at a time. If more
than one SHA digest is calculated at the same time, one will than one SHA digest is calculated at the same time, one will
be calculated fully in hardware and the rest will be calculated be calculated fully in hardware and the rest will be calculated

View file

@ -509,246 +509,3 @@ int esp_aes_crypt_ofb( esp_aes_context *ctx,
return( ret ); return( ret );
} }
/* Below XTS implementation is copied aes.c of mbedtls library.
* When MBEDTLS_AES_ALT is defined mbedtls expects alternate
* definition of XTS functions to be available. Even if this
* could have been avoided, it is done for consistency reason.
*/
void esp_aes_xts_init( esp_aes_xts_context *ctx )
{
esp_aes_init( &ctx->crypt );
esp_aes_init( &ctx->tweak );
}
void esp_aes_xts_free( esp_aes_xts_context *ctx )
{
esp_aes_free( &ctx->crypt );
esp_aes_free( &ctx->tweak );
}
static int esp_aes_xts_decode_keys( const unsigned char *key,
unsigned int keybits,
const unsigned char **key1,
unsigned int *key1bits,
const unsigned char **key2,
unsigned int *key2bits )
{
const unsigned int half_keybits = keybits / 2;
const unsigned int half_keybytes = half_keybits / 8;
switch( keybits )
{
case 256: break;
case 512: break;
default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
}
*key1bits = half_keybits;
*key2bits = half_keybits;
*key1 = &key[0];
*key2 = &key[half_keybytes];
return 0;
}
int esp_aes_xts_setkey_enc( esp_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits)
{
int ret;
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
ret = esp_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
&key2, &key2bits );
if( ret != 0 )
return( ret );
/* Set the tweak key. Always set tweak key for the encryption mode. */
ret = esp_aes_setkey( &ctx->tweak, key2, key2bits );
if( ret != 0 )
return( ret );
/* Set crypt key for encryption. */
return esp_aes_setkey( &ctx->crypt, key1, key1bits );
}
int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits)
{
int ret;
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
ret = esp_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
&key2, &key2bits );
if( ret != 0 )
return( ret );
/* Set the tweak key. Always set tweak key for encryption. */
ret = esp_aes_setkey( &ctx->tweak, key2, key2bits );
if( ret != 0 )
return( ret );
/* Set crypt key for decryption. */
return esp_aes_setkey( &ctx->crypt, key1, key1bits );
}
/* Endianess with 64 bits values */
#ifndef GET_UINT64_LE
#define GET_UINT64_LE(n,b,i) \
{ \
(n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \
| ( (uint64_t) (b)[(i) + 6] << 48 ) \
| ( (uint64_t) (b)[(i) + 5] << 40 ) \
| ( (uint64_t) (b)[(i) + 4] << 32 ) \
| ( (uint64_t) (b)[(i) + 3] << 24 ) \
| ( (uint64_t) (b)[(i) + 2] << 16 ) \
| ( (uint64_t) (b)[(i) + 1] << 8 ) \
| ( (uint64_t) (b)[(i) ] ); \
}
#endif
#ifndef PUT_UINT64_LE
#define PUT_UINT64_LE(n,b,i) \
{ \
(b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \
(b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \
(b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \
(b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) ] = (unsigned char) ( (n) ); \
}
#endif
typedef unsigned char esp_be128[16];
/*
* GF(2^128) multiplication function
*
* This function multiplies a field element by x in the polynomial field
* representation. It uses 64-bit word operations to gain speed but compensates
* for machine endianess and hence works correctly on both big and little
* endian machines.
*/
static void esp_gf128mul_x_ble( unsigned char r[16],
const unsigned char x[16] )
{
uint64_t a, b, ra, rb;
GET_UINT64_LE( a, x, 0 );
GET_UINT64_LE( b, x, 8 );
ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) );
rb = ( a >> 63 ) | ( b << 1 );
PUT_UINT64_LE( ra, r, 0 );
PUT_UINT64_LE( rb, r, 8 );
}
/*
* AES-XTS buffer encryption/decryption
*/
int esp_aes_crypt_xts( esp_aes_xts_context *ctx,
int mode,
size_t length,
const unsigned char data_unit[16],
const unsigned char *input,
unsigned char *output )
{
int ret;
size_t blocks = length / 16;
size_t leftover = length % 16;
unsigned char tweak[16];
unsigned char prev_tweak[16];
unsigned char tmp[16];
/* Sectors must be at least 16 bytes. */
if( length < 16 )
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
/* NIST SP 80-38E disallows data units larger than 2**20 blocks. */
if( length > ( 1 << 20 ) * 16 )
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
/* Compute the tweak. */
ret = esp_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT,
data_unit, tweak );
if( ret != 0 )
return( ret );
while( blocks-- )
{
size_t i;
if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 )
{
/* We are on the last block in a decrypt operation that has
* leftover bytes, so we need to use the next tweak for this block,
* and this tweak for the lefover bytes. Save the current tweak for
* the leftovers and then update the current tweak for use on this,
* the last full block. */
memcpy( prev_tweak, tweak, sizeof( tweak ) );
esp_gf128mul_x_ble( tweak, tweak );
}
for( i = 0; i < 16; i++ )
tmp[i] = input[i] ^ tweak[i];
ret = esp_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
if( ret != 0 )
return( ret );
for( i = 0; i < 16; i++ )
output[i] = tmp[i] ^ tweak[i];
/* Update the tweak for the next block. */
esp_gf128mul_x_ble( tweak, tweak );
output += 16;
input += 16;
}
if( leftover )
{
/* If we are on the leftover bytes in a decrypt operation, we need to
* use the previous tweak for these bytes (as saved in prev_tweak). */
unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak;
/* We are now on the final part of the data unit, which doesn't divide
* evenly by 16. It's time for ciphertext stealing. */
size_t i;
unsigned char *prev_output = output - 16;
/* Copy ciphertext bytes from the previous block to our output for each
* byte of cyphertext we won't steal. At the same time, copy the
* remainder of the input for this final round (since the loop bounds
* are the same). */
for( i = 0; i < leftover; i++ )
{
output[i] = prev_output[i];
tmp[i] = input[i] ^ t[i];
}
/* Copy ciphertext bytes from the previous block for input in this
* round. */
for( ; i < 16; i++ )
tmp[i] = prev_output[i] ^ t[i];
ret = esp_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
if( ret != 0 )
return ret;
/* Write the result back to the previous block, overriding the previous
* output we copied. */
for( i = 0; i < 16; i++ )
prev_output[i] = tmp[i] ^ t[i];
}
return( 0 );
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,255 @@
/*
* SHA-1 implementation with hardware ESP32 support added.
* Uses mbedTLS software implementation for failover when concurrent
* SHA operations are in use.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016-2020, Espressif Systems (Shanghai) PTE LTD
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/*
* The SHA-1 standard was published by NIST in 1993.
*
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA1_C) && defined(MBEDTLS_SHA1_ALT)
#include "mbedtls/sha1.h"
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#include "esp32s2/sha.h"
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n )
{
volatile unsigned char *p = (unsigned char *)v; while ( n-- ) *p++ = 0;
}
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
}
#endif
void mbedtls_sha1_init( mbedtls_sha1_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_sha1_context ) );
}
void mbedtls_sha1_free( mbedtls_sha1_context *ctx )
{
if ( ctx == NULL ) {
return;
}
mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) );
}
void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
const mbedtls_sha1_context *src )
{
memcpy(dst, src, sizeof(mbedtls_sha1_context));
}
/*
* SHA-1 context setup
*/
int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx )
{
ctx->total[0] = 0;
ctx->total[1] = 0;
memset( ctx, 0, sizeof( mbedtls_sha1_context ) );
ctx->mode = SHA1;
return 0;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha1_starts( mbedtls_sha1_context *ctx )
{
mbedtls_sha1_starts_ret( ctx );
}
#endif
static int esp_internal_sha1_dma_process(mbedtls_sha1_context *ctx,
const uint8_t *data, size_t len,
uint8_t *buf, size_t buf_len)
{
return esp_sha_dma(SHA1, data, len, buf, buf_len, ctx->first_block);
}
int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] )
{
int ret;
esp_sha_acquire_hardware();
ret = esp_sha_dma(ctx->mode, data, 64, 0, 0, ctx->first_block);
esp_sha_release_hardware();
return ret;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha1_process( mbedtls_sha1_context *ctx,
const unsigned char data[64] )
{
mbedtls_internal_sha1_process( ctx, data );
}
#endif
int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen )
{
int ret;
size_t fill;
uint32_t left, len, local_len = 0;
if ( !ilen || (input == NULL)) {
return 0;
}
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if ( ctx->total[0] < (uint32_t) ilen ) {
ctx->total[1]++;
}
if ( left && ilen >= fill ) {
memcpy( (void *) (ctx->buffer + left), input, fill );
input += fill;
ilen -= fill;
left = 0;
local_len = 64;
}
len = (ilen / 64) * 64;
if ( len || local_len) {
esp_sha_acquire_hardware();
if (ctx->sha_state == ESP_SHA1_STATE_INIT) {
ctx->first_block = true;
ctx->sha_state = ESP_SHA1_STATE_IN_PROCESS;
} else if (ctx->sha_state == ESP_SHA1_STATE_IN_PROCESS) {
ctx->first_block = false;
esp_sha_write_digest_state(SHA1, ctx->state);
}
ret = esp_internal_sha1_dma_process(ctx, input, len, ctx->buffer, local_len);
esp_sha_read_digest_state(SHA1, ctx->state);
esp_sha_release_hardware();
if (ret != 0) {
return ret;
}
}
if ( ilen > 0 ) {
memcpy( (void *) (ctx->buffer + left), input + len, ilen - len );
}
return 0;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha1_update( mbedtls_sha1_context *ctx,
const unsigned char *input,
size_t ilen )
{
mbedtls_sha1_update_ret( ctx, input, ilen );
}
#endif
static const unsigned char sha1_padding[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-1 final digest
*/
int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, unsigned char output[20] )
{
int ret;
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
if ( ( ret = mbedtls_sha1_update_ret( ctx, sha1_padding, padn ) ) != 0 ) {
return ret;
}
if ( ( ret = mbedtls_sha1_update_ret( ctx, msglen, 8 ) ) != 0 ) {
return ret;
}
memcpy(output, ctx->state, 20);
return ret;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx,
unsigned char output[20] )
{
mbedtls_sha1_finish_ret( ctx, output );
}
#endif
#endif /* MBEDTLS_SHA1_C && MBEDTLS_SHA1_ALT */

View file

@ -0,0 +1,267 @@
/*
* SHA-256 implementation with hardware ESP32 support added.
* Uses mbedTLS software implementation for failover when concurrent
* SHA operations are in use.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016-2020, Espressif Systems (Shanghai) PTE LTD
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/*
* The SHA-256 Secure Hash Standard was published by NIST in 2002.
*
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA256_C) && defined(MBEDTLS_SHA256_ALT)
#include "mbedtls/sha256.h"
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#include "esp32s2/sha.h"
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n )
{
volatile unsigned char *p = v; while ( n-- ) *p++ = 0;
}
/*
* 32-bit integer manipulation macros (big endian)
*/
#ifndef GET_UINT32_BE
#define GET_UINT32_BE(n,b,i) \
do { \
(n) = ( (uint32_t) (b)[(i) ] << 24 ) \
| ( (uint32_t) (b)[(i) + 1] << 16 ) \
| ( (uint32_t) (b)[(i) + 2] << 8 ) \
| ( (uint32_t) (b)[(i) + 3] ); \
} while( 0 )
#endif
#ifndef PUT_UINT32_BE
#define PUT_UINT32_BE(n,b,i) \
do { \
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 3] = (unsigned char) ( (n) ); \
} while( 0 )
#endif
void mbedtls_sha256_init( mbedtls_sha256_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_sha256_context ) );
}
void mbedtls_sha256_free( mbedtls_sha256_context *ctx )
{
if ( ctx == NULL ) {
return;
}
mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) );
}
void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src )
{
*dst = *src;
}
/*
* SHA-256 context setup
*/
int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 )
{
memset( ctx, 0, sizeof( mbedtls_sha256_context ) );
if ( is224 ) {
ctx->mode = SHA2_224;
} else {
ctx->mode = SHA2_256;
}
return 0;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256_starts( mbedtls_sha256_context *ctx,
int is224 )
{
mbedtls_sha256_starts_ret( ctx, is224 );
}
#endif
int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] )
{
int ret;
esp_sha_acquire_hardware();
ret = esp_sha_dma(ctx->mode, data, 64, 0, 0, ctx->first_block);
esp_sha_release_hardware();
return ret;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256_process( mbedtls_sha256_context *ctx,
const unsigned char data[64] )
{
mbedtls_internal_sha256_process( ctx, data );
}
#endif
/*
* SHA-256 process buffer
*/
int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, const unsigned char *input,
size_t ilen )
{
int ret = 0;
size_t fill;
uint32_t left, len, local_len = 0;
if ( ilen == 0 ) {
return 0;
}
left = ctx->total[0] & 0x3F;
fill = 64 - left;
ctx->total[0] += (uint32_t) ilen;
ctx->total[0] &= 0xFFFFFFFF;
if ( ctx->total[0] < (uint32_t) ilen ) {
ctx->total[1]++;
}
/* Check if any data pending from previous call to this API */
if ( left && ilen >= fill ) {
memcpy( (void *) (ctx->buffer + left), input, fill );
input += fill;
ilen -= fill;
left = 0;
local_len = 64;
}
len = (ilen / 64) * 64;
if ( len || local_len) {
esp_sha_acquire_hardware();
if (ctx->sha_state == ESP_SHA256_STATE_INIT) {
ctx->first_block = true;
ctx->sha_state = ESP_SHA256_STATE_IN_PROCESS;
} else if (ctx->sha_state == ESP_SHA256_STATE_IN_PROCESS) {
ctx->first_block = false;
esp_sha_write_digest_state(ctx->mode, ctx->state);
}
ret = esp_sha_dma(ctx->mode, input, len, ctx->buffer, local_len, ctx->first_block);
esp_sha_read_digest_state(ctx->mode, ctx->state);
esp_sha_release_hardware();
if (ret != 0) {
return ret;
}
}
if ( ilen > 0 ) {
memcpy( (void *) (ctx->buffer + left), input + len, ilen - len );
}
return 0;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256_update( mbedtls_sha256_context *ctx,
const unsigned char *input,
size_t ilen )
{
mbedtls_sha256_update_ret( ctx, input, ilen );
}
#endif
static const unsigned char sha256_padding[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-256 final digest
*/
int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, unsigned char output[32] )
{
int ret;
uint32_t last, padn;
uint32_t high, low;
unsigned char msglen[8];
high = ( ctx->total[0] >> 29 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT32_BE( high, msglen, 0 );
PUT_UINT32_BE( low, msglen, 4 );
last = ctx->total[0] & 0x3F;
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
if ( ( ret = mbedtls_sha256_update_ret( ctx, sha256_padding, padn ) ) != 0 ) {
return ret;
}
if ( ( ret = mbedtls_sha256_update_ret( ctx, msglen, 8 ) ) != 0 ) {
return ret;
}
memcpy(output, ctx->state, 32);
return ret;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx,
unsigned char output[32] )
{
mbedtls_sha256_finish_ret( ctx, output );
}
#endif
#endif /* MBEDTLS_SHA256_C && MBEDTLS_SHA256_ALT */

View file

@ -0,0 +1,317 @@
/*
* SHA-512 implementation with hardware ESP32 support added.
* Uses mbedTLS software implementation for failover when concurrent
* SHA operations are in use.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016-2020, Espressif Systems (Shanghai) PTE LTD
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/*
* The SHA-512 Secure Hash Standard was published by NIST in 2002.
*
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
*/
#if !defined(MBEDTLS_CONFIG_FILE)
#include "mbedtls/config.h"
#else
#include MBEDTLS_CONFIG_FILE
#endif
#if defined(MBEDTLS_SHA512_C) && defined(MBEDTLS_SHA512_ALT)
#include "mbedtls/sha512.h"
#if defined(_MSC_VER) || defined(__WATCOMC__)
#define UL64(x) x##ui64
#else
#define UL64(x) x##ULL
#endif
#include <string.h>
#if defined(MBEDTLS_SELF_TEST)
#if defined(MBEDTLS_PLATFORM_C)
#include "mbedtls/platform.h"
#else
#include <stdio.h>
#define mbedtls_printf printf
#endif /* MBEDTLS_PLATFORM_C */
#endif /* MBEDTLS_SELF_TEST */
#include "esp32s2/sha.h"
/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n )
{
volatile unsigned char *p = v; while ( n-- ) *p++ = 0;
}
/*
* 64-bit integer manipulation macros (big endian)
*/
#ifndef PUT_UINT64_BE
#define PUT_UINT64_BE(n,b,i) \
{ \
(b)[(i) ] = (unsigned char) ( (n) >> 56 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \
(b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) + 7] = (unsigned char) ( (n) ); \
}
#endif /* PUT_UINT64_BE */
void esp_sha512_set_mode(mbedtls_sha512_context *ctx, esp_sha_type type)
{
switch (type) {
case SHA2_384:
case SHA2_512224:
case SHA2_512256:
case SHA2_512T:
ctx->mode = type;
break;
default:
ctx->mode = SHA2_512;
break;
}
}
/* For SHA512/t mode the intial hash value will depend on t */
void esp_sha512_set_t( mbedtls_sha512_context *ctx, uint16_t t_val)
{
ctx->t_val = t_val;
}
void mbedtls_sha512_init( mbedtls_sha512_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_sha512_context ) );
}
void mbedtls_sha512_free( mbedtls_sha512_context *ctx )
{
if ( ctx == NULL ) {
return;
}
mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) );
}
void mbedtls_sha512_clone( mbedtls_sha512_context *dst,
const mbedtls_sha512_context *src )
{
memcpy(dst, src, sizeof(mbedtls_sha512_context));
}
/*
* SHA-512 context setup
*/
int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 )
{
mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) );
if ( is384 ) {
ctx->mode = SHA2_384;
} else {
ctx->mode = SHA2_512;
}
return 0;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha512_starts( mbedtls_sha512_context *ctx,
int is384 )
{
mbedtls_sha512_starts_ret( ctx, is384 );
}
#endif
static int esp_internal_sha512_dma_process(mbedtls_sha512_context *ctx,
const uint8_t *data, size_t len,
uint8_t *buf, size_t buf_len)
{
return esp_sha_dma(ctx->mode, data, len, buf, buf_len, ctx->first_block);
}
int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] )
{
int ret;
esp_sha_acquire_hardware();
ret = esp_internal_sha512_dma_process(ctx, data, 128, 0, 0);
esp_sha_release_hardware();
return ret;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha512_process( mbedtls_sha512_context *ctx,
const unsigned char data[128] )
{
mbedtls_internal_sha512_process( ctx, data );
}
#endif
/*
* SHA-512 process buffer
*/
int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, const unsigned char *input,
size_t ilen )
{
int ret;
size_t fill;
unsigned int left, len, local_len = 0;
if ( ilen == 0 ) {
return 0;
}
left = (unsigned int) (ctx->total[0] & 0x7F);
fill = 128 - left;
ctx->total[0] += (uint64_t) ilen;
if ( ctx->total[0] < (uint64_t) ilen ) {
ctx->total[1]++;
}
if ( left && ilen >= fill ) {
memcpy( (void *) (ctx->buffer + left), input, fill );
input += fill;
ilen -= fill;
left = 0;
local_len = 128;
}
len = (ilen / 128) * 128;
if ( len || local_len) {
esp_sha_acquire_hardware();
if (ctx->sha_state == ESP_SHA512_STATE_INIT) {
if (ctx->mode == SHA2_512T) {
esp_sha_512_t_init_hash(ctx->t_val);
ctx->first_block = false;
} else {
ctx->first_block = true;
}
ctx->sha_state = ESP_SHA512_STATE_IN_PROCESS;
} else if (ctx->sha_state == ESP_SHA512_STATE_IN_PROCESS) {
ctx->first_block = false;
esp_sha_write_digest_state(ctx->mode, ctx->state);
}
ret = esp_internal_sha512_dma_process(ctx, input, len, ctx->buffer, local_len);
esp_sha_read_digest_state(ctx->mode, ctx->state);
esp_sha_release_hardware();
if (ret != 0) {
return ret;
}
}
if ( ilen > 0 ) {
memcpy( (void *) (ctx->buffer + left), input + len, ilen - len );
}
return 0;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha512_update( mbedtls_sha512_context *ctx,
const unsigned char *input,
size_t ilen )
{
mbedtls_sha512_update_ret( ctx, input, ilen );
}
#endif
static const unsigned char sha512_padding[128] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/*
* SHA-512 final digest
*/
int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, unsigned char output[64] )
{
int ret;
size_t last, padn;
uint64_t high, low;
unsigned char msglen[16];
high = ( ctx->total[0] >> 61 )
| ( ctx->total[1] << 3 );
low = ( ctx->total[0] << 3 );
PUT_UINT64_BE( high, msglen, 0 );
PUT_UINT64_BE( low, msglen, 8 );
last = (size_t)( ctx->total[0] & 0x7F );
padn = ( last < 112 ) ? ( 112 - last ) : ( 240 - last );
if ( ( ret = mbedtls_sha512_update_ret( ctx, sha512_padding, padn ) ) != 0 ) {
return ret;
}
if ( ( ret = mbedtls_sha512_update_ret( ctx, msglen, 16 ) ) != 0 ) {
return ret;
}
if (ctx->mode == SHA2_384) {
memcpy(output, ctx->state, 48);
} else {
memcpy(output, ctx->state, 64);
}
return ret;
}
#if !defined(MBEDTLS_DEPRECATED_REMOVED)
void mbedtls_sha512_finish( mbedtls_sha512_context *ctx,
unsigned char output[64] )
{
mbedtls_sha512_finish_ret( ctx, output );
}
#endif
#endif /* MBEDTLS_SHA512_C && MBEDTLS_SHA512_ALT */

View file

@ -3,7 +3,7 @@
* based on mbedTLS FIPS-197 compliant version. * based on mbedTLS FIPS-197 compliant version.
* *
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd * Additions Copyright (C) 2016-2020, Espressif Systems (Shanghai) PTE Ltd
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may * Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -28,34 +28,38 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <sys/lock.h> #include <sys/lock.h>
#include <assert.h>
#include "soc/soc.h" #include "esp_log.h"
#include "esp32s2/crypto_dma.h"
#include "esp32s2/sha.h"
#include "soc/crypto_dma_reg.h"
#include "esp32s2/rom/ets_sys.h" #include "esp32s2/rom/ets_sys.h"
#include "soc/dport_reg.h" #include "soc/dport_reg.h"
#include "soc/hwcrypto_reg.h" #include "soc/hwcrypto_reg.h"
#include "esp32s2/rom/lldesc.h"
#include "esp32s2/rom/cache.h" #include "esp32s2/rom/cache.h"
#include "esp_intr_alloc.h"
#include "esp_log.h" #include "soc/cache_memory.h"
#include "soc/periph_defs.h"
#include "freertos/FreeRTOS.h" #include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h" #include "freertos/semphr.h"
/* Single lock for SHA engine #include "esp32s2/sha.h"
#include "esp32s2/crypto_dma.h"
#include "esp32s2/rom/lldesc.h"
#include "soc/periph_defs.h"
#include "soc/crypto_dma_reg.h"
#include "driver/periph_ctrl.h"
#include "sys/param.h"
/* Max amount of bytes in a single DMA operation is 4095,
for SHA this means that the biggest safe amount of bytes is
31 blocks of 128 bytes = 3968
*/ */
#define SHA_DMA_MAX_BYTES 3968
/* Lock for SHA engine */
static _lock_t s_sha_lock; static _lock_t s_sha_lock;
/* Enable if want to use SHA interrupt */ const static char *TAG = "esp-sha";
//#define CONFIG_MBEDTLS_SHA_USE_INTERRUPT
#if defined(CONFIG_MBEDTLS_SHA_USE_INTERRUPT)
static SemaphoreHandle_t op_complete_sem;
#endif
/* Return block size (in bytes) for a given SHA type */ /* Return block size (in bytes) for a given SHA type */
inline static size_t block_length(esp_sha_type type) inline static size_t block_length(esp_sha_type type)
@ -96,190 +100,265 @@ inline static size_t state_length(esp_sha_type type)
} }
} }
/* This API was designed for ESP32, which has seperate /* Enable SHA peripheral and then lock it */
engines for SHA1,256,512. ESP32C has a single engine. void esp_sha_acquire_hardware()
*/
static void esp_sha_lock_engine_inner(void);
bool esp_sha_try_lock_engine(esp_sha_type sha_type)
{
if (_lock_try_acquire(&s_sha_lock) != 0) {
/* SHA engine is already in use */
return false;
} else {
esp_sha_lock_engine_inner();
return true;
}
}
void esp_sha_lock_engine(esp_sha_type sha_type)
{
_lock_acquire(&s_sha_lock);
esp_sha_lock_engine_inner();
}
/* Enable SHA block and then lock it */
static void esp_sha_lock_engine_inner(void)
{ {
/* Need to lock DMA since it is shared with AES block */ /* Need to lock DMA since it is shared with AES block */
portENTER_CRITICAL(&crypto_dma_spinlock); _lock_acquire(&crypto_dma_lock);
_lock_acquire(&s_sha_lock);
REG_SET_BIT(DPORT_PERIP_CLK_EN1_REG, DPORT_CRYPTO_SHA_CLK_EN | DPORT_CRYPTO_DMA_CLK_EN); /* Enable SHA and DMA hardware */
REG_CLR_BIT(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_SHA_RST | DPORT_CRYPTO_HMAC_RST | periph_module_enable(PERIPH_SHA_DMA_MODULE);
DPORT_CRYPTO_DMA_RST | DPORT_CRYPTO_DS_RST);
/* DMA for SHA */ /* DMA for SHA */
REG_WRITE(CRYPTO_DMA_AES_SHA_SELECT_REG, 1); REG_WRITE(CRYPTO_DMA_AES_SHA_SELECT_REG, 1);
} }
/* Disable SHA block and then unlock it */ /* Disable SHA peripheral block and then release it */
void esp_sha_unlock_engine(esp_sha_type sha_type) void esp_sha_release_hardware()
{ {
REG_WRITE(CRYPTO_DMA_AES_SHA_SELECT_REG, 0); /* Disable SHA and DMA hardware */
periph_module_disable(PERIPH_SHA_DMA_MODULE);
REG_SET_BIT(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_SHA_RST | DPORT_CRYPTO_DMA_RST |
DPORT_CRYPTO_DS_RST);
REG_CLR_BIT(DPORT_PERIP_CLK_EN1_REG, DPORT_CRYPTO_SHA_CLK_EN | DPORT_CRYPTO_DMA_CLK_EN);
portEXIT_CRITICAL(&crypto_dma_spinlock);
/* Need to lock DMA since it is shared with AES block */
_lock_release(&s_sha_lock); _lock_release(&s_sha_lock);
_lock_release(&crypto_dma_lock);
} }
#if defined (CONFIG_MBEDTLS_SHA_USE_INTERRUPT)
static IRAM_ATTR void esp_sha_dma_isr(void *arg)
{
BaseType_t higher_woken;
REG_WRITE(SHA_CLEAR_IRQ_REG, 1);
xSemaphoreGiveFromISR(op_complete_sem, &higher_woken);
if (higher_woken) {
portYIELD_FROM_ISR();
}
}
#endif
/* Check if SHA operation completed */ /* Busy wait until SHA is idle */
static int esp_sha_dma_complete(void) static void esp_sha_wait_idle(void)
{ {
#if defined (CONFIG_MBEDTLS_SHA_USE_INTERRUPT) while (DPORT_REG_READ(SHA_BUSY_REG) != 0) {
if (!xSemaphoreTake(op_complete_sem, 2000 / portTICK_PERIOD_MS)) {
ESP_LOGE("SHA", "Timed out waiting for completion of SHA Interrupt");
return -1;
} }
#else
esp_sha_wait_idle();
#endif
return 0;
} }
/* Wait until SHA is busy */
void esp_sha_wait_idle(void) void esp_sha_write_digest_state(esp_sha_type sha_type, void *digest_state)
{ {
while (DPORT_REG_READ(SHA_BUSY_REG) != 0) { } uint32_t *digest_state_words = (uint32_t *)digest_state;
uint32_t *reg_addr_buf = (uint32_t *)(SHA_H_BASE);
for (int i = 0; i < state_length(sha_type) / 4; i++) {
REG_WRITE(&reg_addr_buf[i], digest_state_words[i]);
}
} }
/* Read the SHA digest from hardware */ /* Read the SHA digest from hardware */
void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state) void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state)
{ {
esp_sha_wait_idle(); uint32_t *digest_state_words = (uint32_t *)digest_state;
memcpy(digest_state, (void *)SHA_H_BASE, state_length(sha_type)); int word_len = state_length(sha_type) / 4;
esp_dport_access_read_buffer(digest_state_words, SHA_H_BASE, word_len);
/* Fault injection check: verify SHA engine actually ran,
state is not all zeroes.
*/
for (int i = 0; i < word_len; i++) {
if (digest_state_words[i] != 0) {
return;
}
}
abort(); // SHA peripheral returned all zero state, probably due to fault injection
} }
/* Internally calls DMA API for single block */ /* The initial hash value for SHA512/t is generated according to the
void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block) algorithm described in the TRM, chapter SHA-Accelerator
*/
int esp_sha_512_t_init_hash(uint16_t t)
{ {
esp_sha_dma(sha_type, data_block, block_length(sha_type), is_first_block); uint32_t t_string = 0;
uint8_t t0, t1, t2, t_len;
if (t == 384) {
ESP_LOGE(TAG, "Invalid t for SHA512/t, t = %u,cannot be 384", t);
return -1;
} }
/* Performs SHA on multiple blocks at a time */ if (t <= 9) {
int esp_sha_dma(esp_sha_type sha_type, const void *data_block, uint32_t ilen, bool is_first_block) t_string = (uint32_t)((1 << 23) | ((0x30 + t) << 24));
{ t_len = 0x48;
size_t blk_len = 0; } else if (t <= 99) {
const uint8_t *local_buf = data_block; t0 = t % 10;
int ret = 0; t1 = (t / 10) % 10;
volatile lldesc_t dma_descr; t_string = (uint32_t)((1 << 15) | ((0x30 + t0) << 16) |
(((0x30 + t1) << 24)));
if (ilen == 0) { t_len = 0x50;
return ret; } else if (t <= 512) {
t0 = t % 10;
t1 = (t / 10) % 10;
t2 = t / 100;
t_string = (uint32_t)((1 << 7) | ((0x30 + t0) << 8) |
(((0x30 + t1) << 16) + ((0x30 + t2) << 24)));
t_len = 0x58;
} else {
ESP_LOGE(TAG, "Invalid t for SHA512/t, t = %u, must equal or less than 512", t);
return -1;
} }
blk_len = block_length(sha_type); REG_WRITE(SHA_T_LENGTH_REG, t_len);
REG_WRITE(SHA_T_STRING_REG, t_string);
REG_WRITE(SHA_MODE_REG, sha_type); REG_WRITE(SHA_MODE_REG, SHA2_512T);
if ((sha_type == SHA2_512T) && (is_first_block == true)) {
REG_WRITE(SHA_START_REG, 1); REG_WRITE(SHA_START_REG, 1);
}
REG_WRITE(SHA_BLOCK_NUM_REG, (ilen / blk_len));
if ((sha_type == SHA2_512T) && (is_first_block == true)) {
esp_sha_wait_idle(); esp_sha_wait_idle();
is_first_block = false;
return 0;
} }
bzero( (void *)&dma_descr, sizeof( dma_descr ) );
/* DMA descriptor for Memory to DMA-AES transfer */ static int esp_sha_dma_process(esp_sha_type sha_type, const void *input, uint32_t ilen,
dma_descr.length = ilen; const void *buf, uint32_t buf_len, bool is_first_block);
dma_descr.size = ilen;
dma_descr.owner = 1; /* Performs SHA on multiple blocks at a time using DMA
dma_descr.eof = 1; splits up into smaller operations for inputs that exceed a single DMA list
dma_descr.buf = local_buf; */
dma_descr.sosf = 0; int esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen,
dma_descr.empty = 0; const void *buf, uint32_t buf_len, bool is_first_block)
{
int ret = 0;
const void *dma_input;
unsigned char *non_icache_input = NULL;
unsigned char *non_icache_buf = NULL;
int dma_op_num = ( ilen / (SHA_DMA_MAX_BYTES + 1) ) + 1;
if (buf_len > 128) {
ESP_LOGE(TAG, "SHA DMA buf_len cannot exceed max size for a single block");
return -1;
}
#if (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC) #if (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
if ((unsigned int)data_block >= SOC_EXTRAM_DATA_LOW && (unsigned int)data_block <= SOC_EXTRAM_DATA_HIGH) { if (esp_ptr_external_ram(input) || esp_ptr_external_ram(buf)) {
Cache_WriteBack_All(); Cache_WriteBack_All();
} }
#endif #endif
/* DMA cannot access memory in the iCache range, copy data to temporary buffers before transfer */
if (!esp_ptr_dma_ext_capable(input) && !esp_ptr_dma_capable(input)) {
non_icache_input = malloc(sizeof(unsigned char) * MIN(ilen, SHA_DMA_MAX_BYTES));
if (non_icache_input == NULL) {
ESP_LOGE(TAG, "Failed to allocate memory");
ret = ESP_ERR_NO_MEM;
goto cleanup;
}
}
if (!esp_ptr_dma_ext_capable(buf) && !esp_ptr_dma_capable(buf)) {
non_icache_buf = malloc(sizeof(unsigned char) * buf_len);
if (non_icache_buf == NULL) {
ESP_LOGE(TAG, "Failed to allocate memory");
ret = ESP_ERR_NO_MEM;
goto cleanup;
}
memcpy(non_icache_buf, buf, buf_len);
buf = non_icache_buf;
}
/* The max amount of blocks in a single hardware operation is 2^6 - 1 = 63
Thus we only do a single DMA input list + dma buf list,
which is max 3968/64 + 64/64 = 63 blocks */
for (int i = 0; i < dma_op_num; i++) {
int dma_chunk_len = MIN(ilen, SHA_DMA_MAX_BYTES);
/* Input depends on if it's a temp alloc buffer or supplied by user */
if (non_icache_input != NULL) {
memcpy(non_icache_input, input, dma_chunk_len);
dma_input = non_icache_input;
} else {
dma_input = input;
}
ret = esp_sha_dma_process(sha_type, dma_input, dma_chunk_len, buf, buf_len, is_first_block);
if (ret != 0) {
return ret;
}
is_first_block = false;
ilen -= dma_chunk_len;
input += dma_chunk_len;
// Only append buf to the first operation
buf_len = 0;
}
cleanup:
free(non_icache_input);
free(non_icache_buf);
return ret;
}
static void esp_sha_dma_init(lldesc_t *input)
{
/* Reset DMA */ /* Reset DMA */
SET_PERI_REG_MASK(CRYPTO_DMA_CONF0_REG, CONF0_REG_AHBM_RST | CONF0_REG_OUT_RST | CONF0_REG_AHBM_FIFO_RST); SET_PERI_REG_MASK(CRYPTO_DMA_CONF0_REG, CONF0_REG_AHBM_RST | CONF0_REG_OUT_RST | CONF0_REG_AHBM_FIFO_RST);
CLEAR_PERI_REG_MASK(CRYPTO_DMA_CONF0_REG, CONF0_REG_AHBM_RST | CONF0_REG_OUT_RST | CONF0_REG_AHBM_FIFO_RST); CLEAR_PERI_REG_MASK(CRYPTO_DMA_CONF0_REG, CONF0_REG_AHBM_RST | CONF0_REG_OUT_RST | CONF0_REG_AHBM_FIFO_RST);
/* Set descriptors */ /* Set descriptors */
CLEAR_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, OUT_LINK_REG_OUTLINK_ADDR); CLEAR_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, OUT_LINK_REG_OUTLINK_ADDR);
SET_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, ((uint32_t)(&dma_descr))&OUT_LINK_REG_OUTLINK_ADDR); SET_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, ((uint32_t)(input))&OUT_LINK_REG_OUTLINK_ADDR);
/* Start transfer */ /* Start transfer */
SET_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, OUT_LINK_REG_OUTLINK_START); SET_PERI_REG_MASK(CRYPTO_DMA_OUT_LINK_REG, OUT_LINK_REG_OUTLINK_START);
#if defined (CONFIG_MBEDTLS_SHA_USE_INTERRUPT)
REG_WRITE(SHA_CLEAR_IRQ_REG, 1);
if (op_complete_sem == NULL) {
op_complete_sem = xSemaphoreCreateBinary();
esp_intr_alloc(ETS_SHA_INTR_SOURCE, 0, esp_sha_dma_isr, 0, 0);
} }
REG_WRITE(SHA_INT_ENA_REG, 1);
#endif
/* Performs SHA on multiple blocks at a time */
static esp_err_t esp_sha_dma_process(esp_sha_type sha_type, const void *input, uint32_t ilen,
const void *buf, uint32_t buf_len, bool is_first_block)
{
size_t blk_len = 0;
int ret = 0;
lldesc_t dma_descr_input = {};
lldesc_t dma_descr_buf = {};
lldesc_t *dma_descr_head;
blk_len = block_length(sha_type);
REG_WRITE(SHA_MODE_REG, sha_type);
REG_WRITE(SHA_BLOCK_NUM_REG, ((ilen + buf_len) / blk_len));
/* DMA descriptor for Memory to DMA-SHA transfer */
if (ilen) {
dma_descr_input.length = ilen;
dma_descr_input.size = ilen;
dma_descr_input.owner = 1;
dma_descr_input.eof = 1;
dma_descr_input.buf = input;
dma_descr_head = &dma_descr_input;
}
/* Check after input to overide head if there is any buf*/
if (buf_len) {
dma_descr_buf.length = buf_len;
dma_descr_buf.size = buf_len;
dma_descr_buf.owner = 1;
dma_descr_buf.eof = 1;
dma_descr_buf.buf = buf;
dma_descr_head = &dma_descr_buf;
}
/* Link DMA lists */
if (buf_len && ilen) {
dma_descr_buf.eof = 0;
dma_descr_buf.empty = (uint32_t)(&dma_descr_input);
}
esp_sha_dma_init(dma_descr_head);
/* Start hashing */
if (is_first_block) { if (is_first_block) {
REG_WRITE(SHA_DMA_START_REG, 1); REG_WRITE(SHA_DMA_START_REG, 1);
} else { } else {
REG_WRITE(SHA_DMA_CONTINUE_REG, 1); REG_WRITE(SHA_DMA_CONTINUE_REG, 1);
} }
ret = esp_sha_dma_complete(); esp_sha_wait_idle();
#if (CONFIG_SPIRAM_USE_CAPS_ALLOC || CONFIG_SPIRAM_USE_MALLOC)
if ((unsigned int)data_block >= SOC_EXTRAM_DATA_LOW && (unsigned int)data_block <= SOC_EXTRAM_DATA_HIGH) {
Cache_Invalidate_DCache_All();
}
#endif
return ret; return ret;
} }
void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output)
{
SHA_CTX ctx;
esp_sha_lock_engine(sha_type);
ets_sha_init(&ctx, sha_type);
ets_sha_starts(&ctx, 0);
ets_sha_update(&ctx, input, ilen, false);
ets_sha_finish(&ctx, output);
esp_sha_unlock_engine(sha_type);
}

View file

@ -0,0 +1,288 @@
/**
* \brief AES block cipher, ESP32-S2 hardware accelerated version
* Based on mbedTLS FIPS-197 compliant version.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016-2020, Espressif Systems (Shanghai) PTE Ltd
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
/*
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
*
* http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
*/
/* Below XTS implementation is copied aes.c of mbedtls library.
* When MBEDTLS_AES_ALT is defined mbedtls expects alternate
* definition of XTS functions to be available. Even if this
* could have been avoided, it is done for consistency reason.
*/
#include <stdio.h>
#include <string.h>
#include <sys/lock.h>
#include "mbedtls/aes.h"
#if CONFIG_IDF_TARGET_ESP32
#include "esp32/aes.h"
#elif CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/aes.h"
#endif
void esp_aes_xts_init( esp_aes_xts_context *ctx )
{
esp_aes_init( &ctx->crypt );
esp_aes_init( &ctx->tweak );
}
void esp_aes_xts_free( esp_aes_xts_context *ctx )
{
esp_aes_free( &ctx->crypt );
esp_aes_free( &ctx->tweak );
}
static int esp_aes_xts_decode_keys( const unsigned char *key,
unsigned int keybits,
const unsigned char **key1,
unsigned int *key1bits,
const unsigned char **key2,
unsigned int *key2bits )
{
const unsigned int half_keybits = keybits / 2;
const unsigned int half_keybytes = half_keybits / 8;
switch ( keybits ) {
case 256: break;
case 512: break;
default : return ( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
}
*key1bits = half_keybits;
*key2bits = half_keybits;
*key1 = &key[0];
*key2 = &key[half_keybytes];
return 0;
}
int esp_aes_xts_setkey_enc( esp_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits)
{
int ret;
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
ret = esp_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
&key2, &key2bits );
if ( ret != 0 ) {
return ( ret );
}
/* Set the tweak key. Always set tweak key for the encryption mode. */
ret = esp_aes_setkey( &ctx->tweak, key2, key2bits );
if ( ret != 0 ) {
return ( ret );
}
/* Set crypt key for encryption. */
return esp_aes_setkey( &ctx->crypt, key1, key1bits );
}
int esp_aes_xts_setkey_dec( esp_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits)
{
int ret;
const unsigned char *key1, *key2;
unsigned int key1bits, key2bits;
ret = esp_aes_xts_decode_keys( key, keybits, &key1, &key1bits,
&key2, &key2bits );
if ( ret != 0 ) {
return ( ret );
}
/* Set the tweak key. Always set tweak key for encryption. */
ret = esp_aes_setkey( &ctx->tweak, key2, key2bits );
if ( ret != 0 ) {
return ( ret );
}
/* Set crypt key for decryption. */
return esp_aes_setkey( &ctx->crypt, key1, key1bits );
}
/* Endianess with 64 bits values */
#ifndef GET_UINT64_LE
#define GET_UINT64_LE(n,b,i) \
{ \
(n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \
| ( (uint64_t) (b)[(i) + 6] << 48 ) \
| ( (uint64_t) (b)[(i) + 5] << 40 ) \
| ( (uint64_t) (b)[(i) + 4] << 32 ) \
| ( (uint64_t) (b)[(i) + 3] << 24 ) \
| ( (uint64_t) (b)[(i) + 2] << 16 ) \
| ( (uint64_t) (b)[(i) + 1] << 8 ) \
| ( (uint64_t) (b)[(i) ] ); \
}
#endif
#ifndef PUT_UINT64_LE
#define PUT_UINT64_LE(n,b,i) \
{ \
(b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \
(b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \
(b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \
(b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \
(b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \
(b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \
(b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \
(b)[(i) ] = (unsigned char) ( (n) ); \
}
#endif
/*
* GF(2^128) multiplication function
*
* This function multiplies a field element by x in the polynomial field
* representation. It uses 64-bit word operations to gain speed but compensates
* for machine endianess and hence works correctly on both big and little
* endian machines.
*/
static void esp_gf128mul_x_ble( unsigned char r[16],
const unsigned char x[16] )
{
uint64_t a, b, ra, rb;
GET_UINT64_LE( a, x, 0 );
GET_UINT64_LE( b, x, 8 );
ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) );
rb = ( a >> 63 ) | ( b << 1 );
PUT_UINT64_LE( ra, r, 0 );
PUT_UINT64_LE( rb, r, 8 );
}
/*
* AES-XTS buffer encryption/decryption
*/
int esp_aes_crypt_xts( esp_aes_xts_context *ctx,
int mode,
size_t length,
const unsigned char data_unit[16],
const unsigned char *input,
unsigned char *output )
{
int ret;
size_t blocks = length / 16;
size_t leftover = length % 16;
unsigned char tweak[16];
unsigned char prev_tweak[16];
unsigned char tmp[16];
/* Sectors must be at least 16 bytes. */
if ( length < 16 ) {
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
}
/* NIST SP 80-38E disallows data units larger than 2**20 blocks. */
if ( length > ( 1 << 20 ) * 16 ) {
return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
}
/* Compute the tweak. */
ret = esp_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT,
data_unit, tweak );
if ( ret != 0 ) {
return ( ret );
}
while ( blocks-- ) {
size_t i;
if ( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 ) {
/* We are on the last block in a decrypt operation that has
* leftover bytes, so we need to use the next tweak for this block,
* and this tweak for the lefover bytes. Save the current tweak for
* the leftovers and then update the current tweak for use on this,
* the last full block. */
memcpy( prev_tweak, tweak, sizeof( tweak ) );
esp_gf128mul_x_ble( tweak, tweak );
}
for ( i = 0; i < 16; i++ ) {
tmp[i] = input[i] ^ tweak[i];
}
ret = esp_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
if ( ret != 0 ) {
return ( ret );
}
for ( i = 0; i < 16; i++ ) {
output[i] = tmp[i] ^ tweak[i];
}
/* Update the tweak for the next block. */
esp_gf128mul_x_ble( tweak, tweak );
output += 16;
input += 16;
}
if ( leftover ) {
/* If we are on the leftover bytes in a decrypt operation, we need to
* use the previous tweak for these bytes (as saved in prev_tweak). */
unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak;
/* We are now on the final part of the data unit, which doesn't divide
* evenly by 16. It's time for ciphertext stealing. */
size_t i;
unsigned char *prev_output = output - 16;
/* Copy ciphertext bytes from the previous block to our output for each
* byte of cyphertext we won't steal. At the same time, copy the
* remainder of the input for this final round (since the loop bounds
* are the same). */
for ( i = 0; i < leftover; i++ ) {
output[i] = prev_output[i];
tmp[i] = input[i] ^ t[i];
}
/* Copy ciphertext bytes from the previous block for input in this
* round. */
for ( ; i < 16; i++ ) {
tmp[i] = prev_output[i] ^ t[i];
}
ret = esp_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp );
if ( ret != 0 ) {
return ret;
}
/* Write the result back to the previous block, overriding the previous
* output we copied. */
for ( i = 0; i < 16; i++ ) {
prev_output[i] = tmp[i] ^ t[i];
}
}
return ( 0 );
}

View file

@ -26,7 +26,6 @@
#include <mbedtls/sha512.h> #include <mbedtls/sha512.h>
#if CONFIG_IDF_TARGET_ESP32
void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output) void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output)
{ {
int ret; int ret;
@ -83,4 +82,3 @@ void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, uns
} }
} }
#endif

View file

@ -3,7 +3,7 @@
* Based on mbedTLS FIPS-197 compliant version. * Based on mbedTLS FIPS-197 compliant version.
* *
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd * Additions Copyright (C) 2016-20, Espressif Systems (Shanghai) PTE Ltd
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may * Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -38,6 +38,7 @@ extern "C" {
#define ERR_ESP_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ #define ERR_ESP_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */
#define ERR_ESP_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ #define ERR_ESP_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
/** /**
* \brief AES context structure * \brief AES context structure
* *
@ -52,11 +53,11 @@ typedef struct {
uint8_t key[32]; uint8_t key[32];
} esp_aes_context; } esp_aes_context;
/** /**
* \brief The AES XTS context-type definition. * \brief The AES XTS context-type definition.
*/ */
typedef struct typedef struct {
{
esp_aes_context crypt; /*!< The AES context to use for AES block esp_aes_context crypt; /*!< The AES context to use for AES block
encryption or decryption. */ encryption or decryption. */
esp_aes_context tweak; /*!< The AES context used for tweak esp_aes_context tweak; /*!< The AES context used for tweak

View file

@ -31,7 +31,7 @@ extern "C" {
/* Since crypto DMA is shared between DMA-AES and SHA blocks /* Since crypto DMA is shared between DMA-AES and SHA blocks
* Needs to be taken by respective blocks before using Crypto DMA * Needs to be taken by respective blocks before using Crypto DMA
*/ */
extern portMUX_TYPE crypto_dma_spinlock; extern _lock_t crypto_dma_lock;
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -3,7 +3,7 @@
* Based on mbedTLS FIPS-197 compliant version. * Based on mbedTLS FIPS-197 compliant version.
* *
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd * Additions Copyright (C) 2019-2020, Espressif Systems (Shanghai) PTE Ltd
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may * Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -30,27 +30,39 @@
extern "C" { extern "C" {
#endif #endif
#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */ #define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */
#define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function.*/ #define MBEDTLS_ERR_GCM_BAD_INPUT -0x0014 /**< Bad input parameters to function.*/
typedef enum {
ESP_AES_GCM_STATE_INIT,
ESP_AES_GCM_STATE_UPDATE,
ESP_AES_GCM_STATE_FINISH
} esp_aes_gcm_state;
/** /**
* \brief The GCM context structure. * \brief The GCM context structure.
*/ */
typedef struct { typedef struct {
uint8_t H[16]; /*!< H */ uint8_t H[16]; /*!< H */
uint8_t S[16];
uint8_t J0[16];
uint8_t ori_j0[16];
const uint8_t *iv;
size_t iv_len; /*!< The length of IV. */ size_t iv_len; /*!< The length of IV. */
uint64_t aad_len; /*!< The total length of the additional data. */ uint64_t aad_len; /*!< The total length of the additional data. */
size_t data_len;
int mode;
const unsigned char *aad; /*!< The additional data. */ const unsigned char *aad; /*!< The additional data. */
esp_aes_context aes_ctx; esp_aes_context aes_ctx;
} esp_aes_gcm_state gcm_state;
esp_aes_gcm_context; } esp_gcm_context;
/** /**
* \brief This function initializes the specified GCM context * \brief This function initializes the specified GCM context
* *
* \param ctx The GCM context to initialize. * \param ctx The GCM context to initialize.
*/ */
void esp_aes_gcm_init( esp_aes_gcm_context *ctx); void esp_aes_gcm_init( esp_gcm_context *ctx);
/** /**
* \brief This function associates a GCM context with a * \brief This function associates a GCM context with a
@ -67,7 +79,7 @@ void esp_aes_gcm_init( esp_aes_gcm_context *ctx);
* \return \c 0 on success. * \return \c 0 on success.
* \return A cipher-specific error code on failure. * \return A cipher-specific error code on failure.
*/ */
int esp_aes_gcm_setkey( esp_aes_gcm_context *ctx, int esp_aes_gcm_setkey( esp_gcm_context *ctx,
mbedtls_cipher_id_t cipher, mbedtls_cipher_id_t cipher,
const unsigned char *key, const unsigned char *key,
unsigned int keybits ); unsigned int keybits );
@ -88,7 +100,7 @@ int esp_aes_gcm_setkey( esp_aes_gcm_context *ctx,
* *
* \return \c 0 on success. * \return \c 0 on success.
*/ */
int esp_aes_gcm_starts( esp_aes_gcm_context *ctx, int esp_aes_gcm_starts( esp_gcm_context *ctx,
int mode, int mode,
const unsigned char *iv, const unsigned char *iv,
size_t iv_len, size_t iv_len,
@ -116,7 +128,7 @@ int esp_aes_gcm_starts( esp_aes_gcm_context *ctx,
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure.
*/ */
int esp_aes_gcm_update( esp_aes_gcm_context *ctx, int esp_aes_gcm_update( esp_gcm_context *ctx,
size_t length, size_t length,
const unsigned char *input, const unsigned char *input,
unsigned char *output ); unsigned char *output );
@ -135,7 +147,7 @@ int esp_aes_gcm_update( esp_aes_gcm_context *ctx,
* \return \c 0 on success. * \return \c 0 on success.
* \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure. * \return #MBEDTLS_ERR_GCM_BAD_INPUT on failure.
*/ */
int esp_aes_gcm_finish( esp_aes_gcm_context *ctx, int esp_aes_gcm_finish( esp_gcm_context *ctx,
unsigned char *tag, unsigned char *tag,
size_t tag_len ); size_t tag_len );
@ -144,7 +156,7 @@ int esp_aes_gcm_finish( esp_aes_gcm_context *ctx,
* *
* \param ctx The GCM context to clear. * \param ctx The GCM context to clear.
*/ */
void esp_aes_gcm_free( esp_aes_gcm_context *ctx); void esp_aes_gcm_free( esp_gcm_context *ctx);
/** /**
* \brief This function performs GCM encryption or decryption of a buffer. * \brief This function performs GCM encryption or decryption of a buffer.
@ -170,7 +182,7 @@ void esp_aes_gcm_free( esp_aes_gcm_context *ctx);
* *
* \return \c 0 on success. * \return \c 0 on success.
*/ */
int esp_aes_gcm_crypt_and_tag( esp_aes_gcm_context *ctx, int esp_aes_gcm_crypt_and_tag( esp_gcm_context *ctx,
int mode, int mode,
size_t length, size_t length,
const unsigned char *iv, const unsigned char *iv,
@ -206,7 +218,7 @@ int esp_aes_gcm_crypt_and_tag( esp_aes_gcm_context *ctx,
* \return 0 if successful and authenticated. * \return 0 if successful and authenticated.
* \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match. * \return #MBEDTLS_ERR_GCM_AUTH_FAILED if the tag does not match.
*/ */
int esp_aes_gcm_auth_decrypt( esp_aes_gcm_context *ctx, int esp_aes_gcm_auth_decrypt( esp_gcm_context *ctx,
size_t length, size_t length,
const unsigned char *iv, const unsigned char *iv,
size_t iv_len, size_t iv_len,

View file

@ -1,4 +1,4 @@
// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD // Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD
// //
// Licensed under the Apache License, Version 2.0 (the "License"); // Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. // you may not use this file except in compliance with the License.
@ -16,9 +16,8 @@
#define _ESP_SHA_H_ #define _ESP_SHA_H_
#include "esp32s2/rom/sha.h" #include "esp32s2/rom/sha.h"
#include "esp_types.h"
/** @brief Low-level support functions for the hardware SHA engine /** @brief Low-level support functions for the hardware SHA engine using DMA
* *
* @note If you're looking for a SHA API to use, try mbedtls component * @note If you're looking for a SHA API to use, try mbedtls component
* mbedtls/shaXX.h. That API supports hardware acceleration. * mbedtls/shaXX.h. That API supports hardware acceleration.
@ -28,15 +27,8 @@
* *
* Some technical details about the hardware SHA engine: * Some technical details about the hardware SHA engine:
* *
* - SHA accelerator engine calculates one digest at a time, per SHA * - The crypto DMA is shared between the SHA and AES engine, it is not
* algorithm type. It initialises and maintains the digest state * possible for them to run calcalutions in parallel.
* internally. It is possible to read out an in-progress SHA digest
* state, but it is not possible to restore a SHA digest state
* into the engine.
*
* - The memory block SHA_TEXT_BASE is shared between all SHA digest
* engines, so all engines must be idle before this memory block is
* modified.
* *
*/ */
@ -50,17 +42,11 @@ typedef SHA_TYPE esp_sha_type;
/** @brief Calculate SHA1 or SHA2 sum of some data, using hardware SHA engine /** @brief Calculate SHA1 or SHA2 sum of some data, using hardware SHA engine
* *
* @note For more versatile SHA calculations, where data doesn't need * @note For more versatile SHA calculations, where data doesn't need
* to be passed all at once, try the mbedTLS mbedtls/shaX.h APIs. The * to be passed all at once, try the mbedTLS mbedtls/shaX.h APIs.
* hardware-accelerated mbedTLS implementation is also faster when
* hashing large amounts of data.
* *
* @note It is not necessary to lock any SHA hardware before calling * @note It is not necessary to lock any SHA hardware before calling
* this function, thread safety is managed internally. * this function, thread safety is managed internally.
* *
* @note If a TLS connection is open then this function may block
* indefinitely waiting for a SHA engine to become available. Use the
* mbedTLS SHA API to avoid this problem.
*
* @param sha_type SHA algorithm to use. * @param sha_type SHA algorithm to use.
* *
* @param input Input data buffer. * @param input Input data buffer.
@ -73,157 +59,106 @@ typedef SHA_TYPE esp_sha_type;
*/ */
void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output); void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output);
/* @brief Begin to execute a single SHA block operation /** @brief Execute SHA block operation using DMA
* *
* @note This is a piece of a SHA algorithm, rather than an entire SHA * @note This is a piece of a SHA algorithm, rather than an entire SHA
* algorithm. * algorithm.
* *
* @note Call esp_sha_try_lock_engine() before calling this * @note Call esp_sha_aquire_hardware() before calling this
* function. Do not call esp_sha_lock_memory_block() beforehand, this * function.
* is done inside the function.
* *
* @param sha_type SHA algorithm to use. * @param sha_type SHA algorithm to use.
* *
* @param data_block Pointer to block of data. Block size is * @param input Pointer to the input data. Block size is
* determined by algorithm (SHA1/SHA2_256 = 64 bytes,
* SHA2_384/SHA2_512 = 128 bytes)
*
* @param is_first_block If this parameter is true, the SHA state will
* be initialised (with the initial state of the given SHA algorithm)
* before the block is calculated. If false, the existing state of the
* SHA engine will be used.
*
* @return As a performance optimisation, this function returns before
* the SHA block operation is complete. Both this function and
* esp_sha_read_state() will automatically wait for any previous
* operation to complete before they begin. If using the SHA registers
* directly in another way, call esp_sha_wait_idle() after calling this
* function but before accessing the SHA registers.
*/
void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block);
/* @brief Begin to execute SHA block operation using DMA
*
* @note This is a piece of a SHA algorithm, rather than an entire SHA
* algorithm.
*
* @note Call esp_sha_try_lock_engine() before calling this
* function. Do not call esp_sha_lock_memory_block() beforehand, this
* is done inside the function.
*
* @param sha_type SHA algorithm to use.
*
* @param data_block Pointer to block of data. Block size is
* determined by algorithm (SHA1/SHA2_256 = 64 bytes, * determined by algorithm (SHA1/SHA2_256 = 64 bytes,
* SHA2_384/SHA2_512 = 128 bytes) * SHA2_384/SHA2_512 = 128 bytes)
* *
* @param ilen length of input data should be multiple of block length. * @param ilen length of input data should be multiple of block length.
* *
* @param buf Pointer to blocks of data that will be prepended
* to data_block before hashing. Useful when there is two sources of
* data that need to be efficiently calculated in a single SHA DMA
* operation.
*
* @param buf_len length of buf data should be multiple of block length.
* Should not be longer than the maximum amount of bytes in a single block
* (128 bytes)
*
* @param is_first_block If this parameter is true, the SHA state will * @param is_first_block If this parameter is true, the SHA state will
* be initialised (with the initial state of the given SHA algorithm) * be initialised (with the initial state of the given SHA algorithm)
* before the block is calculated. If false, the existing state of the * before the block is calculated. If false, the existing state of the
* SHA engine will be used. * SHA engine will be used.
* *
* @param t The number of bits for the SHA512/t hash function, with
* output truncated to t bits. Used for calculating the inital hash.
* t is any positive integer between 1 and 512, except 384.
*
* @return 0 if successful
*/ */
int esp_sha_dma(esp_sha_type sha_type, const void *data_block, uint32_t ilen, bool is_first_block); int esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen,
const void *buf, uint32_t buf_len, bool is_first_block);
/** @brief Read out the current state of the SHA digest loaded in the engine. /**
* @brief Read out the current state of the SHA digest
* *
* @note This is a piece of a SHA algorithm, rather than an entire SHA algorithm. * @note This is a piece of a SHA algorithm, rather than an entire SHA algorithm.
* *
* @note Call esp_sha_try_lock_engine() before calling this * @note Call esp_sha_aquire_hardware() before calling this
* function. Do not call esp_sha_lock_memory_block() beforehand, this * function.
* is done inside the function.
* *
* If the SHA suffix padding block has been executed already, the * If the SHA suffix padding block has been executed already, the
* value that is read is the SHA digest (in big endian * value that is read is the SHA digest.
* format). Otherwise, the value that is read is an interim SHA state. * Otherwise, the value that is read is an interim SHA state.
*
* @note If sha_type is SHA2_384, only 48 bytes of state will be read.
* This is enough for the final SHA2_384 digest, but if you want the
* interim SHA-384 state (to continue digesting) then pass SHA2_512 instead.
* *
* @param sha_type SHA algorithm in use. * @param sha_type SHA algorithm in use.
* * @param digest_state Pointer to a memory buffer to hold the SHA state. Size
* @param state Pointer to a memory buffer to hold the SHA state. Size * is 20 bytes (SHA1), 32 bytes (SHA2_256), or 64 bytes (SHA2_384, SHA2_512).
* is 20 bytes (SHA1), 32 bytes (SHA2_256), 48 bytes (SHA2_384) or 64 bytes (SHA2_512).
*
*/ */
void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state); void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state);
/** /**
* @brief Obtain exclusive access to a particular SHA engine * @brief Set the current state of the SHA digest
* *
* @param sha_type Type of SHA engine to use. * @note Call esp_sha_aquire_hardware() before calling this
* function.
* *
* Blocks until engine is available. Note: Can block indefinitely * When resuming a
* while a TLS connection is open, suggest using *
* esp_sha_try_lock_engine() and failing over to software SHA. * @param sha_type SHA algorithm in use.
* @param digest_state
*/ */
void esp_sha_lock_engine(esp_sha_type sha_type); void esp_sha_write_digest_state(esp_sha_type sha_type, void *digest_state);
/** /**
* @brief Try and obtain exclusive access to a particular SHA engine * @brief Enables the SHA and crypto DMA peripheral and takes the
* * locks for both of them.
* @param sha_type Type of SHA engine to use.
*
* @return Returns true if the SHA engine is locked for exclusive
* use. Call esp_sha_unlock_sha_engine() when done. Returns false if
* the SHA engine is already in use, caller should use software SHA
* algorithm for this digest.
*/ */
bool esp_sha_try_lock_engine(esp_sha_type sha_type); void esp_sha_acquire_hardware(void);
/** /**
* @brief Unlock an engine previously locked with esp_sha_lock_engine() or esp_sha_try_lock_engine() * @brief Disables the SHA and crypto DMA peripheral and releases the
* * locks.
* @param sha_type Type of engine to release. */
void esp_sha_release_hardware(void);
/*
*/ */
void esp_sha_unlock_engine(esp_sha_type sha_type);
/** /**
* @brief Acquire exclusive access to the SHA shared memory block at SHA_TEXT_BASE * @brief Sets the initial hash value for SHA512/t.
* *
* This memory block is shared across all the SHA algorithm types. * @note Is generated according to the algorithm described in the TRM,
* chapter SHA-Accelerator
* *
* Caller should have already locked a SHA engine before calling this function. * @note The engine must be locked until the value is used for an operation
* or read out. Else you risk another operation overwriting it.
* *
* Note that it is possible to obtain exclusive access to the memory block even * @param t
* while it is in use by the SHA engine. Caller should use esp_sha_wait_idle()
* to ensure the SHA engine is not reading from the memory block in hardware.
* *
* @note You do not need to lock the memory block before calling esp_sha_block() or esp_sha_read_digest_state(), these functions handle memory block locking internally. * @return 0 if successful
*
* Call esp_sha_unlock_memory_block() when done.
*/ */
void esp_sha_lock_memory_block(void); int esp_sha_512_t_init_hash(uint16_t t);
/**
* @brief Release exclusive access to the SHA register memory block at SHA_TEXT_BASE
*
* Caller should have already locked a SHA engine before calling this function.
*
* Call following esp_sha_lock_memory_block().
*/
void esp_sha_unlock_memory_block(void);
/** @brief Wait for the SHA engine to finish any current operation
*
* @note This function does not ensure exclusive access to any SHA
* engine. Caller should use esp_sha_try_lock_engine() and
* esp_sha_lock_memory_block() as required.
*
* @note Functions declared in this header file wait for SHA engine
* completion automatically, so you don't need to use this API for
* these. However if accessing SHA registers directly, you will need
* to call this before accessing SHA registers if using the
* esp_sha_block() function.
*
* @note This function busy-waits, so wastes CPU resources.
* Best to delay calling until you are about to need it.
*
*/
void esp_sha_wait_idle(void);
#ifdef __cplusplus #ifdef __cplusplus
} }

View file

@ -0,0 +1,55 @@
/**
* \file gcm_alt.h
*
* \brief AES block cipher
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*
*/
#ifndef GCM_ALT_H
#define GCM_ALT_H
#ifdef __cplusplus
extern "C" {
#endif
#if defined(MBEDTLS_GCM_ALT)
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/gcm.h"
typedef esp_gcm_context mbedtls_gcm_context;
#define mbedtls_gcm_init esp_aes_gcm_init
#define mbedtls_gcm_free esp_aes_gcm_free
#define mbedtls_gcm_setkey esp_aes_gcm_setkey
#define mbedtls_gcm_starts esp_aes_gcm_starts
#define mbedtls_gcm_update esp_aes_gcm_update
#define mbedtls_gcm_finish esp_aes_gcm_finish
#define mbedtls_gcm_auth_decrypt esp_aes_gcm_auth_decrypt
#define mbedtls_gcm_crypt_and_tag esp_aes_gcm_crypt_and_tag
#endif // CONFIG_IDF_TARGET_ESP32S2
#endif /* MBEDTLS_GCM_ALT */
#ifdef __cplusplus
}
#endif
#endif

View file

@ -118,6 +118,12 @@
#undef MBEDTLS_AES_ALT #undef MBEDTLS_AES_ALT
#endif #endif
#ifdef CONFIG_MBEDTLS_HARDWARE_GCM
#define MBEDTLS_GCM_ALT
#else
#undef MBEDTLS_GCM_ALT
#endif
/* MBEDTLS_SHAxx_ALT to enable hardware SHA support /* MBEDTLS_SHAxx_ALT to enable hardware SHA support
with software fallback. with software fallback.
*/ */

View file

@ -29,6 +29,30 @@ extern "C" {
#if defined(MBEDTLS_SHA1_ALT) #if defined(MBEDTLS_SHA1_ALT)
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/sha.h"
typedef enum {
ESP_SHA1_STATE_INIT,
ESP_SHA1_STATE_IN_PROCESS
} esp_sha1_state;
/**
* \brief SHA-1 context structure
*/
typedef struct {
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[5]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
int first_block; /*!< if first then true else false */
esp_sha_type mode;
esp_sha1_state sha_state;
} mbedtls_sha1_context;
#endif //CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32
typedef enum { typedef enum {
ESP_MBEDTLS_SHA1_UNUSED, /* first block hasn't been processed yet */ ESP_MBEDTLS_SHA1_UNUSED, /* first block hasn't been processed yet */
ESP_MBEDTLS_SHA1_HARDWARE, /* using hardware SHA engine */ ESP_MBEDTLS_SHA1_HARDWARE, /* using hardware SHA engine */
@ -38,8 +62,7 @@ typedef enum {
/** /**
* \brief SHA-1 context structure * \brief SHA-1 context structure
*/ */
typedef struct typedef struct {
{
uint32_t total[2]; /*!< number of bytes processed */ uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[5]; /*!< intermediate digest state */ uint32_t state[5]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */ unsigned char buffer[64]; /*!< data block being processed */
@ -47,6 +70,8 @@ typedef struct
} }
mbedtls_sha1_context; mbedtls_sha1_context;
#endif //CONFIG_IDF_TARGET_ESP32
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -29,6 +29,33 @@ extern "C" {
#if defined(MBEDTLS_SHA256_ALT) #if defined(MBEDTLS_SHA256_ALT)
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/sha.h"
typedef enum {
ESP_SHA256_STATE_INIT,
ESP_SHA256_STATE_IN_PROCESS
} esp_sha256_state;
/**
* \brief SHA-256 context structure
*/
typedef struct {
uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[8]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */
int first_block; /*!< if first then true, else false */
esp_sha_type mode;
esp_sha256_state sha_state;
}
mbedtls_sha256_context;
#endif //CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32
typedef enum { typedef enum {
ESP_MBEDTLS_SHA256_UNUSED, /* first block hasn't been processed yet */ ESP_MBEDTLS_SHA256_UNUSED, /* first block hasn't been processed yet */
ESP_MBEDTLS_SHA256_HARDWARE, /* using hardware SHA engine */ ESP_MBEDTLS_SHA256_HARDWARE, /* using hardware SHA engine */
@ -38,8 +65,7 @@ typedef enum {
/** /**
* \brief SHA-256 context structure * \brief SHA-256 context structure
*/ */
typedef struct typedef struct {
{
uint32_t total[2]; /*!< number of bytes processed */ uint32_t total[2]; /*!< number of bytes processed */
uint32_t state[8]; /*!< intermediate digest state */ uint32_t state[8]; /*!< intermediate digest state */
unsigned char buffer[64]; /*!< data block being processed */ unsigned char buffer[64]; /*!< data block being processed */
@ -48,6 +74,8 @@ typedef struct
} }
mbedtls_sha256_context; mbedtls_sha256_context;
#endif //CONFIG_IDF_TARGET_ESP32
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -23,12 +23,51 @@
#ifndef _SHA512_ALT_H_ #ifndef _SHA512_ALT_H_
#define _SHA512_ALT_H_ #define _SHA512_ALT_H_
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
#endif #endif
#if defined(MBEDTLS_SHA512_ALT) #if defined(MBEDTLS_SHA512_ALT)
#if CONFIG_IDF_TARGET_ESP32S2
#include "esp32s2/sha.h"
typedef enum {
ESP_SHA512_STATE_INIT,
ESP_SHA512_STATE_IN_PROCESS
} esp_sha512_state;
/**
* \brief SHA-512 context structure
*/
typedef struct {
uint64_t total[2]; /*!< number of bytes processed */
uint64_t state[8]; /*!< intermediate digest state */
unsigned char buffer[128]; /*!< data block being processed */
int first_block;
esp_sha_type mode;
uint32_t t_val; /*!< t_val for 512/t mode */
esp_sha512_state sha_state;
} mbedtls_sha512_context;
/**
* @brief Sets the specfic algorithm for SHA512
*
* @param ctx The mbedtls sha512 context
*
* @param type The mode, used for setting SHA2_512224 and SHA2_512256:
*
*/
void esp_sha512_set_mode(mbedtls_sha512_context *ctx, esp_sha_type type);
/* For SHA512/t mode the intial hash value will depend on t */
void esp_sha512_set_t( mbedtls_sha512_context *ctx, uint16_t t_val);
#endif //CONFIG_IDF_TARGET_ESP32S2
#if CONFIG_IDF_TARGET_ESP32
typedef enum { typedef enum {
ESP_MBEDTLS_SHA512_UNUSED, /* first block hasn't been processed yet */ ESP_MBEDTLS_SHA512_UNUSED, /* first block hasn't been processed yet */
ESP_MBEDTLS_SHA512_HARDWARE, /* using hardware SHA engine */ ESP_MBEDTLS_SHA512_HARDWARE, /* using hardware SHA engine */
@ -38,8 +77,7 @@ typedef enum {
/** /**
* \brief SHA-512 context structure * \brief SHA-512 context structure
*/ */
typedef struct typedef struct {
{
uint64_t total[2]; /*!< number of bytes processed */ uint64_t total[2]; /*!< number of bytes processed */
uint64_t state[8]; /*!< intermediate digest state */ uint64_t state[8]; /*!< intermediate digest state */
unsigned char buffer[128]; /*!< data block being processed */ unsigned char buffer[128]; /*!< data block being processed */
@ -48,6 +86,8 @@ typedef struct
} }
mbedtls_sha512_context; mbedtls_sha512_context;
#endif //CONFIG_IDF_TARGET_ESP32
#endif #endif
#ifdef __cplusplus #ifdef __cplusplus

File diff suppressed because it is too large Load diff

View file

@ -5,6 +5,7 @@
#include <stdbool.h> #include <stdbool.h>
#include <esp_system.h> #include <esp_system.h>
#include "mbedtls/aes.h" #include "mbedtls/aes.h"
#include "mbedtls/gcm.h"
#include "unity.h" #include "unity.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#include "esp_timer.h" #include "esp_timer.h"
@ -63,9 +64,65 @@ TEST_CASE("mbedtls AES performance", "[aes]")
float mb_sec = (CALL_SZ * CALLS) / usecs; float mb_sec = (CALL_SZ * CALLS) / usecs;
printf("Encryption rate %.3fMB/sec\n", mb_sec); printf("Encryption rate %.3fMB/sec\n", mb_sec);
#ifdef CONFIG_MBEDTLS_HARDWARE_AES #ifdef CONFIG_MBEDTLS_HARDWARE_AES
// Don't put a hard limit on software AES performance (software is approx 2.3MB/sec on Release config) // Don't put a hard limit on software AES performance
TEST_PERFORMANCE_GREATER_THAN(AES_CBC_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec); TEST_PERFORMANCE_GREATER_THAN(AES_CBC_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
#endif #endif
} }
TEST_CASE("mbedtls AES GCM performance", "[aes]")
{
const unsigned CALLS = 1;
const unsigned CALL_SZ = 32 * 1024;
mbedtls_gcm_context ctx;
int64_t start, end;
unsigned char tag_buf[16];
mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES;
uint8_t iv[16];
uint8_t key[16];
memset(iv, 0xEE, 16);
memset(key, 0x44, 16);
// allocate internal memory
uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_8BIT | MALLOC_CAP_INTERNAL);
TEST_ASSERT_NOT_NULL(buf);
mbedtls_gcm_init(&ctx);
mbedtls_gcm_setkey( &ctx, cipher, key, 128);
start = esp_timer_get_time();
for (int c = 0; c < CALLS; c++) {
memset(buf, 0xAA, CALL_SZ);
mbedtls_gcm_crypt_and_tag(&ctx, MBEDTLS_AES_ENCRYPT, CALL_SZ, iv, sizeof(iv), NULL, 0, buf, buf, 16, tag_buf);
}
end = esp_timer_get_time();
/* Sanity check: make sure the last ciphertext block matches
what we expect to see.
Last block produced via this Python:
import os, binascii
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.backends import default_backend
key = b'\x44' * 16
iv = b'\xee' * 16
cipher = Cipher(algorithms.AES(key), modes.GCM(iv), backend=default_backend())
encryptor = cipher.encryptor()
ct = encryptor.update(b'\xaa' * 1 * 32 * 1024) + encryptor.finalize()
print(binascii.hexlify(ct[-16:]))
*/
const uint8_t expected_last_block[] = {
0x7d, 0x3d, 0x16, 0x84, 0xd0, 0xb4, 0x38, 0x30,
0xd1, 0x24, 0x6f, 0x7e, 0x9a, 0x9c, 0x81, 0x58,
};
TEST_ASSERT_EQUAL_HEX8_ARRAY(expected_last_block, buf + CALL_SZ - 16, 16);
free(buf);
float usecs = end - start;
// bytes/usec = MB/sec
float mb_sec = (CALL_SZ * CALLS) / usecs;
printf("GCM encryption rate %.3fMB/sec\n", mb_sec);
}

View file

@ -14,6 +14,7 @@
#include "unity.h" #include "unity.h"
#include "sdkconfig.h" #include "sdkconfig.h"
#include "test_apb_dport_access.h" #include "test_apb_dport_access.h"
#include "sodium/utils.h"
TEST_CASE("mbedtls SHA self-tests", "[mbedtls]") TEST_CASE("mbedtls SHA self-tests", "[mbedtls]")
{ {
@ -21,7 +22,6 @@ TEST_CASE("mbedtls SHA self-tests", "[mbedtls]")
TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha1_self_test(1), "SHA1 self-tests should pass."); 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_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.");
TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha512_self_test(1), "SHA512 self-tests should pass.");
verify_apb_access_loop(); verify_apb_access_loop();
} }
@ -33,7 +33,8 @@ static const unsigned char *one_hundred_bs = (unsigned char *)
static const uint8_t sha256_thousand_as[32] = { static const uint8_t sha256_thousand_as[32] = {
0x41, 0xed, 0xec, 0xe4, 0x2d, 0x63, 0xe8, 0xd9, 0xbf, 0x51, 0x5a, 0x9b, 0xa6, 0x93, 0x2e, 0x1c, 0x41, 0xed, 0xec, 0xe4, 0x2d, 0x63, 0xe8, 0xd9, 0xbf, 0x51, 0x5a, 0x9b, 0xa6, 0x93, 0x2e, 0x1c,
0x20, 0xcb, 0xc9, 0xf5, 0xa5, 0xd1, 0x34, 0x64, 0x5a, 0xdb, 0x5d, 0xb1, 0xb9, 0x73, 0x7e, 0xa3 }; 0x20, 0xcb, 0xc9, 0xf5, 0xa5, 0xd1, 0x34, 0x64, 0x5a, 0xdb, 0x5d, 0xb1, 0xb9, 0x73, 0x7e, 0xa3
};
static const uint8_t sha256_thousand_bs[32] = { static const uint8_t sha256_thousand_bs[32] = {
0xf6, 0xf1, 0x18, 0xe1, 0x20, 0xe5, 0x2b, 0xe0, 0xbd, 0x0c, 0xfd, 0xf2, 0x79, 0x4c, 0xd1, 0x2c, 0x07, 0x68, 0x6c, 0xc8, 0x71, 0x23, 0x5a, 0xc2, 0xf1, 0x14, 0x59, 0x37, 0x8e, 0x6d, 0x23, 0x5b 0xf6, 0xf1, 0x18, 0xe1, 0x20, 0xe5, 0x2b, 0xe0, 0xbd, 0x0c, 0xfd, 0xf2, 0x79, 0x4c, 0xd1, 0x2c, 0x07, 0x68, 0x6c, 0xc8, 0x71, 0x23, 0x5a, 0xc2, 0xf1, 0x14, 0x59, 0x37, 0x8e, 0x6d, 0x23, 0x5b
@ -49,7 +50,9 @@ static const uint8_t sha384_thousand_bs[48] = {
static const uint8_t sha1_thousand_as[20] = { static const uint8_t sha1_thousand_as[20] = {
0x29, 0x1e, 0x9a, 0x6c, 0x66, 0x99, 0x49, 0x49, 0xb5, 0x7b, 0xa5, 0x29, 0x1e, 0x9a, 0x6c, 0x66, 0x99, 0x49, 0x49, 0xb5, 0x7b, 0xa5,
0xe6, 0x50, 0x36, 0x1e, 0x98, 0xfc, 0x36, 0xb1, 0xba }; 0xe6, 0x50, 0x36, 0x1e, 0x98, 0xfc, 0x36, 0xb1, 0xba
};
TEST_CASE("mbedtls SHA interleaving", "[mbedtls]") TEST_CASE("mbedtls SHA interleaving", "[mbedtls]")
{ {
@ -164,7 +167,6 @@ void tskRunSHASelftests(void *param)
vTaskDelete(NULL); vTaskDelete(NULL);
} }
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
TEST_CASE("mbedtls SHA self-tests multithreaded", "[mbedtls]") TEST_CASE("mbedtls SHA self-tests multithreaded", "[mbedtls]")
{ {
done_sem = xSemaphoreCreateCounting(2, 0); done_sem = xSemaphoreCreateCounting(2, 0);
@ -180,7 +182,6 @@ TEST_CASE("mbedtls SHA self-tests multithreaded", "[mbedtls]")
} }
vSemaphoreDelete(done_sem); vSemaphoreDelete(done_sem);
} }
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
TEST_CASE("mbedtls SHA512 clone", "[mbedtls]") TEST_CASE("mbedtls SHA512 clone", "[mbedtls]")
{ {
@ -207,10 +208,11 @@ TEST_CASE("mbedtls SHA512 clone", "[mbedtls]")
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 cloned calculation"); TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_thousand_bs, sha512, 64, "SHA512 cloned calculation");
} }
TEST_CASE("mbedtls SHA384 clone", "[mbedtls]") TEST_CASE("mbedtls SHA384 clone", "[mbedtls][")
{ {
mbedtls_sha512_context ctx; mbedtls_sha512_context ctx;
mbedtls_sha512_context clone; mbedtls_sha512_context clone;
unsigned char sha384[48]; unsigned char sha384[48];
mbedtls_sha512_init(&ctx); mbedtls_sha512_init(&ctx);
@ -220,12 +222,12 @@ TEST_CASE("mbedtls SHA384 clone", "[mbedtls]")
} }
mbedtls_sha512_clone(&clone, &ctx); mbedtls_sha512_clone(&clone, &ctx);
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&ctx, one_hundred_bs, 100)); TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&ctx, one_hundred_bs, 100));
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&clone, one_hundred_bs, 100)); TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&clone, one_hundred_bs, 100));
} }
TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish_ret(&ctx, sha384)); TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish_ret(&ctx, sha384));
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha384_thousand_bs, sha384, 48, "SHA512 original calculation"); TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha384_thousand_bs, sha384, 48, "SHA512 original calculation");
TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish_ret(&clone, sha384)); TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish_ret(&clone, sha384));
@ -258,7 +260,6 @@ TEST_CASE("mbedtls SHA256 clone", "[mbedtls]")
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, sha256, 32, "SHA256 cloned calculation"); TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, sha256, 32, "SHA256 cloned calculation");
} }
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
typedef struct { typedef struct {
mbedtls_sha256_context ctx; mbedtls_sha256_context ctx;
uint8_t result[32]; uint8_t result[32];
@ -279,7 +280,7 @@ static void tskFinaliseSha(void *v_param)
vTaskDelete(NULL); vTaskDelete(NULL);
} }
// No concurrent SHA sessions in esp32s2, only has one engine
TEST_CASE("mbedtls SHA session passed between tasks", "[mbedtls]") TEST_CASE("mbedtls SHA session passed between tasks", "[mbedtls]")
{ {
finalise_sha_param_t param = { 0 }; finalise_sha_param_t param = { 0 };
@ -303,4 +304,130 @@ TEST_CASE("mbedtls SHA session passed between tasks" , "[mbedtls]")
TEST_ASSERT_EQUAL(0, param.ret); TEST_ASSERT_EQUAL(0, param.ret);
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, param.result, 32, "SHA256 result from other task"); TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha256_thousand_as, param.result, 32, "SHA256 result from other task");
} }
#endif
/* ESP32 do not have SHA512/t functions */
#if !DISABLED_FOR_TARGETS(ESP32)
/* Function are not implemented in SW */
#ifdef CONFIG_MBEDTLS_HARDWARE_SHA
/*
* FIPS-180-2 test vectors
*/
static unsigned char sha512T_test_buf[2][113] = {
{ "abc" },
{
"abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn"
"hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu"
}
};
static const size_t sha512T_test_buflen[2] = {
3, 112
};
static const esp_sha_type sha512T_algo[4] = {
SHA2_512224, SHA2_512256, SHA2_512T, SHA2_512T
};
static const size_t sha512T_t_len[4] = { 224, 256, 224, 256 };
static const unsigned char sha512_test_sum[4][32] = {
/* SHA512-224 */
{
0x46, 0x34, 0x27, 0x0f, 0x70, 0x7b, 0x6a, 0x54,
0xda, 0xae, 0x75, 0x30, 0x46, 0x08, 0x42, 0xe2,
0x0e, 0x37, 0xed, 0x26, 0x5c, 0xee, 0xe9, 0xa4,
0x3e, 0x89, 0x24, 0xaa
},
{
0x23, 0xfe, 0xc5, 0xbb, 0x94, 0xd6, 0x0b, 0x23,
0x30, 0x81, 0x92, 0x64, 0x0b, 0x0c, 0x45, 0x33,
0x35, 0xd6, 0x64, 0x73, 0x4f, 0xe4, 0x0e, 0x72,
0x68, 0x67, 0x4a, 0xf9
},
/* SHA512-256 */
{
0x53, 0x04, 0x8e, 0x26, 0x81, 0x94, 0x1e, 0xf9,
0x9b, 0x2e, 0x29, 0xb7, 0x6b, 0x4c, 0x7d, 0xab,
0xe4, 0xc2, 0xd0, 0xc6, 0x34, 0xfc, 0x6d, 0x46,
0xe0, 0xe2, 0xf1, 0x31, 0x07, 0xe7, 0xaf, 0x23
},
{
0x39, 0x28, 0xe1, 0x84, 0xfb, 0x86, 0x90, 0xf8,
0x40, 0xda, 0x39, 0x88, 0x12, 0x1d, 0x31, 0xbe,
0x65, 0xcb, 0x9d, 0x3e, 0xf8, 0x3e, 0xe6, 0x14,
0x6f, 0xea, 0xc8, 0x61, 0xe1, 0x9b, 0x56, 0x3a
}
/* For SHA512_T testing we use t=224 & t=256
* so the hash digest should be same as above
*/
};
/* This will run total of 8 test cases, 2 for each of the below MODE
* SHA512/224, SHA512/256, SHA512/t with t=224 & SHA512/t with t=256
*
* Test is disabled for ESP32 as there is no hardware for SHA512/t
*/
TEST_CASE("mbedtls SHA512/t", "[mbedtls]")
{
mbedtls_sha512_context sha512_ctx;
unsigned char sha512[64], k;
for (int i = 0; i < 4; i++) {
for (int j = 0; j < 2; j++) {
k = i * 2 + j;
mbedtls_sha512_init(&sha512_ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha512_starts_ret(&sha512_ctx, false));
esp_sha512_set_mode(&sha512_ctx, sha512T_algo[i]);
if (i > 1) {
k = (i - 2) * 2 + j;
esp_sha512_set_t(&sha512_ctx, sha512T_t_len[i]);
}
TEST_ASSERT_EQUAL(0, mbedtls_sha512_update_ret(&sha512_ctx, sha512T_test_buf[j], sha512T_test_buflen[j]));
TEST_ASSERT_EQUAL(0, mbedtls_sha512_finish_ret(&sha512_ctx, sha512));
TEST_ASSERT_EQUAL_MEMORY_MESSAGE(sha512_test_sum[k], sha512, sha512T_t_len[i] / 8, "SHA512t calculation");
}
}
}
#ifdef CONFIG_SPIRAM
TEST_CASE("mbedtls SHA256 PSRAM DMA", "[mbedtls]")
{
const unsigned CALLS = 256;
const unsigned CALL_SZ = 16 * 1024;
mbedtls_sha256_context sha256_ctx;
unsigned char sha256[32];
// allocate internal memory
uint8_t *buf = heap_caps_malloc(CALL_SZ, MALLOC_CAP_SPIRAM);
TEST_ASSERT(esp_ptr_external_ram(buf));
memset(buf, 0x54, CALL_SZ);
mbedtls_sha256_init(&sha256_ctx);
TEST_ASSERT_EQUAL(0, mbedtls_sha256_starts_ret(&sha256_ctx, false));
for (int c = 0; c < CALLS; c++) {
TEST_ASSERT_EQUAL(0, mbedtls_sha256_update_ret(&sha256_ctx, buf, CALL_SZ));
}
TEST_ASSERT_EQUAL(0, mbedtls_sha256_finish_ret(&sha256_ctx, sha256));
free(buf);
mbedtls_sha256_free(&sha256_ctx);
/* Check the result. Reference value can be calculated using:
* dd if=/dev/zero bs=$((16*1024)) count=256 | tr '\000' '\124' | sha256sum
*/
const char *expected_hash = "8d031167bd706ac337e07aa9129c34ae4ae792d0a79a2c70e7f012102e8adc3d";
char hash_str[sizeof(sha256) * 2 + 1];
sodium_bin2hex(hash_str, sizeof(hash_str), sha256, sizeof(sha256));
TEST_ASSERT_EQUAL_STRING(expected_hash, hash_str);
}
#endif //CONFIG_SPIRAM
#endif //CONFIG_MBEDTLS_HARDWARE_SHA
#endif //!DISABLED_FOR_TARGETS(ESP32S2)

View file

@ -49,7 +49,7 @@ TEST_CASE("mbedtls SHA performance", "[aes]")
// bytes/usec = MB/sec // bytes/usec = MB/sec
float mb_sec = (CALL_SZ * CALLS) / usecs; float mb_sec = (CALL_SZ * CALLS) / usecs;
printf("SHA256 rate %.3fMB/sec\n", mb_sec); printf("SHA256 rate %.3fMB/sec\n", mb_sec);
#ifdef CONFIG_MBEDTLS_HARDWARE #ifdef CONFIG_MBEDTLS_HARDWARE_SHA
// Don't put a hard limit on software SHA performance // Don't put a hard limit on software SHA performance
TEST_PERFORMANCE_GREATER_THAN(SHA256_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec); TEST_PERFORMANCE_GREATER_THAN(SHA256_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
#endif #endif

View file

@ -145,6 +145,15 @@ inline static bool IRAM_ATTR esp_ptr_dma_capable(const void *p)
return (intptr_t)p >= SOC_DMA_LOW && (intptr_t)p < SOC_DMA_HIGH; return (intptr_t)p >= SOC_DMA_LOW && (intptr_t)p < SOC_DMA_HIGH;
} }
inline static bool IRAM_ATTR esp_ptr_dma_ext_capable(const void *p)
{
#if CONFIG_IDF_TARGET_ESP32S2
return (intptr_t)p >= SOC_DMA_EXT_LOW && (intptr_t)p < SOC_DMA_EXT_HIGH;
#else
return false;
#endif
}
inline static bool IRAM_ATTR esp_ptr_word_aligned(const void *p) inline static bool IRAM_ATTR esp_ptr_word_aligned(const void *p)
{ {
return ((intptr_t)p) % 4 == 0; return ((intptr_t)p) % 4 == 0;

View file

@ -69,24 +69,6 @@
#define SHA_H_BASE ((DR_REG_SHA_BASE) + 0x40) #define SHA_H_BASE ((DR_REG_SHA_BASE) + 0x40)
#define SHA_TEXT_BASE ((DR_REG_SHA_BASE) + 0x80) #define SHA_TEXT_BASE ((DR_REG_SHA_BASE) + 0x80)
/* AES Block operation modes */
#define AES_BLOCK_MODE_ECB 0
#define AES_BLOCK_MODE_CBC 1
#define AES_BLOCK_MODE_OFB 2
#define AES_BLOCK_MODE_CTR 3
#define AES_BLOCK_MODE_CFB8 4
#define AES_BLOCK_MODE_CFB128 5
#define AES_BLOCK_MODE_GCM 6
/* AES Block operation modes (used with DMA) */
#define AES_BLOCK_MODE_ECB 0
#define AES_BLOCK_MODE_CBC 1
#define AES_BLOCK_MODE_OFB 2
#define AES_BLOCK_MODE_CTR 3
#define AES_BLOCK_MODE_CFB8 4
#define AES_BLOCK_MODE_CFB128 5
#define AES_BLOCK_MODE_GCM 6
/* AES acceleration registers */ /* AES acceleration registers */
#define AES_MODE_REG ((DR_REG_AES_BASE) + 0x40) #define AES_MODE_REG ((DR_REG_AES_BASE) + 0x40)
#define AES_ENDIAN_REG ((DR_REG_AES_BASE) + 0x44) #define AES_ENDIAN_REG ((DR_REG_AES_BASE) + 0x44)

View file

@ -48,6 +48,12 @@ typedef enum {
PERIPH_WIFI_MODULE, PERIPH_WIFI_MODULE,
PERIPH_WIFI_BT_COMMON_MODULE, PERIPH_WIFI_BT_COMMON_MODULE,
PERIPH_SYSTIMER_MODULE, PERIPH_SYSTIMER_MODULE,
PERIPH_AES_MODULE,
PERIPH_SHA_MODULE,
PERIPH_RSA_MODULE,
PERIPH_CRYPTO_DMA_MODULE, //this DMA is shared between AES and SHA
PERIPH_AES_DMA_MODULE,
PERIPH_SHA_DMA_MODULE,
} periph_module_t; } periph_module_t;
typedef enum { typedef enum {

View file

@ -270,10 +270,14 @@
#define SOC_DIRAM_DRAM_LOW 0x3FFB0000 #define SOC_DIRAM_DRAM_LOW 0x3FFB0000
#define SOC_DIRAM_DRAM_HIGH 0x40000000 #define SOC_DIRAM_DRAM_HIGH 0x40000000
// Region of memory accessible via DMA. See esp_ptr_dma_capable(). // Region of memory accessible via DMA in internal memory. See esp_ptr_dma_capable().
#define SOC_DMA_LOW 0x3FFB0000 #define SOC_DMA_LOW 0x3FFB0000
#define SOC_DMA_HIGH 0x40000000 #define SOC_DMA_HIGH 0x40000000
// Region of memory accessible via DMA in external memory. See esp_ptr_dma_ext_capable().
#define SOC_DMA_EXT_LOW 0x3F500000
#define SOC_DMA_EXT_HIGH 0x3FF80000
// Region of memory that is byte-accessible. See esp_ptr_byte_accessible(). // Region of memory that is byte-accessible. See esp_ptr_byte_accessible().
#define SOC_BYTE_ACCESSIBLE_LOW 0x3FF9E000 #define SOC_BYTE_ACCESSIBLE_LOW 0x3FF9E000
#define SOC_BYTE_ACCESSIBLE_HIGH 0x40000000 #define SOC_BYTE_ACCESSIBLE_HIGH 0x40000000

View file

@ -84,6 +84,18 @@ static inline uint32_t periph_ll_get_clk_en_mask(periph_module_t periph)
return DPORT_WIFI_CLK_WIFI_BT_COMMON_M; return DPORT_WIFI_CLK_WIFI_BT_COMMON_M;
case PERIPH_SYSTIMER_MODULE: case PERIPH_SYSTIMER_MODULE:
return DPORT_SYSTIMER_CLK_EN; return DPORT_SYSTIMER_CLK_EN;
case PERIPH_AES_MODULE:
return DPORT_CRYPTO_AES_CLK_EN;
case PERIPH_SHA_MODULE:
return DPORT_CRYPTO_SHA_CLK_EN;
case PERIPH_RSA_MODULE:
return DPORT_CRYPTO_RSA_CLK_EN;
case PERIPH_CRYPTO_DMA_MODULE:
return DPORT_CRYPTO_DMA_CLK_EN;
case PERIPH_SHA_DMA_MODULE:
return DPORT_CRYPTO_DMA_CLK_EN | DPORT_CRYPTO_SHA_CLK_EN;
case PERIPH_AES_DMA_MODULE:
return DPORT_CRYPTO_DMA_CLK_EN | DPORT_CRYPTO_AES_CLK_EN;
default: default:
return 0; return 0;
} }
@ -144,6 +156,49 @@ static inline uint32_t periph_ll_get_rst_en_mask(periph_module_t periph, bool en
return DPORT_CAN_RST; return DPORT_CAN_RST;
case PERIPH_SYSTIMER_MODULE: case PERIPH_SYSTIMER_MODULE:
return DPORT_SYSTIMER_RST; return DPORT_SYSTIMER_RST;
case PERIPH_AES_MODULE:
if (enable == true) {
// Clear reset on digital signature, otherwise AES unit is held in reset also.
return (DPORT_CRYPTO_AES_RST | DPORT_CRYPTO_DS_RST);
} else {
//Don't return other units to reset, as this pulls reset on RSA & SHA units, respectively.
return DPORT_CRYPTO_AES_RST;
}
case PERIPH_SHA_MODULE:
if (enable == true) {
// Clear reset on digital signature and HMAC, otherwise SHA is held in reset
return (DPORT_CRYPTO_SHA_RST | DPORT_CRYPTO_DS_RST | DPORT_CRYPTO_HMAC_RST);
} else {
// Don't assert reset on secure boot, otherwise AES is held in reset
return DPORT_CRYPTO_SHA_RST;
}
case PERIPH_RSA_MODULE:
if (enable == true) {
// Also clear reset on digital signature, otherwise RSA is held in reset
return (DPORT_CRYPTO_RSA_RST | DPORT_CRYPTO_DS_RST);
} else {
// Don't reset digital signature unit, as this resets AES also
return DPORT_CRYPTO_RSA_RST;
}
case PERIPH_CRYPTO_DMA_MODULE:
return DPORT_CRYPTO_DMA_RST;
case PERIPH_AES_DMA_MODULE:
if (enable == true) {
// Clear reset on digital signature, otherwise AES unit is held in reset also.
return (DPORT_CRYPTO_AES_RST | DPORT_CRYPTO_DS_RST | DPORT_CRYPTO_DMA_RST);
} else {
//Don't return other units to reset, as this pulls reset on RSA & SHA units, respectively.
return (DPORT_CRYPTO_AES_RST | DPORT_CRYPTO_DMA_RST);
}
case PERIPH_SHA_DMA_MODULE:
if (enable == true) {
// Clear reset on digital signature and HMAC, otherwise SHA is held in reset
return (DPORT_CRYPTO_SHA_RST | DPORT_CRYPTO_DS_RST | DPORT_CRYPTO_HMAC_RST | DPORT_CRYPTO_DMA_RST);
} else {
// Don't assert reset on secure boot, otherwise AES is held in reset
return (DPORT_CRYPTO_SHA_RST | DPORT_CRYPTO_DMA_RST);
}
default: default:
return 0; return 0;
} }
@ -156,6 +211,13 @@ static inline uint32_t periph_ll_get_clk_en_reg(periph_module_t periph)
case PERIPH_WIFI_MODULE: case PERIPH_WIFI_MODULE:
case PERIPH_WIFI_BT_COMMON_MODULE: case PERIPH_WIFI_BT_COMMON_MODULE:
return DPORT_WIFI_CLK_EN_REG; return DPORT_WIFI_CLK_EN_REG;
case PERIPH_AES_MODULE:
case PERIPH_SHA_MODULE:
case PERIPH_RSA_MODULE:
case PERIPH_CRYPTO_DMA_MODULE:
case PERIPH_AES_DMA_MODULE:
case PERIPH_SHA_DMA_MODULE:
return DPORT_PERIP_CLK_EN1_REG;
default: default:
return DPORT_PERIP_CLK_EN_REG; return DPORT_PERIP_CLK_EN_REG;
} }
@ -168,6 +230,13 @@ static inline uint32_t periph_ll_get_rst_en_reg(periph_module_t periph)
case PERIPH_WIFI_MODULE: case PERIPH_WIFI_MODULE:
case PERIPH_WIFI_BT_COMMON_MODULE: case PERIPH_WIFI_BT_COMMON_MODULE:
return DPORT_CORE_RST_EN_REG; return DPORT_CORE_RST_EN_REG;
case PERIPH_AES_MODULE:
case PERIPH_SHA_MODULE:
case PERIPH_RSA_MODULE:
case PERIPH_CRYPTO_DMA_MODULE:
case PERIPH_AES_DMA_MODULE:
case PERIPH_SHA_DMA_MODULE:
return DPORT_PERIP_RST_EN1_REG;
default: default:
return DPORT_PERIP_RST_EN_REG; return DPORT_PERIP_RST_EN_REG;
} }