From: Vitaly Chikunov Date: Sun, 1 Mar 2020 03:03:40 +0000 (+0300) Subject: test_digest: Test all block sizes and alignments X-Git-Tag: v3.0.0~187 X-Git-Url: http://wagner.pp.ru/gitweb/?a=commitdiff_plain;h=7c30097805cba0c62555493df6dad9f0c5d1d0f3;p=openssl-gost%2Fengine.git test_digest: Test all block sizes and alignments There need to be more tests than 2 constant fixed size blocks. Final digest values are generated from the first run. Test description in comments. --- diff --git a/test_digest.c b/test_digest.c index 1628ab2..1e539ae 100644 --- a/test_digest.c +++ b/test_digest.c @@ -50,6 +50,8 @@ struct hash_testvec { const char *plaintext; const char *digest; unsigned short psize; + unsigned short mdsize; + unsigned short block_size; }; static const struct hash_testvec testvecs[] = { @@ -126,6 +128,30 @@ static const struct hash_testvec testvecs[] = { { 0 } }; +/* synthetic test */ +static const struct hash_testvec stestvecs[] = { + { + .nid = NID_id_GostR3411_2012_256, + .name = "streebog256", + .mdsize = 32, + .block_size = 64, + .digest = + "\xa2\xf3\x6d\x9c\x42\xa1\x1e\xad\xe3\xc1\xfe\x99\xf9\x99\xc3\x84" + "\xe7\x98\xae\x24\x50\x75\x73\xd7\xfc\x99\x81\xa0\x45\x85\x41\xf6" + }, { + .nid = NID_id_GostR3411_2012_512, + .name = "streebog512", + .mdsize = 64, + .block_size = 64, + .digest = + "\x1d\x14\x4d\xd8\xb8\x27\xfb\x55\x1a\x5a\x7d\x03\xbb\xdb\xfa\xcb" + "\x43\x6b\x5b\xc5\x77\x59\xfd\x5f\xf2\x3b\x8e\xf9\xc4\xdd\x6f\x79" + "\x45\xd8\x16\x59\x9e\xaa\xbc\xf2\xb1\x4f\xd0\xe4\xf6\xad\x46\x60" + "\x90\x89\xf7\x2f\x93\xd8\x85\x0c\xb0\x43\xff\x5a\xb6\xe3\x69\xbd" + }, + { 0 } +}; + static int do_digest(int hash_nid, const char *plaintext, unsigned int psize, const char *etalon) { @@ -166,7 +192,7 @@ static int do_test(const struct hash_testvec *tv) mdname = "streebog256"; else if (tv->nid == NID_id_GostR3411_2012_512) mdname = "streebog512"; - printf(cBLUE "Test %s %s: " cNORM, mdname, tv->name); + printf(cBLUE "Test 1 %s %s: " cNORM, mdname, tv->name); fflush(stdout); ret |= do_digest(tv->nid, tv->plaintext, tv->psize, tv->digest); @@ -188,6 +214,106 @@ static int do_test(const struct hash_testvec *tv) return ret; } +#define SUPER_SIZE 256 +/* + * For 256-byte buffer filled with 256 bytes from 0 to 255; + * Digest them 256 times from the buffer end with lengths from 0 to 256, + * and from beginning of the buffer with lengths from 0 to 256; + * Each produced digest is digested again into final sum. + */ +static int do_stest_once(const struct hash_testvec *tv, unsigned int shifts) +{ + unsigned char *ibuf, *md; + T(ibuf = OPENSSL_zalloc(SUPER_SIZE + shifts)); + + /* fill with pattern */ + unsigned int len; + for (len = 0; len < SUPER_SIZE; len++) + ibuf[shifts + len] = len & 0xff; + + const EVP_MD *mdtype; + T(mdtype = EVP_get_digestbynid(tv->nid)); + OPENSSL_assert(tv->nid == EVP_MD_type(mdtype)); + EVP_MD_CTX *ctx, *ctx2; + T(ctx = EVP_MD_CTX_new()); + T(ctx2 = EVP_MD_CTX_new()); + T(EVP_DigestInit(ctx2, mdtype)); + OPENSSL_assert(tv->nid == EVP_MD_CTX_type(ctx2)); + OPENSSL_assert(EVP_MD_block_size(mdtype) == tv->block_size); + OPENSSL_assert(EVP_MD_CTX_size(ctx2) == tv->mdsize); + OPENSSL_assert(EVP_MD_CTX_block_size(ctx2) == tv->block_size); + + const unsigned int mdlen = EVP_MD_size(mdtype); + OPENSSL_assert(mdlen == tv->mdsize); + T(md = OPENSSL_zalloc(mdlen + shifts)); + md += shifts; /* test for output digest alignment problems */ + + /* digest cycles */ + for (len = 0; len < SUPER_SIZE; len++) { + /* for each len digest len bytes from the end of buf */ + T(EVP_DigestInit(ctx, mdtype)); + T(EVP_DigestUpdate(ctx, ibuf + shifts + SUPER_SIZE - len, len)); + T(EVP_DigestFinal(ctx, md, NULL)); + T(EVP_DigestUpdate(ctx2, md, mdlen)); + } + + for (len = 0; len < SUPER_SIZE; len++) { + /* for each len digest len bytes from the beginning of buf */ + T(EVP_DigestInit(ctx, mdtype)); + T(EVP_DigestUpdate(ctx, ibuf + shifts, len)); + T(EVP_DigestFinal(ctx, md, NULL)); + T(EVP_DigestUpdate(ctx2, md, mdlen)); + } + + OPENSSL_free(ibuf); + EVP_MD_CTX_free(ctx); + + T(EVP_DigestFinal(ctx2, md, &len)); + EVP_MD_CTX_free(ctx2); + + if (len != mdlen) { + printf(cRED "digest output len mismatch %u != %u (expected)\n" cNORM, + len, mdlen); + goto err; + } + + if (memcmp(md, tv->digest, mdlen) != 0) { + printf(cRED "digest mismatch\n" cNORM); + + unsigned int i; + printf(" Expected value is: "); + for (i = 0; i < mdlen; i++) + printf("\\x%02x", md[i]); + printf("\n"); + goto err; + } + + OPENSSL_free(md - shifts); + return 0; +err: + OPENSSL_free(md - shifts); + return 1; +} + +/* do different block sizes and different memory offsets */ +static int do_stest(const struct hash_testvec *tv) +{ + int ret = 0; + + printf(cBLUE "Test 2 %s: " cNORM, tv->name); + fflush(stdout); + + unsigned int shifts; + for (shifts = 0; shifts < 16 && !ret; shifts++) + ret |= do_stest_once(tv, shifts); + + if (!ret) + printf(cGREEN "success\n" cNORM); + else + printf(cRED "fail\n" cNORM); + return 0; +} + int main(int argc, char **argv) { int ret = 0; @@ -207,6 +333,8 @@ int main(int argc, char **argv) const struct hash_testvec *tv; for (tv = testvecs; tv->nid; tv++) ret |= do_test(tv); + for (tv = stestvecs; tv->nid; tv++) + ret |= do_stest(tv); ENGINE_finish(eng); ENGINE_free(eng);