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
40 int dh_init(struct dh_group *);
41 int dh_getlen(struct dh_group *);
42 int dh_secretlen(struct dh_group *);
43
44 /* MODP */
45 int modp_init(struct dh_group *);
46 int modp_getlen(struct dh_group *);
47 int modp_create_exchange(struct dh_group *, uint8_t *);
48 int modp_create_shared(struct dh_group *, uint8_t *, uint8_t *);
49
50 /* ECP */
51 int ec_init(struct dh_group *);
52 int ec_getlen(struct dh_group *);
53 int ec_secretlen(struct dh_group *);
54 int ec_create_exchange(struct dh_group *, uint8_t *);
55 int ec_create_shared(struct dh_group *, uint8_t *, uint8_t *);
56
57 #define EC_POINT2RAW_FULL 0
58 #define EC_POINT2RAW_XONLY 1
59 int ec_point2raw(struct dh_group *, const EC_POINT *, uint8_t *, size_t, int);
60 EC_POINT *
61 ec_raw2point(struct dh_group *, uint8_t *, size_t);
62
63 /* curve25519 */
64 int ec25519_init(struct dh_group *);
65 int ec25519_getlen(struct dh_group *);
66 int ec25519_create_exchange(struct dh_group *, uint8_t *);
67 int ec25519_create_shared(struct dh_group *, uint8_t *, uint8_t *);
68
69 #define CURVE25519_SIZE 32 /* 256 bits */
70 struct curve25519_key {
71 uint8_t secret[CURVE25519_SIZE];
72 uint8_t public[CURVE25519_SIZE];
73 };
74 extern 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 */
82 int kemsx_init(struct dh_group *);
83 int kemsx_getlen(struct dh_group *);
84 int kemsx_create_exchange2(struct dh_group *, struct ibuf **, struct ibuf *);
85 int kemsx_create_shared2(struct dh_group *, struct ibuf **, struct ibuf *);
86
87 struct 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
94 const 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
279 void
group_init(void)280 group_init(void)
281 {
282 /* currently not used */
283 return;
284 }
285
286 void
group_free(struct dh_group * group)287 group_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
301 struct dh_group *
group_get(uint32_t id)302 group_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
355 const struct group_id *
group_getid(uint32_t id)356 group_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
371 int
dh_init(struct dh_group * group)372 dh_init(struct dh_group *group)
373 {
374 return (group->init(group));
375 }
376
377 int
dh_getlen(struct dh_group * group)378 dh_getlen(struct dh_group *group)
379 {
380 return (group->getlen(group));
381 }
382
383 int
dh_secretlen(struct dh_group * group)384 dh_secretlen(struct dh_group *group)
385 {
386 if (group->secretlen)
387 return (group->secretlen(group));
388 else
389 return (group->getlen(group));
390 }
391
392 int
dh_create_exchange(struct dh_group * group,struct ibuf ** bufp,struct ibuf * iexchange)393 dh_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
407 int
dh_create_shared(struct dh_group * group,struct ibuf ** secretp,struct ibuf * exchange)408 dh_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
425 int
modp_init(struct dh_group * group)426 modp_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
451 int
modp_getlen(struct dh_group * group)452 modp_getlen(struct dh_group *group)
453 {
454 if (group->spec == NULL)
455 return (0);
456 return (roundup(group->spec->bits, 8) / 8);
457 }
458
459 int
modp_create_exchange(struct dh_group * group,uint8_t * buf)460 modp_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
484 int
modp_create_shared(struct dh_group * group,uint8_t * secret,uint8_t * exchange)485 modp_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
509 int
ec_init(struct dh_group * group)510 ec_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
521 int
ec_getlen(struct dh_group * group)522 ec_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 */
538 int
ec_secretlen(struct dh_group * group)539 ec_secretlen(struct dh_group *group)
540 {
541 return (ec_getlen(group) / 2);
542 }
543
544 int
ec_create_exchange(struct dh_group * group,uint8_t * buf)545 ec_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
556 int
ec_create_shared(struct dh_group * group,uint8_t * secret,uint8_t * exchange)557 ec_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
604 int
ec_point2raw(struct dh_group * group,const EC_POINT * point,uint8_t * buf,size_t len,int mode)605 ec_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
668 EC_POINT *
ec_raw2point(struct dh_group * group,uint8_t * buf,size_t len)669 ec_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
718 int
ec25519_init(struct dh_group * group)719 ec25519_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
736 int
ec25519_getlen(struct dh_group * group)737 ec25519_getlen(struct dh_group *group)
738 {
739 if (group->spec == NULL)
740 return (0);
741 return (CURVE25519_SIZE);
742 }
743
744 int
ec25519_create_exchange(struct dh_group * group,uint8_t * buf)745 ec25519_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
753 int
ec25519_create_shared(struct dh_group * group,uint8_t * shared,uint8_t * public)754 ec25519_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
764 int
kemsx_init(struct dh_group * group)765 kemsx_init(struct dh_group *group)
766 {
767 /* delayed until kemsx_create_exchange2 */
768 return (0);
769 }
770
771 int
kemsx_getlen(struct dh_group * group)772 kemsx_getlen(struct dh_group *group)
773 {
774 return (0);
775 }
776
777 int
kemsx_create_exchange2(struct dh_group * group,struct ibuf ** bufp,struct ibuf * iexchange)778 kemsx_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
833 int
kemsx_create_shared2(struct dh_group * group,struct ibuf ** sharedp,struct ibuf * exchange)834 kemsx_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