dh.c revision 1.13
1/*	$OpenBSD: dh.c,v 1.13 2010/11/29 22:49:26 markus Exp $	*/
2/*	$vantronix: dh.c,v 1.13 2010/05/28 15:34:35 reyk Exp $	*/
3
4/*
5 * Copyright (c) 2010 Reyk Floeter <reyk@vantronix.net>
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18 */
19
20#include <sys/param.h>
21#include <string.h>
22
23#include <openssl/obj_mac.h>
24#include <openssl/dh.h>
25#include <openssl/ec.h>
26#include <openssl/ecdh.h>
27
28#include "dh.h"
29
30int	dh_init(struct group *);
31
32int	modp_init(struct group *);
33int	modp_getlen(struct group *);
34int	modp_create_exchange(struct group *, u_int8_t *);
35int	modp_create_shared(struct group *, u_int8_t *, u_int8_t *);
36
37int	ec_init(struct group *);
38int	ec_getlen(struct group *);
39int	ec_create_exchange(struct group *, u_int8_t *);
40int	ec_create_shared(struct group *, u_int8_t *, u_int8_t *);
41
42int	ec_point2raw(struct group *, const EC_POINT *, u_int8_t *, size_t);
43EC_POINT *
44	ec_raw2point(struct group *, u_int8_t *, size_t);
45
46struct group_id ike_groups[] = {
47	{ GROUP_MODP, 1, 768,
48	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
49	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
50	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
51	    "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF",
52	    "02"
53	},
54	{ GROUP_MODP, 2, 1024,
55	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
56	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
57	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
58	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
59	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
60	    "FFFFFFFFFFFFFFFF",
61	    "02"
62	},
63	{ GROUP_EC2N, 3, 155, NULL, NULL, NID_ipsec3 },
64	{ GROUP_EC2N, 4, 185, NULL, NULL, NID_ipsec4 },
65	{ GROUP_MODP, 5, 1536,
66	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
67	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
68	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
69	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
70	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
71	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
72	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
73	    "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF",
74	    "02"
75	},
76	{ GROUP_MODP, 14, 2048,
77	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
78	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
79	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
80	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
81	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
82	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
83	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
84	    "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
85	    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
86	    "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
87	    "15728E5A8AACAA68FFFFFFFFFFFFFFFF",
88	    "02"
89	},
90	{ GROUP_MODP, 15, 3072,
91	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
92	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
93	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
94	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
95	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
96	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
97	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
98	    "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
99	    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
100	    "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
101	    "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
102	    "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
103	    "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
104	    "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
105	    "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
106	    "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF",
107	    "02"
108	},
109	{ GROUP_MODP, 16, 4096,
110	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
111	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
112	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
113	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
114	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
115	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
116	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
117	    "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
118	    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
119	    "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
120	    "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
121	    "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
122	    "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
123	    "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
124	    "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
125	    "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
126	    "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
127	    "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
128	    "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
129	    "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
130	    "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199"
131	    "FFFFFFFFFFFFFFFF",
132	    "02"
133	},
134	{ GROUP_MODP, 17, 6144,
135	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
136	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
137	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
138	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
139	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
140	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
141	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
142	    "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
143	    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
144	    "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
145	    "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
146	    "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
147	    "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
148	    "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
149	    "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
150	    "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
151	    "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
152	    "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
153	    "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
154	    "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
155	    "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
156	    "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"
157	    "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
158	    "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
159	    "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
160	    "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"
161	    "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
162	    "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
163	    "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
164	    "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
165	    "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
166	    "12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF",
167	    "02"
168	},
169	{ GROUP_MODP, 18, 8192,
170	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
171	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
172	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
173	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
174	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
175	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
176	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
177	    "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
178	    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
179	    "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
180	    "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
181	    "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
182	    "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
183	    "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
184	    "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
185	    "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
186	    "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
187	    "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
188	    "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
189	    "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
190	    "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
191	    "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"
192	    "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
193	    "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
194	    "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
195	    "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"
196	    "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
197	    "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
198	    "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
199	    "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
200	    "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
201	    "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4"
202	    "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300"
203	    "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568"
204	    "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9"
205	    "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B"
206	    "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A"
207	    "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36"
208	    "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1"
209	    "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92"
210	    "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47"
211	    "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71"
212	    "60C980DD98EDD3DFFFFFFFFFFFFFFFFF",
213	    "02"
214	},
215	{ GROUP_ECP, 19, 256, NULL, NULL, NID_X9_62_prime256v1 },
216	{ GROUP_ECP, 20, 384, NULL, NULL, NID_secp384r1 },
217	{ GROUP_ECP, 21, 521, NULL, NULL, NID_secp521r1 },
218	{ GROUP_MODP, 22, 1024,
219	    "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C6"
220	    "9A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C0"
221	    "13ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD70"
222	    "98488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0"
223	    "A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708"
224	    "DF1FB2BC2E4A4371",
225	    "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507F"
226	    "D6406CFF14266D31266FEA1E5C41564B777E690F5504F213"
227	    "160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1"
228	    "909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A"
229	    "D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24"
230	    "855E6EEB22B3B2E5"
231	},
232	{ GROUP_MODP, 23, 2048,
233	    "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1"
234	    "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15"
235	    "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212"
236	    "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207"
237	    "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708"
238	    "B3BF8A317091883681286130BC8985DB1602E714415D9330"
239	    "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D"
240	    "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8"
241	    "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763"
242	    "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71"
243	    "CF9DE5384E71B81C0AC4DFFE0C10E64F",
244	    "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF"
245	    "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA"
246	    "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7"
247	    "C17669101999024AF4D027275AC1348BB8A762D0521BC98A"
248	    "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE"
249	    "F180EB34118E98D119529A45D6F834566E3025E316A330EF"
250	    "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB"
251	    "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381"
252	    "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269"
253	    "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179"
254	    "81BC087F2A7065B384B890D3191F2BFA"
255	},
256	{ GROUP_MODP, 24, 2048,
257	    "87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F2"
258	    "5D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA30"
259	    "16C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD"
260	    "5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B"
261	    "6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C"
262	    "4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0E"
263	    "F13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D9"
264	    "67E144E5140564251CCACB83E6B486F6B3CA3F7971506026"
265	    "C0B857F689962856DED4010ABD0BE621C3A3960A54E710C3"
266	    "75F26375D7014103A4B54330C198AF126116D2276E11715F"
267	    "693877FAD7EF09CADB094AE91E1A1597",
268	    "3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF2054"
269	    "07F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555"
270	    "BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18"
271	    "A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B"
272	    "777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC83"
273	    "1D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55"
274	    "A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14"
275	    "C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915"
276	    "B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6"
277	    "184B523D1DB246C32F63078490F00EF8D647D148D4795451"
278	    "5E2327CFEF98C582664B4C0F6CC41659"
279	},
280	{ GROUP_ECP, 25, 192, NULL, NULL, NID_X9_62_prime192v1 },
281	{ GROUP_ECP, 26, 224, NULL, NULL, NID_secp224r1 }
282};
283
284void
285group_init(void)
286{
287	/* currently not used */
288	return;
289}
290
291void
292group_free(struct group *group)
293{
294	if (group == NULL)
295		return;
296	if (group->dh != NULL)
297		DH_free(group->dh);
298	if (group->ec != NULL)
299		EC_KEY_free(group->ec);
300	group->spec = NULL;
301}
302
303struct group *
304group_get(u_int32_t id)
305{
306	struct group_id	*p = NULL;
307	struct group	*group;
308	u_int		 i, items;
309
310	items = sizeof(ike_groups) / sizeof(ike_groups[0]);
311	for (i = 0; i < items; i++) {
312		if (id == ike_groups[i].id) {
313			p = &ike_groups[i];
314			break;
315		}
316	}
317	if (p == NULL)
318		return (NULL);
319
320	if ((group = calloc(1, sizeof(*group))) == NULL)
321		return (NULL);
322
323	group->id = id;
324	group->spec = p;
325
326	switch (p->type) {
327	case GROUP_MODP:
328		group->init = modp_init;
329		group->getlen = modp_getlen;
330		group->exchange = modp_create_exchange;
331		group->shared = modp_create_shared;
332		break;
333	case GROUP_EC2N:
334	case GROUP_ECP:
335		group->init = ec_init;
336		group->getlen = ec_getlen;
337		group->exchange = ec_create_exchange;
338		group->shared = ec_create_shared;
339		break;
340	default:
341		group_free(group);
342		return (NULL);
343	}
344
345	if (dh_init(group) != 0) {
346		group_free(group);
347		return (NULL);
348	}
349
350	return (group);
351}
352
353int
354dh_init(struct group *group)
355{
356	return (group->init(group));
357}
358
359int
360dh_getlen(struct group *group)
361{
362	return (group->getlen(group));
363}
364
365int
366dh_create_exchange(struct group *group, u_int8_t *buf)
367{
368	return (group->exchange(group, buf));
369}
370
371int
372dh_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
373{
374	return (group->shared(group, secret, exchange));
375}
376
377int
378modp_init(struct group *group)
379{
380	DH	*dh;
381
382	if ((dh = DH_new()) == NULL)
383		return (-1);
384	group->dh = dh;
385
386	if (!BN_hex2bn(&dh->p, group->spec->prime) ||
387	    !BN_hex2bn(&dh->g, group->spec->generator))
388		return (-1);
389
390	return (0);
391}
392
393int
394modp_getlen(struct group *group)
395{
396	if (group->spec == NULL)
397		return (0);
398	return (roundup(group->spec->bits, 8) / 8);
399}
400
401int
402modp_create_exchange(struct group *group, u_int8_t *buf)
403{
404	DH	*dh = group->dh;
405
406	if (!DH_generate_key(dh))
407		return (-1);
408	if (!BN_bn2bin(dh->pub_key, buf))
409		return (-1);
410
411	return (0);
412}
413
414int
415modp_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
416{
417	BIGNUM	*ex;
418	int	 ret;
419
420	if ((ex = BN_bin2bn(exchange, dh_getlen(group), NULL)) == NULL)
421		return (-1);
422
423	ret = DH_compute_key(secret, ex, group->dh);
424	BN_clear_free(ex);
425	if (!ret)
426		return (-1);
427
428	return (0);
429}
430
431int
432ec_init(struct group *group)
433{
434	if ((group->ec = EC_KEY_new_by_curve_name(group->spec->nid)) == NULL)
435		return (-1);
436	if (!EC_KEY_generate_key(group->ec))
437		return (-1);
438	return (0);
439}
440
441int
442ec_getlen(struct group *group)
443{
444	if (group->spec == NULL)
445		return (0);
446	return ((roundup(group->spec->bits, 8) * 2) / 8);
447}
448
449int
450ec_create_exchange(struct group *group, u_int8_t *buf)
451{
452	size_t	 len;
453
454	len = ec_getlen(group);
455	bzero(buf, len);
456
457	return (ec_point2raw(group, EC_KEY_get0_public_key(group->ec),
458	    buf, len));
459}
460
461int
462ec_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
463{
464	const EC_GROUP	*ecgroup = NULL;
465	const BIGNUM	*privkey;
466	EC_POINT	*exchangep = NULL, *secretp = NULL;
467	int		 ret = -1;
468
469	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL ||
470	    (privkey = EC_KEY_get0_private_key(group->ec)) == NULL)
471		goto done;
472
473	if ((exchangep =
474	    ec_raw2point(group, exchange, ec_getlen(group))) == NULL)
475		goto done;
476
477	if ((secretp = EC_POINT_new(ecgroup)) == NULL)
478		goto done;
479
480	if (!EC_POINT_mul(ecgroup, secretp, NULL, exchangep, privkey, NULL))
481		goto done;
482
483	ret = ec_point2raw(group, secretp, secret, ec_getlen(group));
484
485 done:
486	if (exchangep != NULL)
487		EC_POINT_clear_free(exchangep);
488	if (secretp != NULL)
489		EC_POINT_clear_free(secretp);
490
491	return (ret);
492}
493
494int
495ec_point2raw(struct group *group, const EC_POINT *point,
496    u_int8_t *buf, size_t len)
497{
498	const EC_GROUP	*ecgroup = NULL;
499	BN_CTX		*bnctx = NULL;
500	BIGNUM		*x = NULL, *y = NULL;
501	int		 ret = -1;
502	size_t		 xlen, ylen;
503	off_t		 xoff, yoff;
504
505	if ((bnctx = BN_CTX_new()) == NULL)
506		goto done;
507	BN_CTX_start(bnctx);
508	if ((x = BN_CTX_get(bnctx)) == NULL ||
509	    (y = BN_CTX_get(bnctx)) == NULL)
510		goto done;
511
512	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL)
513		goto done;
514
515	if (EC_METHOD_get_field_type(EC_GROUP_method_of(ecgroup)) ==
516	    NID_X9_62_prime_field) {
517		if (!EC_POINT_get_affine_coordinates_GFp(ecgroup,
518		    point, x, y, bnctx))
519			goto done;
520	} else {
521		if (!EC_POINT_get_affine_coordinates_GF2m(ecgroup,
522		    point, x, y, bnctx))
523			goto done;
524	}
525
526	xlen = roundup(BN_num_bytes(x), 2);
527	xoff = xlen - BN_num_bytes(x);
528	if (!BN_bn2bin(x, buf + xoff))
529		goto done;
530
531	ylen = roundup(BN_num_bytes(y), 2);
532	yoff = (ylen - BN_num_bytes(y)) + xlen;
533	if (!BN_bn2bin(y, buf + yoff))
534		goto done;
535
536	ret = 0;
537 done:
538	BN_CTX_end(bnctx);
539	BN_CTX_free(bnctx);
540
541	return (ret);
542}
543
544EC_POINT *
545ec_raw2point(struct group *group, u_int8_t *buf, size_t len)
546{
547	const EC_GROUP	*ecgroup = NULL;
548	EC_POINT	*point = NULL;
549	BN_CTX		*bnctx = NULL;
550	BIGNUM		*x = NULL, *y = NULL;
551	int		 ret = -1;
552	size_t		 eclen;
553	size_t		 xlen, ylen;
554
555	if ((bnctx = BN_CTX_new()) == NULL)
556		goto done;
557	BN_CTX_start(bnctx);
558	if ((x = BN_CTX_get(bnctx)) == NULL ||
559	    (y = BN_CTX_get(bnctx)) == NULL)
560		goto done;
561
562	eclen = ec_getlen(group);
563	if (len < eclen)
564		goto done;
565	xlen = ylen = eclen / 2;
566	if ((x = BN_bin2bn(buf, xlen, x)) == NULL ||
567	    (y = BN_bin2bn(buf + xlen, ylen, y)) == NULL)
568		goto done;
569
570	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL)
571		goto done;
572
573	if ((point = EC_POINT_new(ecgroup)) == NULL)
574		goto done;
575
576	if (EC_METHOD_get_field_type(EC_GROUP_method_of(ecgroup)) ==
577	    NID_X9_62_prime_field) {
578		if (!EC_POINT_set_affine_coordinates_GFp(ecgroup,
579		    point, x, y, bnctx))
580			goto done;
581	} else {
582		if (!EC_POINT_set_affine_coordinates_GF2m(ecgroup,
583		    point, x, y, bnctx))
584			goto done;
585	}
586
587	ret = 0;
588 done:
589	if (ret != 0 && point != NULL)
590		EC_POINT_clear_free(point);
591	BN_CTX_end(bnctx);
592	BN_CTX_free(bnctx);
593
594	return (point);
595}
596