feat(util): Add extra SHA and unit test

1. wpa_supplicatn use extra SHA default
2. mbedtls use extra SHA default
3. bootloader use extra SHA default
4. user code can use extra SHA default

Above all, using unified module is easy to maintenance code and save rom or ram.
This commit is contained in:
dongheng
2019-04-01 19:11:41 +08:00
parent da6c51d298
commit 768afde238
17 changed files with 1452 additions and 205 deletions

View File

@ -218,217 +218,29 @@ void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest
#else #else
#include "bootloader_sha.h" #include "bootloader_sha.h"
#include <stdbool.h> #include "esp_sha.h"
#include <string.h>
#include <assert.h>
#include <sys/param.h>
typedef void* bootloader_sha256_handle_t; // typedef esp_sha_t* bootloader_sha256_handle_t;
// Code from mbedTLS sha256 static esp_sha_t s_sha256_ctx;
#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 );
}
bootloader_sha256_handle_t bootloader_sha256_start() 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)); esp_sha256_init(ctx);
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;
return ctx; return ctx;
} }
void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len) void bootloader_sha256_data(bootloader_sha256_handle_t handle, const void *data, size_t data_len)
{ {
mbedtls_sha256_context *ctx = (mbedtls_sha256_context *)handle; esp_sha256_update((esp_sha_t *)handle, data, data_len);
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 );
} }
void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest) void bootloader_sha256_finish(bootloader_sha256_handle_t handle, uint8_t *digest)
{ {
uint32_t last, padn; esp_sha256_finish((esp_sha_t *)handle, digest);
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 ;
} }
#endif #endif

View File

@ -118,7 +118,7 @@ set(COMPONENT_SRCS "${SRC}/crypto_aead/chacha20poly1305/sodium/aead_chacha20poly
"${SRC}/sodium/version.c" "${SRC}/sodium/version.c"
"port/randombytes_esp8266.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" list(APPEND COMPONENT_SRCS "port/crypto_hash_mbedtls/crypto_hash_sha256_mbedtls.c"
"port/crypto_hash_mbedtls/crypto_hash_sha512_mbedtls.c") "port/crypto_hash_mbedtls/crypto_hash_sha512_mbedtls.c")
else() else()

View File

@ -3,13 +3,13 @@ menu "libsodium"
config LIBSODIUM_USE_MBEDTLS_SHA config LIBSODIUM_USE_MBEDTLS_SHA
bool "Use mbedTLS SHA256 & SHA512 implementations" bool "Use mbedTLS SHA256 & SHA512 implementations"
default y default y
depends on !MBEDTLS_HARDWARE_SHA depends on !ESP_SHA
help help
If this option is enabled, libsodium will use thin wrappers If this option is enabled, libsodium will use thin wrappers
around mbedTLS for SHA256 & SHA512 operations. around mbedTLS for SHA256 & SHA512 operations.
This saves some code size if mbedTLS is also used. However it 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). way libsodium's API manages SHA state).
endmenu # libsodium endmenu # libsodium

View File

@ -58,7 +58,7 @@ COMPONENT_SRCDIRS += \
$(LSRC)/randombytes \ $(LSRC)/randombytes \
$(LSRC)/sodium $(LSRC)/sodium
ifdef CONFIG_SSL_USING_MBEDTLS ifdef CONFIG_LIBSODIUM_USE_MBEDTLS_SHA
COMPONENT_SRCDIRS += port/crypto_hash_mbedtls COMPONENT_SRCDIRS += port/crypto_hash_mbedtls
else else
COMPONENT_SRCDIRS += \ COMPONENT_SRCDIRS += \

View File

@ -290,10 +290,14 @@
//#define MBEDTLS_MD5_ALT //#define MBEDTLS_MD5_ALT
//#define MBEDTLS_RIPEMD160_ALT //#define MBEDTLS_RIPEMD160_ALT
//#define MBEDTLS_RSA_ALT //#define MBEDTLS_RSA_ALT
//#define MBEDTLS_SHA1_ALT
//#define MBEDTLS_SHA256_ALT
//#define MBEDTLS_SHA512_ALT
//#define MBEDTLS_XTEA_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 * When replacing the elliptic curve module, pleace consider, that it is
* implemented with two .c files: * implemented with two .c files:

