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