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