implement WC_C_DYNAMIC_FALLBACK for SHA256.

This commit is contained in:
Daniel Pouzzner
2024-04-27 01:02:31 -05:00
parent 4cc27fa58b
commit 65649b63d1
2 changed files with 99 additions and 30 deletions

View File

@@ -203,8 +203,12 @@ on the specific device platform.
#if defined(LITTLE_ENDIAN_ORDER) && \ #if defined(LITTLE_ENDIAN_ORDER) && \
defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) (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) \ #define SHA256_UPDATE_REV_BYTES(ctx) \
(!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags)) (!IS_INTEL_AVX1(intel_flags) && !IS_INTEL_AVX2(intel_flags))
#endif
#elif defined(FREESCALE_MMCAU_SHA) #elif defined(FREESCALE_MMCAU_SHA)
#define SHA256_UPDATE_REV_BYTES(ctx) 0 /* reverse not needed on update */ #define SHA256_UPDATE_REV_BYTES(ctx) 0 /* reverse not needed on update */
#else #else
@@ -228,6 +232,13 @@ on the specific device platform.
(!defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH)) && \ (!defined(WOLFSSL_HAVE_PSA) || defined(WOLFSSL_PSA_NO_HASH)) && \
!defined(WOLFSSL_RENESAS_RX64_HASH) !defined(WOLFSSL_RENESAS_RX64_HASH)
static void Sha256_SetTransform(
#ifdef WC_C_DYNAMIC_FALLBACK
int *sha_method
#else
void
#endif
);
static int InitSha256(wc_Sha256* sha256) static int InitSha256(wc_Sha256* sha256)
{ {
@@ -253,6 +264,16 @@ static int InitSha256(wc_Sha256* sha256)
sha256->used = 0; sha256->used = 0;
#endif #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 WOLF_CRYPTO_CB #ifdef WOLF_CRYPTO_CB
sha256->devId = wc_CryptoCb_DefaultDevID(); sha256->devId = wc_CryptoCb_DefaultDevID();
#endif #endif
@@ -371,34 +392,56 @@ static int InitSha256(wc_Sha256* sha256)
} /* extern "C" */ } /* extern "C" */
#endif #endif
static word32 intel_flags; #if defined(WC_C_DYNAMIC_FALLBACK) && !defined(WC_NO_INTERNAL_FUNCTION_POINTERS)
static int Transform_Sha256_is_vectorized = 0; #define WC_NO_INTERNAL_FUNCTION_POINTERS
#endif
#ifdef WC_NO_INTERNAL_FUNCTION_POINTERS #ifdef WC_NO_INTERNAL_FUNCTION_POINTERS
static enum { SHA256_UNSET, SHA256_AVX1, SHA256_AVX2, SHA256_AVX1_RORX, enum sha_methods { SHA256_UNSET = 0, SHA256_AVX1, SHA256_AVX2,
SHA256_AVX2_RORX, SHA256_SSE2, SHA256_C } SHA256_AVX1_RORX, SHA256_AVX2_RORX, SHA256_SSE2,
sha_method = SHA256_UNSET; SHA256_C };
static void Sha256_SetTransform(void) #ifndef WC_C_DYNAMIC_FALLBACK
static word32 intel_flags;
static enum sha_methods sha_method = SHA256_UNSET;
#endif
static void Sha256_SetTransform(
#ifdef WC_C_DYNAMIC_FALLBACK
int *sha_method
#else
void
#endif
)
{ {
#ifdef WC_C_DYNAMIC_FALLBACK
if (sha_method != SHA256_UNSET) #define SHA_METHOD (*sha_method)
word32 intel_flags;
#else
#define SHA_METHOD sha_method
#endif
if (SHA_METHOD != SHA256_UNSET)
return; return;
#ifdef WC_C_DYNAMIC_FALLBACK
if (! CAN_SAVE_VECTOR_REGISTERS()) {
SHA_METHOD = SHA256_C;
return;
}
#endif
intel_flags = cpuid_get_flags(); intel_flags = cpuid_get_flags();
if (IS_INTEL_SHA(intel_flags)) { if (IS_INTEL_SHA(intel_flags)) {
#ifdef HAVE_INTEL_AVX1 #ifdef HAVE_INTEL_AVX1
if (IS_INTEL_AVX1(intel_flags)) { if (IS_INTEL_AVX1(intel_flags)) {
sha_method = SHA256_AVX1; SHA_METHOD = SHA256_AVX1;
Transform_Sha256_is_vectorized = 1;
} }
else else
#endif #endif
{ {
sha_method = SHA256_SSE2; SHA_METHOD = SHA256_SSE2;
Transform_Sha256_is_vectorized = 1;
} }
} }
else else
@@ -406,14 +449,12 @@ static int InitSha256(wc_Sha256* sha256)
if (IS_INTEL_AVX2(intel_flags)) { if (IS_INTEL_AVX2(intel_flags)) {
#ifdef HAVE_INTEL_RORX #ifdef HAVE_INTEL_RORX
if (IS_INTEL_BMI2(intel_flags)) { if (IS_INTEL_BMI2(intel_flags)) {
sha_method = SHA256_AVX2_RORX; SHA_METHOD = SHA256_AVX2_RORX;
Transform_Sha256_is_vectorized = 1;
} }
else else
#endif #endif
{ {
sha_method = SHA256_AVX2; SHA_METHOD = SHA256_AVX2;
Transform_Sha256_is_vectorized = 1;
} }
} }
else else
@@ -422,30 +463,34 @@ static int InitSha256(wc_Sha256* sha256)
if (IS_INTEL_AVX1(intel_flags)) { if (IS_INTEL_AVX1(intel_flags)) {
#ifdef HAVE_INTEL_RORX #ifdef HAVE_INTEL_RORX
if (IS_INTEL_BMI2(intel_flags)) { if (IS_INTEL_BMI2(intel_flags)) {
sha_method = SHA256_AVX1_RORX; SHA_METHOD = SHA256_AVX1_RORX;
Transform_Sha256_is_vectorized = 1;
} }
else else
#endif #endif
{ {
sha_method = SHA256_AVX1; SHA_METHOD = SHA256_AVX1;
Transform_Sha256_is_vectorized = 1;
} }
} }
else else
#endif #endif
{ {
sha_method = SHA256_C; SHA_METHOD = SHA256_C;
Transform_Sha256_is_vectorized = 0;
} }
#undef SHA_METHOD
} }
static WC_INLINE int inline_XTRANSFORM(wc_Sha256* S, const byte* D) { 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; int ret;
if (sha_method == SHA256_C)
if (SHA_METHOD == SHA256_C)
return Transform_Sha256(S, D); return Transform_Sha256(S, D);
SAVE_VECTOR_REGISTERS(return _svr_ret;); SAVE_VECTOR_REGISTERS(return _svr_ret;);
switch (sha_method) { switch (SHA_METHOD) {
case SHA256_AVX2: case SHA256_AVX2:
ret = Transform_Sha256_AVX2(S, D); ret = Transform_Sha256_AVX2(S, D);
break; break;
@@ -469,13 +514,19 @@ static int InitSha256(wc_Sha256* sha256)
} }
RESTORE_VECTOR_REGISTERS(); RESTORE_VECTOR_REGISTERS();
return ret; return ret;
#undef SHA_METHOD
} }
#define XTRANSFORM(...) inline_XTRANSFORM(__VA_ARGS__) #define XTRANSFORM(...) inline_XTRANSFORM(__VA_ARGS__)
static WC_INLINE int inline_XTRANSFORM_LEN(wc_Sha256* S, const byte* D, word32 L) { 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; int ret;
SAVE_VECTOR_REGISTERS(return _svr_ret;); SAVE_VECTOR_REGISTERS(return _svr_ret;);
switch (sha_method) { switch (SHA_METHOD) {
case SHA256_AVX2: case SHA256_AVX2:
ret = Transform_Sha256_AVX2_Len(S, D, L); ret = Transform_Sha256_AVX2_Len(S, D, L);
break; break;
@@ -499,6 +550,7 @@ static int InitSha256(wc_Sha256* sha256)
} }
RESTORE_VECTOR_REGISTERS(); RESTORE_VECTOR_REGISTERS();
return ret; return ret;
#undef SHA_METHOD
} }
#define XTRANSFORM_LEN(...) inline_XTRANSFORM_LEN(__VA_ARGS__) #define XTRANSFORM_LEN(...) inline_XTRANSFORM_LEN(__VA_ARGS__)
@@ -510,6 +562,7 @@ static int InitSha256(wc_Sha256* sha256)
word32 len); word32 len);
/* = NULL */ /* = NULL */
static int transform_check = 0; static int transform_check = 0;
static int Transform_Sha256_is_vectorized = 0;
static WC_INLINE int inline_XTRANSFORM(wc_Sha256* S, const byte* D) { static WC_INLINE int inline_XTRANSFORM(wc_Sha256* S, const byte* D) {
int ret; int ret;
@@ -632,9 +685,6 @@ static int InitSha256(wc_Sha256* sha256)
if (ret != 0) if (ret != 0)
return ret; return ret;
/* choose best Transform function under this runtime environment */
Sha256_SetTransform();
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256) #if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
ret = wolfAsync_DevCtxInit(&sha256->asyncDev, ret = wolfAsync_DevCtxInit(&sha256->asyncDev,
WOLFSSL_ASYNC_MARKER_SHA256, sha256->heap, devId); WOLFSSL_ASYNC_MARKER_SHA256, sha256->heap, devId);
@@ -1312,7 +1362,9 @@ static int InitSha256(wc_Sha256* sha256)
#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))
#ifdef WC_NO_INTERNAL_FUNCTION_POINTERS #ifdef WC_C_DYNAMIC_FALLBACK
if (sha256->sha_method != SHA256_C)
#elif defined(WC_NO_INTERNAL_FUNCTION_POINTERS)
if (sha_method != SHA256_C) if (sha_method != SHA256_C)
#else #else
if (Transform_Sha256_Len_p != NULL) if (Transform_Sha256_Len_p != NULL)
@@ -1553,8 +1605,12 @@ static int InitSha256(wc_Sha256* sha256)
/* Kinetis requires only these bytes reversed */ /* Kinetis requires only these bytes reversed */
#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) (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)) if (IS_INTEL_AVX1(intel_flags) || IS_INTEL_AVX2(intel_flags))
#endif #endif
#endif
{ {
ByteReverseWords( ByteReverseWords(
&sha256->buffer[WC_SHA256_PAD_SIZE / sizeof(word32)], &sha256->buffer[WC_SHA256_PAD_SIZE / sizeof(word32)],
@@ -1898,10 +1954,18 @@ static int InitSha256(wc_Sha256* sha256)
sha224->loLen = 0; sha224->loLen = 0;
sha224->hiLen = 0; sha224->hiLen = 0;
#ifdef WC_C_DYNAMIC_FALLBACK
sha224->sha_method = 0;
#endif
#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \ #if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) (defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))
/* choose best Transform function under this runtime environment */ /* choose best Transform function under this runtime environment */
#ifdef WC_C_DYNAMIC_FALLBACK
Sha256_SetTransform(&sha224->sha_method);
#else
Sha256_SetTransform(); Sha256_SetTransform();
#endif
#endif #endif
#ifdef WOLFSSL_HASH_FLAGS #ifdef WOLFSSL_HASH_FLAGS
sha224->flags = 0; sha224->flags = 0;

View File

@@ -186,6 +186,11 @@ struct wc_Sha256 {
word32 loLen; /* length in bytes */ word32 loLen; /* length in bytes */
word32 hiLen; /* length in bytes */ word32 hiLen; /* length in bytes */
void* heap; void* heap;
#ifdef WC_C_DYNAMIC_FALLBACK
int sha_method;
#endif
#endif #endif
#ifdef WOLFSSL_PIC32MZ_HASH #ifdef WOLFSSL_PIC32MZ_HASH
hashUpdCache cache; /* cache for updates */ hashUpdCache cache; /* cache for updates */