xref: /openbsd-src/sbin/isakmpd/dh.c (revision f51d8a344da2c3e0999375e44a80acaae4c4543b)
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