GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: sbin/isakmpd/dh.c Lines: 0 159 0.0 %
Date: 2017-11-13 Branches: 0 131 0.0 %

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