Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 15 additions & 1 deletion .github/workflows/cryptocb-only.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,19 @@ jobs:
# the software path via cryptocb.
- name: SHA256
cppflags: -DWOLF_CRYPTO_CB_ONLY_SHA256
# WOLF_CRYPTO_CB_ONLY_SHA512: strips software SHA-512 family (SHA-384,
# SHA-512/224, SHA-512/256, SHA-512); swdev handles every variant
# explicitly via cryptocb.
- name: SHA512
cppflags: -DWOLF_CRYPTO_CB_ONLY_SHA512
# Same as SHA512 but tells swdev to refuse the SHA-384 / SHA-512/224 /
# SHA-512/256 variant callbacks (WOLFSSL_SWDEV_SHA512_GENERAL_ONLY). That
# forces the cryptocb dispatcher's fallback-to-plain-SHA-512-with-
# truncation path. The SHA512 entry above instead has swdev handle
# every variant end-to-end, so the dispatcher fallback is otherwise
# uncovered.
- name: SHA512_via_general
cppflags: -DWOLF_CRYPTO_CB_ONLY_SHA512 -DWOLFSSL_SWDEV_SHA512_GENERAL_ONLY
# WOLF_CRYPTO_CB_ONLY_AES: strips software AES; swdev provides the
# software path via cryptocb.
- name: AES
Expand All @@ -51,7 +64,8 @@ jobs:
- name: ALL
cppflags: >-
-DWOLF_CRYPTO_CB_ONLY_ECC -DWOLF_CRYPTO_CB_ONLY_RSA
-DWOLF_CRYPTO_CB_ONLY_SHA256 -DWOLF_CRYPTO_CB_ONLY_AES
-DWOLF_CRYPTO_CB_ONLY_SHA256 -DWOLF_CRYPTO_CB_ONLY_SHA512
-DWOLF_CRYPTO_CB_ONLY_AES
name: make check (${{ matrix.name }})
if: ${{ (github.repository_owner == 'wolfssl') && (github.event_name != 'pull_request' || github.event.pull_request.draft == false) }}
runs-on: ubuntu-24.04
Expand Down
2 changes: 2 additions & 0 deletions .wolfssl_known_macro_extras
Original file line number Diff line number Diff line change
Expand Up @@ -966,6 +966,8 @@ WOLFSSL_XIL_MSG_NO_SLEEP
WOLFSSL_ZEPHYR
WOLF_ALLOW_BUILTIN
WOLF_CRYPTO_CB_CMD
WOLF_CRYPTO_CB_NO_SHA512_FALLBACK
WOLF_CRYPTO_CB_ONLY_SHA512
WOLF_CRYPTO_DEV
WOLF_NO_TRAILING_ENUM_COMMAS
WindowsCE
Expand Down
9 changes: 6 additions & 3 deletions src/ssl_crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -611,7 +611,8 @@ int wolfSSL_SHA512_Final(byte* output, WOLFSSL_SHA512_CTX* sha512)

