2 #include <openssl/evp.h>
5 #include "e_gost_err.h"
8 * Function expects that out is a preallocated buffer of length
9 * defined as sum of shared_len and mac length defined by mac_nid
11 int gost_kexp15(const unsigned char *shared_key, const int shared_len,
12 int cipher_nid, const unsigned char *cipher_key,
13 const size_t cipher_key_len, int mac_nid,
14 unsigned char *mac_key, const size_t mac_key_len,
15 const unsigned char *iv, const size_t ivlen, unsigned char *out,
18 unsigned char iv_full[16], mac_buf[16];
21 EVP_CIPHER_CTX *ciph = NULL;
22 EVP_MD_CTX *mac = NULL;
27 mac_len = (cipher_nid == NID_magma_ctr) ? 8 :
28 (cipher_nid == NID_grasshopper_ctr) ? 16 : 0;
31 GOSTerr(GOST_F_GOST_KEXP15, GOST_R_INVALID_CIPHER);
35 /* we expect IV of half length */
36 memset(iv_full, 0, 16);
37 memcpy(iv_full, iv, ivlen);
39 mac = EVP_MD_CTX_new();
41 GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
45 if (EVP_DigestInit_ex(mac, EVP_get_digestbynid(mac_nid), NULL) <= 0
46 || EVP_MD_CTX_ctrl(mac, EVP_MD_CTRL_SET_KEY, mac_key_len, mac_key) <= 0
47 || EVP_MD_CTX_ctrl(mac, EVP_MD_CTRL_MAC_LEN, mac_len, NULL) <= 0
48 || EVP_DigestUpdate(mac, iv, ivlen) <= 0
49 || EVP_DigestUpdate(mac, shared_key, shared_len) <= 0
50 /* As we set MAC length directly, we should not allow overwriting it */
51 || EVP_DigestFinal_ex(mac, mac_buf, NULL) <= 0) {
52 GOSTerr(GOST_F_GOST_KEXP15, ERR_R_INTERNAL_ERROR);
56 ciph = EVP_CIPHER_CTX_new();
58 GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
63 (ciph, EVP_get_cipherbynid(cipher_nid), NULL, NULL, NULL, 1) <= 0
64 || EVP_CipherInit_ex(ciph, NULL, NULL, cipher_key, iv_full, 1) <= 0
65 || EVP_CipherUpdate(ciph, out, &len, shared_key, shared_len) <= 0
66 || EVP_CipherUpdate(ciph, out + shared_len, &len, mac_buf, mac_len) <= 0
67 || EVP_CipherFinal_ex(ciph, out + shared_len + len, out_len) <= 0) {
68 GOSTerr(GOST_F_GOST_KEXP15, ERR_R_INTERNAL_ERROR);
72 *out_len = shared_len + mac_len;
77 OPENSSL_cleanse(mac_buf, mac_len);
79 EVP_CIPHER_CTX_free(ciph);
84 int gost_kimp15(const unsigned char *expkey, const size_t expkeylen,
85 int cipher_nid, const unsigned char *cipher_key,
86 const size_t cipher_key_len, int mac_nid, char *mac_key,
87 const size_t mac_key_len, const char *iv, const size_t ivlen,
88 char *shared_key, size_t shared_len)
90 unsigned char iv_full[16], out[48], mac_buf[16];
93 EVP_CIPHER_CTX *ciph = NULL;
94 EVP_MD_CTX *mac = NULL;
99 mac_len = (cipher_nid == NID_magma_ctr) ? 8 :
100 (cipher_nid == NID_grasshopper_ctr) ? 16 : 0;
103 GOSTerr(GOST_F_GOST_KIMP15, GOST_R_INVALID_CIPHER);
107 /* we expect IV of half length */
108 memset(iv_full, 0, 16);
109 memcpy(iv_full, iv, ivlen);
111 if (EVP_CipherInit_ex
112 (ciph, EVP_get_cipherbynid(cipher_nid), NULL, NULL, NULL, 0) <= 0
113 || EVP_CipherInit_ex(ciph, NULL, NULL, cipher_key, iv_full, 0) <= 0
114 || EVP_CipherUpdate(ciph, out, &len, expkey, expkeylen) <= 0
115 || EVP_CipherFinal_ex(ciph, out + len, &len) <= 0) {
116 GOSTerr(GOST_F_GOST_KIMP15, ERR_R_INTERNAL_ERROR);
119 /*Now we have shared key and mac in out[] */
121 if (EVP_DigestInit_ex(mac, EVP_get_digestbynid(mac_nid), NULL) <= 0
122 || EVP_MD_CTX_ctrl(mac, EVP_MD_CTRL_SET_KEY, mac_key_len, mac_key) <= 0
123 || EVP_MD_CTX_ctrl(mac, EVP_MD_CTRL_MAC_LEN, mac_len, NULL) <= 0
124 || EVP_DigestUpdate(mac, iv, ivlen) <= 0
125 || EVP_DigestUpdate(mac, out, shared_len) <= 0
126 /* As we set MAC length directly, we should not allow overwriting it */
127 || EVP_DigestFinal_ex(mac, mac_buf, NULL) <= 0) {
128 GOSTerr(GOST_F_GOST_KIMP15, ERR_R_INTERNAL_ERROR);
132 if (CRYPTO_memcmp(mac_buf, out + shared_len, mac_len) != 0) {
133 GOSTerr(GOST_F_GOST_KIMP15, GOST_R_BAD_MAC);
137 memcpy(shared_key, out, shared_len);
141 OPENSSL_cleanse(out, sizeof(out));
142 EVP_MD_CTX_free(mac);
143 EVP_CIPHER_CTX_free(ciph);
148 * keyout expected to be 64 bytes
150 int gost_keg(const unsigned char *seckey, const size_t seckey_len,
151 const EC_POINT *pub, const unsigned char *h, unsigned char *keyout)
156 #ifdef ENABLE_UNIT_TESTS
159 # include <openssl/obj_mac.h>
161 static void hexdump(FILE *f, const char *title, const unsigned char *s, int l)
165 fprintf(f, "%s", title);
168 fprintf(f, "\n%04x", n);
169 fprintf(f, " %02x", s[n]);
176 const unsigned char key[] = {
177 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
178 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
179 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
180 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
183 const unsigned char magma_key[] = {
184 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
185 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
186 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
187 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
190 unsigned char mac_magma_key[] = {
191 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
192 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
193 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
194 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
197 const unsigned char magma_iv[] = { 0x67, 0xBE, 0xD6, 0x54 };
199 const unsigned char magma_export[] =
200 { 0xCF, 0xD5, 0xA1, 0x2D, 0x5B, 0x81, 0xB6, 0xE1, 0xE9, 0x9C, 0x91,
201 0x6D, 0x07, 0x90, 0x0C, 0x6A,
202 0xC1, 0x27, 0x03, 0xFB, 0x3A, 0xBD, 0xED, 0x55, 0x56, 0x7B, 0xF3, 0x74,
203 0x2C, 0x89, 0x9C, 0x75,
204 0x5D, 0xAF, 0xE7, 0xB4, 0x2E, 0x3A, 0x8B, 0xD9
207 unsigned char buf[32 + 16];
211 OpenSSL_add_all_algorithms();
212 memset(buf, 0, sizeof(buf));
214 ret = gost_kexp15(key, 32,
215 NID_magma_ctr, magma_key, 32,
216 NID_magma_mac, mac_magma_key, 32,
217 magma_iv, 4, buf, &outlen);
220 ERR_print_errors_fp(stderr);
222 hexdump(stdout, "Magma key export", buf, 40);
223 if (memcmp(buf, magma_export, 40) != 0) {
224 fprintf(stdout, "ERROR! test failed\n");