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 /* out_len = key_len + mac_len */
19 unsigned char iv_full[16], mac_buf[16];
22 EVP_CIPHER_CTX *ciph = NULL;
23 EVP_MD_CTX *mac = NULL;
28 mac_len = (cipher_nid == NID_magma_ctr) ? 8 :
29 (cipher_nid == NID_grasshopper_ctr) ? 16 : 0;
32 GOSTerr(GOST_F_GOST_KEXP15, ERR_R_INTERNAL_ERROR);
36 /* we expect IV of half length */
37 memset(iv_full, 0, 16);
38 memcpy(iv_full, iv, ivlen);
40 mac = EVP_MD_CTX_new();
42 GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
46 if (EVP_DigestInit_ex(mac, EVP_get_digestbynid(mac_nid), NULL) <= 0
47 || EVP_MD_CTX_ctrl(mac, EVP_MD_CTRL_SET_KEY, mac_key_len, mac_key) <= 0
48 || EVP_MD_CTX_ctrl(mac, EVP_MD_CTRL_MAC_LEN, mac_len, NULL) <= 0
49 || EVP_DigestUpdate(mac, iv, ivlen) <= 0
50 || EVP_DigestUpdate(mac, shared_key, shared_len) <= 0
51 /* As we set MAC length directly, we should not allow overwriting it */
52 || EVP_DigestFinal_ex(mac, mac_buf, NULL) <= 0) {
53 GOSTerr(GOST_F_GOST_KEXP15, ERR_R_INTERNAL_ERROR);
57 ciph = EVP_CIPHER_CTX_new();
59 GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
64 (ciph, EVP_get_cipherbynid(cipher_nid), NULL, NULL, NULL, 1) <= 0
65 || EVP_CipherInit_ex(ciph, NULL, NULL, cipher_key, iv_full, 1) <= 0
66 || EVP_CipherUpdate(ciph, out, &len, shared_key, shared_len) <= 0
67 || EVP_CipherUpdate(ciph, out + shared_len, &len, mac_buf, mac_len) <= 0
68 || EVP_CipherFinal_ex(ciph, out + shared_len + len, out_len) <= 0) {
69 GOSTerr(GOST_F_GOST_KEXP15, ERR_R_INTERNAL_ERROR);
73 *out_len = shared_len + mac_len;
78 /* TODO clear mac_buf */
80 EVP_CIPHER_CTX_free(ciph);
85 int gost_kimp15(const char *expkey, const size_t expkeylen,
86 int cipher_nid, const char *cipher_key,
87 const size_t cipher_key_len, int mac_nid, const char *mac_key,
88 const size_t mac_key_len, const char *iv, const size_t ivlen,
89 char *shared_key, size_t *shared_len)
95 * keyout expected to be 64 bytes
97 int gost_keg(const unsigned char *seckey, const size_t seckey_len,
98 const EC_POINT *pub, const unsigned char *h, unsigned char *keyout)
103 #ifdef ENABLE_UNIT_TESTS
106 # include <openssl/obj_mac.h>
108 static void hexdump(FILE *f, const char *title, const unsigned char *s, int l)
112 fprintf(f, "%s", title);
115 fprintf(f, "\n%04x", n);
116 fprintf(f, " %02x", s[n]);
123 const unsigned char key[] = {
124 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
125 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
126 0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
127 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
130 const unsigned char magma_key[] = {
131 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
132 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
133 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
134 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
137 unsigned char mac_magma_key[] = {
138 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
139 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
140 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
141 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
144 const unsigned char magma_iv[] = { 0x67, 0xBE, 0xD6, 0x54 };
146 const unsigned char magma_export[] =
147 { 0xCF, 0xD5, 0xA1, 0x2D, 0x5B, 0x81, 0xB6, 0xE1, 0xE9, 0x9C, 0x91,
148 0x6D, 0x07, 0x90, 0x0C, 0x6A,
149 0xC1, 0x27, 0x03, 0xFB, 0x3A, 0xBD, 0xED, 0x55, 0x56, 0x7B, 0xF3, 0x74,
150 0x2C, 0x89, 0x9C, 0x75,
151 0x5D, 0xAF, 0xE7, 0xB4, 0x2E, 0x3A, 0x8B, 0xD9
154 unsigned char buf[32 + 16];
158 OpenSSL_add_all_algorithms();
159 memset(buf, 0, sizeof(buf));
161 ret = gost_kexp15(key, 32,
162 NID_magma_ctr, magma_key, 32,
163 NID_magma_mac, mac_magma_key, 32,
164 magma_iv, 4, buf, &outlen);
167 ERR_print_errors_fp(stderr);
169 hexdump(stdout, "Magma key export", buf, 40);
170 if (memcmp(buf, magma_export, 40) != 0) {
171 fprintf(stdout, "ERROR! test failed\n");