]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_keyexpimp.c
Merge pull request #100 from vt-alt/master
[openssl-gost/engine.git] / gost_keyexpimp.c
1 #include <arpa/inet.h>
2 #include <string.h>
3 #include <openssl/evp.h>
4 #include <openssl/hmac.h>
5
6 #include "gost_lcl.h"
7 #include "e_gost_err.h"
8
9 /*
10  * Function expects that out is a preallocated buffer of length
11  * defined as sum of shared_len and mac length defined by mac_nid
12  * */
13 int gost_kexp15(const unsigned char *shared_key, const int shared_len,
14                 int cipher_nid, const unsigned char *cipher_key,
15                 int mac_nid, unsigned char *mac_key,
16                 const unsigned char *iv, const size_t ivlen,
17                 unsigned char *out, int *out_len)
18 {
19     unsigned char iv_full[16], mac_buf[16];
20     unsigned int mac_len;
21
22     EVP_CIPHER_CTX *ciph = NULL;
23     EVP_MD_CTX *mac = NULL;
24
25     int ret = 0;
26     int len;
27
28     mac_len = (cipher_nid == NID_magma_ctr) ? 8 :
29         (cipher_nid == NID_grasshopper_ctr) ? 16 : 0;
30
31     if (mac_len == 0) {
32         GOSTerr(GOST_F_GOST_KEXP15, GOST_R_INVALID_CIPHER);
33         goto err;
34     }
35
36     /* we expect IV of half length */
37     memset(iv_full, 0, 16);
38     memcpy(iv_full, iv, ivlen);
39
40     mac = EVP_MD_CTX_new();
41     if (mac == NULL) {
42         GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
43         goto err;
44     }
45
46     if (EVP_DigestInit_ex(mac, EVP_get_digestbynid(mac_nid), NULL) <= 0
47         || EVP_MD_CTX_ctrl(mac, EVP_MD_CTRL_SET_KEY, 32, 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);
54         goto err;
55     }
56
57     ciph = EVP_CIPHER_CTX_new();
58     if (ciph == NULL) {
59         GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
60         goto err;
61     }
62
63     if (EVP_CipherInit_ex
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);
70         goto err;
71     }
72
73     *out_len = shared_len + mac_len;
74
75     ret = 1;
76
77  err:
78     OPENSSL_cleanse(mac_buf, mac_len);
79     EVP_MD_CTX_free(mac);
80     EVP_CIPHER_CTX_free(ciph);
81
82     return ret;
83 }
84
85 /*
86  * Function expects that shared_key is a preallocated buffer
87  * with length defined as expkeylen - mac_len defined by mac_nid
88  * */
89 int gost_kimp15(const unsigned char *expkey, const size_t expkeylen,
90                 int cipher_nid, const unsigned char *cipher_key,
91                 int mac_nid, unsigned char *mac_key,
92                 const unsigned char *iv, const size_t ivlen,
93                 unsigned char *shared_key)
94 {
95     unsigned char iv_full[16], out[48], mac_buf[16];
96     unsigned int mac_len;
97     const size_t shared_len = 32;
98
99     EVP_CIPHER_CTX *ciph = NULL;
100     EVP_MD_CTX *mac = NULL;
101
102     int ret = 0;
103     int len;
104
105     mac_len = (cipher_nid == NID_magma_ctr) ? 8 :
106         (cipher_nid == NID_grasshopper_ctr) ? 16 : 0;
107
108     if (mac_len == 0) {
109         GOSTerr(GOST_F_GOST_KIMP15, GOST_R_INVALID_CIPHER);
110         goto err;
111     }
112
113     /* we expect IV of half length */
114     memset(iv_full, 0, 16);
115     memcpy(iv_full, iv, ivlen);
116
117     ciph = EVP_CIPHER_CTX_new();
118     if (ciph == NULL) {
119         GOSTerr(GOST_F_GOST_KIMP15, ERR_R_MALLOC_FAILURE);
120         goto err;
121     }
122
123     if (EVP_CipherInit_ex
124         (ciph, EVP_get_cipherbynid(cipher_nid), NULL, NULL, NULL, 0) <= 0
125         || EVP_CipherInit_ex(ciph, NULL, NULL, cipher_key, iv_full, 0) <= 0
126         || EVP_CipherUpdate(ciph, out, &len, expkey, expkeylen) <= 0
127         || EVP_CipherFinal_ex(ciph, out + len, &len) <= 0) {
128         GOSTerr(GOST_F_GOST_KIMP15, ERR_R_INTERNAL_ERROR);
129         goto err;
130     }
131     /*Now we have shared key and mac in out[] */
132
133     mac = EVP_MD_CTX_new();
134     if (mac == NULL) {
135         GOSTerr(GOST_F_GOST_KIMP15, ERR_R_MALLOC_FAILURE);
136         goto err;
137     }
138
139     if (EVP_DigestInit_ex(mac, EVP_get_digestbynid(mac_nid), NULL) <= 0
140         || EVP_MD_CTX_ctrl(mac, EVP_MD_CTRL_SET_KEY, 32, mac_key) <= 0
141         || EVP_MD_CTX_ctrl(mac, EVP_MD_CTRL_MAC_LEN, mac_len, NULL) <= 0
142         || EVP_DigestUpdate(mac, iv, ivlen) <= 0
143         || EVP_DigestUpdate(mac, out, shared_len) <= 0
144         /* As we set MAC length directly, we should not allow overwriting it */
145         || EVP_DigestFinal_ex(mac, mac_buf, NULL) <= 0) {
146         GOSTerr(GOST_F_GOST_KIMP15, ERR_R_INTERNAL_ERROR);
147         goto err;
148     }
149
150     if (CRYPTO_memcmp(mac_buf, out + shared_len, mac_len) != 0) {
151         GOSTerr(GOST_F_GOST_KIMP15, GOST_R_BAD_MAC);
152         goto err;
153     }
154
155     memcpy(shared_key, out, shared_len);
156     ret = 1;
157
158  err:
159     OPENSSL_cleanse(out, sizeof(out));
160     EVP_MD_CTX_free(mac);
161     EVP_CIPHER_CTX_free(ciph);
162     return ret;
163 }
164
165 int gost_kdftree2012_256(unsigned char *keyout, size_t keyout_len,
166                          const unsigned char *key, size_t keylen,
167                          const unsigned char *label, size_t label_len,
168                          const unsigned char *seed, size_t seed_len,
169                          const size_t representation)
170 {
171     int iters, i = 0;
172     unsigned char zero = 0;
173     unsigned char *ptr = keyout;
174     HMAC_CTX *ctx = NULL;
175     unsigned char *len_ptr = NULL;
176     uint32_t len_repr = htonl(keyout_len * 8);
177     size_t len_repr_len = 4;
178
179     ctx = HMAC_CTX_new();
180     if (ctx == NULL) {
181         GOSTerr(GOST_F_GOST_KDFTREE2012_256, ERR_R_MALLOC_FAILURE);
182         return 0;
183     }
184
185     if ((keyout_len == 0) || (keyout_len % 32 != 0)) {
186         GOSTerr(GOST_F_GOST_KDFTREE2012_256, ERR_R_INTERNAL_ERROR);
187         return 0;
188     }
189     iters = keyout_len / 32;
190
191     len_ptr = (unsigned char *)&len_repr;
192     while (*len_ptr == 0) {
193         len_ptr++;
194         len_repr_len--;
195     }
196
197     for (i = 1; i <= iters; i++) {
198         uint32_t iter_net = htonl(i);
199         unsigned char *rep_ptr =
200             ((unsigned char *)&iter_net) + (4 - representation);
201
202         if (HMAC_Init_ex(ctx, key, keylen,
203                          EVP_get_digestbynid(NID_id_GostR3411_2012_256),
204                          NULL) <= 0
205             || HMAC_Update(ctx, rep_ptr, representation) <= 0
206             || HMAC_Update(ctx, label, label_len) <= 0
207             || HMAC_Update(ctx, &zero, 1) <= 0
208             || HMAC_Update(ctx, seed, seed_len) <= 0
209             || HMAC_Update(ctx, len_ptr, len_repr_len) <= 0
210             || HMAC_Final(ctx, ptr, NULL) <= 0) {
211             GOSTerr(GOST_F_GOST_KDFTREE2012_256, ERR_R_INTERNAL_ERROR);
212             HMAC_CTX_free(ctx);
213             return 0;
214         }
215
216         HMAC_CTX_reset(ctx);
217         ptr += 32;
218     }
219
220     HMAC_CTX_free(ctx);
221
222     return 1;
223 }
224
225 int gost_tlstree(int cipher_nid, const unsigned char *in, unsigned char *out,
226                  const unsigned char *tlsseq)
227 {
228 #ifndef L_ENDIAN
229     uint64_t gh_c1 = 0xFFFFFFFF00000000, gh_c2 = 0xFFFFFFFFFFF80000,
230         gh_c3 = 0xFFFFFFFFFFFFFFC0;
231     uint64_t mg_c1 = 0xFFFFFFC000000000, mg_c2 = 0xFFFFFFFFFE000000,
232         mg_c3 = 0xFFFFFFFFFFFFF000;
233 #else
234     uint64_t gh_c1 = 0x00000000FFFFFFFF, gh_c2 = 0x0000F8FFFFFFFFFF,
235         gh_c3 = 0xC0FFFFFFFFFFFFFF;
236     uint64_t mg_c1 = 0x00000000C0FFFFFF, mg_c2 = 0x000000FEFFFFFFFF,
237         mg_c3 = 0x00F0FFFFFFFFFFFF;
238 #endif
239     uint64_t c1, c2, c3;
240     uint64_t seed1, seed2, seed3;
241     uint64_t seq;
242     unsigned char ko1[32], ko2[32];
243
244     switch (cipher_nid) {
245     case NID_magma_cbc:
246         c1 = mg_c1;
247         c2 = mg_c2;
248         c3 = mg_c3;
249         break;
250     case NID_grasshopper_cbc:
251         c1 = gh_c1;
252         c2 = gh_c2;
253         c3 = gh_c3;
254         break;
255     default:
256         return 0;
257     }
258     memcpy(&seq, tlsseq, 8);
259     seed1 = seq & c1;
260     seed2 = seq & c2;
261     seed3 = seq & c3;
262
263     if (gost_kdftree2012_256(ko1, 32, in, 32, (const unsigned char *)"level1", 6,
264                          (const unsigned char *)&seed1, 8, 1) <= 0
265                           || gost_kdftree2012_256(ko2, 32, ko1, 32, (const unsigned char *)"level2", 6,
266                          (const unsigned char *)&seed2, 8, 1) <= 0
267         || gost_kdftree2012_256(out, 32, ko2, 32, (const unsigned char *)"level3", 6,
268                          (const unsigned char *)&seed3, 8, 1) <= 0)
269                         return 0;
270
271     return 1;
272 }