#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) && \
!defined(WOLFSSL_KCAPI_HASH) /* doesn't support direct transform */
!defined(WOLFSSL_KCAPI_HASH) /* doesn't support direct transform */ && \
!defined(WOLF_CRYPTO_CB_ONLY_SHA512) /* no wc_Sha512Transform in CB-only */
/* Apply SHA-512 transformation to the data.
*
* @param [in, out] sha512 SHA512 context object.
Expand Down Expand Up @@ -687,7 +688,8 @@ int wolfSSL_SHA512_224_Final(byte* output, WOLFSSL_SHA512_224_CTX* sha512)
}

#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)))
(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) && \
!defined(WOLF_CRYPTO_CB_ONLY_SHA512) /* no wc_Sha512_224Transform in CB-only */
/* Apply SHA-512-224 transformation to the data.
*
* @param [in, out] sha512 SHA512 context object.
Expand Down Expand Up @@ -765,7 +767,8 @@ int wolfSSL_SHA512_256_Final(byte* output, WOLFSSL_SHA512_256_CTX* sha512)
}

#if !defined(HAVE_SELFTEST) && (!defined(HAVE_FIPS) || \
(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2)))
(defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION > 2))) && \
!defined(WOLF_CRYPTO_CB_ONLY_SHA512) /* no wc_Sha512_256Transform in CB-only */
/* Apply SHA-512-256 transformation to the data.
*
* @param [in, out] sha512 SHA512 context object.
Expand Down
6 changes: 4 additions & 2 deletions tests/api.c
Original file line number Diff line number Diff line change
Expand Up @@ -27527,7 +27527,8 @@ static int test_SSL_CIPHER_get_xxx(void)

#if defined(WOLF_CRYPTO_CB) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \
(!defined(WOLF_CRYPTO_CB_ONLY_SHA256) && !defined(WOLF_CRYPTO_CB_ONLY_AES) && \
!defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA))
!defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA) && \
!defined(WOLF_CRYPTO_CB_ONLY_SHA512))

static int load_pem_key_file_as_der(const char* privKeyFile, DerBuffer** pDer,
int* keyFormat)
Expand Down Expand Up @@ -28531,7 +28532,8 @@ static int test_wc_CryptoCb(void)
EXPECT_DECLS;
#if defined(WOLF_CRYPTO_CB) && \
(!defined(WOLF_CRYPTO_CB_ONLY_SHA256) && !defined(WOLF_CRYPTO_CB_ONLY_AES) && \
!defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA))
!defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA) && \
!defined(WOLF_CRYPTO_CB_ONLY_SHA512))
/* TODO: Add crypto callback API tests */

#ifdef HAVE_IO_TESTS_DEPENDENCIES
Expand Down
281 changes: 281 additions & 0 deletions tests/api/test_sha512.c
Original file line number Diff line number Diff line change
Expand Up @@ -874,3 +874,284 @@ int test_wc_Sha384_Flags(void)
return EXPECT_RESULT();
}

/* The SHA-512/224 and SHA-512/256 variants are only available under these
* build conditions. */
#if defined(WOLFSSL_SHA512) && !defined(WOLFSSL_NOSHA512_224) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 3)) && !defined(HAVE_SELFTEST)
#define TEST_WC_SHA512_224_FALLBACK
#endif
#if defined(WOLFSSL_SHA512) && !defined(WOLFSSL_NOSHA512_256) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 3)) && !defined(HAVE_SELFTEST)
#define TEST_WC_SHA512_256_FALLBACK
#endif

#if defined(WOLF_CRYPTO_CB) && defined(WOLFSSL_SHA512) && \
!defined(NO_SHA2_CRYPTO_CB) && \
((!defined(WOLF_CRYPTO_CB_NO_SHA512_FALLBACK) && \
(defined(WOLFSSL_SHA384) || defined(TEST_WC_SHA512_224_FALLBACK) || \
defined(TEST_WC_SHA512_256_FALLBACK))) || \
defined(WOLF_CRYPTO_CB_ONLY_SHA512))

#include <wolfssl/wolfcrypt/cryptocb.h>

#define TEST_CRYPTOCB_SHA512_DEVID 2

typedef struct {
int variantSeen; /* SHA-384 / SHA-512-224 / SHA-512-256 callback declined */
int sha512Seen; /* generic SHA-512 callback the fallback lands on */
#ifdef WOLF_CRYPTO_CB_FREE
int freeSeen; /* SHA-512-family free callbacks the CB-only free routes to */
#endif
} Sha512DevCbCtx;

