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"
"${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_sha.c"
"${COMPONENT_DIR}/port/esp_aes_xts.c"
"${COMPONENT_DIR}/port/${idf_target}/esp_bignum.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})
target_compile_definitions(${target} PUBLIC -DMBEDTLS_CONFIG_FILE="mbedtls/esp_config.h")

View file

@ -189,13 +189,33 @@ menu "mbedTLS"
config MBEDTLS_HARDWARE_AES
bool "Enable hardware AES acceleration"
default y
depends on !IDF_TARGET_ESP32S2
help
Enable hardware accelerated AES encryption & decryption.
Note that if the ESP32 CPU is running at 240MHz, hardware AES does not
offer any speed boost over software AES.
config MBEDTLS_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
bool "Enable hardware MPI (bignum) acceleration"
default y
@ -211,11 +231,10 @@ menu "mbedTLS"
config MBEDTLS_HARDWARE_SHA
bool "Enable hardware SHA acceleration"
default y
depends on !IDF_TARGET_ESP32S2
help
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
than one SHA digest is calculated at the same time, one will
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 );
}
/* 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.
*
* 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
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -28,34 +28,38 @@
#include <string.h>
#include <stdio.h>
#include <sys/lock.h>
#include <assert.h>
#include "soc/soc.h"
#include "esp32s2/crypto_dma.h"
#include "esp32s2/sha.h"
#include "soc/crypto_dma_reg.h"
#include "esp_log.h"
#include "esp32s2/rom/ets_sys.h"
#include "soc/dport_reg.h"
#include "soc/hwcrypto_reg.h"
#include "esp32s2/rom/lldesc.h"
#include "esp32s2/rom/cache.h"
#include "esp_intr_alloc.h"
#include "esp_log.h"
#include "soc/periph_defs.h"
#include "soc/cache_memory.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.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;
/* Enable if want to use SHA interrupt */
//#define CONFIG_MBEDTLS_SHA_USE_INTERRUPT
#if defined(CONFIG_MBEDTLS_SHA_USE_INTERRUPT)
static SemaphoreHandle_t op_complete_sem;
#endif
const static char *TAG = "esp-sha";
/* Return block size (in bytes) for a given SHA 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
engines for SHA1,256,512. ESP32C has a single engine.
*/
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)
/* Enable SHA peripheral and then lock it */
void esp_sha_acquire_hardware()
{
/* 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);
REG_CLR_BIT(DPORT_PERIP_RST_EN1_REG, DPORT_CRYPTO_SHA_RST | DPORT_CRYPTO_HMAC_RST |
DPORT_CRYPTO_DMA_RST | DPORT_CRYPTO_DS_RST);
/* Enable SHA and DMA hardware */
periph_module_enable(PERIPH_SHA_DMA_MODULE);
/* DMA for SHA */
REG_WRITE(CRYPTO_DMA_AES_SHA_SELECT_REG, 1);
}
/* Disable SHA block and then unlock it */
void esp_sha_unlock_engine(esp_sha_type sha_type)
/* Disable SHA peripheral block and then release it */
void esp_sha_release_hardware()
{
REG_WRITE(CRYPTO_DMA_AES_SHA_SELECT_REG, 0);
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);
/* Disable SHA and DMA hardware */
periph_module_disable(PERIPH_SHA_DMA_MODULE);
/* Need to lock DMA since it is shared with AES block */
_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 */
static int esp_sha_dma_complete(void)
/* Busy wait until SHA is idle */
static void esp_sha_wait_idle(void)
{
#if defined (CONFIG_MBEDTLS_SHA_USE_INTERRUPT)
if (!xSemaphoreTake(op_complete_sem, 2000 / portTICK_PERIOD_MS)) {
ESP_LOGE("SHA", "Timed out waiting for completion of SHA Interrupt");
return -1;
while (DPORT_REG_READ(SHA_BUSY_REG) != 0) {
}
#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 */
void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state)
{
esp_sha_wait_idle();
memcpy(digest_state, (void *)SHA_H_BASE, state_length(sha_type));
uint32_t *digest_state_words = (uint32_t *)digest_state;
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 */
void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block)
/* The initial hash value for SHA512/t is generated according to the
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 */
int esp_sha_dma(esp_sha_type sha_type, const void *data_block, uint32_t ilen, bool is_first_block)
{
size_t blk_len = 0;
const uint8_t *local_buf = data_block;
int ret = 0;
volatile lldesc_t dma_descr;
if (ilen == 0) {
return ret;
if (t <= 9) {
t_string = (uint32_t)((1 << 23) | ((0x30 + t) << 24));
t_len = 0x48;
} else if (t <= 99) {
t0 = t % 10;
t1 = (t / 10) % 10;
t_string = (uint32_t)((1 << 15) | ((0x30 + t0) << 16) |
(((0x30 + t1) << 24)));
t_len = 0x50;
} 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_MODE_REG, sha_type);
if ((sha_type == SHA2_512T) && (is_first_block == true)) {
REG_WRITE(SHA_T_LENGTH_REG, t_len);
REG_WRITE(SHA_T_STRING_REG, t_string);
REG_WRITE(SHA_MODE_REG, SHA2_512T);
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();
is_first_block = false;
return 0;
}
bzero( (void *)&dma_descr, sizeof( dma_descr ) );
/* DMA descriptor for Memory to DMA-AES transfer */
dma_descr.length = ilen;
dma_descr.size = ilen;
dma_descr.owner = 1;
dma_descr.eof = 1;
dma_descr.buf = local_buf;
dma_descr.sosf = 0;
dma_descr.empty = 0;
static int 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);
/* Performs SHA on multiple blocks at a time using DMA
splits up into smaller operations for inputs that exceed a single DMA list
*/
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)
{
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 ((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();
}
#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 */
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);
/* Set descriptors */
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 */
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) {
REG_WRITE(SHA_DMA_START_REG, 1);
} else {
REG_WRITE(SHA_DMA_CONTINUE_REG, 1);
}
ret = esp_sha_dma_complete();
#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
esp_sha_wait_idle();
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>
#if CONFIG_IDF_TARGET_ESP32
void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output)
{
int ret;
@ -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.
*
* 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
*
* 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_INPUT_LENGTH -0x0022 /**< Invalid data input length. */
/**
* \brief AES context structure
*
@ -52,11 +53,11 @@ typedef struct {
uint8_t key[32];
} esp_aes_context;
/**
* \brief The AES XTS context-type definition.
*/
typedef struct
{
typedef struct {
esp_aes_context crypt; /*!< The AES context to use for AES block
encryption or decryption. */
esp_aes_context tweak; /*!< The AES context used for tweak

View file

@ -31,7 +31,7 @@ extern "C" {
/* Since crypto DMA is shared between DMA-AES and SHA blocks
* 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
}

View file

@ -3,7 +3,7 @@
* Based on mbedTLS FIPS-197 compliant version.
*
* Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
* Additions Copyright (C) 2016, Espressif Systems (Shanghai) PTE Ltd
* Additions Copyright (C) 2019-2020, Espressif Systems (Shanghai) PTE Ltd
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
@ -30,27 +30,39 @@
extern "C" {
#endif
#define MBEDTLS_ERR_GCM_AUTH_FAILED -0x0012 /**< Authenticated decryption failed. */
#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.
*/
typedef struct {
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. */
uint64_t aad_len; /*!< The total length of the additional data. */
size_t data_len;
int mode;
const unsigned char *aad; /*!< The additional data. */
esp_aes_context aes_ctx;
}
esp_aes_gcm_context;
esp_aes_gcm_state gcm_state;
} esp_gcm_context;
/**
* \brief This function initializes the specified GCM context
*
* \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
@ -67,7 +79,7 @@ void esp_aes_gcm_init( esp_aes_gcm_context *ctx);
* \return \c 0 on success.
* \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,
const unsigned char *key,
unsigned int keybits );
@ -88,7 +100,7 @@ int esp_aes_gcm_setkey( esp_aes_gcm_context *ctx,
*
* \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,
const unsigned char *iv,
size_t iv_len,
@ -116,7 +128,7 @@ int esp_aes_gcm_starts( esp_aes_gcm_context *ctx,
* \return \c 0 on success.
* \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,
const unsigned char *input,
unsigned char *output );
@ -135,7 +147,7 @@ int esp_aes_gcm_update( esp_aes_gcm_context *ctx,
* \return \c 0 on success.
* \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,
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.
*/
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.
@ -170,7 +182,7 @@ void esp_aes_gcm_free( esp_aes_gcm_context *ctx);
*
* \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,
size_t length,
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 #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,
const unsigned char *iv,
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");
// you may not use this file except in compliance with the License.
@ -16,9 +16,8 @@
#define _ESP_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
* mbedtls/shaXX.h. That API supports hardware acceleration.
@ -28,15 +27,8 @@
*
* Some technical details about the hardware SHA engine:
*
* - SHA accelerator engine calculates one digest at a time, per SHA
* algorithm type. It initialises and maintains the digest state
* 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.
* - The crypto DMA is shared between the SHA and AES engine, it is not
* possible for them to run calcalutions in parallel.
*
*/
@ -50,17 +42,11 @@ typedef SHA_TYPE esp_sha_type;
/** @brief Calculate SHA1 or SHA2 sum of some data, using hardware SHA engine
*
* @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
* hardware-accelerated mbedTLS implementation is also faster when
* hashing large amounts of data.
* to be passed all at once, try the mbedTLS mbedtls/shaX.h APIs.
*
* @note It is not necessary to lock any SHA hardware before calling
* 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 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);
/* @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
* 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.
* @note Call esp_sha_aquire_hardware() before calling this
* 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,
* 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
* @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 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
* 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.
*
* @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 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.
* @note Call esp_sha_aquire_hardware() before calling this
* function.
*
* If the SHA suffix padding block has been executed already, the
* value that is read is the SHA digest (in big endian
* format). 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.
* value that is read is the SHA digest.
* Otherwise, the value that is read is an interim SHA state.
*
* @param sha_type SHA algorithm in use.
*
* @param state Pointer to a memory buffer to hold the SHA state. Size
* is 20 bytes (SHA1), 32 bytes (SHA2_256), 48 bytes (SHA2_384) or 64 bytes (SHA2_512).
*
* @param digest_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).
*/
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
* while a TLS connection is open, suggest using
* esp_sha_try_lock_engine() and failing over to software SHA.
* When resuming a
*
* @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
*
* @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.
* @brief Enables the SHA and crypto DMA peripheral and takes the
* locks for both of them.
*/
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()
*
* @param sha_type Type of engine to release.
* @brief Disables the SHA and crypto DMA peripheral and releases the
* locks.
*/
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
* 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.
* @param t
*
* @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.
*
* Call esp_sha_unlock_memory_block() when done.
* @return 0 if successful
*/
void esp_sha_lock_memory_block(void);
/**
* @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);
int esp_sha_512_t_init_hash(uint16_t t);
#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
#endif
#ifdef CONFIG_MBEDTLS_HARDWARE_GCM
#define MBEDTLS_GCM_ALT
#else
#undef MBEDTLS_GCM_ALT
#endif
/* MBEDTLS_SHAxx_ALT to enable hardware SHA support
with software fallback.
*/

View file

@ -29,6 +29,30 @@ extern "C" {
#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 {
ESP_MBEDTLS_SHA1_UNUSED, /* first block hasn't been processed yet */
ESP_MBEDTLS_SHA1_HARDWARE, /* using hardware SHA engine */
@ -38,8 +62,7 @@ typedef enum {
/**
* \brief SHA-1 context structure
*/
typedef struct
{
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 */
@ -47,6 +70,8 @@ typedef struct
}
mbedtls_sha1_context;
#endif //CONFIG_IDF_TARGET_ESP32
#endif
#ifdef __cplusplus

View file

@ -29,6 +29,33 @@ extern "C" {
#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 {
ESP_MBEDTLS_SHA256_UNUSED, /* first block hasn't been processed yet */
ESP_MBEDTLS_SHA256_HARDWARE, /* using hardware SHA engine */
@ -38,8 +65,7 @@ typedef enum {
/**
* \brief SHA-256 context structure
*/
typedef struct
{
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 */
@ -48,6 +74,8 @@ typedef struct
}
mbedtls_sha256_context;
#endif //CONFIG_IDF_TARGET_ESP32
#endif
#ifdef __cplusplus

View file

@ -23,12 +23,51 @@
#ifndef _SHA512_ALT_H_
#define _SHA512_ALT_H_
#ifdef __cplusplus
extern "C" {
#endif
#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 {
ESP_MBEDTLS_SHA512_UNUSED, /* first block hasn't been processed yet */
ESP_MBEDTLS_SHA512_HARDWARE, /* using hardware SHA engine */
@ -38,8 +77,7 @@ typedef enum {
/**
* \brief SHA-512 context structure
*/
typedef struct
{
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 */
@ -48,6 +86,8 @@ typedef struct
}
mbedtls_sha512_context;
#endif //CONFIG_IDF_TARGET_ESP32
#endif
#ifdef __cplusplus

File diff suppressed because it is too large Load diff

View file

@ -5,6 +5,7 @@
#include <stdbool.h>
#include <esp_system.h>
#include "mbedtls/aes.h"
#include "mbedtls/gcm.h"
#include "unity.h"
#include "sdkconfig.h"
#include "esp_timer.h"
@ -63,9 +64,65 @@ TEST_CASE("mbedtls AES performance", "[aes]")
float mb_sec = (CALL_SZ * CALLS) / usecs;
printf("Encryption rate %.3fMB/sec\n", mb_sec);
#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);
#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 "sdkconfig.h"
#include "test_apb_dport_access.h"
#include "sodium/utils.h"
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_sha256_self_test(1), "SHA256 self-tests should pass.");
TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha512_self_test(1), "SHA512 self-tests should pass.");
TEST_ASSERT_FALSE_MESSAGE(mbedtls_sha512_self_test(1), "SHA512 self-tests should pass.");
verify_apb_access_loop();
}
@ -33,7 +33,8 @@ static const unsigned char *one_hundred_bs = (unsigned char *)
static const uint8_t sha256_thousand_as[32] = {
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] = {
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] = {
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]")
{
@ -164,7 +167,6 @@ void tskRunSHASelftests(void *param)
vTaskDelete(NULL);
}
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
TEST_CASE("mbedtls SHA self-tests multithreaded", "[mbedtls]")
{
done_sem = xSemaphoreCreateCounting(2, 0);
@ -180,7 +182,6 @@ TEST_CASE("mbedtls SHA self-tests multithreaded", "[mbedtls]")
}
vSemaphoreDelete(done_sem);
}
#endif //!TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
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_CASE("mbedtls SHA384 clone", "[mbedtls]")
TEST_CASE("mbedtls SHA384 clone", "[mbedtls][")
{
mbedtls_sha512_context ctx;
mbedtls_sha512_context clone;
unsigned char sha384[48];
mbedtls_sha512_init(&ctx);
@ -220,12 +222,12 @@ TEST_CASE("mbedtls SHA384 clone", "[mbedtls]")
}
mbedtls_sha512_clone(&clone, &ctx);
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(&clone, one_hundred_bs, 100));
}
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(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");
}
#if !TEMPORARY_DISABLED_FOR_TARGETS(ESP32S2)
typedef struct {
mbedtls_sha256_context ctx;
uint8_t result[32];
@ -279,7 +280,7 @@ static void tskFinaliseSha(void *v_param)
vTaskDelete(NULL);
}
// No concurrent SHA sessions in esp32s2, only has one engine
TEST_CASE("mbedtls SHA session passed between tasks", "[mbedtls]")
{
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_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
float mb_sec = (CALL_SZ * CALLS) / usecs;
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
TEST_PERFORMANCE_GREATER_THAN(SHA256_THROUGHPUT_MBSEC, "%.3fMB/sec", mb_sec);
#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;
}
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)
{
return ((intptr_t)p) % 4 == 0;

View file

@ -69,24 +69,6 @@
#define SHA_H_BASE ((DR_REG_SHA_BASE) + 0x40)
#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 */
#define AES_MODE_REG ((DR_REG_AES_BASE) + 0x40)
#define AES_ENDIAN_REG ((DR_REG_AES_BASE) + 0x44)

View file

@ -48,6 +48,12 @@ typedef enum {
PERIPH_WIFI_MODULE,
PERIPH_WIFI_BT_COMMON_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;
typedef enum {

View file

@ -270,10 +270,14 @@
#define SOC_DIRAM_DRAM_LOW 0x3FFB0000
#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_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().
#define SOC_BYTE_ACCESSIBLE_LOW 0x3FF9E000
#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;
case PERIPH_SYSTIMER_MODULE:
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:
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;
case PERIPH_SYSTIMER_MODULE:
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:
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_BT_COMMON_MODULE:
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:
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_BT_COMMON_MODULE:
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:
return DPORT_PERIP_RST_EN_REG;
}