2 * Test "Recommendations for standardization R 1323565.1.026 - 2019"
3 * authentivated encryption block cipher operation modes
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.
9 * Contents licensed under the terms of the OpenSSL license
10 * See https://www.openssl.org/source/license.html for details
13 #include <openssl/engine.h>
14 #include <openssl/evp.h>
17 #include "gost_grasshopper_cipher.h"
18 #include "gost_gost2015.h"
21 # define alloca _alloca
22 #elif defined __linux__
28 ERR_print_errors_fp(stderr);\
29 OpenSSLDie(__FILE__, __LINE__, #e);\
33 #define TEST_ASSERT(e) {if ((test = (e))) \
34 printf("Test FAILED\n"); \
36 printf("Test passed\n");}
39 /* MGM-Encrypt/MGM-decrypt test data from "R 1323565.1.026-2019" */
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,
46 const unsigned char gh_nonce[16] = {
47 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88
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
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,
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,
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
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
81 const unsigned char mg_nonce[8] = {
82 0x12, 0xDE, 0xF0, 0x6B, 0x3C, 0x13, 0x0A, 0x59
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
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,
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,
107 const unsigned char mg_e_tag[8] = {
108 0xa7, 0x92, 0x80, 0x69, 0xaa, 0x10, 0xfd, 0x10
112 static struct testcase {
114 const unsigned char *key;
115 const unsigned char *nonce;
117 const unsigned char *aad;
119 const unsigned char *plaintext;
121 const unsigned char *expected;
122 const unsigned char *expected_tag;
125 .sn = SN_kuznyechik_mgm,
128 .nonce_len = sizeof(gh_nonce),
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
140 .nonce_len = sizeof(mg_nonce),
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
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)
156 EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new();
157 unsigned char *c = alloca(plen);
159 unsigned char *t = alloca(tag_len);
160 int outlen1, outlen2, tmplen;
161 int ret = 0, rv, test, i;
164 printf("Encryption test %s [%s]: ", name, small ? "small chunks" : "big chunks");
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
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
178 outlen1 = outlen2 = 0;
180 for (i = 0; i < alen; i++) {
181 EVP_EncryptUpdate(ctx, NULL, &tmplen, aad + i, 1);
184 for (i = 0, p = c; i < plen; i++) {
185 EVP_EncryptUpdate(ctx, p, &tmplen, ptext + i, 1);
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);
194 TEST_ASSERT(outlen1 != alen || outlen2 != plen ||
195 memcmp(c, exp_ctext, plen) ||
196 memcmp(t, exp_tag, tag_len));
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);
209 EVP_DecryptUpdate(ctx, NULL, &outlen1, aad, alen);
210 EVP_DecryptUpdate(ctx, c, &outlen2, exp_ctext, plen);
213 outlen1 = outlen2 = 0;
215 for (i = 0; i < alen; i++) {
216 EVP_DecryptUpdate(ctx, NULL, &tmplen, aad + i, 1);
219 for (i = 0, p = c; i < plen; i++) {
220 EVP_DecryptUpdate(ctx, p, &tmplen, exp_ctext + i, 1);
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);
230 TEST_ASSERT(outlen1 != alen || outlen2 != plen ||
231 memcmp(c, ptext, plen) || rv != 1);
240 const struct testcase *t;
242 OPENSSL_add_all_algorithms_conf();
244 for (t = testcases; t->sn; t++) {
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;
251 printf("failed to load %s\n", t->sn);
254 name = EVP_CIPHER_name(ciph);
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);
265 printf("Some tests FAILED!\n");
267 printf("All tests passed!\n");