diff --git a/components/bootloader_support/src/secure_boot_signatures.c b/components/bootloader_support/src/secure_boot_signatures.c index f7e435e86..076dfb335 100644 --- a/components/bootloader_support/src/secure_boot_signatures.c +++ b/components/bootloader_support/src/secure_boot_signatures.c @@ -25,7 +25,6 @@ typedef SHA_CTX sha_context; #else #include "hwcrypto/sha.h" -typedef esp_sha_context sha_context; #endif typedef struct { @@ -42,7 +41,9 @@ extern const uint8_t signature_verification_key_end[] asm("_binary_signature_ver esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) { - sha_context sha; +#ifdef BOOTLOADER_BUILD + SHA_CTX sha; +#endif uint8_t digest[32]; ptrdiff_t keylen; const uint8_t *data; @@ -83,12 +84,8 @@ esp_err_t esp_secure_boot_verify_signature(uint32_t src_addr, uint32_t length) ets_sha_finish(&sha, SHA2_256, digest); ets_sha_disable(); #else - /* Use thread-safe esp-idf SHA layer */ - esp_sha256_init(&sha); - esp_sha256_start(&sha, false); - esp_sha256_update(&sha, data, length); - esp_sha256_finish(&sha, digest); - esp_sha256_free(&sha); + /* Use thread-safe esp-idf SHA function */ + esp_sha(SHA2_256, data, length, digest); #endif keylen = signature_verification_key_end - signature_verification_key_start; diff --git a/components/esp32/hwcrypto/aes.c b/components/esp32/hwcrypto/aes.c index 169465822..8f27cd17c 100644 --- a/components/esp32/hwcrypto/aes.c +++ b/components/esp32/hwcrypto/aes.c @@ -28,6 +28,7 @@ #include #include "hwcrypto/aes.h" #include "rom/aes.h" +#include "soc/dport_reg.h" #include static _lock_t aes_lock; @@ -36,14 +37,23 @@ void esp_aes_acquire_hardware( void ) { /* newlib locks lazy initialize on ESP-IDF */ _lock_acquire(&aes_lock); - ets_aes_enable(); + /* Enable AES hardware */ + REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES); + /* Clear reset on digital signature & secure boot units, + otherwise AES unit is held in reset also. */ + REG_CLR_BIT(DPORT_PERI_RST_EN_REG, + DPORT_PERI_EN_AES + | DPORT_PERI_EN_DIGITAL_SIGNATURE + | DPORT_PERI_EN_SECUREBOOT); } void esp_aes_release_hardware( void ) { - uint8_t zero[256/8] = { 0 }; - ets_aes_setkey_enc(zero, AES256); - ets_aes_disable(); + /* Disable AES hardware */ + REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_AES); + /* Don't return other units to reset, as this pulls + reset on RSA & SHA units, respectively. */ + REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_AES); _lock_release(&aes_lock); } diff --git a/components/esp32/hwcrypto/sha.c b/components/esp32/hwcrypto/sha.c index 06b00c54a..601981e2a 100644 --- a/components/esp32/hwcrypto/sha.c +++ b/components/esp32/hwcrypto/sha.c @@ -26,242 +26,264 @@ */ #include +#include #include +#include +#include + #include "hwcrypto/sha.h" #include "rom/ets_sys.h" +#include "soc/dport_reg.h" +#include "soc/hwcrypto_reg.h" - -static _lock_t sha_lock; - -void esp_sha_acquire_hardware( void ) -{ - /* newlib locks lazy initialize on ESP-IDF */ - _lock_acquire(&sha_lock); - ets_sha_enable(); +inline static uint32_t SHA_LOAD_REG(esp_sha_type sha_type) { + return SHA_1_LOAD_REG + sha_type * 0x10; } -void esp_sha_release_hardware( void ) -{ - /* Want to empty internal SHA buffers where possible, - need to check if this is sufficient for this. */ - SHA_CTX zero = { 0 }; - ets_sha_init(&zero); - ets_sha_disable(); - _lock_release(&sha_lock); +inline static uint32_t SHA_BUSY_REG(esp_sha_type sha_type) { + return SHA_1_BUSY_REG + sha_type * 0x10; } -/* Generic esp_shaX_update implementation */ -static void esp_sha_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen, size_t block_size) +inline static uint32_t SHA_START_REG(esp_sha_type sha_type) { + return SHA_1_START_REG + sha_type * 0x10; +} + +inline static uint32_t SHA_CONTINUE_REG(esp_sha_type sha_type) { + return SHA_1_CONTINUE_REG + sha_type * 0x10; +} + +/* Single lock for SHA engine memory block +*/ +static _lock_t memory_block_lock; + +typedef struct { + _lock_t lock; + bool in_use; +} sha_engine_state; + +/* Pointer to state of each concurrent SHA engine. + + Indexes: + 0 = SHA1 + 1 = SHA2_256 + 2 = SHA2_384 or SHA2_512 +*/ +static sha_engine_state engine_states[3]; + +/* Index into the sha_engine_state array */ +inline static size_t sha_engine_index(esp_sha_type type) { + switch(type) { + case SHA1: + return 0; + case SHA2_256: + return 1; + default: + return 2; + } +} + +/* Return state & digest length (in bytes) for a given SHA type */ +inline static size_t sha_length(esp_sha_type type) { + switch(type) { + case SHA1: + return 20; + case SHA2_256: + return 32; + case SHA2_384: + return 64; + case SHA2_512: + return 64; + default: + return 0; + } +} + +/* Return block size (in bytes) for a given SHA type */ +inline static size_t block_length(esp_sha_type type) { + switch(type) { + case SHA1: + case SHA2_256: + return 64; + case SHA2_384: + case SHA2_512: + return 128; + default: + return 0; + } +} + +void esp_sha_lock_memory_block(void) { - /* Feed the SHA engine one block at a time */ + _lock_acquire(&memory_block_lock); +} + +void esp_sha_unlock_memory_block(void) +{ + _lock_release(&memory_block_lock); +} + +/* Lock to hold when changing SHA engine state, + allows checking of sha_engines_all_idle() +*/ +static _lock_t state_change_lock; + +inline static bool sha_engines_all_idle() { + return !engine_states[0].in_use + && !engine_states[1].in_use + && !engine_states[2].in_use; +} + +static void esp_sha_lock_engine_inner(sha_engine_state *engine); + +bool esp_sha_try_lock_engine(esp_sha_type sha_type) +{ + sha_engine_state *engine = &engine_states[sha_engine_index(sha_type)]; + if(_lock_try_acquire(&engine->lock) != 0) { + /* This SHA engine is already in use */ + return false; + } else { + esp_sha_lock_engine_inner(engine); + return true; + } +} + +void esp_sha_lock_engine(esp_sha_type sha_type) +{ + sha_engine_state *engine = &engine_states[sha_engine_index(sha_type)]; + _lock_acquire(&engine->lock); + esp_sha_lock_engine_inner(engine); +} + +static void esp_sha_lock_engine_inner(sha_engine_state *engine) +{ + _lock_acquire(&state_change_lock); + + if (sha_engines_all_idle()) { + /* Enable SHA hardware */ + REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA); + /* also clear reset on secure boot, otherwise SHA is held in reset */ + REG_CLR_BIT(DPORT_PERI_RST_EN_REG, + DPORT_PERI_EN_SHA + | DPORT_PERI_EN_SECUREBOOT); + ets_sha_enable(); + } + + _lock_release(&state_change_lock); + + assert( !engine->in_use && "in_use flag should be cleared" ); + engine->in_use = true; +} + + +void esp_sha_unlock_engine(esp_sha_type sha_type) +{ + sha_engine_state *engine = &engine_states[sha_engine_index(sha_type)]; + + _lock_acquire(&state_change_lock); + + assert( engine->in_use && "in_use flag should be set" ); + engine->in_use = false; + + if (sha_engines_all_idle()) { + /* Disable SHA hardware */ + /* Don't assert reset on secure boot, otherwise AES is held in reset */ + REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_SHA); + REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_SHA); + } + + _lock_release(&state_change_lock); + + _lock_release(&engine->lock); +} + +void esp_sha_wait_idle(void) +{ + while(REG_READ(SHA_1_BUSY_REG) == 1) {} + while(REG_READ(SHA_256_BUSY_REG) == 1) {} + while(REG_READ(SHA_384_BUSY_REG) == 1) {} + while(REG_READ(SHA_512_BUSY_REG) == 1) {} +} + +void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state) +{ + sha_engine_state *engine = &engine_states[sha_engine_index(sha_type)]; + assert(engine->in_use && "SHA engine should be locked" ); + + esp_sha_lock_memory_block(); + + esp_sha_wait_idle(); + + REG_WRITE(SHA_LOAD_REG(sha_type), 1); + while(REG_READ(SHA_BUSY_REG(sha_type)) == 1) { } + + uint32_t *digest_state_words = (uint32_t *)digest_state; + uint32_t *reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE); + if(sha_type == SHA2_384 || sha_type == SHA2_512) { + /* for these ciphers using 64-bit states, swap each pair of words */ + for(int i = 0; i < sha_length(sha_type)/4; i += 2) { + digest_state_words[i+1] = reg_addr_buf[i]; + digest_state_words[i]= reg_addr_buf[i+1]; + } + } else { + memcpy(digest_state_words, reg_addr_buf, sha_length(sha_type)); + } + asm volatile ("memw"); + + esp_sha_unlock_memory_block(); +} + +void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block) +{ + sha_engine_state *engine = &engine_states[sha_engine_index(sha_type)]; + assert(engine->in_use && "SHA engine should be locked" ); + + esp_sha_lock_memory_block(); + + esp_sha_wait_idle(); + + /* Fill the data block */ + uint32_t *reg_addr_buf = (uint32_t *)(SHA_TEXT_BASE); + uint32_t *data_words = (uint32_t *)data_block; + for (int i = 0; i < block_length(sha_type) / 4; i++) { + reg_addr_buf[i] = __bswap_32(data_words[i]); + } + asm volatile ("memw"); + + if(is_first_block) { + REG_WRITE(SHA_START_REG(sha_type), 1); + } else { + REG_WRITE(SHA_CONTINUE_REG(sha_type), 1); + } + + esp_sha_unlock_memory_block(); + + /* Note: deliberately not waiting for this operation to complete, + as a performance tweak - delay waiting until the next time we need the SHA + unit, instead. + */ +} + +void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output) +{ + size_t block_len = block_length(sha_type); + + esp_sha_lock_engine(sha_type); + + SHA_CTX ctx; + ets_sha_init(&ctx); while(ilen > 0) { - size_t chunk_len = (ilen > block_size) ? block_size : ilen; - ets_sha_update(&ctx->context, ctx->context_type, input, chunk_len * 8); + size_t chunk_len = (ilen > block_len) ? block_len : ilen; + esp_sha_lock_memory_block(); + esp_sha_wait_idle(); + ets_sha_update(&ctx, sha_type, input, chunk_len * 8); + esp_sha_unlock_memory_block(); input += chunk_len; ilen -= chunk_len; } + esp_sha_lock_memory_block(); + esp_sha_wait_idle(); + ets_sha_finish(&ctx, sha_type, output); + esp_sha_unlock_memory_block(); + + esp_sha_unlock_engine(sha_type); } - -void esp_sha1_init( esp_sha_context *ctx ) -{ - bzero( ctx, sizeof( esp_sha_context ) ); -} - -void esp_sha1_free( esp_sha_context *ctx ) -{ - if ( ctx == NULL ) { - return; - } - - bzero( ctx, sizeof( esp_sha_context ) ); -} - -void esp_sha1_clone( esp_sha_context *dst, const esp_sha_context *src ) -{ - *dst = *src; -} - -/* - * SHA-1 context setup - */ -void esp_sha1_start( esp_sha_context *ctx ) -{ - ctx->context_type = SHA1; - esp_sha_acquire_hardware(); - ets_sha_init(&ctx->context); -} - -/* - * SHA-1 process buffer - */ -void esp_sha1_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen ) -{ - esp_sha_update(ctx, input, ilen, 64); -} - -/* - * SHA-1 final digest - */ -void esp_sha1_finish( esp_sha_context *ctx, unsigned char output[20] ) -{ - ets_sha_finish(&ctx->context, ctx->context_type, output); - esp_sha_release_hardware(); -} - -/* Full SHA-1 calculation */ -void esp_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) -{ - esp_sha_context ctx; - - esp_sha1_init( &ctx ); - esp_sha1_start( &ctx ); - esp_sha1_update( &ctx, input, ilen ); - esp_sha1_finish( &ctx, output ); - esp_sha1_free( &ctx ); -} - -void esp_sha256_init( esp_sha_context *ctx ) -{ - bzero( ctx, sizeof( esp_sha_context ) ); -} - -void esp_sha256_free( esp_sha_context *ctx ) -{ - if ( ctx == NULL ) { - return; - } - - bzero( ctx, sizeof( esp_sha_context ) ); -} - -void esp_sha256_clone( esp_sha_context *dst, const esp_sha_context *src ) -{ - *dst = *src; -} - -/* - * SHA-256 context setup - */ -void esp_sha256_start( esp_sha_context *ctx, int is224 ) -{ - if ( is224 == 0 ) { - /* SHA-256 */ - ctx->context_type = SHA2_256; - esp_sha_acquire_hardware(); - ets_sha_init(&ctx->context); - } else { - /* SHA-224 is not supported! */ - ctx->context_type = SHA_INVALID; - } -} - -/* - * SHA-256 process buffer - */ -void esp_sha256_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen ) -{ - if( ctx->context_type == SHA2_256 ) { - esp_sha_update(ctx, input, ilen, 64); - } - /* SHA-224 is a no-op */ -} - -/* - * SHA-256 final digest - */ -void esp_sha256_finish( esp_sha_context *ctx, unsigned char output[32] ) -{ - if ( ctx->context_type == SHA2_256 ) { - ets_sha_finish(&ctx->context, ctx->context_type, output); - esp_sha_release_hardware(); - } else { - /* No hardware SHA-224 support, but mbedTLS API doesn't allow failure. - For now, zero the output to make it clear it's not valid. */ - bzero( output, 28 ); - } -} - -/* - * Full SHA-256 calculation - */ -void esp_sha256( const unsigned char *input, size_t ilen, unsigned char output[32], int is224 ) -{ - esp_sha_context ctx; - - esp_sha256_init( &ctx ); - esp_sha256_start( &ctx, is224 ); - esp_sha256_update( &ctx, input, ilen ); - esp_sha256_finish( &ctx, output ); - esp_sha256_free( &ctx ); -} - - -///// -void esp_sha512_init( esp_sha_context *ctx ) -{ - memset( ctx, 0, sizeof( esp_sha_context ) ); -} - -void esp_sha512_free( esp_sha_context *ctx ) -{ - if ( ctx == NULL ) { - return; - } - - bzero( ctx, sizeof( esp_sha_context ) ); -} - -void esp_sha512_clone( esp_sha_context *dst, const esp_sha_context *src ) -{ - *dst = *src; -} - -/* - * SHA-512 context setup - */ -void esp_sha512_start( esp_sha_context *ctx, int is384 ) -{ - if ( is384 == 0 ) { - /* SHA-512 */ - ctx->context_type = SHA2_512; - } else { - /* SHA-384 */ - ctx->context_type = SHA2_384; - } - esp_sha_acquire_hardware(); - ets_sha_init(&ctx->context); -} - -/* - * SHA-512 process buffer - */ -void esp_sha512_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen ) -{ - esp_sha_update(ctx, input, ilen, 128); -} - -/* - * SHA-512 final digest - */ -void esp_sha512_finish( esp_sha_context *ctx, unsigned char output[64] ) -{ - ets_sha_finish(&ctx->context, ctx->context_type, output); - esp_sha_release_hardware(); -} - -/* - * Full SHA-512 calculation - */ -void esp_sha512( const unsigned char *input, size_t ilen, unsigned char output[64], int is384 ) -{ - esp_sha_context ctx; - - esp_sha512_init( &ctx ); - esp_sha512_start( &ctx, is384 ); - esp_sha512_update( &ctx, input, ilen ); - esp_sha512_finish( &ctx, output ); - esp_sha512_free( &ctx ); -} - -//// - diff --git a/components/esp32/include/hwcrypto/sha.h b/components/esp32/include/hwcrypto/sha.h index a165c46c1..2a0ec78ab 100644 --- a/components/esp32/include/hwcrypto/sha.h +++ b/components/esp32/include/hwcrypto/sha.h @@ -1,246 +1,200 @@ -/* - * ESP32 hardware accelerated SHA1/256/512 implementation - * 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 - * 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. - * - */ +// Copyright 2015-2016 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. +// 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 _ESP_SHA_H_ #define _ESP_SHA_H_ #include "rom/sha.h" - #include "esp_types.h" +/** @brief Low-level support functions for the hardware SHA engine + * + * @note If you're looking for a SHA API to use, try mbedtls component + * mbedtls/shaXX.h. That API supports hardware acceleration. + * + * The API in this header provides some building blocks for implementing a + * full SHA API such as the one in mbedtls, and also a basic SHA function esp_sha(). + * + * 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. + * + */ + #ifdef __cplusplus extern "C" { #endif -/** - * \brief SHA-1 context structure - */ -typedef struct { - /* both types defined in rom/sha.h */ - SHA_CTX context; - enum SHA_TYPE context_type; -} esp_sha_context; +/* Defined in rom/sha.h */ +typedef enum SHA_TYPE esp_sha_type; -/** - * \brief Lock access to SHA hardware unit +/** @brief Calculate SHA1 or SHA2 sum of some data, using hardware SHA engine * - * SHA hardware unit can only be used by one - * consumer at a time. + * @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. * - * esp_sha_xxx API calls automatically manage locking & unlocking of - * hardware, this function is only needed if you want to call - * ets_sha_xxx functions directly. - */ -void esp_sha_acquire_hardware( void ); - -/** - * \brief Unlock access to SHA hardware unit + * @note It is not necessary to lock any SHA hardware before calling + * this function, thread safety is managed internally. * - * esp_sha_xxx API calls automatically manage locking & unlocking of - * hardware, this function is only needed if you want to call - * ets_sha_xxx functions directly. - */ -void esp_sha_release_hardware( void ); - -/** - * \brief Initialize SHA-1 context + * @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 ctx SHA-1 context to be initialized - */ -void esp_sha1_init( esp_sha_context *ctx ); - -/** - * \brief Clear SHA-1 context + * @param sha_type SHA algorithm to use. * - * \param ctx SHA-1 context to be cleared - */ -void esp_sha1_free( esp_sha_context *ctx ); - -/** - * \brief Clone (the state of) a SHA-1 context + * @param input Input data buffer. * - * \param dst The destination context - * \param src The context to be cloned - */ -void esp_sha1_clone( esp_sha_context *dst, const esp_sha_context *src ); - -/** - * \brief SHA-1 context setup + * @param ilen Length of input data in bytes. * - * \param ctx context to be initialized + * @param output Buffer for output SHA digest. Output is 20 bytes for + * sha_type SHA1, 32 bytes for sha_type SHA2_256, 48 bytes for + * sha_type SHA2_384, 64 bytes for sha_type SHA2_512. */ -void esp_sha1_start( esp_sha_context *ctx ); +void esp_sha(esp_sha_type sha_type, const unsigned char *input, size_t ilen, unsigned char *output); -/** - * \brief SHA-1 process buffer +/* @brief Begin to execute a single SHA block operation * - * \param ctx SHA-1 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void esp_sha1_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief SHA-1 final digest + * @note This is a piece of a SHA algorithm, rather than an entire SHA + * algorithm. * - * \param ctx SHA-1 context - * \param output SHA-1 checksum result - */ -void esp_sha1_finish( esp_sha_context *ctx, unsigned char output[20] ); - -/** - * \brief Calculate SHA-1 of input buffer + * @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 input buffer holding the data - * \param ilen length of the input data - * \param output SHA-1 checksum result - */ -void esp_sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ); - -/** - * \brief SHA-256 context structure - */ - -/** - * \brief Initialize SHA-256 context + * @param sha_type SHA algorithm to use. * - * \param ctx SHA-256 context to be initialized - */ -void esp_sha256_init( esp_sha_context *ctx ); - -/** - * \brief Clear SHA-256 context + * @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 ctx SHA-256 context to be cleared - */ -void esp_sha256_free( esp_sha_context *ctx ); - -/** - * \brief Clone (the state of) a SHA-256 context + * @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 dst The destination context - * \param src The context to be cloned + * @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_sha256_clone( esp_sha_context *dst, const esp_sha_context *src ); +void esp_sha_block(esp_sha_type sha_type, const void *data_block, bool is_first_block); -/** - * \brief SHA-256 context setup +/** @brief Read out the current state of the SHA digest loaded in the engine. * - * \param ctx context to be initialized - * \param is224 0 = use SHA256, 1 = use SHA224 - */ -void esp_sha256_start( esp_sha_context *ctx, int is224 ); - -/** - * \brief SHA-256 process buffer + * @note This is a piece of a SHA algorithm, rather than an entire SHA algorithm. * - * \param ctx SHA-256 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void esp_sha256_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief SHA-256 final digest + * @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 ctx SHA-256 context - * \param output SHA-224/256 checksum result - */ -void esp_sha256_finish( esp_sha_context *ctx, unsigned char output[32] ); - -/** - * \brief Calculate SHA-256 of input buffer + * 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. * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-224/256 checksum result - * \param is224 0 = use SHA256, 1 = use SHA224 - */ -void esp_sha256( const unsigned char *input, size_t ilen, unsigned char output[32], int is224 ); - -// - -/** - * \brief SHA-512 context structure - */ - -/** - * \brief Initialize SHA-512 context + * @param sha_type SHA algorithm in use. + * + * @param state Pointer to a memory buffer to hold the SHA state. Size + * is 20 bytes (SHA1), 64 bytes (SHA2_256), or 128 bytes (SHA2_384 or + * SHA2_512). * - * \param ctx SHA-512 context to be initialized */ -void esp_sha512_init( esp_sha_context *ctx ); +void esp_sha_read_digest_state(esp_sha_type sha_type, void *digest_state); /** - * \brief Clear SHA-512 context + * @brief Obtain exclusive access to a particular SHA engine * - * \param ctx SHA-512 context to be cleared + * @param sha_type Type of SHA engine to use. + * + * 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. */ -void esp_sha512_free( esp_sha_context *ctx ); +void esp_sha_lock_engine(esp_sha_type sha_type); /** - * \brief Clone (the state of) a SHA-512 context + * @brief Try and obtain exclusive access to a particular SHA engine * - * \param dst The destination context - * \param src The context to be cloned + * @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. */ -void esp_sha512_clone( esp_sha_context *dst, const esp_sha_context *src ); +bool esp_sha_try_lock_engine(esp_sha_type sha_type); /** - * \brief SHA-512 context setup + * @brief Unlock an engine previously locked with esp_sha_lock_engine() or esp_sha_try_lock_engine() * - * \param ctx context to be initialized - * \param is384 0 = use SHA512, 1 = use SHA384 + * @param sha_type Type of engine to release. */ -void esp_sha512_start( esp_sha_context *ctx, int is384 ); +void esp_sha_unlock_engine(esp_sha_type sha_type); /** - * \brief SHA-512 process buffer + * @brief Acquire exclusive access to the SHA shared memory block at SHA_TEXT_BASE * - * \param ctx SHA-512 context - * \param input buffer holding the data - * \param ilen length of the input data + * This memory block is shared across all the SHA algorithm types. + * + * Caller should have already locked a SHA engine before calling this function. + * + * 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. + * + * @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. */ -void esp_sha512_update( esp_sha_context *ctx, const unsigned char *input, size_t ilen ); +void esp_sha_lock_memory_block(void); /** - * \brief SHA-512 final digest + * @brief Release exclusive access to the SHA register memory block at SHA_TEXT_BASE * - * \param ctx SHA-512 context - * \param output SHA-384/512 checksum result - */ -void esp_sha512_finish( esp_sha_context *ctx, unsigned char output[64] ); - -/** - * \brief Calculate SHA-512 of input buffer. + * Caller should have already locked a SHA engine before calling this function. * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-384/512 checksum result - * \param is384 0 = use SHA512, 1 = use SHA384 + * Call following esp_sha_lock_memory_block(). */ -void esp_sha512( const unsigned char *input, size_t ilen, unsigned char output[64], int is384 ); +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 } diff --git a/components/esp32/include/rom/sha.h b/components/esp32/include/rom/sha.h index 8082a394c..5dd9c9981 100644 --- a/components/esp32/include/rom/sha.h +++ b/components/esp32/include/rom/sha.h @@ -1,9 +1,10 @@ /* ROM functions for hardware SHA support. - It is not recommended to use these functions directly, - use the wrapper functions in hwcrypto/sha.h instead. - + It is not recommended to use these functions directly. If using + them from esp-idf then use the esp_sha_lock_engine() and + esp_sha_lock_memory_block() functions in hwcrypto/sha.h to ensure + exclusive access. */ // Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD // @@ -38,6 +39,8 @@ enum SHA_TYPE { SHA2_256, SHA2_384, SHA2_512, + + SHA_INVALID = -1, }; diff --git a/components/esp32/include/soc/dport_reg.h b/components/esp32/include/soc/dport_reg.h index 1be0fdee1..f84346717 100644 --- a/components/esp32/include/soc/dport_reg.h +++ b/components/esp32/include/soc/dport_reg.h @@ -94,6 +94,16 @@ #define DPORT_PERI_RST_EN_V 0xFFFFFFFF #define DPORT_PERI_RST_EN_S 0 +/* The following bits apply to DPORT_PERI_CLK_EN_REG, DPORT_PERI_RST_EN_REG + */ +#define DPORT_PERI_EN_AES (1<<0) +#define DPORT_PERI_EN_SHA (1<<1) +#define DPORT_PERI_EN_RSA (1<<2) +/* NB: Secure boot reset will hold SHA & AES in reset */ +#define DPORT_PERI_EN_SECUREBOOT (1<<3) +/* NB: Digital signature reset will hold AES & RSA in reset */ +#define DPORT_PERI_EN_DIGITAL_SIGNATURE (1<<4) + #define DPORT_WIFI_BB_CFG_REG (DR_REG_DPORT_BASE + 0x024) /* DPORT_WIFI_BB_CFG : R/W ;bitpos:[31:0] ;default: 32'h0 ; */ /*description: */ diff --git a/components/esp32/include/soc/hwcrypto_reg.h b/components/esp32/include/soc/hwcrypto_reg.h index 4f38b1ba9..10e80d935 100644 --- a/components/esp32/include/soc/hwcrypto_reg.h +++ b/components/esp32/include/soc/hwcrypto_reg.h @@ -30,8 +30,31 @@ #define RSA_MULT_MODE_REG (DR_REG_RSA_BASE + 0x80c) #define RSA_MULT_START_REG (DR_REG_RSA_BASE + 0x810) -#define RSA_INTERRUPT_REG (DR_REG_RSA_BASE + 0X814) +#define RSA_INTERRUPT_REG (DR_REG_RSA_BASE + 0x814) -#define RSA_CLEAN_ADDR (DR_REG_RSA_BASE + 0X818) +#define RSA_CLEAN_REG (DR_REG_RSA_BASE + 0x818) + +/* SHA acceleration registers */ +#define SHA_TEXT_BASE ((DR_REG_SHA_BASE) + 0x00) + +#define SHA_1_START_REG ((DR_REG_SHA_BASE) + 0x80) +#define SHA_1_CONTINUE_REG ((DR_REG_SHA_BASE) + 0x84) +#define SHA_1_LOAD_REG ((DR_REG_SHA_BASE) + 0x88) +#define SHA_1_BUSY_REG ((DR_REG_SHA_BASE) + 0x8c) + +#define SHA_256_START_REG ((DR_REG_SHA_BASE) + 0x90) +#define SHA_256_CONTINUE_REG ((DR_REG_SHA_BASE) + 0x94) +#define SHA_256_LOAD_REG ((DR_REG_SHA_BASE) + 0x98) +#define SHA_256_BUSY_REG ((DR_REG_SHA_BASE) + 0x9c) + +#define SHA_384_START_REG ((DR_REG_SHA_BASE) + 0xa0) +#define SHA_384_CONTINUE_REG ((DR_REG_SHA_BASE) + 0xa4) +#define SHA_384_LOAD_REG ((DR_REG_SHA_BASE) + 0xa8) +#define SHA_384_BUSY_REG ((DR_REG_SHA_BASE) + 0xac) + +#define SHA_512_START_REG ((DR_REG_SHA_BASE) + 0xb0) +#define SHA_512_CONTINUE_REG ((DR_REG_SHA_BASE) + 0xb4) +#define SHA_512_LOAD_REG ((DR_REG_SHA_BASE) + 0xb8) +#define SHA_512_BUSY_REG ((DR_REG_SHA_BASE) + 0xbc) #endif diff --git a/components/esp32/include/soc/soc.h b/components/esp32/include/soc/soc.h index 61ec2e1f2..5781b4c85 100755 --- a/components/esp32/include/soc/soc.h +++ b/components/esp32/include/soc/soc.h @@ -142,6 +142,7 @@ #define DR_REG_DPORT_BASE 0x3ff00000 #define DR_REG_RSA_BASE 0x3ff02000 +#define DR_REG_SHA_BASE 0x3ff03000 #define DR_REG_UART_BASE 0x3ff40000 #define DR_REG_SPI1_BASE 0x3ff42000 #define DR_REG_SPI0_BASE 0x3ff43000 diff --git a/components/mbedtls/Kconfig b/components/mbedtls/Kconfig index d6e2a2dcb..1e347582f 100644 --- a/components/mbedtls/Kconfig +++ b/components/mbedtls/Kconfig @@ -69,4 +69,16 @@ config MBEDTLS_MPI_INTERRUPT_NUM CPU interrupt number for MPI interrupt to connect to. Must be otherwise unused. Eventually this assignment will be handled automatically at runtime. +config MBEDTLS_HARDWARE_SHA + bool "Enable hardware SHA acceleration" + default y + help + Enable hardware accelerated SHA1, SHA256, SHA384 & SHA512 in mbedTLS. + + Due to a hardware limitation, hardware acceleration is only + guaranteed if SHA digests are calculated one at a time. If more + than one SHA digest is calculated at the same time, only will + be calculated fully in hardware and the rest will be calculated + (at least partially calculated) in software. + endmenu diff --git a/components/mbedtls/component.mk b/components/mbedtls/component.mk index bd7209a92..d2cd0455f 100644 --- a/components/mbedtls/component.mk +++ b/components/mbedtls/component.mk @@ -5,4 +5,3 @@ COMPONENT_ADD_INCLUDEDIRS := port/include include COMPONENT_SRCDIRS := library port - diff --git a/components/mbedtls/port/esp_bignum.c b/components/mbedtls/port/esp_bignum.c index ec2e42039..2fe4d920c 100644 --- a/components/mbedtls/port/esp_bignum.c +++ b/components/mbedtls/port/esp_bignum.c @@ -34,6 +34,8 @@ #include "esp_intr.h" #include "esp_attr.h" +#include "soc/dport_reg.h" + #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "freertos/semphr.h" @@ -72,7 +74,16 @@ void esp_mpi_acquire_hardware( void ) { /* newlib locks lazy initialize on ESP-IDF */ _lock_acquire(&mpi_lock); - ets_bigint_enable(); + REG_SET_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA); + /* also clear reset on digital signature, otherwise RSA is held in reset */ + REG_CLR_BIT(DPORT_PERI_RST_EN_REG, + DPORT_PERI_EN_RSA + | DPORT_PERI_EN_DIGITAL_SIGNATURE); + + REG_CLR_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); + + while(REG_READ(RSA_CLEAN_REG) != 1); + #ifdef CONFIG_MBEDTLS_MPI_USE_INTERRUPT rsa_isr_initialise(); #endif @@ -80,7 +91,12 @@ void esp_mpi_acquire_hardware( void ) void esp_mpi_release_hardware( void ) { - ets_bigint_disable(); + REG_SET_BIT(DPORT_RSA_PD_CTRL_REG, DPORT_RSA_PD); + + /* don't reset digital signature unit, as this resets AES also */ + REG_SET_BIT(DPORT_PERI_RST_EN_REG, DPORT_PERI_EN_RSA); + REG_CLR_BIT(DPORT_PERI_CLK_EN_REG, DPORT_PERI_EN_RSA); + _lock_release(&mpi_lock); } diff --git a/components/mbedtls/port/esp_sha1.c b/components/mbedtls/port/esp_sha1.c new file mode 100644 index 000000000..675159693 --- /dev/null +++ b/components/mbedtls/port/esp_sha1.c @@ -0,0 +1,395 @@ +/* + * 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, 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 + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#include "hwcrypto/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 GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#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; + + if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) { + esp_sha_unlock_engine(SHA1); + } + mbedtls_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ) +{ + *dst = *src; + + if (src->mode == ESP_MBEDTLS_SHA1_HARDWARE) { + /* Copy hardware digest state out to cloned state, + which will be a software digest. + */ + esp_sha_read_digest_state(SHA1, dst->state); + dst->mode = ESP_MBEDTLS_SHA1_SOFTWARE; + } +} + + +/* + * SHA-1 context setup + */ +void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + ctx->state[4] = 0xC3D2E1F0; + + if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) { + esp_sha_unlock_engine(SHA1); + } + ctx->mode = ESP_MBEDTLS_SHA1_UNUSED; +} + +static void mbedtls_sha1_software_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ); + +void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) +{ + bool first_block = false; + if (ctx->mode == ESP_MBEDTLS_SHA1_UNUSED) { + /* try to use hardware for this digest */ + if (esp_sha_try_lock_engine(SHA1)) { + ctx->mode = ESP_MBEDTLS_SHA1_HARDWARE; + first_block = true; + } else { + ctx->mode = ESP_MBEDTLS_SHA1_SOFTWARE; + } + } + + if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) { + esp_sha_block(SHA1, data, first_block); + } else { + mbedtls_sha1_software_process(ctx, data); + } +} + + +static void mbedtls_sha1_software_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ) +{ + uint32_t temp, W[16], A, B, C, D, E; + + GET_UINT32_BE( W[ 0], data, 0 ); + GET_UINT32_BE( W[ 1], data, 4 ); + GET_UINT32_BE( W[ 2], data, 8 ); + GET_UINT32_BE( W[ 3], data, 12 ); + GET_UINT32_BE( W[ 4], data, 16 ); + GET_UINT32_BE( W[ 5], data, 20 ); + GET_UINT32_BE( W[ 6], data, 24 ); + GET_UINT32_BE( W[ 7], data, 28 ); + GET_UINT32_BE( W[ 8], data, 32 ); + GET_UINT32_BE( W[ 9], data, 36 ); + GET_UINT32_BE( W[10], data, 40 ); + GET_UINT32_BE( W[11], data, 44 ); + GET_UINT32_BE( W[12], data, 48 ); + GET_UINT32_BE( W[13], data, 52 ); + GET_UINT32_BE( W[14], data, 56 ); + GET_UINT32_BE( W[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define R(t) \ +( \ + temp = W[( t - 3 ) & 0x0F] ^ W[( t - 8 ) & 0x0F] ^ \ + W[( t - 14 ) & 0x0F] ^ W[ t & 0x0F], \ + ( W[t & 0x0F] = S(temp,1) ) \ +) + +#define P(a,b,c,d,e,x) \ +{ \ + e += S(a,5) + F(b,c,d) + K + x; b = S(b,30); \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define K 0x5A827999 + + P( A, B, C, D, E, W[0] ); + P( E, A, B, C, D, W[1] ); + P( D, E, A, B, C, W[2] ); + P( C, D, E, A, B, W[3] ); + P( B, C, D, E, A, W[4] ); + P( A, B, C, D, E, W[5] ); + P( E, A, B, C, D, W[6] ); + P( D, E, A, B, C, W[7] ); + P( C, D, E, A, B, W[8] ); + P( B, C, D, E, A, W[9] ); + P( A, B, C, D, E, W[10] ); + P( E, A, B, C, D, W[11] ); + P( D, E, A, B, C, W[12] ); + P( C, D, E, A, B, W[13] ); + P( B, C, D, E, A, W[14] ); + P( A, B, C, D, E, W[15] ); + P( E, A, B, C, D, R(16) ); + P( D, E, A, B, C, R(17) ); + P( C, D, E, A, B, R(18) ); + P( B, C, D, E, A, R(19) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0x6ED9EBA1 + + P( A, B, C, D, E, R(20) ); + P( E, A, B, C, D, R(21) ); + P( D, E, A, B, C, R(22) ); + P( C, D, E, A, B, R(23) ); + P( B, C, D, E, A, R(24) ); + P( A, B, C, D, E, R(25) ); + P( E, A, B, C, D, R(26) ); + P( D, E, A, B, C, R(27) ); + P( C, D, E, A, B, R(28) ); + P( B, C, D, E, A, R(29) ); + P( A, B, C, D, E, R(30) ); + P( E, A, B, C, D, R(31) ); + P( D, E, A, B, C, R(32) ); + P( C, D, E, A, B, R(33) ); + P( B, C, D, E, A, R(34) ); + P( A, B, C, D, E, R(35) ); + P( E, A, B, C, D, R(36) ); + P( D, E, A, B, C, R(37) ); + P( C, D, E, A, B, R(38) ); + P( B, C, D, E, A, R(39) ); + +#undef K +#undef F + +#define F(x,y,z) ((x & y) | (z & (x | y))) +#define K 0x8F1BBCDC + + P( A, B, C, D, E, R(40) ); + P( E, A, B, C, D, R(41) ); + P( D, E, A, B, C, R(42) ); + P( C, D, E, A, B, R(43) ); + P( B, C, D, E, A, R(44) ); + P( A, B, C, D, E, R(45) ); + P( E, A, B, C, D, R(46) ); + P( D, E, A, B, C, R(47) ); + P( C, D, E, A, B, R(48) ); + P( B, C, D, E, A, R(49) ); + P( A, B, C, D, E, R(50) ); + P( E, A, B, C, D, R(51) ); + P( D, E, A, B, C, R(52) ); + P( C, D, E, A, B, R(53) ); + P( B, C, D, E, A, R(54) ); + P( A, B, C, D, E, R(55) ); + P( E, A, B, C, D, R(56) ); + P( D, E, A, B, C, R(57) ); + P( C, D, E, A, B, R(58) ); + P( B, C, D, E, A, R(59) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0xCA62C1D6 + + P( A, B, C, D, E, R(60) ); + P( E, A, B, C, D, R(61) ); + P( D, E, A, B, C, R(62) ); + P( C, D, E, A, B, R(63) ); + P( B, C, D, E, A, R(64) ); + P( A, B, C, D, E, R(65) ); + P( E, A, B, C, D, R(66) ); + P( D, E, A, B, C, R(67) ); + P( C, D, E, A, B, R(68) ); + P( B, C, D, E, A, R(69) ); + P( A, B, C, D, E, R(70) ); + P( E, A, B, C, D, R(71) ); + P( D, E, A, B, C, R(72) ); + P( C, D, E, A, B, R(73) ); + P( B, C, D, E, A, R(74) ); + P( A, B, C, D, E, R(75) ); + P( E, A, B, C, D, R(76) ); + P( D, E, A, B, C, R(77) ); + P( C, D, E, A, B, R(78) ); + P( B, C, D, E, A, R(79) ); + +#undef K +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; +} + +/* + * SHA-1 process buffer + */ +void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ) +{ + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return; + + 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 ); + mbedtls_sha1_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + mbedtls_sha1_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); +} + +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 + */ +void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ) +{ + 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 ); + + mbedtls_sha1_update( ctx, sha1_padding, padn ); + mbedtls_sha1_update( ctx, msglen, 8 ); + + /* if state is in hardware, read it out */ + if (ctx->mode == ESP_MBEDTLS_SHA1_HARDWARE) { + esp_sha_read_digest_state(SHA1, ctx->state); + esp_sha_unlock_engine(SHA1); + ctx->mode = ESP_MBEDTLS_SHA1_SOFTWARE; + } + + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); + +} + +#endif /* MBEDTLS_SHA1_C && MBEDTLS_SHA1_ALT */ diff --git a/components/mbedtls/port/esp_sha256.c b/components/mbedtls/port/esp_sha256.c new file mode 100644 index 000000000..fd136062a --- /dev/null +++ b/components/mbedtls/port/esp_sha256.c @@ -0,0 +1,367 @@ +/* + * 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, 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 + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#include "hwcrypto/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; + + if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) { + esp_sha_unlock_engine(SHA2_256); + } + mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); +} + +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ) +{ + *dst = *src; + + if (src->mode == ESP_MBEDTLS_SHA256_HARDWARE) { + /* Copy hardware digest state out to cloned state, + which will become a software digest. + */ + esp_sha_read_digest_state(SHA2_256, dst->state); + dst->mode = ESP_MBEDTLS_SHA256_SOFTWARE; + } +} + +/* + * SHA-256 context setup + */ +void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is224 == 0 ) + { + /* SHA-256 */ + ctx->state[0] = 0x6A09E667; + ctx->state[1] = 0xBB67AE85; + ctx->state[2] = 0x3C6EF372; + ctx->state[3] = 0xA54FF53A; + ctx->state[4] = 0x510E527F; + ctx->state[5] = 0x9B05688C; + ctx->state[6] = 0x1F83D9AB; + ctx->state[7] = 0x5BE0CD19; + } + else + { + /* SHA-224 */ + ctx->state[0] = 0xC1059ED8; + ctx->state[1] = 0x367CD507; + ctx->state[2] = 0x3070DD17; + ctx->state[3] = 0xF70E5939; + ctx->state[4] = 0xFFC00B31; + ctx->state[5] = 0x68581511; + ctx->state[6] = 0x64F98FA7; + ctx->state[7] = 0xBEFA4FA4; + } + + ctx->is224 = is224; + if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) { + esp_sha_unlock_engine(SHA2_256); + } + ctx->mode = ESP_MBEDTLS_SHA256_UNUSED; +} + +#if !defined(MBEDTLS_SHA256_PROCESS_ALT) +static const uint32_t K[] = +{ + 0x428A2F98, 0x71374491, 0xB5C0FBCF, 0xE9B5DBA5, + 0x3956C25B, 0x59F111F1, 0x923F82A4, 0xAB1C5ED5, + 0xD807AA98, 0x12835B01, 0x243185BE, 0x550C7DC3, + 0x72BE5D74, 0x80DEB1FE, 0x9BDC06A7, 0xC19BF174, + 0xE49B69C1, 0xEFBE4786, 0x0FC19DC6, 0x240CA1CC, + 0x2DE92C6F, 0x4A7484AA, 0x5CB0A9DC, 0x76F988DA, + 0x983E5152, 0xA831C66D, 0xB00327C8, 0xBF597FC7, + 0xC6E00BF3, 0xD5A79147, 0x06CA6351, 0x14292967, + 0x27B70A85, 0x2E1B2138, 0x4D2C6DFC, 0x53380D13, + 0x650A7354, 0x766A0ABB, 0x81C2C92E, 0x92722C85, + 0xA2BFE8A1, 0xA81A664B, 0xC24B8B70, 0xC76C51A3, + 0xD192E819, 0xD6990624, 0xF40E3585, 0x106AA070, + 0x19A4C116, 0x1E376C08, 0x2748774C, 0x34B0BCB5, + 0x391C0CB3, 0x4ED8AA4A, 0x5B9CCA4F, 0x682E6FF3, + 0x748F82EE, 0x78A5636F, 0x84C87814, 0x8CC70208, + 0x90BEFFFA, 0xA4506CEB, 0xBEF9A3F7, 0xC67178F2, +}; + +#define SHR(x,n) ((x & 0xFFFFFFFF) >> n) +#define ROTR(x,n) (SHR(x,n) | (x << (32 - n))) + +#define S0(x) (ROTR(x, 7) ^ ROTR(x,18) ^ SHR(x, 3)) +#define S1(x) (ROTR(x,17) ^ ROTR(x,19) ^ SHR(x,10)) + +#define S2(x) (ROTR(x, 2) ^ ROTR(x,13) ^ ROTR(x,22)) +#define S3(x) (ROTR(x, 6) ^ ROTR(x,11) ^ ROTR(x,25)) + +#define F0(x,y,z) ((x & y) | (z & (x | y))) +#define F1(x,y,z) (z ^ (x & (y ^ z))) + +#define R(t) \ +( \ + W[t] = S1(W[t - 2]) + W[t - 7] + \ + S0(W[t - 15]) + W[t - 16] \ +) + +#define P(a,b,c,d,e,f,g,h,x,K) \ +{ \ + temp1 = h + S3(e) + F1(e,f,g) + K + x; \ + temp2 = S2(a) + F0(a,b,c); \ + d += temp1; h = temp1 + temp2; \ +} + +static void mbedtls_sha256_software_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ); + +void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) +{ + bool first_block = false; + + if (ctx->mode == ESP_MBEDTLS_SHA256_UNUSED) { + /* try to use hardware for this digest */ + if (!ctx->is224 && esp_sha_try_lock_engine(SHA2_256)) { + ctx->mode = ESP_MBEDTLS_SHA256_HARDWARE; + first_block = true; + } else { + ctx->mode = ESP_MBEDTLS_SHA256_SOFTWARE; + } + } + + if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) { + esp_sha_block(SHA2_256, data, first_block); + } else { + mbedtls_sha256_software_process(ctx, data); + } +} + + +static void mbedtls_sha256_software_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) +{ + uint32_t temp1, temp2, W[64]; + uint32_t A[8]; + unsigned int i; + + for( i = 0; i < 8; i++ ) + A[i] = ctx->state[i]; + +#if defined(MBEDTLS_SHA256_SMALLER) + for( i = 0; i < 64; i++ ) + { + if( i < 16 ) + GET_UINT32_BE( W[i], data, 4 * i ); + else + R( i ); + + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); + + temp1 = A[7]; A[7] = A[6]; A[6] = A[5]; A[5] = A[4]; A[4] = A[3]; + A[3] = A[2]; A[2] = A[1]; A[1] = A[0]; A[0] = temp1; + } +#else /* MBEDTLS_SHA256_SMALLER */ + for( i = 0; i < 16; i++ ) + GET_UINT32_BE( W[i], data, 4 * i ); + + for( i = 0; i < 16; i += 8 ) + { + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i+0], K[i+0] ); + P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i+1], K[i+1] ); + P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i+2], K[i+2] ); + P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i+3], K[i+3] ); + P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i+4], K[i+4] ); + P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i+5], K[i+5] ); + P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i+6], K[i+6] ); + P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i+7], K[i+7] ); + } + + for( i = 16; i < 64; i += 8 ) + { + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], R(i+0), K[i+0] ); + P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], R(i+1), K[i+1] ); + P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], R(i+2), K[i+2] ); + P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], R(i+3), K[i+3] ); + P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], R(i+4), K[i+4] ); + P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], R(i+5), K[i+5] ); + P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], R(i+6), K[i+6] ); + P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], R(i+7), K[i+7] ); + } +#endif /* MBEDTLS_SHA256_SMALLER */ + + for( i = 0; i < 8; i++ ) + ctx->state[i] += A[i]; +} +#endif /* !MBEDTLS_SHA256_PROCESS_ALT */ + +/* + * SHA-256 process buffer + */ +void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, + size_t ilen ) +{ + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return; + + 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 ); + mbedtls_sha256_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + mbedtls_sha256_process( ctx, input ); + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); +} + +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 + */ +void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ) +{ + 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 ); + + mbedtls_sha256_update( ctx, sha256_padding, padn ); + mbedtls_sha256_update( ctx, msglen, 8 ); + + /* if state is in hardware, read it out */ + if (ctx->mode == ESP_MBEDTLS_SHA256_HARDWARE) { + esp_sha_read_digest_state(SHA2_256, ctx->state); + esp_sha_unlock_engine(SHA2_256); + ctx->mode = ESP_MBEDTLS_SHA256_SOFTWARE; + } + + PUT_UINT32_BE( ctx->state[0], output, 0 ); + PUT_UINT32_BE( ctx->state[1], output, 4 ); + PUT_UINT32_BE( ctx->state[2], output, 8 ); + PUT_UINT32_BE( ctx->state[3], output, 12 ); + PUT_UINT32_BE( ctx->state[4], output, 16 ); + PUT_UINT32_BE( ctx->state[5], output, 20 ); + PUT_UINT32_BE( ctx->state[6], output, 24 ); + + if( ctx->is224 == 0 ) + PUT_UINT32_BE( ctx->state[7], output, 28 ); +} + +#endif /* MBEDTLS_SHA256_C && MBEDTLS_SHA256_ALT */ diff --git a/components/mbedtls/port/esp_sha512.c b/components/mbedtls/port/esp_sha512.c new file mode 100644 index 000000000..cfd0f3fdf --- /dev/null +++ b/components/mbedtls/port/esp_sha512.c @@ -0,0 +1,408 @@ +/* + * 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, 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 + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#include "hwcrypto/sha.h" + +inline static esp_sha_type sha_type(const mbedtls_sha512_context *ctx) +{ + return ctx->is384 ? SHA2_384 : SHA2_512; +} + +/* 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 GET_UINT64_BE +#define GET_UINT64_BE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) ] << 56 ) \ + | ( (uint64_t) (b)[(i) + 1] << 48 ) \ + | ( (uint64_t) (b)[(i) + 2] << 40 ) \ + | ( (uint64_t) (b)[(i) + 3] << 32 ) \ + | ( (uint64_t) (b)[(i) + 4] << 24 ) \ + | ( (uint64_t) (b)[(i) + 5] << 16 ) \ + | ( (uint64_t) (b)[(i) + 6] << 8 ) \ + | ( (uint64_t) (b)[(i) + 7] ); \ +} +#endif /* GET_UINT64_BE */ + +#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 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; + + if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) { + esp_sha_unlock_engine(sha_type(ctx)); + } + mbedtls_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ) +{ + *dst = *src; + + if (src->mode == ESP_MBEDTLS_SHA512_HARDWARE) { + /* Copy hardware digest state out to cloned state, + which will be a software digest. + */ + esp_sha_read_digest_state(sha_type(dst), dst->state); + dst->mode = ESP_MBEDTLS_SHA512_SOFTWARE; + } +} + + +/* + * SHA-512 context setup + */ +void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is384 == 0 ) + { + /* SHA-512 */ + ctx->state[0] = UL64(0x6A09E667F3BCC908); + ctx->state[1] = UL64(0xBB67AE8584CAA73B); + ctx->state[2] = UL64(0x3C6EF372FE94F82B); + ctx->state[3] = UL64(0xA54FF53A5F1D36F1); + ctx->state[4] = UL64(0x510E527FADE682D1); + ctx->state[5] = UL64(0x9B05688C2B3E6C1F); + ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); + ctx->state[7] = UL64(0x5BE0CD19137E2179); + } + else + { + /* SHA-384 */ + ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); + ctx->state[1] = UL64(0x629A292A367CD507); + ctx->state[2] = UL64(0x9159015A3070DD17); + ctx->state[3] = UL64(0x152FECD8F70E5939); + ctx->state[4] = UL64(0x67332667FFC00B31); + ctx->state[5] = UL64(0x8EB44A8768581511); + ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); + ctx->state[7] = UL64(0x47B5481DBEFA4FA4); + } + + ctx->is384 = is384; + if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) { + esp_sha_unlock_engine(sha_type(ctx)); + } + ctx->mode = ESP_MBEDTLS_SHA512_UNUSED; +} + + +/* + * Round constants + */ +static const uint64_t K[80] = +{ + UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), + UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), + UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), + UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), + UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), + UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), + UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), + UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), + UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), + UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), + UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), + UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), + UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), + UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), + UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), + UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), + UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), + UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), + UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), + UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), + UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), + UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), + UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), + UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), + UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), + UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), + UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), + UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), + UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), + UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), + UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), + UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), + UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), + UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), + UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), + UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), + UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), + UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), + UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), + UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) +}; + +static void mbedtls_sha512_software_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ); + +void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ) +{ + bool first_block = false; + + if (ctx->mode == ESP_MBEDTLS_SHA512_UNUSED) { + /* try to use hardware for this digest */ + if (esp_sha_try_lock_engine(sha_type(ctx))) { + ctx->mode = ESP_MBEDTLS_SHA512_HARDWARE; + first_block = true; + } else { + ctx->mode = ESP_MBEDTLS_SHA512_SOFTWARE; + } + } + + if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) { + esp_sha_block(sha_type(ctx), data, first_block); + } else { + mbedtls_sha512_software_process(ctx, data); + } +} + + + +static void mbedtls_sha512_software_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ) +{ + int i; + uint64_t temp1, temp2, W[80]; + uint64_t A, B, C, D, E, F, G, H; + +#define SHR(x,n) (x >> n) +#define ROTR(x,n) (SHR(x,n) | (x << (64 - n))) + +#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) +#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) + +#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) +#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) + +#define F0(x,y,z) ((x & y) | (z & (x | y))) +#define F1(x,y,z) (z ^ (x & (y ^ z))) + +#define P(a,b,c,d,e,f,g,h,x,K) \ +{ \ + temp1 = h + S3(e) + F1(e,f,g) + K + x; \ + temp2 = S2(a) + F0(a,b,c); \ + d += temp1; h = temp1 + temp2; \ +} + + for( i = 0; i < 16; i++ ) + { + GET_UINT64_BE( W[i], data, i << 3 ); + } + + for( ; i < 80; i++ ) + { + W[i] = S1(W[i - 2]) + W[i - 7] + + S0(W[i - 15]) + W[i - 16]; + } + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + F = ctx->state[5]; + G = ctx->state[6]; + H = ctx->state[7]; + i = 0; + + do + { + P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++; + P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++; + P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++; + P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++; + P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++; + P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++; + P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++; + P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++; + } + while( i < 80 ); + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + ctx->state[5] += F; + ctx->state[6] += G; + ctx->state[7] += H; +} + +/* + * SHA-512 process buffer + */ +void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input, + size_t ilen ) +{ + size_t fill; + unsigned int left; + + if( ilen == 0 ) + return; + + 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 ); + mbedtls_sha512_process( ctx, ctx->buffer ); + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 128 ) + { + mbedtls_sha512_process( ctx, input ); + input += 128; + ilen -= 128; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); +} + +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 + */ +void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] ) +{ + 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 ); + + mbedtls_sha512_update( ctx, sha512_padding, padn ); + mbedtls_sha512_update( ctx, msglen, 16 ); + + /* if state is in hardware, read it out */ + if (ctx->mode == ESP_MBEDTLS_SHA512_HARDWARE) { + esp_sha_read_digest_state(sha_type(ctx), ctx->state); + esp_sha_unlock_engine(sha_type(ctx)); + ctx->mode = ESP_MBEDTLS_SHA512_SOFTWARE; + } + + PUT_UINT64_BE( ctx->state[0], output, 0 ); + PUT_UINT64_BE( ctx->state[1], output, 8 ); + PUT_UINT64_BE( ctx->state[2], output, 16 ); + PUT_UINT64_BE( ctx->state[3], output, 24 ); + PUT_UINT64_BE( ctx->state[4], output, 32 ); + PUT_UINT64_BE( ctx->state[5], output, 40 ); + + if( ctx->is384 == 0 ) + { + PUT_UINT64_BE( ctx->state[6], output, 48 ); + PUT_UINT64_BE( ctx->state[7], output, 56 ); + } +} + +#endif /* MBEDTLS_SHA512_C && MBEDTLS_SHA512_ALT */ diff --git a/components/mbedtls/port/include/mbedtls/esp_config.h b/components/mbedtls/port/include/mbedtls/esp_config.h index db87c6ef3..cd9f87e69 100644 --- a/components/mbedtls/port/include/mbedtls/esp_config.h +++ b/components/mbedtls/port/include/mbedtls/esp_config.h @@ -243,11 +243,14 @@ #define MBEDTLS_AES_ALT #endif -/* Currently hardware SHA does not work with TLS handshake, - due to concurrency issue. Internal TW#7111. */ -//#define MBEDTLS_SHA1_ALT -//#define MBEDTLS_SHA256_ALT -//#define MBEDTLS_SHA512_ALT +/* MBEDTLS_SHAxx_ALT to enable hardware SHA support + with software fallback. +*/ +#ifdef CONFIG_MBEDTLS_HARDWARE_SHA +#define MBEDTLS_SHA1_ALT +#define MBEDTLS_SHA256_ALT +#define MBEDTLS_SHA512_ALT +#endif /* The following MPI (bignum) functions have ESP32 hardware support, Uncommenting these macros will use the hardware-accelerated diff --git a/components/mbedtls/port/include/sha1_alt.h b/components/mbedtls/port/include/sha1_alt.h index f5e69b3f9..fbe740c7e 100644 --- a/components/mbedtls/port/include/sha1_alt.h +++ b/components/mbedtls/port/include/sha1_alt.h @@ -1,16 +1,25 @@ -// Copyright 2015-2016 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. -// 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. +/* + * 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, 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. + * + */ #ifndef _SHA1_ALT_H_ #define _SHA1_ALT_H_ @@ -20,17 +29,73 @@ extern "C" { #if defined(MBEDTLS_SHA1_ALT) -#include "hwcrypto/sha.h" +typedef enum { + ESP_MBEDTLS_SHA1_UNUSED, /* first block hasn't been processed yet */ + ESP_MBEDTLS_SHA1_HARDWARE, /* using hardware SHA engine */ + ESP_MBEDTLS_SHA1_SOFTWARE, /* using software SHA */ +} esp_mbedtls_sha1_mode; -typedef esp_sha_context mbedtls_sha1_context; +/** + * \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 */ + esp_mbedtls_sha1_mode mode; +} +mbedtls_sha1_context; -#define mbedtls_sha1_init esp_sha1_init -#define mbedtls_sha1_starts esp_sha1_start -#define mbedtls_sha1_clone esp_sha1_clone -#define mbedtls_sha1_update esp_sha1_update -#define mbedtls_sha1_finish esp_sha1_finish -#define mbedtls_sha1_free esp_sha1_free -#define mbedtls_sha1_process(...) +/** + * \brief Initialize SHA-1 context + * + * \param ctx SHA-1 context to be initialized + */ +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); + +/** + * \brief Clear SHA-1 context + * + * \param ctx SHA-1 context to be cleared + */ +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); + +/** + * \brief Clone (the state of) a SHA-1 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ); + +/** + * \brief SHA-1 context setup + * + * \param ctx context to be initialized + */ +void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); + +/** + * \brief SHA-1 process buffer + * + * \param ctx SHA-1 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief SHA-1 final digest + * + * \param ctx SHA-1 context + * \param output SHA-1 checksum result + */ +void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] ); + +/* Internal use */ +void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] ); #endif diff --git a/components/mbedtls/port/include/sha256_alt.h b/components/mbedtls/port/include/sha256_alt.h index 143d8c75e..cc87333aa 100644 --- a/components/mbedtls/port/include/sha256_alt.h +++ b/components/mbedtls/port/include/sha256_alt.h @@ -1,16 +1,25 @@ -// Copyright 2015-2016 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. -// 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. +/* + * 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, 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. + * + */ #ifndef _SHA256_ALT_H_ #define _SHA256_ALT_H_ @@ -20,17 +29,76 @@ extern "C" { #if defined(MBEDTLS_SHA256_ALT) -#include "hwcrypto/sha.h" +typedef enum { + ESP_MBEDTLS_SHA256_UNUSED, /* first block hasn't been processed yet */ + ESP_MBEDTLS_SHA256_HARDWARE, /* using hardware SHA engine */ + ESP_MBEDTLS_SHA256_SOFTWARE, /* using software SHA */ +} esp_mbedtls_sha256_mode; -typedef esp_sha_context mbedtls_sha256_context; +/** + * \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 is224; /*!< 0 => SHA-256, else SHA-224 */ + esp_mbedtls_sha256_mode mode; +} +mbedtls_sha256_context; -#define mbedtls_sha256_init esp_sha256_init -#define mbedtls_sha256_clone esp_sha256_clone -#define mbedtls_sha256_starts esp_sha256_start -#define mbedtls_sha256_update esp_sha256_update -#define mbedtls_sha256_finish esp_sha256_finish -#define mbedtls_sha256_free esp_sha256_free -#define mbedtls_sha256_process(...) +/** + * \brief Initialize SHA-256 context + * + * \param ctx SHA-256 context to be initialized + */ +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); + +/** + * \brief Clear SHA-256 context + * + * \param ctx SHA-256 context to be cleared + */ +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); + +/** + * \brief Clone (the state of) a SHA-256 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ); + +/** + * \brief SHA-256 context setup + * + * \param ctx context to be initialized + * \param is224 0 = use SHA256, 1 = use SHA224 + */ +void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ); + +/** + * \brief SHA-256 process buffer + * + * \param ctx SHA-256 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-256 final digest + * + * \param ctx SHA-256 context + * \param output SHA-224/256 checksum result + */ +void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ); + +/* Internal use */ +void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ); #endif diff --git a/components/mbedtls/port/include/sha512_alt.h b/components/mbedtls/port/include/sha512_alt.h index 8044b4275..70ae24e16 100644 --- a/components/mbedtls/port/include/sha512_alt.h +++ b/components/mbedtls/port/include/sha512_alt.h @@ -1,16 +1,25 @@ -// Copyright 2015-2016 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. -// 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. +/* + * 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, 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. + * + */ #ifndef _SHA512_ALT_H_ #define _SHA512_ALT_H_ @@ -19,17 +28,77 @@ extern "C" { #endif #if defined(MBEDTLS_SHA512_ALT) -#include "hwcrypto/sha.h" -typedef esp_sha_context mbedtls_sha512_context; +typedef enum { + ESP_MBEDTLS_SHA512_UNUSED, /* first block hasn't been processed yet */ + ESP_MBEDTLS_SHA512_HARDWARE, /* using hardware SHA engine */ + ESP_MBEDTLS_SHA512_SOFTWARE, /* using software SHA */ +} esp_mbedtls_sha512_mode; -#define mbedtls_sha512_init esp_sha512_init -#define mbedtls_sha512_clone esp_sha512_clone -#define mbedtls_sha512_starts esp_sha512_start -#define mbedtls_sha512_update esp_sha512_update -#define mbedtls_sha512_finish esp_sha512_finish -#define mbedtls_sha512_free esp_sha512_free -#define mbedtls_sha512_process(...) +/** + * \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 is384; /*!< 0 => SHA-512, else SHA-384 */ + esp_mbedtls_sha512_mode mode; +} +mbedtls_sha512_context; + +/** + * \brief Initialize SHA-512 context + * + * \param ctx SHA-512 context to be initialized + */ +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); + +/** + * \brief Clear SHA-512 context + * + * \param ctx SHA-512 context to be cleared + */ +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); + +/** + * \brief Clone (the state of) a SHA-512 context + * + * \param dst The destination context + * \param src The context to be cloned + */ +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ); + +/** + * \brief SHA-512 context setup + * + * \param ctx context to be initialized + * \param is384 0 = use SHA512, 1 = use SHA384 + */ +void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, int is384 ); + +/** + * \brief SHA-512 process buffer + * + * \param ctx SHA-512 context + * \param input buffer holding the data + * \param ilen length of the input data + */ +void mbedtls_sha512_update( mbedtls_sha512_context *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief SHA-512 final digest + * + * \param ctx SHA-512 context + * \param output SHA-384/512 checksum result + */ +void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, unsigned char output[64] ); + +/* Internal use */ +void mbedtls_sha512_process( mbedtls_sha512_context *ctx, const unsigned char data[128] ); #endif diff --git a/docs/build_system.rst b/docs/build_system.rst index 4ba89f865..ad263da7a 100644 --- a/docs/build_system.rst +++ b/docs/build_system.rst @@ -244,6 +244,7 @@ The following variables can be set inside ``component.mk`` to control the build settings. Component-specific additions can be made via ``CXXFLAGS +=``. It is also possible (although not recommended) to override this variable completely for a component. +- ``FLAGS_basename`` allows you to set compilation flags to apply to a single source file only. For example, this can useful for disabling warnings in a single upstream source file. The ``basename`` portion is the directory (relative to ``COMPONENT_PATH``) and the base filename (without extension) of the source file. For example, if a file inside ``COMPONENT_PATH`` is ``library/alpha/widget.c`` then you can set variable ``FLAGS_library/alpha/widget := -DTEST`` to pass the TEST macro when compiling this source file only. Component Configuration ----------------------- diff --git a/make/component_wrapper.mk b/make/component_wrapper.mk index c6ea52a2b..63f687d93 100644 --- a/make/component_wrapper.mk +++ b/make/component_wrapper.mk @@ -155,17 +155,17 @@ endif # This pattern is generated for each COMPONENT_SRCDIR to compile the files in it. define GenerateCompileTargets # $(1) - directory containing source files, relative to $(COMPONENT_PATH) -$(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.c | $(1) +$(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.c $(COMMON_MAKEFILES) $(COMPONENT_MAKEFILE) | $(1) $$(summary) CC $$@ - $$(CC) $$(CFLAGS) $$(CPPFLAGS) $$(addprefix -I ,$$(COMPONENT_INCLUDES)) $$(addprefix -I ,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@ + $$(CC) $$(CFLAGS) $$(CPPFLAGS) $$(FLAGS_$$(subst .o,,$$(@))) $$(addprefix -I ,$$(COMPONENT_INCLUDES)) $$(addprefix -I ,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@ -$(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.cpp | $(1) +$(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.cpp $(COMMON_MAKEFILES) $(COMPONENT_MAKEFILE) | $(1) $$(summary) CXX $$@ - $$(CXX) $$(CXXFLAGS) $$(CPPFLAGS) $$(addprefix -I,$$(COMPONENT_INCLUDES)) $$(addprefix -I,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@ + $$(CXX) $$(CXXFLAGS) $$(CPPFLAGS) $$(FLAGS_$$(subst .o,,$$(@))) $$(addprefix -I,$$(COMPONENT_INCLUDES)) $$(addprefix -I,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@ -$(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.S | $(1) +$(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.S $(COMMON_MAKEFILES) $(COMPONENT_MAKEFILE) | $(1) $$(summary) AS $$@ - $$(CC) $$(CPPFLAGS) $$(addprefix -I ,$$(COMPONENT_INCLUDES)) $$(addprefix -I ,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@ + $$(CC) $$(CPPFLAGS) $$(FLAGS_$$(subst .o,,$$(@))) $$(addprefix -I ,$$(COMPONENT_INCLUDES)) $$(addprefix -I ,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@ # CWD is build dir, create the build subdirectory if it doesn't exist $(1):