xref: /openbsd/sbin/isakmpd/dh.c (revision cca36db2)
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 
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 };
283 
284 void
285 group_init(void)
286 {
287 	/* currently not used */
288 	return;
289 }
290 
291 void
292 group_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 
303 struct group *
304 group_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 
353 int
354 dh_init(struct group *group)
355 {
356 	return (group->init(group));
357 }
358 
359 int
360 dh_getlen(struct group *group)
361 {
362 	return (group->getlen(group));
363 }
364 
365 int
366 dh_create_exchange(struct group *group, u_int8_t *buf)
367 {
368 	return (group->exchange(group, buf));
369 }
370 
371 int
372 dh_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
373 {
374 	return (group->shared(group, secret, exchange));
375 }
376 
377 int
378 modp_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 
393 int
394 modp_getlen(struct group *group)
395 {
396 	if (group->spec == NULL)
397 		return (0);
398 	return (roundup(group->spec->bits, 8) / 8);
399 }
400 
401 int
402 modp_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 
424 int
425 modp_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 
449 int
450 ec_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 
459 int
460 ec_getlen(struct group *group)
461 {
462 	if (group->spec == NULL)
463 		return (0);
464 	return ((roundup(group->spec->bits, 8) * 2) / 8);
465 }
466 
467 int
468 ec_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 
479 int
480 ec_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 
512 int
513 ec_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 
562 EC_POINT *
563 ec_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