]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - test_context.c
tcl_tests: ca.try: Ignore openssl crl exit status for 'corrupted CRL' test
[openssl-gost/engine.git] / test_context.c
1 /*
2  * Copyright (C) 2018,2020 Vitaly Chikunov <vt@altlinux.org> All Rights Reserved.
3  *
4  * Contents licensed under the terms of the OpenSSL license
5  * See https://www.openssl.org/source/license.html for details
6  */
7
8 #ifdef _MSC_VER
9 # pragma warning(push, 3)
10 # include <openssl/applink.c>
11 # pragma warning(pop)
12 #endif
13 #include <openssl/engine.h>
14 #include <openssl/evp.h>
15 #include <openssl/rand.h>
16 #include <openssl/err.h>
17 #include <openssl/asn1.h>
18 #include <string.h>
19 #ifndef EVP_MD_CTRL_SET_KEY
20 # include "gost_lcl.h"
21 #endif
22
23 #define T(e) \
24     if (!(e)) { \
25         ERR_print_errors_fp(stderr); \
26         OpenSSLDie(__FILE__, __LINE__, #e); \
27     }
28
29 #define cRED    "\033[1;31m"
30 #define cDRED   "\033[0;31m"
31 #define cGREEN  "\033[1;32m"
32 #define cDGREEN "\033[0;32m"
33 #define cBLUE   "\033[1;34m"
34 #define cDBLUE  "\033[0;34m"
35 #define cNORM   "\033[m"
36 #define TEST_ASSERT(e) {if ((test = (e))) \
37                  printf(cRED "  Test FAILED" cNORM "\n"); \
38              else \
39                  printf(cGREEN "  Test passed" cNORM "\n");}
40
41 static void hexdump(const void *ptr, size_t len)
42 {
43     const unsigned char *p = ptr;
44     size_t i, j;
45
46     for (i = 0; i < len; i += j) {
47         for (j = 0; j < 16 && i + j < len; j++)
48             printf("%s%02x", j? "" : " ", p[i + j]);
49     }
50     printf("\n");
51 }
52
53 #define TEST_SIZE 256
54 #define STEP_SIZE 16
55
56 static int test_contexts_cipher(const char *name, const int enc, int acpkm)
57 {
58     EVP_CIPHER_CTX *ctx, *save;
59     unsigned char pt[TEST_SIZE] = {1};
60     unsigned char b[TEST_SIZE]; /* base output */
61     unsigned char c[TEST_SIZE]; /* cloned output */
62     unsigned char K[32] = {1};
63     unsigned char iv[16] = {1};
64     int outlen, tmplen;
65     int ret = 0, test = 0;
66
67     EVP_CIPHER *type;
68     ERR_set_mark();
69     T((type = (EVP_CIPHER *)EVP_get_cipherbyname(name))
70       || (type = EVP_CIPHER_fetch(NULL, name, NULL)));
71     ERR_pop_to_mark();
72
73     printf(cBLUE "%s test for %s" cNORM "\n",
74            enc ? "Encryption" : "Decryption", name);
75
76     /* produce base encryption */
77     ctx = EVP_CIPHER_CTX_new();
78     T(ctx);
79     T(EVP_CipherInit_ex(ctx, type, NULL, K, iv, enc));
80     if (acpkm) {
81         if (EVP_CIPHER_get0_provider(type) != NULL) {
82             OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
83             size_t v = (size_t)acpkm;
84
85             params[0] = OSSL_PARAM_construct_size_t("key-mesh", &v);
86             T(EVP_CIPHER_CTX_set_params(ctx, params));
87         } else {
88             T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, acpkm, NULL));
89         }
90     }
91     T(EVP_CIPHER_CTX_set_padding(ctx, 0));
92     T(EVP_CipherUpdate(ctx, b, &outlen, pt, sizeof(b)));
93     T(EVP_CipherFinal_ex(ctx, b + outlen, &tmplen));
94
95     /* and now tests */
96     EVP_CIPHER_CTX_reset(ctx);
97     EVP_CIPHER_CTX_reset(ctx); /* double call is intentional */
98     T(EVP_CipherInit_ex(ctx, type, NULL, K, iv, enc));
99     T(EVP_CIPHER_CTX_set_padding(ctx, 0));
100     if (acpkm) {
101         if (EVP_CIPHER_get0_provider(type) != NULL) {
102             OSSL_PARAM params[] = { OSSL_PARAM_END, OSSL_PARAM_END };
103             size_t v = (size_t)acpkm;
104
105             params[0] = OSSL_PARAM_construct_size_t("key-mesh", &v);
106             T(EVP_CIPHER_CTX_set_params(ctx, params));
107         } else {
108             T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, acpkm, NULL));
109         }
110     }
111     save = ctx;
112
113     printf(" cloned contexts: ");
114     int i;
115     memset(c, 0, sizeof(c));
116     for (i = 0; i < TEST_SIZE / STEP_SIZE; i++) {
117         EVP_CIPHER_CTX *copy = EVP_CIPHER_CTX_new();
118         T(copy);
119         T(EVP_CIPHER_CTX_copy(copy, ctx));
120         if (save != ctx) /* else original context */
121             EVP_CIPHER_CTX_free(ctx);
122         ctx = copy;
123
124         T(EVP_CipherUpdate(ctx, c + STEP_SIZE * i, &outlen,
125                            pt + STEP_SIZE * i, STEP_SIZE));
126     }
127
128     outlen = i * STEP_SIZE;
129     T(EVP_CipherFinal_ex(ctx, c + outlen, &tmplen));
130     TEST_ASSERT(outlen != TEST_SIZE || memcmp(c, b, TEST_SIZE));
131     EVP_CIPHER_CTX_free(ctx);
132     if (test) {
133         printf("  b[%d] = ", outlen);
134         hexdump(b, outlen);
135         printf("  c[%d] = ", outlen);
136         hexdump(c, outlen);
137     }
138     ret |= test;
139
140     /* resume original context */
141     printf("    base context: ");
142     memset(c, 0, sizeof(c));
143     T(EVP_CipherUpdate(save, c, &outlen, pt, sizeof(c)));
144     T(EVP_CipherFinal_ex(save, c + outlen, &tmplen));
145     TEST_ASSERT(outlen != TEST_SIZE || memcmp(c, b, TEST_SIZE));
146     EVP_CIPHER_CTX_cleanup(save); /* multiple calls are intentional */
147     EVP_CIPHER_CTX_cleanup(save);
148     EVP_CIPHER_CTX_free(save);
149     EVP_CIPHER_free(type);
150     if (test) {
151         printf("  b[%d] = ", outlen);
152         hexdump(b, outlen);
153         printf("  c[%d] = ", outlen);
154         hexdump(c, outlen);
155     }
156     ret |= test;
157
158     return ret;
159 }
160
161 static int test_contexts_digest_or_legacy_mac(const EVP_MD *type, int mac)
162 {
163     int ret = 0, test = 0;
164     unsigned char K[32] = {1};
165
166     /* produce base digest */
167     EVP_MD_CTX *ctx, *save;
168     unsigned char pt[TEST_SIZE] = {1};
169     unsigned char b[EVP_MAX_MD_SIZE] = {0};
170     unsigned char c[EVP_MAX_MD_SIZE];
171     unsigned int outlen, tmplen;
172
173     /* Simply digest whole input. */
174     T(ctx = EVP_MD_CTX_new());
175     T(EVP_DigestInit_ex(ctx, type, NULL));
176     if (mac)
177         T(EVP_MD_CTX_ctrl(ctx, EVP_MD_CTRL_SET_KEY, sizeof(K), (void *)K));
178     T(EVP_DigestUpdate(ctx, pt, sizeof(pt)));
179     T(EVP_DigestFinal_ex(ctx, b, &tmplen));
180     save = ctx; /* will be not freed while cloning */
181
182     /* cloned digest */
183     EVP_MD_CTX_reset(ctx); /* test double reset */
184     EVP_MD_CTX_reset(ctx);
185     T(EVP_DigestInit_ex(ctx, type, NULL));
186     if (mac)
187         T(EVP_MD_CTX_ctrl(ctx, EVP_MD_CTRL_SET_KEY, sizeof(K), (void *)K));
188     printf(" cloned contexts: ");
189     memset(c, 0, sizeof(c));
190     int i;
191     for (i = 0; i < TEST_SIZE / STEP_SIZE; i++) {
192         /* Clone and continue digesting next part of input. */
193         EVP_MD_CTX *copy;
194         T(copy = EVP_MD_CTX_new());
195         T(EVP_MD_CTX_copy_ex(copy, ctx));
196
197         /* rolling */
198         if (save != ctx)
199             EVP_MD_CTX_free(ctx);
200         ctx = copy;
201
202         T(EVP_DigestUpdate(ctx, pt + STEP_SIZE * i, STEP_SIZE));
203     }
204     outlen = i * STEP_SIZE;
205     T(EVP_DigestFinal_ex(ctx, c, &tmplen));
206     /* Should be same as the simple digest. */
207     TEST_ASSERT(outlen != TEST_SIZE || memcmp(c, b, EVP_MAX_MD_SIZE));
208     EVP_MD_CTX_free(ctx);
209     if (test) {
210         printf("  b[%d] = ", outlen);
211         hexdump(b, outlen);
212         printf("  c[%d] = ", outlen);
213         hexdump(c, outlen);
214     }
215     ret |= test;
216
217     /* Resume original context, what if it's damaged? */
218     printf("    base context: ");
219     memset(c, 0, sizeof(c));
220     T(EVP_DigestUpdate(save, pt, sizeof(pt)));
221     T(EVP_DigestFinal_ex(save, c, &tmplen));
222     TEST_ASSERT(outlen != TEST_SIZE || memcmp(c, b, EVP_MAX_MD_SIZE));
223     EVP_MD_CTX_free(save);
224     if (test) {
225         printf("  b[%d] = ", outlen);
226         hexdump(b, outlen);
227         printf("  c[%d] = ", outlen);
228         hexdump(c, outlen);
229     }
230     ret |= test;
231
232     return ret;
233 }
234
235 static int test_contexts_digest(const char *name)
236 {
237     EVP_MD *type;
238     ERR_set_mark();
239     T((type = (EVP_MD *)EVP_get_digestbyname(name))
240       || (type = EVP_MD_fetch(NULL, name, NULL)));
241     ERR_pop_to_mark();
242
243     printf(cBLUE "Digest test for %s" cNORM "\n", name);
244     int ret = test_contexts_digest_or_legacy_mac(type, 0);
245     EVP_MD_free(type);
246     return ret;
247 }
248
249 static int test_contexts_mac(const char *name)
250 {
251     int ret = 0, test = 0;
252     unsigned char K[32] = {1};
253     const EVP_MD *type = EVP_get_digestbyname(name);
254     EVP_MAC *mac;
255
256     if (type) {
257         printf(cBLUE "Mac via EVP_MD test for %s" cNORM "\n", name);
258         return test_contexts_digest_or_legacy_mac(type, 1);
259     }
260
261     T(mac = EVP_MAC_fetch(NULL, name, NULL));
262     printf(cBLUE "Mac test for %s" cNORM "\n", name);
263
264     /* produce base mac */
265     EVP_MAC_CTX *ctx;
266     unsigned char pt[TEST_SIZE] = {1};
267     unsigned char b[EVP_MAX_MD_SIZE] = {0};
268     unsigned char c[EVP_MAX_MD_SIZE] = {0};
269     size_t outlen, tmplen;
270
271     /* Simply mac whole input. */
272     T(ctx = EVP_MAC_CTX_new(mac));
273     T(EVP_MAC_init(ctx, K, sizeof(K), NULL));
274     T(EVP_MAC_update(ctx, pt, sizeof(pt)));
275     T(EVP_MAC_final(ctx, b, &tmplen, sizeof(b)));
276     EVP_MAC_CTX_free(ctx);
277
278     /* Mac with rolling input. */
279     printf(" cloned contexts: ");
280     T(ctx = EVP_MAC_CTX_new(mac));
281     T(EVP_MAC_init(ctx, K, sizeof(K), NULL));
282     int i;
283     for (i = 0; i < TEST_SIZE / STEP_SIZE; i++) {
284         T(EVP_MAC_update(ctx, pt + STEP_SIZE * i, STEP_SIZE));
285     }
286     outlen = i * STEP_SIZE;
287     T(EVP_MAC_final(ctx, c, &tmplen, sizeof(c)));
288     EVP_MAC_CTX_free(ctx);
289     EVP_MAC_free(mac);
290
291     /* Rolling mac should give the same result as the simple mac. */
292     TEST_ASSERT(outlen != TEST_SIZE || memcmp(c, b, EVP_MAX_MD_SIZE));
293
294     if (test) {
295         printf("  b[%d] = ", (int)outlen);
296         hexdump(b, outlen);
297         printf("  c[%d] = ", (int)outlen);
298         hexdump(c, outlen);
299     }
300     ret |= test;
301
302     return ret;
303 }
304
305 static struct testcase_cipher {
306     const char *name;
307     int acpkm;
308 } testcases_ciphers[] = {
309     { SN_id_Gost28147_89, },
310     { SN_gost89_cnt, },
311     { SN_gost89_cnt_12, },
312     { SN_gost89_cbc, },
313     { SN_grasshopper_ecb, },
314     { SN_grasshopper_cbc, },
315     { SN_grasshopper_cfb, },
316     { SN_grasshopper_ofb, },
317     { SN_grasshopper_ctr, },
318     { SN_magma_cbc, },
319     { SN_magma_ctr, },
320     { SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm, 256 / 8 },
321     { 0 },
322 };
323
324 static struct testcase_digest {
325     const char *name;
326     int mac;
327 } testcases_digests[] = {
328     { SN_id_GostR3411_94, },
329     { SN_id_Gost28147_89_MAC, 1 },
330     { SN_id_GostR3411_2012_256, },
331     { SN_id_GostR3411_2012_512, },
332     { SN_gost_mac_12, 1 },
333     { SN_magma_mac, 1 },
334     { SN_grasshopper_mac, 1 },
335     { SN_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac, 1 },
336     { 0 },
337 };
338 int main(int argc, char **argv)
339 {
340     int ret = 0;
341
342     OPENSSL_add_all_algorithms_conf();
343
344     const struct testcase_cipher *tc;
345     for (tc = testcases_ciphers; tc->name; tc++) {
346         ret |= test_contexts_cipher(tc->name, 1, tc->acpkm);
347         ret |= test_contexts_cipher(tc->name, 0, tc->acpkm);
348     }
349     const struct testcase_digest *td;
350     for (td = testcases_digests; td->name; td++) {
351         if (td->mac)
352             ret |= test_contexts_mac(td->name);
353         else
354             ret |= test_contexts_digest(td->name);
355     }
356
357     if (ret)
358         printf(cDRED "= Some tests FAILED!" cNORM "\n");
359     else
360         printf(cDGREEN "= All tests passed!" cNORM "\n");
361     return ret;
362 }