3 # include <openssl/err.h>
4 # include <openssl/evp.h>
5 #include <openssl/buffer.h>
8 static void hexdump(FILE *f, const char *title, const unsigned char *s, int l)
12 fprintf(f, "%s", title);
15 fprintf(f, "\n%04x", n);
16 fprintf(f, " %02x", s[n]);
21 void grasshopper_mgm_big()
23 const unsigned char gh_key[] = {
24 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
25 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
28 const unsigned char gh_nonce[] = {
29 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88
32 const unsigned char gh_adata[] = {
33 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
34 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
35 0xEA, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05
38 const unsigned char gh_pdata[] = {
39 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88,
40 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xEE, 0xFF, 0x0A,
41 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xEE, 0xFF, 0x0A, 0x00,
42 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xEE, 0xFF, 0x0A, 0x00, 0x11,
46 const unsigned char etalon_tag[] = {
47 0xCF, 0x5D, 0x65, 0x6F, 0x40, 0xC3, 0x4F, 0x5C, 0x46, 0xE8, 0xBB, 0x0E, 0x29, 0xFC, 0xDB, 0x4C
50 unsigned char tag[16];
51 unsigned char gh_cdata[sizeof(gh_pdata)];
52 unsigned char *pcdata = gh_cdata;
54 int asize = sizeof(gh_adata);
55 int psize = sizeof(gh_pdata);
58 const EVP_CIPHER *ciph;
59 EVP_CIPHER_CTX *enc = NULL;
63 ciph = EVP_get_cipherbynid(NID_kuznyechik_mgm);
65 fprintf(stderr, "Could not obtain cipher");
69 enc = EVP_CIPHER_CTX_new();
70 EVP_EncryptInit_ex(enc, ciph, NULL, gh_key, gh_nonce);
72 EVP_EncryptUpdate(enc, NULL, &asize, gh_adata, sizeof(gh_adata));
73 EVP_EncryptUpdate(enc, gh_cdata, &psize, gh_pdata, sizeof(gh_pdata));
74 EVP_EncryptFinal_ex(enc, NULL, &fsize);
76 EVP_CIPHER_CTX_ctrl(enc, EVP_CTRL_AEAD_GET_TAG, 16, tag);
78 if (memcmp (tag, etalon_tag, 16)) {
79 fprintf(stderr, "Shit happens!\n");
80 hexdump(stderr, "Etalon tag", etalon_tag, 16);
81 hexdump(stderr, "Got tag", tag, 16);
84 fprintf(stderr, "OK - big chunks!\n");
85 EVP_CIPHER_CTX_free(enc);
87 fprintf(stderr, "================ \n");
90 void grasshopper_mgm_small()
92 const unsigned char gh_key[] = {
93 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
94 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10, 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF,
97 const unsigned char gh_nonce[] = {
98 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88
101 const unsigned char gh_adata[] = {
102 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
103 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
104 0xEA, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05
107 const unsigned char gh_pdata[] = {
108 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x00, 0xFF, 0xEE, 0xDD, 0xCC, 0xBB, 0xAA, 0x99, 0x88,
109 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xEE, 0xFF, 0x0A,
110 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xEE, 0xFF, 0x0A, 0x00,
111 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xEE, 0xFF, 0x0A, 0x00, 0x11,
115 const unsigned char etalon_tag[] = {
116 0xCF, 0x5D, 0x65, 0x6F, 0x40, 0xC3, 0x4F, 0x5C, 0x46, 0xE8, 0xBB, 0x0E, 0x29, 0xFC, 0xDB, 0x4C
119 unsigned char tag[16];
120 unsigned char gh_cdata[sizeof(gh_pdata)];
121 unsigned char *pcdata = gh_cdata;
123 int asize = sizeof(gh_adata);
124 int psize = sizeof(gh_pdata);
127 const EVP_CIPHER *ciph;
128 EVP_CIPHER_CTX *enc = NULL;
132 ciph = EVP_get_cipherbynid(NID_kuznyechik_mgm);
134 fprintf(stderr, "Could not obtain cipher");
138 enc = EVP_CIPHER_CTX_new();
139 EVP_EncryptInit_ex(enc, ciph, NULL, gh_key, gh_nonce);
141 for (i = 0; i < sizeof(gh_adata); i++)
144 EVP_EncryptUpdate(enc, NULL, &asize, gh_adata+i, 1);
147 for (i = 0; i < sizeof(gh_pdata); i++)
150 EVP_EncryptUpdate(enc, pcdata, &psize, gh_pdata+i, 1);
154 EVP_EncryptFinal_ex(enc, NULL, &fsize);
156 EVP_CIPHER_CTX_ctrl(enc, EVP_CTRL_AEAD_GET_TAG, 16, tag);
158 if (memcmp (tag, etalon_tag, 16)) {
159 fprintf(stderr, "Shit happens!\n");
160 hexdump(stderr, "Etalon tag", etalon_tag, 16);
161 hexdump(stderr, "Got tag", tag, 16);
164 fprintf(stderr, "OK - small chunks!\n");
165 EVP_CIPHER_CTX_free(enc);
170 static void gf128_mul_uint64(uint64_t *z, uint64_t *x, uint64_t *y)
175 BUF_reverse((unsigned char *)x, NULL, 16);
176 BUF_reverse((unsigned char *)y, NULL, 16);
186 memset(z, 0, sizeof(uint64_t)*2);
195 for( i = 0; i < 64; i++ ) {
196 if( t&0x1 ) { z[0] ^= s0; z[1] ^= s1; }
199 s1 <<= 1; s1 ^= ( s0 >> 63 ); s0 <<= 1;
210 for( i = 0; i < 63; i++ ) {
211 if( t&0x1 ) { z[0] ^= s0; z[1] ^= s1; }
214 s1 <<= 1; s1 ^= ( s0 >> 63 ); s0 <<= 1;
223 z[0] = bswap_64(z[0]);
224 z[1] = bswap_64(z[1]);
226 BUF_reverse((unsigned char *)z, NULL, 16);
231 unsigned char H[16] = {
232 0x8D, 0xB1, 0x87, 0xD6, 0x53, 0x83, 0x0E, 0xA4, 0xBC, 0x44, 0x64, 0x76, 0x95, 0x2C, 0x30, 0x0B
235 unsigned char A[16] = {
236 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
239 unsigned char etalon[16] = {
240 0x4C, 0xF4, 0x27, 0xF4, 0xAD, 0xB7, 0x5C, 0xF4, 0xC0, 0xDA, 0x39, 0xD5, 0xAB, 0x48, 0xCF, 0x38
243 unsigned char result_bd[16];
244 gf128_mul_uint64((uint64_t *)result_bd, (uint64_t *)H, (uint64_t *)A);
247 hexdump(stderr, "Etalon", etalon, 16);
249 if (memcmp (etalon, result_bd, 16)) {
250 fprintf(stderr, "Shit happens - BD!\n");
251 hexdump(stderr, "Result - BD", result_bd, 16);
253 fprintf(stderr, "OK - BD!\n");
260 OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CONFIG, NULL);
263 grasshopper_mgm_big();
264 grasshopper_mgm_small();
265 ERR_print_errors_fp(stderr);