diff --git a/components/bootloader_support/src/bootloader_sha.c b/components/bootloader_support/src/bootloader_sha.c index 299d4261..2b1bd584 100644 --- a/components/bootloader_support/src/bootloader_sha.c +++ b/components/bootloader_support/src/bootloader_sha.c @@ -218,217 +218,29 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest #else #include "bootloader_sha.h" -#include -#include -#include -#include +#include "esp_sha.h" -typedef void* bootloader_sha256_handle_t; +// typedef esp_sha_t* bootloader_sha256_handle_t; -// Code from mbedTLS sha256 - -#define F0(x,y,z) ((x & y) | (z & (x | y))) -#define F1(x,y,z) (z ^ (x & (y ^ z))) - -#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 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 ) - -#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 ) - -#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; \ -} - -typedef struct { - uint32_t total[2]; - uint32_t state[8]; - uint8_t buffer[64]; -} mbedtls_sha256_context; - -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, -}; - -static mbedtls_sha256_context s_sha256; - -static int internal_sha256_process(mbedtls_sha256_context *ctx, const uint8_t 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]; - - 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; - } - - for( i = 0; i < 8; i++ ) - ctx->state[i] += A[i]; - - return( 0 ); -} +static esp_sha_t s_sha256_ctx; bootloader_sha256_handle_t bootloader_sha256_start() { - mbedtls_sha256_context *ctx = &s_sha256; + esp_sha_t *ctx = &s_sha256_ctx; - memset(ctx, 0, sizeof(mbedtls_sha256_context)); - - ctx->total[0] = 0; - ctx->total[1] = 0; - - 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; + esp_sha256_init(ctx); return ctx; } void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len) { - mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle; - size_t ilen = data_len; - const uint8_t *input = (const uint8_t *)data; - - int ret; - size_t fill; - uint32_t left; - - 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); - - if( ( ret = internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) - return ; - - input += fill; - ilen -= fill; - left = 0; - } - - while( ilen >= 64 ) - { - if( ( ret = internal_sha256_process( ctx, input ) ) != 0 ) - return ; - - input += 64; - ilen -= 64; - } - - if( ilen > 0 ) - memcpy( (void *) (ctx->buffer + left), input, ilen ); + esp_sha256_update((esp_sha_t *)handle, data, data_len); } void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest) { - uint32_t last, padn; - uint32_t high, low; - uint8_t msglen[8]; - uint8_t *output = digest; - mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle; - - 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 - }; - - 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 ); - - bootloader_sha256_data(ctx, sha256_padding, padn); - - bootloader_sha256_data(ctx, msglen, 8); - - 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 ); - - PUT_UINT32_BE( ctx->state[7], output, 28 ); - - return ; + esp_sha256_finish((esp_sha_t *)handle, digest); } #endif diff --git a/components/libsodium/CMakeLists.txt b/components/libsodium/CMakeLists.txt index 49b8adce..bc4eafea 100644 --- a/components/libsodium/CMakeLists.txt +++ b/components/libsodium/CMakeLists.txt @@ -118,7 +118,7 @@ set(COMPONENT_SRCS "${SRC}/crypto_aead/chacha20poly1305/sodium/aead_chacha20poly "${SRC}/sodium/version.c" "port/randombytes_esp8266.c") -if(CONFIG_SSL_USING_MBEDTLS) +if(CONFIG_LIBSODIUM_USE_MBEDTLS_SHA) list(APPEND COMPONENT_SRCS "port/crypto_hash_mbedtls/crypto_hash_sha256_mbedtls.c" "port/crypto_hash_mbedtls/crypto_hash_sha512_mbedtls.c") else() diff --git a/components/libsodium/Kconfig b/components/libsodium/Kconfig index 045538c1..a63a86c1 100644 --- a/components/libsodium/Kconfig +++ b/components/libsodium/Kconfig @@ -3,13 +3,13 @@ menu "libsodium" config LIBSODIUM_USE_MBEDTLS_SHA bool "Use mbedTLS SHA256 & SHA512 implementations" default y - depends on !MBEDTLS_HARDWARE_SHA + depends on !ESP_SHA help If this option is enabled, libsodium will use thin wrappers around mbedTLS for SHA256 & SHA512 operations. This saves some code size if mbedTLS is also used. However it - is incompatible with hardware SHA acceleration (due to the + is incompatible with Espressif SHA (due to the way libsodium's API manages SHA state). endmenu # libsodium diff --git a/components/libsodium/component.mk b/components/libsodium/component.mk index 7cb6b8ec..bee2d5dd 100644 --- a/components/libsodium/component.mk +++ b/components/libsodium/component.mk @@ -58,7 +58,7 @@ COMPONENT_SRCDIRS += \ $(LSRC)/randombytes \ $(LSRC)/sodium -ifdef CONFIG_SSL_USING_MBEDTLS +ifdef CONFIG_LIBSODIUM_USE_MBEDTLS_SHA COMPONENT_SRCDIRS += port/crypto_hash_mbedtls else COMPONENT_SRCDIRS += \ diff --git a/components/ssl/mbedtls/port/esp8266/include/mbedtls/esp_config.h b/components/ssl/mbedtls/port/esp8266/include/mbedtls/esp_config.h index fb6354d6..3cae8c86 100644 --- a/components/ssl/mbedtls/port/esp8266/include/mbedtls/esp_config.h +++ b/components/ssl/mbedtls/port/esp8266/include/mbedtls/esp_config.h @@ -290,10 +290,14 @@ //#define MBEDTLS_MD5_ALT //#define MBEDTLS_RIPEMD160_ALT //#define MBEDTLS_RSA_ALT -//#define MBEDTLS_SHA1_ALT -//#define MBEDTLS_SHA256_ALT -//#define MBEDTLS_SHA512_ALT //#define MBEDTLS_XTEA_ALT + +#ifdef CONFIG_ESP_SHA +#define MBEDTLS_SHA1_ALT +#define MBEDTLS_SHA256_ALT +#define MBEDTLS_SHA512_ALT +#endif + /* * When replacing the elliptic curve module, pleace consider, that it is * implemented with two .c files: diff --git a/components/ssl/mbedtls/port/esp8266/include/sha1_alt.h b/components/ssl/mbedtls/port/esp8266/include/sha1_alt.h new file mode 100644 index 00000000..c7f0f9d1 --- /dev/null +++ b/components/ssl/mbedtls/port/esp8266/include/sha1_alt.h @@ -0,0 +1,56 @@ +/* + * SHA-1 implementation with extra ESP8266 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_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SHA1_ALT) + +#include "esp_sha.h" + +typedef esp_sha1_t mbedtls_sha1_context; + +#define mbedtls_sha1_init(_ctx) { } + +#define mbedtls_sha1_free(_ctx) { } + +#define mbedtls_sha1_clone(_d, _s) { *(_d) = *(_s); } + +#define mbedtls_sha1_starts_ret(_ctx) esp_sha1_init(_ctx) + +#define mbedtls_sha1_update_ret(_ctx, _s, _l) esp_sha1_update(_ctx, _s, _l) + +#define mbedtls_sha1_finish_ret(_ctx, _d) esp_sha1_finish(_ctx, _d) + +#define mbedtls_internal_sha1_process(_ctx, _s) esp_sha1_update(_ctx, _s, 64) + +#endif /* MBEDTLS_SHA1_ALT */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/ssl/mbedtls/port/esp8266/include/sha256_alt.h b/components/ssl/mbedtls/port/esp8266/include/sha256_alt.h new file mode 100644 index 00000000..d602e532 --- /dev/null +++ b/components/ssl/mbedtls/port/esp8266/include/sha256_alt.h @@ -0,0 +1,66 @@ +/* + * SHA-256 implementation with extra ESP8266 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_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SHA256_ALT) + +#include "esp_sha.h" + +typedef esp_sha_t mbedtls_sha256_context; + +#define mbedtls_sha256_init(_ctx) { } + +#define mbedtls_sha256_free(_ctx) { } + +#define mbedtls_sha256_clone(_d, _s) { *(_d) = *(_s); } + +#define mbedtls_sha256_starts_ret(_ctx, _is224) \ +({ \ + int ret; \ + \ + if (_is224) \ + ret = esp_sha224_init(_ctx); \ + else \ + ret = esp_sha256_init(_ctx); \ + \ + ret; \ +}) + +#define mbedtls_sha256_update_ret(_ctx, _s, _l) esp_sha256_update(_ctx, _s, _l) + +#define mbedtls_sha256_finish_ret(_ctx, _d) esp_sha256_finish(_ctx, _d) + +#define mbedtls_internal_sha256_process(_ctx, _s) esp_sha256_update(_ctx, _s, 64) + +#endif /* MBEDTLS_SHA256_ALT */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/ssl/mbedtls/port/esp8266/include/sha512_alt.h b/components/ssl/mbedtls/port/esp8266/include/sha512_alt.h new file mode 100644 index 00000000..1fe60382 --- /dev/null +++ b/components/ssl/mbedtls/port/esp8266/include/sha512_alt.h @@ -0,0 +1,66 @@ +/* + * SHA-512 implementation with extra ESP8266 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_ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_SHA512_ALT) + +#include "esp_sha.h" + +typedef esp_sha512_t mbedtls_sha512_context; + +#define mbedtls_sha512_init(_ctx) { } + +#define mbedtls_sha512_free(_ctx) { } + +#define mbedtls_sha512_clone(_d, _s) { *(_d) = *(_s); } + +#define mbedtls_sha512_starts_ret(_ctx, _is384) \ +({ \ + int ret; \ + \ + if (_is384) \ + ret = esp_sha384_init(_ctx); \ + else \ + ret = esp_sha512_init(_ctx); \ + \ + ret; \ +}) + +#define mbedtls_sha512_update_ret(_ctx, _s, _l) esp_sha512_update(_ctx, _s, _l) + +#define mbedtls_sha512_finish_ret(_ctx, _d) esp_sha512_finish(_ctx, _d) + +#define mbedtls_internal_sha512_process(_ctx, _s) esp_sha512_update(_ctx, _s, 128) + +#endif /* MBEDTLS_SHA512_ALT */ + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/components/util/Kconfig b/components/util/Kconfig new file mode 100644 index 00000000..afc66d25 --- /dev/null +++ b/components/util/Kconfig @@ -0,0 +1,15 @@ +menu "Util" + +config ESP_SHA + bool "Enable Espressif SHA" + default y + help + Enable Espressif SHA1, SHA256, SHA384 & SHA512 for other components to + save code size for ESP8285(ESP8266 + 1MB flash) users. + + Although this option is disable, bootloader will use it if booloader + is configured to use SHA256 to check hash. + + Disabling the "assert" function at menuconfig can speed up the calculation. + +endmenu # Util diff --git a/components/util/include/esp_sha.h b/components/util/include/esp_sha.h new file mode 100644 index 00000000..e7d819e9 --- /dev/null +++ b/components/util/include/esp_sha.h @@ -0,0 +1,313 @@ +// 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. +// 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. + +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef int (*sha_cal_t)(void *ctx, const void *src); + +typedef enum { + SHA1 = 0, + SHA224 = 1, + SHA256 = 2, + SHA384 = 3, + SHA512 = 4, + + SHA_INVALID = -1, +} esp_sha_type_t; + +typedef struct { + esp_sha_type_t type; /*!< The sha type */ + uint8_t buffer[64]; /*!< The data block being processed. */ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[8]; /*!< The intermediate digest state. */ + sha_cal_t sha_cal; /*!< The sha calculation. */ +} esp_sha_t; + +typedef struct { + esp_sha_type_t type; /*!< The sha type */ + uint8_t buffer[128]; /*!< The data block being processed. */ + uint64_t total[2]; /*!< The number of Bytes processed. */ + uint64_t state[8]; /*!< The intermediate digest state. */ + sha_cal_t sha_cal; /*!< The sha calculation. */ +} esp_sha512_t; + +typedef esp_sha_t esp_sha1_t; +typedef esp_sha_t esp_sha224_t; +typedef esp_sha_t esp_sha256_t; +typedef esp_sha512_t esp_sha384_t; + +/** + * @brief initialize the SHA(1/224/256) contex + * + * @param ctx SHA contex pointer + * @param type SHA type + * @param state_ctx SHA calculation factor + * @param size calculation factor size by "uint32_t" + * @param sha_cal calculation function for real SHA + * + * @return 0 if success or fail + */ +int __esp_sha_init(esp_sha_t *ctx, esp_sha_type_t type, const uint32_t *state_ctx, size_t size, sha_cal_t sha_cal); + +/** + * @brief initialize the SHA(384/512) contex + * + * @param ctx SHA contex pointer + * @param type SHA type + * @param state_ctx SHA calculation factor + * @param size calculation factor size by "uint64_t" + * + * @return 0 if success or fail + */ +int __esp_sha512_init(esp_sha512_t *ctx, esp_sha_type_t type, const uint64_t *state_ctx, size_t size); + +/** + * @brief initialize the SHA1 contex + * + * @param ctx SHA1 contex pointer + * + * @return 0 if success or fail + */ +static inline int esp_sha1_init(esp_sha1_t *ctx) +{ + extern const uint32_t __g_esp_sha1_state_ctx[]; + extern int __esp_sha1_process(void *ctx, const void *data); + + return __esp_sha_init(ctx, SHA1, __g_esp_sha1_state_ctx, 5, __esp_sha1_process); +} + +/** + * @brief initialize the SHA224 contex + * + * @param ctx SHA224 contex pointer + * + * @return 0 if success or fail + */ +static inline int esp_sha224_init(esp_sha224_t *ctx) +{ + extern const uint32_t __g_esp_sha224_state_ctx[]; + extern int __esp_sha256_process(void *ctx, const void *data); + + return __esp_sha_init(ctx, SHA224, __g_esp_sha224_state_ctx, 8, __esp_sha256_process); +} + +/** + * @brief initialize the SHA256 contex + * + * @param ctx SHA256 contex pointer + * + * @return 0 if success or fail + */ +static inline int esp_sha256_init(esp_sha256_t *ctx) +{ + extern const uint32_t __g_esp_sha256_state_ctx[]; + extern int __esp_sha256_process(void *ctx, const void *data); + + return __esp_sha_init(ctx, SHA256, __g_esp_sha256_state_ctx, 8, __esp_sha256_process); +} + +/** + * @brief initialize the SHA384 contex + * + * @param ctx SHA384 contex pointer + * + * @return 0 if success or fail + */ +static inline int esp_sha384_init(esp_sha384_t *ctx) +{ + extern const uint64_t __g_esp_sha384_state_ctx[]; + + return __esp_sha512_init(ctx, SHA384, __g_esp_sha384_state_ctx, 8); +} + +/** + * @brief initialize the SHA512 contex + * + * @param ctx SHA512 contex pointer + * + * @return 0 if success or fail + */ +static inline int esp_sha512_init(esp_sha512_t *ctx) +{ + extern const uint64_t __g_esp_sha512_state_ctx[]; + + return __esp_sha512_init(ctx, SHA512, __g_esp_sha512_state_ctx, 8); +} + +/** + * @brief calculate input data for SHA + * + * @param ctx SHA contex pointer + * @param src input data buffer pointer + * @param size input data bytes + * + * @return 0 if success or fail + */ +int __esp_sha_update(esp_sha_t *ctx, const void *src, size_t size); + +/** + * @brief calculate input data for SHA1 + * + * @param ctx SHA1 contex pointer + * @param src input data buffer pointer + * @param size input data bytes + * + * @return 0 if success or fail + */ +static inline int esp_sha1_update(esp_sha1_t *ctx, const void *src, size_t size) +{ + return __esp_sha_update(ctx, src, size); +} + +/** + * @brief calculate input data for SHA224 + * + * @param ctx SHA224 contex pointer + * @param src input data buffer pointer + * @param size input data bytes + * + * @return 0 if success or fail + */ +static inline int esp_sha224_update(esp_sha224_t *ctx, const void *src, size_t size) +{ + return __esp_sha_update(ctx, src, size); +} + +/** + * @brief calculate input data for SHA256 + * + * @param ctx SHA256 contex pointer + * @param src input data buffer pointer + * @param size input data bytes + * + * @return 0 if success or fail + */ +static inline int esp_sha256_update(esp_sha256_t *ctx, const void *src, size_t size) +{ + return __esp_sha_update(ctx, src, size); +} + +/** + * @brief calculate input data for SHA384 + * + * @param ctx SHA384 contex pointer + * @param src input data buffer pointer + * @param size input data bytes + * + * @return 0 if success or fail + */ +static inline int esp_sha384_update(esp_sha384_t *ctx, const void *src, size_t size) +{ + return __esp_sha_update((esp_sha_t *)ctx, src, size); +} + +/** + * @brief calculate input data for SHA512 + * + * @param ctx SHA512 contex pointer + * @param src input data buffer pointer + * @param size input data bytes + * + * @return 0 if success or fail + */ +static inline int esp_sha512_update(esp_sha512_t *ctx, const void *src, size_t size) +{ + return __esp_sha_update((esp_sha_t *)ctx, src, size); +} + +/** + * @brief output SHA(1/224/256/384/512) calculation result + * + * @param ctx SHA contex pointer + * @param dest output data buffer pointer + * + * @return 0 if success or fail + */ +int __esp_sha_finish(esp_sha_t *ctx, void *dest); + +/** + * @brief output SHA1 calculation result + * + * @param ctx SHA1 contex pointer + * @param dest output data buffer pointer + * + * @return 0 if success or fail + */ +static inline int esp_sha1_finish(esp_sha1_t *ctx, void *dest) +{ + return __esp_sha_finish(ctx, dest); +} + +/** + * @brief output SHA224 calculation result + * + * @param ctx SHA224 contex pointer + * @param dest output data buffer pointer + * + * @return 0 if success or fail + */ +static inline int esp_sha224_finish(esp_sha224_t *ctx, void *dest) +{ + return __esp_sha_finish(ctx, dest); +} + +/** + * @brief output SHA256 calculation result + * + * @param ctx SHA256 contex pointer + * @param dest output data buffer pointer + * + * @return 0 if success or fail + */ +static inline int esp_sha256_finish(esp_sha256_t *ctx, void *dest) +{ + return __esp_sha_finish(ctx, dest); +} + +/** + * @brief output SHA384 calculation result + * + * @param ctx SHA384 contex pointer + * @param dest output data buffer pointer + * + * @return 0 if success or fail + */ +static inline int esp_sha384_finish(esp_sha384_t *ctx, void *dest) +{ + return __esp_sha_finish((esp_sha_t *)ctx, dest); +} + +/** + * @brief output SHA512 calculation result + * + * @param ctx SHA512 contex pointer + * @param dest output data buffer pointer + * + * @return 0 if success or fail + */ +static inline int esp_sha512_finish(esp_sha512_t *ctx, void *dest) +{ + return __esp_sha_finish((esp_sha_t *)ctx, dest); +} + +#ifdef __cplusplus +} +#endif diff --git a/components/util/src/sha.c b/components/util/src/sha.c new file mode 100644 index 00000000..2c54e64d --- /dev/null +++ b/components/util/src/sha.c @@ -0,0 +1,599 @@ +// Copyright 2018 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. + +#include +#include +#include +#include +#include "esp_sha.h" +#include "esp_log.h" + +#define UL64(x) x##ULL + +#define F0(x, y, z) ((x & y) | (z & (x | y))) +#define F1(x, y, z) (z ^ (x & (y ^ z))) + +#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 TAG "SHA" + +static const uint32_t sha_padding[] = { + 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, +}; + +const uint32_t __g_esp_sha1_state_ctx[] = { + 0x67452301, 0xEFCDAB89, 0x98BADCFE, 0x10325476, 0xC3D2E1F0 +}; + +const uint32_t __g_esp_sha224_state_ctx[] = { + 0xC1059ED8, 0x367CD507, 0x3070DD17, 0xF70E5939, + 0xFFC00B31, 0x68581511, 0x64F98FA7, 0xBEFA4FA4 +}; + +const uint32_t __g_esp_sha256_state_ctx[] = { + 0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, + 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19 +}; + +const uint64_t __g_esp_sha384_state_ctx[] = { + 0xCBBB9D5DC1059ED8, 0x629A292A367CD507, 0x9159015A3070DD17, + 0x152FECD8F70E5939, 0x67332667FFC00B31, 0x8EB44A8768581511, + 0xDB0C2E0D64F98FA7, 0x47B5481DBEFA4FA4 +}; + +const uint64_t __g_esp_sha512_state_ctx[] = { + 0x6A09E667F3BCC908, 0xBB67AE8584CAA73B, 0x3C6EF372FE94F82B, + 0xA54FF53A5F1D36F1, 0x510E527FADE682D1, 0x9B05688C2B3E6C1F, + 0x1F83D9ABFB41BD6B, 0x5BE0CD19137E2179 +}; + +static void esp_sha_put_be(void *dest, const void *src, size_t size, size_t steps) +{ + uint8_t *d_buf = (uint8_t *)dest; + const uint8_t *s_buf = (const uint8_t *)src; + + for (int i = 0; i < size; i += steps) { + for (int j = 0; j < steps; j++) { + d_buf[i + j] = s_buf[i + (steps - j - 1)]; + } + } +} + +int __esp_sha1_process(void *in_ctx, const void *src) +{ + const uint8_t *data = (const uint8_t *)src; + esp_sha_t *ctx = (esp_sha_t *)in_ctx; + + uint32_t temp, W[16], A[5]; + + esp_sha_put_be(W, data, 64, sizeof(uint32_t)); + +#undef S +#undef R +#undef P +#undef F +#undef K + +#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); \ +} + + for (int i = 0; i < 5; i++) + A[i] = ctx->state[i]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) +#define K 0x5A827999 + + P( A[0], A[1], A[2], A[3], A[4], W[0] ); + P( A[4], A[0], A[1], A[2], A[3], W[1] ); + P( A[3], A[4], A[0], A[1], A[2], W[2] ); + P( A[2], A[3], A[4], A[0], A[1], W[3] ); + P( A[1], A[2], A[3], A[4], A[0], W[4] ); + P( A[0], A[1], A[2], A[3], A[4], W[5] ); + P( A[4], A[0], A[1], A[2], A[3], W[6] ); + P( A[3], A[4], A[0], A[1], A[2], W[7] ); + P( A[2], A[3], A[4], A[0], A[1], W[8] ); + P( A[1], A[2], A[3], A[4], A[0], W[9] ); + P( A[0], A[1], A[2], A[3], A[4], W[10] ); + P( A[4], A[0], A[1], A[2], A[3], W[11] ); + P( A[3], A[4], A[0], A[1], A[2], W[12] ); + P( A[2], A[3], A[4], A[0], A[1], W[13] ); + P( A[1], A[2], A[3], A[4], A[0], W[14] ); + P( A[0], A[1], A[2], A[3], A[4], W[15] ); + P( A[4], A[0], A[1], A[2], A[3], R(16) ); + P( A[3], A[4], A[0], A[1], A[2], R(17) ); + P( A[2], A[3], A[4], A[0], A[1], R(18) ); + P( A[1], A[2], A[3], A[4], A[0], R(19) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0x6ED9EBA1 + + P( A[0], A[1], A[2], A[3], A[4], R(20) ); + P( A[4], A[0], A[1], A[2], A[3], R(21) ); + P( A[3], A[4], A[0], A[1], A[2], R(22) ); + P( A[2], A[3], A[4], A[0], A[1], R(23) ); + P( A[1], A[2], A[3], A[4], A[0], R(24) ); + P( A[0], A[1], A[2], A[3], A[4], R(25) ); + P( A[4], A[0], A[1], A[2], A[3], R(26) ); + P( A[3], A[4], A[0], A[1], A[2], R(27) ); + P( A[2], A[3], A[4], A[0], A[1], R(28) ); + P( A[1], A[2], A[3], A[4], A[0], R(29) ); + P( A[0], A[1], A[2], A[3], A[4], R(30) ); + P( A[4], A[0], A[1], A[2], A[3], R(31) ); + P( A[3], A[4], A[0], A[1], A[2], R(32) ); + P( A[2], A[3], A[4], A[0], A[1], R(33) ); + P( A[1], A[2], A[3], A[4], A[0], R(34) ); + P( A[0], A[1], A[2], A[3], A[4], R(35) ); + P( A[4], A[0], A[1], A[2], A[3], R(36) ); + P( A[3], A[4], A[0], A[1], A[2], R(37) ); + P( A[2], A[3], A[4], A[0], A[1], R(38) ); + P( A[1], A[2], A[3], A[4], A[0], R(39) ); + +#undef K +#undef F + +#define F(x,y,z) ((x & y) | (z & (x | y))) +#define K 0x8F1BBCDC + + P( A[0], A[1], A[2], A[3], A[4], R(40) ); + P( A[4], A[0], A[1], A[2], A[3], R(41) ); + P( A[3], A[4], A[0], A[1], A[2], R(42) ); + P( A[2], A[3], A[4], A[0], A[1], R(43) ); + P( A[1], A[2], A[3], A[4], A[0], R(44) ); + P( A[0], A[1], A[2], A[3], A[4], R(45) ); + P( A[4], A[0], A[1], A[2], A[3], R(46) ); + P( A[3], A[4], A[0], A[1], A[2], R(47) ); + P( A[2], A[3], A[4], A[0], A[1], R(48) ); + P( A[1], A[2], A[3], A[4], A[0], R(49) ); + P( A[0], A[1], A[2], A[3], A[4], R(50) ); + P( A[4], A[0], A[1], A[2], A[3], R(51) ); + P( A[3], A[4], A[0], A[1], A[2], R(52) ); + P( A[2], A[3], A[4], A[0], A[1], R(53) ); + P( A[1], A[2], A[3], A[4], A[0], R(54) ); + P( A[0], A[1], A[2], A[3], A[4], R(55) ); + P( A[4], A[0], A[1], A[2], A[3], R(56) ); + P( A[3], A[4], A[0], A[1], A[2], R(57) ); + P( A[2], A[3], A[4], A[0], A[1], R(58) ); + P( A[1], A[2], A[3], A[4], A[0], R(59) ); + +#undef K +#undef F + +#define F(x,y,z) (x ^ y ^ z) +#define K 0xCA62C1D6 + + P( A[0], A[1], A[2], A[3], A[4], R(60) ); + P( A[4], A[0], A[1], A[2], A[3], R(61) ); + P( A[3], A[4], A[0], A[1], A[2], R(62) ); + P( A[2], A[3], A[4], A[0], A[1], R(63) ); + P( A[1], A[2], A[3], A[4], A[0], R(64) ); + P( A[0], A[1], A[2], A[3], A[4], R(65) ); + P( A[4], A[0], A[1], A[2], A[3], R(66) ); + P( A[3], A[4], A[0], A[1], A[2], R(67) ); + P( A[2], A[3], A[4], A[0], A[1], R(68) ); + P( A[1], A[2], A[3], A[4], A[0], R(69) ); + P( A[0], A[1], A[2], A[3], A[4], R(70) ); + P( A[4], A[0], A[1], A[2], A[3], R(71) ); + P( A[3], A[4], A[0], A[1], A[2], R(72) ); + P( A[2], A[3], A[4], A[0], A[1], R(73) ); + P( A[1], A[2], A[3], A[4], A[0], R(74) ); + P( A[0], A[1], A[2], A[3], A[4], R(75) ); + P( A[4], A[0], A[1], A[2], A[3], R(76) ); + P( A[3], A[4], A[0], A[1], A[2], R(77) ); + P( A[2], A[3], A[4], A[0], A[1], R(78) ); + P( A[1], A[2], A[3], A[4], A[0], R(79) ); + +#undef K +#undef F +#undef R +#undef P + + for (int i = 0; i < 5; i++) + ctx->state[i] += A[i]; + + return 0; +} + +int __esp_sha256_process(void *in_ctx, const void *src) +{ + const uint8_t *data = (const uint8_t *)src; + esp_sha_t *ctx = (esp_sha_t *)in_ctx; + uint32_t temp1, temp2, W[64]; + uint32_t A[8]; + +#undef R +#undef P + +#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 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, + }; + + for (int i = 0; i < 8; i++) + A[i] = ctx->state[i]; + + for (int i = 0; i < 64; i++) { + if (i < 16) + esp_sha_put_be(&W[i], data + 4 * i, 4, sizeof(uint32_t)); + 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; + } + + for (int i = 0; i < 8; i++) + ctx->state[i] += A[i]; + + return 0; + +#undef R +#undef P +} + +int __esp_sha512_process(void *in_ctx, const void *src) +{ + int i; + uint64_t temp1, temp2, W[80]; + uint64_t A[8]; + const uint8_t *data = (const uint8_t *)src; + esp_sha512_t *ctx = (esp_sha512_t *)in_ctx; + + 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) + }; + +#undef SHR +#undef ROTR +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef F0 +#undef F1 +#undef P + +#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++) { + esp_sha_put_be(&W[i], data + (i << 3), sizeof(uint64_t), sizeof(uint64_t)); + } + + for (; i < 80; i++) { + W[i] = S1(W[i - 2]) + W[i - 7] + + S0(W[i - 15]) + W[i - 16]; + } + + for (int j = 0; j < 8; j++) + A[j] = ctx->state[j]; + + i = 0; + do { + P( A[0], A[1], A[2], A[3], A[4], A[5], A[6], A[7], W[i], K[i] ); i++; + P( A[7], A[0], A[1], A[2], A[3], A[4], A[5], A[6], W[i], K[i] ); i++; + P( A[6], A[7], A[0], A[1], A[2], A[3], A[4], A[5], W[i], K[i] ); i++; + P( A[5], A[6], A[7], A[0], A[1], A[2], A[3], A[4], W[i], K[i] ); i++; + P( A[4], A[5], A[6], A[7], A[0], A[1], A[2], A[3], W[i], K[i] ); i++; + P( A[3], A[4], A[5], A[6], A[7], A[0], A[1], A[2], W[i], K[i] ); i++; + P( A[2], A[3], A[4], A[5], A[6], A[7], A[0], A[1], W[i], K[i] ); i++; + P( A[1], A[2], A[3], A[4], A[5], A[6], A[7], A[0], W[i], K[i] ); i++; + } while (i < 80); + + for (int j = 0; j < 8; j++) + ctx->state[j] += A[j]; + + return 0; + +#undef SHR +#undef ROTR +#undef S0 +#undef S1 +#undef S2 +#undef S3 +#undef F0 +#undef F1 +#undef P +} + +/** + * @brief initialize the SHA1/SHA224/SHA256 contex + */ +int __esp_sha_init(esp_sha_t *ctx, esp_sha_type_t type, const uint32_t *state_ctx, size_t size, sha_cal_t sha_cal) +{ + assert(ctx); + + ctx->total[0] = 0; + ctx->total[1] = 0; + + for (int i = 0; i < size; i ++) + ctx->state[i] = state_ctx[i]; + + ctx->type = type; + ctx->sha_cal = sha_cal; + + return 0; +} + +/** + * @brief initialize the SHA512 contex + */ +int __esp_sha512_init(esp_sha512_t *ctx, esp_sha_type_t type, const uint64_t *state_ctx, size_t size) +{ + assert(ctx); + + ctx->total[0] = 0; + ctx->total[1] = 0; + + for (int i = 0; i < size; i ++) + ctx->state[i] = state_ctx[i]; + + ctx->type = type; + ctx->sha_cal = __esp_sha512_process; + + return 0; +} + +/** + * @brief input data which is calculated for SHA + */ +int __esp_sha_update(esp_sha_t *ctx, const void *src, size_t size) +{ + int ret; + size_t fill; + uint32_t left; + uint32_t step; + sha_cal_t sha_cal; + size_t ilen = size; + const uint8_t *input = (const uint8_t *)src; + + assert(ctx); + assert(src); + + if (ilen == 0) + return 0; + + if (SHA1 == ctx->type || SHA224 == ctx->type || SHA256 == ctx->type) { + left = ctx->total[0] & 0x3F; + + ctx->total[0] += (uint32_t)ilen; + if (ctx->total[0] < (uint32_t)ilen) + ctx->total[1]++; + + sha_cal = ctx->sha_cal; + step = 64; + } else { + esp_sha512_t *ctx512 = (esp_sha512_t *)ctx; + + left = (uint32_t)(ctx512->total[0] & 0x7F); + + ctx512->total[0] += ilen; + if (ctx512->total[0] < ilen) + ctx512->total[1]++; + + sha_cal = ctx512->sha_cal; + step = 128; + } + + fill = step - left; + + if (left && ilen >= fill) { + memcpy(ctx->buffer + left, input, fill); + + if ((ret = sha_cal(ctx, ctx->buffer)) != 0) + return ret; + + input += fill; + ilen -= fill; + left = 0; + } + + while (ilen >= step) { + ret = sha_cal(ctx, input); + if (ret) + return ret; + + input += step; + ilen -= step; + } + + if (ilen > 0) + memcpy(ctx->buffer + left, input, ilen); + + return 0; +} + +/** + * @brief input data which is calculated for SHA + */ +int __esp_sha_finish(esp_sha_t *ctx, void *dest) +{ + int ret; + size_t bytes = 0; + uint32_t last, padn; + uint64_t high, low; + uint8_t *output = dest; + size_t step; + void *state; + uint8_t msglen[16]; + + assert(ctx); + assert(dest); + + if (SHA1 == ctx->type) + bytes = 20; + else if (SHA224 == ctx->type) + bytes = 28; + else if (SHA256 == ctx->type) + bytes = 32; + else if (SHA384 == ctx->type) + bytes = 48; + else if (SHA512 == ctx->type) + bytes = 64; + + if (SHA1 == ctx->type || SHA224 == ctx->type || SHA256 == ctx->type) { + high = (ctx->total[0] >> 29) + | (ctx->total[1] << 3); + + low = (ctx->total[0] << 3); + + last = ctx->total[0] & 0x3F; + padn = (last < 56) ? (56 - last) : (120 - last); + + step = 4; + state = ctx->state; + } else { + esp_sha512_t *ctx512 = (esp_sha512_t *)ctx; + + high = (ctx512->total[0] >> 61) + | (ctx512->total[1] << 3); + + low = (ctx512->total[0] << 3); + + last = (size_t)(ctx512->total[0] & 0x7F); + padn = (last < 112) ? (112 - last) : (240 - last); + + step = 8; + state = ctx512->state; + } + + esp_sha_put_be(msglen, &high, step, step); + esp_sha_put_be(msglen + step, &low, step, step); + + ret = __esp_sha_update(ctx, sha_padding, padn); + if (ret) + return ret; + + ret = __esp_sha_update(ctx, msglen, step * 2); + if (ret) + return ret; + + esp_sha_put_be(output, state, bytes, step); + + return 0; +} + diff --git a/components/util/test/test_sha.c b/components/util/test/test_sha.c new file mode 100644 index 00000000..269cff7f --- /dev/null +++ b/components/util/test/test_sha.c @@ -0,0 +1,223 @@ +// Copyright 2018-2019 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. + +#include +#include +#include +#include "esp_sha.h" +#include "esp_heap_caps.h" +#include "esp_log.h" +#include "unity.h" + +//#define DEBUG_SHA_RESULT + +#define TAG "SHA_TEST" + +TEST_CASE("Test SHA1", "[SHA]") +{ + int ret; + uint8_t *buf; + esp_sha1_t sha_ctx; + + const uint32_t sha_result[] = { + 0xc3b837ce, 0x0c8a528c, 0x032939b5, 0x50a88285, 0x6433458d + }; + + buf = heap_caps_malloc(1024, MALLOC_CAP_8BIT); + TEST_ASSERT(buf != NULL); + + memset(buf, 11, 1024); + + ret = esp_sha1_init(&sha_ctx); + TEST_ASSERT(ret == 0); + + ret = esp_sha1_update(&sha_ctx, buf, 1024); + TEST_ASSERT(ret == 0); + + memset(buf, 0, 1024); + ret = esp_sha1_finish(&sha_ctx, buf); + TEST_ASSERT(ret == 0); + +#ifdef DEBUG_SHA_RESULT + const uint32_t *pbuf = (const uint32_t *)buf; + printf("\n"); + for (int j = 0; j < sizeof(sha_result) / sizeof(sha_result[0]); j++) { + printf("0x%x(0x%x) ", pbuf[j], sha_result[j]); + } + printf("\n"); +#endif + + TEST_ASSERT(memcmp(buf, sha_result, sizeof(sha_result)) == 0); + + heap_caps_free(buf); +} + +TEST_CASE("Test SHA224", "[SHA]") +{ + int ret; + uint8_t *buf; + esp_sha224_t sha_ctx; + + const uint32_t sha_result[] = { + 0xeb5dd981, 0x0ea2508e, 0xfe5708b8, 0xc15f30b5, 0x833f2144, 0xbbf4de16, 0x50d112b7 + }; + + buf = heap_caps_malloc(1024, MALLOC_CAP_8BIT); + TEST_ASSERT(buf != NULL); + + memset(buf, 11, 1024); + + ret = esp_sha224_init(&sha_ctx); + TEST_ASSERT(ret == 0); + + ret = esp_sha224_update(&sha_ctx, buf, 1024); + TEST_ASSERT(ret == 0); + + memset(buf, 0, 1024); + ret = esp_sha224_finish(&sha_ctx, buf); + TEST_ASSERT(ret == 0); + +#ifdef DEBUG_SHA_RESULT + const uint32_t *pbuf = (const uint32_t *)buf; + printf("\n"); + for (int j = 0; j < sizeof(sha_result) / sizeof(sha_result[0]); j++) { + printf("0x%x(0x%x) ", pbuf[j], sha_result[j]); + } + printf("\n"); +#endif + + TEST_ASSERT(memcmp(buf, sha_result, sizeof(sha_result)) == 0); + + heap_caps_free(buf); +} + +TEST_CASE("Test SHA256", "[SHA]") +{ + int ret; + uint8_t *buf; + esp_sha256_t sha_ctx; + + const uint32_t sha_result[] = { + 0xfc875b5a, 0x318e3c5a, 0xac2b3233, 0x4df7b366, 0x4c4c9261, 0x0e70af8d, 0x69a7e57c, 0x179cd56e + }; + + buf = heap_caps_malloc(1024, MALLOC_CAP_8BIT); + TEST_ASSERT(buf != NULL); + + memset(buf, 11, 1024); + + ret = esp_sha256_init(&sha_ctx); + TEST_ASSERT(ret == 0); + + ret = esp_sha256_update(&sha_ctx, buf, 1024); + TEST_ASSERT(ret == 0); + + memset(buf, 0, 1024); + ret = esp_sha256_finish(&sha_ctx, buf); + TEST_ASSERT(ret == 0); + +#ifdef DEBUG_SHA_RESULT + const uint32_t *pbuf = (const uint32_t *)buf; + printf("\n"); + for (int j = 0; j < sizeof(sha_result) / sizeof(sha_result[0]); j++) { + printf("0x%x(0x%x) ", pbuf[j], sha_result[j]); + } + printf("\n"); +#endif + + TEST_ASSERT(memcmp(buf, sha_result, sizeof(sha_result)) == 0); + + heap_caps_free(buf); +} + +TEST_CASE("Test SHA384", "[SHA]") +{ + int ret; + uint8_t *buf; + esp_sha384_t sha_ctx; + + const uint32_t sha_result[] = { + 0xd1d31575, 0x494afdef, 0x1d042951, 0x77a02c7b, 0x546db656, 0xdf31c571, + 0x1c3f87c1, 0x0d5cd544, 0x73628b2a, 0xecf051e7, 0xb72e6478, 0x83cee28b + }; + + buf = heap_caps_malloc(1024, MALLOC_CAP_8BIT); + TEST_ASSERT(buf != NULL); + + memset(buf, 11, 1024); + + ret = esp_sha384_init(&sha_ctx); + TEST_ASSERT(ret == 0); + + ret = esp_sha384_update(&sha_ctx, buf, 1024); + TEST_ASSERT(ret == 0); + + memset(buf, 0, 1024); + ret = esp_sha384_finish(&sha_ctx, buf); + TEST_ASSERT(ret == 0); + +#if DEBUG_SHA_RESULT + const uint32_t *pbuf = (const uint32_t *)buf; + printf("\n"); + for (int j = 0; j < sizeof(sha_result) / sizeof(sha_result[0]); j++) { + printf("0x%x(0x%x) ", pbuf[j], sha_result[j]); + } + printf("\n"); +#endif + + TEST_ASSERT(memcmp(buf, sha_result, sizeof(sha_result)) == 0); + + heap_caps_free(buf); +} + +TEST_CASE("Test SHA512", "[SHA]") +{ + int ret; + uint8_t *buf; + esp_sha512_t sha_ctx; + + const uint32_t sha_result[] = { + 0x153be81b, 0x37abc24e, 0x3b6f1a5b, 0x42c713f9, 0x51c9a8e1, 0x7303f29b, + 0x2c979121, 0x1c4e632d, 0xad470c5a, 0xe7643b5e, 0x63447f10, 0x05d613e6, + 0xa3c6b5cc, 0x99e52218, 0x665b659f, 0x1bfc639b + }; + + buf = heap_caps_malloc(1024, MALLOC_CAP_8BIT); + TEST_ASSERT(buf != NULL); + + memset(buf, 11, 1024); + + ret = esp_sha512_init(&sha_ctx); + TEST_ASSERT(ret == 0); + + ret = esp_sha512_update(&sha_ctx, buf, 1024); + TEST_ASSERT(ret == 0); + + memset(buf, 0, 1024); + ret = esp_sha512_finish(&sha_ctx, buf); + TEST_ASSERT(ret == 0); + +#if DEBUG_SHA_RESULT + const uint32_t *pbuf = (const uint32_t *)buf; + printf("\n"); + for (int j = 0; j < sizeof(sha_result) / sizeof(sha_result[0]); j++) { + printf("0x%x(0x%x) ", pbuf[j], sha_result[j]); + } + printf("\n"); +#endif + + TEST_ASSERT(memcmp(buf, sha_result, sizeof(sha_result)) == 0); + + heap_caps_free(buf); +} diff --git a/components/wpa_supplicant/include/crypto/sha1_i.h b/components/wpa_supplicant/include/crypto/sha1_i.h index ec2f82f7..15bd79f3 100644 --- a/components/wpa_supplicant/include/crypto/sha1_i.h +++ b/components/wpa_supplicant/include/crypto/sha1_i.h @@ -15,6 +15,17 @@ #ifndef SHA1_I_H #define SHA1_I_H +#include "sdkconfig.h" + +#ifdef CONFIG_ESP_SHA +#include "esp_sha.h" + +typedef esp_sha_t SHA1_CTX; + +#define SHA1Init(_sha) esp_sha1_init(_sha) +#define SHA1Update(_sha, _s, _l) esp_sha1_update(_sha, _s, _l) +#define SHA1Final(_d, _sha) esp_sha1_finish(_sha, _d) +#else /* CONFIG_ESP_SHA */ struct SHA1Context { u32 state[5]; u32 count[2]; @@ -25,5 +36,6 @@ void SHA1Init(struct SHA1Context *context); void SHA1Update(struct SHA1Context *context, const void *data, u32 len); void SHA1Final(unsigned char digest[20], struct SHA1Context *context); void SHA1Transform(u32 state[5], const unsigned char buffer[64]); +#endif /* CONFIG_ESP_SHA */ #endif /* SHA1_I_H */ diff --git a/components/wpa_supplicant/src/crypto/sha1-internal.c b/components/wpa_supplicant/src/crypto/sha1-internal.c index 7da5cbb9..23ee0fd7 100644 --- a/components/wpa_supplicant/src/crypto/sha1-internal.c +++ b/components/wpa_supplicant/src/crypto/sha1-internal.c @@ -20,10 +20,12 @@ #include "crypto/md5.h" #include "crypto/crypto.h" +#ifndef CONFIG_ESP_SHA typedef struct SHA1Context SHA1_CTX; void SHA1Transform(u32 state[5], const unsigned char buffer[64]); +#endif /** * sha1_vector - SHA-1 hash for data vector @@ -47,6 +49,7 @@ sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) } +#ifndef CONFIG_ESP_SHA /* ===== start - public domain SHA1 implementation ===== */ /* @@ -320,3 +323,4 @@ SHA1Final(unsigned char digest[20], SHA1_CTX* context) } /* ===== end - public domain SHA1 implementation ===== */ +#endif /* CONFIG_ESP_SHA */ diff --git a/components/wpa_supplicant/src/crypto/sha256-internal.c b/components/wpa_supplicant/src/crypto/sha256-internal.c index 9a1fca1c..8e56bdf8 100644 --- a/components/wpa_supplicant/src/crypto/sha256-internal.c +++ b/components/wpa_supplicant/src/crypto/sha256-internal.c @@ -18,19 +18,31 @@ #include "crypto/sha256.h" #include "crypto/crypto.h" +#include "sdkconfig.h" + +#ifdef CONFIG_ESP_SHA +#include "esp_sha.h" + +typedef esp_sha_t sha256_state_t; + +#define sha256_init(_sha) esp_sha256_init(_sha) +#define sha256_process(_sha, _s, _l) esp_sha256_update(_sha, _s, _l) +#define sha256_done(_sha, _d) esp_sha1_finish(_sha, _d) +#else /* CONFIG_ESP_SHA */ #define SHA256_BLOCK_SIZE 64 -struct sha256_state { +typedef struct sha256_state { u64 length; u32 state[8], curlen; u8 buf[SHA256_BLOCK_SIZE]; -}; +} sha256_state_t; static void sha256_init(struct sha256_state *md); static int sha256_process(struct sha256_state *md, const unsigned char *in, unsigned long inlen); static int sha256_done(struct sha256_state *md, unsigned char *out); +#endif /* CONFIG_ESP_SHA */ /** * sha256_vector - SHA256 hash for data vector @@ -44,7 +56,7 @@ int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac) { - struct sha256_state ctx; + sha256_state_t ctx; size_t i; sha256_init(&ctx); @@ -57,6 +69,7 @@ sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len, } +#ifndef CONFIG_ESP_SHA /* ===== start - public domain SHA256 implementation ===== */ /* This is based on SHA256 implementation in LibTomCrypt that was released into @@ -247,3 +260,4 @@ sha256_done(struct sha256_state *md, unsigned char *out) } /* ===== end - public domain SHA256 implementation ===== */ +#endif /* CONFIG_ESP_SHA */ diff --git a/components/wpa_supplicant/test/component.mk b/components/wpa_supplicant/test/component.mk new file mode 100644 index 00000000..5dd172bd --- /dev/null +++ b/components/wpa_supplicant/test/component.mk @@ -0,0 +1,5 @@ +# +#Component Makefile +# + +COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive diff --git a/components/wpa_supplicant/test/test_sha_vector.c b/components/wpa_supplicant/test/test_sha_vector.c new file mode 100644 index 00000000..d7f2acc9 --- /dev/null +++ b/components/wpa_supplicant/test/test_sha_vector.c @@ -0,0 +1,58 @@ +// Copyright 2018-2019 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. + +#include +#include +#include +#include "esp_log.h" +#include "unity.h" +#include "crypto/crypto.h" + +#define TEST_COUNT 1024 +#define TEST_DBG 1 + +TEST_CASE("Test SHA1 Vector", "[SHA1 Vector]") +{ + uint32_t test_time = 0; + const uint8_t result[20] = { + 0x01, 0xec, 0x29, 0xec, 0x5c, 0x60, 0xa4, 0xef, + 0xb1, 0x66, 0xa3, 0x84, 0x7a, 0x83, 0xce, 0x55, + 0x17, 0x18, 0x4a, 0x7f + }; + + extern uint32_t esp_get_time(void); + + for (int i = 0; i < TEST_COUNT; i++) { + uint32_t tmp; + char ssid[10] = "AFAST_IK"; + char count[10] = "kkkk"; + char *addr[2] = {ssid, count}; + size_t len[2] = {9, 4}; + uint8_t output[20]; + + tmp = esp_get_time(); + sha1_vector(2, (const uint8_t **)addr, len, output); + test_time += esp_get_time() - tmp; + + TEST_ASSERT_TRUE(memcmp(output, result, 20) == 0); + } + +#if TEST_DBG + printf("SHA1 vector test cost time totally %u us, once cost is about %u us\n", test_time, test_time / TEST_COUNT); +#endif +} + + +// new SHA1: SHA1 vector test cost time totally 77949 us, once cost is about 76 us +// old SHA1: SHA1 vector test cost time totally 95417 us, once cost is about 93 us