xref: /openbsd-src/sbin/isakmpd/dh.c (revision f2da64fbbbf1b03f09f390ab01267c93dfd77c4c)
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 
30 int	dh_init(struct group *);
31 
32 int	modp_init(struct group *);
33 int	modp_getlen(struct group *);
34 int	modp_create_exchange(struct group *, u_int8_t *);
35 int	modp_create_shared(struct group *, u_int8_t *, u_int8_t *);
36 
37 int	ec_init(struct group *);
38 int	ec_getlen(struct group *);
39 int	ec_create_exchange(struct group *, u_int8_t *);
40 int	ec_create_shared(struct group *, u_int8_t *, u_int8_t *);
41 
42 int	ec_point2raw(struct group *, const EC_POINT *, u_int8_t *, size_t);
43 EC_POINT *
44 	ec_raw2point(struct group *, u_int8_t *, size_t);
45 
46 struct 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 
288 void
289 group_init(void)
290 {
291 	/* currently not used */
292 	return;
293 }
294 
295 void
296 group_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 
308 struct group *
309 group_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 
358 int
359 dh_init(struct group *group)
360 {
361 	return (group->init(group));
362 }
363 
364 int
365 dh_getlen(struct group *group)
366 {
367 	return (group->getlen(group));
368 }
369 
370 int
371 dh_create_exchange(struct group *group, u_int8_t *buf)
372 {
373 	return (group->exchange(group, buf));
374 }
375 
376 int
377 dh_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
378 {
379 	return (group->shared(group, secret, exchange));
380 }
381 
382 int
383 modp_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 
398 int
399 modp_getlen(struct group *group)
400 {
401 	if (group->spec == NULL)
402 		return (0);
403 	return (roundup(group->spec->bits, 8) / 8);
404 }
405 
406 int
407 modp_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 
429 int
430 modp_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 
454 int
455 ec_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 
468 int
469 ec_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 
477 int
478 ec_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 
489 int
490 ec_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 
536 int
537 ec_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 
596 EC_POINT *
597 ec_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