/* Shared SHA-512 crypto-callback test device. For HASH ops it declines every
* SHA-512 variant callback so the cryptocb dispatcher falls back to the generic
* SHA-512 callback; that callback fills a recognisable digest and deliberately
* leaves the SHA-512 IV in the caller's state, forcing the dispatcher to reset
* the state back to the variant IV. */
static int sha512_dev_cb(int devIdArg, wc_CryptoInfo* info, void* ctx)
{
Sha512DevCbCtx* cbCtx = (Sha512DevCbCtx*)ctx;
int i;

(void)devIdArg;

if (info == NULL || cbCtx == NULL)
return BAD_FUNC_ARG;

#ifdef WOLF_CRYPTO_CB_FREE
if (info->algo_type == WC_ALGO_TYPE_FREE) {
/* Count SHA-512-family frees so the test can confirm the
* CB-only free path reaches the callback instead of only zeroing the
* struct. Decline so the caller still performs its standard cleanup. */
if (info->free.algo == WC_ALGO_TYPE_HASH &&
(info->free.type == WC_HASH_TYPE_SHA512 ||
info->free.type == WC_HASH_TYPE_SHA384))
cbCtx->freeSeen++;
return CRYPTOCB_UNAVAILABLE;
}
#endif

if (info->algo_type != WC_ALGO_TYPE_HASH)
return CRYPTOCB_UNAVAILABLE;

switch (info->hash.type) {
case WC_HASH_TYPE_SHA384:
case WC_HASH_TYPE_SHA512_224:
case WC_HASH_TYPE_SHA512_256:
cbCtx->variantSeen++;
return CRYPTOCB_UNAVAILABLE;

case WC_HASH_TYPE_SHA512:
cbCtx->sha512Seen++;
if (info->hash.digest != NULL) {
for (i = 0; i < WC_SHA512_DIGEST_SIZE; i++)
info->hash.digest[i] = (byte)(0x80 + i);
}
#ifndef WOLF_CRYPTO_CB_NO_SHA512_FALLBACK
/* leave the SHA-512 IV in the caller's state to force the
* dispatcher's variant IV reset; backends that drop the digest[]
* field disable the fallback, so this only runs when it exists */
if (info->hash.sha512 != NULL) {
for (i = 0; i < (int)(sizeof(info->hash.sha512->digest) /
sizeof(info->hash.sha512->digest[0])); i++) {
info->hash.sha512->digest[i] = W64LIT(0xdeadbeefcafebabe);
}
}
#endif
return 0;

default:
return CRYPTOCB_UNAVAILABLE;
}
}

#endif

