mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-07-10 09:50:51 +02:00
6016cc0c97
Make testing digests consistent. Add KATs for all digests. Check unaligned input and output works. Perform chunking tests for all digests. Fix Blake2b and Blake2s to checkout parameters in update and final functions. Fix Shake256 and Shake128 to checkout parameters in absorb and squeeze blocks functions. Add default digest size enums for Blake2b and Blake2s.
2628 lines
82 KiB
C
2628 lines
82 KiB
C
/* sha256.c
|
|
*
|
|
* Copyright (C) 2006-2025 wolfSSL Inc.
|
|
*
|
|
* This file is part of wolfSSL.
|
|
*
|
|
* wolfSSL is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 2 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* wolfSSL is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
|
|
*/
|
|
|
|
/* For more info on the algorithm, see https://tools.ietf.org/html/rfc6234
|
|
*
|
|
* For more information on NIST FIPS PUB 180-4, see
|
|
* https://nvlpubs.nist.gov/nistpubs/FIPS/NIST.FIPS.180-4.pdf
|
|
*/
|
|
|
|
/*
|
|
|
|
DESCRIPTION
|
|
This library provides the interface to SHA-256 secure hash algorithms.
|
|
SHA-256 performs processing on message blocks to produce a final hash digest
|
|
output. It can be used to hash a message, M, having a length of L bits,
|
|
where 0 <= L < 2^64.
|
|
|
|
Note that in some cases, hardware acceleration may be enabled, depending
|
|
on the specific device platform.
|
|
|
|
*/
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
#include <wolfssl/wolfcrypt/settings.h>
|
|
#include <wolfssl/wolfcrypt/types.h>
|
|
|
|
/*
|
|
* SHA256 Build Options:
|
|
* USE_SLOW_SHA256: Reduces code size by not partially unrolling
|
|
(~2KB smaller and ~25% slower) (default OFF)
|
|
* WOLFSSL_SHA256_BY_SPEC: Uses the Ch/Maj based on SHA256 specification
|
|
(default ON)
|
|
* WOLFSSL_SHA256_ALT_CH_MAJ: Alternate Ch/Maj that is easier for compilers to
|
|
optimize and recognize as SHA256 (default OFF)
|
|
* SHA256_MANY_REGISTERS: A SHA256 version that keeps all data in registers
|
|
and partial unrolled (default OFF)
|
|
*/
|
|
|
|
/* Default SHA256 to use Ch/Maj based on specification */
|
|
#if !defined(WOLFSSL_SHA256_BY_SPEC) && !defined(WOLFSSL_SHA256_ALT_CH_MAJ)
|
|
#define WOLFSSL_SHA256_BY_SPEC
|
|
#endif
|
|
|
|
|
|
#if !defined(NO_SHA256) && !(defined(WOLFSSL_ARMASM) || \
|
|
defined(WOLFSSL_ARMASM_NO_NEON)) && !defined(WOLFSSL_RISCV_ASM)
|
|
|
|
#if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
|
|
/* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
|
|
#define FIPS_NO_WRAPPERS
|
|
|
|
#ifdef USE_WINDOWS_API
|
|
#pragma code_seg(".fipsA$l")
|
|
#pragma const_seg(".fipsB$l")
|
|
#endif
|
|
#endif
|
|
|
|
#include <wolfssl/wolfcrypt/sha256.h>
|
|
#include <wolfssl/wolfcrypt/error-crypt.h>
|
|
#include <wolfssl/wolfcrypt/cpuid.h>
|
|
#include <wolfssl/wolfcrypt/hash.h>
|
|
|
|
#ifdef WOLF_CRYPTO_CB
|
|
#include <wolfssl/wolfcrypt/cryptocb.h>
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_IMXRT1170_CAAM
|
|
#include <wolfssl/wolfcrypt/port/caam/wolfcaam_fsl_nxp.h>
|
|
#endif
|
|
|
|
|
|
/* determine if we are using Espressif SHA hardware acceleration */
|
|
#undef WOLFSSL_USE_ESP32_CRYPT_HASH_HW
|
|
#if defined(WOLFSSL_ESP32_CRYPT) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH)
|
|
/* define a single keyword for simplicity & readability
|
|
*
|
|
* by default the HW acceleration is on for ESP32-WROOM32
|
|
* but individual components can be turned off.
|
|
*/
|
|
#define WOLFSSL_USE_ESP32_CRYPT_HASH_HW
|
|
#else
|
|
#undef WOLFSSL_USE_ESP32_CRYPT_HASH_HW
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_ESPIDF
|
|
/* Define the ESP_LOGx(TAG, WOLFSSL_ESPIDF_BLANKLINE_MESSAGE value for output messages here.
|
|
**
|
|
** Beware of possible conflict in test.c (that one now named TEST_TAG)
|
|
*/
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256)
|
|
static const char* TAG = "wc_sha256";
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_TI_HASH)
|
|
/* #include <wolfcrypt/src/port/ti/ti-hash.c> included by wc_port.c */
|
|
#elif defined(WOLFSSL_CRYPTOCELL)
|
|
/* wc_port.c includes wolfcrypt/src/port/arm/cryptoCellHash.c */
|
|
|
|
#elif defined(WOLFSSL_PSOC6_CRYPTO)
|
|
|
|
#elif defined(MAX3266X_SHA)
|
|
/* Already brought in by sha256.h */
|
|
/* #include <wolfssl/wolfcrypt/port/maxim/max3266x.h> */
|
|
#else
|
|
|
|
#include <wolfssl/wolfcrypt/logging.h>
|
|
|
|
#ifdef NO_INLINE
|
|
#include <wolfssl/wolfcrypt/misc.h>
|
|
#else
|
|
#define WOLFSSL_MISC_INCLUDED
|
|
#include <wolfcrypt/src/misc.c>
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_DEVCRYPTO_HASH
|
|
#include <wolfssl/wolfcrypt/port/devcrypto/wc_devcrypto.h>
|
|
#endif
|
|
#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_HASH)
|
|
#include <wolfssl/wolfcrypt/port/nxp/se050_port.h>
|
|
#endif
|
|
|
|
#if FIPS_VERSION3_GE(6,0,0)
|
|
const unsigned int wolfCrypt_FIPS_sha256_ro_sanity[2] =
|
|
{ 0x1a2b3c4d, 0x00000014 };
|
|
int wolfCrypt_FIPS_SHA256_sanity(void)
|
|
{
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP)
|
|
#if defined(__GNUC__) && ((__GNUC__ < 4) || \
|
|
(__GNUC__ == 4 && __GNUC_MINOR__ <= 8))
|
|
#undef NO_AVX2_SUPPORT
|
|
#define NO_AVX2_SUPPORT
|
|
#endif
|
|
#if defined(__clang__) && ((__clang_major__ < 3) || \
|
|
(__clang_major__ == 3 && __clang_minor__ <= 5))
|
|
#define NO_AVX2_SUPPORT
|
|
#elif defined(__clang__) && defined(NO_AVX2_SUPPORT)
|
|
#undef NO_AVX2_SUPPORT
|
|
#endif
|
|
|
|
#define HAVE_INTEL_AVX1
|
|
#ifndef NO_AVX2_SUPPORT
|
|
#define HAVE_INTEL_AVX2
|
|
#endif
|
|
#else
|
|
#undef HAVE_INTEL_AVX1
|
|
#undef HAVE_INTEL_AVX2
|
|
#endif /* WOLFSSL_X86_64_BUILD && USE_INTEL_SPEEDUP */
|
|
|
|
#if defined(HAVE_INTEL_AVX2)
|
|
#define HAVE_INTEL_RORX
|
|
#endif
|
|
|
|
#if defined(LITTLE_ENDIAN_ORDER)
|
|
#if ( defined(CONFIG_IDF_TARGET_ESP32C2) || \
|
|
defined(CONFIG_IDF_TARGET_ESP8684) || \
|
|
defined(CONFIG_IDF_TARGET_ESP32C3) || \
|
|
defined(CONFIG_IDF_TARGET_ESP32C6) \
|
|
) && \
|
|
defined(WOLFSSL_ESP32_CRYPT) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256)
|
|
/* For Espressif RISC-V Targets, we *may* need to reverse bytes
|
|
* depending on if HW is active or not. */
|
|
#define SHA256_REV_BYTES(ctx) \
|
|
(esp_sha_need_byte_reversal(ctx))
|
|
#elif defined(FREESCALE_MMCAU_SHA)
|
|
#define SHA256_REV_BYTES(ctx) 1 /* reverse needed on final */
|
|
#endif
|
|
#endif
|
|
#ifndef SHA256_REV_BYTES
|
|
#if defined(LITTLE_ENDIAN_ORDER)
|
|
#define SHA256_REV_BYTES(ctx) 1
|
|
#else
|
|
#define SHA256_REV_BYTES(ctx) 0
|
|
#endif
|
|
#endif
|
|
#if defined(LITTLE_ENDIAN_ORDER) && \
|
|
defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
|
|
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))
|
|
#ifdef WC_C_DYNAMIC_FALLBACK
|
|
#define SHA256_UPDATE_REV_BYTES(ctx) (sha256->sha_method == SHA256_C)
|
|
#else
|
|
#define SHA256_UPDATE_REV_BYTES(ctx) \
|
|
(!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
|
|
#endif
|
|
#elif defined(FREESCALE_MMCAU_SHA)
|
|
#define SHA256_UPDATE_REV_BYTES(ctx) 0 /* reverse not needed on update */
|
|
#else
|
|
#define SHA256_UPDATE_REV_BYTES(ctx) SHA256_REV_BYTES(ctx)
|
|
#endif
|
|
|
|
|
|
#if !defined(WOLFSSL_PIC32MZ_HASH) && !defined(STM32_HASH_SHA2) && \
|
|
(!defined(WOLFSSL_IMX6_CAAM) || defined(NO_IMX6_CAAM_HASH) || \
|
|
defined(WOLFSSL_QNX_CAAM)) && \
|
|
!defined(WOLFSSL_AFALG_HASH) && !defined(WOLFSSL_DEVCRYPTO_HASH) && \
|
|
(!defined(WOLFSSL_ESP32_CRYPT) || defined(NO_WOLFSSL_ESP32_CRYPT_HASH)) && \
|
|
((!defined(WOLFSSL_RENESAS_TSIP_TLS) && \
|
|
!defined(WOLFSSL_RENESAS_TSIP_CRYPTONLY)) || \
|
|
defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH)) && \
|
|
!defined(WOLFSSL_PSOC6_CRYPTO) && !defined(WOLFSSL_IMXRT_DCP) && !defined(WOLFSSL_SILABS_SE_ACCEL) && \
|
|
!defined(WOLFSSL_KCAPI_HASH) && !defined(WOLFSSL_SE050_HASH) && \
|
|
((!defined(WOLFSSL_RENESAS_SCEPROTECT) && \
|
|
!defined(WOLFSSL_RENESAS_RSIP)) \
|
|
|| defined(NO_WOLFSSL_RENESAS_FSPSM_HASH)) && \
|
|
(!defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH)) && \
|
|
!defined(WOLFSSL_RENESAS_RX64_HASH)
|
|
|
|
#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
|
|
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))
|
|
#ifdef WC_C_DYNAMIC_FALLBACK
|
|
#define SHA256_SETTRANSFORM_ARGS int *sha_method
|
|
#else
|
|
#define SHA256_SETTRANSFORM_ARGS void
|
|
#endif
|
|
static void Sha256_SetTransform(SHA256_SETTRANSFORM_ARGS);
|
|
#endif
|
|
|
|
static int InitSha256(wc_Sha256* sha256)
|
|
{
|
|
XMEMSET(sha256->digest, 0, sizeof(sha256->digest));
|
|
sha256->digest[0] = 0x6A09E667L;
|
|
sha256->digest[1] = 0xBB67AE85L;
|
|
sha256->digest[2] = 0x3C6EF372L;
|
|
sha256->digest[3] = 0xA54FF53AL;
|
|
sha256->digest[4] = 0x510E527FL;
|
|
sha256->digest[5] = 0x9B05688CL;
|
|
sha256->digest[6] = 0x1F83D9ABL;
|
|
sha256->digest[7] = 0x5BE0CD19L;
|
|
|
|
sha256->buffLen = 0;
|
|
sha256->loLen = 0;
|
|
sha256->hiLen = 0;
|
|
#ifdef WOLFSSL_HASH_FLAGS
|
|
sha256->flags = 0;
|
|
#endif
|
|
#ifdef WOLFSSL_HASH_KEEP
|
|
sha256->msg = NULL;
|
|
sha256->len = 0;
|
|
sha256->used = 0;
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
|
|
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))
|
|
/* choose best Transform function under this runtime environment */
|
|
#ifdef WC_C_DYNAMIC_FALLBACK
|
|
sha256->sha_method = 0;
|
|
Sha256_SetTransform(&sha256->sha_method);
|
|
#else
|
|
Sha256_SetTransform();
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_MAXQ10XX_CRYPTO
|
|
XMEMSET(&sha256->maxq_ctx, 0, sizeof(sha256->maxq_ctx));
|
|
#endif
|
|
|
|
#ifdef HAVE_ARIA
|
|
sha256->hSession = NULL;
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
|
|
/* Hardware Acceleration */
|
|
#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
|
|
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))
|
|
|
|
/* in case intel instructions aren't available, plus we need the K[] global */
|
|
#define NEED_SOFT_SHA256
|
|
|
|
/*****
|
|
Intel AVX1/AVX2 Macro Control Structure
|
|
|
|
#define HAVE_INTEL_AVX1
|
|
#define HAVE_INTEL_AVX2
|
|
|
|
#define HAVE_INTEL_RORX
|
|
|
|
|
|
int InitSha256(wc_Sha256* sha256) {
|
|
Save/Recover XMM, YMM
|
|
...
|
|
}
|
|
|
|
#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2)
|
|
Transform_Sha256(); Function prototype
|
|
#else
|
|
Transform_Sha256() { }
|
|
int Sha256Final() {
|
|
Save/Recover XMM, YMM
|
|
...
|
|
}
|
|
#endif
|
|
|
|
#if defined(HAVE_INTEL_AVX1)|| defined(HAVE_INTEL_AVX2)
|
|
#if defined(HAVE_INTEL_RORX
|
|
#define RND with rorx instruction
|
|
#else
|
|
#define RND
|
|
#endif
|
|
#endif
|
|
|
|
#if defined(HAVE_INTEL_AVX1)
|
|
|
|
#define XMM Instructions/inline asm
|
|
|
|
int Transform_Sha256() {
|
|
Stitched Message Sched/Round
|
|
}
|
|
|
|
#elif defined(HAVE_INTEL_AVX2)
|
|
|
|
#define YMM Instructions/inline asm
|
|
|
|
int Transform_Sha256() {
|
|
More granular Stitched Message Sched/Round
|
|
}
|
|
|
|
#endif
|
|
|
|
*/
|
|
|
|
/* Each platform needs to query info type 1 from cpuid to see if aesni is
|
|
* supported. Also, let's setup a macro for proper linkage w/o ABI conflicts
|
|
*/
|
|
|
|
/* #if defined(HAVE_INTEL_AVX1/2) at the tail of sha256 */
|
|
static int Transform_Sha256(wc_Sha256* sha256, const byte* data);
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
extern int Transform_Sha256_SSE2_Sha(wc_Sha256 *sha256,
|
|
const byte* data);
|
|
extern int Transform_Sha256_SSE2_Sha_Len(wc_Sha256* sha256,
|
|
const byte* data, word32 len);
|
|
#if defined(HAVE_INTEL_AVX1)
|
|
extern int Transform_Sha256_AVX1_Sha(wc_Sha256 *sha256,
|
|
const byte* data);
|
|
extern int Transform_Sha256_AVX1_Sha_Len(wc_Sha256* sha256,
|
|
const byte* data, word32 len);
|
|
extern int Transform_Sha256_AVX1(wc_Sha256 *sha256, const byte* data);
|
|
extern int Transform_Sha256_AVX1_Len(wc_Sha256* sha256,
|
|
const byte* data, word32 len);
|
|
#endif
|
|
#if defined(HAVE_INTEL_AVX2)
|
|
extern int Transform_Sha256_AVX2(wc_Sha256 *sha256, const byte* data);
|
|
extern int Transform_Sha256_AVX2_Len(wc_Sha256* sha256,
|
|
const byte* data, word32 len);
|
|
#ifdef HAVE_INTEL_RORX
|
|
extern int Transform_Sha256_AVX1_RORX(wc_Sha256 *sha256, const byte* data);
|
|
extern int Transform_Sha256_AVX1_RORX_Len(wc_Sha256* sha256,
|
|
const byte* data, word32 len);
|
|
extern int Transform_Sha256_AVX2_RORX(wc_Sha256 *sha256, const byte* data);
|
|
extern int Transform_Sha256_AVX2_RORX_Len(wc_Sha256* sha256,
|
|
const byte* data, word32 len);
|
|
#endif /* HAVE_INTEL_RORX */
|
|
#endif /* HAVE_INTEL_AVX2 */
|
|
|
|
#ifdef __cplusplus
|
|
} /* extern "C" */
|
|
#endif
|
|
|
|
static word32 intel_flags = 0;
|
|
|
|
#if defined(WC_C_DYNAMIC_FALLBACK) && !defined(WC_NO_INTERNAL_FUNCTION_POINTERS)
|
|
#define WC_NO_INTERNAL_FUNCTION_POINTERS
|
|
#endif
|
|
|
|
#ifdef WC_NO_INTERNAL_FUNCTION_POINTERS
|
|
|
|
enum sha_methods { SHA256_UNSET = 0, SHA256_AVX1_SHA, SHA256_AVX2,
|
|
SHA256_AVX1_RORX, SHA256_AVX1_NOSHA, SHA256_AVX2_RORX,
|
|
SHA256_SSE2, SHA256_C };
|
|
|
|
#ifndef WC_C_DYNAMIC_FALLBACK
|
|
/* note that all write access to this static variable must be idempotent,
|
|
* as arranged by Sha256_SetTransform(), else it will be susceptible to
|
|
* data races.
|
|
*/
|
|
static enum sha_methods sha_method = SHA256_UNSET;
|
|
#endif
|
|
|
|
static void Sha256_SetTransform(SHA256_SETTRANSFORM_ARGS)
|
|
{
|
|
#ifdef WC_C_DYNAMIC_FALLBACK
|
|
#define SHA_METHOD (*sha_method)
|
|
#else
|
|
#define SHA_METHOD sha_method
|
|
#endif
|
|
if (SHA_METHOD != SHA256_UNSET)
|
|
return;
|
|
|
|
#ifdef WC_C_DYNAMIC_FALLBACK
|
|
if (! CAN_SAVE_VECTOR_REGISTERS()) {
|
|
SHA_METHOD = SHA256_C;
|
|
return;
|
|
}
|
|
#endif
|
|
|
|
if (intel_flags == 0)
|
|
intel_flags = cpuid_get_flags();
|
|
|
|
if (IS_INTEL_SHA(intel_flags)) {
|
|
#ifdef HAVE_INTEL_AVX1
|
|
if (IS_INTEL_AVX1(intel_flags)) {
|
|
SHA_METHOD = SHA256_AVX1_SHA;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
SHA_METHOD = SHA256_SSE2;
|
|
}
|
|
}
|
|
else
|
|
#ifdef HAVE_INTEL_AVX2
|
|
if (IS_INTEL_AVX2(intel_flags)) {
|
|
#ifdef HAVE_INTEL_RORX
|
|
if (IS_INTEL_BMI2(intel_flags)) {
|
|
SHA_METHOD = SHA256_AVX2_RORX;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
SHA_METHOD = SHA256_AVX2;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
#ifdef HAVE_INTEL_AVX1
|
|
if (IS_INTEL_AVX1(intel_flags)) {
|
|
#ifdef HAVE_INTEL_RORX
|
|
if (IS_INTEL_BMI2(intel_flags)) {
|
|
SHA_METHOD = SHA256_AVX1_RORX;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
SHA_METHOD = SHA256_AVX1_NOSHA;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
SHA_METHOD = SHA256_C;
|
|
}
|
|
#undef SHA_METHOD
|
|
}
|
|
|
|
static WC_INLINE int inline_XTRANSFORM(wc_Sha256* S, const byte* D) {
|
|
#ifdef WC_C_DYNAMIC_FALLBACK
|
|
#define SHA_METHOD (S->sha_method)
|
|
#else
|
|
#define SHA_METHOD sha_method
|
|
#endif
|
|
int ret;
|
|
|
|
if (SHA_METHOD == SHA256_C)
|
|
return Transform_Sha256(S, D);
|
|
SAVE_VECTOR_REGISTERS(return _svr_ret;);
|
|
switch (SHA_METHOD) {
|
|
case SHA256_AVX2:
|
|
ret = Transform_Sha256_AVX2(S, D);
|
|
break;
|
|
case SHA256_AVX2_RORX:
|
|
ret = Transform_Sha256_AVX2_RORX(S, D);
|
|
break;
|
|
case SHA256_AVX1_SHA:
|
|
ret = Transform_Sha256_AVX1_Sha(S, D);
|
|
break;
|
|
case SHA256_AVX1_NOSHA:
|
|
ret = Transform_Sha256_AVX1(S, D);
|
|
break;
|
|
case SHA256_AVX1_RORX:
|
|
ret = Transform_Sha256_AVX1_RORX(S, D);
|
|
break;
|
|
case SHA256_SSE2:
|
|
ret = Transform_Sha256_SSE2_Sha(S, D);
|
|
break;
|
|
case SHA256_C:
|
|
case SHA256_UNSET:
|
|
default:
|
|
ret = Transform_Sha256(S, D);
|
|
break;
|
|
}
|
|
RESTORE_VECTOR_REGISTERS();
|
|
return ret;
|
|
#undef SHA_METHOD
|
|
}
|
|
#define XTRANSFORM(...) inline_XTRANSFORM(__VA_ARGS__)
|
|
|
|
static WC_INLINE int inline_XTRANSFORM_LEN(wc_Sha256* S, const byte* D, word32 L) {
|
|
#ifdef WC_C_DYNAMIC_FALLBACK
|
|
#define SHA_METHOD (S->sha_method)
|
|
#else
|
|
#define SHA_METHOD sha_method
|
|
#endif
|
|
int ret;
|
|
SAVE_VECTOR_REGISTERS(return _svr_ret;);
|
|
switch (SHA_METHOD) {
|
|
case SHA256_AVX2:
|
|
ret = Transform_Sha256_AVX2_Len(S, D, L);
|
|
break;
|
|
case SHA256_AVX2_RORX:
|
|
ret = Transform_Sha256_AVX2_RORX_Len(S, D, L);
|
|
break;
|
|
case SHA256_AVX1_SHA:
|
|
ret = Transform_Sha256_AVX1_Sha_Len(S, D, L);
|
|
break;
|
|
case SHA256_AVX1_NOSHA:
|
|
ret = Transform_Sha256_AVX1_Len(S, D, L);
|
|
break;
|
|
case SHA256_AVX1_RORX:
|
|
ret = Transform_Sha256_AVX1_RORX_Len(S, D, L);
|
|
break;
|
|
case SHA256_SSE2:
|
|
ret = Transform_Sha256_SSE2_Sha_Len(S, D, L);
|
|
break;
|
|
case SHA256_C:
|
|
case SHA256_UNSET:
|
|
default:
|
|
ret = 0;
|
|
break;
|
|
}
|
|
RESTORE_VECTOR_REGISTERS();
|
|
return ret;
|
|
#undef SHA_METHOD
|
|
}
|
|
#define XTRANSFORM_LEN(...) inline_XTRANSFORM_LEN(__VA_ARGS__)
|
|
|
|
#else /* !WC_NO_INTERNAL_FUNCTION_POINTERS */
|
|
|
|
static int (*Transform_Sha256_p)(wc_Sha256* sha256, const byte* data);
|
|
/* = _Transform_Sha256 */
|
|
static int (*Transform_Sha256_Len_p)(wc_Sha256* sha256, const byte* data,
|
|
word32 len);
|
|
/* = NULL */
|
|
static int transform_check = 0;
|
|
static int Transform_Sha256_is_vectorized = 0;
|
|
|
|
static WC_INLINE int inline_XTRANSFORM(wc_Sha256* S, const byte* D) {
|
|
int ret;
|
|
#ifdef WOLFSSL_LINUXKM
|
|
if (Transform_Sha256_is_vectorized)
|
|
SAVE_VECTOR_REGISTERS(return _svr_ret;);
|
|
#endif
|
|
ret = (*Transform_Sha256_p)(S, D);
|
|
#ifdef WOLFSSL_LINUXKM
|
|
if (Transform_Sha256_is_vectorized)
|
|
RESTORE_VECTOR_REGISTERS();
|
|
#endif
|
|
return ret;
|
|
}
|
|
#define XTRANSFORM(...) inline_XTRANSFORM(__VA_ARGS__)
|
|
|
|
static WC_INLINE int inline_XTRANSFORM_LEN(wc_Sha256* S, const byte* D, word32 L) {
|
|
int ret;
|
|
#ifdef WOLFSSL_LINUXKM
|
|
if (Transform_Sha256_is_vectorized)
|
|
SAVE_VECTOR_REGISTERS(return _svr_ret;);
|
|
#endif
|
|
ret = (*Transform_Sha256_Len_p)(S, D, L);
|
|
#ifdef WOLFSSL_LINUXKM
|
|
if (Transform_Sha256_is_vectorized)
|
|
RESTORE_VECTOR_REGISTERS();
|
|
#endif
|
|
return ret;
|
|
}
|
|
#define XTRANSFORM_LEN(...) inline_XTRANSFORM_LEN(__VA_ARGS__)
|
|
|
|
static void Sha256_SetTransform(void)
|
|
{
|
|
|
|
if (transform_check)
|
|
return;
|
|
|
|
intel_flags = cpuid_get_flags();
|
|
|
|
if (IS_INTEL_SHA(intel_flags)) {
|
|
#ifdef HAVE_INTEL_AVX1
|
|
if (IS_INTEL_AVX1(intel_flags)) {
|
|
Transform_Sha256_p = Transform_Sha256_AVX1_Sha;
|
|
Transform_Sha256_Len_p = Transform_Sha256_AVX1_Sha_Len;
|
|
Transform_Sha256_is_vectorized = 1;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
Transform_Sha256_p = Transform_Sha256_SSE2_Sha;
|
|
Transform_Sha256_Len_p = Transform_Sha256_SSE2_Sha_Len;
|
|
Transform_Sha256_is_vectorized = 1;
|
|
}
|
|
}
|
|
else
|
|
#ifdef HAVE_INTEL_AVX2
|
|
if (IS_INTEL_AVX2(intel_flags)) {
|
|
#ifdef HAVE_INTEL_RORX
|
|
if (IS_INTEL_BMI2(intel_flags)) {
|
|
Transform_Sha256_p = Transform_Sha256_AVX2_RORX;
|
|
Transform_Sha256_Len_p = Transform_Sha256_AVX2_RORX_Len;
|
|
Transform_Sha256_is_vectorized = 1;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
Transform_Sha256_p = Transform_Sha256_AVX2;
|
|
Transform_Sha256_Len_p = Transform_Sha256_AVX2_Len;
|
|
Transform_Sha256_is_vectorized = 1;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
#ifdef HAVE_INTEL_AVX1
|
|
if (IS_INTEL_AVX1(intel_flags)) {
|
|
#ifdef HAVE_INTEL_RORX
|
|
if (IS_INTEL_BMI2(intel_flags)) {
|
|
Transform_Sha256_p = Transform_Sha256_AVX1_RORX;
|
|
Transform_Sha256_Len_p = Transform_Sha256_AVX1_RORX_Len;
|
|
Transform_Sha256_is_vectorized = 1;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
Transform_Sha256_p = Transform_Sha256_AVX1;
|
|
Transform_Sha256_Len_p = Transform_Sha256_AVX1_Len;
|
|
Transform_Sha256_is_vectorized = 1;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
Transform_Sha256_p = Transform_Sha256;
|
|
Transform_Sha256_Len_p = NULL;
|
|
Transform_Sha256_is_vectorized = 0;
|
|
}
|
|
|
|
transform_check = 1;
|
|
}
|
|
|
|
#endif /* !WC_NO_INTERNAL_FUNCTION_POINTERS */
|
|
|
|
#if !defined(WOLFSSL_KCAPI_HASH)
|
|
int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
|
|
{
|
|
int ret = 0;
|
|
if (sha256 == NULL)
|
|
return BAD_FUNC_ARG;
|
|
|
|
sha256->heap = heap;
|
|
#ifdef WOLF_CRYPTO_CB
|
|
sha256->devId = devId;
|
|
sha256->devCtx = NULL;
|
|
#endif
|
|
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
|
sha256->W = NULL;
|
|
#endif
|
|
|
|
ret = InitSha256(sha256);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
|
|
ret = wolfAsync_DevCtxInit(&sha256->asyncDev,
|
|
WOLFSSL_ASYNC_MARKER_SHA256, sha256->heap, devId);
|
|
#else
|
|
(void)devId;
|
|
#endif /* WOLFSSL_ASYNC_CRYPT */
|
|
|
|
return ret;
|
|
}
|
|
#endif /* !WOLFSSL_KCAPI_HASH */
|
|
|
|
#elif defined(FREESCALE_LTC_SHA)
|
|
int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
|
|
{
|
|
(void)heap;
|
|
(void)devId;
|
|
|
|
LTC_HASH_Init(LTC_BASE, &sha256->ctx, kLTC_Sha256, NULL, 0);
|
|
|
|
return 0;
|
|
}
|
|
|
|
#elif defined(FREESCALE_MMCAU_SHA)
|
|
|
|
#ifdef FREESCALE_MMCAU_CLASSIC_SHA
|
|
#include "cau_api.h"
|
|
#else
|
|
#include "fsl_mmcau.h"
|
|
#endif
|
|
|
|
#define XTRANSFORM(S, D) Transform_Sha256((S),(D))
|
|
#define XTRANSFORM_LEN(S, D, L) Transform_Sha256_Len((S),(D),(L))
|
|
|
|
#ifndef WC_HASH_DATA_ALIGNMENT
|
|
/* these hardware API's require 4 byte (word32) alignment */
|
|
#define WC_HASH_DATA_ALIGNMENT 4
|
|
#endif
|
|
|
|
int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
|
|
{
|
|
int ret = 0;
|
|
|
|
(void)heap;
|
|
(void)devId;
|
|
|
|
ret = wolfSSL_CryptHwMutexLock();
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
#ifdef FREESCALE_MMCAU_CLASSIC_SHA
|
|
cau_sha256_initialize_output(sha256->digest);
|
|
#else
|
|
MMCAU_SHA256_InitializeOutput((uint32_t*)sha256->digest);
|
|
#endif
|
|
wolfSSL_CryptHwMutexUnLock();
|
|
|
|
sha256->buffLen = 0;
|
|
sha256->loLen = 0;
|
|
sha256->hiLen = 0;
|
|
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
|
sha256->W = NULL;
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int Transform_Sha256(wc_Sha256* sha256, const byte* data)
|
|
{
|
|
int ret = wolfSSL_CryptHwMutexLock();
|
|
if (ret == 0) {
|
|
#ifdef FREESCALE_MMCAU_CLASSIC_SHA
|
|
cau_sha256_hash_n((byte*)data, 1, sha256->digest);
|
|
#else
|
|
MMCAU_SHA256_HashN((byte*)data, 1, (uint32_t*)sha256->digest);
|
|
#endif
|
|
wolfSSL_CryptHwMutexUnLock();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
static int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
|
|
word32 len)
|
|
{
|
|
int ret = wolfSSL_CryptHwMutexLock();
|
|
if (ret == 0) {
|
|
#if defined(WC_HASH_DATA_ALIGNMENT) && WC_HASH_DATA_ALIGNMENT > 0
|
|
if ((wc_ptr_t)data % WC_HASH_DATA_ALIGNMENT) {
|
|
/* data pointer is NOT aligned,
|
|
* so copy and perform one block at a time */
|
|
byte* local = (byte*)sha256->buffer;
|
|
while (len >= WC_SHA256_BLOCK_SIZE) {
|
|
XMEMCPY(local, data, WC_SHA256_BLOCK_SIZE);
|
|
#ifdef FREESCALE_MMCAU_CLASSIC_SHA
|
|
cau_sha256_hash_n(local, 1, sha256->digest);
|
|
#else
|
|
MMCAU_SHA256_HashN(local, 1, (uint32_t*)sha256->digest);
|
|
#endif
|
|
data += WC_SHA256_BLOCK_SIZE;
|
|
len -= WC_SHA256_BLOCK_SIZE;
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
#ifdef FREESCALE_MMCAU_CLASSIC_SHA
|
|
cau_sha256_hash_n((byte*)data, len/WC_SHA256_BLOCK_SIZE,
|
|
sha256->digest);
|
|
#else
|
|
MMCAU_SHA256_HashN((byte*)data, len/WC_SHA256_BLOCK_SIZE,
|
|
(uint32_t*)sha256->digest);
|
|
#endif
|
|
}
|
|
wolfSSL_CryptHwMutexUnLock();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
#elif defined(WOLFSSL_PIC32MZ_HASH)
|
|
#include <wolfssl/wolfcrypt/port/pic32/pic32mz-crypt.h>
|
|
|
|
#elif defined(STM32_HASH_SHA2)
|
|
|
|
/* Supports CubeMX HAL or Standard Peripheral Library */
|
|
|
|
int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
|
|
{
|
|
if (sha256 == NULL)
|
|
return BAD_FUNC_ARG;
|
|
|
|
(void)devId;
|
|
(void)heap;
|
|
|
|
XMEMSET(sha256, 0, sizeof(wc_Sha256));
|
|
wc_Stm32_Hash_Init(&sha256->stmCtx);
|
|
return 0;
|
|
}
|
|
|
|
int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (sha256 == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
if (data == NULL && len == 0) {
|
|
/* valid, but do nothing */
|
|
return 0;
|
|
}
|
|
if (data == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
ret = wolfSSL_CryptHwMutexLock();
|
|
if (ret == 0) {
|
|
ret = wc_Stm32_Hash_Update(&sha256->stmCtx,
|
|
HASH_AlgoSelection_SHA256, data, len, WC_SHA256_BLOCK_SIZE);
|
|
wolfSSL_CryptHwMutexUnLock();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int wc_Sha256Final(wc_Sha256* sha256, byte* hash)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (sha256 == NULL || hash == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
ret = wolfSSL_CryptHwMutexLock();
|
|
if (ret == 0) {
|
|
ret = wc_Stm32_Hash_Final(&sha256->stmCtx,
|
|
HASH_AlgoSelection_SHA256, hash, WC_SHA256_DIGEST_SIZE);
|
|
wolfSSL_CryptHwMutexUnLock();
|
|
}
|
|
|
|
(void)wc_InitSha256(sha256); /* reset state */
|
|
|
|
return ret;
|
|
}
|
|
|
|
#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) && \
|
|
!defined(WOLFSSL_QNX_CAAM)
|
|
/* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */
|
|
|
|
#elif defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_HASH)
|
|
|
|
int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
|
|
{
|
|
if (sha256 == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
(void)devId;
|
|
|
|
return se050_hash_init(&sha256->se050Ctx, heap);
|
|
}
|
|
|
|
int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len)
|
|
{
|
|
if (sha256 == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
if (data == NULL && len == 0) {
|
|
/* valid, but do nothing */
|
|
return 0;
|
|
}
|
|
if (data == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
return se050_hash_update(&sha256->se050Ctx, data, len);
|
|
}
|
|
|
|
int wc_Sha256Final(wc_Sha256* sha256, byte* hash)
|
|
{
|
|
int ret = 0;
|
|
ret = se050_hash_final(&sha256->se050Ctx, hash, WC_SHA256_DIGEST_SIZE,
|
|
kAlgorithm_SSS_SHA256);
|
|
return ret;
|
|
}
|
|
int wc_Sha256FinalRaw(wc_Sha256* sha256, byte* hash)
|
|
{
|
|
int ret = 0;
|
|
ret = se050_hash_final(&sha256->se050Ctx, hash, WC_SHA256_DIGEST_SIZE,
|
|
kAlgorithm_SSS_SHA256);
|
|
return ret;
|
|
}
|
|
|
|
#elif defined(WOLFSSL_AFALG_HASH)
|
|
/* implemented in wolfcrypt/src/port/af_alg/afalg_hash.c */
|
|
|
|
#elif defined(WOLFSSL_DEVCRYPTO_HASH)
|
|
/* implemented in wolfcrypt/src/port/devcrypto/devcrypt_hash.c */
|
|
|
|
#elif defined(WOLFSSL_SCE) && !defined(WOLFSSL_SCE_NO_HASH)
|
|
#include "hal_data.h"
|
|
|
|
#ifndef WOLFSSL_SCE_SHA256_HANDLE
|
|
#define WOLFSSL_SCE_SHA256_HANDLE g_sce_hash_0
|
|
#endif
|
|
|
|
#define WC_SHA256_DIGEST_WORD_SIZE 16
|
|
#define XTRANSFORM(S, D) wc_Sha256SCE_XTRANSFORM((S), (D))
|
|
static int wc_Sha256SCE_XTRANSFORM(wc_Sha256* sha256, const byte* data)
|
|
{
|
|
if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag ==
|
|
CRYPTO_WORD_ENDIAN_LITTLE)
|
|
{
|
|
ByteReverseWords((word32*)data, (word32*)data,
|
|
WC_SHA256_BLOCK_SIZE);
|
|
ByteReverseWords(sha256->digest, sha256->digest,
|
|
WC_SHA256_DIGEST_SIZE);
|
|
}
|
|
|
|
if (WOLFSSL_SCE_SHA256_HANDLE.p_api->hashUpdate(
|
|
WOLFSSL_SCE_SHA256_HANDLE.p_ctrl, (word32*)data,
|
|
WC_SHA256_DIGEST_WORD_SIZE, sha256->digest) != SSP_SUCCESS){
|
|
WOLFSSL_MSG("Unexpected hardware return value");
|
|
return WC_HW_E;
|
|
}
|
|
|
|
if (WOLFSSL_SCE_GSCE_HANDLE.p_cfg->endian_flag ==
|
|
CRYPTO_WORD_ENDIAN_LITTLE)
|
|
{
|
|
ByteReverseWords((word32*)data, (word32*)data,
|
|
WC_SHA256_BLOCK_SIZE);
|
|
ByteReverseWords(sha256->digest, sha256->digest,
|
|
WC_SHA256_DIGEST_SIZE);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
|
|
{
|
|
int ret = 0;
|
|
if (sha256 == NULL)
|
|
return BAD_FUNC_ARG;
|
|
|
|
sha256->heap = heap;
|
|
|
|
ret = InitSha256(sha256);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
(void)devId;
|
|
|
|
return ret;
|
|
}
|
|
|
|
#elif defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW)
|
|
|
|
/* HW may fail since there's only one, so we still need SW */
|
|
#define NEED_SOFT_SHA256
|
|
|
|
/*
|
|
** An Espressif-specific InitSha256()
|
|
**
|
|
** soft SHA needs initialization digest, but HW does not.
|
|
*/
|
|
static int InitSha256(wc_Sha256* sha256)
|
|
{
|
|
int ret = 0; /* zero = success */
|
|
|
|
/* We may or may not need initial digest for HW.
|
|
* Always needed for SW-only. */
|
|
sha256->digest[0] = 0x6A09E667L;
|
|
sha256->digest[1] = 0xBB67AE85L;
|
|
sha256->digest[2] = 0x3C6EF372L;
|
|
sha256->digest[3] = 0xA54FF53AL;
|
|
sha256->digest[4] = 0x510E527FL;
|
|
sha256->digest[5] = 0x9B05688CL;
|
|
sha256->digest[6] = 0x1F83D9ABL;
|
|
sha256->digest[7] = 0x5BE0CD19L;
|
|
|
|
sha256->buffLen = 0;
|
|
sha256->loLen = 0;
|
|
sha256->hiLen = 0;
|
|
|
|
#ifndef NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256
|
|
ret = esp_sha_init((WC_ESP32SHA*)&(sha256->ctx), WC_HASH_TYPE_SHA256);
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
/*
|
|
** An Espressif-specific wolfCrypt InitSha256 external wrapper.
|
|
**
|
|
** we'll assume this is ALWAYS for a new, uninitialized sha256
|
|
*/
|
|
int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
|
|
{
|
|
(void)devId;
|
|
if (sha256 == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256)
|
|
/* We know this is a fresh, uninitialized item, so set to INIT */
|
|
if (sha256->ctx.mode != ESP32_SHA_INIT) {
|
|
ESP_LOGV(TAG, "Set ctx mode from prior value: "
|
|
"%d", sha256->ctx.mode);
|
|
}
|
|
sha256->ctx.mode = ESP32_SHA_INIT;
|
|
#endif
|
|
|
|
return InitSha256(sha256);
|
|
}
|
|
|
|
#elif (defined(WOLFSSL_RENESAS_TSIP_TLS) || \
|
|
defined(WOLFSSL_RENESAS_TSIP_CRYPTONLY)) && \
|
|
!defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH)
|
|
|
|
/* implemented in wolfcrypt/src/port/Renesas/renesas_tsip_sha.c */
|
|
|
|
#elif (defined(WOLFSSL_RENESAS_SCEPROTECT) || defined(WOLFSSL_RENESAS_RSIP)) \
|
|
&& !defined(NO_WOLFSSL_RENESAS_FSPSM_HASH)
|
|
|
|
/* implemented in wolfcrypt/src/port/Renesas/renesas_fspsm_sha.c */
|
|
|
|
#elif defined(WOLFSSL_PSOC6_CRYPTO)
|
|
|
|
/* implemented in wolfcrypt/src/port/cypress/psoc6_crypto.c */
|
|
|
|
#elif defined(WOLFSSL_IMXRT_DCP)
|
|
#include <wolfssl/wolfcrypt/port/nxp/dcp_port.h>
|
|
/* implemented in wolfcrypt/src/port/nxp/dcp_port.c */
|
|
|
|
#elif defined(WOLFSSL_SILABS_SE_ACCEL)
|
|
/* implemented in wolfcrypt/src/port/silabs/silabs_hash.c */
|
|
|
|
#elif defined(WOLFSSL_KCAPI_HASH)
|
|
/* implemented in wolfcrypt/src/port/kcapi/kcapi_hash.c */
|
|
|
|
#elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH)
|
|
/* implemented in wolfcrypt/src/port/psa/psa_hash.c */
|
|
|
|
#elif defined(WOLFSSL_RENESAS_RX64_HASH)
|
|
|
|
/* implemented in wolfcrypt/src/port/Renesas/renesas_rx64_hw_sha.c */
|
|
|
|
#else
|
|
#define NEED_SOFT_SHA256
|
|
|
|
int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
|
|
{
|
|
int ret = 0;
|
|
if (sha256 == NULL)
|
|
return BAD_FUNC_ARG;
|
|
ret = InitSha256(sha256);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
sha256->heap = heap;
|
|
#ifdef WOLF_CRYPTO_CB
|
|
sha256->devId = devId;
|
|
sha256->devCtx = NULL;
|
|
#endif
|
|
#ifdef MAX3266X_SHA_CB
|
|
ret = wc_MXC_TPU_SHA_Init(&(sha256->mxcCtx));
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
#endif
|
|
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
|
sha256->W = NULL;
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
|
|
ret = wolfAsync_DevCtxInit(&sha256->asyncDev,
|
|
WOLFSSL_ASYNC_MARKER_SHA256, sha256->heap, devId);
|
|
#else
|
|
(void)devId;
|
|
#endif /* WOLFSSL_ASYNC_CRYPT */
|
|
#ifdef WOLFSSL_IMXRT1170_CAAM
|
|
ret = wc_CAAM_HashInit(&sha256->hndl, &sha256->ctx, WC_HASH_TYPE_SHA256);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
#endif /* End Hardware Acceleration */
|
|
|
|
#ifdef NEED_SOFT_SHA256
|
|
|
|
static const FLASH_QUALIFIER ALIGN32 word32 K[64] = {
|
|
0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL,
|
|
0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L,
|
|
0x243185BEL, 0x550C7DC3L, 0x72BE5D74L, 0x80DEB1FEL, 0x9BDC06A7L,
|
|
0xC19BF174L, 0xE49B69C1L, 0xEFBE4786L, 0x0FC19DC6L, 0x240CA1CCL,
|
|
0x2DE92C6FL, 0x4A7484AAL, 0x5CB0A9DCL, 0x76F988DAL, 0x983E5152L,
|
|
0xA831C66DL, 0xB00327C8L, 0xBF597FC7L, 0xC6E00BF3L, 0xD5A79147L,
|
|
0x06CA6351L, 0x14292967L, 0x27B70A85L, 0x2E1B2138L, 0x4D2C6DFCL,
|
|
0x53380D13L, 0x650A7354L, 0x766A0ABBL, 0x81C2C92EL, 0x92722C85L,
|
|
0xA2BFE8A1L, 0xA81A664BL, 0xC24B8B70L, 0xC76C51A3L, 0xD192E819L,
|
|
0xD6990624L, 0xF40E3585L, 0x106AA070L, 0x19A4C116L, 0x1E376C08L,
|
|
0x2748774CL, 0x34B0BCB5L, 0x391C0CB3L, 0x4ED8AA4AL, 0x5B9CCA4FL,
|
|
0x682E6FF3L, 0x748F82EEL, 0x78A5636FL, 0x84C87814L, 0x8CC70208L,
|
|
0x90BEFFFAL, 0xA4506CEBL, 0xBEF9A3F7L, 0xC67178F2L
|
|
};
|
|
|
|
/* Both versions of Ch and Maj are logically the same, but with the second set
|
|
the compilers can recognize them better for optimization */
|
|
#ifdef WOLFSSL_SHA256_BY_SPEC
|
|
/* SHA256 math based on specification */
|
|
#define Ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
|
|
#define Maj(x,y,z) ((((x) | (y)) & (z)) | ((x) & (y)))
|
|
#else
|
|
/* SHA256 math reworked for easier compiler optimization */
|
|
#define Ch(x,y,z) ((((y) ^ (z)) & (x)) ^ (z))
|
|
#define Maj(x,y,z) ((((x) ^ (y)) & ((y) ^ (z))) ^ (y))
|
|
#endif
|
|
#define R(x, n) (((x) & 0xFFFFFFFFU) >> (n))
|
|
|
|
#define S(x, n) rotrFixed(x, n)
|
|
#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
|
|
#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
|
|
#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
|
|
#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
|
|
|
|
#define a(i) S[(0-(i)) & 7]
|
|
#define b(i) S[(1-(i)) & 7]
|
|
#define c(i) S[(2-(i)) & 7]
|
|
#define d(i) S[(3-(i)) & 7]
|
|
#define e(i) S[(4-(i)) & 7]
|
|
#define f(i) S[(5-(i)) & 7]
|
|
#define g(i) S[(6-(i)) & 7]
|
|
#define h(i) S[(7-(i)) & 7]
|
|
|
|
#ifndef XTRANSFORM
|
|
#define XTRANSFORM(S, D) Transform_Sha256((S),(D))
|
|
#endif
|
|
|
|
#ifndef SHA256_MANY_REGISTERS
|
|
#define RND(j) \
|
|
t0 = h(j) + Sigma1(e(j)) + Ch(e(j), f(j), g(j)) + K[i+(j)] + W[i+(j)]; \
|
|
t1 = Sigma0(a(j)) + Maj(a(j), b(j), c(j)); \
|
|
d(j) += t0; \
|
|
h(j) = t0 + t1
|
|
|
|
static int Transform_Sha256(wc_Sha256* sha256, const byte* data)
|
|
{
|
|
word32 S[8], t0, t1;
|
|
int i;
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
|
word32* W = sha256->W;
|
|
if (W == NULL) {
|
|
W = (word32*)XMALLOC(sizeof(word32) * WC_SHA256_BLOCK_SIZE, NULL,
|
|
DYNAMIC_TYPE_DIGEST);
|
|
if (W == NULL)
|
|
return MEMORY_E;
|
|
sha256->W = W;
|
|
}
|
|
#elif defined(WOLFSSL_SMALL_STACK)
|
|
word32* W;
|
|
W = (word32*)XMALLOC(sizeof(word32) * WC_SHA256_BLOCK_SIZE, NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (W == NULL)
|
|
return MEMORY_E;
|
|
#else
|
|
word32 W[WC_SHA256_BLOCK_SIZE];
|
|
#endif
|
|
|
|
/* Copy context->state[] to working vars */
|
|
for (i = 0; i < 8; i++)
|
|
S[i] = sha256->digest[i];
|
|
|
|
for (i = 0; i < 16; i++)
|
|
W[i] = *((const word32*)&data[i*(int)sizeof(word32)]);
|
|
|
|
for (i = 16; i < WC_SHA256_BLOCK_SIZE; i++)
|
|
W[i] = Gamma1(W[i-2]) + W[i-7] + Gamma0(W[i-15]) + W[i-16];
|
|
|
|
#ifdef USE_SLOW_SHA256
|
|
/* not unrolled - ~2k smaller and ~25% slower */
|
|
for (i = 0; i < WC_SHA256_BLOCK_SIZE; i += 8) {
|
|
int j;
|
|
for (j = 0; j < 8; j++) { /* braces needed here for macros {} */
|
|
RND(j);
|
|
}
|
|
}
|
|
#else
|
|
/* partially loop unrolled */
|
|
for (i = 0; i < WC_SHA256_BLOCK_SIZE; i += 8) {
|
|
RND(0); RND(1); RND(2); RND(3);
|
|
RND(4); RND(5); RND(6); RND(7);
|
|
}
|
|
#endif /* USE_SLOW_SHA256 */
|
|
|
|
/* Add the working vars back into digest state[] */
|
|
for (i = 0; i < 8; i++) {
|
|
sha256->digest[i] += S[i];
|
|
}
|
|
|
|
#if defined(WOLFSSL_SMALL_STACK) && !defined(WOLFSSL_SMALL_STACK_CACHE)
|
|
ForceZero(W, sizeof(word32) * WC_SHA256_BLOCK_SIZE);
|
|
XFREE(W, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
return 0;
|
|
}
|
|
#else
|
|
/* SHA256 version that keeps all data in registers */
|
|
#define SCHED1(j) (W[j] = *((word32*)&data[j*sizeof(word32)]))
|
|
#define SCHED(j) ( \
|
|
W[ j & 15] += \
|
|
Gamma1(W[(j-2) & 15])+ \
|
|
W[(j-7) & 15] + \
|
|
Gamma0(W[(j-15) & 15]) \
|
|
)
|
|
|
|
#define RND1(j) \
|
|
t0 = h(j) + Sigma1(e(j)) + Ch(e(j), f(j), g(j)) + K[i+j] + SCHED1(j); \
|
|
t1 = Sigma0(a(j)) + Maj(a(j), b(j), c(j)); \
|
|
d(j) += t0; \
|
|
h(j) = t0 + t1
|
|
#define RNDN(j) \
|
|
t0 = h(j) + Sigma1(e(j)) + Ch(e(j), f(j), g(j)) + K[i+j] + SCHED(j); \
|
|
t1 = Sigma0(a(j)) + Maj(a(j), b(j), c(j)); \
|
|
d(j) += t0; \
|
|
h(j) = t0 + t1
|
|
|
|
static int Transform_Sha256(wc_Sha256* sha256, const byte* data)
|
|
{
|
|
word32 S[8], t0, t1;
|
|
int i;
|
|
#ifdef USE_SLOW_SHA256
|
|
int j;
|
|
#endif
|
|
word32 W[WC_SHA256_BLOCK_SIZE/sizeof(word32)];
|
|
|
|
/* Copy digest to working vars */
|
|
S[0] = sha256->digest[0];
|
|
S[1] = sha256->digest[1];
|
|
S[2] = sha256->digest[2];
|
|
S[3] = sha256->digest[3];
|
|
S[4] = sha256->digest[4];
|
|
S[5] = sha256->digest[5];
|
|
S[6] = sha256->digest[6];
|
|
S[7] = sha256->digest[7];
|
|
|
|
i = 0;
|
|
#ifdef USE_SLOW_SHA256
|
|
for (j = 0; j < 16; j++) {
|
|
RND1(j);
|
|
}
|
|
for (i = 16; i < 64; i += 16) {
|
|
for (j = 0; j < 16; j++) {
|
|
RNDN(j);
|
|
}
|
|
}
|
|
#else
|
|
RND1( 0); RND1( 1); RND1( 2); RND1( 3);
|
|
RND1( 4); RND1( 5); RND1( 6); RND1( 7);
|
|
RND1( 8); RND1( 9); RND1(10); RND1(11);
|
|
RND1(12); RND1(13); RND1(14); RND1(15);
|
|
/* 64 operations, partially loop unrolled */
|
|
for (i = 16; i < 64; i += 16) {
|
|
RNDN( 0); RNDN( 1); RNDN( 2); RNDN( 3);
|
|
RNDN( 4); RNDN( 5); RNDN( 6); RNDN( 7);
|
|
RNDN( 8); RNDN( 9); RNDN(10); RNDN(11);
|
|
RNDN(12); RNDN(13); RNDN(14); RNDN(15);
|
|
}
|
|
#endif
|
|
|
|
/* Add the working vars back into digest */
|
|
sha256->digest[0] += S[0];
|
|
sha256->digest[1] += S[1];
|
|
sha256->digest[2] += S[2];
|
|
sha256->digest[3] += S[3];
|
|
sha256->digest[4] += S[4];
|
|
sha256->digest[5] += S[5];
|
|
sha256->digest[6] += S[6];
|
|
sha256->digest[7] += S[7];
|
|
|
|
return 0;
|
|
}
|
|
#endif /* SHA256_MANY_REGISTERS */
|
|
#endif
|
|
/* End wc_ software implementation */
|
|
|
|
|
|
#ifdef XTRANSFORM
|
|
|
|
static WC_INLINE void AddLength(wc_Sha256* sha256, word32 len)
|
|
{
|
|
word32 tmp = sha256->loLen;
|
|
if ((sha256->loLen += len) < tmp) {
|
|
sha256->hiLen++; /* carry low to high */
|
|
}
|
|
}
|
|
|
|
/* do block size increments/updates */
|
|
static WC_INLINE int Sha256Update(wc_Sha256* sha256, const byte* data,
|
|
word32 len)
|
|
{
|
|
int ret = 0;
|
|
word32 blocksLen;
|
|
byte* local;
|
|
|
|
/* check that internal buffLen is valid */
|
|
if (sha256->buffLen >= WC_SHA256_BLOCK_SIZE) {
|
|
return BUFFER_E;
|
|
}
|
|
|
|
/* add length for final */
|
|
AddLength(sha256, len);
|
|
|
|
local = (byte*)sha256->buffer;
|
|
|
|
/* process any remainder from previous operation */
|
|
if (sha256->buffLen > 0) {
|
|
blocksLen = min(len, WC_SHA256_BLOCK_SIZE - sha256->buffLen);
|
|
XMEMCPY(&local[sha256->buffLen], data, blocksLen);
|
|
|
|
sha256->buffLen += blocksLen;
|
|
data += blocksLen;
|
|
len -= blocksLen;
|
|
|
|
if (sha256->buffLen == WC_SHA256_BLOCK_SIZE) {
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256)
|
|
if (sha256->ctx.mode == ESP32_SHA_INIT) {
|
|
ESP_LOGV(TAG, "Sha256Update try hardware");
|
|
esp_sha_try_hw_lock(&sha256->ctx);
|
|
}
|
|
#endif
|
|
|
|
if (SHA256_UPDATE_REV_BYTES(&sha256->ctx)) {
|
|
ByteReverseWords(sha256->buffer, sha256->buffer,
|
|
WC_SHA256_BLOCK_SIZE);
|
|
}
|
|
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256)
|
|
if (sha256->ctx.mode == ESP32_SHA_SW) {
|
|
#if defined(WOLFSSL_DEBUG_MUTEX)
|
|
{
|
|
ESP_LOGI(TAG, "Sha256Update process software");
|
|
}
|
|
#endif
|
|
#ifdef WOLFSSL_HW_METRICS
|
|
{
|
|
/* Track of # SW during transforms during active HW */
|
|
esp_sw_sha256_count_add();
|
|
}
|
|
#endif /* WOLFSSL_HW_METRICS */
|
|
ret = XTRANSFORM(sha256, (const byte*)local);
|
|
}
|
|
else {
|
|
#if defined(WOLFSSL_DEBUG_MUTEX)
|
|
{
|
|
ESP_LOGI(TAG, "Sha256Update process hardware");
|
|
}
|
|
#endif
|
|
esp_sha256_process(sha256, (const byte*)local);
|
|
}
|
|
#else
|
|
/* Always SW */
|
|
ret = XTRANSFORM(sha256, (const byte*)local);
|
|
#endif
|
|
if (ret == 0)
|
|
sha256->buffLen = 0;
|
|
else
|
|
len = 0; /* error */
|
|
}
|
|
}
|
|
|
|
/* process blocks */
|
|
#ifdef XTRANSFORM_LEN
|
|
#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
|
|
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))
|
|
|
|
#ifdef WC_C_DYNAMIC_FALLBACK
|
|
if (sha256->sha_method != SHA256_C)
|
|
#elif defined(WC_NO_INTERNAL_FUNCTION_POINTERS)
|
|
if (sha_method != SHA256_C)
|
|
#else
|
|
if (Transform_Sha256_Len_p != NULL)
|
|
#endif
|
|
|
|
#endif
|
|
{
|
|
if (len >= WC_SHA256_BLOCK_SIZE) {
|
|
/* get number of blocks */
|
|
/* 64-1 = 0x3F (~ Inverted = 0xFFFFFFC0) */
|
|
/* len (masked by 0xFFFFFFC0) returns block aligned length */
|
|
blocksLen = len & ~((word32)WC_SHA256_BLOCK_SIZE-1);
|
|
/* Byte reversal and alignment handled in function if required
|
|
*/
|
|
XTRANSFORM_LEN(sha256, data, blocksLen);
|
|
data += blocksLen;
|
|
len -= blocksLen;
|
|
}
|
|
}
|
|
#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
|
|
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))
|
|
else
|
|
#endif
|
|
#endif /* XTRANSFORM_LEN */
|
|
#if !defined(XTRANSFORM_LEN) || \
|
|
(defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
|
|
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)))
|
|
{
|
|
while (len >= WC_SHA256_BLOCK_SIZE) {
|
|
word32* local32 = sha256->buffer;
|
|
/* optimization to avoid memcpy if data pointer is properly aligned */
|
|
/* Intel transform function requires use of sha256->buffer */
|
|
/* Little Endian requires byte swap, so can't use data directly */
|
|
#if defined(WC_HASH_DATA_ALIGNMENT) && !defined(LITTLE_ENDIAN_ORDER) && \
|
|
!(defined(WOLFSSL_X86_64_BUILD) && \
|
|
defined(USE_INTEL_SPEEDUP) && \
|
|
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)))
|
|
if (((wc_ptr_t)data % WC_HASH_DATA_ALIGNMENT) == 0) {
|
|
local32 = (word32*)data;
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
XMEMCPY(local32, data, WC_SHA256_BLOCK_SIZE);
|
|
}
|
|
|
|
data += WC_SHA256_BLOCK_SIZE;
|
|
len -= WC_SHA256_BLOCK_SIZE;
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
|
|
!defined( NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256)
|
|
if (sha256->ctx.mode == ESP32_SHA_INIT){
|
|
ESP_LOGV(TAG, "Sha256Update try hardware loop");
|
|
esp_sha_try_hw_lock(&sha256->ctx);
|
|
}
|
|
#endif
|
|
|
|
if (SHA256_UPDATE_REV_BYTES(&sha256->ctx)) {
|
|
ByteReverseWords(local32, local32, WC_SHA256_BLOCK_SIZE);
|
|
}
|
|
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256)
|
|
if (sha256->ctx.mode == ESP32_SHA_SW) {
|
|
ESP_LOGV(TAG, "Sha256Update process software loop");
|
|
ret = XTRANSFORM(sha256, (const byte*)local32);
|
|
}
|
|
else {
|
|
ESP_LOGV(TAG, "Sha256Update process hardware");
|
|
esp_sha256_process(sha256, (const byte*)local32);
|
|
}
|
|
#else
|
|
ret = XTRANSFORM(sha256, (const byte*)local32);
|
|
#endif
|
|
|
|
if (ret != 0)
|
|
break;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
/* save remainder */
|
|
if (ret == 0 && len > 0) {
|
|
XMEMCPY(local, data, len);
|
|
sha256->buffLen = len;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
#if defined(WOLFSSL_KCAPI_HASH)
|
|
/* implemented in wolfcrypt/src/port/kcapi/kcapi_hash.c */
|
|
|
|
#else
|
|
int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len)
|
|
{
|
|
if (sha256 == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
if (data == NULL && len == 0) {
|
|
/* valid, but do nothing */
|
|
return 0;
|
|
}
|
|
if (data == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
#ifdef WOLF_CRYPTO_CB
|
|
#ifndef WOLF_CRYPTO_CB_FIND
|
|
if (sha256->devId != INVALID_DEVID)
|
|
#endif
|
|
{
|
|
int ret = wc_CryptoCb_Sha256Hash(sha256, data, len, NULL);
|
|
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
|
|
return ret;
|
|
/* fall-through when unavailable */
|
|
}
|
|
#endif
|
|
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
|
|
if (sha256->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA256) {
|
|
#if defined(HAVE_INTEL_QA)
|
|
return IntelQaSymSha256(&sha256->asyncDev, NULL, data, len);
|
|
#endif
|
|
}
|
|
#endif /* WOLFSSL_ASYNC_CRYPT */
|
|
|
|
return Sha256Update(sha256, data, len);
|
|
}
|
|
#endif
|
|
|
|
static WC_INLINE int Sha256Final(wc_Sha256* sha256)
|
|
{
|
|
int ret;
|
|
byte* local;
|
|
|
|
/* we'll add a 0x80 byte at the end,
|
|
** so make sure we have appropriate buffer length. */
|
|
if (sha256->buffLen > WC_SHA256_BLOCK_SIZE - 1) {
|
|
/* exit with error code if there's a bad buffer size in buffLen */
|
|
return BAD_STATE_E;
|
|
} /* buffLen check */
|
|
|
|
local = (byte*)sha256->buffer;
|
|
local[sha256->buffLen++] = 0x80; /* add 1 */
|
|
|
|
/* pad with zeros */
|
|
if (sha256->buffLen > WC_SHA256_PAD_SIZE) {
|
|
if (sha256->buffLen < WC_SHA256_BLOCK_SIZE) {
|
|
XMEMSET(&local[sha256->buffLen], 0,
|
|
WC_SHA256_BLOCK_SIZE - sha256->buffLen);
|
|
}
|
|
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256)
|
|
if (sha256->ctx.mode == ESP32_SHA_INIT) {
|
|
esp_sha_try_hw_lock(&sha256->ctx);
|
|
}
|
|
#endif
|
|
|
|
if (SHA256_UPDATE_REV_BYTES(&sha256->ctx)) {
|
|
ByteReverseWords(sha256->buffer, sha256->buffer,
|
|
WC_SHA256_BLOCK_SIZE);
|
|
}
|
|
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256)
|
|
if (sha256->ctx.mode == ESP32_SHA_INIT) {
|
|
esp_sha_try_hw_lock(&sha256->ctx);
|
|
}
|
|
if (sha256->ctx.mode == ESP32_SHA_SW) {
|
|
ret = XTRANSFORM(sha256, (const byte*)local);
|
|
}
|
|
else {
|
|
ret = esp_sha256_process(sha256, (const byte*)local);
|
|
}
|
|
#else
|
|
ret = XTRANSFORM(sha256, (const byte*)local);
|
|
#endif
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
sha256->buffLen = 0;
|
|
}
|
|
XMEMSET(&local[sha256->buffLen], 0,
|
|
WC_SHA256_PAD_SIZE - sha256->buffLen);
|
|
|
|
/* put 64 bit length in separate 32 bit parts */
|
|
sha256->hiLen = (sha256->loLen >> (8 * sizeof(sha256->loLen) - 3)) +
|
|
(sha256->hiLen << 3);
|
|
sha256->loLen = sha256->loLen << 3;
|
|
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256)
|
|
if (sha256->ctx.mode == ESP32_SHA_INIT) {
|
|
esp_sha_try_hw_lock(&sha256->ctx);
|
|
}
|
|
#endif
|
|
|
|
/* store lengths */
|
|
if (SHA256_UPDATE_REV_BYTES(&sha256->ctx)) {
|
|
ByteReverseWords(sha256->buffer, sha256->buffer,
|
|
WC_SHA256_PAD_SIZE);
|
|
}
|
|
/* ! 64-bit length ordering dependent on digest endian type ! */
|
|
XMEMCPY(&local[WC_SHA256_PAD_SIZE], &sha256->hiLen, sizeof(word32));
|
|
XMEMCPY(&local[WC_SHA256_PAD_SIZE + sizeof(word32)], &sha256->loLen,
|
|
sizeof(word32));
|
|
|
|
/* Only the ESP32-C3 with HW enabled may need pad size byte order reversal
|
|
* depending on HW or SW mode */
|
|
#if ( defined(CONFIG_IDF_TARGET_ESP32C2) || \
|
|
defined(CONFIG_IDF_TARGET_ESP8684) || \
|
|
defined(CONFIG_IDF_TARGET_ESP32C3) || \
|
|
defined(CONFIG_IDF_TARGET_ESP32C6) \
|
|
) && \
|
|
defined(WOLFSSL_ESP32_CRYPT) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256)
|
|
/* For Espressif RISC-V Targets, we *may* need to reverse bytes
|
|
* depending on if HW is active or not. */
|
|
if (sha256->ctx.mode == ESP32_SHA_HW) {
|
|
#if defined(WOLFSSL_SUPER_VERBOSE_DEBUG)
|
|
ESP_LOGV(TAG, "Start: Reverse PAD SIZE Endianness.");
|
|
#endif
|
|
ByteReverseWords(
|
|
&sha256->buffer[WC_SHA256_PAD_SIZE / sizeof(word32)], /* out */
|
|
&sha256->buffer[WC_SHA256_PAD_SIZE / sizeof(word32)], /* in */
|
|
2 * sizeof(word32) /* byte count to reverse */
|
|
);
|
|
#if defined(WOLFSSL_SUPER_VERBOSE_DEBUG)
|
|
ESP_LOGV(TAG, "End: Reverse PAD SIZE Endianness.");
|
|
#endif
|
|
} /* end if (sha256->ctx.mode == ESP32_SHA_HW) */
|
|
#endif
|
|
|
|
#if defined(FREESCALE_MMCAU_SHA) || \
|
|
(defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
|
|
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)))
|
|
/* Kinetis requires only these bytes reversed */
|
|
#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
|
|
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))
|
|
#ifdef WC_C_DYNAMIC_FALLBACK
|
|
if (sha256->sha_method != SHA256_C)
|
|
#else
|
|
if (IS_INTEL_AVX1(intel_flags) || IS_INTEL_AVX2(intel_flags))
|
|
#endif
|
|
#endif
|
|
{
|
|
ByteReverseWords(
|
|
&sha256->buffer[WC_SHA256_PAD_SIZE / sizeof(word32)],
|
|
&sha256->buffer[WC_SHA256_PAD_SIZE / sizeof(word32)],
|
|
2 * sizeof(word32));
|
|
}
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256)
|
|
if (sha256->ctx.mode == ESP32_SHA_INIT) {
|
|
esp_sha_try_hw_lock(&sha256->ctx);
|
|
}
|
|
/* depending on architecture and ctx.mode value
|
|
* we may or may not need default digest */
|
|
if (sha256->ctx.mode == ESP32_SHA_SW) {
|
|
ret = XTRANSFORM(sha256, (const byte*)local);
|
|
}
|
|
else {
|
|
ret = esp_sha256_digest_process(sha256, 1);
|
|
}
|
|
#else
|
|
ret = XTRANSFORM(sha256, (const byte*)local);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
#if !defined(WOLFSSL_KCAPI_HASH)
|
|
|
|
int wc_Sha256FinalRaw(wc_Sha256* sha256, byte* hash)
|
|
{
|
|
#ifdef LITTLE_ENDIAN_ORDER
|
|
word32 digest[WC_SHA256_DIGEST_SIZE / sizeof(word32)];
|
|
#endif
|
|
|
|
if (sha256 == NULL || hash == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
#ifdef LITTLE_ENDIAN_ORDER
|
|
if (SHA256_REV_BYTES(&sha256->ctx)) {
|
|
ByteReverseWords((word32*)digest, (word32*)sha256->digest,
|
|
WC_SHA256_DIGEST_SIZE);
|
|
}
|
|
XMEMCPY(hash, digest, WC_SHA256_DIGEST_SIZE);
|
|
#else
|
|
XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
int wc_Sha256Final(wc_Sha256* sha256, byte* hash)
|
|
{
|
|
int ret;
|
|
|
|
if (sha256 == NULL || hash == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
#ifdef WOLF_CRYPTO_CB
|
|
#ifndef WOLF_CRYPTO_CB_FIND
|
|
if (sha256->devId != INVALID_DEVID)
|
|
#endif
|
|
{
|
|
ret = wc_CryptoCb_Sha256Hash(sha256, NULL, 0, hash);
|
|
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
|
|
return ret;
|
|
/* fall-through when unavailable */
|
|
}
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
|
|
if (sha256->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA256) {
|
|
#if defined(HAVE_INTEL_QA)
|
|
return IntelQaSymSha256(&sha256->asyncDev, hash, NULL,
|
|
WC_SHA256_DIGEST_SIZE);
|
|
#endif
|
|
}
|
|
#endif /* WOLFSSL_ASYNC_CRYPT */
|
|
|
|
ret = Sha256Final(sha256);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
#if defined(LITTLE_ENDIAN_ORDER)
|
|
if (SHA256_REV_BYTES(&sha256->ctx)) {
|
|
ByteReverseWords(sha256->digest, sha256->digest,
|
|
WC_SHA256_DIGEST_SIZE);
|
|
}
|
|
#endif
|
|
XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE);
|
|
|
|
return InitSha256(sha256); /* reset state */
|
|
}
|
|
|
|
#if defined(OPENSSL_EXTRA) || defined(HAVE_CURL)
|
|
/* Apply SHA256 transformation to the data */
|
|
/* @param sha a pointer to wc_Sha256 structure */
|
|
/* @param data data to be applied SHA256 transformation */
|
|
/* @return 0 on successful, otherwise non-zero on failure */
|
|
int wc_Sha256Transform(wc_Sha256* sha256, const unsigned char* data)
|
|
{
|
|
if (sha256 == NULL || data == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
return Transform_Sha256(sha256, data);
|
|
}
|
|
#endif /* OPENSSL_EXTRA || HAVE_CURL */
|
|
|
|
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_FULL_HASH)
|
|
/* One block will be used from data.
|
|
* hash must be big enough to hold all of digest output.
|
|
*/
|
|
int wc_Sha256HashBlock(wc_Sha256* sha256, const unsigned char* data,
|
|
unsigned char* hash)
|
|
{
|
|
int ret;
|
|
|
|
if ((sha256 == NULL) || (data == NULL)) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
if (SHA256_UPDATE_REV_BYTES(&sha256->ctx)) {
|
|
ByteReverseWords(sha256->buffer, (word32*)data,
|
|
WC_SHA256_BLOCK_SIZE);
|
|
data = (unsigned char*)sha256->buffer;
|
|
}
|
|
ret = XTRANSFORM(sha256, data);
|
|
|
|
if ((ret == 0) && (hash != NULL)) {
|
|
if (!SHA256_REV_BYTES(&sha256->ctx)) {
|
|
XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE);
|
|
}
|
|
else {
|
|
#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP)
|
|
__asm__ __volatile__ (
|
|
"mov 0x00(%[d]), %%esi\n\t"
|
|
"movbe %%esi, 0x00(%[h])\n\t"
|
|
"mov 0x04(%[d]), %%esi\n\t"
|
|
"movbe %%esi, 0x04(%[h])\n\t"
|
|
"mov 0x08(%[d]), %%esi\n\t"
|
|
"movbe %%esi, 0x08(%[h])\n\t"
|
|
"mov 0x0c(%[d]), %%esi\n\t"
|
|
"movbe %%esi, 0x0c(%[h])\n\t"
|
|
"mov 0x10(%[d]), %%esi\n\t"
|
|
"movbe %%esi, 0x10(%[h])\n\t"
|
|
"mov 0x14(%[d]), %%esi\n\t"
|
|
"movbe %%esi, 0x14(%[h])\n\t"
|
|
"mov 0x18(%[d]), %%esi\n\t"
|
|
"movbe %%esi, 0x18(%[h])\n\t"
|
|
"mov 0x1c(%[d]), %%esi\n\t"
|
|
"movbe %%esi, 0x1c(%[h])\n\t"
|
|
:
|
|
: [d] "r" (sha256->digest), [h] "r" (hash)
|
|
: "memory", "esi"
|
|
);
|
|
#else
|
|
word32* hash32 = (word32*)hash;
|
|
word32* digest = (word32*)sha256->digest;
|
|
#if WOLFSSL_GENERAL_ALIGNMENT < 4
|
|
ALIGN16 word32 buf[WC_SHA256_DIGEST_SIZE / sizeof(word32)];
|
|
|
|
if (((size_t)digest & 0x3) != 0) {
|
|
if (((size_t)hash32 & 0x3) != 0) {
|
|
XMEMCPY(buf, digest, WC_SHA256_DIGEST_SIZE);
|
|
hash32 = buf;
|
|
digest = buf;
|
|
}
|
|
else {
|
|
XMEMCPY(hash, digest, WC_SHA256_DIGEST_SIZE);
|
|
digest = hash32;
|
|
}
|
|
}
|
|
else if (((size_t)hash32 & 0x3) != 0) {
|
|
hash32 = digest;
|
|
}
|
|
#endif
|
|
hash32[0] = ByteReverseWord32(digest[0]);
|
|
hash32[1] = ByteReverseWord32(digest[1]);
|
|
hash32[2] = ByteReverseWord32(digest[2]);
|
|
hash32[3] = ByteReverseWord32(digest[3]);
|
|
hash32[4] = ByteReverseWord32(digest[4]);
|
|
hash32[5] = ByteReverseWord32(digest[5]);
|
|
hash32[6] = ByteReverseWord32(digest[6]);
|
|
hash32[7] = ByteReverseWord32(digest[7]);
|
|
#if WOLFSSL_GENERAL_ALIGNMENT < 4
|
|
if (hash != (byte*)hash32) {
|
|
XMEMCPY(hash, hash32, WC_SHA256_DIGEST_SIZE);
|
|
}
|
|
#endif
|
|
#endif /* WOLFSSL_X86_64_BUILD && USE_INTEL_SPEEDUP */
|
|
}
|
|
sha256->digest[0] = 0x6A09E667L;
|
|
sha256->digest[1] = 0xBB67AE85L;
|
|
sha256->digest[2] = 0x3C6EF372L;
|
|
sha256->digest[3] = 0xA54FF53AL;
|
|
sha256->digest[4] = 0x510E527FL;
|
|
sha256->digest[5] = 0x9B05688CL;
|
|
sha256->digest[6] = 0x1F83D9ABL;
|
|
sha256->digest[7] = 0x5BE0CD19L;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
#endif /* WOLFSSL_HAVE_LMS && !WOLFSSL_LMS_FULL_HASH */
|
|
#endif /* !WOLFSSL_KCAPI_HASH */
|
|
|
|
#endif /* XTRANSFORM */
|
|
|
|
|
|
#ifdef WOLFSSL_SHA224
|
|
|
|
#ifdef STM32_HASH_SHA2
|
|
|
|
/* Supports CubeMX HAL or Standard Peripheral Library */
|
|
|
|
int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId)
|
|
{
|
|
if (sha224 == NULL)
|
|
return BAD_FUNC_ARG;
|
|
(void)devId;
|
|
(void)heap;
|
|
|
|
XMEMSET(sha224, 0, sizeof(wc_Sha224));
|
|
wc_Stm32_Hash_Init(&sha224->stmCtx);
|
|
return 0;
|
|
}
|
|
|
|
int wc_Sha224Update(wc_Sha224* sha224, const byte* data, word32 len)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (sha224 == NULL || (data == NULL && len > 0)) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
ret = wolfSSL_CryptHwMutexLock();
|
|
if (ret == 0) {
|
|
ret = wc_Stm32_Hash_Update(&sha224->stmCtx,
|
|
HASH_AlgoSelection_SHA224, data, len, WC_SHA224_BLOCK_SIZE);
|
|
wolfSSL_CryptHwMutexUnLock();
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
int wc_Sha224Final(wc_Sha224* sha224, byte* hash)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (sha224 == NULL || hash == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
ret = wolfSSL_CryptHwMutexLock();
|
|
if (ret == 0) {
|
|
ret = wc_Stm32_Hash_Final(&sha224->stmCtx,
|
|
HASH_AlgoSelection_SHA224, hash, WC_SHA224_DIGEST_SIZE);
|
|
wolfSSL_CryptHwMutexUnLock();
|
|
}
|
|
|
|
(void)wc_InitSha224(sha224); /* reset state */
|
|
|
|
return ret;
|
|
}
|
|
#elif defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_HASH)
|
|
|
|
int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId)
|
|
{
|
|
if (sha224 == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
(void)devId;
|
|
|
|
return se050_hash_init(&sha224->se050Ctx, heap);
|
|
}
|
|
|
|
int wc_Sha224Update(wc_Sha224* sha224, const byte* data, word32 len)
|
|
{
|
|
return se050_hash_update(&sha224->se050Ctx, data, len);
|
|
}
|
|
|
|
int wc_Sha224Final(wc_Sha224* sha224, byte* hash)
|
|
{
|
|
int ret = 0;
|
|
ret = se050_hash_final(&sha224->se050Ctx, hash, WC_SHA224_DIGEST_SIZE,
|
|
kAlgorithm_SSS_SHA224);
|
|
(void)wc_InitSha224(sha224);
|
|
return ret;
|
|
}
|
|
|
|
#elif defined(WOLFSSL_IMX6_CAAM) && !defined(NO_IMX6_CAAM_HASH) && \
|
|
!defined(WOLFSSL_QNX_CAAM)
|
|
/* functions defined in wolfcrypt/src/port/caam/caam_sha256.c */
|
|
|
|
#elif defined(WOLFSSL_AFALG_HASH)
|
|
#error SHA224 currently not supported with AF_ALG enabled
|
|
|
|
#elif defined(WOLFSSL_DEVCRYPTO_HASH)
|
|
/* implemented in wolfcrypt/src/port/devcrypto/devcrypt_hash.c */
|
|
|
|
#elif defined(WOLFSSL_SILABS_SE_ACCEL)
|
|
/* implemented in wolfcrypt/src/port/silabs/silabs_hash.c */
|
|
|
|
#elif defined(WOLFSSL_KCAPI_HASH) && !defined(WOLFSSL_NO_KCAPI_SHA224)
|
|
/* implemented in wolfcrypt/src/port/kcapi/kcapi_hash.c */
|
|
|
|
#elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH)
|
|
/* implemented in wolfcrypt/src/port/psa/psa_hash.c */
|
|
|
|
#elif defined(MAX3266X_SHA)
|
|
/* implemented in wolfcrypt/src/port/maxim/max3266x.c */
|
|
|
|
#elif defined(WOLFSSL_RENESAS_RX64_HASH)
|
|
|
|
/* implemented in wolfcrypt/src/port/Renesas/renesas_rx64_hw_sha.c */
|
|
|
|
#elif defined(WOLFSSL_RENESAS_RSIP) && \
|
|
!defined(NO_WOLFSSL_RENESAS_FSPSM_HASH)
|
|
|
|
/* implemented in wolfcrypt/src/port/Renesas/renesas_fspsm_sha.c */
|
|
|
|
#else
|
|
|
|
#define NEED_SOFT_SHA224
|
|
|
|
|
|
static int InitSha224(wc_Sha224* sha224)
|
|
{
|
|
int ret = 0;
|
|
|
|
sha224->digest[0] = 0xc1059ed8;
|
|
sha224->digest[1] = 0x367cd507;
|
|
sha224->digest[2] = 0x3070dd17;
|
|
sha224->digest[3] = 0xf70e5939;
|
|
sha224->digest[4] = 0xffc00b31;
|
|
sha224->digest[5] = 0x68581511;
|
|
sha224->digest[6] = 0x64f98fa7;
|
|
sha224->digest[7] = 0xbefa4fa4;
|
|
|
|
sha224->buffLen = 0;
|
|
sha224->loLen = 0;
|
|
sha224->hiLen = 0;
|
|
|
|
#ifdef WC_C_DYNAMIC_FALLBACK
|
|
sha224->sha_method = 0;
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
|
|
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))
|
|
/* choose best Transform function under this runtime environment */
|
|
#ifdef WC_C_DYNAMIC_FALLBACK
|
|
Sha256_SetTransform(&sha224->sha_method);
|
|
#else
|
|
Sha256_SetTransform();
|
|
#endif
|
|
#endif
|
|
#ifdef WOLFSSL_HASH_FLAGS
|
|
sha224->flags = 0;
|
|
#endif
|
|
#ifdef WOLFSSL_HASH_KEEP
|
|
sha224->msg = NULL;
|
|
sha224->len = 0;
|
|
sha224->used = 0;
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
|
|
(!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) || \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224))
|
|
/* not to be confused with SHAS512_224 */
|
|
ret = esp_sha_init(&(sha224->ctx), WC_HASH_TYPE_SHA224);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endif
|
|
|
|
#ifdef NEED_SOFT_SHA224
|
|
int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (sha224 == NULL)
|
|
return BAD_FUNC_ARG;
|
|
|
|
sha224->heap = heap;
|
|
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
|
sha224->W = NULL;
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW)
|
|
#if defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224)
|
|
/* We know this is a fresh, uninitialized item, so set to INIT */
|
|
if (sha224->ctx.mode != ESP32_SHA_SW) {
|
|
ESP_LOGV(TAG, "Set sha224 ctx mode init to ESP32_SHA_SW. "
|
|
"Prior value: %d", sha224->ctx.mode);
|
|
}
|
|
/* no sha224 HW support is available, set to SW */
|
|
sha224->ctx.mode = ESP32_SHA_SW;
|
|
#else
|
|
/* We know this is a fresh, uninitialized item, so set to INIT */
|
|
sha224->ctx.mode = ESP32_SHA_INIT;
|
|
#endif
|
|
#endif
|
|
|
|
ret = InitSha224(sha224);
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
|
|
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224)
|
|
ret = wolfAsync_DevCtxInit(&sha224->asyncDev,
|
|
WOLFSSL_ASYNC_MARKER_SHA224, sha224->heap, devId);
|
|
#else
|
|
(void)devId;
|
|
#endif /* WOLFSSL_ASYNC_CRYPT */
|
|
#ifdef WOLFSSL_IMXRT1170_CAAM
|
|
ret = wc_CAAM_HashInit(&sha224->hndl, &sha224->ctx, WC_HASH_TYPE_SHA224);
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
|
|
(!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) || \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224))
|
|
if (sha224->ctx.mode != ESP32_SHA_INIT) {
|
|
ESP_LOGV("SHA224", "Set ctx mode from prior value: "
|
|
"%d", sha224->ctx.mode);
|
|
}
|
|
/* We know this is a fresh, uninitialized item, so set to INIT */
|
|
sha224->ctx.mode = ESP32_SHA_INIT;
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
int wc_Sha224Update(wc_Sha224* sha224, const byte* data, word32 len)
|
|
{
|
|
int ret;
|
|
|
|
if (sha224 == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
if (data == NULL && len == 0) {
|
|
/* valid, but do nothing */
|
|
return 0;
|
|
}
|
|
if (data == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224)
|
|
if (sha224->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA224) {
|
|
#if defined(HAVE_INTEL_QA)
|
|
return IntelQaSymSha224(&sha224->asyncDev, NULL, data, len);
|
|
#endif
|
|
}
|
|
#endif /* WOLFSSL_ASYNC_CRYPT */
|
|
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
|
|
(defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) || \
|
|
defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224))
|
|
sha224->ctx.mode = ESP32_SHA_SW; /* no SHA224 HW, so always SW */
|
|
#endif
|
|
|
|
ret = Sha256Update((wc_Sha256*)sha224, data, len);
|
|
|
|
return ret;
|
|
}
|
|
|
|
int wc_Sha224Final(wc_Sha224* sha224, byte* hash)
|
|
{
|
|
int ret;
|
|
|
|
if (sha224 == NULL || hash == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224)
|
|
if (sha224->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA224) {
|
|
#if defined(HAVE_INTEL_QA)
|
|
return IntelQaSymSha224(&sha224->asyncDev, hash, NULL,
|
|
WC_SHA224_DIGEST_SIZE);
|
|
#endif
|
|
}
|
|
#endif /* WOLFSSL_ASYNC_CRYPT */
|
|
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
|
|
( !defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) || \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224) )
|
|
|
|
/* nothing enabled here for RISC-V C2/C3/C6 success */
|
|
#endif
|
|
|
|
ret = Sha256Final((wc_Sha256*)sha224);
|
|
if (ret != 0)
|
|
return ret;
|
|
|
|
#if defined(LITTLE_ENDIAN_ORDER)
|
|
if (SHA256_REV_BYTES(&sha224->ctx)) {
|
|
ByteReverseWords(sha224->digest,
|
|
sha224->digest,
|
|
WC_SHA224_DIGEST_SIZE);
|
|
}
|
|
#endif
|
|
XMEMCPY(hash, sha224->digest, WC_SHA224_DIGEST_SIZE);
|
|
|
|
return InitSha224(sha224); /* reset state */
|
|
}
|
|
#endif /* end of SHA224 software implementation */
|
|
|
|
int wc_InitSha224(wc_Sha224* sha224)
|
|
{
|
|
int devId = INVALID_DEVID;
|
|
|
|
#ifdef WOLF_CRYPTO_CB
|
|
devId = wc_CryptoCb_DefaultDevID();
|
|
#endif
|
|
return wc_InitSha224_ex(sha224, NULL, devId);
|
|
}
|
|
|
|
#if !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH)
|
|
/* implemented in wolfcrypt/src/port/psa/psa_hash.c */
|
|
|
|
void wc_Sha224Free(wc_Sha224* sha224)
|
|
{
|
|
if (sha224 == NULL)
|
|
return;
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
|
if (sha224->W != NULL) {
|
|
ForceZero(sha224->W, sizeof(word32) * WC_SHA224_BLOCK_SIZE);
|
|
XFREE(sha224->W, NULL, DYNAMIC_TYPE_DIGEST);
|
|
sha224->W = NULL;
|
|
}
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224)
|
|
wolfAsync_DevCtxFree(&sha224->asyncDev, WOLFSSL_ASYNC_MARKER_SHA224);
|
|
#endif /* WOLFSSL_ASYNC_CRYPT */
|
|
|
|
#ifdef WOLFSSL_PIC32MZ_HASH
|
|
wc_Sha256Pic32Free(sha224);
|
|
#endif
|
|
#if defined(WOLFSSL_KCAPI_HASH)
|
|
KcapiHashFree(&sha224->kcapi);
|
|
#endif
|
|
#if defined(WOLFSSL_RENESAS_RX64_HASH)
|
|
if (sha224->msg != NULL) {
|
|
ForceZero(sha224->msg, sha224->len);
|
|
XFREE(sha224->msg, sha224->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
|
sha224->msg = NULL;
|
|
}
|
|
#endif
|
|
ForceZero(sha224, sizeof(*sha224));
|
|
}
|
|
#endif /* !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH) */
|
|
#endif /* WOLFSSL_SHA224 */
|
|
|
|
|
|
int wc_InitSha256(wc_Sha256* sha256)
|
|
{
|
|
int devId = INVALID_DEVID;
|
|
|
|
#ifdef WOLF_CRYPTO_CB
|
|
devId = wc_CryptoCb_DefaultDevID();
|
|
#endif
|
|
return wc_InitSha256_ex(sha256, NULL, devId);
|
|
}
|
|
|
|
#if !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH)
|
|
/* implemented in wolfcrypt/src/port/psa/psa_hash.c */
|
|
|
|
void wc_Sha256Free(wc_Sha256* sha256)
|
|
{
|
|
if (sha256 == NULL)
|
|
return;
|
|
|
|
#if defined(WOLFSSL_ESP32) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256)
|
|
esp_sha_release_unfinished_lock(&sha256->ctx);
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
|
if (sha256->W != NULL) {
|
|
ForceZero(sha256->W, sizeof(word32) * WC_SHA256_BLOCK_SIZE);
|
|
XFREE(sha256->W, NULL, DYNAMIC_TYPE_DIGEST);
|
|
sha256->W = NULL;
|
|
}
|
|
#endif
|
|
|
|
#ifdef MAX3266X_SHA_CB
|
|
wc_MXC_TPU_SHA_Free(&(sha256->mxcCtx));
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
|
|
wolfAsync_DevCtxFree(&sha256->asyncDev, WOLFSSL_ASYNC_MARKER_SHA256);
|
|
#endif /* WOLFSSL_ASYNC_CRYPT */
|
|
#ifdef WOLFSSL_PIC32MZ_HASH
|
|
wc_Sha256Pic32Free(sha256);
|
|
#endif
|
|
#if defined(WOLFSSL_AFALG_HASH)
|
|
if (sha256->alFd > 0) {
|
|
close(sha256->alFd);
|
|
sha256->alFd = -1; /* avoid possible double close on socket */
|
|
}
|
|
if (sha256->rdFd > 0) {
|
|
close(sha256->rdFd);
|
|
sha256->rdFd = -1; /* avoid possible double close on socket */
|
|
}
|
|
#endif /* WOLFSSL_AFALG_HASH */
|
|
#ifdef WOLFSSL_DEVCRYPTO_HASH
|
|
wc_DevCryptoFree(&sha256->ctx);
|
|
#endif /* WOLFSSL_DEVCRYPTO */
|
|
#if (defined(WOLFSSL_AFALG_HASH) && defined(WOLFSSL_AFALG_HASH_KEEP)) || \
|
|
(defined(WOLFSSL_DEVCRYPTO_HASH) && defined(WOLFSSL_DEVCRYPTO_HASH_KEEP)) || \
|
|
((defined(WOLFSSL_RENESAS_TSIP_TLS) || \
|
|
defined(WOLFSSL_RENESAS_TSIP_CRYPTONLY)) && \
|
|
!defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH)) || \
|
|
(defined(WOLFSSL_RENESAS_SCEPROTECT) && \
|
|
!defined(NO_WOLFSSL_RENESAS_FSPSM_HASH)) || \
|
|
defined(WOLFSSL_RENESAS_RX64_HASH) || \
|
|
defined(WOLFSSL_HASH_KEEP)
|
|
|
|
if (sha256->msg != NULL) {
|
|
ForceZero(sha256->msg, sha256->len);
|
|
XFREE(sha256->msg, sha256->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
|
sha256->msg = NULL;
|
|
}
|
|
#endif
|
|
#if defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_HASH)
|
|
se050_hash_free(&sha256->se050Ctx);
|
|
#endif
|
|
#if defined(WOLFSSL_KCAPI_HASH)
|
|
KcapiHashFree(&sha256->kcapi);
|
|
#endif
|
|
#ifdef WOLFSSL_IMXRT_DCP
|
|
DCPSha256Free(sha256);
|
|
#endif
|
|
#ifdef WOLFSSL_MAXQ10XX_CRYPTO
|
|
wc_MAXQ10XX_Sha256Free(sha256);
|
|
#endif
|
|
|
|
#ifdef HAVE_ARIA
|
|
if (sha256->hSession != NULL) {
|
|
MC_CloseSession(sha256->hSession);
|
|
sha256->hSession = NULL;
|
|
}
|
|
#endif
|
|
|
|
/* Espressif embedded hardware acceleration specific: */
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256)
|
|
if (sha256->ctx.lockDepth > 0) {
|
|
/* probably due to unclean shutdown, error, or other problem.
|
|
*
|
|
* if you find yourself here, code needs to be cleaned up to
|
|
* properly release hardware. this init is only for handling
|
|
* the unexpected. by the time free is called, the hardware
|
|
* should have already been released (lockDepth = 0)
|
|
*/
|
|
(void)InitSha256(sha256); /* unlock mutex, set mode to ESP32_SHA_INIT */
|
|
ESP_LOGV(TAG, "Alert: hardware unlock needed in wc_Sha256Free.");
|
|
}
|
|
else {
|
|
ESP_LOGV(TAG, "Hardware unlock not needed in wc_Sha256Free.");
|
|
}
|
|
#endif
|
|
ForceZero(sha256, sizeof(*sha256));
|
|
} /* wc_Sha256Free */
|
|
|
|
#endif /* !defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH) */
|
|
#ifdef WOLFSSL_HASH_KEEP
|
|
/* Some hardware have issues with update, this function stores the data to be
|
|
* hashed into an array. Once ready, the Final operation is called on all of the
|
|
* data to be hashed at once.
|
|
* returns 0 on success
|
|
*/
|
|
int wc_Sha256_Grow(wc_Sha256* sha256, const byte* in, int inSz)
|
|
{
|
|
return _wc_Hash_Grow(&(sha256->msg), &(sha256->used), &(sha256->len), in,
|
|
inSz, sha256->heap);
|
|
}
|
|
#ifdef WOLFSSL_SHA224
|
|
int wc_Sha224_Grow(wc_Sha224* sha224, const byte* in, int inSz)
|
|
{
|
|
return _wc_Hash_Grow(&(sha224->msg), &(sha224->used), &(sha224->len), in,
|
|
inSz, sha224->heap);
|
|
}
|
|
#endif /* WOLFSSL_SHA224 */
|
|
#endif /* WOLFSSL_HASH_KEEP */
|
|
|
|
#endif /* !WOLFSSL_TI_HASH */
|
|
|
|
|
|
#ifndef WOLFSSL_TI_HASH
|
|
#if !defined(WOLFSSL_RENESAS_RX64_HASH) && \
|
|
(!defined(WOLFSSL_RENESAS_RSIP) || \
|
|
defined(NO_WOLFSSL_RENESAS_FSPSM_HASH))
|
|
#ifdef WOLFSSL_SHA224
|
|
|
|
#if defined(WOLFSSL_KCAPI_HASH) && !defined(WOLFSSL_NO_KCAPI_SHA224)
|
|
/* implemented in wolfcrypt/src/port/kcapi/kcapi_hash.c */
|
|
#elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH)
|
|
/* implemented in wolfcrypt/src/port/psa/psa_hash.c */
|
|
|
|
#elif defined(MAX3266X_SHA)
|
|
/* implemented in wolfcrypt/src/port/maxim/max3266x.c */
|
|
|
|
#else
|
|
|
|
int wc_Sha224GetHash(wc_Sha224* sha224, byte* hash)
|
|
{
|
|
int ret;
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
wc_Sha224* tmpSha224;
|
|
#else
|
|
wc_Sha224 tmpSha224[1];
|
|
#endif
|
|
|
|
if (sha224 == NULL || hash == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
tmpSha224 = (wc_Sha224*)XMALLOC(sizeof(wc_Sha224), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (tmpSha224 == NULL) {
|
|
return MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
ret = wc_Sha224Copy(sha224, tmpSha224);
|
|
if (ret == 0) {
|
|
ret = wc_Sha224Final(tmpSha224, hash);
|
|
wc_Sha224Free(tmpSha224);
|
|
}
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
XFREE(tmpSha224, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
return ret;
|
|
}
|
|
|
|
int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst)
|
|
{
|
|
int ret = 0; /* assume success unless proven otherwise */
|
|
|
|
if (src == NULL || dst == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
XMEMCPY(dst, src, sizeof(wc_Sha224));
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
|
dst->W = NULL;
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_SILABS_SE_ACCEL) && defined(WOLFSSL_SILABS_SE_ACCEL_3)
|
|
dst->silabsCtx.hash_ctx.cmd_ctx = &dst->silabsCtx.cmd_ctx;
|
|
dst->silabsCtx.hash_ctx.hash_type_ctx = &dst->silabsCtx.hash_type_ctx;
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA224)
|
|
ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
|
|
(!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256) || \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA224))
|
|
/* regardless of any other settings, there's no SHA-224 HW on ESP32 */
|
|
#ifndef CONFIG_IDF_TARGET_ESP32
|
|
ret = esp_sha224_ctx_copy(src, dst);
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_HASH_FLAGS
|
|
dst->flags |= WC_HASH_FLAG_ISCOPY;
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_HASH_KEEP)
|
|
if (src->msg != NULL) {
|
|
dst->msg = (byte*)XMALLOC(src->len, dst->heap,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (dst->msg == NULL)
|
|
return MEMORY_E;
|
|
XMEMCPY(dst->msg, src->msg, src->len);
|
|
}
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endif /* WOLFSSL_KCAPI_HASH && !WOLFSSL_NO_KCAPI_SHA224 */
|
|
|
|
#ifdef WOLFSSL_HASH_FLAGS
|
|
int wc_Sha224SetFlags(wc_Sha224* sha224, word32 flags)
|
|
{
|
|
if (sha224) {
|
|
sha224->flags = flags;
|
|
}
|
|
return 0;
|
|
}
|
|
int wc_Sha224GetFlags(wc_Sha224* sha224, word32* flags)
|
|
{
|
|
if (sha224 && flags) {
|
|
*flags = sha224->flags;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
#endif /* WOLFSSL_SHA224 */
|
|
#endif /* WOLFSSL_RENESAS_RX64_HASH */
|
|
|
|
#ifdef WOLFSSL_AFALG_HASH
|
|
/* implemented in wolfcrypt/src/port/af_alg/afalg_hash.c */
|
|
|
|
#elif defined(WOLFSSL_DEVCRYPTO_HASH)
|
|
/* implemented in wolfcrypt/src/port/devcrypto/devcrypt_hash.c */
|
|
|
|
#elif (defined(WOLFSSL_RENESAS_TSIP_TLS) || \
|
|
defined(WOLFSSL_RENESAS_TSIP_CRYPTONLY)) && \
|
|
!defined(NO_WOLFSSL_RENESAS_TSIP_CRYPT_HASH)
|
|
|
|
/* implemented in wolfcrypt/src/port/Renesas/renesas_tsip_sha.c */
|
|
|
|
#elif (defined(WOLFSSL_RENESAS_SCEPROTECT) || defined(WOLFSSL_RENESAS_RSIP))\
|
|
&& !defined(NO_WOLFSSL_RENESAS_FSPSM_HASH)
|
|
|
|
/* implemented in wolfcrypt/src/port/Renesas/renesas_fspsm_sha.c */
|
|
|
|
#elif defined(WOLFSSL_PSOC6_CRYPTO)
|
|
/* implemented in wolfcrypt/src/port/cypress/psoc6_crypto.c */
|
|
#elif defined(WOLFSSL_IMXRT_DCP)
|
|
/* implemented in wolfcrypt/src/port/nxp/dcp_port.c */
|
|
#elif defined(WOLFSSL_KCAPI_HASH)
|
|
/* implemented in wolfcrypt/src/port/kcapi/kcapi_hash.c */
|
|
|
|
#elif defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH)
|
|
/* implemented in wolfcrypt/src/port/psa/psa_hash.c */
|
|
#elif defined(WOLFSSL_RENESAS_RX64_HASH)
|
|
/* implemented in wolfcrypt/src/port/Renesas/renesas_rx64_hw_sha.c */
|
|
#elif defined(MAX3266X_SHA)
|
|
/* Implemented in wolfcrypt/src/port/maxim/max3266x.c */
|
|
#else
|
|
|
|
int wc_Sha256GetHash(wc_Sha256* sha256, byte* hash)
|
|
{
|
|
int ret;
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
wc_Sha256* tmpSha256;
|
|
#else
|
|
wc_Sha256 tmpSha256[1];
|
|
#endif
|
|
|
|
if (sha256 == NULL || hash == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
tmpSha256 = (wc_Sha256*)XMALLOC(sizeof(wc_Sha256), NULL,
|
|
DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (tmpSha256 == NULL) {
|
|
return MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
ret = wc_Sha256Copy(sha256, tmpSha256);
|
|
if (ret == 0) {
|
|
ret = wc_Sha256Final(tmpSha256, hash);
|
|
wc_Sha256Free(tmpSha256);
|
|
}
|
|
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK
|
|
XFREE(tmpSha256, NULL, DYNAMIC_TYPE_TMP_BUFFER);
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst)
|
|
{
|
|
int ret = 0;
|
|
|
|
if (src == NULL || dst == NULL) {
|
|
return BAD_FUNC_ARG;
|
|
}
|
|
|
|
XMEMCPY(dst, src, sizeof(wc_Sha256));
|
|
|
|
#ifdef WOLFSSL_MAXQ10XX_CRYPTO
|
|
wc_MAXQ10XX_Sha256Copy(src);
|
|
#endif
|
|
|
|
#ifdef MAX3266X_SHA_CB
|
|
ret = wc_MXC_TPU_SHA_Copy(&(src->mxcCtx), &(dst->mxcCtx));
|
|
if (ret != 0) {
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_SMALL_STACK_CACHE
|
|
dst->W = NULL;
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_SILABS_SE_ACCEL) && defined(WOLFSSL_SILABS_SE_ACCEL_3)
|
|
dst->silabsCtx.hash_ctx.cmd_ctx = &dst->silabsCtx.cmd_ctx;
|
|
dst->silabsCtx.hash_ctx.hash_type_ctx = &dst->silabsCtx.hash_type_ctx;
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
|
|
ret = wolfAsync_DevCopy(&src->asyncDev, &dst->asyncDev);
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_PIC32MZ_HASH
|
|
ret = wc_Pic32HashCopy(&src->cache, &dst->cache);
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_USE_ESP32_CRYPT_HASH_HW) && \
|
|
!defined(NO_WOLFSSL_ESP32_CRYPT_HASH_SHA256)
|
|
esp_sha256_ctx_copy(src, dst);
|
|
#endif
|
|
|
|
#ifdef HAVE_ARIA
|
|
dst->hSession = NULL;
|
|
if((src->hSession != NULL) && (MC_CopySession(src->hSession, &(dst->hSession)) != MC_OK)) {
|
|
return MEMORY_E;
|
|
}
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_HASH_FLAGS
|
|
dst->flags |= WC_HASH_FLAG_ISCOPY;
|
|
#endif
|
|
|
|
#if defined(WOLFSSL_HASH_KEEP)
|
|
if (src->msg != NULL) {
|
|
dst->msg = (byte*)XMALLOC(src->len, dst->heap, DYNAMIC_TYPE_TMP_BUFFER);
|
|
if (dst->msg == NULL)
|
|
return MEMORY_E;
|
|
XMEMCPY(dst->msg, src->msg, src->len);
|
|
}
|
|
#endif
|
|
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
#ifdef WOLFSSL_HASH_FLAGS
|
|
int wc_Sha256SetFlags(wc_Sha256* sha256, word32 flags)
|
|
{
|
|
if (sha256) {
|
|
sha256->flags = flags;
|
|
}
|
|
return 0;
|
|
}
|
|
int wc_Sha256GetFlags(wc_Sha256* sha256, word32* flags)
|
|
{
|
|
if (sha256 && flags) {
|
|
*flags = sha256->flags;
|
|
}
|
|
return 0;
|
|
}
|
|
#endif
|
|
#endif /* !WOLFSSL_TI_HASH */
|
|
|
|
#endif /* NO_SHA256 */
|