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 int mac_nid, unsigned char *mac_key,
14 const unsigned char *iv, const size_t ivlen,
15 unsigned char *out, int *out_len)
17 unsigned char iv_full[16], mac_buf[16];
20 EVP_CIPHER_CTX *ciph = NULL;
21 EVP_MD_CTX *mac = NULL;
26 mac_len = (cipher_nid == NID_magma_ctr) ? 8 :
27 (cipher_nid == NID_grasshopper_ctr) ? 16 : 0;
30 GOSTerr(GOST_F_GOST_KEXP15, GOST_R_INVALID_CIPHER);
34 /* we expect IV of half length */
35 memset(iv_full, 0, 16);
36 memcpy(iv_full, iv, ivlen);
38 mac = EVP_MD_CTX_new();
40 GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
44 if (EVP_DigestInit_ex(mac, EVP_get_digestbynid(mac_nid), NULL) <= 0
45 || EVP_MD_CTX_ctrl(mac, EVP_MD_CTRL_SET_KEY, 32, mac_key) <= 0
46 || EVP_MD_CTX_ctrl(mac, EVP_MD_CTRL_MAC_LEN, mac_len, NULL) <= 0
47 || EVP_DigestUpdate(mac, iv, ivlen) <= 0
48 || EVP_DigestUpdate(mac, shared_key, shared_len) <= 0
49 /* As we set MAC length directly, we should not allow overwriting it */
50 || EVP_DigestFinal_ex(mac, mac_buf, NULL) <= 0) {
51 GOSTerr(GOST_F_GOST_KEXP15, ERR_R_INTERNAL_ERROR);
55 ciph = EVP_CIPHER_CTX_new();
57 GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
62 (ciph, EVP_get_cipherbynid(cipher_nid), NULL, NULL, NULL, 1) <= 0
63 || EVP_CipherInit_ex(ciph, NULL, NULL, cipher_key, iv_full, 1) <= 0
64 || EVP_CipherUpdate(ciph, out, &len, shared_key, shared_len) <= 0
65 || EVP_CipherUpdate(ciph, out + shared_len, &len, mac_buf, mac_len) <= 0
66 || EVP_CipherFinal_ex(ciph, out + shared_len + len, out_len) <= 0) {
67 GOSTerr(GOST_F_GOST_KEXP15, ERR_R_INTERNAL_ERROR);
71 *out_len = shared_len + mac_len;
76 OPENSSL_cleanse(mac_buf, mac_len);
78 EVP_CIPHER_CTX_free(ciph);
83 int gost_kimp15(const unsigned char *expkey, const size_t expkeylen,
84 int cipher_nid, const unsigned char *cipher_key,
85 int mac_nid, unsigned char *mac_key,
86 const unsigned char *iv, const size_t ivlen,
87 unsigned char *shared_key, size_t shared_len)
89 unsigned char iv_full[16], out[48], mac_buf[16];
92 EVP_CIPHER_CTX *ciph = NULL;
93 EVP_MD_CTX *mac = NULL;
98 mac_len = (cipher_nid == NID_magma_ctr) ? 8 :
99 (cipher_nid == NID_grasshopper_ctr) ? 16 : 0;
102 GOSTerr(GOST_F_GOST_KIMP15, GOST_R_INVALID_CIPHER);
106 /* we expect IV of half length */
107 memset(iv_full, 0, 16);
108 memcpy(iv_full, iv, ivlen);
110 ciph = EVP_CIPHER_CTX_new();
112 GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
116 if (EVP_CipherInit_ex
117 (ciph, EVP_get_cipherbynid(cipher_nid), NULL, NULL, NULL, 0) <= 0
118 || EVP_CipherInit_ex(ciph, NULL, NULL, cipher_key, iv_full, 0) <= 0
119 || EVP_CipherUpdate(ciph, out, &len, expkey, expkeylen) <= 0
120 || EVP_CipherFinal_ex(ciph, out + len, &len) <= 0) {
121 GOSTerr(GOST_F_GOST_KIMP15, ERR_R_INTERNAL_ERROR);
124 /*Now we have shared key and mac in out[] */
126 mac = EVP_MD_CTX_new();
128 GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
132 if (EVP_DigestInit_ex(mac, EVP_get_digestbynid(mac_nid), NULL) <= 0
133 || EVP_MD_CTX_ctrl(mac, EVP_MD_CTRL_SET_KEY, 32, mac_key) <= 0
134 || EVP_MD_CTX_ctrl(mac, EVP_MD_CTRL_MAC_LEN, mac_len, NULL) <= 0
135 || EVP_DigestUpdate(mac, iv, ivlen) <= 0
136 || EVP_DigestUpdate(mac, out, shared_len) <= 0
137 /* As we set MAC length directly, we should not allow overwriting it */
138 || EVP_DigestFinal_ex(mac, mac_buf, NULL) <= 0) {
139 GOSTerr(GOST_F_GOST_KIMP15, ERR_R_INTERNAL_ERROR);
143 if (CRYPTO_memcmp(mac_buf, out + shared_len, mac_len) != 0) {
144 GOSTerr(GOST_F_GOST_KIMP15, GOST_R_BAD_MAC);
148 memcpy(shared_key, out, shared_len);
152 OPENSSL_cleanse(out, sizeof(out));
153 EVP_MD_CTX_free(mac);
154 EVP_CIPHER_CTX_free(ciph);
159 * keyout expected to be 64 bytes
161 int gost_keg(const unsigned char *seckey, const size_t seckey_len,
162 const EC_POINT *pub, const unsigned char *h, unsigned char *keyout)
167 #ifdef ENABLE_UNIT_TESTS
170 # include <openssl/obj_mac.h>
172 static void hexdump(FILE *f, const char *title, const unsigned char *s, int l)
176 fprintf(f, "%s", title);
179 fprintf(f, "\n%04x", n);
180 fprintf(f, " %02x", s[n]);
187 const unsigned char shared_key[] = {
188 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
189 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
190 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
191 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
194 const unsigned char magma_key[] = {
195 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
196 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
197 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
198 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
201 unsigned char mac_magma_key[] = {
202 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
203 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
204 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
205 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
208 const unsigned char magma_iv[] = { 0x67, 0xBE, 0xD6, 0x54 };
210 const unsigned char magma_export[] = {
211 0xCF, 0xD5, 0xA1, 0x2D, 0x5B, 0x81, 0xB6, 0xE1,
212 0xE9, 0x9C, 0x91, 0x6D, 0x07, 0x90, 0x0C, 0x6A,
213 0xC1, 0x27, 0x03, 0xFB, 0x3A, 0xBD, 0xED, 0x55,
214 0x56, 0x7B, 0xF3, 0x74, 0x2C, 0x89, 0x9C, 0x75,
215 0x5D, 0xAF, 0xE7, 0xB4, 0x2E, 0x3A, 0x8B, 0xD9
218 unsigned char buf[32 + 16];
222 OpenSSL_add_all_algorithms();
223 memset(buf, 0, sizeof(buf));
225 ret = gost_kexp15(shared_key, 32,
226 NID_magma_ctr, magma_key,
227 NID_magma_mac, mac_magma_key, magma_iv, 4, buf, &outlen);
230 ERR_print_errors_fp(stderr);
232 hexdump(stdout, "Magma key export", buf, 40);
233 if (memcmp(buf, magma_export, 40) != 0) {
234 fprintf(stdout, "ERROR! test failed\n");
238 ret = gost_kimp15(magma_export, 40,
239 NID_magma_ctr, magma_key,
240 NID_magma_mac, mac_magma_key, magma_iv, 4, buf, 32);
243 ERR_print_errors_fp(stderr);
245 hexdump(stdout, "Magma key import", buf, 32);
246 if (memcmp(buf, shared_key, 32) != 0) {
247 fprintf(stdout, "ERROR! test failed\n");