int test_wc_sha512_cryptocb_fallback(void)
{
EXPECT_DECLS;
#if defined(WOLF_CRYPTO_CB) && defined(WOLFSSL_SHA512) && \
!defined(NO_SHA2_CRYPTO_CB) && \
!defined(WOLF_CRYPTO_CB_NO_SHA512_FALLBACK) && \
(defined(WOLFSSL_SHA384) || defined(TEST_WC_SHA512_224_FALLBACK) || \
defined(TEST_WC_SHA512_256_FALLBACK))
typedef struct {
const char* name;
int (*initFn)(wc_Sha512* sha, void* heap, int devId);
int (*finalFn)(wc_Sha512* sha, byte* hash);
word32 digestSz;
} Sha512FallbackCase;
static const Sha512FallbackCase sha512FallbackCases[] = {
#ifdef WOLFSSL_SHA384
{ "SHA-384", wc_InitSha384_ex, wc_Sha384Final, WC_SHA384_DIGEST_SIZE },
#endif
#ifdef TEST_WC_SHA512_224_FALLBACK
{ "SHA-512/224", wc_InitSha512_224_ex, wc_Sha512_224Final,
WC_SHA512_224_DIGEST_SIZE },
#endif
#ifdef TEST_WC_SHA512_256_FALLBACK
{ "SHA-512/256", wc_InitSha512_256_ex, wc_Sha512_256Final,
WC_SHA512_256_DIGEST_SIZE },
#endif
};
wc_Sha512 sha;
wc_Sha512 refSha;
Sha512DevCbCtx cbCtx;
byte hash[WC_SHA512_DIGEST_SIZE];
byte devCtxMarker;
const Sha512FallbackCase* tc;
size_t c;
word32 i;

for (c = 0;
c < sizeof(sha512FallbackCases) / sizeof(sha512FallbackCases[0]);
c++) {
tc = &sha512FallbackCases[c];
devCtxMarker = 0;

XMEMSET(&sha, 0, sizeof(sha));
sha.devId = INVALID_DEVID;
sha.devCtx = NULL;
XMEMSET(&refSha, 0, sizeof(refSha));
XMEMSET(&cbCtx, 0, sizeof(cbCtx));
XMEMSET(hash, 0, sizeof(hash));

/* Reference struct capturing the freshly-initialised variant IV state,
* against which we verify the test struct after Final. */
ExpectIntEQ(tc->initFn(&refSha, HEAP_HINT, INVALID_DEVID), 0);

ExpectIntEQ(wc_CryptoCb_RegisterDevice(
TEST_CRYPTOCB_SHA512_DEVID, sha512_dev_cb,
&cbCtx), 0);

ExpectIntEQ(tc->initFn(&sha, HEAP_HINT,
TEST_CRYPTOCB_SHA512_DEVID), 0);
sha.devCtx = &devCtxMarker;

ExpectIntEQ(tc->finalFn(&sha, hash), 0);

/* the variant callback is declined, forcing the generic SHA-512
* fallback */
ExpectIntEQ(cbCtx.variantSeen, 1);
ExpectIntEQ(cbCtx.sha512Seen, 1);

/* devId and devCtx must be preserved across the SHA-512 fallback. */
ExpectIntEQ(sha.devId, TEST_CRYPTOCB_SHA512_DEVID);
ExpectPtrEq(sha.devCtx, &devCtxMarker);

/* the digest is the generic SHA-512 output truncated to the variant
* digest size */
for (i = 0; i < tc->digestSz; i++)
ExpectIntEQ(hash[i], (byte)(0x80 + i));

/* the SHA-512 fallback leaves the SHA-512 IV in the state buffer; the
* fallback must reset it back to the variant IV so the struct is ready
* to hash a new message */
ExpectIntEQ(XMEMCMP(sha.digest, refSha.digest, sizeof(sha.digest)), 0);

wc_Sha512Free(&sha);
wc_Sha512Free(&refSha);
wc_CryptoCb_UnRegisterDevice(TEST_CRYPTOCB_SHA512_DEVID);
}
#endif
return EXPECT_RESULT();
}

/* Regression test for the no-_ex SHA-512/224 and SHA-512/256 initializers under
* WOLF_CRYPTO_CB_ONLY_SHA512. With the software path stripped, they must adopt
* the registered default CryptoCb device just like wc_InitSha512() and
* wc_InitSha384(); otherwise devId stays INVALID_DEVID and the public streaming
* API returns NO_VALID_DEVID even though a default device is registered. */
int test_wc_sha512_variants_default_devid(void)
{
EXPECT_DECLS;
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_ONLY_SHA512) && \
defined(WOLFSSL_SHA512) && !defined(NO_SHA2_CRYPTO_CB) && \
!defined(WC_NO_DEFAULT_DEVID) && \
(!defined(WOLFSSL_NOSHA512_224) || !defined(WOLFSSL_NOSHA512_256))
typedef struct {
const char* name;
int (*initFn)(wc_Sha512* sha);
} Sha512VariantCase;
static const Sha512VariantCase cases[] = {
#ifndef WOLFSSL_NOSHA512_224
{ "SHA-512/224", wc_InitSha512_224 },
#endif
#ifndef WOLFSSL_NOSHA512_256
{ "SHA-512/256", wc_InitSha512_256 },
#endif
};
Sha512DevCbCtx cbCtx;
int defaultDevId;
wc_Sha512 sha;
const Sha512VariantCase* tc;
size_t c;

XMEMSET(&cbCtx, 0, sizeof(cbCtx));

ExpectIntEQ(wc_CryptoCb_RegisterDevice(TEST_CRYPTOCB_SHA512_DEVID,
sha512_dev_cb, &cbCtx), 0);
defaultDevId = wc_CryptoCb_DefaultDevID();
ExpectIntNE(defaultDevId, INVALID_DEVID);

