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