dh.c revision 1.19
1/*	$OpenBSD: dh.c,v 1.19 2015/01/16 06:39:58 deraadt Exp $	*/
2
3/*
4 * Copyright (c) 2010-2014 Reyk Floeter <reyk@openbsd.org>
5 *
6 * Permission to use, copy, modify, and distribute this software for any
7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
9 *
10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include <sys/param.h>	/* roundup */
20#include <string.h>
21
22#include <openssl/obj_mac.h>
23#include <openssl/dh.h>
24#include <openssl/ec.h>
25#include <openssl/ecdh.h>
26#include <openssl/bn.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	{ GROUP_ECP, 27, 224, NULL, NULL, NID_brainpoolP224r1 },
283	{ GROUP_ECP, 28, 256, NULL, NULL, NID_brainpoolP256r1 },
284	{ GROUP_ECP, 29, 384, NULL, NULL, NID_brainpoolP384r1 },
285	{ GROUP_ECP, 30, 512, NULL, NULL, NID_brainpoolP512r1 }
286};
287
288void
289group_init(void)
290{
291	/* currently not used */
292	return;
293}
294
295void
296group_free(struct group *group)
297{
298	if (group == NULL)
299		return;
300	if (group->dh != NULL)
301		DH_free(group->dh);
302	if (group->ec != NULL)
303		EC_KEY_free(group->ec);
304	group->spec = NULL;
305	free(group);
306}
307
308struct group *
309group_get(u_int32_t id)
310{
311	struct group_id	*p = NULL;
312	struct group	*group;
313	u_int		 i, items;
314
315	items = sizeof(ike_groups) / sizeof(ike_groups[0]);
316	for (i = 0; i < items; i++) {
317		if (id == ike_groups[i].id) {
318			p = &ike_groups[i];
319			break;
320		}
321	}
322	if (p == NULL)
323		return (NULL);
324
325	if ((group = calloc(1, sizeof(*group))) == NULL)
326		return (NULL);
327
328	group->id = id;
329	group->spec = p;
330
331	switch (p->type) {
332	case GROUP_MODP:
333		group->init = modp_init;
334		group->getlen = modp_getlen;
335		group->exchange = modp_create_exchange;
336		group->shared = modp_create_shared;
337		break;
338	case GROUP_EC2N:
339	case GROUP_ECP:
340		group->init = ec_init;
341		group->getlen = ec_getlen;
342		group->exchange = ec_create_exchange;
343		group->shared = ec_create_shared;
344		break;
345	default:
346		group_free(group);
347		return (NULL);
348	}
349
350	if (dh_init(group) != 0) {
351		group_free(group);
352		return (NULL);
353	}
354
355	return (group);
356}
357
358int
359dh_init(struct group *group)
360{
361	return (group->init(group));
362}
363
364int
365dh_getlen(struct group *group)
366{
367	return (group->getlen(group));
368}
369
370int
371dh_create_exchange(struct group *group, u_int8_t *buf)
372{
373	return (group->exchange(group, buf));
374}
375
376int
377dh_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
378{
379	return (group->shared(group, secret, exchange));
380}
381
382int
383modp_init(struct group *group)
384{
385	DH	*dh;
386
387	if ((dh = DH_new()) == NULL)
388		return (-1);
389	group->dh = dh;
390
391	if (!BN_hex2bn(&dh->p, group->spec->prime) ||
392	    !BN_hex2bn(&dh->g, group->spec->generator))
393		return (-1);
394
395	return (0);
396}
397
398int
399modp_getlen(struct group *group)
400{
401	if (group->spec == NULL)
402		return (0);
403	return (roundup(group->spec->bits, 8) / 8);
404}
405
406int
407modp_create_exchange(struct group *group, u_int8_t *buf)
408{
409	DH	*dh = group->dh;
410	int	 len, ret;
411
412	if (!DH_generate_key(dh))
413		return (-1);
414	ret = BN_bn2bin(dh->pub_key, buf);
415	if (!ret)
416		return (-1);
417
418	len = dh_getlen(group);
419
420	/* add zero padding */
421	if (ret < len) {
422		bcopy(buf, buf + (len - ret), ret);
423		bzero(buf, len - ret);
424	}
425
426	return (0);
427}
428
429int
430modp_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
431{
432	BIGNUM	*ex;
433	int	 len, ret;
434
435	len = dh_getlen(group);
436
437	if ((ex = BN_bin2bn(exchange, len, NULL)) == NULL)
438		return (-1);
439
440	ret = DH_compute_key(secret, ex, group->dh);
441	BN_clear_free(ex);
442	if (ret <= 0)
443		return (-1);
444
445	/* add zero padding */
446	if (ret < len) {
447		bcopy(secret, secret + (len - ret), ret);
448		bzero(secret, len - ret);
449	}
450
451	return (0);
452}
453
454int
455ec_init(struct group *group)
456{
457	if ((group->ec = EC_KEY_new_by_curve_name(group->spec->nid)) == NULL)
458		return (-1);
459	if (!EC_KEY_generate_key(group->ec))
460		return (-1);
461	if (!EC_KEY_check_key(group->ec)) {
462		EC_KEY_free(group->ec);
463		return (-1);
464	}
465	return (0);
466}
467
468int
469ec_getlen(struct group *group)
470{
471	if (group->spec == NULL)
472		return (0);
473	/* NB:  Return value will always be even */
474	return ((roundup(group->spec->bits, 8) * 2) / 8);
475}
476
477int
478ec_create_exchange(struct group *group, u_int8_t *buf)
479{
480	size_t	 len;
481
482	len = ec_getlen(group);
483	bzero(buf, len);
484
485	return (ec_point2raw(group, EC_KEY_get0_public_key(group->ec),
486	    buf, len));
487}
488
489int
490ec_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
491{
492	const EC_GROUP	*ecgroup = NULL;
493	const BIGNUM	*privkey;
494	EC_KEY		*exkey = NULL;
495	EC_POINT	*exchangep = NULL, *secretp = NULL;
496	int		 ret = -1;
497
498	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL ||
499	    (privkey = EC_KEY_get0_private_key(group->ec)) == NULL)
500		goto done;
501
502	if ((exchangep =
503	    ec_raw2point(group, exchange, ec_getlen(group))) == NULL)
504		goto done;
505
506	if ((exkey = EC_KEY_new()) == NULL)
507		goto done;
508	if (!EC_KEY_set_group(exkey, ecgroup))
509		goto done;
510	if (!EC_KEY_set_public_key(exkey, exchangep))
511		goto done;
512
513	/* validate exchangep */
514	if (!EC_KEY_check_key(exkey))
515		goto done;
516
517	if ((secretp = EC_POINT_new(ecgroup)) == NULL)
518		goto done;
519
520	if (!EC_POINT_mul(ecgroup, secretp, NULL, exchangep, privkey, NULL))
521		goto done;
522
523	ret = ec_point2raw(group, secretp, secret, ec_getlen(group));
524
525 done:
526	if (exkey != NULL)
527		EC_KEY_free(exkey);
528	if (exchangep != NULL)
529		EC_POINT_clear_free(exchangep);
530	if (secretp != NULL)
531		EC_POINT_clear_free(secretp);
532
533	return (ret);
534}
535
536int
537ec_point2raw(struct group *group, const EC_POINT *point,
538    u_int8_t *buf, size_t len)
539{
540	const EC_GROUP	*ecgroup = NULL;
541	BN_CTX		*bnctx = NULL;
542	BIGNUM		*x = NULL, *y = NULL;
543	int		 ret = -1;
544	size_t		 eclen, xlen, ylen;
545	off_t		 xoff, yoff;
546
547	if ((bnctx = BN_CTX_new()) == NULL)
548		goto done;
549	BN_CTX_start(bnctx);
550	if ((x = BN_CTX_get(bnctx)) == NULL ||
551	    (y = BN_CTX_get(bnctx)) == NULL)
552		goto done;
553
554	eclen = ec_getlen(group);
555	if (len < eclen)
556		goto done;
557	xlen = ylen = eclen / 2;
558
559	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL)
560		goto done;
561
562	if (EC_METHOD_get_field_type(EC_GROUP_method_of(ecgroup)) ==
563	    NID_X9_62_prime_field) {
564		if (!EC_POINT_get_affine_coordinates_GFp(ecgroup,
565		    point, x, y, bnctx))
566			goto done;
567	} else {
568		if (!EC_POINT_get_affine_coordinates_GF2m(ecgroup,
569		    point, x, y, bnctx))
570			goto done;
571	}
572
573	xoff = xlen - BN_num_bytes(x);
574	bzero(buf, xoff);
575	if (!BN_bn2bin(x, buf + xoff))
576		goto done;
577
578	yoff = (ylen - BN_num_bytes(y)) + xlen;
579	bzero(buf + xlen, yoff - xlen);
580	if (!BN_bn2bin(y, buf + yoff))
581		goto done;
582
583	ret = 0;
584 done:
585	/* Make sure to erase sensitive data */
586	if (x != NULL)
587		BN_clear(x);
588	if (y != NULL)
589		BN_clear(y);
590	BN_CTX_end(bnctx);
591	BN_CTX_free(bnctx);
592
593	return (ret);
594}
595
596EC_POINT *
597ec_raw2point(struct group *group, u_int8_t *buf, size_t len)
598{
599	const EC_GROUP	*ecgroup = NULL;
600	EC_POINT	*point = NULL;
601	BN_CTX		*bnctx = NULL;
602	BIGNUM		*x = NULL, *y = NULL;
603	int		 ret = -1;
604	size_t		 eclen;
605	size_t		 xlen, ylen;
606
607	if ((bnctx = BN_CTX_new()) == NULL)
608		goto done;
609	BN_CTX_start(bnctx);
610	if ((x = BN_CTX_get(bnctx)) == NULL ||
611	    (y = BN_CTX_get(bnctx)) == NULL)
612		goto done;
613
614	eclen = ec_getlen(group);
615	if (len < eclen)
616		goto done;
617	xlen = ylen = eclen / 2;
618	if ((x = BN_bin2bn(buf, xlen, x)) == NULL ||
619	    (y = BN_bin2bn(buf + xlen, ylen, y)) == NULL)
620		goto done;
621
622	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL)
623		goto done;
624
625	if ((point = EC_POINT_new(ecgroup)) == NULL)
626		goto done;
627
628	if (EC_METHOD_get_field_type(EC_GROUP_method_of(ecgroup)) ==
629	    NID_X9_62_prime_field) {
630		if (!EC_POINT_set_affine_coordinates_GFp(ecgroup,
631		    point, x, y, bnctx))
632			goto done;
633	} else {
634		if (!EC_POINT_set_affine_coordinates_GF2m(ecgroup,
635		    point, x, y, bnctx))
636			goto done;
637	}
638
639	ret = 0;
640 done:
641	if (ret != 0 && point != NULL)
642		EC_POINT_clear_free(point);
643	/* Make sure to erase sensitive data */
644	if (x != NULL)
645		BN_clear(x);
646	if (y != NULL)
647		BN_clear(y);
648	BN_CTX_end(bnctx);
649	BN_CTX_free(bnctx);
650
651	return (point);
652}
653