View File

@ -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

View File

@ -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

View File

@ -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

15
components/util/Kconfig Normal file
View File

@ -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

View File

@ -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 <stdint.h>
#include <stddef.h>
#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

599
components/util/src/sha.c Normal file
View File

@ -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 <stdio.h>
#include <string.h>
#include <assert.h>
#include <sys/errno.h>
#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;
}

View File

@ -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 <string.h>
#include <stdio.h>
#include <assert.h>
#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);
}

View File

@ -15,6 +15,17 @@
#ifndef SHA1_I_H #ifndef SHA1_I_H
#define 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 { struct SHA1Context {
u32 state[5]; u32 state[5];
u32 count[2]; u32 count[2];
@ -25,5 +36,6 @@ void SHA1Init(struct SHA1Context *context);
void SHA1Update(struct SHA1Context *context, const void *data, u32 len); void SHA1Update(struct SHA1Context *context, const void *data, u32 len);
void SHA1Final(unsigned char digest[20], struct SHA1Context *context); void SHA1Final(unsigned char digest[20], struct SHA1Context *context);
void SHA1Transform(u32 state[5], const unsigned char buffer[64]); void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
#endif /* CONFIG_ESP_SHA */
#endif /* SHA1_I_H */ #endif /* SHA1_I_H */

View File

@ -20,10 +20,12 @@
#include "crypto/md5.h" #include "crypto/md5.h"
#include "crypto/crypto.h" #include "crypto/crypto.h"
#ifndef CONFIG_ESP_SHA
typedef struct SHA1Context SHA1_CTX; typedef struct SHA1Context SHA1_CTX;
void SHA1Transform(u32 state[5], const unsigned char buffer[64]); void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
#endif
/** /**
* sha1_vector - SHA-1 hash for data vector * 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 ===== */ /* ===== start - public domain SHA1 implementation ===== */
/* /*
@ -320,3 +323,4 @@ SHA1Final(unsigned char digest[20], SHA1_CTX* context)
} }
/* ===== end - public domain SHA1 implementation ===== */ /* ===== end - public domain SHA1 implementation ===== */
#endif /* CONFIG_ESP_SHA */

View File

@ -18,19 +18,31 @@
#include "crypto/sha256.h" #include "crypto/sha256.h"
#include "crypto/crypto.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 #define SHA256_BLOCK_SIZE 64
struct sha256_state { typedef struct sha256_state {
u64 length; u64 length;
u32 state[8], curlen; u32 state[8], curlen;
u8 buf[SHA256_BLOCK_SIZE]; u8 buf[SHA256_BLOCK_SIZE];
}; } sha256_state_t;
static void sha256_init(struct sha256_state *md); static void sha256_init(struct sha256_state *md);
static int sha256_process(struct sha256_state *md, const unsigned char *in, static int sha256_process(struct sha256_state *md, const unsigned char *in,
unsigned long inlen); unsigned long inlen);
static int sha256_done(struct sha256_state *md, unsigned char *out); static int sha256_done(struct sha256_state *md, unsigned char *out);
#endif /* CONFIG_ESP_SHA */
/** /**
* sha256_vector - SHA256 hash for data vector * 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, sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
u8 *mac) u8 *mac)
{ {
struct sha256_state ctx; sha256_state_t ctx;
size_t i; size_t i;
sha256_init(&ctx); 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 ===== */ /* ===== start - public domain SHA256 implementation ===== */
/* This is based on SHA256 implementation in LibTomCrypt that was released into /* 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 ===== */ /* ===== end - public domain SHA256 implementation ===== */
#endif /* CONFIG_ESP_SHA */

View File

@ -0,0 +1,5 @@
#
#Component Makefile
#
COMPONENT_ADD_LDFLAGS = -Wl,--whole-archive -l$(COMPONENT_NAME) -Wl,--no-whole-archive

View File

@ -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 <string.h>
#include <stdio.h>
#include <assert.h>
#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