dh.c revision 1.12
1/*	$OpenBSD: dh.c,v 1.12 2010/06/29 19:50:16 reyk 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	int	 codes;
405	DH	*dh = group->dh;
406
407	if (!DH_generate_key(dh))
408		return (-1);
409	if (!DH_check(dh, &codes))
410		return (-1);
411	if (!BN_bn2bin(dh->pub_key, buf))
412		return (-1);
413
414	return (0);
415}
416
417int
418modp_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
419{
420	BIGNUM	*ex;
421	int	 ret;
422
423	if ((ex = BN_bin2bn(exchange, dh_getlen(group), NULL)) == NULL)
424		return (-1);
425
426	ret = DH_compute_key(secret, ex, group->dh);
427	BN_clear_free(ex);
428	if (!ret)
429		return (-1);
430
431	return (0);
432}
433
434int
435ec_init(struct group *group)
436{
437	if ((group->ec = EC_KEY_new_by_curve_name(group->spec->nid)) == NULL)
438		return (-1);
439	if (!EC_KEY_generate_key(group->ec))
440		return (-1);
441	return (0);
442}
443
444int
445ec_getlen(struct group *group)
446{
447	if (group->spec == NULL)
448		return (0);
449	return ((roundup(group->spec->bits, 8) * 2) / 8);
450}
451
452int
453ec_create_exchange(struct group *group, u_int8_t *buf)
454{
455	size_t	 len;
456
457	len = ec_getlen(group);
458	bzero(buf, len);
459
460	return (ec_point2raw(group, EC_KEY_get0_public_key(group->ec),
461	    buf, len));
462}
463
464int
465ec_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
466{
467	const EC_GROUP	*ecgroup = NULL;
468	const BIGNUM	*privkey;
469	EC_POINT	*exchangep = NULL, *secretp = NULL;
470	int		 ret = -1;
471
472	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL ||
473	    (privkey = EC_KEY_get0_private_key(group->ec)) == NULL)
474		goto done;
475
476	if ((exchangep =
477	    ec_raw2point(group, exchange, ec_getlen(group))) == NULL)
478		goto done;
479
480	if ((secretp = EC_POINT_new(ecgroup)) == NULL)
481		goto done;
482
483	if (!EC_POINT_mul(ecgroup, secretp, NULL, exchangep, privkey, NULL))
484		goto done;
485
486	ret = ec_point2raw(group, secretp, secret, ec_getlen(group));
487
488 done:
489	if (exchangep != NULL)
490		EC_POINT_clear_free(exchangep);
491	if (secretp != NULL)
492		EC_POINT_clear_free(secretp);
493
494	return (ret);
495}
496
497int
498ec_point2raw(struct group *group, const EC_POINT *point,
499    u_int8_t *buf, size_t len)
500{
501	const EC_GROUP	*ecgroup = NULL;
502	BN_CTX		*bnctx = NULL;
503	BIGNUM		*x = NULL, *y = NULL;
504	int		 ret = -1;
505	size_t		 xlen, ylen;
506	off_t		 xoff, yoff;
507
508	if ((bnctx = BN_CTX_new()) == NULL)
509		goto done;
510	BN_CTX_start(bnctx);
511	if ((x = BN_CTX_get(bnctx)) == NULL ||
512	    (y = BN_CTX_get(bnctx)) == NULL)
513		goto done;
514
515	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL)
516		goto done;
517
518	if (EC_METHOD_get_field_type(EC_GROUP_method_of(ecgroup)) ==
519	    NID_X9_62_prime_field) {
520		if (!EC_POINT_get_affine_coordinates_GFp(ecgroup,
521		    point, x, y, bnctx))
522			goto done;
523	} else {
524		if (!EC_POINT_get_affine_coordinates_GF2m(ecgroup,
525		    point, x, y, bnctx))
526			goto done;
527	}
528
529	xlen = roundup(BN_num_bytes(x), 2);
530	xoff = xlen - BN_num_bytes(x);
531	if (!BN_bn2bin(x, buf + xoff))
532		goto done;
533
534	ylen = roundup(BN_num_bytes(y), 2);
535	yoff = (ylen - BN_num_bytes(y)) + xlen;
536	if (!BN_bn2bin(y, buf + yoff))
537		goto done;
538
539	ret = 0;
540 done:
541	BN_CTX_end(bnctx);
542	BN_CTX_free(bnctx);
543
544	return (ret);
545}
546
547EC_POINT *
548ec_raw2point(struct group *group, u_int8_t *buf, size_t len)
549{
550	const EC_GROUP	*ecgroup = NULL;
551	EC_POINT	*point = NULL;
552	BN_CTX		*bnctx = NULL;
553	BIGNUM		*x = NULL, *y = NULL;
554	int		 ret = -1;
555	size_t		 eclen;
556	size_t		 xlen, ylen;
557
558	if ((bnctx = BN_CTX_new()) == NULL)
559		goto done;
560	BN_CTX_start(bnctx);
561	if ((x = BN_CTX_get(bnctx)) == NULL ||
562	    (y = BN_CTX_get(bnctx)) == NULL)
563		goto done;
564
565	eclen = ec_getlen(group);
566	if (len < eclen)
567		goto done;
568	xlen = ylen = eclen / 2;
569	if ((x = BN_bin2bn(buf, xlen, x)) == NULL ||
570	    (y = BN_bin2bn(buf + xlen, ylen, y)) == NULL)
571		goto done;
572
573	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL)
574		goto done;
575
576	if ((point = EC_POINT_new(ecgroup)) == NULL)
577		goto done;
578
579	if (EC_METHOD_get_field_type(EC_GROUP_method_of(ecgroup)) ==
580	    NID_X9_62_prime_field) {
581		if (!EC_POINT_set_affine_coordinates_GFp(ecgroup,
582		    point, x, y, bnctx))
583			goto done;
584	} else {
585		if (!EC_POINT_set_affine_coordinates_GF2m(ecgroup,
586		    point, x, y, bnctx))
587			goto done;
588	}
589
590	ret = 0;
591 done:
592	if (ret != 0 && point != NULL)
593		EC_POINT_clear_free(point);
594	BN_CTX_end(bnctx);
595	BN_CTX_free(bnctx);
596
597	return (point);
598}
599