]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - test_context.c
Always cNORM before "\n"
[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 #include <openssl/engine.h>
9 #include <openssl/evp.h>
10 #include <openssl/rand.h>
11 #include <openssl/err.h>
12 #include <openssl/asn1.h>
13 #include <string.h>
14 #ifndef EVP_MD_CTRL_SET_KEY
15 # include "gost_lcl.h"
16 #endif
17
18 #define T(e) if (!(e)) {\
19         ERR_print_errors_fp(stderr);\
20         OpenSSLDie(__FILE__, __LINE__, #e);\
21     }
22
23 #define cRED    "\033[1;31m"
24 #define cDRED   "\033[0;31m"
25 #define cGREEN  "\033[1;32m"
26 #define cDGREEN "\033[0;32m"
27 #define cBLUE   "\033[1;34m"
28 #define cDBLUE  "\033[0;34m"
29 #define cNORM   "\033[m"
30 #define TEST_ASSERT(e) {if ((test = (e))) \
31                  printf(cRED "  Test FAILED" cNORM "\n"); \
32              else \
33                  printf(cGREEN "  Test passed" cNORM "\n");}
34
35 static void hexdump(const void *ptr, size_t len)
36 {
37     const unsigned char *p = ptr;
38     size_t i, j;
39
40     for (i = 0; i < len; i += j) {
41         for (j = 0; j < 16 && i + j < len; j++)
42             printf("%s%02x", j? "" : " ", p[i + j]);
43     }
44     printf("\n");
45 }
46
47 #define TEST_SIZE 256
48 #define STEP_SIZE 16
49
50 static int test_contexts_cipher(int nid, const int enc, int acpkm)
51 {
52     EVP_CIPHER_CTX *ctx, *save;
53     unsigned char pt[TEST_SIZE] = {1};
54     unsigned char b[TEST_SIZE]; /* base output */
55     unsigned char c[TEST_SIZE]; /* cloned output */
56     unsigned char K[32] = {1};
57     unsigned char iv[16] = {1};
58     int outlen, tmplen;
59     int ret = 0, test = 0;
60
61     const EVP_CIPHER *type = EVP_get_cipherbynid(nid);
62     const char *name = EVP_CIPHER_name(type);
63
64     printf(cBLUE "%s test for %s (nid %d)" cNORM "\n",
65         enc ? "Encryption" : "Decryption", name, nid);
66
67     /* produce base encryption */
68     ctx = EVP_CIPHER_CTX_new();
69     T(ctx);
70     T(EVP_CipherInit_ex(ctx, type, NULL, K, iv, enc));
71     if (acpkm)
72         T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, acpkm, NULL));
73     T(EVP_CIPHER_CTX_set_padding(ctx, 0));
74     T(EVP_CipherUpdate(ctx, b, &outlen, pt, sizeof(b)));
75     T(EVP_CipherFinal_ex(ctx, b + outlen, &tmplen));
76
77     /* and now tests */
78     EVP_CIPHER_CTX_reset(ctx);
79     EVP_CIPHER_CTX_reset(ctx); /* double call is intentional */
80     T(EVP_CipherInit_ex(ctx, type, NULL, K, iv, enc));
81     T(EVP_CIPHER_CTX_set_padding(ctx, 0));
82     if (acpkm)
83         T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, acpkm, NULL));
84     save = ctx;
85
86     printf(" cloned contexts: ");
87     int i;
88     memset(c, 0, sizeof(c));
89     for (i = 0; i < TEST_SIZE / STEP_SIZE; i++) {
90         EVP_CIPHER_CTX *copy = EVP_CIPHER_CTX_new();
91         T(copy);
92         T(EVP_CIPHER_CTX_copy(copy, ctx));
93         if (save != ctx) /* else original context */
94             EVP_CIPHER_CTX_free(ctx);
95         ctx = copy;
96
97         T(EVP_CipherUpdate(ctx, c + STEP_SIZE * i, &outlen,
98                 pt + STEP_SIZE * i, STEP_SIZE));
99     }
100
101     outlen = i * STEP_SIZE;
102     T(EVP_CipherFinal_ex(ctx, c + outlen, &tmplen));
103     TEST_ASSERT(outlen != TEST_SIZE || memcmp(c, b, TEST_SIZE));
104     EVP_CIPHER_CTX_free(ctx);
105     if (test) {
106         printf("  b[%d] = ", outlen);
107         hexdump(b, outlen);
108         printf("  c[%d] = ", outlen);
109         hexdump(c, outlen);
110     }
111     ret |= test;
112
113     /* resume original context */
114     printf("    base context: ");
115     memset(c, 0, sizeof(c));
116     T(EVP_CipherUpdate(save, c, &outlen, pt, sizeof(c)));
117     T(EVP_CipherFinal_ex(save, c + outlen, &tmplen));
118     TEST_ASSERT(outlen != TEST_SIZE || memcmp(c, b, TEST_SIZE));
119     EVP_CIPHER_CTX_cleanup(save); /* multiple calls are intentional */
120     EVP_CIPHER_CTX_cleanup(save);
121     EVP_CIPHER_CTX_free(save);
122     if (test) {
123         printf("  b[%d] = ", outlen);
124         hexdump(b, outlen);
125         printf("  c[%d] = ", outlen);
126         hexdump(c, outlen);
127     }
128     ret |= test;
129
130     return ret;
131 }
132
133 static int test_contexts_digest(int nid, int mac)
134 {
135     int ret = 0, test = 0;
136     unsigned char K[32] = {1};
137     const EVP_MD *type = EVP_get_digestbynid(nid);
138     const char *name = EVP_MD_name(type);
139
140     printf(cBLUE "Digest test for %s (nid %d)" cNORM "\n", name, nid);
141
142     /* produce base digest */
143     EVP_MD_CTX *ctx, *save;
144     unsigned char pt[TEST_SIZE] = {1};
145     unsigned char b[EVP_MAX_MD_SIZE] = {0};
146     unsigned char c[EVP_MAX_MD_SIZE];
147     unsigned int outlen, tmplen;
148
149     /* Simply digest whole input. */
150     T(ctx = EVP_MD_CTX_new());
151     T(EVP_DigestInit_ex(ctx, type, NULL));
152     if (mac)
153         T(EVP_MD_CTX_ctrl(ctx, EVP_MD_CTRL_SET_KEY, sizeof(K), (void *)K));
154     T(EVP_DigestUpdate(ctx, pt, sizeof(pt)));
155     T(EVP_DigestFinal_ex(ctx, b, &tmplen));
156     save = ctx; /* will be not freed while cloning */
157
158     /* cloned digest */
159     EVP_MD_CTX_reset(ctx); /* test double reset */
160     EVP_MD_CTX_reset(ctx);
161     T(EVP_DigestInit_ex(ctx, type, NULL));
162     if (mac)
163         T(EVP_MD_CTX_ctrl(ctx, EVP_MD_CTRL_SET_KEY, sizeof(K), (void *)K));
164     printf(" cloned contexts: ");
165     memset(c, 0, sizeof(c));
166     int i;
167     for (i = 0; i < TEST_SIZE / STEP_SIZE; i++) {
168         /* Clone and continue digesting next part of input. */
169         EVP_MD_CTX *copy;
170         T(copy = EVP_MD_CTX_new());
171         T(EVP_MD_CTX_copy_ex(copy, ctx));
172
173         /* rolling */
174         if (save != ctx)
175             EVP_MD_CTX_free(ctx);
176         ctx = copy;
177
178         T(EVP_DigestUpdate(ctx, pt + STEP_SIZE * i, STEP_SIZE));
179     }
180     outlen = i * STEP_SIZE;
181     T(EVP_DigestFinal_ex(ctx, c, &tmplen));
182     /* Should be same as the simple digest. */
183     TEST_ASSERT(outlen != TEST_SIZE || memcmp(c, b, EVP_MAX_MD_SIZE));
184     EVP_MD_CTX_free(ctx);
185     if (test) {
186         printf("  b[%d] = ", outlen);
187         hexdump(b, outlen);
188         printf("  c[%d] = ", outlen);
189         hexdump(c, outlen);
190     }
191     ret |= test;
192
193     /* Resume original context, what if it's damaged? */
194     printf("    base context: ");
195     memset(c, 0, sizeof(c));
196     T(EVP_DigestUpdate(save, pt, sizeof(pt)));
197     T(EVP_DigestFinal_ex(save, c, &tmplen));
198     TEST_ASSERT(outlen != TEST_SIZE || memcmp(c, b, EVP_MAX_MD_SIZE));
199     EVP_MD_CTX_free(save);
200     if (test) {
201         printf("  b[%d] = ", outlen);
202         hexdump(b, outlen);
203         printf("  c[%d] = ", outlen);
204         hexdump(c, outlen);
205     }
206     ret |= test;
207
208     return ret;
209 }
210
211 static struct testcase_cipher {
212     int nid;
213     int acpkm;
214 } testcases_ciphers[] = {
215     { NID_id_Gost28147_89, },
216     { NID_gost89_cnt, },
217     { NID_gost89_cnt_12, },
218     { NID_gost89_cbc, },
219     { NID_grasshopper_ecb, },
220     { NID_grasshopper_cbc, },
221     { NID_grasshopper_cfb, },
222     { NID_grasshopper_ofb, },
223     { NID_grasshopper_ctr, },
224     { NID_magma_cbc, },
225     { NID_magma_ctr, },
226     { NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm, 256 / 8 },
227     { 0 },
228 };
229
230 static struct testcase_digest {
231     int nid;
232     int mac;
233 } testcases_digests[] = {
234     { NID_id_GostR3411_94, },
235     { NID_id_Gost28147_89_MAC, 1 },
236     { NID_id_GostR3411_2012_256, },
237     { NID_id_GostR3411_2012_512, },
238     { NID_gost_mac_12, 1 },
239     { NID_magma_mac, 1 },
240     { NID_grasshopper_mac, 1 },
241     { NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm_omac, 1 },
242     { 0 },
243 };
244 int main(int argc, char **argv)
245 {
246     int ret = 0;
247
248     setenv("OPENSSL_ENGINES", ENGINE_DIR, 0);
249     OPENSSL_add_all_algorithms_conf();
250     ERR_load_crypto_strings();
251     ENGINE *eng;
252     T(eng = ENGINE_by_id("gost"));
253     T(ENGINE_init(eng));
254     T(ENGINE_set_default(eng, ENGINE_METHOD_ALL));
255
256     const struct testcase_cipher *tc;
257     for (tc = testcases_ciphers; tc->nid; tc++) {
258         ret |= test_contexts_cipher(tc->nid, 1, tc->acpkm);
259         ret |= test_contexts_cipher(tc->nid, 0, tc->acpkm);
260     }
261     const struct testcase_digest *td;
262     for (td = testcases_digests; td->nid; td++) {
263         ret |= test_contexts_digest(td->nid, td->mac);
264     }
265
266     ENGINE_finish(eng);
267     ENGINE_free(eng);
268
269     if (ret)
270         printf(cDRED "= Some tests FAILED!" cNORM "\n");
271     else
272         printf(cDGREEN "= All tests passed!" cNORM "\n");
273     return ret;
274 }