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