Files
wolfssl/tests/api/test_digest.h
Sean Parkinson 6016cc0c97 Digest testing: improve
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.
2025-02-25 19:07:20 +10:00

693 lines
49 KiB
C

/* test_digest.h
*
* 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
*/
#define PRINT_DATA(name, data, len) \
do { \
int ii; \
fprintf(stderr, "%s\n", name); \
for (ii = 0; ii < (int)(len); ii++) { \
if ((ii % 8) == 0) \
fprintf(stderr, " \""); \
fprintf(stderr, "\\x%02x", (data)[ii]); \
if ((ii % 8) == 7) \
fprintf(stderr, "\"\n"); \
} \
if ((ii % 8) != 0) \
fprintf(stderr, "\""); \
fprintf(stderr, "\n"); \
} while (0)
#define DIGEST_INIT_TEST(type, name) \
do { \
type dgst; \
\
/* Test bad arg. */ \
ExpectIntEQ(wc_Init##name(NULL, HEAP_HINT, INVALID_DEVID), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
\
/* Test good arg. */ \
ExpectIntEQ(wc_Init##name(&dgst, HEAP_HINT, INVALID_DEVID), 0); \
wc_##name##_Free(&dgst); \
\
wc_##name##_Free(NULL); \
} while (0)
#define DIGEST_INIT_AND_INIT_EX_TEST(type, name) \
type dgst; \
\
/* Test bad arg. */ \
ExpectIntEQ(wc_Init##name(NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_Init##name##_ex(NULL, HEAP_HINT, INVALID_DEVID), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
\
/* Test good arg. */ \
ExpectIntEQ(wc_Init##name(&dgst), 0); \
wc_##name##Free(&dgst); \
\
ExpectIntEQ(wc_Init##name##_ex(&dgst, HEAP_HINT, INVALID_DEVID), 0); \
wc_##name##Free(&dgst); \
\
wc_##name##Free(NULL)
#define DIGEST_UPDATE_TEST(type, name) \
type dgst; \
\
ExpectIntEQ(wc_Init##name(&dgst), 0); \
\
/* Pass in bad values. */ \
ExpectIntEQ(wc_##name##Update(NULL, NULL, 1), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##Update(&dgst, NULL, 1), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##Update(NULL, NULL, 0), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
\
ExpectIntEQ(wc_##name##Update(&dgst, NULL, 0), 0); \
ExpectIntEQ(wc_##name##Update(&dgst, (byte*)"a", 1), 0); \
\
wc_##name##Free(&dgst)
#define DIGEST_ALT_UPDATE_TEST(type, name) \
do { \
type dgst; \
\
ExpectIntEQ(wc_Init##name(&dgst, HEAP_HINT, INVALID_DEVID), 0); \
\
/* Pass in bad values. */ \
ExpectIntEQ(wc_##name##_Update(NULL, NULL, 1), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##_Update(&dgst, NULL, 1), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##_Update(NULL, NULL, 0), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
\
ExpectIntEQ(wc_##name##_Update(&dgst, NULL, 0), 0); \
ExpectIntEQ(wc_##name##_Update(&dgst, (byte*)"a", 1), 0); \
\
wc_##name##_Free(&dgst); \
} while (0)
#define DIGEST_FINAL_TEST(type, name, upper) \
type dgst; \
byte hash[WC_##upper##_DIGEST_SIZE]; \
\
/* Initialize */ \
ExpectIntEQ(wc_Init##name(&dgst), 0); \
\
/* Test bad args. */ \
ExpectIntEQ(wc_##name##Final(NULL, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##Final(&dgst, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##Final(NULL, hash), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
\
/* Test good args. */ \
ExpectIntEQ(wc_##name##Final(&dgst, hash), 0); \
\
wc_##name##Free(&dgst)
#define DIGEST_ALT_FINAL_TEST(type, name, upper) \
do { \
type dgst; \
byte hash[WC_##upper##_DIGEST_SIZE]; \
\
/* Initialize */ \
ExpectIntEQ(wc_Init##name(&dgst, HEAP_HINT, INVALID_DEVID), 0); \
\
/* Test bad args. */ \
ExpectIntEQ(wc_##name##_Final(NULL, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##_Final(&dgst, NULL), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##_Final(NULL, hash), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
\
/* Test good args. */ \
ExpectIntEQ(wc_##name##_Final(&dgst, hash), 0); \
\
wc_##name##_Free(&dgst); \
} while (0)
#define DIGEST_COUNT_FINAL_TEST(type, name, upper) \
do { \
type dgst; \
byte hash[WC_##upper##_COUNT * 8]; \
\
/* Initialize */ \
ExpectIntEQ(wc_Init##name(&dgst, HEAP_HINT, INVALID_DEVID), 0); \
\
/* Test bad args. */ \
ExpectIntEQ(wc_##name##_Final(NULL, NULL, WC_##upper##_COUNT * 8), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##_Final(&dgst, NULL, WC_##upper##_COUNT * 8), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##_Final(NULL, hash, WC_##upper##_COUNT * 8), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
\
/* Test good args. */ \
ExpectIntEQ(wc_##name##_Final(&dgst, hash, WC_##upper##_COUNT * 8), 0); \
\
wc_##name##_Free(&dgst); \
} while (0)
#define DIGEST_FINAL_RAW_TEST(type, name, upper, hashStr) \
type dgst; \
byte hash[WC_##upper##_DIGEST_SIZE]; \
const char* expHash = hashStr; \
\
/* Initialize */ \
ExpectIntEQ(wc_Init##name(&dgst), 0); \
\
/* Test bad args. */ \
ExpectIntEQ(wc_##name##FinalRaw(NULL, NULL), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##FinalRaw(&dgst, NULL), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##FinalRaw(NULL, hash), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
\
/* Test good args. */ \
ExpectIntEQ(wc_##name##FinalRaw(&dgst, hash), 0); \
ExpectBufEQ(hash, expHash, WC_##upper##_DIGEST_SIZE); \
\
wc_##name##Free(&dgst)
#define DIGEST_KATS_TEST_VARS(type, upper) \
type dgst; \
testVector dgst_kat[upper##_KAT_CNT]; \
byte hash[WC_##upper##_DIGEST_SIZE]; \
int i = 0
#define DIGEST_COUNT_KATS_TEST_VARS(type, upper, count) \
type dgst; \
testVector dgst_kat[upper##_KAT_CNT]; \
byte hash[WC_##count##_COUNT * 8]; \
int i = 0
#define DIGEST_KATS_ADD(in, len, out) \
dgst_kat[i].input = in; \
dgst_kat[i].inLen = len; \
dgst_kat[i].output = out; \
dgst_kat[i].outLen = 0; \
i++
#define DIGEST_KATS_TEST(name, upper) \
(void)i; \
\
/* Initialize */ \
ExpectIntEQ(wc_Init##name(&dgst), 0); \
\
for (i = 0; i < upper##_KAT_CNT; i++) { \
/* Do KAT. */ \
ExpectIntEQ(wc_##name##Update(&dgst, (byte*)dgst_kat[i].input, \
(word32)dgst_kat[i].inLen), 0); \
ExpectIntEQ(wc_##name##Final(&dgst, hash), 0); \
ExpectBufEQ(hash, (byte*)dgst_kat[i].output, \
WC_##upper##_DIGEST_SIZE); \
} \
\
wc_##name##Free(&dgst)
#define DIGEST_COUNT_KATS_TEST(name, upper, count) \
(void)i; \
\
/* Initialize */ \
ExpectIntEQ(wc_Init##name(&dgst, HEAP_HINT, INVALID_DEVID), 0); \
\
for (i = 0; i < upper##_KAT_CNT; i++) { \
/* Do KAT. */ \
ExpectIntEQ(wc_##name##_Update(&dgst, (byte*)dgst_kat[i].input, \
(word32)dgst_kat[i].inLen), 0); \
ExpectIntEQ(wc_##name##_Final(&dgst, hash, WC_##count##_COUNT * 8), \
0); \
ExpectBufEQ(hash, (byte*)dgst_kat[i].output, \
WC_##count##_COUNT * 8); \
} \
\
wc_##name##_Free(&dgst)
#define DIGEST_OTHER_TEST(type, name, upper, hashStr) \
type dgst; \
byte hash[WC_##upper##_DIGEST_SIZE + 1]; \
byte data[WC_##upper##_DIGEST_SIZE * 8 + 1]; \
int dataLen = WC_##upper##_DIGEST_SIZE * 8; \
const char* expHash = hashStr; \
int i; \
int j; \
\
XMEMSET(data, 0xa5, sizeof(data)); \
\
/* Initialize */ \
ExpectIntEQ(wc_Init##name(&dgst), 0); \
\
/* Unaligned input and output buffer. */ \
ExpectIntEQ(wc_##name##Update(&dgst, data + 1, dataLen), 0); \
ExpectIntEQ(wc_##name##Final(&dgst, hash + 1), 0); \
ExpectBufEQ(hash + 1, (byte*)expHash, WC_##upper##_DIGEST_SIZE); \
\
/* Test that empty updates work. */ \
ExpectIntEQ(wc_##name##Update(&dgst, NULL, 0), 0); \
ExpectIntEQ(wc_##name##Update(&dgst, (byte*)"", 0), 0); \
ExpectIntEQ(wc_##name##Update(&dgst, data, dataLen), 0); \
ExpectIntEQ(wc_##name##Final(&dgst, hash), 0); \
ExpectBufEQ(hash, (byte*)expHash, WC_##upper##_DIGEST_SIZE); \
\
/* Ensure chunking works. */ \
for (i = 1; i < dataLen; i++) { \
for (j = 0; j < dataLen; j += i) { \
int len = dataLen - j; \
if (i < len) \
len = i; \
ExpectIntEQ(wc_##name##Update(&dgst, data + j, len), 0); \
} \
ExpectIntEQ(wc_##name##Final(&dgst, hash), 0); \
ExpectBufEQ(hash, (byte*)expHash, WC_##upper##_DIGEST_SIZE); \
} \
\
wc_##name##Free(&dgst)
#define DIGEST_ALT_OTHER_TEST(type, name, upper, hashStr) \
do { \
type dgst; \
byte hash[WC_##upper##_DIGEST_SIZE + 1]; \
byte data[WC_##upper##_DIGEST_SIZE * 8 + 1]; \
int dataLen = WC_##upper##_DIGEST_SIZE * 8; \
const char* expHash = hashStr; \
int i; \
int j; \
\
XMEMSET(data, 0xa5, sizeof(data)); \
\
/* Initialize */ \
ExpectIntEQ(wc_Init##name(&dgst, HEAP_HINT, INVALID_DEVID), 0); \
\
/* Unaligned input and output buffer. */ \
ExpectIntEQ(wc_##name##_Update(&dgst, data + 1, dataLen), 0); \
ExpectIntEQ(wc_##name##_Final(&dgst, hash + 1), 0); \
ExpectBufEQ(hash + 1, (byte*)expHash, WC_##upper##_DIGEST_SIZE); \
\
/* Test that empty updates work. */ \
ExpectIntEQ(wc_##name##_Update(&dgst, NULL, 0), 0); \
ExpectIntEQ(wc_##name##_Update(&dgst, (byte*)"", 0), 0); \
ExpectIntEQ(wc_##name##_Update(&dgst, data, dataLen), 0); \
ExpectIntEQ(wc_##name##_Final(&dgst, hash), 0); \
ExpectBufEQ(hash, (byte*)expHash, WC_##upper##_DIGEST_SIZE); \
\
/* Ensure chunking works. */ \
for (i = 1; i < dataLen; i++) { \
for (j = 0; j < dataLen; j += i) { \
int len = dataLen - j; \
if (i < len) \
len = i; \
ExpectIntEQ(wc_##name##_Update(&dgst, data + j, len), 0); \
} \
ExpectIntEQ(wc_##name##_Final(&dgst, hash), 0); \
ExpectBufEQ(hash, (byte*)expHash, WC_##upper##_DIGEST_SIZE); \
} \
\
wc_##name##_Free(&dgst); \
} while (0)
#define DIGEST_COUNT_OTHER_TEST(type, name, upper, hashStr) \
do { \
type dgst; \
byte hash[WC_##upper##_COUNT * 8 + 1]; \
byte data[WC_##upper##_COUNT * 8 * 8 + 1]; \
int dataLen = WC_##upper##_COUNT * 8 * 8; \
const char* expHash = hashStr; \
int i; \
int j; \
\
XMEMSET(data, 0xa5, sizeof(data)); \
\
/* Initialize */ \
ExpectIntEQ(wc_Init##name(&dgst, HEAP_HINT, INVALID_DEVID), 0); \
\
/* Unaligned input and output buffer. */ \
ExpectIntEQ(wc_##name##_Update(&dgst, data + 1, dataLen), 0); \
ExpectIntEQ(wc_##name##_Final(&dgst, hash + 1, WC_##upper##_COUNT * 8), \
0); \
ExpectBufEQ(hash + 1, (byte*)expHash, WC_##upper##_COUNT * 8); \
\
/* Test that empty updates work. */ \
ExpectIntEQ(wc_##name##_Update(&dgst, NULL, 0), 0); \
ExpectIntEQ(wc_##name##_Update(&dgst, (byte*)"", 0), 0); \
ExpectIntEQ(wc_##name##_Update(&dgst, data, dataLen), 0); \
ExpectIntEQ(wc_##name##_Final(&dgst, hash, WC_##upper##_COUNT * 8), 0); \
ExpectBufEQ(hash, (byte*)expHash, WC_##upper##_COUNT * 8); \
\
/* Ensure chunking works. */ \
for (i = 1; i < dataLen; i++) { \
for (j = 0; j < dataLen; j += i) { \
int len = dataLen - j; \
if (i < len) \
len = i; \
ExpectIntEQ(wc_##name##_Update(&dgst, data + j, len), 0); \
} \
ExpectIntEQ(wc_##name##_Final(&dgst, hash, WC_##upper##_COUNT * 8), \
0); \
ExpectBufEQ(hash, (byte*)expHash, WC_##upper##_COUNT * 8); \
} \
\
wc_##name##_Free(&dgst); \
} while (0)
#define DIGEST_COPY_TEST(type, name, upper, emptyHashStr, abcHashStr) \
type src; \
type dst; \
byte hashSrc[WC_##upper##_DIGEST_SIZE]; \
byte hashDst[WC_##upper##_DIGEST_SIZE]; \
const char* emptyHash = emptyHashStr; \
const char* abcHash = abcHashStr; \
byte data[WC_##upper##_BLOCK_SIZE]; \
\
XMEMSET(data, 0xa5, sizeof(data)); \
\
ExpectIntEQ(wc_Init##name(&src), 0); \
XMEMSET(&dst, 0, sizeof(dst)); \
\
/* Tests bad params. */ \
ExpectIntEQ(wc_##name##Copy(NULL, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##Copy(&src, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##Copy(NULL, &dst), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
\
/* Test copy works. */ \
ExpectIntEQ(wc_##name##Copy(&src, &dst), 0); \
ExpectIntEQ(wc_##name##Final(&src, hashSrc), 0); \
ExpectIntEQ(wc_##name##Final(&dst, hashDst), 0); \
ExpectBufEQ(hashSrc, emptyHash, WC_##upper##_DIGEST_SIZE); \
ExpectBufEQ(hashDst, emptyHash, WC_##upper##_DIGEST_SIZE); \
wc_##name##Free(&dst); \
\
/* Test buffered data is copied. */ \
ExpectIntEQ(wc_##name##Update(&src, (byte*)"abc", 3), 0); \
ExpectIntEQ(wc_##name##Copy(&src, &dst), 0); \
ExpectIntEQ(wc_##name##Final(&src, hashSrc), 0); \
ExpectIntEQ(wc_##name##Final(&dst, hashDst), 0); \
ExpectBufEQ(hashSrc, abcHash, WC_##upper##_DIGEST_SIZE); \
ExpectBufEQ(hashDst, abcHash, WC_##upper##_DIGEST_SIZE); \
wc_##name##Free(&dst); \
\
/* Test count of length is copied. */ \
ExpectIntEQ(wc_##name##Update(&src, data, sizeof(data)), 0); \
ExpectIntEQ(wc_##name##Copy(&src, &dst), 0); \
ExpectIntEQ(wc_##name##Final(&src, hashSrc), 0); \
ExpectIntEQ(wc_##name##Final(&dst, hashDst), 0); \
ExpectBufEQ(hashSrc, hashDst, WC_##upper##_DIGEST_SIZE); \
wc_##name##Free(&dst); \
\
wc_##name##Free(&src)
#define DIGEST_ALT_COPY_TEST(type, name, upper, emptyHashStr, abcHashStr) \
do { \
type src; \
type dst; \
byte hashSrc[WC_##upper##_DIGEST_SIZE]; \
byte hashDst[WC_##upper##_DIGEST_SIZE]; \
const char* emptyHash = emptyHashStr; \
const char* abcHash = abcHashStr; \
byte data[WC_##upper##_BLOCK_SIZE]; \
\
XMEMSET(data, 0xa5, sizeof(data)); \
\
ExpectIntEQ(wc_Init##name(&src, HEAP_HINT, INVALID_DEVID), 0); \
XMEMSET(&dst, 0, sizeof(dst)); \
\
ExpectIntEQ(wc_##name##_Copy(NULL, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##_Copy(&src, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##_Copy(NULL, &dst), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
\
/* Test copy works. */ \
ExpectIntEQ(wc_##name##_Copy(&src, &dst), 0); \
ExpectIntEQ(wc_##name##_Final(&src, hashSrc), 0); \
ExpectIntEQ(wc_##name##_Final(&dst, hashDst), 0); \
ExpectBufEQ(hashSrc, emptyHash, WC_##upper##_DIGEST_SIZE); \
ExpectBufEQ(hashDst, emptyHash, WC_##upper##_DIGEST_SIZE); \
wc_##name##_Free(&dst); \
\
/* Test buffered data is copied. */ \
ExpectIntEQ(wc_##name##_Update(&src, (byte*)"abc", 3), 0); \
ExpectIntEQ(wc_##name##_Copy(&src, &dst), 0); \
ExpectIntEQ(wc_##name##_Final(&src, hashSrc), 0); \
ExpectIntEQ(wc_##name##_Final(&dst, hashDst), 0); \
ExpectBufEQ(hashSrc, abcHash, WC_##upper##_DIGEST_SIZE); \
ExpectBufEQ(hashDst, abcHash, WC_##upper##_DIGEST_SIZE); \
wc_##name##_Free(&dst); \
\
/* Test count of length is copied. */ \
ExpectIntEQ(wc_##name##_Update(&src, data, sizeof(data)), 0); \
ExpectIntEQ(wc_##name##_Copy(&src, &dst), 0); \
ExpectIntEQ(wc_##name##_Final(&src, hashSrc), 0); \
ExpectIntEQ(wc_##name##_Final(&dst, hashDst), 0); \
ExpectBufEQ(hashSrc, hashDst, WC_##upper##_DIGEST_SIZE); \
wc_##name##_Free(&dst); \
\
wc_##name##_Free(&src); \
} while (0)
#define DIGEST_COUNT_COPY_TEST(type, name, upper, emptyHashStr, abcHashStr) \
do { \
type src; \
type dst; \
byte hashSrc[WC_##upper##_COUNT * 8]; \
byte hashDst[WC_##upper##_COUNT * 8]; \
const char* emptyHash = emptyHashStr; \
const char* abcHash = abcHashStr; \
byte data[WC_##upper##_BLOCK_SIZE]; \
\
XMEMSET(data, 0xa5, sizeof(data)); \
\
ExpectIntEQ(wc_Init##name(&src, HEAP_HINT, INVALID_DEVID), 0); \
XMEMSET(&dst, 0, sizeof(dst)); \
\
ExpectIntEQ(wc_##name##_Copy(NULL, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##_Copy(&src, NULL), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##_Copy(NULL, &dst), WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
\
/* Test copy works. */ \
ExpectIntEQ(wc_##name##_Copy(&src, &dst), 0); \
ExpectIntEQ(wc_##name##_Final(&src, hashSrc, WC_##upper##_COUNT * 8), 0); \
ExpectIntEQ(wc_##name##_Final(&dst, hashDst, WC_##upper##_COUNT * 8), 0); \
ExpectBufEQ(hashSrc, emptyHash, WC_##upper##_COUNT * 8); \
ExpectBufEQ(hashDst, emptyHash, WC_##upper##_COUNT * 8); \
wc_##name##_Free(&src); \
\
/* Test buffered data is copied. */ \
ExpectIntEQ(wc_##name##_Update(&src, (byte*)"abc", 3), 0); \
ExpectIntEQ(wc_##name##_Copy(&src, &dst), 0); \
ExpectIntEQ(wc_##name##_Final(&src, hashSrc, WC_##upper##_COUNT * 8), 0); \
ExpectIntEQ(wc_##name##_Final(&dst, hashDst, WC_##upper##_COUNT * 8), 0); \
ExpectBufEQ(hashSrc, abcHash, WC_##upper##_COUNT * 8); \
ExpectBufEQ(hashDst, abcHash, WC_##upper##_COUNT * 8); \
wc_##name##_Free(&src); \
\
/* Test count of length is copied. */ \
ExpectIntEQ(wc_##name##_Update(&src, data, sizeof(data)), 0); \
ExpectIntEQ(wc_##name##_Copy(&src, &dst), 0); \
ExpectIntEQ(wc_##name##_Final(&src, hashSrc, WC_##upper##_COUNT * 8), 0); \
ExpectIntEQ(wc_##name##_Final(&dst, hashDst, WC_##upper##_COUNT * 8), 0); \
ExpectBufEQ(hashSrc, hashDst, WC_##upper##_COUNT * 8); \
wc_##name##_Free(&dst); \
\
wc_##name##_Free(&src); \
} while (0)
#define DIGEST_GET_HASH_TEST(type, name, upper, emptyHashStr, abcHashStr) \
type dgst; \
byte hash[WC_##upper##_DIGEST_SIZE]; \
const char* emptyHash = emptyHashStr; \
const char* abcHash = abcHashStr; \
\
ExpectIntEQ(wc_Init##name(&dgst), 0); \
\
ExpectIntEQ(wc_##name##GetHash(NULL, NULL), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##GetHash(&dgst, NULL), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
ExpectIntEQ(wc_##name##GetHash(NULL, hash), \
WC_NO_ERR_TRACE(BAD_FUNC_ARG)); \
\
ExpectIntEQ(wc_##name##GetHash(&dgst, hash), 0); \
ExpectBufEQ(hash, emptyHash, WC_##upper##_DIGEST_SIZE); \
/* Test that the hash state hasn't been modified. */ \
ExpectIntEQ(wc_##name##Update(&dgst, (byte*)"abc", 3), 0); \
ExpectIntEQ(wc_##name##GetHash(&dgst, hash), 0); \
ExpectBufEQ(hash, abcHash, WC_##upper##_DIGEST_SIZE); \
\
wc_##name##Free(&dgst)
#ifdef LITTLE_ENDIAN_ORDER
#define DIGEST_TRANSFORM_TEST(type, name, upper, abcBlockStr, abcHashStr) \
type dgst; \
const char* abc##name##Data = abcBlockStr; \
const char* abcHash = abcHashStr; \
\
ExpectIntEQ(wc_Init##name(&dgst), 0); \
\
/* Test bad args. */ \
ExpectIntEQ(wc_##name##Transform(NULL, NULL), BAD_FUNC_ARG); \
ExpectIntEQ(wc_##name##Transform(&dgst, NULL), BAD_FUNC_ARG); \
ExpectIntEQ(wc_##name##Transform(NULL, (byte*)abc##name##Data), \
BAD_FUNC_ARG); \
\
ExpectIntEQ(wc_##name##Transform(&dgst, (byte*)abc##name##Data), 0); \
ExpectBufEQ((byte*)dgst.digest, (byte*)abcHash, WC_##upper##_DIGEST_SIZE); \
\
wc_##name##Free(&dgst)
#define DIGEST_TRANSFORM_FINAL_RAW_TEST(type, name, upper, abcBlockStr, \
abcHashStr) \
type dgst; \
const char* abc##name##Data = abcBlockStr; \
const char* abcHash = abcHashStr; \
byte abcData[WC_##upper##_BLOCK_SIZE]; \
byte hash[WC_##upper##_DIGEST_SIZE]; \
\
XMEMCPY(abcData, abc##name##Data, WC_##upper##_BLOCK_SIZE); \
\
ExpectIntEQ(wc_Init##name(&dgst), 0); \
\
/* Test bad args. */ \
ExpectIntEQ(wc_##name##Transform(NULL, NULL), BAD_FUNC_ARG); \
ExpectIntEQ(wc_##name##Transform(&dgst, NULL), BAD_FUNC_ARG); \
ExpectIntEQ(wc_##name##Transform(NULL, (byte*)abc##name##Data), \
BAD_FUNC_ARG); \
\
ExpectIntEQ(wc_##name##Transform(&dgst, (byte*)abcData), 0); \
ExpectIntEQ(wc_##name##FinalRaw(&dgst, hash), 0); \
ExpectBufEQ(hash, (byte*)abcHash, WC_##upper##_DIGEST_SIZE); \
\
wc_##name##Free(&dgst)
#else
#define DIGEST_TRANSFORM_TEST(type, name, upper, abcBlockStr, abcHashStr) \
type dgst; \
const char* abc##name##Data = abcBlockStr; \
const char* abcHash = abcHashStr; \
char abc##name##DataBE[WC_##upper##_BLOCK_SIZE]; \
char abcHashBE[WC_##upper##_DIGEST_SIZE]; \
\
ExpectIntEQ(wc_Init##name(&dgst), 0); \
\
/* Test bad args. */ \
ExpectIntEQ(wc_##name##Transform(NULL, NULL), BAD_FUNC_ARG); \
ExpectIntEQ(wc_##name##Transform(&dgst, NULL), BAD_FUNC_ARG); \
ExpectIntEQ(wc_##name##Transform(NULL, (byte*)abc##name##Data), \
BAD_FUNC_ARG); \
\
ByteReverseWords((word32*)abc##name##DataBE, (word32*)abc##name##Data, \
WC_##upper##_BLOCK_SIZE); \
ByteReverseWords((word32*)abcHashBE, (word32*)abcHash, \
WC_##upper##_DIGEST_SIZE); \
ExpectIntEQ(wc_##name##Transform(&dgst, (byte*)abc##name##DataBE), 0); \
ExpectBufEQ((byte*)dgst.digest, (byte*)abcHashBE, \
WC_##upper##_DIGEST_SIZE); \
\
wc_##name##Free(&dgst)
#define DIGEST_TRANSFORM_FINAL_RAW_TEST(type, name, upper, abcBlockStr, \
abcHashStr) \
type dgst; \
const char* abc##name##Data = abcBlockStr; \
const char* abcHash = abcHashStr; \
char abc##name##DataBE[WC_##upper##_BLOCK_SIZE]; \
byte hash[WC_##upper##_DIGEST_SIZE]; \
\
ExpectIntEQ(wc_Init##name(&dgst), 0); \
\
/* Test bad args. */ \
ExpectIntEQ(wc_##name##Transform(NULL, NULL), BAD_FUNC_ARG); \
ExpectIntEQ(wc_##name##Transform(&dgst, NULL), BAD_FUNC_ARG); \
ExpectIntEQ(wc_##name##Transform(NULL, (byte*)abc##name##Data), \
BAD_FUNC_ARG); \
\
ByteReverseWords((word32*)abc##name##DataBE, (word32*)abc##name##Data, \
WC_##upper##_BLOCK_SIZE); \
ExpectIntEQ(wc_##name##Transform(&dgst, (byte*)abc##name##DataBE), 0); \
ExpectIntEQ(wc_##name##FinalRaw(&dgst, hash), 0); \
ExpectBufEQ(hash, (byte*)abcHash, WC_##upper##_DIGEST_SIZE); \
\
wc_##name##Free(&dgst)
#endif
#define DIGEST_FLAGS_TEST(type, name) \
type dgst; \
type dgst_copy; \
word32 flags; \
\
XMEMSET(&dgst_copy, 0, sizeof(dgst_copy)); \
ExpectIntEQ(wc_Init##name(&dgst), 0); \
\
/* Do nothing. */ \
ExpectIntEQ(wc_##name##GetFlags(NULL, NULL), 0); \
ExpectIntEQ(wc_##name##GetFlags(&dgst, NULL), 0); \
ExpectIntEQ(wc_##name##GetFlags(NULL, &flags), 0); \
ExpectIntEQ(wc_##name##SetFlags(NULL, 1), 0); \
\
ExpectIntEQ(wc_##name##GetFlags(&dgst, &flags), 0); \
ExpectIntEQ(flags, 0); \
\
ExpectIntEQ(wc_##name##Copy(&dgst, &dgst_copy), 0); \
ExpectIntEQ(wc_##name##GetFlags(&dgst, &flags), 0); \
ExpectIntEQ(flags, 0); \
ExpectIntEQ(wc_##name##GetFlags(&dgst_copy, &flags), 0); \
ExpectIntEQ(flags, WC_HASH_FLAG_ISCOPY); \
\
ExpectIntEQ(wc_##name##SetFlags(&dgst, WC_HASH_FLAG_WILLCOPY), 0); \
ExpectIntEQ(wc_##name##GetFlags(&dgst, &flags), 0); \
ExpectIntEQ(flags, WC_HASH_FLAG_WILLCOPY); \
ExpectIntEQ(wc_##name##SetFlags(&dgst, 0), 0); \
\
wc_##name##Free(&dgst_copy); \
wc_##name##Free(&dgst)
#define DIGEST_ALT_FLAGS_TEST(type, name, inst) \
type dgst; \
type dgst_copy; \
word32 flags; \
\
XMEMSET(&dgst_copy, 0, sizeof(dgst_copy)); \
ExpectIntEQ(wc_Init##inst(&dgst, HEAP_HINT, INVALID_DEVID), 0); \
\
/* Do nothing. */ \
ExpectIntEQ(wc_##name##_GetFlags(NULL, NULL), 0); \
ExpectIntEQ(wc_##name##_GetFlags(&dgst, NULL), 0); \
ExpectIntEQ(wc_##name##_GetFlags(NULL, &flags), 0); \
ExpectIntEQ(wc_##name##_SetFlags(NULL, 1), 0); \
\
ExpectIntEQ(wc_##name##_GetFlags(&dgst, &flags), 0); \
ExpectIntEQ(flags, 0); \
\
ExpectIntEQ(wc_##inst##_Copy(&dgst, &dgst_copy), 0); \
ExpectIntEQ(wc_##name##_GetFlags(&dgst, &flags), 0); \
ExpectIntEQ(flags, 0); \
ExpectIntEQ(wc_##name##_GetFlags(&dgst_copy, &flags), 0); \
ExpectIntEQ(flags, WC_HASH_FLAG_ISCOPY); \
\
ExpectIntEQ(wc_##name##_SetFlags(&dgst, 1), 0); \
ExpectIntEQ(wc_##name##_GetFlags(&dgst, &flags), 0); \
ExpectIntEQ(flags, 1); \
ExpectIntEQ(wc_##name##_SetFlags(&dgst, 0), 0); \
\
wc_##inst##_Free(&dgst_copy); \
wc_##inst##_Free(&dgst)