3 #include <openssl/err.h>
4 #include <openssl/evp.h>
5 #include <openssl/buffer.h>
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,
15 const unsigned char gh_nonce[] = {
16 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, 0xFF, 0xEE, 0xDD, 0xCC,
17 0xBB, 0xAA, 0x99, 0x88
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
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,
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,
52 const unsigned char etalon_tag[] = {
53 0xCF, 0x5D, 0x65, 0x6F, 0x40, 0xC3, 0x4F, 0x5C, 0x46, 0xE8, 0xBB, 0x0E,
54 0x29, 0xFC, 0xDB, 0x4C
57 static void hexdump(FILE *f, const char *title, const unsigned char *s, int l)
61 fprintf(f, "%s", title);
64 fprintf(f, "\n%04x", n);
65 fprintf(f, " %02x", s[n]);
70 void grasshopper_enc_mgm_big(const EVP_CIPHER *ciph)
72 unsigned char tag[16];
73 unsigned char gh_cdata[sizeof(gh_pdata)];
74 unsigned char *pcdata = gh_cdata;
76 int asize = sizeof(gh_adata);
77 int psize = sizeof(gh_pdata);
80 EVP_CIPHER_CTX *enc = NULL;
84 enc = EVP_CIPHER_CTX_new();
85 EVP_EncryptInit_ex(enc, ciph, NULL, gh_key, gh_nonce);
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);
91 EVP_CIPHER_CTX_ctrl(enc, EVP_CTRL_AEAD_GET_TAG, 16, tag);
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));
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);
106 fprintf(stderr, "OK encryption - big chunks!\n");
107 EVP_CIPHER_CTX_free(enc);
110 void grasshopper_enc_mgm_small(const EVP_CIPHER *ciph)
112 unsigned char tag[16];
113 unsigned char gh_cdata[sizeof(gh_pdata)];
114 unsigned char *pcdata = gh_cdata;
116 int asize = sizeof(gh_adata);
117 int psize = sizeof(gh_pdata);
120 EVP_CIPHER_CTX *enc = NULL;
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++) {
128 EVP_EncryptUpdate(enc, NULL, &asize, gh_adata + i, 1);
130 for (i = 0; i < sizeof(gh_pdata); i++) {
132 EVP_EncryptUpdate(enc, pcdata, &psize, gh_pdata + i, 1);
136 EVP_EncryptFinal_ex(enc, NULL, &fsize);
138 EVP_CIPHER_CTX_ctrl(enc, EVP_CTRL_AEAD_GET_TAG, 16, tag);
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));
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);
153 fprintf(stderr, "OK encryption - small chunks!\n");
154 EVP_CIPHER_CTX_free(enc);
159 static void gf128_mul_uint64(uint64_t *z, uint64_t *x, uint64_t *y)
164 BUF_reverse((unsigned char *)x, NULL, 16);
165 BUF_reverse((unsigned char *)y, NULL, 16);
175 memset(z, 0, sizeof(uint64_t) * 2);
184 for (i = 0; i < 64; i++) {
205 for (i = 0; i < 63; i++) {
224 z[0] = bswap_64(z[0]);
225 z[1] = bswap_64(z[1]);
227 BUF_reverse((unsigned char *)z, NULL, 16);
232 unsigned char H[16] = {
233 0x8D, 0xB1, 0x87, 0xD6, 0x53, 0x83, 0x0E, 0xA4, 0xBC, 0x44, 0x64, 0x76,
234 0x95, 0x2C, 0x30, 0x0B
237 unsigned char A[16] = {
238 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
239 0x01, 0x01, 0x01, 0x01
242 unsigned char etalon[16] = {
243 0x4C, 0xF4, 0x27, 0xF4, 0xAD, 0xB7, 0x5C, 0xF4, 0xC0, 0xDA, 0x39, 0xD5,
244 0xAB, 0x48, 0xCF, 0x38
247 unsigned char result_bd[16];
248 gf128_mul_uint64((uint64_t *)result_bd, (uint64_t *)H, (uint64_t *)A);
250 hexdump(stderr, "Etalon", etalon, 16);
252 if (memcmp(etalon, result_bd, 16)) {
253 fprintf(stderr, "Shit happens - BD!\n");
254 hexdump(stderr, "Result - BD", result_bd, 16);
256 fprintf(stderr, "OK - BD!\n");
261 void grasshopper_dec_mgm_big(const EVP_CIPHER *ciph)
263 unsigned char tag[16];
264 unsigned char gh_cdata[sizeof(gh_pdata)];
265 unsigned char *pcdata = gh_cdata;
267 int asize = sizeof(gh_adata);
268 int psize = sizeof(gh_pdata);
271 EVP_CIPHER_CTX *enc = NULL;
275 memcpy(tag, etalon_tag, 16);
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);
281 EVP_DecryptUpdate(enc, NULL, &asize, gh_adata, sizeof(gh_adata));
282 EVP_DecryptUpdate(enc, gh_cdata, &psize, etalon_cdata,
283 sizeof(etalon_cdata));
285 if (EVP_DecryptFinal_ex(enc, NULL, &fsize) <= 0) {
286 fprintf(stderr, "Shit happens - bad tag!\n");
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));
297 fprintf(stderr, "OK decryption - big chunks!\n");
298 EVP_CIPHER_CTX_free(enc);
301 void grasshopper_dec_mgm_small(const EVP_CIPHER *ciph)
303 unsigned char tag[16];
304 unsigned char gh_cdata[sizeof(gh_pdata)];
305 unsigned char *pcdata = gh_cdata;
307 int asize = sizeof(gh_adata);
308 int psize = sizeof(gh_pdata);
311 EVP_CIPHER_CTX *enc = NULL;
315 memcpy(tag, etalon_tag, 16);
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);
321 for (i = 0; i < sizeof(gh_adata); i++) {
323 EVP_DecryptUpdate(enc, NULL, &asize, gh_adata + i, 1);
325 for (i = 0; i < sizeof(gh_pdata); i++) {
327 EVP_DecryptUpdate(enc, pcdata, &psize, etalon_cdata + i, 1);
331 if (EVP_DecryptFinal_ex(enc, NULL, &fsize) <= 0) {
332 fprintf(stderr, "Shit happens - bad tag!\n");
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));
343 fprintf(stderr, "OK decryption - small chunks!\n");
344 EVP_CIPHER_CTX_free(enc);
349 OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
351 const EVP_CIPHER *ciph;
352 ciph = EVP_get_cipherbynid(NID_kuznyechik_mgm);
354 fprintf(stderr, "Could not obtain cipher");
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);