dh.c revision 1.15
1/*	$OpenBSD: dh.c,v 1.15 2012/06/04 09:14:29 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	/* NB:  Return value will always be even */
465	return ((roundup(group->spec->bits, 8) * 2) / 8);
466}
467
468int
469ec_create_exchange(struct group *group, u_int8_t *buf)
470{
471	size_t	 len;
472
473	len = ec_getlen(group);
474	bzero(buf, len);
475
476	return (ec_point2raw(group, EC_KEY_get0_public_key(group->ec),
477	    buf, len));
478}
479
480int
481ec_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
482{
483	const EC_GROUP	*ecgroup = NULL;
484	const BIGNUM	*privkey;
485	EC_POINT	*exchangep = NULL, *secretp = NULL;
486	int		 ret = -1;
487
488	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL ||
489	    (privkey = EC_KEY_get0_private_key(group->ec)) == NULL)
490		goto done;
491
492	if ((exchangep =
493	    ec_raw2point(group, exchange, ec_getlen(group))) == NULL)
494		goto done;
495
496	if ((secretp = EC_POINT_new(ecgroup)) == NULL)
497		goto done;
498
499	if (!EC_POINT_mul(ecgroup, secretp, NULL, exchangep, privkey, NULL))
500		goto done;
501
502	ret = ec_point2raw(group, secretp, secret, ec_getlen(group));
503
504 done:
505	if (exchangep != NULL)
506		EC_POINT_clear_free(exchangep);
507	if (secretp != NULL)
508		EC_POINT_clear_free(secretp);
509
510	return (ret);
511}
512
513int
514ec_point2raw(struct group *group, const EC_POINT *point,
515    u_int8_t *buf, size_t len)
516{
517	const EC_GROUP	*ecgroup = NULL;
518	BN_CTX		*bnctx = NULL;
519	BIGNUM		*x = NULL, *y = NULL;
520	int		 ret = -1;
521	size_t		 eclen, xlen, ylen;
522	off_t		 xoff, yoff;
523
524	if ((bnctx = BN_CTX_new()) == NULL)
525		goto done;
526	BN_CTX_start(bnctx);
527	if ((x = BN_CTX_get(bnctx)) == NULL ||
528	    (y = BN_CTX_get(bnctx)) == NULL)
529		goto done;
530
531	eclen = ec_getlen(group);
532	if (len < eclen)
533		goto done;
534	xlen = ylen = eclen / 2;
535
536	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL)
537		goto done;
538
539	if (EC_METHOD_get_field_type(EC_GROUP_method_of(ecgroup)) ==
540	    NID_X9_62_prime_field) {
541		if (!EC_POINT_get_affine_coordinates_GFp(ecgroup,
542		    point, x, y, bnctx))
543			goto done;
544	} else {
545		if (!EC_POINT_get_affine_coordinates_GF2m(ecgroup,
546		    point, x, y, bnctx))
547			goto done;
548	}
549
550	xoff = xlen - BN_num_bytes(x);
551	bzero(buf, xoff);
552	if (!BN_bn2bin(x, buf + xoff))
553		goto done;
554
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	ret = 0;
561 done:
562	BN_CTX_end(bnctx);
563	BN_CTX_free(bnctx);
564
565	return (ret);
566}
567
568EC_POINT *
569ec_raw2point(struct group *group, u_int8_t *buf, size_t len)
570{
571	const EC_GROUP	*ecgroup = NULL;
572	EC_POINT	*point = NULL;
573	BN_CTX		*bnctx = NULL;
574	BIGNUM		*x = NULL, *y = NULL;
575	int		 ret = -1;
576	size_t		 eclen;
577	size_t		 xlen, ylen;
578
579	if ((bnctx = BN_CTX_new()) == NULL)
580		goto done;
581	BN_CTX_start(bnctx);
582	if ((x = BN_CTX_get(bnctx)) == NULL ||
583	    (y = BN_CTX_get(bnctx)) == NULL)
584		goto done;
585
586	eclen = ec_getlen(group);
587	if (len < eclen)
588		goto done;
589	xlen = ylen = eclen / 2;
590	if ((x = BN_bin2bn(buf, xlen, x)) == NULL ||
591	    (y = BN_bin2bn(buf + xlen, ylen, y)) == NULL)
592		goto done;
593
594	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL)
595		goto done;
596
597	if ((point = EC_POINT_new(ecgroup)) == NULL)
598		goto done;
599
600	if (EC_METHOD_get_field_type(EC_GROUP_method_of(ecgroup)) ==
601	    NID_X9_62_prime_field) {
602		if (!EC_POINT_set_affine_coordinates_GFp(ecgroup,
603		    point, x, y, bnctx))
604			goto done;
605	} else {
606		if (!EC_POINT_set_affine_coordinates_GF2m(ecgroup,
607		    point, x, y, bnctx))
608			goto done;
609	}
610
611	ret = 0;
612 done:
613	if (ret != 0 && point != NULL)
614		EC_POINT_clear_free(point);
615	BN_CTX_end(bnctx);
616	BN_CTX_free(bnctx);
617
618	return (point);
619}
620