xref: /openbsd/sbin/iked/dh.c (revision a4194998)
1*a4194998Sjsg /*	$OpenBSD: dh.c,v 1.12 2014/07/10 12:50:05 jsg Exp $	*/
245ae9d61Sreyk 
345ae9d61Sreyk /*
4fcebd35dSreyk  * Copyright (c) 2010-2013 Reyk Floeter <reyk@openbsd.org>
545ae9d61Sreyk  *
645ae9d61Sreyk  * Permission to use, copy, modify, and distribute this software for any
745ae9d61Sreyk  * purpose with or without fee is hereby granted, provided that the above
845ae9d61Sreyk  * copyright notice and this permission notice appear in all copies.
945ae9d61Sreyk  *
1045ae9d61Sreyk  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
1145ae9d61Sreyk  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
1245ae9d61Sreyk  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
1345ae9d61Sreyk  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
1445ae9d61Sreyk  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
1545ae9d61Sreyk  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
1645ae9d61Sreyk  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
1745ae9d61Sreyk  */
1845ae9d61Sreyk 
1945ae9d61Sreyk #include <sys/param.h>
2045ae9d61Sreyk #include <string.h>
2145ae9d61Sreyk 
2245ae9d61Sreyk #include <openssl/obj_mac.h>
2345ae9d61Sreyk #include <openssl/dh.h>
2445ae9d61Sreyk #include <openssl/ec.h>
2545ae9d61Sreyk #include <openssl/ecdh.h>
26*a4194998Sjsg #include <openssl/bn.h>
2745ae9d61Sreyk 
2845ae9d61Sreyk #include "dh.h"
290d5bf58dSreyk 
300d5bf58dSreyk int	dh_init(struct group *);
3145ae9d61Sreyk 
3245ae9d61Sreyk int	modp_init(struct group *);
3345ae9d61Sreyk int	modp_getlen(struct group *);
3445ae9d61Sreyk int	modp_create_exchange(struct group *, u_int8_t *);
3545ae9d61Sreyk int	modp_create_shared(struct group *, u_int8_t *, u_int8_t *);
3645ae9d61Sreyk 
3745ae9d61Sreyk int	ec_init(struct group *);
3845ae9d61Sreyk int	ec_getlen(struct group *);
3945ae9d61Sreyk int	ec_create_exchange(struct group *, u_int8_t *);
4045ae9d61Sreyk int	ec_create_shared(struct group *, u_int8_t *, u_int8_t *);
4145ae9d61Sreyk 
4245ae9d61Sreyk int	ec_point2raw(struct group *, const EC_POINT *, u_int8_t *, size_t);
4345ae9d61Sreyk EC_POINT *
4445ae9d61Sreyk 	ec_raw2point(struct group *, u_int8_t *, size_t);
4545ae9d61Sreyk 
4645ae9d61Sreyk struct group_id ike_groups[] = {
4745ae9d61Sreyk 	{ GROUP_MODP, 1, 768,
4845ae9d61Sreyk 	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
4945ae9d61Sreyk 	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
5045ae9d61Sreyk 	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
5145ae9d61Sreyk 	    "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF",
5245ae9d61Sreyk 	    "02"
5345ae9d61Sreyk 	},
5445ae9d61Sreyk 	{ GROUP_MODP, 2, 1024,
5545ae9d61Sreyk 	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
5645ae9d61Sreyk 	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
5745ae9d61Sreyk 	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
5845ae9d61Sreyk 	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
5945ae9d61Sreyk 	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381"
6045ae9d61Sreyk 	    "FFFFFFFFFFFFFFFF",
6145ae9d61Sreyk 	    "02"
6245ae9d61Sreyk 	},
63369beec1Sreyk 	{ GROUP_EC2N, 3, 155, NULL, NULL, NID_ipsec3 },
64369beec1Sreyk 	{ GROUP_EC2N, 4, 185, NULL, NULL, NID_ipsec4 },
6545ae9d61Sreyk 	{ GROUP_MODP, 5, 1536,
6645ae9d61Sreyk 	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
6745ae9d61Sreyk 	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
6845ae9d61Sreyk 	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
6945ae9d61Sreyk 	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
7045ae9d61Sreyk 	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
7145ae9d61Sreyk 	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
7245ae9d61Sreyk 	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
7345ae9d61Sreyk 	    "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF",
7445ae9d61Sreyk 	    "02"
7545ae9d61Sreyk 	},
7645ae9d61Sreyk 	{ GROUP_MODP, 14, 2048,
7745ae9d61Sreyk 	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
7845ae9d61Sreyk 	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
7945ae9d61Sreyk 	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
8045ae9d61Sreyk 	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
8145ae9d61Sreyk 	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
8245ae9d61Sreyk 	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
8345ae9d61Sreyk 	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
8445ae9d61Sreyk 	    "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
8545ae9d61Sreyk 	    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
8645ae9d61Sreyk 	    "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
8745ae9d61Sreyk 	    "15728E5A8AACAA68FFFFFFFFFFFFFFFF",
8845ae9d61Sreyk 	    "02"
8945ae9d61Sreyk 	},
9045ae9d61Sreyk 	{ GROUP_MODP, 15, 3072,
9145ae9d61Sreyk 	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
9245ae9d61Sreyk 	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
9345ae9d61Sreyk 	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
9445ae9d61Sreyk 	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
9545ae9d61Sreyk 	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
9645ae9d61Sreyk 	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
9745ae9d61Sreyk 	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
9845ae9d61Sreyk 	    "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
9945ae9d61Sreyk 	    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
10045ae9d61Sreyk 	    "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
10145ae9d61Sreyk 	    "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
10245ae9d61Sreyk 	    "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
10345ae9d61Sreyk 	    "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
10445ae9d61Sreyk 	    "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
10545ae9d61Sreyk 	    "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
10645ae9d61Sreyk 	    "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF",
10745ae9d61Sreyk 	    "02"
10845ae9d61Sreyk 	},
10945ae9d61Sreyk 	{ GROUP_MODP, 16, 4096,
11045ae9d61Sreyk 	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
11145ae9d61Sreyk 	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
11245ae9d61Sreyk 	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
11345ae9d61Sreyk 	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
11445ae9d61Sreyk 	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
11545ae9d61Sreyk 	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
11645ae9d61Sreyk 	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
11745ae9d61Sreyk 	    "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
11845ae9d61Sreyk 	    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
11945ae9d61Sreyk 	    "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
12045ae9d61Sreyk 	    "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
12145ae9d61Sreyk 	    "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
12245ae9d61Sreyk 	    "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
12345ae9d61Sreyk 	    "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
12445ae9d61Sreyk 	    "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
12545ae9d61Sreyk 	    "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
12645ae9d61Sreyk 	    "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
12745ae9d61Sreyk 	    "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
12845ae9d61Sreyk 	    "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
12945ae9d61Sreyk 	    "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
13045ae9d61Sreyk 	    "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199"
13145ae9d61Sreyk 	    "FFFFFFFFFFFFFFFF",
13245ae9d61Sreyk 	    "02"
13345ae9d61Sreyk 	},
13445ae9d61Sreyk 	{ GROUP_MODP, 17, 6144,
13545ae9d61Sreyk 	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
13645ae9d61Sreyk 	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
13745ae9d61Sreyk 	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
13845ae9d61Sreyk 	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
13945ae9d61Sreyk 	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
14045ae9d61Sreyk 	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
14145ae9d61Sreyk 	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
14245ae9d61Sreyk 	    "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
14345ae9d61Sreyk 	    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
14445ae9d61Sreyk 	    "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
14545ae9d61Sreyk 	    "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
14645ae9d61Sreyk 	    "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
14745ae9d61Sreyk 	    "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
14845ae9d61Sreyk 	    "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
14945ae9d61Sreyk 	    "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
15045ae9d61Sreyk 	    "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
15145ae9d61Sreyk 	    "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
15245ae9d61Sreyk 	    "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
15345ae9d61Sreyk 	    "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
15445ae9d61Sreyk 	    "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
15545ae9d61Sreyk 	    "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
15645ae9d61Sreyk 	    "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"
15745ae9d61Sreyk 	    "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
15845ae9d61Sreyk 	    "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
15945ae9d61Sreyk 	    "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
16045ae9d61Sreyk 	    "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"
16145ae9d61Sreyk 	    "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
16245ae9d61Sreyk 	    "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
16345ae9d61Sreyk 	    "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
16445ae9d61Sreyk 	    "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
16545ae9d61Sreyk 	    "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
16645ae9d61Sreyk 	    "12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF",
16745ae9d61Sreyk 	    "02"
16845ae9d61Sreyk 	},
16945ae9d61Sreyk 	{ GROUP_MODP, 18, 8192,
17045ae9d61Sreyk 	    "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1"
17145ae9d61Sreyk 	    "29024E088A67CC74020BBEA63B139B22514A08798E3404DD"
17245ae9d61Sreyk 	    "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245"
17345ae9d61Sreyk 	    "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED"
17445ae9d61Sreyk 	    "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D"
17545ae9d61Sreyk 	    "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F"
17645ae9d61Sreyk 	    "83655D23DCA3AD961C62F356208552BB9ED529077096966D"
17745ae9d61Sreyk 	    "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B"
17845ae9d61Sreyk 	    "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9"
17945ae9d61Sreyk 	    "DE2BCBF6955817183995497CEA956AE515D2261898FA0510"
18045ae9d61Sreyk 	    "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64"
18145ae9d61Sreyk 	    "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7"
18245ae9d61Sreyk 	    "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B"
18345ae9d61Sreyk 	    "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C"
18445ae9d61Sreyk 	    "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31"
18545ae9d61Sreyk 	    "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7"
18645ae9d61Sreyk 	    "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA"
18745ae9d61Sreyk 	    "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6"
18845ae9d61Sreyk 	    "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED"
18945ae9d61Sreyk 	    "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9"
19045ae9d61Sreyk 	    "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492"
19145ae9d61Sreyk 	    "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD"
19245ae9d61Sreyk 	    "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831"
19345ae9d61Sreyk 	    "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B"
19445ae9d61Sreyk 	    "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF"
19545ae9d61Sreyk 	    "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6"
19645ae9d61Sreyk 	    "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3"
19745ae9d61Sreyk 	    "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA"
19845ae9d61Sreyk 	    "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328"
19945ae9d61Sreyk 	    "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C"
20045ae9d61Sreyk 	    "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE"
20145ae9d61Sreyk 	    "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4"
20245ae9d61Sreyk 	    "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300"
20345ae9d61Sreyk 	    "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568"
20445ae9d61Sreyk 	    "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9"
20545ae9d61Sreyk 	    "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B"
20645ae9d61Sreyk 	    "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A"
20745ae9d61Sreyk 	    "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36"
20845ae9d61Sreyk 	    "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1"
20945ae9d61Sreyk 	    "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92"
21045ae9d61Sreyk 	    "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47"
21145ae9d61Sreyk 	    "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71"
21245ae9d61Sreyk 	    "60C980DD98EDD3DFFFFFFFFFFFFFFFFF",
21345ae9d61Sreyk 	    "02"
21445ae9d61Sreyk 	},
215369beec1Sreyk 	{ GROUP_ECP, 19, 256, NULL, NULL, NID_X9_62_prime256v1 },
216369beec1Sreyk 	{ GROUP_ECP, 20, 384, NULL, NULL, NID_secp384r1 },
217369beec1Sreyk 	{ GROUP_ECP, 21, 521, NULL, NULL, NID_secp521r1 },
21845ae9d61Sreyk 	{ GROUP_MODP, 22, 1024,
21945ae9d61Sreyk 	    "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C6"
22045ae9d61Sreyk 	    "9A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C0"
22145ae9d61Sreyk 	    "13ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD70"
22245ae9d61Sreyk 	    "98488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0"
22345ae9d61Sreyk 	    "A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708"
22445ae9d61Sreyk 	    "DF1FB2BC2E4A4371",
22545ae9d61Sreyk 	    "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507F"
22645ae9d61Sreyk 	    "D6406CFF14266D31266FEA1E5C41564B777E690F5504F213"
22745ae9d61Sreyk 	    "160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1"
22845ae9d61Sreyk 	    "909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A"
22945ae9d61Sreyk 	    "D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24"
23045ae9d61Sreyk 	    "855E6EEB22B3B2E5"
23145ae9d61Sreyk 	},
23245ae9d61Sreyk 	{ GROUP_MODP, 23, 2048,
23345ae9d61Sreyk 	    "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1"
23445ae9d61Sreyk 	    "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15"
23545ae9d61Sreyk 	    "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212"
23645ae9d61Sreyk 	    "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207"
23745ae9d61Sreyk 	    "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708"
23845ae9d61Sreyk 	    "B3BF8A317091883681286130BC8985DB1602E714415D9330"
23945ae9d61Sreyk 	    "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D"
24045ae9d61Sreyk 	    "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8"
24145ae9d61Sreyk 	    "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763"
24245ae9d61Sreyk 	    "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71"
24345ae9d61Sreyk 	    "CF9DE5384E71B81C0AC4DFFE0C10E64F",
24445ae9d61Sreyk 	    "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF"
24545ae9d61Sreyk 	    "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA"
24645ae9d61Sreyk 	    "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7"
24745ae9d61Sreyk 	    "C17669101999024AF4D027275AC1348BB8A762D0521BC98A"
24845ae9d61Sreyk 	    "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE"
24945ae9d61Sreyk 	    "F180EB34118E98D119529A45D6F834566E3025E316A330EF"
25045ae9d61Sreyk 	    "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB"
25145ae9d61Sreyk 	    "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381"
25245ae9d61Sreyk 	    "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269"
25345ae9d61Sreyk 	    "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179"
25445ae9d61Sreyk 	    "81BC087F2A7065B384B890D3191F2BFA"
25545ae9d61Sreyk 	},
25645ae9d61Sreyk 	{ GROUP_MODP, 24, 2048,
25745ae9d61Sreyk 	    "87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F2"
25845ae9d61Sreyk 	    "5D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA30"
25945ae9d61Sreyk 	    "16C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD"
26045ae9d61Sreyk 	    "5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B"
26145ae9d61Sreyk 	    "6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C"
26245ae9d61Sreyk 	    "4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0E"
26345ae9d61Sreyk 	    "F13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D9"
26445ae9d61Sreyk 	    "67E144E5140564251CCACB83E6B486F6B3CA3F7971506026"
26545ae9d61Sreyk 	    "C0B857F689962856DED4010ABD0BE621C3A3960A54E710C3"
26645ae9d61Sreyk 	    "75F26375D7014103A4B54330C198AF126116D2276E11715F"
26745ae9d61Sreyk 	    "693877FAD7EF09CADB094AE91E1A1597",
26845ae9d61Sreyk 	    "3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF2054"
26945ae9d61Sreyk 	    "07F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555"
27045ae9d61Sreyk 	    "BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18"
27145ae9d61Sreyk 	    "A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B"
27245ae9d61Sreyk 	    "777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC83"
27345ae9d61Sreyk 	    "1D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55"
27445ae9d61Sreyk 	    "A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14"
27545ae9d61Sreyk 	    "C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915"
27645ae9d61Sreyk 	    "B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6"
27745ae9d61Sreyk 	    "184B523D1DB246C32F63078490F00EF8D647D148D4795451"
27845ae9d61Sreyk 	    "5E2327CFEF98C582664B4C0F6CC41659"
27945ae9d61Sreyk 	},
280369beec1Sreyk 	{ GROUP_ECP, 25, 192, NULL, NULL, NID_X9_62_prime192v1 },
281369beec1Sreyk 	{ GROUP_ECP, 26, 224, NULL, NULL, NID_secp224r1 }
28245ae9d61Sreyk };
28345ae9d61Sreyk 
28445ae9d61Sreyk void
28545ae9d61Sreyk group_init(void)
28645ae9d61Sreyk {
2870d5bf58dSreyk 	/* currently not used */
28845ae9d61Sreyk 	return;
28945ae9d61Sreyk }
29045ae9d61Sreyk 
29145ae9d61Sreyk void
29245ae9d61Sreyk group_free(struct group *group)
29345ae9d61Sreyk {
29445ae9d61Sreyk 	if (group == NULL)
29545ae9d61Sreyk 		return;
29645ae9d61Sreyk 	if (group->dh != NULL)
29745ae9d61Sreyk 		DH_free(group->dh);
29845ae9d61Sreyk 	if (group->ec != NULL)
29945ae9d61Sreyk 		EC_KEY_free(group->ec);
30045ae9d61Sreyk 	group->spec = NULL;
30164449014Sreyk 	free(group);
30245ae9d61Sreyk }
30345ae9d61Sreyk 
30445ae9d61Sreyk struct group *
30545ae9d61Sreyk group_get(u_int32_t id)
30645ae9d61Sreyk {
30745ae9d61Sreyk 	struct group_id	*p = NULL;
30845ae9d61Sreyk 	struct group	*group;
30945ae9d61Sreyk 	u_int		 i, items;
31045ae9d61Sreyk 
31145ae9d61Sreyk 	items = sizeof(ike_groups) / sizeof(ike_groups[0]);
31245ae9d61Sreyk 	for (i = 0; i < items; i++) {
31345ae9d61Sreyk 		if (id == ike_groups[i].id) {
31445ae9d61Sreyk 			p = &ike_groups[i];
31545ae9d61Sreyk 			break;
31645ae9d61Sreyk 		}
31745ae9d61Sreyk 	}
31845ae9d61Sreyk 	if (p == NULL)
31945ae9d61Sreyk 		return (NULL);
32045ae9d61Sreyk 
32145ae9d61Sreyk 	if ((group = calloc(1, sizeof(*group))) == NULL)
32245ae9d61Sreyk 		return (NULL);
32345ae9d61Sreyk 
32445ae9d61Sreyk 	group->id = id;
32545ae9d61Sreyk 	group->spec = p;
32645ae9d61Sreyk 
32745ae9d61Sreyk 	switch (p->type) {
32845ae9d61Sreyk 	case GROUP_MODP:
32945ae9d61Sreyk 		group->init = modp_init;
33045ae9d61Sreyk 		group->getlen = modp_getlen;
33145ae9d61Sreyk 		group->exchange = modp_create_exchange;
33245ae9d61Sreyk 		group->shared = modp_create_shared;
33345ae9d61Sreyk 		break;
334369beec1Sreyk 	case GROUP_EC2N:
335369beec1Sreyk 	case GROUP_ECP:
33645ae9d61Sreyk 		group->init = ec_init;
33745ae9d61Sreyk 		group->getlen = ec_getlen;
33845ae9d61Sreyk 		group->exchange = ec_create_exchange;
33945ae9d61Sreyk 		group->shared = ec_create_shared;
34045ae9d61Sreyk 		break;
34145ae9d61Sreyk 	default:
34245ae9d61Sreyk 		group_free(group);
34345ae9d61Sreyk 		return (NULL);
34445ae9d61Sreyk 	}
34545ae9d61Sreyk 
34645ae9d61Sreyk 	if (dh_init(group) != 0) {
34745ae9d61Sreyk 		group_free(group);
34845ae9d61Sreyk 		return (NULL);
34945ae9d61Sreyk 	}
35045ae9d61Sreyk 
35145ae9d61Sreyk 	return (group);
35245ae9d61Sreyk }
35345ae9d61Sreyk 
35445ae9d61Sreyk int
35545ae9d61Sreyk dh_init(struct group *group)
35645ae9d61Sreyk {
35745ae9d61Sreyk 	return (group->init(group));
35845ae9d61Sreyk }
35945ae9d61Sreyk 
36045ae9d61Sreyk int
36145ae9d61Sreyk dh_getlen(struct group *group)
36245ae9d61Sreyk {
36345ae9d61Sreyk 	return (group->getlen(group));
36445ae9d61Sreyk }
36545ae9d61Sreyk 
36645ae9d61Sreyk int
36745ae9d61Sreyk dh_create_exchange(struct group *group, u_int8_t *buf)
36845ae9d61Sreyk {
36945ae9d61Sreyk 	return (group->exchange(group, buf));
37045ae9d61Sreyk }
37145ae9d61Sreyk 
37245ae9d61Sreyk int
37345ae9d61Sreyk dh_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
37445ae9d61Sreyk {
37545ae9d61Sreyk 	return (group->shared(group, secret, exchange));
37645ae9d61Sreyk }
37745ae9d61Sreyk 
37845ae9d61Sreyk int
37945ae9d61Sreyk modp_init(struct group *group)
38045ae9d61Sreyk {
38145ae9d61Sreyk 	DH	*dh;
38245ae9d61Sreyk 
38345ae9d61Sreyk 	if ((dh = DH_new()) == NULL)
38445ae9d61Sreyk 		return (-1);
3857d7b0856Sreyk 	group->dh = dh;
38645ae9d61Sreyk 
38745ae9d61Sreyk 	if (!BN_hex2bn(&dh->p, group->spec->prime) ||
38845ae9d61Sreyk 	    !BN_hex2bn(&dh->g, group->spec->generator))
38945ae9d61Sreyk 		return (-1);
39045ae9d61Sreyk 
39145ae9d61Sreyk 	return (0);
39245ae9d61Sreyk }
39345ae9d61Sreyk 
39445ae9d61Sreyk int
39545ae9d61Sreyk modp_getlen(struct group *group)
39645ae9d61Sreyk {
39745ae9d61Sreyk 	if (group->spec == NULL)
39845ae9d61Sreyk 		return (0);
39945ae9d61Sreyk 	return (roundup(group->spec->bits, 8) / 8);
40045ae9d61Sreyk }
40145ae9d61Sreyk 
40245ae9d61Sreyk int
40345ae9d61Sreyk modp_create_exchange(struct group *group, u_int8_t *buf)
40445ae9d61Sreyk {
40545ae9d61Sreyk 	DH	*dh = group->dh;
40612abf43bSmikeb 	int	 len, ret;
40745ae9d61Sreyk 
40845ae9d61Sreyk 	if (!DH_generate_key(dh))
40945ae9d61Sreyk 		return (-1);
41012abf43bSmikeb 	ret = BN_bn2bin(dh->pub_key, buf);
41112abf43bSmikeb 	if (!ret)
41245ae9d61Sreyk 		return (-1);
41345ae9d61Sreyk 
41412abf43bSmikeb 	len = dh_getlen(group);
41512abf43bSmikeb 
41612abf43bSmikeb 	/* add zero padding */
41712abf43bSmikeb 	if (ret < len) {
41812abf43bSmikeb 		bcopy(buf, buf + (len - ret), ret);
41912abf43bSmikeb 		bzero(buf, len - ret);
42012abf43bSmikeb 	}
42112abf43bSmikeb 
4227d7b0856Sreyk 	return (0);
42345ae9d61Sreyk }
42445ae9d61Sreyk 
42545ae9d61Sreyk int
42645ae9d61Sreyk modp_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
42745ae9d61Sreyk {
42845ae9d61Sreyk 	BIGNUM	*ex;
42912abf43bSmikeb 	int	 len, ret;
43045ae9d61Sreyk 
43112abf43bSmikeb 	len = dh_getlen(group);
43212abf43bSmikeb 
43312abf43bSmikeb 	if ((ex = BN_bin2bn(exchange, len, NULL)) == NULL)
43445ae9d61Sreyk 		return (-1);
4357d7b0856Sreyk 
4367d7b0856Sreyk 	ret = DH_compute_key(secret, ex, group->dh);
4377d7b0856Sreyk 	BN_clear_free(ex);
4387d7b0856Sreyk 	if (!ret)
43945ae9d61Sreyk 		return (-1);
44045ae9d61Sreyk 
44112abf43bSmikeb 	/* add zero padding */
44212abf43bSmikeb 	if (ret < len) {
44312abf43bSmikeb 		bcopy(secret, secret + (len - ret), ret);
44412abf43bSmikeb 		bzero(secret, len - ret);
44512abf43bSmikeb 	}
44612abf43bSmikeb 
4477d7b0856Sreyk 	return (0);
44845ae9d61Sreyk }
44945ae9d61Sreyk 
45045ae9d61Sreyk int
45145ae9d61Sreyk ec_init(struct group *group)
45245ae9d61Sreyk {
45345ae9d61Sreyk 	if ((group->ec = EC_KEY_new_by_curve_name(group->spec->nid)) == NULL)
45445ae9d61Sreyk 		return (-1);
45545ae9d61Sreyk 	if (!EC_KEY_generate_key(group->ec))
45645ae9d61Sreyk 		return (-1);
457c900656bSmarkus 	if (!EC_KEY_check_key(group->ec)) {
458c900656bSmarkus 		EC_KEY_free(group->ec);
459c900656bSmarkus 		return (-1);
460c900656bSmarkus 	}
46145ae9d61Sreyk 	return (0);
46245ae9d61Sreyk }
46345ae9d61Sreyk 
46445ae9d61Sreyk int
46545ae9d61Sreyk ec_getlen(struct group *group)
46645ae9d61Sreyk {
46745ae9d61Sreyk 	if (group->spec == NULL)
46845ae9d61Sreyk 		return (0);
46945b72fd1Smikeb 	/* NB:  Return value will always be even */
47045ae9d61Sreyk 	return ((roundup(group->spec->bits, 8) * 2) / 8);
47145ae9d61Sreyk }
47245ae9d61Sreyk 
47345ae9d61Sreyk int
47445ae9d61Sreyk ec_create_exchange(struct group *group, u_int8_t *buf)
47545ae9d61Sreyk {
4760d5bf58dSreyk 	size_t	 len;
4770d5bf58dSreyk 
4780d5bf58dSreyk 	len = ec_getlen(group);
4790d5bf58dSreyk 	bzero(buf, len);
4800d5bf58dSreyk 
48145ae9d61Sreyk 	return (ec_point2raw(group, EC_KEY_get0_public_key(group->ec),
4820d5bf58dSreyk 	    buf, len));
48345ae9d61Sreyk }
48445ae9d61Sreyk 
48545ae9d61Sreyk int
48645ae9d61Sreyk ec_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange)
48745ae9d61Sreyk {
48845ae9d61Sreyk 	const EC_GROUP	*ecgroup = NULL;
48945ae9d61Sreyk 	const BIGNUM	*privkey;
490c900656bSmarkus 	EC_KEY		*exkey = NULL;
49145ae9d61Sreyk 	EC_POINT	*exchangep = NULL, *secretp = NULL;
49245ae9d61Sreyk 	int		 ret = -1;
49345ae9d61Sreyk 
49445ae9d61Sreyk 	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL ||
49545ae9d61Sreyk 	    (privkey = EC_KEY_get0_private_key(group->ec)) == NULL)
49645ae9d61Sreyk 		goto done;
49745ae9d61Sreyk 
49845ae9d61Sreyk 	if ((exchangep =
49945ae9d61Sreyk 	    ec_raw2point(group, exchange, ec_getlen(group))) == NULL)
50045ae9d61Sreyk 		goto done;
50145ae9d61Sreyk 
502c900656bSmarkus 	if ((exkey = EC_KEY_new()) == NULL)
503c900656bSmarkus 		goto done;
504c900656bSmarkus 	if (!EC_KEY_set_group(exkey, ecgroup))
505c900656bSmarkus 		goto done;
506c900656bSmarkus 	if (!EC_KEY_set_public_key(exkey, exchangep))
507c900656bSmarkus 		goto done;
508c900656bSmarkus 
509c900656bSmarkus 	/* validate exchangep */
510c900656bSmarkus 	if (!EC_KEY_check_key(exkey))
511c900656bSmarkus 		goto done;
512c900656bSmarkus 
51345ae9d61Sreyk 	if ((secretp = EC_POINT_new(ecgroup)) == NULL)
51445ae9d61Sreyk 		goto done;
51545ae9d61Sreyk 
51645ae9d61Sreyk 	if (!EC_POINT_mul(ecgroup, secretp, NULL, exchangep, privkey, NULL))
51745ae9d61Sreyk 		goto done;
51845ae9d61Sreyk 
51945ae9d61Sreyk 	ret = ec_point2raw(group, secretp, secret, ec_getlen(group));
52045ae9d61Sreyk 
52145ae9d61Sreyk  done:
522c900656bSmarkus 	if (exkey != NULL)
523c900656bSmarkus 		EC_KEY_free(exkey);
52445ae9d61Sreyk 	if (exchangep != NULL)
52545ae9d61Sreyk 		EC_POINT_clear_free(exchangep);
52645ae9d61Sreyk 	if (secretp != NULL)
52745ae9d61Sreyk 		EC_POINT_clear_free(secretp);
52845ae9d61Sreyk 
52945ae9d61Sreyk 	return (ret);
53045ae9d61Sreyk }
53145ae9d61Sreyk 
53245ae9d61Sreyk int
53345ae9d61Sreyk ec_point2raw(struct group *group, const EC_POINT *point,
53445ae9d61Sreyk     u_int8_t *buf, size_t len)
53545ae9d61Sreyk {
53645ae9d61Sreyk 	const EC_GROUP	*ecgroup = NULL;
53745ae9d61Sreyk 	BN_CTX		*bnctx = NULL;
53845ae9d61Sreyk 	BIGNUM		*x = NULL, *y = NULL;
53945ae9d61Sreyk 	int		 ret = -1;
54045b72fd1Smikeb 	size_t		 eclen, xlen, ylen;
54145ae9d61Sreyk 	off_t		 xoff, yoff;
54245ae9d61Sreyk 
54345ae9d61Sreyk 	if ((bnctx = BN_CTX_new()) == NULL)
54445ae9d61Sreyk 		goto done;
54545ae9d61Sreyk 	BN_CTX_start(bnctx);
54645ae9d61Sreyk 	if ((x = BN_CTX_get(bnctx)) == NULL ||
54745ae9d61Sreyk 	    (y = BN_CTX_get(bnctx)) == NULL)
54845ae9d61Sreyk 		goto done;
54945ae9d61Sreyk 
55045b72fd1Smikeb 	eclen = ec_getlen(group);
55145b72fd1Smikeb 	if (len < eclen)
55245b72fd1Smikeb 		goto done;
55345b72fd1Smikeb 	xlen = ylen = eclen / 2;
55445b72fd1Smikeb 
55545ae9d61Sreyk 	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL)
55645ae9d61Sreyk 		goto done;
55745ae9d61Sreyk 
55845ae9d61Sreyk 	if (EC_METHOD_get_field_type(EC_GROUP_method_of(ecgroup)) ==
55945ae9d61Sreyk 	    NID_X9_62_prime_field) {
56045ae9d61Sreyk 		if (!EC_POINT_get_affine_coordinates_GFp(ecgroup,
56145ae9d61Sreyk 		    point, x, y, bnctx))
56245ae9d61Sreyk 			goto done;
56345ae9d61Sreyk 	} else {
56445ae9d61Sreyk 		if (!EC_POINT_get_affine_coordinates_GF2m(ecgroup,
56545ae9d61Sreyk 		    point, x, y, bnctx))
56645ae9d61Sreyk 			goto done;
56745ae9d61Sreyk 	}
56845ae9d61Sreyk 
56945ae9d61Sreyk 	xoff = xlen - BN_num_bytes(x);
57045b72fd1Smikeb 	bzero(buf, xoff);
57145ae9d61Sreyk 	if (!BN_bn2bin(x, buf + xoff))
57245ae9d61Sreyk 		goto done;
57345ae9d61Sreyk 
57445ae9d61Sreyk 	yoff = (ylen - BN_num_bytes(y)) + xlen;
57545b72fd1Smikeb 	bzero(buf + xlen, yoff - xlen);
57645ae9d61Sreyk 	if (!BN_bn2bin(y, buf + yoff))
57745ae9d61Sreyk 		goto done;
57845ae9d61Sreyk 
57945ae9d61Sreyk 	ret = 0;
58045ae9d61Sreyk  done:
581c900656bSmarkus 	/* Make sure to erase sensitive data */
582c900656bSmarkus 	if (x != NULL)
583c900656bSmarkus 		BN_clear(x);
584c900656bSmarkus 	if (y != NULL)
585c900656bSmarkus 		BN_clear(y);
58645ae9d61Sreyk 	BN_CTX_end(bnctx);
58745ae9d61Sreyk 	BN_CTX_free(bnctx);
58845ae9d61Sreyk 
58945ae9d61Sreyk 	return (ret);
59045ae9d61Sreyk }
59145ae9d61Sreyk 
59245ae9d61Sreyk EC_POINT *
59345ae9d61Sreyk ec_raw2point(struct group *group, u_int8_t *buf, size_t len)
59445ae9d61Sreyk {
59545ae9d61Sreyk 	const EC_GROUP	*ecgroup = NULL;
59645ae9d61Sreyk 	EC_POINT	*point = NULL;
59745ae9d61Sreyk 	BN_CTX		*bnctx = NULL;
59845ae9d61Sreyk 	BIGNUM		*x = NULL, *y = NULL;
59945ae9d61Sreyk 	int		 ret = -1;
60045ae9d61Sreyk 	size_t		 eclen;
60145ae9d61Sreyk 	size_t		 xlen, ylen;
60245ae9d61Sreyk 
60345ae9d61Sreyk 	if ((bnctx = BN_CTX_new()) == NULL)
60445ae9d61Sreyk 		goto done;
60545ae9d61Sreyk 	BN_CTX_start(bnctx);
60645ae9d61Sreyk 	if ((x = BN_CTX_get(bnctx)) == NULL ||
60745ae9d61Sreyk 	    (y = BN_CTX_get(bnctx)) == NULL)
60845ae9d61Sreyk 		goto done;
60945ae9d61Sreyk 
61045ae9d61Sreyk 	eclen = ec_getlen(group);
61145ae9d61Sreyk 	if (len < eclen)
61245ae9d61Sreyk 		goto done;
61345ae9d61Sreyk 	xlen = ylen = eclen / 2;
61445ae9d61Sreyk 	if ((x = BN_bin2bn(buf, xlen, x)) == NULL ||
61545ae9d61Sreyk 	    (y = BN_bin2bn(buf + xlen, ylen, y)) == NULL)
61645ae9d61Sreyk 		goto done;
61745ae9d61Sreyk 
61845ae9d61Sreyk 	if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL)
61945ae9d61Sreyk 		goto done;
62045ae9d61Sreyk 
62145ae9d61Sreyk 	if ((point = EC_POINT_new(ecgroup)) == NULL)
62245ae9d61Sreyk 		goto done;
62345ae9d61Sreyk 
62445ae9d61Sreyk 	if (EC_METHOD_get_field_type(EC_GROUP_method_of(ecgroup)) ==
62545ae9d61Sreyk 	    NID_X9_62_prime_field) {
62645ae9d61Sreyk 		if (!EC_POINT_set_affine_coordinates_GFp(ecgroup,
62745ae9d61Sreyk 		    point, x, y, bnctx))
62845ae9d61Sreyk 			goto done;
62945ae9d61Sreyk 	} else {
63045ae9d61Sreyk 		if (!EC_POINT_set_affine_coordinates_GF2m(ecgroup,
63145ae9d61Sreyk 		    point, x, y, bnctx))
63245ae9d61Sreyk 			goto done;
63345ae9d61Sreyk 	}
63445ae9d61Sreyk 
63545ae9d61Sreyk 	ret = 0;
63645ae9d61Sreyk  done:
63745ae9d61Sreyk 	if (ret != 0 && point != NULL)
63845ae9d61Sreyk 		EC_POINT_clear_free(point);
639c900656bSmarkus 	/* Make sure to erase sensitive data */
640c900656bSmarkus 	if (x != NULL)
641c900656bSmarkus 		BN_clear(x);
642c900656bSmarkus 	if (y != NULL)
643c900656bSmarkus 		BN_clear(y);
64445ae9d61Sreyk 	BN_CTX_end(bnctx);
64545ae9d61Sreyk 	BN_CTX_free(bnctx);
64645ae9d61Sreyk 
64745ae9d61Sreyk 	return (point);
64845ae9d61Sreyk }
649