]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_keyexpimp.c
gost_kimp15 tested
[openssl-gost/engine.git] / gost_keyexpimp.c
1 #include <string.h>
2 #include <openssl/evp.h>
3
4 #include "gost_lcl.h"
5 #include "e_gost_err.h"
6
7 /*
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
10  * */
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,
16                 int *out_len)
17 {
18     unsigned char iv_full[16], mac_buf[16];
19     unsigned int mac_len;
20
21     EVP_CIPHER_CTX *ciph = NULL;
22     EVP_MD_CTX *mac = NULL;
23
24     int ret = 0;
25     int len;
26
27     mac_len = (cipher_nid == NID_magma_ctr) ? 8 :
28         (cipher_nid == NID_grasshopper_ctr) ? 16 : 0;
29
30     if (mac_len == 0) {
31         GOSTerr(GOST_F_GOST_KEXP15, GOST_R_INVALID_CIPHER);
32         goto err;
33     }
34
35     /* we expect IV of half length */
36     memset(iv_full, 0, 16);
37     memcpy(iv_full, iv, ivlen);
38
39     mac = EVP_MD_CTX_new();
40     if (mac == NULL) {
41         GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
42         goto err;
43     }
44
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);
53         goto err;
54     }
55
56     ciph = EVP_CIPHER_CTX_new();
57     if (ciph == NULL) {
58         GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
59         goto err;
60     }
61
62     if (EVP_CipherInit_ex
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);
69         goto err;
70     }
71
72     *out_len = shared_len + mac_len;
73
74     ret = 1;
75
76  err:
77     OPENSSL_cleanse(mac_buf, mac_len);
78     EVP_MD_CTX_free(mac);
79     EVP_CIPHER_CTX_free(ciph);
80
81     return ret;
82 }
83
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,
87                 unsigned char *mac_key, const size_t mac_key_len,
88                 const unsigned char *iv, const size_t ivlen,
89                 unsigned char *shared_key, size_t shared_len)
90 {
91     unsigned char iv_full[16], out[48], mac_buf[16];
92     unsigned int mac_len;
93
94     EVP_CIPHER_CTX *ciph = NULL;
95     EVP_MD_CTX *mac = NULL;
96
97     int ret = 0;
98     int len;
99
100     mac_len = (cipher_nid == NID_magma_ctr) ? 8 :
101         (cipher_nid == NID_grasshopper_ctr) ? 16 : 0;
102
103     if (mac_len == 0) {
104         GOSTerr(GOST_F_GOST_KIMP15, GOST_R_INVALID_CIPHER);
105         goto err;
106     }
107
108     /* we expect IV of half length */
109     memset(iv_full, 0, 16);
110     memcpy(iv_full, iv, ivlen);
111
112     ciph = EVP_CIPHER_CTX_new();
113     if (ciph == NULL) {
114         GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
115         goto err;
116     }
117
118     if (EVP_CipherInit_ex
119         (ciph, EVP_get_cipherbynid(cipher_nid), NULL, NULL, NULL, 0) <= 0
120         || EVP_CipherInit_ex(ciph, NULL, NULL, cipher_key, iv_full, 0) <= 0
121         || EVP_CipherUpdate(ciph, out, &len, expkey, expkeylen) <= 0
122         || EVP_CipherFinal_ex(ciph, out + len, &len) <= 0) {
123         GOSTerr(GOST_F_GOST_KIMP15, ERR_R_INTERNAL_ERROR);
124         goto err;
125     }
126     /*Now we have shared key and mac in out[] */
127
128     mac = EVP_MD_CTX_new();
129     if (mac == NULL) {
130         GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
131         goto err;
132     }
133
134     if (EVP_DigestInit_ex(mac, EVP_get_digestbynid(mac_nid), NULL) <= 0
135         || EVP_MD_CTX_ctrl(mac, EVP_MD_CTRL_SET_KEY, mac_key_len, mac_key) <= 0
136         || EVP_MD_CTX_ctrl(mac, EVP_MD_CTRL_MAC_LEN, mac_len, NULL) <= 0
137         || EVP_DigestUpdate(mac, iv, ivlen) <= 0
138         || EVP_DigestUpdate(mac, out, shared_len) <= 0
139         /* As we set MAC length directly, we should not allow overwriting it */
140         || EVP_DigestFinal_ex(mac, mac_buf, NULL) <= 0) {
141         GOSTerr(GOST_F_GOST_KIMP15, ERR_R_INTERNAL_ERROR);
142         goto err;
143     }
144
145     if (CRYPTO_memcmp(mac_buf, out + shared_len, mac_len) != 0) {
146         GOSTerr(GOST_F_GOST_KIMP15, GOST_R_BAD_MAC);
147         goto err;
148     }
149
150     memcpy(shared_key, out, shared_len);
151     ret = 1;
152
153  err:
154     OPENSSL_cleanse(out, sizeof(out));
155     EVP_MD_CTX_free(mac);
156     EVP_CIPHER_CTX_free(ciph);
157     return ret;
158 }
159
160 /*
161  * keyout expected to be 64 bytes
162  * */
163 int gost_keg(const unsigned char *seckey, const size_t seckey_len,
164              const EC_POINT *pub, const unsigned char *h, unsigned char *keyout)
165 {
166     return 0;
167 }
168
169 #ifdef ENABLE_UNIT_TESTS
170 # include <stdio.h>
171 # include <string.h>
172 # include <openssl/obj_mac.h>
173
174 static void hexdump(FILE *f, const char *title, const unsigned char *s, int l)
175 {
176     int n = 0;
177
178     fprintf(f, "%s", title);
179     for (; n < l; ++n) {
180         if ((n % 16) == 0)
181             fprintf(f, "\n%04x", n);
182         fprintf(f, " %02x", s[n]);
183     }
184     fprintf(f, "\n");
185 }
186
187 int main(void)
188 {
189     const unsigned char shared_key[] = {
190         0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF,
191         0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77,
192         0xFE, 0xDC, 0xBA, 0x98, 0x76, 0x54, 0x32, 0x10,
193         0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF
194     };
195
196     const unsigned char magma_key[] = {
197         0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
198         0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
199         0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
200         0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
201     };
202
203     unsigned char mac_magma_key[] = {
204         0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
205         0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
206         0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
207         0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
208     };
209
210     const unsigned char magma_iv[] = { 0x67, 0xBE, 0xD6, 0x54 };
211
212     const unsigned char magma_export[] = {
213         0xCF, 0xD5, 0xA1, 0x2D, 0x5B, 0x81, 0xB6, 0xE1,
214         0xE9, 0x9C, 0x91, 0x6D, 0x07, 0x90, 0x0C, 0x6A,
215         0xC1, 0x27, 0x03, 0xFB, 0x3A, 0xBD, 0xED, 0x55,
216         0x56, 0x7B, 0xF3, 0x74, 0x2C, 0x89, 0x9C, 0x75,
217         0x5D, 0xAF, 0xE7, 0xB4, 0x2E, 0x3A, 0x8B, 0xD9
218     };
219
220     unsigned char buf[32 + 16];
221     int ret = 0;
222     int outlen = 40;
223
224     OpenSSL_add_all_algorithms();
225     memset(buf, 0, sizeof(buf));
226
227     ret = gost_kexp15(shared_key, 32,
228                       NID_magma_ctr, magma_key, 32,
229                       NID_magma_mac, mac_magma_key, 32,
230                       magma_iv, 4, buf, &outlen);
231
232     if (ret <= 0)
233         ERR_print_errors_fp(stderr);
234     else {
235         hexdump(stdout, "Magma key export", buf, 40);
236         if (memcmp(buf, magma_export, 40) != 0) {
237             fprintf(stdout, "ERROR! test failed\n");
238         }
239     }
240
241     ret = gost_kimp15(magma_export, 40,
242                       NID_magma_ctr, magma_key, 32,
243                       NID_magma_mac, mac_magma_key, 32, magma_iv, 4, buf, 32);
244
245     if (ret <= 0)
246         ERR_print_errors_fp(stderr);
247     else {
248         hexdump(stdout, "Magma key import", buf, 32);
249         if (memcmp(buf, shared_key, 32) != 0) {
250             fprintf(stdout, "ERROR! test failed\n");
251         }
252     }
253
254     return 0;
255 }
256
257 #endif