for (c = 0; c < sizeof(cases) / sizeof(cases[0]); c++) {
tc = &cases[c];

XMEMSET(&sha, 0, sizeof(sha));
sha.devId = INVALID_DEVID;

/* the no-_ex initializer must adopt the default device rather than
* leaving devId INVALID_DEVID (which the stripped software path would
* surface as NO_VALID_DEVID from the public streaming API) */
ExpectIntEQ(tc->initFn(&sha), 0);
ExpectIntEQ(sha.devId, defaultDevId);

wc_Sha512Free(&sha);
}

wc_CryptoCb_UnRegisterDevice(TEST_CRYPTOCB_SHA512_DEVID);
#endif
return EXPECT_RESULT();
}

/* WOLF_CRYPTO_CB_FREE under WOLF_CRYPTO_CB_ONLY_SHA512: the
* stripped-software wc_Sha512Free()/wc_Sha384Free() must route through the
* crypto callback. */
int test_wc_sha512_cryptocb_free(void)
{
EXPECT_DECLS;
#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_FREE) && \
defined(WOLF_CRYPTO_CB_ONLY_SHA512) && defined(WOLFSSL_SHA512)
Sha512DevCbCtx cbCtx;
wc_Sha512 sha512;
#ifdef WOLFSSL_SHA384
wc_Sha384 sha384;
#endif

XMEMSET(&cbCtx, 0, sizeof(cbCtx));

ExpectIntEQ(wc_CryptoCb_RegisterDevice(TEST_CRYPTOCB_SHA512_DEVID,
sha512_dev_cb, &cbCtx), 0);

XMEMSET(&sha512, 0, sizeof(sha512));
ExpectIntEQ(wc_InitSha512_ex(&sha512, HEAP_HINT,
TEST_CRYPTOCB_SHA512_DEVID), 0);
wc_Sha512Free(&sha512);
/* the free must reach the device callback */
ExpectIntEQ(cbCtx.freeSeen, 1);

#ifdef WOLFSSL_SHA384
cbCtx.freeSeen = 0;
XMEMSET(&sha384, 0, sizeof(sha384));
ExpectIntEQ(wc_InitSha384_ex(&sha384, HEAP_HINT,
TEST_CRYPTOCB_SHA512_DEVID), 0);
wc_Sha384Free(&sha384);
ExpectIntEQ(cbCtx.freeSeen, 1);
#endif

wc_CryptoCb_UnRegisterDevice(TEST_CRYPTOCB_SHA512_DEVID);
#endif
return EXPECT_RESULT();
}

8 changes: 7 additions & 1 deletion tests/api/test_sha512.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ int test_wc_Sha384_other(void);
int test_wc_Sha384Copy(void);
int test_wc_Sha384GetHash(void);
int test_wc_Sha384_Flags(void);
int test_wc_sha512_cryptocb_fallback(void);
int test_wc_sha512_variants_default_devid(void);
int test_wc_sha512_cryptocb_free(void);

#define TEST_SHA512_DECLS \
TEST_DECL_GROUP("sha512", test_wc_InitSha512), \
Expand All @@ -77,7 +80,10 @@ int test_wc_Sha384_Flags(void);
TEST_DECL_GROUP("sha512", test_wc_Sha512Copy), \
TEST_DECL_GROUP("sha512", test_wc_Sha512GetHash), \
TEST_DECL_GROUP("sha512", test_wc_Sha512Transform), \
TEST_DECL_GROUP("sha512", test_wc_Sha512_Flags)
TEST_DECL_GROUP("sha512", test_wc_Sha512_Flags), \
TEST_DECL_GROUP("sha512", test_wc_sha512_cryptocb_fallback), \
TEST_DECL_GROUP("sha512", test_wc_sha512_variants_default_devid), \
TEST_DECL_GROUP("sha512", test_wc_sha512_cryptocb_free)

#define TEST_SHA512_224_DECLS \
TEST_DECL_GROUP("sha512_224", test_wc_InitSha512_224), \
Expand Down
Loading
Loading