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