xref: /openbsd-src/sbin/isakmpd/dh.c (revision f51d8a344da2c3e0999375e44a80acaae4c4543b)
1*f51d8a34Stb /*	$OpenBSD: dh.c,v 1.27 2023/03/31 07:28:46 tb Exp $	*/
22040585eSniklas 
32040585eSniklas /*
48978eb1dSreyk  * Copyright (c) 2010-2014 Reyk Floeter <reyk@openbsd.org>
52040585eSniklas  *
6fefcb31aSreyk  * Permission to use, copy, modify, and distribute this software for any
7fefcb31aSreyk  * purpose with or without fee is hereby granted, provided that the above
8fefcb31aSreyk  * copyright notice and this permission notice appear in all copies.
92040585eSniklas  *
10fefcb31aSreyk  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11fefcb31aSreyk  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12fefcb31aSreyk  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13fefcb31aSreyk  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14fefcb31aSreyk  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15fefcb31aSreyk  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16fefcb31aSreyk  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
172040585eSniklas  */
182040585eSniklas 
19fefcb31aSreyk #include <string.h>
202040585eSniklas 
21fefcb31aSreyk #include <openssl/obj_mac.h>
22fefcb31aSreyk #include <openssl/dh.h>
23fefcb31aSreyk #include <openssl/ec.h>
24fefcb31aSreyk #include <openssl/ecdh.h>
258978eb1dSreyk #include <openssl/bn.h>
26fefcb31aSreyk 
272040585eSniklas #include "dh.h"
282040585eSniklas 
2913c7cd53Sderaadt #define roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
3013c7cd53Sderaadt 
31fefcb31aSreyk int	dh_init(struct group *);
32fefcb31aSreyk 
33fefcb31aSreyk int	modp_init(struct group *);
34fefcb31aSreyk int	modp_getlen(struct group *);
35fefcb31aSreyk int	modp_create_exchange(struct group *, u_int8_t *);
36fefcb31aSreyk int	modp_create_shared(struct group *, u_int8_t *, u_int8_t *);
37fefcb31aSreyk 
38fefcb31aSreyk int	ec_init(struct group *);
39fefcb31aSreyk int	ec_getlen(struct group *);
40f2c2b5e4Spatrick int	ec_secretlen(struct group *);
41fefcb31aSreyk int	ec_create_exchange(struct group *, u_int8_t *);
42fefcb31aSreyk int	ec_create_shared(struct group *, u_int8_t *, u_int8_t *);
43fefcb31aSreyk 
44f2c2b5e4Spatrick #define EC_POINT2RAW_FULL	0
45f2c2b5e4Spatrick #define EC_POINT2RAW_XONLY	1
46f2c2b5e4Spatrick int	ec_point2raw(struct group *, const EC_POINT *, uint8_t *, size_t, int);
47fefcb31aSreyk EC_POINT *
48fefcb31aSreyk 	ec_raw2point(struct group *, u_int8_t *, size_t);
49fefcb31aSreyk 
50fefcb31aSreyk struct group_id ike_groups[] = {
51fefcb31aSreyk 	{ GROUP_MODP, 1, 768,
52fefcb31aSreyk 	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
53fefcb31aSreyk 	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
54fefcb31aSreyk 	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
55fefcb31aSreyk 	    "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF",
56fefcb31aSreyk 	    "02"
57fefcb31aSreyk 	},
58fefcb31aSreyk 	{ GROUP_MODP, 2, 1024,
59fefcb31aSreyk 	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
60fefcb31aSreyk 	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
61fefcb31aSreyk 	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
62fefcb31aSreyk 	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
63fefcb31aSreyk 	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
64fefcb31aSreyk 	    "FFFFFFFFFFFFFFFF",
65fefcb31aSreyk 	    "02"
66fefcb31aSreyk 	},
67*f51d8a34Stb #ifndef OPENSSL_NO_EC2M
68fefcb31aSreyk 	{ GROUP_EC2N, 3, 155, NULL, NULL, NID_ipsec3 },
69fefcb31aSreyk 	{ GROUP_EC2N, 4, 185, NULL, NULL, NID_ipsec4 },
70*f51d8a34Stb #endif
71fefcb31aSreyk 	{ GROUP_MODP, 5, 1536,
72fefcb31aSreyk 	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
73fefcb31aSreyk 	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
74fefcb31aSreyk 	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
75fefcb31aSreyk 	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
76fefcb31aSreyk 	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
77fefcb31aSreyk 	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
78fefcb31aSreyk 	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
79fefcb31aSreyk 	    "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF",
80fefcb31aSreyk 	    "02"
81fefcb31aSreyk 	},
82fefcb31aSreyk 	{ GROUP_MODP, 14, 2048,
83fefcb31aSreyk 	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
84fefcb31aSreyk 	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
85fefcb31aSreyk 	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
86fefcb31aSreyk 	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
87fefcb31aSreyk 	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
88fefcb31aSreyk 	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
89fefcb31aSreyk 	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
90fefcb31aSreyk 	    "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
91fefcb31aSreyk 	    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
92fefcb31aSreyk 	    "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
93fefcb31aSreyk 	    "15728E5A8AACAA68FFFFFFFFFFFFFFFF",
94fefcb31aSreyk 	    "02"
95fefcb31aSreyk 	},
96fefcb31aSreyk 	{ GROUP_MODP, 15, 3072,
97fefcb31aSreyk 	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
98fefcb31aSreyk 	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
99fefcb31aSreyk 	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
100fefcb31aSreyk 	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
101fefcb31aSreyk 	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
102fefcb31aSreyk 	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
103fefcb31aSreyk 	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
104fefcb31aSreyk 	    "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
105fefcb31aSreyk 	    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
106fefcb31aSreyk 	    "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
107fefcb31aSreyk 	    "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
108fefcb31aSreyk 	    "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
109fefcb31aSreyk 	    "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
110fefcb31aSreyk 	    "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
111fefcb31aSreyk 	    "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
112fefcb31aSreyk 	    "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF",
113fefcb31aSreyk 	    "02"
114fefcb31aSreyk 	},
115fefcb31aSreyk 	{ GROUP_MODP, 16, 4096,
116fefcb31aSreyk 	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
117fefcb31aSreyk 	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
118fefcb31aSreyk 	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
119fefcb31aSreyk 	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
120fefcb31aSreyk 	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
121fefcb31aSreyk 	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
122fefcb31aSreyk 	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
123fefcb31aSreyk 	    "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
124fefcb31aSreyk 	    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
125fefcb31aSreyk 	    "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
126fefcb31aSreyk 	    "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
127fefcb31aSreyk 	    "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
128fefcb31aSreyk 	    "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
129fefcb31aSreyk 	    "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
130fefcb31aSreyk 	    "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
131fefcb31aSreyk 	    "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
132fefcb31aSreyk 	    "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
133fefcb31aSreyk 	    "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
134fefcb31aSreyk 	    "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
135fefcb31aSreyk 	    "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
136fefcb31aSreyk 	    "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199"
137fefcb31aSreyk 	    "FFFFFFFFFFFFFFFF",
138fefcb31aSreyk 	    "02"
139fefcb31aSreyk 	},
140fefcb31aSreyk 	{ GROUP_MODP, 17, 6144,
141fefcb31aSreyk 	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
142fefcb31aSreyk 	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
143fefcb31aSreyk 	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
144fefcb31aSreyk 	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
145fefcb31aSreyk 	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
146fefcb31aSreyk 	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
147fefcb31aSreyk 	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
148fefcb31aSreyk 	    "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
149fefcb31aSreyk 	    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
150fefcb31aSreyk 	    "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
151fefcb31aSreyk 	    "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
152fefcb31aSreyk 	    "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
153fefcb31aSreyk 	    "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
154fefcb31aSreyk 	    "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
155fefcb31aSreyk 	    "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
156fefcb31aSreyk 	    "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
157fefcb31aSreyk 	    "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
158fefcb31aSreyk 	    "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
159fefcb31aSreyk 	    "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
160fefcb31aSreyk 	    "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
161fefcb31aSreyk 	    "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
162fefcb31aSreyk 	    "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"
163fefcb31aSreyk 	    "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
164fefcb31aSreyk 	    "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
165fefcb31aSreyk 	    "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
166fefcb31aSreyk 	    "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"
167fefcb31aSreyk 	    "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
168fefcb31aSreyk 	    "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
169fefcb31aSreyk 	    "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
170fefcb31aSreyk 	    "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
171fefcb31aSreyk 	    "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
172fefcb31aSreyk 	    "12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF",
173fefcb31aSreyk 	    "02"
174fefcb31aSreyk 	},
175fefcb31aSreyk 	{ GROUP_MODP, 18, 8192,
176fefcb31aSreyk 	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
177fefcb31aSreyk 	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
178fefcb31aSreyk 	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
179fefcb31aSreyk 	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
180fefcb31aSreyk 	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
181fefcb31aSreyk 	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
182fefcb31aSreyk 	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
183fefcb31aSreyk 	    "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
184fefcb31aSreyk 	    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
185fefcb31aSreyk 	    "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
186fefcb31aSreyk 	    "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
187fefcb31aSreyk 	    "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
188fefcb31aSreyk 	    "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
189fefcb31aSreyk 	    "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
190fefcb31aSreyk 	    "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
191fefcb31aSreyk 	    "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
192fefcb31aSreyk 	    "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
193fefcb31aSreyk 	    "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
194fefcb31aSreyk 	    "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
195fefcb31aSreyk 	    "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
196fefcb31aSreyk 	    "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
197fefcb31aSreyk 	    "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"
198fefcb31aSreyk 	    "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
199fefcb31aSreyk 	    "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
200fefcb31aSreyk 	    "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
201fefcb31aSreyk 	    "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"
202fefcb31aSreyk 	    "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
203fefcb31aSreyk 	    "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
204fefcb31aSreyk 	    "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
205fefcb31aSreyk 	    "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
206fefcb31aSreyk 	    "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
207fefcb31aSreyk 	    "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4"
208fefcb31aSreyk 	    "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300"
209fefcb31aSreyk 	    "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568"
210fefcb31aSreyk 	    "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9"
211fefcb31aSreyk 	    "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B"
212fefcb31aSreyk 	    "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A"
213fefcb31aSreyk 	    "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36"
214fefcb31aSreyk 	    "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1"
215fefcb31aSreyk 	    "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92"
216fefcb31aSreyk 	    "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47"
217fefcb31aSreyk 	    "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71"
218fefcb31aSreyk 	    "60C980DD98EDD3DFFFFFFFFFFFFFFFFF",
219fefcb31aSreyk 	    "02"
220fefcb31aSreyk 	},
221fefcb31aSreyk 	{ GROUP_ECP, 19, 256, NULL, NULL, NID_X9_62_prime256v1 },
222fefcb31aSreyk 	{ GROUP_ECP, 20, 384, NULL, NULL, NID_secp384r1 },
223fefcb31aSreyk 	{ GROUP_ECP, 21, 521, NULL, NULL, NID_secp521r1 },
224fefcb31aSreyk 	{ GROUP_ECP, 25, 192, NULL, NULL, NID_X9_62_prime192v1 },
2258978eb1dSreyk 	{ GROUP_ECP, 26, 224, NULL, NULL, NID_secp224r1 },
2268978eb1dSreyk 	{ GROUP_ECP, 27, 224, NULL, NULL, NID_brainpoolP224r1 },
2278978eb1dSreyk 	{ GROUP_ECP, 28, 256, NULL, NULL, NID_brainpoolP256r1 },
2288978eb1dSreyk 	{ GROUP_ECP, 29, 384, NULL, NULL, NID_brainpoolP384r1 },
2298978eb1dSreyk 	{ GROUP_ECP, 30, 512, NULL, NULL, NID_brainpoolP512r1 }
230fefcb31aSreyk };
231fefcb31aSreyk 
232fefcb31aSreyk void
group_init(void)233fefcb31aSreyk group_init(void)
234fefcb31aSreyk {
235fefcb31aSreyk 	/* currently not used */
236fefcb31aSreyk 	return;
237fefcb31aSreyk }
238fefcb31aSreyk 
239fefcb31aSreyk void
group_free(struct group * group)240fefcb31aSreyk group_free(struct group *group)
241fefcb31aSreyk {
242fefcb31aSreyk 	if (group == NULL)
243fefcb31aSreyk 		return;
244fefcb31aSreyk 	if (group->dh != NULL)
245fefcb31aSreyk 		DH_free(group->dh);
246fefcb31aSreyk 	if (group->ec != NULL)
247fefcb31aSreyk 		EC_KEY_free(group->ec);
248fefcb31aSreyk 	group->spec = NULL;
2498978eb1dSreyk 	free(group);
250fefcb31aSreyk }
251fefcb31aSreyk 
252fefcb31aSreyk struct group *
group_get(u_int32_t id)253fefcb31aSreyk group_get(u_int32_t id)
254fefcb31aSreyk {
255fefcb31aSreyk 	struct group_id	*p = NULL;
256fefcb31aSreyk 	struct group	*group;
257fefcb31aSreyk 	u_int		 i, items;
258fefcb31aSreyk 
259fefcb31aSreyk 	items = sizeof(ike_groups) / sizeof(ike_groups[0]);
260fefcb31aSreyk 	for (i = 0; i < items; i++) {
261fefcb31aSreyk 		if (id == ike_groups[i].id) {
262fefcb31aSreyk 			p = &ike_groups[i];
263fefcb31aSreyk 			break;
264fefcb31aSreyk 		}
265fefcb31aSreyk 	}
266fefcb31aSreyk 	if (p == NULL)
267fefcb31aSreyk 		return (NULL);
268fefcb31aSreyk 
269fefcb31aSreyk 	if ((group = calloc(1, sizeof(*group))) == NULL)
270fefcb31aSreyk 		return (NULL);
271fefcb31aSreyk 
272fefcb31aSreyk 	group->id = id;
273fefcb31aSreyk 	group->spec = p;
274fefcb31aSreyk 
275fefcb31aSreyk 	switch (p->type) {
276fefcb31aSreyk 	case GROUP_MODP:
277fefcb31aSreyk 		group->init = modp_init;
278fefcb31aSreyk 		group->getlen = modp_getlen;
279fefcb31aSreyk 		group->exchange = modp_create_exchange;
280fefcb31aSreyk 		group->shared = modp_create_shared;
281fefcb31aSreyk 		break;
282*f51d8a34Stb #ifndef OPENSSL_NO_EC2M
283fefcb31aSreyk 	case GROUP_EC2N:
284*f51d8a34Stb #endif
285fefcb31aSreyk 	case GROUP_ECP:
286fefcb31aSreyk 		group->init = ec_init;
287fefcb31aSreyk 		group->getlen = ec_getlen;
288f2c2b5e4Spatrick 		group->secretlen = ec_secretlen;
289fefcb31aSreyk 		group->exchange = ec_create_exchange;
290fefcb31aSreyk 		group->shared = ec_create_shared;
291fefcb31aSreyk 		break;
292fefcb31aSreyk 	default:
293fefcb31aSreyk 		group_free(group);
294fefcb31aSreyk 		return (NULL);
295fefcb31aSreyk 	}
296fefcb31aSreyk 
297fefcb31aSreyk 	if (dh_init(group) != 0) {
298fefcb31aSreyk 		group_free(group);
299fefcb31aSreyk 		return (NULL);
300fefcb31aSreyk 	}
301fefcb31aSreyk 
302fefcb31aSreyk 	return (group);
303fefcb31aSreyk }
304fefcb31aSreyk 
305fefcb31aSreyk int
dh_init(struct group * group)306fefcb31aSreyk dh_init(struct group *group)
307fefcb31aSreyk {
308fefcb31aSreyk 	return (group->init(group));
309fefcb31aSreyk }
3102040585eSniklas 
3112040585eSniklas int
dh_getlen(struct group * group)3122040585eSniklas dh_getlen(struct group *group)
3132040585eSniklas {
314fefcb31aSreyk 	return (group->getlen(group));
3152040585eSniklas }
3162040585eSniklas 
31704c806a6Sniklas int
dh_secretlen(struct group * group)318f2c2b5e4Spatrick dh_secretlen(struct group *group)
319f2c2b5e4Spatrick {
320f2c2b5e4Spatrick 	if (group->secretlen)
321f2c2b5e4Spatrick 		return (group->secretlen(group));
322f2c2b5e4Spatrick 	else
323f2c2b5e4Spatrick 		return (group->getlen(group));
324f2c2b5e4Spatrick }
325f2c2b5e4Spatrick 
326f2c2b5e4Spatrick int
dh_create_exchange(struct group * group,u_int8_t * buf)3272040585eSniklas dh_create_exchange(struct group *group, u_int8_t *buf)
3282040585eSniklas {
329fefcb31aSreyk 	return (group->exchange(group, buf));
3302040585eSniklas }
3312040585eSniklas 
33204c806a6Sniklas int
dh_create_shared(struct group * group,u_int8_t * secret,u_int8_t * exchange)3332040585eSniklas dh_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
3342040585eSniklas {
335fefcb31aSreyk 	return (group->shared(group, secret, exchange));
336fefcb31aSreyk }
337fefcb31aSreyk 
338fefcb31aSreyk int
modp_init(struct group * group)339fefcb31aSreyk modp_init(struct group *group)
340fefcb31aSreyk {
341fefcb31aSreyk 	DH	*dh;
3426ddd611fStb 	BIGNUM	*p = NULL, *g = NULL;
343fefcb31aSreyk 
344fefcb31aSreyk 	if ((dh = DH_new()) == NULL)
345fefcb31aSreyk 		return (-1);
346fefcb31aSreyk 	group->dh = dh;
347fefcb31aSreyk 
3486ddd611fStb 	if (!BN_hex2bn(&p, group->spec->prime) ||
3496ddd611fStb 	    !BN_hex2bn(&g, group->spec->generator)) {
3506ddd611fStb 		BN_free(p);
3516ddd611fStb 		BN_free(g);
352fefcb31aSreyk 		return (-1);
3536ddd611fStb 	}
3546ddd611fStb 
3556ddd611fStb 	if (!DH_set0_pqg(dh, p, NULL, g)) {
3566ddd611fStb 		BN_free(p);
3576ddd611fStb 		BN_free(g);
3586ddd611fStb 		return (-1);
3596ddd611fStb 	}
360fefcb31aSreyk 
361fefcb31aSreyk 	return (0);
362fefcb31aSreyk }
363fefcb31aSreyk 
364fefcb31aSreyk int
modp_getlen(struct group * group)365fefcb31aSreyk modp_getlen(struct group *group)
366fefcb31aSreyk {
367fefcb31aSreyk 	if (group->spec == NULL)
368fefcb31aSreyk 		return (0);
369fefcb31aSreyk 	return (roundup(group->spec->bits, 8) / 8);
370fefcb31aSreyk }
371fefcb31aSreyk 
372fefcb31aSreyk int
modp_create_exchange(struct group * group,u_int8_t * buf)373fefcb31aSreyk modp_create_exchange(struct group *group, u_int8_t *buf)
374fefcb31aSreyk {
375fefcb31aSreyk 	DH	*dh = group->dh;
376390e060eSmikeb 	int	 len, ret;
377fefcb31aSreyk 
378fefcb31aSreyk 	if (!DH_generate_key(dh))
379fefcb31aSreyk 		return (-1);
38066138239Stb 	ret = BN_bn2bin(DH_get0_pub_key(dh), buf);
381390e060eSmikeb 	if (!ret)
382fefcb31aSreyk 		return (-1);
383fefcb31aSreyk 
384390e060eSmikeb 	len = dh_getlen(group);
385390e060eSmikeb 
386390e060eSmikeb 	/* add zero padding */
387390e060eSmikeb 	if (ret < len) {
388390e060eSmikeb 		bcopy(buf, buf + (len - ret), ret);
389390e060eSmikeb 		bzero(buf, len - ret);
390390e060eSmikeb 	}
391390e060eSmikeb 
392fefcb31aSreyk 	return (0);
393fefcb31aSreyk }
394fefcb31aSreyk 
395fefcb31aSreyk int
modp_create_shared(struct group * group,u_int8_t * secret,u_int8_t * exchange)396fefcb31aSreyk modp_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
397fefcb31aSreyk {
398fefcb31aSreyk 	BIGNUM	*ex;
399390e060eSmikeb 	int	 len, ret;
400fefcb31aSreyk 
401390e060eSmikeb 	len = dh_getlen(group);
402390e060eSmikeb 
403390e060eSmikeb 	if ((ex = BN_bin2bn(exchange, len, NULL)) == NULL)
404fefcb31aSreyk 		return (-1);
405fefcb31aSreyk 
406fefcb31aSreyk 	ret = DH_compute_key(secret, ex, group->dh);
407fefcb31aSreyk 	BN_clear_free(ex);
4082ffa77eaSjsg 	if (ret <= 0)
409fefcb31aSreyk 		return (-1);
410fefcb31aSreyk 
411390e060eSmikeb 	/* add zero padding */
412390e060eSmikeb 	if (ret < len) {
413390e060eSmikeb 		bcopy(secret, secret + (len - ret), ret);
414390e060eSmikeb 		bzero(secret, len - ret);
415390e060eSmikeb 	}
416390e060eSmikeb 
417fefcb31aSreyk 	return (0);
418fefcb31aSreyk }
419fefcb31aSreyk 
420fefcb31aSreyk int
ec_init(struct group * group)421fefcb31aSreyk ec_init(struct group *group)
422fefcb31aSreyk {
423fefcb31aSreyk 	if ((group->ec = EC_KEY_new_by_curve_name(group->spec->nid)) == NULL)
424fefcb31aSreyk 		return (-1);
425fefcb31aSreyk 	if (!EC_KEY_generate_key(group->ec))
426fefcb31aSreyk 		return (-1);
42782291602Stb 	if (!EC_KEY_check_key(group->ec))
4288978eb1dSreyk 		return (-1);
429fefcb31aSreyk 	return (0);
430fefcb31aSreyk }
431fefcb31aSreyk 
432fefcb31aSreyk int
ec_getlen(struct group * group)433fefcb31aSreyk ec_getlen(struct group *group)
434fefcb31aSreyk {
435fefcb31aSreyk 	if (group->spec == NULL)
436fefcb31aSreyk 		return (0);
43745b72fd1Smikeb 	/* NB:  Return value will always be even */
438fefcb31aSreyk 	return ((roundup(group->spec->bits, 8) * 2) / 8);
439fefcb31aSreyk }
440fefcb31aSreyk 
441f2c2b5e4Spatrick /*
442f2c2b5e4Spatrick  * Note that the shared secret only includes the x value:
443f2c2b5e4Spatrick  *
444f2c2b5e4Spatrick  * See RFC 5903, 7. ECP Key Exchange Data Formats:
445f2c2b5e4Spatrick  *   The Diffie-Hellman shared secret value consists of the x value of the
446f2c2b5e4Spatrick  *   Diffie-Hellman common value.
447f2c2b5e4Spatrick  * See also RFC 5903, 9. Changes from RFC 4753.
448f2c2b5e4Spatrick  */
449f2c2b5e4Spatrick int
ec_secretlen(struct group * group)450f2c2b5e4Spatrick ec_secretlen(struct group *group)
451f2c2b5e4Spatrick {
452f2c2b5e4Spatrick 	return (ec_getlen(group) / 2);
453f2c2b5e4Spatrick }
454f2c2b5e4Spatrick 
455fefcb31aSreyk int
ec_create_exchange(struct group * group,u_int8_t * buf)456fefcb31aSreyk ec_create_exchange(struct group *group, u_int8_t *buf)
457fefcb31aSreyk {
458fefcb31aSreyk 	size_t	 len;
459fefcb31aSreyk 
460fefcb31aSreyk 	len = ec_getlen(group);
461fefcb31aSreyk 	bzero(buf, len);
462fefcb31aSreyk 
463fefcb31aSreyk 	return (ec_point2raw(group, EC_KEY_get0_public_key(group->ec),
464f2c2b5e4Spatrick 	    buf, len, EC_POINT2RAW_FULL));
465fefcb31aSreyk }
466fefcb31aSreyk 
467fefcb31aSreyk int
ec_create_shared(struct group * group,u_int8_t * secret,u_int8_t * exchange)468fefcb31aSreyk ec_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
469fefcb31aSreyk {
470fefcb31aSreyk 	const EC_GROUP	*ecgroup = NULL;
471fefcb31aSreyk 	const BIGNUM	*privkey;
4728978eb1dSreyk 	EC_KEY		*exkey = NULL;
473fefcb31aSreyk 	EC_POINT	*exchangep = NULL, *secretp = NULL;
474fefcb31aSreyk 	int		 ret = -1;
475fefcb31aSreyk 
476fefcb31aSreyk 	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL ||
477fefcb31aSreyk 	    (privkey = EC_KEY_get0_private_key(group->ec)) == NULL)
478fefcb31aSreyk 		goto done;
479fefcb31aSreyk 
480fefcb31aSreyk 	if ((exchangep =
481fefcb31aSreyk 	    ec_raw2point(group, exchange, ec_getlen(group))) == NULL)
482fefcb31aSreyk 		goto done;
483fefcb31aSreyk 
4848978eb1dSreyk 	if ((exkey = EC_KEY_new()) == NULL)
4858978eb1dSreyk 		goto done;
4868978eb1dSreyk 	if (!EC_KEY_set_group(exkey, ecgroup))
4878978eb1dSreyk 		goto done;
4888978eb1dSreyk 	if (!EC_KEY_set_public_key(exkey, exchangep))
4898978eb1dSreyk 		goto done;
4908978eb1dSreyk 
4918978eb1dSreyk 	/* validate exchangep */
4928978eb1dSreyk 	if (!EC_KEY_check_key(exkey))
4938978eb1dSreyk 		goto done;
4948978eb1dSreyk 
495fefcb31aSreyk 	if ((secretp = EC_POINT_new(ecgroup)) == NULL)
496fefcb31aSreyk 		goto done;
497fefcb31aSreyk 
498fefcb31aSreyk 	if (!EC_POINT_mul(ecgroup, secretp, NULL, exchangep, privkey, NULL))
499fefcb31aSreyk 		goto done;
500fefcb31aSreyk 
501f2c2b5e4Spatrick 	ret = ec_point2raw(group, secretp, secret, ec_secretlen(group),
502f2c2b5e4Spatrick 	    EC_POINT2RAW_XONLY);
503fefcb31aSreyk 
504fefcb31aSreyk  done:
5058978eb1dSreyk 	if (exkey != NULL)
5068978eb1dSreyk 		EC_KEY_free(exkey);
507fefcb31aSreyk 	if (exchangep != NULL)
508fefcb31aSreyk 		EC_POINT_clear_free(exchangep);
509fefcb31aSreyk 	if (secretp != NULL)
510fefcb31aSreyk 		EC_POINT_clear_free(secretp);
511fefcb31aSreyk 
512fefcb31aSreyk 	return (ret);
513fefcb31aSreyk }
514fefcb31aSreyk 
515fefcb31aSreyk int
ec_point2raw(struct group * group,const EC_POINT * point,u_int8_t * buf,size_t len,int mode)516fefcb31aSreyk ec_point2raw(struct group *group, const EC_POINT *point,
517f2c2b5e4Spatrick     u_int8_t *buf, size_t len, int mode)
518fefcb31aSreyk {
519fefcb31aSreyk 	const EC_GROUP	*ecgroup = NULL;
520fefcb31aSreyk 	BN_CTX		*bnctx = NULL;
521fefcb31aSreyk 	BIGNUM		*x = NULL, *y = NULL;
522fefcb31aSreyk 	int		 ret = -1;
52345b72fd1Smikeb 	size_t		 eclen, xlen, ylen;
524fefcb31aSreyk 	off_t		 xoff, yoff;
525fefcb31aSreyk 
526fefcb31aSreyk 	if ((bnctx = BN_CTX_new()) == NULL)
527fefcb31aSreyk 		goto done;
528fefcb31aSreyk 	BN_CTX_start(bnctx);
529fefcb31aSreyk 	if ((x = BN_CTX_get(bnctx)) == NULL ||
530fefcb31aSreyk 	    (y = BN_CTX_get(bnctx)) == NULL)
531fefcb31aSreyk 		goto done;
532fefcb31aSreyk 
53345b72fd1Smikeb 	eclen = ec_getlen(group);
534f2c2b5e4Spatrick 	switch (mode) {
535f2c2b5e4Spatrick 	case EC_POINT2RAW_XONLY:
536f2c2b5e4Spatrick 		xlen = eclen / 2;
537f2c2b5e4Spatrick 		ylen = 0;
538f2c2b5e4Spatrick 		break;
539f2c2b5e4Spatrick 	case EC_POINT2RAW_FULL:
54045b72fd1Smikeb 		xlen = ylen = eclen / 2;
541f2c2b5e4Spatrick 		break;
542f2c2b5e4Spatrick 	default:
543f2c2b5e4Spatrick 		goto done;
544f2c2b5e4Spatrick 	}
545f2c2b5e4Spatrick 	if (len < xlen + ylen)
546f2c2b5e4Spatrick 		goto done;
54745b72fd1Smikeb 
548fefcb31aSreyk 	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL)
549fefcb31aSreyk 		goto done;
550fefcb31aSreyk 
551cc86847bStb 	if (!EC_POINT_get_affine_coordinates(ecgroup, point, x, y, bnctx))
552fefcb31aSreyk 		goto done;
553fefcb31aSreyk 
554fefcb31aSreyk 	xoff = xlen - BN_num_bytes(x);
55545b72fd1Smikeb 	bzero(buf, xoff);
556fefcb31aSreyk 	if (!BN_bn2bin(x, buf + xoff))
557fefcb31aSreyk 		goto done;
558fefcb31aSreyk 
559f2c2b5e4Spatrick 	if (ylen > 0) {
560fefcb31aSreyk 		yoff = (ylen - BN_num_bytes(y)) + xlen;
56145b72fd1Smikeb 		bzero(buf + xlen, yoff - xlen);
562fefcb31aSreyk 		if (!BN_bn2bin(y, buf + yoff))
563fefcb31aSreyk 			goto done;
564f2c2b5e4Spatrick 	}
565fefcb31aSreyk 
566fefcb31aSreyk 	ret = 0;
567fefcb31aSreyk  done:
5688978eb1dSreyk 	/* Make sure to erase sensitive data */
5698978eb1dSreyk 	if (x != NULL)
5708978eb1dSreyk 		BN_clear(x);
5718978eb1dSreyk 	if (y != NULL)
5728978eb1dSreyk 		BN_clear(y);
573fefcb31aSreyk 	BN_CTX_end(bnctx);
574fefcb31aSreyk 	BN_CTX_free(bnctx);
575fefcb31aSreyk 
576fefcb31aSreyk 	return (ret);
577fefcb31aSreyk }
578fefcb31aSreyk 
579fefcb31aSreyk EC_POINT *
ec_raw2point(struct group * group,u_int8_t * buf,size_t len)580fefcb31aSreyk ec_raw2point(struct group *group, u_int8_t *buf, size_t len)
581fefcb31aSreyk {
582fefcb31aSreyk 	const EC_GROUP	*ecgroup = NULL;
583fefcb31aSreyk 	EC_POINT	*point = NULL;
584fefcb31aSreyk 	BN_CTX		*bnctx = NULL;
585fefcb31aSreyk 	BIGNUM		*x = NULL, *y = NULL;
586fefcb31aSreyk 	int		 ret = -1;
587fefcb31aSreyk 	size_t		 eclen;
588fefcb31aSreyk 	size_t		 xlen, ylen;
589fefcb31aSreyk 
590fefcb31aSreyk 	if ((bnctx = BN_CTX_new()) == NULL)
591fefcb31aSreyk 		goto done;
592fefcb31aSreyk 	BN_CTX_start(bnctx);
593fefcb31aSreyk 	if ((x = BN_CTX_get(bnctx)) == NULL ||
594fefcb31aSreyk 	    (y = BN_CTX_get(bnctx)) == NULL)
595fefcb31aSreyk 		goto done;
596fefcb31aSreyk 
597fefcb31aSreyk 	eclen = ec_getlen(group);
598fefcb31aSreyk 	if (len < eclen)
599fefcb31aSreyk 		goto done;
600fefcb31aSreyk 	xlen = ylen = eclen / 2;
601fefcb31aSreyk 	if ((x = BN_bin2bn(buf, xlen, x)) == NULL ||
602fefcb31aSreyk 	    (y = BN_bin2bn(buf + xlen, ylen, y)) == NULL)
603fefcb31aSreyk 		goto done;
604fefcb31aSreyk 
605fefcb31aSreyk 	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL)
606fefcb31aSreyk 		goto done;
607fefcb31aSreyk 
608fefcb31aSreyk 	if ((point = EC_POINT_new(ecgroup)) == NULL)
609fefcb31aSreyk 		goto done;
610fefcb31aSreyk 
611cc86847bStb 	if (!EC_POINT_set_affine_coordinates(ecgroup, point, x, y, bnctx))
612fefcb31aSreyk 		goto done;
613fefcb31aSreyk 
614fefcb31aSreyk 	ret = 0;
615fefcb31aSreyk  done:
616fefcb31aSreyk 	if (ret != 0 && point != NULL)
617fefcb31aSreyk 		EC_POINT_clear_free(point);
6188978eb1dSreyk 	/* Make sure to erase sensitive data */
6198978eb1dSreyk 	if (x != NULL)
6208978eb1dSreyk 		BN_clear(x);
6218978eb1dSreyk 	if (y != NULL)
6228978eb1dSreyk 		BN_clear(y);
623fefcb31aSreyk 	BN_CTX_end(bnctx);
624fefcb31aSreyk 	BN_CTX_free(bnctx);
625fefcb31aSreyk 
626fefcb31aSreyk 	return (point);
6272040585eSniklas }
628