]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - test_digest.c
Update INSTALL.md
[openssl-gost/engine.git] / test_digest.c
1 /*
2  * Test GOST 34.11 Digest operation
3  *
4  * Copyright (C) 2019 vt@altlinux.org. All Rights Reserved.
5  *
6  * Contents licensed under the terms of the OpenSSL license
7  * See https://www.openssl.org/source/license.html for details
8  */
9
10 #include "e_gost_err.h"
11 #include "gost_lcl.h"
12 #include <openssl/evp.h>
13 #include <openssl/rand.h>
14 #include <openssl/err.h>
15 #include <openssl/asn1.h>
16 #include <openssl/obj_mac.h>
17 #include <string.h>
18 #include <stdlib.h>
19 #if MIPSEL
20 # include <sys/sysmips.h>
21 #endif
22
23 #define T(e) ({ if (!(e)) { \
24                 ERR_print_errors_fp(stderr); \
25                 OpenSSLDie(__FILE__, __LINE__, #e); \
26             } \
27         })
28 #define TE(e) ({ if (!(e)) { \
29                 ERR_print_errors_fp(stderr); \
30                 fprintf(stderr, "Error at %s:%d %s\n", __FILE__, __LINE__, #e); \
31                 return -1; \
32             } \
33         })
34
35 #define cRED    "\033[1;31m"
36 #define cDRED   "\033[0;31m"
37 #define cGREEN  "\033[1;32m"
38 #define cDGREEN "\033[0;32m"
39 #define cBLUE   "\033[1;34m"
40 #define cDBLUE  "\033[0;34m"
41 #define cNORM   "\033[m"
42 #define TEST_ASSERT(e) {if ((test = (e))) \
43                  printf(cRED "  Test FAILED\n" cNORM); \
44              else \
45                  printf(cGREEN "  Test passed\n" cNORM);}
46
47 struct hash_testvec {
48         int nid;
49         const char *name;
50         const char *plaintext;
51         const char *digest;
52         unsigned short psize;
53         unsigned short mdsize;
54         unsigned short block_size;
55 };
56
57 static const struct hash_testvec testvecs[] = {
58         { /* M1 */
59                 .nid = NID_id_GostR3411_2012_256,
60                 .name = "M1",
61                 .plaintext = "012345678901234567890123456789012345678901234567890123456789012",
62                 .psize = 63,
63                 .digest =
64                         "\x9d\x15\x1e\xef\xd8\x59\x0b\x89"
65                         "\xda\xa6\xba\x6c\xb7\x4a\xf9\x27"
66                         "\x5d\xd0\x51\x02\x6b\xb1\x49\xa4"
67                         "\x52\xfd\x84\xe5\xe5\x7b\x55\x00",
68         },
69         { /* M2 */
70                 .nid = NID_id_GostR3411_2012_256,
71                 .name = "M2",
72                 .plaintext =
73                         "\xd1\xe5\x20\xe2\xe5\xf2\xf0\xe8"
74                         "\x2c\x20\xd1\xf2\xf0\xe8\xe1\xee"
75                         "\xe6\xe8\x20\xe2\xed\xf3\xf6\xe8"
76                         "\x2c\x20\xe2\xe5\xfe\xf2\xfa\x20"
77                         "\xf1\x20\xec\xee\xf0\xff\x20\xf1"
78                         "\xf2\xf0\xe5\xeb\xe0\xec\xe8\x20"
79                         "\xed\xe0\x20\xf5\xf0\xe0\xe1\xf0"
80                         "\xfb\xff\x20\xef\xeb\xfa\xea\xfb"
81                         "\x20\xc8\xe3\xee\xf0\xe5\xe2\xfb",
82                 .psize = 72,
83                 .digest =
84                         "\x9d\xd2\xfe\x4e\x90\x40\x9e\x5d"
85                         "\xa8\x7f\x53\x97\x6d\x74\x05\xb0"
86                         "\xc0\xca\xc6\x28\xfc\x66\x9a\x74"
87                         "\x1d\x50\x06\x3c\x55\x7e\x8f\x50",
88         },
89         { /* M1 */
90                 .nid = NID_id_GostR3411_2012_512,
91                 .name = "M1",
92                 .plaintext = "012345678901234567890123456789012345678901234567890123456789012",
93                 .psize = 63,
94                 .digest =
95                         "\x1b\x54\xd0\x1a\x4a\xf5\xb9\xd5"
96                         "\xcc\x3d\x86\xd6\x8d\x28\x54\x62"
97                         "\xb1\x9a\xbc\x24\x75\x22\x2f\x35"
98                         "\xc0\x85\x12\x2b\xe4\xba\x1f\xfa"
99                         "\x00\xad\x30\xf8\x76\x7b\x3a\x82"
100                         "\x38\x4c\x65\x74\xf0\x24\xc3\x11"
101                         "\xe2\xa4\x81\x33\x2b\x08\xef\x7f"
102                         "\x41\x79\x78\x91\xc1\x64\x6f\x48",
103         },
104         { /* M2 */
105                 .nid = NID_id_GostR3411_2012_512,
106                 .name = "M2",
107                 .plaintext =
108                         "\xd1\xe5\x20\xe2\xe5\xf2\xf0\xe8"
109                         "\x2c\x20\xd1\xf2\xf0\xe8\xe1\xee"
110                         "\xe6\xe8\x20\xe2\xed\xf3\xf6\xe8"
111                         "\x2c\x20\xe2\xe5\xfe\xf2\xfa\x20"
112                         "\xf1\x20\xec\xee\xf0\xff\x20\xf1"
113                         "\xf2\xf0\xe5\xeb\xe0\xec\xe8\x20"
114                         "\xed\xe0\x20\xf5\xf0\xe0\xe1\xf0"
115                         "\xfb\xff\x20\xef\xeb\xfa\xea\xfb"
116                         "\x20\xc8\xe3\xee\xf0\xe5\xe2\xfb",
117                 .psize = 72,
118                 .digest =
119                         "\x1e\x88\xe6\x22\x26\xbf\xca\x6f"
120                         "\x99\x94\xf1\xf2\xd5\x15\x69\xe0"
121                         "\xda\xf8\x47\x5a\x3b\x0f\xe6\x1a"
122                         "\x53\x00\xee\xe4\x6d\x96\x13\x76"
123                         "\x03\x5f\xe8\x35\x49\xad\xa2\xb8"
124                         "\x62\x0f\xcd\x7c\x49\x6c\xe5\xb3"
125                         "\x3f\x0c\xb9\xdd\xdc\x2b\x64\x60"
126                         "\x14\x3b\x03\xda\xba\xc9\xfb\x28",
127         },
128         { 0 }
129 };
130
131 /* synthetic test */
132 static const struct hash_testvec stestvecs[] = {
133         {
134                 .nid = NID_id_GostR3411_2012_256,
135                 .name = "streebog256",
136                 .mdsize = 32,
137                 .block_size = 64,
138                 .digest =
139                         "\xa2\xf3\x6d\x9c\x42\xa1\x1e\xad\xe3\xc1\xfe\x99\xf9\x99\xc3\x84"
140                         "\xe7\x98\xae\x24\x50\x75\x73\xd7\xfc\x99\x81\xa0\x45\x85\x41\xf6"
141         }, {
142                 .nid = NID_id_GostR3411_2012_512,
143                 .name = "streebog512",
144                 .mdsize = 64,
145                 .block_size = 64,
146                 .digest =
147                         "\x1d\x14\x4d\xd8\xb8\x27\xfb\x55\x1a\x5a\x7d\x03\xbb\xdb\xfa\xcb"
148                         "\x43\x6b\x5b\xc5\x77\x59\xfd\x5f\xf2\x3b\x8e\xf9\xc4\xdd\x6f\x79"
149                         "\x45\xd8\x16\x59\x9e\xaa\xbc\xf2\xb1\x4f\xd0\xe4\xf6\xad\x46\x60"
150                         "\x90\x89\xf7\x2f\x93\xd8\x85\x0c\xb0\x43\xff\x5a\xb6\xe3\x69\xbd"
151         },
152         { 0 }
153 };
154
155 static int do_digest(int hash_nid, const char *plaintext, unsigned int psize,
156     const char *etalon)
157 {
158         unsigned int mdlen = 0;
159         if (hash_nid == NID_id_GostR3411_2012_256)
160                 mdlen = 256 / 8;
161         else if (hash_nid == NID_id_GostR3411_2012_512)
162                 mdlen = 512 / 8;
163         const EVP_MD *mdtype;
164         T(mdtype = EVP_get_digestbynid(hash_nid));
165         EVP_MD_CTX *ctx;
166         T(ctx = EVP_MD_CTX_new());
167         T(EVP_DigestInit(ctx, mdtype));
168         T(EVP_DigestUpdate(ctx, plaintext, psize));
169         unsigned int len;
170         unsigned char md[512 / 8];
171         T(EVP_DigestFinal(ctx, md, &len));
172         EVP_MD_CTX_free(ctx);
173         if (len != mdlen) {
174                 printf(cRED "digest output len mismatch %u != %u (expected)\n" cNORM,
175                     len, mdlen);
176                 return 1;
177         }
178         if (memcmp(md, etalon, mdlen) != 0) {
179                 printf(cRED "digest mismatch\n" cNORM);
180                 return 1;
181         }
182
183         return 0;
184 }
185
186 static int do_test(const struct hash_testvec *tv)
187 {
188         int ret = 0;
189
190         const char *mdname = NULL;
191         if (tv->nid == NID_id_GostR3411_2012_256)
192                 mdname = "streebog256";
193         else if (tv->nid == NID_id_GostR3411_2012_512)
194                 mdname = "streebog512";
195         printf(cBLUE "Test 1 %s %s: " cNORM, mdname, tv->name);
196         fflush(stdout);
197         ret |= do_digest(tv->nid, tv->plaintext, tv->psize, tv->digest);
198
199         /* Text alignment problems. */
200         int shifts = 32;
201         int i;
202         char *buf;
203         T(buf = OPENSSL_malloc(tv->psize + shifts));
204         for (i = 0; i < shifts; i++) {
205                 memcpy(buf + i, tv->plaintext, tv->psize);
206                 ret |= do_digest(tv->nid, buf + i, tv->psize, tv->digest);
207         }
208         OPENSSL_free(buf);
209
210         if (!ret)
211                 printf(cGREEN "success\n" cNORM);
212         else
213                 printf(cRED "fail\n" cNORM);
214         return ret;
215 }
216
217 #define SUPER_SIZE 256
218 /*
219  * For 256-byte buffer filled with 256 bytes from 0 to 255;
220  * Digest them 256 times from the buffer end with lengths from 0 to 256,
221  * and from beginning of the buffer with lengths from 0 to 256;
222  * Each produced digest is digested again into final sum.
223  */
224 static int do_stest_once(const struct hash_testvec *tv, unsigned int shifts)
225 {
226     unsigned char *ibuf, *md;
227     T(ibuf = OPENSSL_zalloc(SUPER_SIZE + shifts));
228
229     /* fill with pattern */
230     unsigned int len;
231     for (len = 0; len < SUPER_SIZE; len++)
232             ibuf[shifts + len] = len & 0xff;
233
234     const EVP_MD *mdtype;
235     T(mdtype = EVP_get_digestbynid(tv->nid));
236     OPENSSL_assert(tv->nid == EVP_MD_type(mdtype));
237     EVP_MD_CTX *ctx, *ctx2;
238     T(ctx  = EVP_MD_CTX_new());
239     T(ctx2 = EVP_MD_CTX_new());
240     T(EVP_DigestInit(ctx2, mdtype));
241     OPENSSL_assert(tv->nid == EVP_MD_CTX_type(ctx2));
242     OPENSSL_assert(EVP_MD_block_size(mdtype) == tv->block_size);
243     OPENSSL_assert(EVP_MD_CTX_size(ctx2) == tv->mdsize);
244     OPENSSL_assert(EVP_MD_CTX_block_size(ctx2) == tv->block_size);
245
246     const unsigned int mdlen = EVP_MD_size(mdtype);
247     OPENSSL_assert(mdlen == tv->mdsize);
248     T(md = OPENSSL_zalloc(mdlen + shifts));
249     md += shifts; /* test for output digest alignment problems */
250
251     /* digest cycles */
252     for (len = 0; len < SUPER_SIZE; len++) {
253         /* for each len digest len bytes from the end of buf */
254         T(EVP_DigestInit(ctx, mdtype));
255         T(EVP_DigestUpdate(ctx, ibuf + shifts + SUPER_SIZE - len, len));
256         T(EVP_DigestFinal(ctx, md, NULL));
257         T(EVP_DigestUpdate(ctx2, md, mdlen));
258     }
259
260     for (len = 0; len < SUPER_SIZE; len++) {
261         /* for each len digest len bytes from the beginning of buf */
262         T(EVP_DigestInit(ctx, mdtype));
263         T(EVP_DigestUpdate(ctx, ibuf + shifts, len));
264         T(EVP_DigestFinal(ctx, md, NULL));
265         T(EVP_DigestUpdate(ctx2, md, mdlen));
266     }
267
268     OPENSSL_free(ibuf);
269     EVP_MD_CTX_free(ctx);
270
271     T(EVP_DigestFinal(ctx2, md, &len));
272     EVP_MD_CTX_free(ctx2);
273
274     if (len != mdlen) {
275         printf(cRED "digest output len mismatch %u != %u (expected)\n" cNORM,
276             len, mdlen);
277         goto err;
278     }
279
280     if (memcmp(md, tv->digest, mdlen) != 0) {
281         printf(cRED "digest mismatch\n" cNORM);
282
283         unsigned int i;
284         printf("  Expected value is: ");
285         for (i = 0; i < mdlen; i++)
286             printf("\\x%02x", md[i]);
287         printf("\n");
288         goto err;
289     }
290
291     OPENSSL_free(md - shifts);
292     return 0;
293 err:
294     OPENSSL_free(md - shifts);
295     return 1;
296 }
297
298 /* do different block sizes and different memory offsets */
299 static int do_stest(const struct hash_testvec *tv)
300 {
301     int ret = 0;
302
303     printf(cBLUE "Test 2 %s: " cNORM, tv->name);
304     fflush(stdout);
305
306     unsigned int shifts;
307     for (shifts = 0; shifts < 16 && !ret; shifts++)
308         ret |= do_stest_once(tv, shifts);
309
310     if (!ret)
311         printf(cGREEN "success\n" cNORM);
312     else
313         printf(cRED "fail\n" cNORM);
314     return 0;
315 }
316
317 int main(int argc, char **argv)
318 {
319     int ret = 0;
320
321 #if MIPSEL
322     /* Trigger SIGBUS for unaligned access. */
323     sysmips(MIPS_FIXADE, 0);
324 #endif
325     setenv("OPENSSL_ENGINES", ENGINE_DIR, 0);
326     OPENSSL_add_all_algorithms_conf();
327     ERR_load_crypto_strings();
328     ENGINE *eng;
329     T(eng = ENGINE_by_id("gost"));
330     T(ENGINE_init(eng));
331     T(ENGINE_set_default(eng, ENGINE_METHOD_ALL));
332
333     const struct hash_testvec *tv;
334     for (tv = testvecs; tv->nid; tv++)
335             ret |= do_test(tv);
336     for (tv = stestvecs; tv->nid; tv++)
337             ret |= do_stest(tv);
338
339     ENGINE_finish(eng);
340     ENGINE_free(eng);
341
342     if (ret)
343         printf(cDRED "= Some tests FAILED!\n" cNORM);
344     else
345         printf(cDGREEN "= All tests passed!\n" cNORM);
346     return ret;
347 }