mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-10-24 04:09:07 +03:00
tests: drive the sha256 and sha512 length-guard error halves
This commit is contained in:
@@ -47,6 +47,28 @@
|
||||
* NULL: every block then flows through the per-block route that evaluates the
|
||||
* decision, and the C transform is safe to run whatever intel_flags claims
|
||||
* (so forcing e.g. SHA-NI never executes SHA-NI asm).
|
||||
*
|
||||
* Second supplement: Sha256Update()'s save-remainder guard (line ~2034)
|
||||
*
|
||||
* if (ret == 0 && len > 0)
|
||||
*
|
||||
* idx0 ("ret == 0") FALSE half. Nothing on the path to that guard can set ret
|
||||
* except the block transform: the two earlier error exits (buffLen >= block
|
||||
* size -> BUFFER_E, and the argument checks in wc_Sha256Update) return before
|
||||
* it. In the plain C variants XTRANSFORM expands straight to the static
|
||||
* Transform_Sha256(), which has no failing return, so the FALSE half is only
|
||||
* reachable where the transform is dispatched through the file-static
|
||||
* Transform_Sha256_p -- i.e. exactly this USE_INTEL_SPEEDUP build. Retargeting
|
||||
* that pointer at a stub returning BAD_FUNC_ARG (and NULLing
|
||||
* Transform_Sha256_Len_p so the multi-block loop, not XTRANSFORM_LEN, runs)
|
||||
* makes the first loop iteration break with ret != 0; the guard is then
|
||||
* evaluated with idx0 FALSE and idx1 short-circuited (never read).
|
||||
* Vectors, all in this one binary:
|
||||
* stub + 3 whole blocks -> (F, -) [the residual]
|
||||
* C transform + 1 block + 5 -> (T, T)
|
||||
* C transform + exactly 1 block -> (T, F)
|
||||
* No digest is ever taken from the faulted context: it is freed and
|
||||
* re-initialised before the baseline vectors run.
|
||||
*/
|
||||
|
||||
#include <wolfcrypt/src/sha256.c>
|
||||
@@ -118,6 +140,110 @@ static void wb_intel_dispatch(void)
|
||||
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* Sha256Update(): "ret == 0" half of the save-remainder guard (~line 2034).
|
||||
* ----------------------------------------------------------------------- */
|
||||
#if !defined(NO_SHA256) && defined(WOLFSSL_X86_64_BUILD) && \
|
||||
defined(USE_INTEL_SPEEDUP) && !defined(WC_C_DYNAMIC_FALLBACK) && \
|
||||
!defined(WC_NO_INTERNAL_FUNCTION_POINTERS) && \
|
||||
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))
|
||||
|
||||
static int wb_transform_fails(wc_Sha256* sha256, const byte* data)
|
||||
{
|
||||
(void)sha256;
|
||||
(void)data;
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
static void wb_update_transform_err(void)
|
||||
{
|
||||
/* Three whole blocks: the loop breaks on the first transform (len is
|
||||
* decremented before it), leaving len == 2 * block size at the guard --
|
||||
* immaterial, since idx1 is short-circuited when idx0 is FALSE. */
|
||||
byte buf[3 * WC_SHA256_BLOCK_SIZE];
|
||||
byte hash[WC_SHA256_DIGEST_SIZE];
|
||||
int (*saved_p)(wc_Sha256*, const byte*) = Transform_Sha256_p;
|
||||
int (*saved_len_p)(wc_Sha256*, const byte*, word32) =
|
||||
Transform_Sha256_Len_p;
|
||||
cpuid_flags_t saved_flags = intel_flags;
|
||||
wc_Sha256 sha;
|
||||
int ret;
|
||||
|
||||
XMEMSET(buf, 0x5a, sizeof(buf));
|
||||
|
||||
/* idx0 FALSE: the transform fails on the first block. */
|
||||
if (wc_InitSha256_ex(&sha, NULL, INVALID_DEVID) != 0) {
|
||||
WB_NOTE("wc_InitSha256_ex failed (transform-error case skipped)");
|
||||
wb_fail = 1;
|
||||
}
|
||||
else {
|
||||
/* Pin the per-block route, then make that block transform fail.
|
||||
* intel_flags is zeroed so the C route the baselines use below is
|
||||
* byte-reversal-consistent; it is restored at the end. */
|
||||
Transform_Sha256_Len_p = NULL;
|
||||
Transform_Sha256_p = wb_transform_fails;
|
||||
intel_flags = 0;
|
||||
|
||||
ret = wc_Sha256Update(&sha, buf, (word32)sizeof(buf));
|
||||
if (ret == 0) {
|
||||
WB_NOTE("faulted wc_Sha256Update unexpectedly succeeded");
|
||||
wb_fail = 1;
|
||||
}
|
||||
/* The context is poisoned; no digest is taken from it. */
|
||||
Transform_Sha256_p = Transform_Sha256;
|
||||
wc_Sha256Free(&sha);
|
||||
}
|
||||
|
||||
/* idx0 TRUE, idx1 TRUE: one whole block plus a 5-byte remainder. */
|
||||
if (wc_InitSha256_ex(&sha, NULL, INVALID_DEVID) != 0) {
|
||||
WB_NOTE("wc_InitSha256_ex failed (remainder baseline skipped)");
|
||||
wb_fail = 1;
|
||||
}
|
||||
else {
|
||||
Transform_Sha256_Len_p = NULL;
|
||||
Transform_Sha256_p = Transform_Sha256;
|
||||
ret = wc_Sha256Update(&sha, buf, WC_SHA256_BLOCK_SIZE + 5);
|
||||
if (ret != 0) {
|
||||
WB_NOTE("wc_Sha256Update remainder baseline failed");
|
||||
wb_fail = 1;
|
||||
}
|
||||
(void)wc_Sha256Final(&sha, hash);
|
||||
wc_Sha256Free(&sha);
|
||||
}
|
||||
|
||||
/* idx0 TRUE, idx1 FALSE: an exact whole number of blocks, no remainder. */
|
||||
if (wc_InitSha256_ex(&sha, NULL, INVALID_DEVID) != 0) {
|
||||
WB_NOTE("wc_InitSha256_ex failed (exact-block baseline skipped)");
|
||||
wb_fail = 1;
|
||||
}
|
||||
else {
|
||||
Transform_Sha256_Len_p = NULL;
|
||||
Transform_Sha256_p = Transform_Sha256;
|
||||
ret = wc_Sha256Update(&sha, buf, WC_SHA256_BLOCK_SIZE);
|
||||
if (ret != 0) {
|
||||
WB_NOTE("wc_Sha256Update exact-block baseline failed");
|
||||
wb_fail = 1;
|
||||
}
|
||||
(void)wc_Sha256Final(&sha, hash);
|
||||
wc_Sha256Free(&sha);
|
||||
}
|
||||
|
||||
Transform_Sha256_p = saved_p;
|
||||
Transform_Sha256_Len_p = saved_len_p;
|
||||
intel_flags = saved_flags;
|
||||
WB_NOTE("Sha256Update save-remainder ret==0 pair exercised");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void wb_update_transform_err(void)
|
||||
{
|
||||
WB_NOTE("no retargetable sha256 transform pointer in this variant; "
|
||||
"save-remainder ret==0 skipped");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("sha256.c white-box MC/DC supplement\n");
|
||||
@@ -126,6 +252,7 @@ int main(void)
|
||||
return 0;
|
||||
#else
|
||||
wb_intel_dispatch();
|
||||
wb_update_transform_err();
|
||||
printf("done (%s)\n", wb_fail ? "with skips" : "ok");
|
||||
/* Setup failures are surfaced as skips, not test failures: the campaign
|
||||
* treats a nonzero exit as a failed variant and discards its coverage. */
|
||||
|
||||
@@ -41,6 +41,28 @@
|
||||
* to the portable C transform and Transform_Sha512_Len_p to NULL (routing
|
||||
* every block through the per-block path that reads intel_flags) -- which is
|
||||
* also crash-safe: the C transform runs whatever intel_flags claims.
|
||||
*
|
||||
* Second supplement: Sha512Update()'s save-remainder guard (line ~2185)
|
||||
*
|
||||
* if (ret == 0 && len > 0)
|
||||
*
|
||||
* idx0 ("ret == 0") FALSE half. ret is 0 everywhere on the path to that guard
|
||||
* except where the block transform writes it: the two earlier error exits
|
||||
* (buffLen >= block size -> BUFFER_E, and wc_Sha512Update's argument checks)
|
||||
* return before the guard is reached. In the plain C / ARMASM variants
|
||||
* Transform_Sha512() resolves to a transform with no failing return, so the
|
||||
* FALSE half is only reachable where the transform is dispatched through the
|
||||
* file-static Transform_Sha512_p -- i.e. exactly this USE_INTEL_SPEEDUP build.
|
||||
* Retargeting that pointer at a stub returning BAD_FUNC_ARG (and NULLing
|
||||
* Transform_Sha512_Len_p so the per-block loop, not the Len transform, runs)
|
||||
* makes the first loop iteration break with ret != 0; the guard is then
|
||||
* evaluated with idx0 FALSE and idx1 short-circuited (never read).
|
||||
* Vectors, all in this one binary:
|
||||
* stub + 3 whole blocks -> (F, -) [the residual]
|
||||
* C transform + 1 block + 5 -> (T, T)
|
||||
* C transform + exactly 1 block -> (T, F)
|
||||
* No digest is taken from the faulted context: it is freed and re-initialised
|
||||
* before the baseline vectors run.
|
||||
*/
|
||||
|
||||
#include <wolfcrypt/src/sha512.c>
|
||||
@@ -128,6 +150,109 @@ static void wb_intel_dispatch(void)
|
||||
|
||||
#endif
|
||||
|
||||
/* --------------------------------------------------------------------------
|
||||
* Sha512Update(): "ret == 0" half of the save-remainder guard (~line 2185).
|
||||
* ----------------------------------------------------------------------- */
|
||||
#if !defined(NO_SHA512) && defined(WOLFSSL_SHA512) && \
|
||||
defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
|
||||
!defined(WC_C_DYNAMIC_FALLBACK) && \
|
||||
!defined(WC_NO_INTERNAL_FUNCTION_POINTERS) && \
|
||||
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))
|
||||
|
||||
static int wb_transform_fails(wc_Sha512* sha512)
|
||||
{
|
||||
(void)sha512;
|
||||
return BAD_FUNC_ARG;
|
||||
}
|
||||
|
||||
static void wb_update_transform_err(void)
|
||||
{
|
||||
/* Three whole blocks: the loop breaks on the first transform (len is
|
||||
* decremented before it), leaving len == 2 * block size at the guard --
|
||||
* immaterial, since idx1 is short-circuited when idx0 is FALSE. */
|
||||
byte buf[3 * WC_SHA512_BLOCK_SIZE];
|
||||
byte hash[WC_SHA512_DIGEST_SIZE];
|
||||
int (*saved_p)(wc_Sha512*) = Transform_Sha512_p;
|
||||
int (*saved_len_p)(wc_Sha512*, word32) = Transform_Sha512_Len_p;
|
||||
cpuid_flags_t saved_flags = intel_flags;
|
||||
wc_Sha512 sha;
|
||||
int ret;
|
||||
|
||||
XMEMSET(buf, 0x5a, sizeof(buf));
|
||||
|
||||
/* idx0 FALSE: the transform fails on the first block. */
|
||||
if (wc_InitSha512_ex(&sha, NULL, INVALID_DEVID) != 0) {
|
||||
WB_NOTE("wc_InitSha512_ex failed (transform-error case skipped)");
|
||||
wb_fail = 1;
|
||||
}
|
||||
else {
|
||||
/* Pin the per-block route, then make that block transform fail.
|
||||
* intel_flags is zeroed so the C transform the baselines use sees a
|
||||
* byte-reversed block; it is restored at the end. */
|
||||
Transform_Sha512_Len_p = NULL;
|
||||
Transform_Sha512_p = wb_transform_fails;
|
||||
intel_flags = 0;
|
||||
|
||||
ret = wc_Sha512Update(&sha, buf, (word32)sizeof(buf));
|
||||
if (ret == 0) {
|
||||
WB_NOTE("faulted wc_Sha512Update unexpectedly succeeded");
|
||||
wb_fail = 1;
|
||||
}
|
||||
/* The context is poisoned; no digest is taken from it. */
|
||||
Transform_Sha512_p = _Transform_Sha512;
|
||||
wc_Sha512Free(&sha);
|
||||
}
|
||||
|
||||
/* idx0 TRUE, idx1 TRUE: one whole block plus a 5-byte remainder. */
|
||||
if (wc_InitSha512_ex(&sha, NULL, INVALID_DEVID) != 0) {
|
||||
WB_NOTE("wc_InitSha512_ex failed (remainder baseline skipped)");
|
||||
wb_fail = 1;
|
||||
}
|
||||
else {
|
||||
Transform_Sha512_Len_p = NULL;
|
||||
Transform_Sha512_p = _Transform_Sha512;
|
||||
ret = wc_Sha512Update(&sha, buf, WC_SHA512_BLOCK_SIZE + 5);
|
||||
if (ret != 0) {
|
||||
WB_NOTE("wc_Sha512Update remainder baseline failed");
|
||||
wb_fail = 1;
|
||||
}
|
||||
(void)wc_Sha512Final(&sha, hash);
|
||||
wc_Sha512Free(&sha);
|
||||
}
|
||||
|
||||
/* idx0 TRUE, idx1 FALSE: an exact whole number of blocks, no remainder. */
|
||||
if (wc_InitSha512_ex(&sha, NULL, INVALID_DEVID) != 0) {
|
||||
WB_NOTE("wc_InitSha512_ex failed (exact-block baseline skipped)");
|
||||
wb_fail = 1;
|
||||
}
|
||||
else {
|
||||
Transform_Sha512_Len_p = NULL;
|
||||
Transform_Sha512_p = _Transform_Sha512;
|
||||
ret = wc_Sha512Update(&sha, buf, WC_SHA512_BLOCK_SIZE);
|
||||
if (ret != 0) {
|
||||
WB_NOTE("wc_Sha512Update exact-block baseline failed");
|
||||
wb_fail = 1;
|
||||
}
|
||||
(void)wc_Sha512Final(&sha, hash);
|
||||
wc_Sha512Free(&sha);
|
||||
}
|
||||
|
||||
Transform_Sha512_p = saved_p;
|
||||
Transform_Sha512_Len_p = saved_len_p;
|
||||
intel_flags = saved_flags;
|
||||
WB_NOTE("Sha512Update save-remainder ret==0 pair exercised");
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static void wb_update_transform_err(void)
|
||||
{
|
||||
WB_NOTE("no retargetable sha512 transform pointer in this variant; "
|
||||
"save-remainder ret==0 skipped");
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
printf("sha512.c white-box MC/DC supplement\n");
|
||||
@@ -136,6 +261,7 @@ int main(void)
|
||||
return 0;
|
||||
#else
|
||||
wb_intel_dispatch();
|
||||
wb_update_transform_err();
|
||||
printf("done (%s)\n", wb_fail ? "with skips" : "ok");
|
||||
return 0;
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user