const char *plaintext;
const char *digest;
unsigned short psize;
+ unsigned short mdsize;
+ unsigned short block_size;
};
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)
{
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);
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;
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);