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