]> www.wagner.pp.ru Git - openssl-gost/engine.git/blob - gost_keyexpimp.c
Remove redundant parameters
[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                 int mac_nid, unsigned char *mac_key,
14                 const unsigned char *iv, const size_t ivlen,
15                 unsigned char *out, int *out_len)
16 {
17     unsigned char iv_full[16], mac_buf[16];
18     unsigned int mac_len;
19
20     EVP_CIPHER_CTX *ciph = NULL;
21     EVP_MD_CTX *mac = NULL;
22
23     int ret = 0;
24     int len;
25
26     mac_len = (cipher_nid == NID_magma_ctr) ? 8 :
27         (cipher_nid == NID_grasshopper_ctr) ? 16 : 0;
28
29     if (mac_len == 0) {
30         GOSTerr(GOST_F_GOST_KEXP15, GOST_R_INVALID_CIPHER);
31         goto err;
32     }
33
34     /* we expect IV of half length */
35     memset(iv_full, 0, 16);
36     memcpy(iv_full, iv, ivlen);
37
38     mac = EVP_MD_CTX_new();
39     if (mac == NULL) {
40         GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
41         goto err;
42     }
43
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);
52         goto err;
53     }
54
55     ciph = EVP_CIPHER_CTX_new();
56     if (ciph == NULL) {
57         GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
58         goto err;
59     }
60
61     if (EVP_CipherInit_ex
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);
68         goto err;
69     }
70
71     *out_len = shared_len + mac_len;
72
73     ret = 1;
74
75  err:
76     OPENSSL_cleanse(mac_buf, mac_len);
77     EVP_MD_CTX_free(mac);
78     EVP_CIPHER_CTX_free(ciph);
79
80     return ret;
81 }
82
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)
88 {
89     unsigned char iv_full[16], out[48], mac_buf[16];
90     unsigned int mac_len;
91
92     EVP_CIPHER_CTX *ciph = NULL;
93     EVP_MD_CTX *mac = NULL;
94
95     int ret = 0;
96     int len;
97
98     mac_len = (cipher_nid == NID_magma_ctr) ? 8 :
99         (cipher_nid == NID_grasshopper_ctr) ? 16 : 0;
100
101     if (mac_len == 0) {
102         GOSTerr(GOST_F_GOST_KIMP15, GOST_R_INVALID_CIPHER);
103         goto err;
104     }
105
106     /* we expect IV of half length */
107     memset(iv_full, 0, 16);
108     memcpy(iv_full, iv, ivlen);
109
110     ciph = EVP_CIPHER_CTX_new();
111     if (ciph == NULL) {
112         GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
113         goto err;
114     }
115
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);
122         goto err;
123     }
124     /*Now we have shared key and mac in out[] */
125
126     mac = EVP_MD_CTX_new();
127     if (mac == NULL) {
128         GOSTerr(GOST_F_GOST_KEXP15, ERR_R_MALLOC_FAILURE);
129         goto err;
130     }
131
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);
140         goto err;
141     }
142
143     if (CRYPTO_memcmp(mac_buf, out + shared_len, mac_len) != 0) {
144         GOSTerr(GOST_F_GOST_KIMP15, GOST_R_BAD_MAC);
145         goto err;
146     }
147
148     memcpy(shared_key, out, shared_len);
149     ret = 1;
150
151  err:
152     OPENSSL_cleanse(out, sizeof(out));
153     EVP_MD_CTX_free(mac);
154     EVP_CIPHER_CTX_free(ciph);
155     return ret;
156 }
157
158 /*
159  * keyout expected to be 64 bytes
160  * */
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)
163 {
164     return 0;
165 }
166
167 #ifdef ENABLE_UNIT_TESTS
168 # include <stdio.h>
169 # include <string.h>
170 # include <openssl/obj_mac.h>
171
172 static void hexdump(FILE *f, const char *title, const unsigned char *s, int l)
173 {
174     int n = 0;
175
176     fprintf(f, "%s", title);
177     for (; n < l; ++n) {
178         if ((n % 16) == 0)
179             fprintf(f, "\n%04x", n);
180         fprintf(f, " %02x", s[n]);
181     }
182     fprintf(f, "\n");
183 }
184
185 int main(void)
186 {
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
192     };
193
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,
199     };
200
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,
206     };
207
208     const unsigned char magma_iv[] = { 0x67, 0xBE, 0xD6, 0x54 };
209
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
216     };
217
218     unsigned char buf[32 + 16];
219     int ret = 0;
220     int outlen = 40;
221
222     OpenSSL_add_all_algorithms();
223     memset(buf, 0, sizeof(buf));
224
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);
228
229     if (ret <= 0)
230         ERR_print_errors_fp(stderr);
231     else {
232         hexdump(stdout, "Magma key export", buf, 40);
233         if (memcmp(buf, magma_export, 40) != 0) {
234             fprintf(stdout, "ERROR! test failed\n");
235         }
236     }
237
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);
241
242     if (ret <= 0)
243         ERR_print_errors_fp(stderr);
244     else {
245         hexdump(stdout, "Magma key import", buf, 32);
246         if (memcmp(buf, shared_key, 32) != 0) {
247             fprintf(stdout, "ERROR! test failed\n");
248         }
249     }
250
251     return 0;
252 }
253
254 #endif