2 * Copyright (C) 2018,2020 Vitaly Chikunov <vt@altlinux.org> All Rights Reserved.
4 * Contents licensed under the terms of the OpenSSL license
5 * See https://www.openssl.org/source/license.html for details
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>
14 #ifndef EVP_MD_CTRL_SET_KEY
15 # include "gost_lcl.h"
18 #define T(e) if (!(e)) {\
19 ERR_print_errors_fp(stderr);\
20 OpenSSLDie(__FILE__, __LINE__, #e);\
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\n" cNORM); \
33 printf(cGREEN " Test passed\n" cNORM);}
35 static void hexdump(const void *ptr, size_t len)
37 const unsigned char *p = ptr;
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]);
50 static int test_contexts_cipher(int nid, const int enc, int acpkm)
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};
59 int ret = 0, test = 0;
61 const EVP_CIPHER *type = EVP_get_cipherbynid(nid);
62 const char *name = EVP_CIPHER_name(type);
64 printf(cBLUE "%s test for %s (nid %d)\n" cNORM,
65 enc ? "Encryption" : "Decryption", name, nid);
67 /* produce base encryption */
68 ctx = EVP_CIPHER_CTX_new();
70 T(EVP_CipherInit_ex(ctx, type, NULL, K, iv, enc));
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));
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));
83 T(EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_KEY_MESH, acpkm, NULL));
86 printf(" cloned contexts: ");
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();
92 T(EVP_CIPHER_CTX_copy(copy, ctx));
93 if (save != ctx) /* else original context */
94 EVP_CIPHER_CTX_free(ctx);
97 T(EVP_CipherUpdate(ctx, c + STEP_SIZE * i, &outlen,
98 pt + STEP_SIZE * i, STEP_SIZE));
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);
106 printf(" b[%d] = ", outlen);
108 printf(" c[%d] = ", outlen);
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);
123 printf(" b[%d] = ", outlen);
125 printf(" c[%d] = ", outlen);
133 static int test_contexts_digest(int nid, int mac)
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);
140 printf(cBLUE "Digest test for %s (nid %d)\n" cNORM, name, nid);
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;
149 /* Simply digest whole input. */
150 T(ctx = EVP_MD_CTX_new());
151 T(EVP_DigestInit_ex(ctx, type, NULL));
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 */
159 EVP_MD_CTX_reset(ctx); /* test double reset */
160 EVP_MD_CTX_reset(ctx);
161 T(EVP_DigestInit_ex(ctx, type, NULL));
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));
167 for (i = 0; i < TEST_SIZE / STEP_SIZE; i++) {
168 /* Clone and continue digesting next part of input. */
170 T(copy = EVP_MD_CTX_new());
171 T(EVP_MD_CTX_copy_ex(copy, ctx));
175 EVP_MD_CTX_free(ctx);
178 T(EVP_DigestUpdate(ctx, pt + STEP_SIZE * i, STEP_SIZE));
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);
186 printf(" b[%d] = ", outlen);
188 printf(" c[%d] = ", outlen);
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);
201 printf(" b[%d] = ", outlen);
203 printf(" c[%d] = ", outlen);
211 static struct testcase_cipher {
214 } testcases_ciphers[] = {
215 { NID_id_Gost28147_89, },
217 { NID_gost89_cnt_12, },
219 { NID_grasshopper_ecb, },
220 { NID_grasshopper_cbc, },
221 { NID_grasshopper_cfb, },
222 { NID_grasshopper_ofb, },
223 { NID_grasshopper_ctr, },
226 { NID_id_tc26_cipher_gostr3412_2015_kuznyechik_ctracpkm, 256 / 8 },
230 static struct testcase_digest {
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 },
244 int main(int argc, char **argv)
248 setenv("OPENSSL_ENGINES", ENGINE_DIR, 0);
249 OPENSSL_add_all_algorithms_conf();
250 ERR_load_crypto_strings();
252 T(eng = ENGINE_by_id("gost"));
254 T(ENGINE_set_default(eng, ENGINE_METHOD_ALL));
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);
261 const struct testcase_digest *td;
262 for (td = testcases_digests; td->nid; td++) {
263 ret |= test_contexts_digest(td->nid, td->mac);
270 printf(cDRED "= Some tests FAILED!\n" cNORM);
272 printf(cDGREEN "= All tests passed!\n" cNORM);