]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - test_mgm.c
tcl_tests: ca.try: Ignore openssl crl exit status for 'corrupted CRL' test
[openssl-gost/engine.git] / test_mgm.c
1 /*
2  * Test "Recommendations for standardization R 1323565.1.026 - 2019"
3  * authentivated encryption block cipher operation modes
4  *
5  * Copyright (C) 2019-2020 Vitaly Chikunov <vt@altlinux.org>. All Rights Reserved.
6  * Copyright (c) 2020-2021 JSC "NPK "Kryptonite" <i.kirillov@kryptonite.ru>.
7  * Code based on test_ciphers.c from master branch.
8  *
9  * Contents licensed under the terms of the OpenSSL license
10  * See https://www.openssl.org/source/license.html for details
11  */
12
13 #include <openssl/engine.h>
14 #include <openssl/evp.h>
15 #include <string.h>
16
17 #include "gost_grasshopper_cipher.h"
18 #include "gost_gost2015.h"
19 #if defined _MSC_VER
20 # include <malloc.h>
21 # define alloca _alloca
22 #elif defined __linux__
23 # include <alloca.h>
24 #endif
25
26 #define T(e) ({ \
27     if (!(e)) {\
28         ERR_print_errors_fp(stderr);\
29         OpenSSLDie(__FILE__, __LINE__, #e);\
30     } \
31 })
32
33 #define TEST_ASSERT(e) {if ((test = (e))) \
34                  printf("Test FAILED\n"); \
35              else \
36                  printf("Test passed\n");}
37
38
39 /* MGM-Encrypt/MGM-decrypt test data from "R 1323565.1.026-2019" */
40
41 const unsigned char gh_key[32] = {
42     0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
43     0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
44 };
45
46 const unsigned char gh_nonce[16] = {
47     0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88
48 };
49
50 const unsigned char gh_adata[41] = {
51     0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
52     0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
53     0xEA, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05
54 };
55
56 const unsigned char gh_pdata[67] = {
57     0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88,
58     0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xEE, 0xFF, 0x0A,
59     0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xEE, 0xFF, 0x0A, 0x00,
60     0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xEE, 0xFF, 0x0A, 0x00, 0x11,
61     0xAA, 0xBB, 0xCC
62 };
63
64 const unsigned char gh_e_cdata[67] = {
65     0xA9, 0x75, 0x7B, 0x81, 0x47, 0x95, 0x6E, 0x90, 0x55, 0xB8, 0xA3, 0x3D, 0xE8, 0x9F, 0x42, 0xFC,
66     0x80, 0x75, 0xD2, 0x21, 0x2B, 0xF9, 0xFD, 0x5B, 0xD3, 0xF7, 0x06, 0x9A, 0xAD, 0xC1, 0x6B, 0x39,
67     0x49, 0x7A, 0xB1, 0x59, 0x15, 0xA6, 0xBA, 0x85, 0x93, 0x6B, 0x5D, 0x0E, 0xA9, 0xF6, 0x85, 0x1C,
68     0xC6, 0x0C, 0x14, 0xD4, 0xD3, 0xF8, 0x83, 0xD0, 0xAB, 0x94, 0x42, 0x06, 0x95, 0xC7, 0x6D, 0xEB,
69     0x2C, 0x75, 0x52
70 };
71
72 const unsigned char gh_e_tag[16] = {
73     0xCF, 0x5D, 0x65, 0x6F, 0x40, 0xC3, 0x4F, 0x5C, 0x46, 0xE8, 0xBB, 0x0E, 0x29, 0xFC, 0xDB, 0x4C
74 };
75
76 const unsigned char mg_key[32] = {
77     0xFF, 0xee, 0xDD, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x77, 0x66, 0x55, 0x44, 0x33, 0x22, 0x11, 0x00,
78     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xff
79 };
80
81 const unsigned char mg_nonce[8] = {
82     0x12, 0xDE, 0xF0, 0x6B, 0x3C, 0x13, 0x0A, 0x59
83 };
84
85 const unsigned char mg_adata[41] = {
86     0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
87     0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
88     0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0xea
89 };
90
91 const unsigned char mg_pdata[67] = {
92     0xFF, 0xee, 0xDD, 0xcc, 0xbb, 0xaa, 0x99, 0x88, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00,
93     0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xee, 0xFF, 0x0A, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
94     0x99, 0xaa, 0xbb, 0xcc, 0xee, 0xFF, 0x0a, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88,
95     0xaa, 0xbb, 0xcc, 0xee, 0xFF, 0x0a, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99,
96     0xaa, 0xbb, 0xcc
97 };
98
99 const unsigned char mg_e_cdata[67] = {
100     0xc7, 0x95, 0x06, 0x6c, 0x5f, 0x9e, 0xa0, 0x3b, 0x85, 0x11, 0x33, 0x42, 0x45, 0x91, 0x85, 0xae,
101     0x1f, 0x2e, 0x00, 0xd6, 0xbf, 0x2b, 0x78, 0x5d, 0x94, 0x04, 0x70, 0xb8, 0xbb, 0x9c, 0x8e, 0x7d,
102     0x9a, 0x5d, 0xd3, 0x73, 0x1f, 0x7d, 0xdc, 0x70, 0xec, 0x27, 0xcb, 0x0a, 0xce, 0x6f, 0xa5, 0x76,
103     0x70, 0xf6, 0x5c, 0x64, 0x6a, 0xbb, 0x75, 0xd5, 0x47, 0xaa, 0x37, 0xc3, 0xbc, 0xb5, 0xc3, 0x4e,
104     0x03, 0xbb, 0x9c
105 };
106
107 const unsigned char mg_e_tag[8] = {
108     0xa7, 0x92, 0x80, 0x69, 0xaa, 0x10, 0xfd, 0x10
109 };
110
111
112 static struct testcase {
113     const char *sn;
114     const unsigned char *key;
115     const unsigned char *nonce;
116     size_t nonce_len;
117     const unsigned char *aad;
118     size_t aad_len;
119     const unsigned char *plaintext;
120     size_t ptext_len;
121     const unsigned char *expected;
122     const unsigned char *expected_tag;
123 } testcases[] = {
124     {
125         .sn = SN_kuznyechik_mgm,
126         .key = gh_key,
127         .nonce = gh_nonce,
128         .nonce_len = sizeof(gh_nonce),
129         .aad = gh_adata,
130         .aad_len = sizeof(gh_adata),
131         .plaintext = gh_pdata,
132         .ptext_len = sizeof(gh_pdata),
133         .expected = gh_e_cdata,
134         .expected_tag = gh_e_tag
135     },
136     {
137         .sn = SN_magma_mgm,
138         .key = mg_key,
139         .nonce = mg_nonce,
140         .nonce_len = sizeof(mg_nonce),
141         .aad = mg_adata,
142         .aad_len = sizeof(mg_adata),
143         .plaintext = mg_pdata,
144         .ptext_len = sizeof(mg_pdata),
145         .expected = mg_e_cdata,
146         .expected_tag = mg_e_tag
147     },
148     { 0 }
149 };
150
151 static int test_block(const EVP_CIPHER *ciph, const char *name, const unsigned char *nonce, size_t nlen,
152                       const unsigned char *aad, size_t alen, const unsigned char *ptext, size_t plen,
153                       const unsigned char *exp_ctext, const unsigned char *exp_tag,
154                       const unsigned char * key, int small)
155 {
156     EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
157     unsigned char *c = alloca(plen);
158     int tag_len = nlen;
159     unsigned char *t = alloca(tag_len);
160     int outlen1, outlen2, tmplen;
161     int ret = 0, rv, test, i;
162
163     OPENSSL_assert(ctx);
164     printf("Encryption test %s [%s]: ", name, small ? "small chunks" : "big chunks");
165
166     // test encrypt
167     EVP_CIPHER_CTX_init(ctx);
168     EVP_EncryptInit_ex(ctx, ciph, NULL, NULL, NULL);                    // Set cipher type and mode
169     EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, nlen, NULL);      // Set IV length
170     EVP_EncryptInit_ex(ctx, NULL, NULL, key, nonce);                    // Initialise key and IV
171     memset(c, 0, plen);
172     if (!small) {
173         // test big chunks
174         EVP_EncryptUpdate(ctx, NULL, &outlen1, aad, alen);              // Zero or more calls to specify any AAD
175         EVP_EncryptUpdate(ctx, c, &outlen2, ptext, plen);               // Encrypt plaintext
176     } else {
177         // test small chunks
178         outlen1 = outlen2 = 0;
179         unsigned char *p;
180         for (i = 0; i < alen; i++) {
181             EVP_EncryptUpdate(ctx, NULL, &tmplen, aad + i, 1);
182             outlen1 += tmplen;
183         }
184         for (i = 0, p = c; i < plen; i++) {
185             EVP_EncryptUpdate(ctx, p, &tmplen, ptext + i, 1);
186             p += tmplen;
187             outlen2 += tmplen;
188         }
189     }
190     EVP_EncryptFinal_ex(ctx, c, &tmplen);
191     EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_GET_TAG, tag_len, t);
192     EVP_CIPHER_CTX_cleanup(ctx);
193
194     TEST_ASSERT(outlen1 != alen || outlen2 != plen ||
195                 memcmp(c, exp_ctext, plen) ||
196                 memcmp(t, exp_tag, tag_len));
197     ret |= test;
198
199
200     // test decrtypt
201     printf("Decryption test %s [%s]: ", name, small ? "small chunks" : "big chunks");
202     EVP_CIPHER_CTX_init(ctx);
203     EVP_DecryptInit_ex(ctx, ciph, NULL, NULL, NULL);
204     EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_IVLEN, nlen, NULL);
205     EVP_DecryptInit_ex(ctx, NULL, NULL, key, nonce);
206     memset(c, 0, plen);
207     if (!small) {
208         // test big chunks
209         EVP_DecryptUpdate(ctx, NULL, &outlen1, aad, alen);
210         EVP_DecryptUpdate(ctx, c, &outlen2, exp_ctext, plen);
211     } else {
212         // test small chunks
213         outlen1 = outlen2 = 0;
214         unsigned char *p;
215         for (i = 0; i < alen; i++) {
216             EVP_DecryptUpdate(ctx, NULL, &tmplen, aad + i, 1);
217             outlen1 += tmplen;
218         }
219         for (i = 0, p = c; i < plen; i++) {
220             EVP_DecryptUpdate(ctx, p, &tmplen, exp_ctext + i, 1);
221             p += tmplen;
222             outlen2 += tmplen;
223         }
224     }
225     EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_AEAD_SET_TAG, tag_len, (void *)exp_tag);
226     rv = EVP_DecryptFinal_ex(ctx, c, &tmplen);
227     EVP_CIPHER_CTX_cleanup(ctx);
228     EVP_CIPHER_CTX_free(ctx);
229
230     TEST_ASSERT(outlen1 != alen || outlen2 != plen ||
231                 memcmp(c, ptext, plen) || rv != 1);
232     ret |= test;
233
234     return ret;
235 }
236
237 int main(void)
238 {
239     int ret = 0;
240     const struct testcase *t;
241
242     OPENSSL_add_all_algorithms_conf();
243
244     for (t = testcases; t->sn; t++) {
245         int small;
246         const EVP_CIPHER *ciph_eng = EVP_get_cipherbyname(t->sn);
247         EVP_CIPHER *ciph_prov = EVP_CIPHER_fetch(NULL, t->sn, NULL);
248         const EVP_CIPHER *ciph = ciph_eng ? ciph_eng : ciph_prov;
249         const char *name;
250         if (!ciph) {
251             printf("failed to load %s\n", t->sn);
252             return 1;
253         }
254         name = EVP_CIPHER_name(ciph);
255
256         printf("Tests for %s\n", name);
257         for (small = 0; small <= 1; small++)
258             ret |= test_block(ciph, name, t->nonce, t->nonce_len,
259                               t->aad, t->aad_len, t->plaintext, t->ptext_len,
260                               t->expected, t->expected_tag, t->key, small);
261         EVP_CIPHER_free(ciph_prov);
262     }
263
264     if (ret) {
265         printf("Some tests FAILED!\n");
266     } else {
267         printf("All tests passed!\n");
268     }
269     return ret;
270 }