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