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