]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - test_mgm.c
Decryption tests + formatting
[openssl-gost/engine.git] / test_mgm.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <openssl/err.h>
4 #include <openssl/evp.h>
5 #include <openssl/buffer.h>
6 #include <byteswap.h>
7
8 const unsigned char gh_key[] = {
9     0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33,
10         0x44, 0x55, 0x66, 0x77,
11     0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67,
12         0x89, 0xAB, 0xCD, 0xEF,
13 };
14
15 const unsigned char gh_nonce[] = {
16     0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, 0xFF, 0xEE, 0xDD, 0xCC,
17         0xBB, 0xAA, 0x99, 0x88
18 };
19
20 const unsigned char gh_adata[] = {
21     0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
22         0x01, 0x01, 0x01, 0x01,
23     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03,
24         0x03, 0x03, 0x03, 0x03,
25     0xEA, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05
26 };
27
28 const unsigned char gh_pdata[] = {
29     0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, 0xFF, 0xEE, 0xDD, 0xCC,
30         0xBB, 0xAA, 0x99, 0x88,
31     0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB,
32         0xCC, 0xEE, 0xFF, 0x0A,
33     0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC,
34         0xEE, 0xFF, 0x0A, 0x00,
35     0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xEE,
36         0xFF, 0x0A, 0x00, 0x11,
37     0xAA, 0xBB, 0xCC
38 };
39
40 const unsigned char etalon_cdata[] = {
41     0xA9, 0x75, 0x7B, 0x81, 0x47, 0x95, 0x6E, 0x90, 0x55, 0xB8, 0xA3, 0x3D,
42         0xE8, 0x9F, 0x42, 0xFC,
43     0x80, 0x75, 0xD2, 0x21, 0x2B, 0xF9, 0xFD, 0x5B, 0xD3, 0xF7, 0x06, 0x9A,
44         0xAD, 0xC1, 0x6B, 0x39,
45     0x49, 0x7A, 0xB1, 0x59, 0x15, 0xA6, 0xBA, 0x85, 0x93, 0x6B, 0x5D, 0x0E,
46         0xA9, 0xF6, 0x85, 0x1C,
47     0xC6, 0x0C, 0x14, 0xD4, 0xD3, 0xF8, 0x83, 0xD0, 0xAB, 0x94, 0x42, 0x06,
48         0x95, 0xC7, 0x6D, 0xEB,
49     0x2C, 0x75, 0x52
50 };
51
52 const unsigned char etalon_tag[] = {
53     0xCF, 0x5D, 0x65, 0x6F, 0x40, 0xC3, 0x4F, 0x5C, 0x46, 0xE8, 0xBB, 0x0E,
54         0x29, 0xFC, 0xDB, 0x4C
55 };
56
57 static void hexdump(FILE *f, const char *title, const unsigned char *s, int l)
58 {
59     int n = 0;
60
61     fprintf(f, "%s", title);
62     for (; n < l; ++n) {
63         if ((n % 16) == 0)
64             fprintf(f, "\n%04x", n);
65         fprintf(f, " %02x", s[n]);
66     }
67     fprintf(f, "\n");
68 }
69
70 void grasshopper_enc_mgm_big(const EVP_CIPHER *ciph)
71 {
72     unsigned char tag[16];
73     unsigned char gh_cdata[sizeof(gh_pdata)];
74     unsigned char *pcdata = gh_cdata;
75
76     int asize = sizeof(gh_adata);
77     int psize = sizeof(gh_pdata);
78     int fsize = 0;
79
80     EVP_CIPHER_CTX *enc = NULL;
81
82     int i;
83
84     enc = EVP_CIPHER_CTX_new();
85     EVP_EncryptInit_ex(enc, ciph, NULL, gh_key, gh_nonce);
86
87     EVP_EncryptUpdate(enc, NULL, &asize, gh_adata, sizeof(gh_adata));
88     EVP_EncryptUpdate(enc, gh_cdata, &psize, gh_pdata, sizeof(gh_pdata));
89     EVP_EncryptFinal_ex(enc, NULL, &fsize);
90
91     EVP_CIPHER_CTX_ctrl(enc, EVP_CTRL_AEAD_GET_TAG, 16, tag);
92
93     if (memcmp(etalon_cdata, gh_cdata, sizeof(gh_cdata))) {
94         fprintf(stderr, "Shit happens - encryption!\n");
95         hexdump(stderr, "Etalon cdata", etalon_cdata, sizeof(etalon_cdata));
96         hexdump(stderr, "Got cdata", gh_cdata, sizeof(gh_cdata));
97         return;
98     }
99
100     if (memcmp(tag, etalon_tag, 16)) {
101         fprintf(stderr, "Shit happens!\n");
102         hexdump(stderr, "Etalon tag", etalon_tag, 16);
103         hexdump(stderr, "Got tag", tag, 16);
104         return;
105     }
106     fprintf(stderr, "OK encryption - big chunks!\n");
107     EVP_CIPHER_CTX_free(enc);
108 }
109
110 void grasshopper_enc_mgm_small(const EVP_CIPHER *ciph)
111 {
112     unsigned char tag[16];
113     unsigned char gh_cdata[sizeof(gh_pdata)];
114     unsigned char *pcdata = gh_cdata;
115
116     int asize = sizeof(gh_adata);
117     int psize = sizeof(gh_pdata);
118     int fsize = 0;
119
120     EVP_CIPHER_CTX *enc = NULL;
121
122     int i;
123
124     enc = EVP_CIPHER_CTX_new();
125     EVP_EncryptInit_ex(enc, ciph, NULL, gh_key, gh_nonce);
126     for (i = 0; i < sizeof(gh_adata); i++) {
127         asize = 1;
128         EVP_EncryptUpdate(enc, NULL, &asize, gh_adata + i, 1);
129     }
130     for (i = 0; i < sizeof(gh_pdata); i++) {
131         psize = 1;
132         EVP_EncryptUpdate(enc, pcdata, &psize, gh_pdata + i, 1);
133         pcdata += psize;
134     }
135
136     EVP_EncryptFinal_ex(enc, NULL, &fsize);
137
138     EVP_CIPHER_CTX_ctrl(enc, EVP_CTRL_AEAD_GET_TAG, 16, tag);
139
140     if (memcmp(etalon_cdata, gh_cdata, sizeof(gh_cdata))) {
141         fprintf(stderr, "Shit happens - encryption!\n");
142         hexdump(stderr, "Etalon cdata", etalon_cdata, sizeof(etalon_cdata));
143         hexdump(stderr, "Got cdata", gh_cdata, sizeof(gh_cdata));
144         return;
145     }
146
147     if (memcmp(tag, etalon_tag, 16)) {
148         fprintf(stderr, "Shit happens!\n");
149         hexdump(stderr, "Etalon tag", etalon_tag, 16);
150         hexdump(stderr, "Got tag", tag, 16);
151         return;
152     }
153     fprintf(stderr, "OK encryption - small chunks!\n");
154     EVP_CIPHER_CTX_free(enc);
155
156 }
157
158 #define L_ENDIAN 1
159 static void gf128_mul_uint64(uint64_t *z, uint64_t *x, uint64_t *y)
160 {
161     int i = 0, n = 0;
162     uint64_t t, s0, s1;
163
164     BUF_reverse((unsigned char *)x, NULL, 16);
165     BUF_reverse((unsigned char *)y, NULL, 16);
166
167 #ifdef L_ENDIAN
168     s0 = x[0];
169     s1 = x[1];
170 #else
171     s0 = bswap_64(x[0]);
172     s1 = bswap_64(x[1]);
173 #endif
174
175     memset(z, 0, sizeof(uint64_t) * 2);
176
177     /* lower half */
178 #ifdef L_ENDIAN
179     t = y[0];
180 #else
181     t = bswap_64(y[0]);
182 #endif
183
184     for (i = 0; i < 64; i++) {
185         if (t & 0x1) {
186             z[0] ^= s0;
187             z[1] ^= s1;
188         }
189         t >>= 1;
190         n = s1 >> 63;
191         s1 <<= 1;
192         s1 ^= (s0 >> 63);
193         s0 <<= 1;
194         if (n)
195             s0 ^= 0x87;
196     }
197
198     /* upper half */
199 #ifdef L_ENDIAN
200     t = y[1];
201 #else
202     t = bswap_64(y[1]);
203 #endif
204
205     for (i = 0; i < 63; i++) {
206         if (t & 0x1) {
207             z[0] ^= s0;
208             z[1] ^= s1;
209         }
210         t >>= 1;
211         n = s1 >> 63;
212         s1 <<= 1;
213         s1 ^= (s0 >> 63);
214         s0 <<= 1;
215         if (n)
216             s0 ^= 0x87;
217     }
218
219     if (t & 0x1) {
220         z[0] ^= s0;
221         z[1] ^= s1;
222     }
223 #ifndef L_ENDIAN
224     z[0] = bswap_64(z[0]);
225     z[1] = bswap_64(z[1]);
226 #endif
227     BUF_reverse((unsigned char *)z, NULL, 16);
228 }
229
230 void gf_mul(void)
231 {
232     unsigned char H[16] = {
233         0x8D, 0xB1, 0x87, 0xD6, 0x53, 0x83, 0x0E, 0xA4, 0xBC, 0x44, 0x64, 0x76,
234             0x95, 0x2C, 0x30, 0x0B
235     };
236
237     unsigned char A[16] = {
238         0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
239             0x01, 0x01, 0x01, 0x01
240     };
241
242     unsigned char etalon[16] = {
243         0x4C, 0xF4, 0x27, 0xF4, 0xAD, 0xB7, 0x5C, 0xF4, 0xC0, 0xDA, 0x39, 0xD5,
244             0xAB, 0x48, 0xCF, 0x38
245     };
246
247     unsigned char result_bd[16];
248     gf128_mul_uint64((uint64_t *)result_bd, (uint64_t *)H, (uint64_t *)A);
249
250     hexdump(stderr, "Etalon", etalon, 16);
251
252     if (memcmp(etalon, result_bd, 16)) {
253         fprintf(stderr, "Shit happens - BD!\n");
254         hexdump(stderr, "Result - BD", result_bd, 16);
255     } else
256         fprintf(stderr, "OK - BD!\n");
257
258     return;
259 }
260
261 void grasshopper_dec_mgm_big(const EVP_CIPHER *ciph)
262 {
263     unsigned char tag[16];
264     unsigned char gh_cdata[sizeof(gh_pdata)];
265     unsigned char *pcdata = gh_cdata;
266
267     int asize = sizeof(gh_adata);
268     int psize = sizeof(gh_pdata);
269     int fsize = 0;
270
271     EVP_CIPHER_CTX *enc = NULL;
272
273     int i;
274
275     memcpy(tag, etalon_tag, 16);
276
277     enc = EVP_CIPHER_CTX_new();
278     EVP_DecryptInit_ex(enc, ciph, NULL, gh_key, gh_nonce);
279     EVP_CIPHER_CTX_ctrl(enc, EVP_CTRL_AEAD_SET_TAG, 16, tag);
280
281     EVP_DecryptUpdate(enc, NULL, &asize, gh_adata, sizeof(gh_adata));
282     EVP_DecryptUpdate(enc, gh_cdata, &psize, etalon_cdata,
283                       sizeof(etalon_cdata));
284
285     if (EVP_DecryptFinal_ex(enc, NULL, &fsize) <= 0) {
286         fprintf(stderr, "Shit happens - bad tag!\n");
287         return;
288     }
289
290     if (memcmp(gh_pdata, gh_cdata, sizeof(gh_cdata))) {
291         fprintf(stderr, "Shit happens - decryption!\n");
292         hexdump(stderr, "Etalon cdata", gh_pdata, sizeof(gh_pdata));
293         hexdump(stderr, "Got cdata", gh_cdata, sizeof(gh_cdata));
294         return;
295     }
296
297     fprintf(stderr, "OK decryption - big chunks!\n");
298     EVP_CIPHER_CTX_free(enc);
299 }
300
301 void grasshopper_dec_mgm_small(const EVP_CIPHER *ciph)
302 {
303     unsigned char tag[16];
304     unsigned char gh_cdata[sizeof(gh_pdata)];
305     unsigned char *pcdata = gh_cdata;
306
307     int asize = sizeof(gh_adata);
308     int psize = sizeof(gh_pdata);
309     int fsize = 0;
310
311     EVP_CIPHER_CTX *enc = NULL;
312
313     int i;
314
315     memcpy(tag, etalon_tag, 16);
316
317     enc = EVP_CIPHER_CTX_new();
318     EVP_DecryptInit_ex(enc, ciph, NULL, gh_key, gh_nonce);
319     EVP_CIPHER_CTX_ctrl(enc, EVP_CTRL_AEAD_SET_TAG, 16, tag);
320
321     for (i = 0; i < sizeof(gh_adata); i++) {
322         asize = 1;
323         EVP_DecryptUpdate(enc, NULL, &asize, gh_adata + i, 1);
324     }
325     for (i = 0; i < sizeof(gh_pdata); i++) {
326         psize = 1;
327         EVP_DecryptUpdate(enc, pcdata, &psize, etalon_cdata + i, 1);
328         pcdata += psize;
329     }
330
331     if (EVP_DecryptFinal_ex(enc, NULL, &fsize) <= 0) {
332         fprintf(stderr, "Shit happens - bad tag!\n");
333         return;
334     }
335
336     if (memcmp(gh_pdata, gh_cdata, sizeof(gh_cdata))) {
337         fprintf(stderr, "Shit happens - decryption!\n");
338         hexdump(stderr, "Etalon cdata", gh_pdata, sizeof(gh_pdata));
339         hexdump(stderr, "Got cdata", gh_cdata, sizeof(gh_cdata));
340         return;
341     }
342
343     fprintf(stderr, "OK decryption - small chunks!\n");
344     EVP_CIPHER_CTX_free(enc);
345 }
346
347 int main(void)
348 {
349     OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
350
351     const EVP_CIPHER *ciph;
352     ciph = EVP_get_cipherbynid(NID_kuznyechik_mgm);
353     if (ciph == NULL) {
354         fprintf(stderr, "Could not obtain cipher");
355         exit(1);
356     }
357 //      gf_mul();
358     grasshopper_enc_mgm_big(ciph);
359     grasshopper_enc_mgm_small(ciph);
360     grasshopper_dec_mgm_big(ciph);
361     grasshopper_dec_mgm_small(ciph);
362     ERR_print_errors_fp(stderr);
363
364     return 0;
365 }