From 0232aa9efea28d3a3ecde4f8ce8ce9c96189af30 Mon Sep 17 00:00:00 2001 From: Vitaly Chikunov Date: Wed, 10 Apr 2019 17:43:45 +0000 Subject: test_digest: simple digest tests Especially test alginment problems on MIPSel. --- CMakeLists.txt | 6 ++ test_digest.c | 219 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 225 insertions(+) create mode 100644 test_digest.c diff --git a/CMakeLists.txt b/CMakeLists.txt index f019f14..2ea9574 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -135,6 +135,11 @@ set(GOST_ENGINE_SOURCE_FILES gost_omac_acpkm.c ) +add_executable(test_digest test_digest.c) +target_link_libraries(test_digest gost_engine gost_core ${OPENSSL_CRYPTO_LIBRARY}) +add_test(NAME digest + COMMAND test_digest) + add_executable(test_curves test_curves.c) target_link_libraries(test_curves gost_engine gost_core ${OPENSSL_CRYPTO_LIBRARY}) add_test(NAME curves @@ -189,6 +194,7 @@ target_link_libraries(sign gost_engine gost_core ${OPENSSL_CRYPTO_LIBRARY} ${CLO # All that may need to load just built engine will have path to it defined. set(BINARY_TESTS_TARGETS + test_digest test_curves test_params test_sign diff --git a/test_digest.c b/test_digest.c new file mode 100644 index 0000000..1628ab2 --- /dev/null +++ b/test_digest.c @@ -0,0 +1,219 @@ +/* + * Test GOST 34.11 Digest operation + * + * Copyright (C) 2019 vt@altlinux.org. All Rights Reserved. + * + * Contents licensed under the terms of the OpenSSL license + * See https://www.openssl.org/source/license.html for details + */ + +#include "e_gost_err.h" +#include "gost_lcl.h" +#include +#include +#include +#include +#include +#include +#include +#if MIPSEL +# include +#endif + +#define T(e) ({ if (!(e)) { \ + ERR_print_errors_fp(stderr); \ + OpenSSLDie(__FILE__, __LINE__, #e); \ + } \ + }) +#define TE(e) ({ if (!(e)) { \ + ERR_print_errors_fp(stderr); \ + fprintf(stderr, "Error at %s:%d %s\n", __FILE__, __LINE__, #e); \ + return -1; \ + } \ + }) + +#define cRED "\033[1;31m" +#define cDRED "\033[0;31m" +#define cGREEN "\033[1;32m" +#define cDGREEN "\033[0;32m" +#define cBLUE "\033[1;34m" +#define cDBLUE "\033[0;34m" +#define cNORM "\033[m" +#define TEST_ASSERT(e) {if ((test = (e))) \ + printf(cRED " Test FAILED\n" cNORM); \ + else \ + printf(cGREEN " Test passed\n" cNORM);} + +struct hash_testvec { + int nid; + const char *name; + const char *plaintext; + const char *digest; + unsigned short psize; +}; + +static const struct hash_testvec testvecs[] = { + { /* M1 */ + .nid = NID_id_GostR3411_2012_256, + .name = "M1", + .plaintext = "012345678901234567890123456789012345678901234567890123456789012", + .psize = 63, + .digest = + "\x9d\x15\x1e\xef\xd8\x59\x0b\x89" + "\xda\xa6\xba\x6c\xb7\x4a\xf9\x27" + "\x5d\xd0\x51\x02\x6b\xb1\x49\xa4" + "\x52\xfd\x84\xe5\xe5\x7b\x55\x00", + }, + { /* M2 */ + .nid = NID_id_GostR3411_2012_256, + .name = "M2", + .plaintext = + "\xd1\xe5\x20\xe2\xe5\xf2\xf0\xe8" + "\x2c\x20\xd1\xf2\xf0\xe8\xe1\xee" + "\xe6\xe8\x20\xe2\xed\xf3\xf6\xe8" + "\x2c\x20\xe2\xe5\xfe\xf2\xfa\x20" + "\xf1\x20\xec\xee\xf0\xff\x20\xf1" + "\xf2\xf0\xe5\xeb\xe0\xec\xe8\x20" + "\xed\xe0\x20\xf5\xf0\xe0\xe1\xf0" + "\xfb\xff\x20\xef\xeb\xfa\xea\xfb" + "\x20\xc8\xe3\xee\xf0\xe5\xe2\xfb", + .psize = 72, + .digest = + "\x9d\xd2\xfe\x4e\x90\x40\x9e\x5d" + "\xa8\x7f\x53\x97\x6d\x74\x05\xb0" + "\xc0\xca\xc6\x28\xfc\x66\x9a\x74" + "\x1d\x50\x06\x3c\x55\x7e\x8f\x50", + }, + { /* M1 */ + .nid = NID_id_GostR3411_2012_512, + .name = "M1", + .plaintext = "012345678901234567890123456789012345678901234567890123456789012", + .psize = 63, + .digest = + "\x1b\x54\xd0\x1a\x4a\xf5\xb9\xd5" + "\xcc\x3d\x86\xd6\x8d\x28\x54\x62" + "\xb1\x9a\xbc\x24\x75\x22\x2f\x35" + "\xc0\x85\x12\x2b\xe4\xba\x1f\xfa" + "\x00\xad\x30\xf8\x76\x7b\x3a\x82" + "\x38\x4c\x65\x74\xf0\x24\xc3\x11" + "\xe2\xa4\x81\x33\x2b\x08\xef\x7f" + "\x41\x79\x78\x91\xc1\x64\x6f\x48", + }, + { /* M2 */ + .nid = NID_id_GostR3411_2012_512, + .name = "M2", + .plaintext = + "\xd1\xe5\x20\xe2\xe5\xf2\xf0\xe8" + "\x2c\x20\xd1\xf2\xf0\xe8\xe1\xee" + "\xe6\xe8\x20\xe2\xed\xf3\xf6\xe8" + "\x2c\x20\xe2\xe5\xfe\xf2\xfa\x20" + "\xf1\x20\xec\xee\xf0\xff\x20\xf1" + "\xf2\xf0\xe5\xeb\xe0\xec\xe8\x20" + "\xed\xe0\x20\xf5\xf0\xe0\xe1\xf0" + "\xfb\xff\x20\xef\xeb\xfa\xea\xfb" + "\x20\xc8\xe3\xee\xf0\xe5\xe2\xfb", + .psize = 72, + .digest = + "\x1e\x88\xe6\x22\x26\xbf\xca\x6f" + "\x99\x94\xf1\xf2\xd5\x15\x69\xe0" + "\xda\xf8\x47\x5a\x3b\x0f\xe6\x1a" + "\x53\x00\xee\xe4\x6d\x96\x13\x76" + "\x03\x5f\xe8\x35\x49\xad\xa2\xb8" + "\x62\x0f\xcd\x7c\x49\x6c\xe5\xb3" + "\x3f\x0c\xb9\xdd\xdc\x2b\x64\x60" + "\x14\x3b\x03\xda\xba\xc9\xfb\x28", + }, + { 0 } +}; + +static int do_digest(int hash_nid, const char *plaintext, unsigned int psize, + const char *etalon) +{ + unsigned int mdlen = 0; + if (hash_nid == NID_id_GostR3411_2012_256) + mdlen = 256 / 8; + else if (hash_nid == NID_id_GostR3411_2012_512) + mdlen = 512 / 8; + const EVP_MD *mdtype; + T(mdtype = EVP_get_digestbynid(hash_nid)); + EVP_MD_CTX *ctx; + T(ctx = EVP_MD_CTX_new()); + T(EVP_DigestInit(ctx, mdtype)); + T(EVP_DigestUpdate(ctx, plaintext, psize)); + unsigned int len; + unsigned char md[512 / 8]; + T(EVP_DigestFinal(ctx, md, &len)); + EVP_MD_CTX_free(ctx); + if (len != mdlen) { + printf(cRED "digest output len mismatch %u != %u (expected)\n" cNORM, + len, mdlen); + return 1; + } + if (memcmp(md, etalon, mdlen) != 0) { + printf(cRED "digest mismatch\n" cNORM); + return 1; + } + + return 0; +} + +static int do_test(const struct hash_testvec *tv) +{ + int ret = 0; + + const char *mdname = NULL; + if (tv->nid == NID_id_GostR3411_2012_256) + mdname = "streebog256"; + else if (tv->nid == NID_id_GostR3411_2012_512) + mdname = "streebog512"; + printf(cBLUE "Test %s %s: " cNORM, mdname, tv->name); + fflush(stdout); + ret |= do_digest(tv->nid, tv->plaintext, tv->psize, tv->digest); + + /* Text alignment problems. */ + int shifts = 32; + int i; + char *buf; + T(buf = OPENSSL_malloc(tv->psize + shifts)); + for (i = 0; i < shifts; i++) { + memcpy(buf + i, tv->plaintext, tv->psize); + ret |= do_digest(tv->nid, buf + i, tv->psize, tv->digest); + } + OPENSSL_free(buf); + + if (!ret) + printf(cGREEN "success\n" cNORM); + else + printf(cRED "fail\n" cNORM); + return ret; +} + +int main(int argc, char **argv) +{ + int ret = 0; + +#if MIPSEL + /* Trigger SIGBUS for unaligned access. */ + sysmips(MIPS_FIXADE, 0); +#endif + setenv("OPENSSL_ENGINES", ENGINE_DIR, 0); + OPENSSL_add_all_algorithms_conf(); + ERR_load_crypto_strings(); + ENGINE *eng; + T(eng = ENGINE_by_id("gost")); + T(ENGINE_init(eng)); + T(ENGINE_set_default(eng, ENGINE_METHOD_ALL)); + + const struct hash_testvec *tv; + for (tv = testvecs; tv->nid; tv++) + ret |= do_test(tv); + + ENGINE_finish(eng); + ENGINE_free(eng); + + if (ret) + printf(cDRED "= Some tests FAILED!\n" cNORM); + else + printf(cDGREEN "= All tests passed!\n" cNORM); + return ret; +} -- cgit v1.1 From e576f52929756beb785f29aa14b6393d7ac6c298 Mon Sep 17 00:00:00 2001 From: Vitaly Chikunov Date: Wed, 10 Apr 2019 18:09:54 +0000 Subject: Fix Streebog alignment problem Some architectures in some circumstances do not allow unaligned memory access (such as ARM, MIPS) triggering SIGBUS. This patch very crudely fixes this issue. The issue is found and original fix is proposed by Eric Biggers: https://patchwork.kernel.org/patch/10878865/ --- gosthash2012.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/gosthash2012.c b/gosthash2012.c index ee534c2..bbe7dcb 100644 --- a/gosthash2012.c +++ b/gosthash2012.c @@ -157,10 +157,13 @@ static void g(union uint512_u *h, const union uint512_u *N, static INLINE void stage2(gost2012_hash_ctx * CTX, const unsigned char *data) { - g(&(CTX->h), &(CTX->N), data); + union uint512_u m; + + memcpy(&m, data, sizeof(m)); + g(&(CTX->h), &(CTX->N), (const unsigned char *)&m); add512(&(CTX->N), &buffer512, &(CTX->N)); - add512(&(CTX->Sigma), (const union uint512_u *)data, &(CTX->Sigma)); + add512(&(CTX->Sigma), &m, &(CTX->Sigma)); } static INLINE void stage3(gost2012_hash_ctx * CTX) -- cgit v1.1