QortalOS Brooklyn for Raspberry Pi 4
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

226 lines
8.0 KiB

/* $Id: test_digest_helper.c 192 2010-05-25 22:33:34Z tp $ */
/*
* Helper code for hash function unit tests. This code is meant to be
* included by another file which then uses the macros defined herein.
*
* ==========================(LICENSE BEGIN)============================
*
* Copyright (c) 2007-2010 Projet RNRT SAPHIR
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* ===========================(LICENSE END)=============================
*
* @author Thomas Pornin <[email protected]>
*/
#include <stdlib.h>
#include <string.h>
#include "utest.h"
/*
* This macro defines a function which verifies a test vector. The input
* data is an ASCII string; the reference string is the hexadecimal
* representation of the expected binary output. Hashing is done twice,
* in order to exercise functions with misaligned input, as well as
* proper state reinitialization. The announced output length is also
* checked against the output size macro.
*/
#define TEST_DIGEST_INTERNAL(Name, cname, blen) \
static void \
test_ ## cname ## _internal(char *data, char *refres) \
{ \
sph_ ## cname ## _context mc; \
unsigned char res[blen], ref[blen]; \
size_t dbuf_len; \
unsigned char *dbuf; \
\
if (((blen) * 8) != SPH_SIZE_ ## cname) \
fail("wrong output size (%u, exp: %u)", \
(unsigned)(blen) * 8, (unsigned)SPH_SIZE_ ## cname); \
dbuf_len = strlen(data); \
sph_ ## cname ## _init(&mc); \
sph_ ## cname(&mc, (unsigned char *)data, dbuf_len); \
sph_ ## cname ## _close(&mc, res); \
utest_strtobin(ref, refres); \
ASSERT(utest_byteequal(res, ref, blen)); \
dbuf = malloc(1 + dbuf_len); \
if (dbuf == NULL) { \
fail("malloc() failed (length = %lu)", \
(unsigned long)(1 + dbuf_len)); \
} \
memset(res, 0, sizeof res); \
memcpy(1 + dbuf, data, dbuf_len); \
sph_ ## cname(&mc, dbuf + 1, dbuf_len); \
sph_ ## cname ## _close(&mc, res); \
ASSERT(utest_byteequal(res, ref, blen)); \
free(dbuf); \
}
/*
* This macro defines a function which verifies a test vector. The input
* data is an hexadecimal string, but 0 to 7 bits in the last byte may
* be ignored. The reference string is the hexadecimal representation of
* the expected binary output. This function exercises the support for
* partial bytes (i.e. an input message bit length which is not a
* multiple of eight).
*
* Hashing is done twice, in order to exercise functions with misaligned
* input, as well as proper state reinitialization. The announced output
* length is also checked against the output size macro.
*/
#define TEST_DIGEST_INTERNAL_BITS(Name, cname, blen) \
static void \
test_ ## cname ## _internal_bits(char *data, unsigned ignored, char *refres) \
{ \
sph_ ## cname ## _context mc; \
unsigned char res[blen], ref[blen]; \
size_t dbuf_len; \
unsigned char *dbuf; \
\
if (((blen) * 8) != SPH_SIZE_ ## cname) \
fail("wrong output size (%u, exp: %u)", \
(unsigned)(blen) * 8, (unsigned)SPH_SIZE_ ## cname); \
dbuf_len = 1 + 2 * strlen(data); \
dbuf = malloc(1 + 2 * strlen(data)); \
if (dbuf == NULL) { \
fail("malloc() failed (length = %lu)", \
(unsigned long)dbuf_len); \
} \
dbuf_len = utest_strtobin(dbuf, data); \
sph_ ## cname ## _init(&mc); \
if (ignored == 0) { \
sph_ ## cname(&mc, dbuf, dbuf_len); \
sph_ ## cname ## _close(&mc, res); \
} else { \
sph_ ## cname(&mc, dbuf, dbuf_len - 1); \
sph_ ## cname ## _addbits_and_close(&mc, \
dbuf[dbuf_len - 1], 8 - ignored, res); \
} \
utest_strtobin(ref, refres); \
ASSERT(utest_byteequal(res, ref, blen)); \
memset(res, 0, sizeof res); \
memmove(1 + dbuf, dbuf, dbuf_len); \
if (ignored == 0) { \
sph_ ## cname(&mc, dbuf + 1, dbuf_len); \
sph_ ## cname ## _close(&mc, res); \
} else { \
sph_ ## cname(&mc, dbuf + 1, dbuf_len - 1); \
sph_ ## cname ## _addbits_and_close(&mc, \
dbuf[dbuf_len], 8 - ignored, res); \
} \
ASSERT(utest_byteequal(res, ref, blen)); \
free(dbuf); \
}
/*
* This macro defines a function which is similar to the one defined
* by TEST_DIGEST_INTERNAL_BITS, except that it uses the NIST messages
* for SHA-3 test vectors, indexed by message size (in bits, from 0 to
* 2047, inclusive).
*/
#define TEST_DIGEST_NIST(Name, cname, blen) \
static void \
test_ ## cname ## _nist(unsigned u, char *refres) \
{ \
sph_ ## cname ## _context mc; \
unsigned char res[blen], ref[blen]; \
size_t dbuf_len; \
unsigned char dbuf[260]; \
unsigned extra; \
\
if (((blen) * 8) != SPH_SIZE_ ## cname) \
fail("wrong output size (%u, exp: %u)", \
(unsigned)(blen) * 8, (unsigned)SPH_SIZE_ ## cname); \
dbuf_len = (u + 7) / 8; \
extra = u & 7; \
memcpy(dbuf, utest_nist_data(u), dbuf_len); \
sph_ ## cname ## _init(&mc); \
if (extra == 0) { \
sph_ ## cname(&mc, dbuf, dbuf_len); \
sph_ ## cname ## _close(&mc, res); \
} else { \
sph_ ## cname(&mc, dbuf, dbuf_len - 1); \
sph_ ## cname ## _addbits_and_close(&mc, \
dbuf[dbuf_len - 1], extra, res); \
} \
utest_strtobin(ref, refres); \
ASSERT(utest_byteequal(res, ref, blen)); \
memset(res, 0, sizeof res); \
memmove(1 + dbuf, dbuf, dbuf_len); \
if (extra == 0) { \
sph_ ## cname(&mc, dbuf + 1, dbuf_len); \
sph_ ## cname ## _close(&mc, res); \
} else { \
sph_ ## cname(&mc, dbuf + 1, dbuf_len - 1); \
sph_ ## cname ## _addbits_and_close(&mc, \
dbuf[dbuf_len], extra, res); \
} \
ASSERT(utest_byteequal(res, ref, blen)); \
}
/*
* This macro hashes a 1000000-byte message where all bytes are equal to
* 0x61 (the 'a' lowercase letter, in ASCII). Output is compared to the
* provided reference string (hexadecimal representation of the expected
* binary output). Hashing is done twice, in order to exercise functions
* with misaligned input.
*/
#define KAT_MILLION_A(Name, cname, blen, refres) do { \
sph_ ## cname ## _context sc; \
unsigned char buf[1001], res[blen], ref[blen]; \
int i; \
\
memset(buf, 'a', sizeof buf); \
sph_ ## cname ## _init(&sc); \
for (i = 0; i < 1000; i ++) \
sph_ ## cname(&sc, buf, 1000); \
sph_ ## cname ## _close(&sc, res); \
utest_strtobin(ref, refres); \
ASSERT(utest_byteequal(res, ref, blen)); \
for (i = 0; i < 1000; i ++) \
sph_ ## cname(&sc, buf + 1, 1000); \
sph_ ## cname ## _close(&sc, res); \
ASSERT(utest_byteequal(res, ref, blen)); \
} while (0)
/*
* This macro hashes two (distinct) messages which are provided as
* hexadecimal strings, and verifies that they yield the same output.
* This is used to check published collisions for those algorithms
* which have been successfully attacked. Both messages must fit in
* 4 kilobytes each.
*/
#define TEST_COLLISION(Name, cname, blen, str1, str2) do { \
sph_ ## cname ## _context sc; \
unsigned char msg1[4096], msg2[4096]; \
unsigned char res1[blen], res2[blen]; \
size_t msg1_len, msg2_len; \
msg1_len = utest_strtobin(msg1, str1); \
msg2_len = utest_strtobin(msg2, str2); \
ASSERT((msg1_len != msg2_len) \
|| !utest_byteequal(msg1, msg2, msg1_len)); \
sph_ ## cname ## _init(&sc); \
sph_ ## cname(&sc, msg1, msg1_len); \
sph_ ## cname ## _close(&sc, res1); \
sph_ ## cname(&sc, msg2, msg2_len); \
sph_ ## cname ## _close(&sc, res2); \
ASSERT(utest_byteequal(res1, res2, blen)); \
} while (0)