1 /* $OpenBSD: dh.c,v 1.27 2023/03/31 07:28:46 tb Exp $ */
2
3 /*
4 * Copyright (c) 2010-2014 Reyk Floeter <reyk@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19 #include <string.h>
20
21 #include <openssl/obj_mac.h>
22 #include <openssl/dh.h>
23 #include <openssl/ec.h>
24 #include <openssl/ecdh.h>
25 #include <openssl/bn.h>
26
27 #include "dh.h"
28
29 #define roundup(x, y) ((((x)+((y)-1))/(y))*(y))
30
31 int dh_init(struct group *);
32
33 int modp_init(struct group *);
34 int modp_getlen(struct group *);
35 int modp_create_exchange(struct group *, u_int8_t *);
36 int modp_create_shared(struct group *, u_int8_t *, u_int8_t *);
37
38 int ec_init(struct group *);
39 int ec_getlen(struct group *);
40 int ec_secretlen(struct group *);
41 int ec_create_exchange(struct group *, u_int8_t *);
42 int ec_create_shared(struct group *, u_int8_t *, u_int8_t *);
43
44 #define EC_POINT2RAW_FULL 0
45 #define EC_POINT2RAW_XONLY 1
46 int ec_point2raw(struct group *, const EC_POINT *, uint8_t *, size_t, int);
47 EC_POINT *
48 ec_raw2point(struct group *, u_int8_t *, size_t);
49
50 struct group_id ike_groups[] = {
51 { GROUP_MODP, 1, 768,
52 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
53 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
54 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
55 "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF",
56 "02"
57 },
58 { GROUP_MODP, 2, 1024,
59 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
60 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
61 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
62 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
63 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
64 "FFFFFFFFFFFFFFFF",
65 "02"
66 },
67 #ifndef OPENSSL_NO_EC2M
68 { GROUP_EC2N, 3, 155, NULL, NULL, NID_ipsec3 },
69 { GROUP_EC2N, 4, 185, NULL, NULL, NID_ipsec4 },
70 #endif
71 { GROUP_MODP, 5, 1536,
72 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
73 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
74 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
75 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
76 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
77 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
78 "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
79 "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF",
80 "02"
81 },
82 { GROUP_MODP, 14, 2048,
83 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
84 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
85 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
86 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
87 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
88 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
89 "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
90 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
91 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
92 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
93 "15728E5A8AACAA68FFFFFFFFFFFFFFFF",
94 "02"
95 },
96 { GROUP_MODP, 15, 3072,
97 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
98 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
99 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
100 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
101 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
102 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
103 "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
104 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
105 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
106 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
107 "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
108 "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
109 "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
110 "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
111 "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
112 "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF",
113 "02"
114 },
115 { GROUP_MODP, 16, 4096,
116 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
117 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
118 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
119 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
120 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
121 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
122 "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
123 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
124 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
125 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
126 "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
127 "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
128 "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
129 "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
130 "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
131 "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
132 "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
133 "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
134 "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
135 "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
136 "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199"
137 "FFFFFFFFFFFFFFFF",
138 "02"
139 },
140 { GROUP_MODP, 17, 6144,
141 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
142 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
143 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
144 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
145 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
146 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
147 "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
148 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
149 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
150 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
151 "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
152 "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
153 "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
154 "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
155 "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
156 "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
157 "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
158 "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
159 "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
160 "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
161 "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
162 "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"
163 "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
164 "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
165 "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
166 "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"
167 "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
168 "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
169 "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
170 "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
171 "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
172 "12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF",
173 "02"
174 },
175 { GROUP_MODP, 18, 8192,
176 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
177 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
178 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
179 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
180 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
181 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
182 "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
183 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
184 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
185 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
186 "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
187 "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
188 "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
189 "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
190 "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
191 "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
192 "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
193 "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
194 "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
195 "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
196 "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
197 "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"
198 "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
199 "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
200 "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
201 "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"
202 "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
203 "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
204 "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
205 "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
206 "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
207 "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4"
208 "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300"
209 "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568"
210 "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9"
211 "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B"
212 "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A"
213 "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36"
214 "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1"
215 "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92"
216 "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47"
217 "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71"
218 "60C980DD98EDD3DFFFFFFFFFFFFFFFFF",
219 "02"
220 },
221 { GROUP_ECP, 19, 256, NULL, NULL, NID_X9_62_prime256v1 },
222 { GROUP_ECP, 20, 384, NULL, NULL, NID_secp384r1 },
223 { GROUP_ECP, 21, 521, NULL, NULL, NID_secp521r1 },
224 { GROUP_ECP, 25, 192, NULL, NULL, NID_X9_62_prime192v1 },
225 { GROUP_ECP, 26, 224, NULL, NULL, NID_secp224r1 },
226 { GROUP_ECP, 27, 224, NULL, NULL, NID_brainpoolP224r1 },
227 { GROUP_ECP, 28, 256, NULL, NULL, NID_brainpoolP256r1 },
228 { GROUP_ECP, 29, 384, NULL, NULL, NID_brainpoolP384r1 },
229 { GROUP_ECP, 30, 512, NULL, NULL, NID_brainpoolP512r1 }
230 };
231
232 void
group_init(void)233 group_init(void)
234 {
235 /* currently not used */
236 return;
237 }
238
239 void
group_free(struct group * group)240 group_free(struct group *group)
241 {
242 if (group == NULL)
243 return;
244 if (group->dh != NULL)
245 DH_free(group->dh);
246 if (group->ec != NULL)
247 EC_KEY_free(group->ec);
248 group->spec = NULL;
249 free(group);
250 }
251
252 struct group *
group_get(u_int32_t id)253 group_get(u_int32_t id)
254 {
255 struct group_id *p = NULL;
256 struct group *group;
257 u_int i, items;
258
259 items = sizeof(ike_groups) / sizeof(ike_groups[0]);
260 for (i = 0; i < items; i++) {
261 if (id == ike_groups[i].id) {
262 p = &ike_groups[i];
263 break;
264 }
265 }
266 if (p == NULL)
267 return (NULL);
268
269 if ((group = calloc(1, sizeof(*group))) == NULL)
270 return (NULL);
271
272 group->id = id;
273 group->spec = p;
274
275 switch (p->type) {
276 case GROUP_MODP:
277 group->init = modp_init;
278 group->getlen = modp_getlen;
279 group->exchange = modp_create_exchange;
280 group->shared = modp_create_shared;
281 break;
282 #ifndef OPENSSL_NO_EC2M
283 case GROUP_EC2N:
284 #endif
285 case GROUP_ECP:
286 group->init = ec_init;
287 group->getlen = ec_getlen;
288 group->secretlen = ec_secretlen;
289 group->exchange = ec_create_exchange;
290 group->shared = ec_create_shared;
291 break;
292 default:
293 group_free(group);
294 return (NULL);
295 }
296
297 if (dh_init(group) != 0) {
298 group_free(group);
299 return (NULL);
300 }
301
302 return (group);
303 }
304
305 int
dh_init(struct group * group)306 dh_init(struct group *group)
307 {
308 return (group->init(group));
309 }
310
311 int
dh_getlen(struct group * group)312 dh_getlen(struct group *group)
313 {
314 return (group->getlen(group));
315 }
316
317 int
dh_secretlen(struct group * group)318 dh_secretlen(struct group *group)
319 {
320 if (group->secretlen)
321 return (group->secretlen(group));
322 else
323 return (group->getlen(group));
324 }
325
326 int
dh_create_exchange(struct group * group,u_int8_t * buf)327 dh_create_exchange(struct group *group, u_int8_t *buf)
328 {
329 return (group->exchange(group, buf));
330 }
331
332 int
dh_create_shared(struct group * group,u_int8_t * secret,u_int8_t * exchange)333 dh_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
334 {
335 return (group->shared(group, secret, exchange));
336 }
337
338 int
modp_init(struct group * group)339 modp_init(struct group *group)
340 {
341 DH *dh;
342 BIGNUM *p = NULL, *g = NULL;
343
344 if ((dh = DH_new()) == NULL)
345 return (-1);
346 group->dh = dh;
347
348 if (!BN_hex2bn(&p, group->spec->prime) ||
349 !BN_hex2bn(&g, group->spec->generator)) {
350 BN_free(p);
351 BN_free(g);
352 return (-1);
353 }
354
355 if (!DH_set0_pqg(dh, p, NULL, g)) {
356 BN_free(p);
357 BN_free(g);
358 return (-1);
359 }
360
361 return (0);
362 }
363
364 int
modp_getlen(struct group * group)365 modp_getlen(struct group *group)
366 {
367 if (group->spec == NULL)
368 return (0);
369 return (roundup(group->spec->bits, 8) / 8);
370 }
371
372 int
modp_create_exchange(struct group * group,u_int8_t * buf)373 modp_create_exchange(struct group *group, u_int8_t *buf)
374 {
375 DH *dh = group->dh;
376 int len, ret;
377
378 if (!DH_generate_key(dh))
379 return (-1);
380 ret = BN_bn2bin(DH_get0_pub_key(dh), buf);
381 if (!ret)
382 return (-1);
383
384 len = dh_getlen(group);
385
386 /* add zero padding */
387 if (ret < len) {
388 bcopy(buf, buf + (len - ret), ret);
389 bzero(buf, len - ret);
390 }
391
392 return (0);
393 }
394
395 int
modp_create_shared(struct group * group,u_int8_t * secret,u_int8_t * exchange)396 modp_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
397 {
398 BIGNUM *ex;
399 int len, ret;
400
401 len = dh_getlen(group);
402
403 if ((ex = BN_bin2bn(exchange, len, NULL)) == NULL)
404 return (-1);
405
406 ret = DH_compute_key(secret, ex, group->dh);
407 BN_clear_free(ex);
408 if (ret <= 0)
409 return (-1);
410
411 /* add zero padding */
412 if (ret < len) {
413 bcopy(secret, secret + (len - ret), ret);
414 bzero(secret, len - ret);
415 }
416
417 return (0);
418 }
419
420 int
ec_init(struct group * group)421 ec_init(struct group *group)
422 {
423 if ((group->ec = EC_KEY_new_by_curve_name(group->spec->nid)) == NULL)
424 return (-1);
425 if (!EC_KEY_generate_key(group->ec))
426 return (-1);
427 if (!EC_KEY_check_key(group->ec))
428 return (-1);
429 return (0);
430 }
431
432 int
ec_getlen(struct group * group)433 ec_getlen(struct group *group)
434 {
435 if (group->spec == NULL)
436 return (0);
437 /* NB: Return value will always be even */
438 return ((roundup(group->spec->bits, 8) * 2) / 8);
439 }
440
441 /*
442 * Note that the shared secret only includes the x value:
443 *
444 * See RFC 5903, 7. ECP Key Exchange Data Formats:
445 * The Diffie-Hellman shared secret value consists of the x value of the
446 * Diffie-Hellman common value.
447 * See also RFC 5903, 9. Changes from RFC 4753.
448 */
449 int
ec_secretlen(struct group * group)450 ec_secretlen(struct group *group)
451 {
452 return (ec_getlen(group) / 2);
453 }
454
455 int
ec_create_exchange(struct group * group,u_int8_t * buf)456 ec_create_exchange(struct group *group, u_int8_t *buf)
457 {
458 size_t len;
459
460 len = ec_getlen(group);
461 bzero(buf, len);
462
463 return (ec_point2raw(group, EC_KEY_get0_public_key(group->ec),
464 buf, len, EC_POINT2RAW_FULL));
465 }
466
467 int
ec_create_shared(struct group * group,u_int8_t * secret,u_int8_t * exchange)468 ec_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
469 {
470 const EC_GROUP *ecgroup = NULL;
471 const BIGNUM *privkey;
472 EC_KEY *exkey = NULL;
473 EC_POINT *exchangep = NULL, *secretp = NULL;
474 int ret = -1;
475
476 if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL ||
477 (privkey = EC_KEY_get0_private_key(group->ec)) == NULL)
478 goto done;
479
480 if ((exchangep =
481 ec_raw2point(group, exchange, ec_getlen(group))) == NULL)
482 goto done;
483
484 if ((exkey = EC_KEY_new()) == NULL)
485 goto done;
486 if (!EC_KEY_set_group(exkey, ecgroup))
487 goto done;
488 if (!EC_KEY_set_public_key(exkey, exchangep))
489 goto done;
490
491 /* validate exchangep */
492 if (!EC_KEY_check_key(exkey))
493 goto done;
494
495 if ((secretp = EC_POINT_new(ecgroup)) == NULL)
496 goto done;
497
498 if (!EC_POINT_mul(ecgroup, secretp, NULL, exchangep, privkey, NULL))
499 goto done;
500
501 ret = ec_point2raw(group, secretp, secret, ec_secretlen(group),
502 EC_POINT2RAW_XONLY);
503
504 done:
505 if (exkey != NULL)
506 EC_KEY_free(exkey);
507 if (exchangep != NULL)
508 EC_POINT_clear_free(exchangep);
509 if (secretp != NULL)
510 EC_POINT_clear_free(secretp);
511
512 return (ret);
513 }
514
515 int
ec_point2raw(struct group * group,const EC_POINT * point,u_int8_t * buf,size_t len,int mode)516 ec_point2raw(struct group *group, const EC_POINT *point,
517 u_int8_t *buf, size_t len, int mode)
518 {
519 const EC_GROUP *ecgroup = NULL;
520 BN_CTX *bnctx = NULL;
521 BIGNUM *x = NULL, *y = NULL;
522 int ret = -1;
523 size_t eclen, xlen, ylen;
524 off_t xoff, yoff;
525
526 if ((bnctx = BN_CTX_new()) == NULL)
527 goto done;
528 BN_CTX_start(bnctx);
529 if ((x = BN_CTX_get(bnctx)) == NULL ||
530 (y = BN_CTX_get(bnctx)) == NULL)
531 goto done;
532
533 eclen = ec_getlen(group);
534 switch (mode) {
535 case EC_POINT2RAW_XONLY:
536 xlen = eclen / 2;
537 ylen = 0;
538 break;
539 case EC_POINT2RAW_FULL:
540 xlen = ylen = eclen / 2;
541 break;
542 default:
543 goto done;
544 }
545 if (len < xlen + ylen)
546 goto done;
547
548 if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL)
549 goto done;
550
551 if (!EC_POINT_get_affine_coordinates(ecgroup, point, x, y, bnctx))
552 goto done;
553
554 xoff = xlen - BN_num_bytes(x);
555 bzero(buf, xoff);
556 if (!BN_bn2bin(x, buf + xoff))
557 goto done;
558
559 if (ylen > 0) {
560 yoff = (ylen - BN_num_bytes(y)) + xlen;
561 bzero(buf + xlen, yoff - xlen);
562 if (!BN_bn2bin(y, buf + yoff))
563 goto done;
564 }
565
566 ret = 0;
567 done:
568 /* Make sure to erase sensitive data */
569 if (x != NULL)
570 BN_clear(x);
571 if (y != NULL)
572 BN_clear(y);
573 BN_CTX_end(bnctx);
574 BN_CTX_free(bnctx);
575
576 return (ret);
577 }
578
579 EC_POINT *
ec_raw2point(struct group * group,u_int8_t * buf,size_t len)580 ec_raw2point(struct group *group, u_int8_t *buf, size_t len)
581 {
582 const EC_GROUP *ecgroup = NULL;
583 EC_POINT *point = NULL;
584 BN_CTX *bnctx = NULL;
585 BIGNUM *x = NULL, *y = NULL;
586 int ret = -1;
587 size_t eclen;
588 size_t xlen, ylen;
589
590 if ((bnctx = BN_CTX_new()) == NULL)
591 goto done;
592 BN_CTX_start(bnctx);
593 if ((x = BN_CTX_get(bnctx)) == NULL ||
594 (y = BN_CTX_get(bnctx)) == NULL)
595 goto done;
596
597 eclen = ec_getlen(group);
598 if (len < eclen)
599 goto done;
600 xlen = ylen = eclen / 2;
601 if ((x = BN_bin2bn(buf, xlen, x)) == NULL ||
602 (y = BN_bin2bn(buf + xlen, ylen, y)) == NULL)
603 goto done;
604
605 if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL)
606 goto done;
607
608 if ((point = EC_POINT_new(ecgroup)) == NULL)
609 goto done;
610
611 if (!EC_POINT_set_affine_coordinates(ecgroup, point, x, y, bnctx))
612 goto done;
613
614 ret = 0;
615 done:
616 if (ret != 0 && point != NULL)
617 EC_POINT_clear_free(point);
618 /* Make sure to erase sensitive data */
619 if (x != NULL)
620 BN_clear(x);
621 if (y != NULL)
622 BN_clear(y);
623 BN_CTX_end(bnctx);
624 BN_CTX_free(bnctx);
625
626 return (point);
627 }
628