1*2ffa77eaSjsg /* $OpenBSD: dh.c,v 1.15 2014/10/12 15:57:00 jsg Exp $ */ 245ae9d61Sreyk 345ae9d61Sreyk /* 4547eb84dSreyk * Copyright (c) 2010-2014 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> 26a4194998Sjsg #include <openssl/bn.h> 2745ae9d61Sreyk 2845ae9d61Sreyk #include "dh.h" 290d5bf58dSreyk 300d5bf58dSreyk int dh_init(struct group *); 3145ae9d61Sreyk 3245135ebcSreyk /* MODP */ 3345ae9d61Sreyk int modp_init(struct group *); 3445ae9d61Sreyk int modp_getlen(struct group *); 3545ae9d61Sreyk int modp_create_exchange(struct group *, u_int8_t *); 3645ae9d61Sreyk int modp_create_shared(struct group *, u_int8_t *, u_int8_t *); 3745ae9d61Sreyk 3845135ebcSreyk /* EC2N/ECP */ 3945ae9d61Sreyk int ec_init(struct group *); 4045ae9d61Sreyk int ec_getlen(struct group *); 4145ae9d61Sreyk int ec_create_exchange(struct group *, u_int8_t *); 4245ae9d61Sreyk int ec_create_shared(struct group *, u_int8_t *, u_int8_t *); 4345ae9d61Sreyk 4445ae9d61Sreyk int ec_point2raw(struct group *, const EC_POINT *, u_int8_t *, size_t); 4545ae9d61Sreyk EC_POINT * 4645ae9d61Sreyk ec_raw2point(struct group *, u_int8_t *, size_t); 4745ae9d61Sreyk 4845135ebcSreyk /* curve25519 */ 4945135ebcSreyk int ec25519_init(struct group *); 5045135ebcSreyk int ec25519_getlen(struct group *); 5145135ebcSreyk int ec25519_create_exchange(struct group *, u_int8_t *); 5245135ebcSreyk int ec25519_create_shared(struct group *, u_int8_t *, u_int8_t *); 5345135ebcSreyk 5445135ebcSreyk #define CURVE25519_SIZE 32 /* 256 bits */ 5545135ebcSreyk struct curve25519_key { 5645135ebcSreyk u_int8_t secret[CURVE25519_SIZE]; 5745135ebcSreyk u_int8_t public[CURVE25519_SIZE]; 5845135ebcSreyk }; 5945135ebcSreyk extern int crypto_scalarmult_curve25519(u_char a[CURVE25519_SIZE], 6045135ebcSreyk const u_char b[CURVE25519_SIZE], const u_char c[CURVE25519_SIZE]) 6145135ebcSreyk __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) 6245135ebcSreyk __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))) 6345135ebcSreyk __attribute__((__bounded__(__minbytes__, 3, CURVE25519_SIZE))); 6445135ebcSreyk 6545ae9d61Sreyk struct group_id ike_groups[] = { 6645ae9d61Sreyk { GROUP_MODP, 1, 768, 6745ae9d61Sreyk "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 6845ae9d61Sreyk "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 6945ae9d61Sreyk "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 7045ae9d61Sreyk "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF", 7145ae9d61Sreyk "02" 7245ae9d61Sreyk }, 7345ae9d61Sreyk { GROUP_MODP, 2, 1024, 7445ae9d61Sreyk "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 7545ae9d61Sreyk "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 7645ae9d61Sreyk "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 7745ae9d61Sreyk "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 7845ae9d61Sreyk "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" 7945ae9d61Sreyk "FFFFFFFFFFFFFFFF", 8045ae9d61Sreyk "02" 8145ae9d61Sreyk }, 82369beec1Sreyk { GROUP_EC2N, 3, 155, NULL, NULL, NID_ipsec3 }, 83369beec1Sreyk { GROUP_EC2N, 4, 185, NULL, NULL, NID_ipsec4 }, 8445ae9d61Sreyk { GROUP_MODP, 5, 1536, 8545ae9d61Sreyk "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 8645ae9d61Sreyk "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 8745ae9d61Sreyk "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 8845ae9d61Sreyk "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 8945ae9d61Sreyk "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" 9045ae9d61Sreyk "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" 9145ae9d61Sreyk "83655D23DCA3AD961C62F356208552BB9ED529077096966D" 9245ae9d61Sreyk "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 9345ae9d61Sreyk "02" 9445ae9d61Sreyk }, 9545ae9d61Sreyk { GROUP_MODP, 14, 2048, 9645ae9d61Sreyk "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 9745ae9d61Sreyk "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 9845ae9d61Sreyk "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 9945ae9d61Sreyk "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 10045ae9d61Sreyk "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" 10145ae9d61Sreyk "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" 10245ae9d61Sreyk "83655D23DCA3AD961C62F356208552BB9ED529077096966D" 10345ae9d61Sreyk "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" 10445ae9d61Sreyk "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" 10545ae9d61Sreyk "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" 10645ae9d61Sreyk "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 10745ae9d61Sreyk "02" 10845ae9d61Sreyk }, 10945ae9d61Sreyk { GROUP_MODP, 15, 3072, 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 "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF", 12645ae9d61Sreyk "02" 12745ae9d61Sreyk }, 12845ae9d61Sreyk { GROUP_MODP, 16, 4096, 12945ae9d61Sreyk "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 13045ae9d61Sreyk "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 13145ae9d61Sreyk "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 13245ae9d61Sreyk "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 13345ae9d61Sreyk "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" 13445ae9d61Sreyk "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" 13545ae9d61Sreyk "83655D23DCA3AD961C62F356208552BB9ED529077096966D" 13645ae9d61Sreyk "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" 13745ae9d61Sreyk "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" 13845ae9d61Sreyk "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" 13945ae9d61Sreyk "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" 14045ae9d61Sreyk "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" 14145ae9d61Sreyk "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" 14245ae9d61Sreyk "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" 14345ae9d61Sreyk "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" 14445ae9d61Sreyk "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" 14545ae9d61Sreyk "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" 14645ae9d61Sreyk "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" 14745ae9d61Sreyk "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" 14845ae9d61Sreyk "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" 14945ae9d61Sreyk "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" 15045ae9d61Sreyk "FFFFFFFFFFFFFFFF", 15145ae9d61Sreyk "02" 15245ae9d61Sreyk }, 15345ae9d61Sreyk { GROUP_MODP, 17, 6144, 15445ae9d61Sreyk "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 15545ae9d61Sreyk "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 15645ae9d61Sreyk "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 15745ae9d61Sreyk "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 15845ae9d61Sreyk "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" 15945ae9d61Sreyk "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" 16045ae9d61Sreyk "83655D23DCA3AD961C62F356208552BB9ED529077096966D" 16145ae9d61Sreyk "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" 16245ae9d61Sreyk "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" 16345ae9d61Sreyk "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" 16445ae9d61Sreyk "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" 16545ae9d61Sreyk "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" 16645ae9d61Sreyk "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" 16745ae9d61Sreyk "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" 16845ae9d61Sreyk "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" 16945ae9d61Sreyk "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" 17045ae9d61Sreyk "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" 17145ae9d61Sreyk "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" 17245ae9d61Sreyk "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" 17345ae9d61Sreyk "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" 17445ae9d61Sreyk "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" 17545ae9d61Sreyk "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" 17645ae9d61Sreyk "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" 17745ae9d61Sreyk "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" 17845ae9d61Sreyk "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" 17945ae9d61Sreyk "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" 18045ae9d61Sreyk "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" 18145ae9d61Sreyk "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" 18245ae9d61Sreyk "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" 18345ae9d61Sreyk "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" 18445ae9d61Sreyk "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" 18545ae9d61Sreyk "12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF", 18645ae9d61Sreyk "02" 18745ae9d61Sreyk }, 18845ae9d61Sreyk { GROUP_MODP, 18, 8192, 18945ae9d61Sreyk "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 19045ae9d61Sreyk "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 19145ae9d61Sreyk "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 19245ae9d61Sreyk "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 19345ae9d61Sreyk "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" 19445ae9d61Sreyk "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" 19545ae9d61Sreyk "83655D23DCA3AD961C62F356208552BB9ED529077096966D" 19645ae9d61Sreyk "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" 19745ae9d61Sreyk "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" 19845ae9d61Sreyk "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" 19945ae9d61Sreyk "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" 20045ae9d61Sreyk "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" 20145ae9d61Sreyk "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" 20245ae9d61Sreyk "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" 20345ae9d61Sreyk "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" 20445ae9d61Sreyk "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" 20545ae9d61Sreyk "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" 20645ae9d61Sreyk "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" 20745ae9d61Sreyk "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" 20845ae9d61Sreyk "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" 20945ae9d61Sreyk "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" 21045ae9d61Sreyk "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" 21145ae9d61Sreyk "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" 21245ae9d61Sreyk "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" 21345ae9d61Sreyk "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" 21445ae9d61Sreyk "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" 21545ae9d61Sreyk "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" 21645ae9d61Sreyk "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" 21745ae9d61Sreyk "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" 21845ae9d61Sreyk "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" 21945ae9d61Sreyk "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" 22045ae9d61Sreyk "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" 22145ae9d61Sreyk "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" 22245ae9d61Sreyk "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" 22345ae9d61Sreyk "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" 22445ae9d61Sreyk "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" 22545ae9d61Sreyk "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" 22645ae9d61Sreyk "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" 22745ae9d61Sreyk "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" 22845ae9d61Sreyk "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" 22945ae9d61Sreyk "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" 23045ae9d61Sreyk "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" 23145ae9d61Sreyk "60C980DD98EDD3DFFFFFFFFFFFFFFFFF", 23245ae9d61Sreyk "02" 23345ae9d61Sreyk }, 234369beec1Sreyk { GROUP_ECP, 19, 256, NULL, NULL, NID_X9_62_prime256v1 }, 235369beec1Sreyk { GROUP_ECP, 20, 384, NULL, NULL, NID_secp384r1 }, 236369beec1Sreyk { GROUP_ECP, 21, 521, NULL, NULL, NID_secp521r1 }, 23745ae9d61Sreyk { GROUP_MODP, 22, 1024, 23845ae9d61Sreyk "B10B8F96A080E01DDE92DE5EAE5D54EC52C99FBCFB06A3C6" 23945ae9d61Sreyk "9A6A9DCA52D23B616073E28675A23D189838EF1E2EE652C0" 24045ae9d61Sreyk "13ECB4AEA906112324975C3CD49B83BFACCBDD7D90C4BD70" 24145ae9d61Sreyk "98488E9C219A73724EFFD6FAE5644738FAA31A4FF55BCCC0" 24245ae9d61Sreyk "A151AF5F0DC8B4BD45BF37DF365C1A65E68CFDA76D4DA708" 24345ae9d61Sreyk "DF1FB2BC2E4A4371", 24445ae9d61Sreyk "A4D1CBD5C3FD34126765A442EFB99905F8104DD258AC507F" 24545ae9d61Sreyk "D6406CFF14266D31266FEA1E5C41564B777E690F5504F213" 24645ae9d61Sreyk "160217B4B01B886A5E91547F9E2749F4D7FBD7D3B9A92EE1" 24745ae9d61Sreyk "909D0D2263F80A76A6A24C087A091F531DBF0A0169B6A28A" 24845ae9d61Sreyk "D662A4D18E73AFA32D779D5918D08BC8858F4DCEF97C2A24" 24945ae9d61Sreyk "855E6EEB22B3B2E5" 25045ae9d61Sreyk }, 25145ae9d61Sreyk { GROUP_MODP, 23, 2048, 25245ae9d61Sreyk "AD107E1E9123A9D0D660FAA79559C51FA20D64E5683B9FD1" 25345ae9d61Sreyk "B54B1597B61D0A75E6FA141DF95A56DBAF9A3C407BA1DF15" 25445ae9d61Sreyk "EB3D688A309C180E1DE6B85A1274A0A66D3F8152AD6AC212" 25545ae9d61Sreyk "9037C9EDEFDA4DF8D91E8FEF55B7394B7AD5B7D0B6C12207" 25645ae9d61Sreyk "C9F98D11ED34DBF6C6BA0B2C8BBC27BE6A00E0A0B9C49708" 25745ae9d61Sreyk "B3BF8A317091883681286130BC8985DB1602E714415D9330" 25845ae9d61Sreyk "278273C7DE31EFDC7310F7121FD5A07415987D9ADC0A486D" 25945ae9d61Sreyk "CDF93ACC44328387315D75E198C641A480CD86A1B9E587E8" 26045ae9d61Sreyk "BE60E69CC928B2B9C52172E413042E9B23F10B0E16E79763" 26145ae9d61Sreyk "C9B53DCF4BA80A29E3FB73C16B8E75B97EF363E2FFA31F71" 26245ae9d61Sreyk "CF9DE5384E71B81C0AC4DFFE0C10E64F", 26345ae9d61Sreyk "AC4032EF4F2D9AE39DF30B5C8FFDAC506CDEBE7B89998CAF" 26445ae9d61Sreyk "74866A08CFE4FFE3A6824A4E10B9A6F0DD921F01A70C4AFA" 26545ae9d61Sreyk "AB739D7700C29F52C57DB17C620A8652BE5E9001A8D66AD7" 26645ae9d61Sreyk "C17669101999024AF4D027275AC1348BB8A762D0521BC98A" 26745ae9d61Sreyk "E247150422EA1ED409939D54DA7460CDB5F6C6B250717CBE" 26845ae9d61Sreyk "F180EB34118E98D119529A45D6F834566E3025E316A330EF" 26945ae9d61Sreyk "BB77A86F0C1AB15B051AE3D428C8F8ACB70A8137150B8EEB" 27045ae9d61Sreyk "10E183EDD19963DDD9E263E4770589EF6AA21E7F5F2FF381" 27145ae9d61Sreyk "B539CCE3409D13CD566AFBB48D6C019181E1BCFE94B30269" 27245ae9d61Sreyk "EDFE72FE9B6AA4BD7B5A0F1C71CFFF4C19C418E1F6EC0179" 27345ae9d61Sreyk "81BC087F2A7065B384B890D3191F2BFA" 27445ae9d61Sreyk }, 27545ae9d61Sreyk { GROUP_MODP, 24, 2048, 27645ae9d61Sreyk "87A8E61DB4B6663CFFBBD19C651959998CEEF608660DD0F2" 27745ae9d61Sreyk "5D2CEED4435E3B00E00DF8F1D61957D4FAF7DF4561B2AA30" 27845ae9d61Sreyk "16C3D91134096FAA3BF4296D830E9A7C209E0C6497517ABD" 27945ae9d61Sreyk "5A8A9D306BCF67ED91F9E6725B4758C022E0B1EF4275BF7B" 28045ae9d61Sreyk "6C5BFC11D45F9088B941F54EB1E59BB8BC39A0BF12307F5C" 28145ae9d61Sreyk "4FDB70C581B23F76B63ACAE1CAA6B7902D52526735488A0E" 28245ae9d61Sreyk "F13C6D9A51BFA4AB3AD8347796524D8EF6A167B5A41825D9" 28345ae9d61Sreyk "67E144E5140564251CCACB83E6B486F6B3CA3F7971506026" 28445ae9d61Sreyk "C0B857F689962856DED4010ABD0BE621C3A3960A54E710C3" 28545ae9d61Sreyk "75F26375D7014103A4B54330C198AF126116D2276E11715F" 28645ae9d61Sreyk "693877FAD7EF09CADB094AE91E1A1597", 28745ae9d61Sreyk "3FB32C9B73134D0B2E77506660EDBD484CA7B18F21EF2054" 28845ae9d61Sreyk "07F4793A1A0BA12510DBC15077BE463FFF4FED4AAC0BB555" 28945ae9d61Sreyk "BE3A6C1B0C6B47B1BC3773BF7E8C6F62901228F8C28CBB18" 29045ae9d61Sreyk "A55AE31341000A650196F931C77A57F2DDF463E5E9EC144B" 29145ae9d61Sreyk "777DE62AAAB8A8628AC376D282D6ED3864E67982428EBC83" 29245ae9d61Sreyk "1D14348F6F2F9193B5045AF2767164E1DFC967C1FB3F2E55" 29345ae9d61Sreyk "A4BD1BFFE83B9C80D052B985D182EA0ADB2A3B7313D3FE14" 29445ae9d61Sreyk "C8484B1E052588B9B7D2BBD2DF016199ECD06E1557CD0915" 29545ae9d61Sreyk "B3353BBB64E0EC377FD028370DF92B52C7891428CDC67EB6" 29645ae9d61Sreyk "184B523D1DB246C32F63078490F00EF8D647D148D4795451" 29745ae9d61Sreyk "5E2327CFEF98C582664B4C0F6CC41659" 29845ae9d61Sreyk }, 299369beec1Sreyk { GROUP_ECP, 25, 192, NULL, NULL, NID_X9_62_prime192v1 }, 300547eb84dSreyk { GROUP_ECP, 26, 224, NULL, NULL, NID_secp224r1 }, 301547eb84dSreyk { GROUP_ECP, 27, 224, NULL, NULL, NID_brainpoolP224r1 }, 302547eb84dSreyk { GROUP_ECP, 28, 256, NULL, NULL, NID_brainpoolP256r1 }, 303547eb84dSreyk { GROUP_ECP, 29, 384, NULL, NULL, NID_brainpoolP384r1 }, 30445135ebcSreyk { GROUP_ECP, 30, 512, NULL, NULL, NID_brainpoolP512r1 }, 30545135ebcSreyk 30645135ebcSreyk /* "Private use" extensions */ 30745135ebcSreyk { GROUP_CURVE25519, 1034, CURVE25519_SIZE * 8 } 30845ae9d61Sreyk }; 30945ae9d61Sreyk 31045ae9d61Sreyk void 31145ae9d61Sreyk group_init(void) 31245ae9d61Sreyk { 3130d5bf58dSreyk /* currently not used */ 31445ae9d61Sreyk return; 31545ae9d61Sreyk } 31645ae9d61Sreyk 31745ae9d61Sreyk void 31845ae9d61Sreyk group_free(struct group *group) 31945ae9d61Sreyk { 32045ae9d61Sreyk if (group == NULL) 32145ae9d61Sreyk return; 32245ae9d61Sreyk if (group->dh != NULL) 32345ae9d61Sreyk DH_free(group->dh); 32445ae9d61Sreyk if (group->ec != NULL) 32545ae9d61Sreyk EC_KEY_free(group->ec); 32645135ebcSreyk if (group->curve25519 != NULL) { 32745135ebcSreyk explicit_bzero(group->curve25519, 32845135ebcSreyk sizeof(struct curve25519_key)); 32945135ebcSreyk free(group->curve25519); 33045135ebcSreyk } 33145ae9d61Sreyk group->spec = NULL; 33264449014Sreyk free(group); 33345ae9d61Sreyk } 33445ae9d61Sreyk 33545ae9d61Sreyk struct group * 33645ae9d61Sreyk group_get(u_int32_t id) 33745ae9d61Sreyk { 33845ae9d61Sreyk struct group_id *p = NULL; 33945ae9d61Sreyk struct group *group; 34045ae9d61Sreyk u_int i, items; 34145ae9d61Sreyk 34245ae9d61Sreyk items = sizeof(ike_groups) / sizeof(ike_groups[0]); 34345ae9d61Sreyk for (i = 0; i < items; i++) { 34445ae9d61Sreyk if (id == ike_groups[i].id) { 34545ae9d61Sreyk p = &ike_groups[i]; 34645ae9d61Sreyk break; 34745ae9d61Sreyk } 34845ae9d61Sreyk } 34945ae9d61Sreyk if (p == NULL) 35045ae9d61Sreyk return (NULL); 35145ae9d61Sreyk 35245ae9d61Sreyk if ((group = calloc(1, sizeof(*group))) == NULL) 35345ae9d61Sreyk return (NULL); 35445ae9d61Sreyk 35545ae9d61Sreyk group->id = id; 35645ae9d61Sreyk group->spec = p; 35745ae9d61Sreyk 35845ae9d61Sreyk switch (p->type) { 35945ae9d61Sreyk case GROUP_MODP: 36045ae9d61Sreyk group->init = modp_init; 36145ae9d61Sreyk group->getlen = modp_getlen; 36245ae9d61Sreyk group->exchange = modp_create_exchange; 36345ae9d61Sreyk group->shared = modp_create_shared; 36445ae9d61Sreyk break; 365369beec1Sreyk case GROUP_EC2N: 366369beec1Sreyk case GROUP_ECP: 36745ae9d61Sreyk group->init = ec_init; 36845ae9d61Sreyk group->getlen = ec_getlen; 36945ae9d61Sreyk group->exchange = ec_create_exchange; 37045ae9d61Sreyk group->shared = ec_create_shared; 37145ae9d61Sreyk break; 37245135ebcSreyk case GROUP_CURVE25519: 37345135ebcSreyk group->init = ec25519_init; 37445135ebcSreyk group->getlen = ec25519_getlen; 37545135ebcSreyk group->exchange = ec25519_create_exchange; 37645135ebcSreyk group->shared = ec25519_create_shared; 37745135ebcSreyk break; 37845ae9d61Sreyk default: 37945ae9d61Sreyk group_free(group); 38045ae9d61Sreyk return (NULL); 38145ae9d61Sreyk } 38245ae9d61Sreyk 38345ae9d61Sreyk if (dh_init(group) != 0) { 38445ae9d61Sreyk group_free(group); 38545ae9d61Sreyk return (NULL); 38645ae9d61Sreyk } 38745ae9d61Sreyk 38845ae9d61Sreyk return (group); 38945ae9d61Sreyk } 39045ae9d61Sreyk 39145ae9d61Sreyk int 39245ae9d61Sreyk dh_init(struct group *group) 39345ae9d61Sreyk { 39445ae9d61Sreyk return (group->init(group)); 39545ae9d61Sreyk } 39645ae9d61Sreyk 39745ae9d61Sreyk int 39845ae9d61Sreyk dh_getlen(struct group *group) 39945ae9d61Sreyk { 40045ae9d61Sreyk return (group->getlen(group)); 40145ae9d61Sreyk } 40245ae9d61Sreyk 40345ae9d61Sreyk int 40445ae9d61Sreyk dh_create_exchange(struct group *group, u_int8_t *buf) 40545ae9d61Sreyk { 40645ae9d61Sreyk return (group->exchange(group, buf)); 40745ae9d61Sreyk } 40845ae9d61Sreyk 40945ae9d61Sreyk int 41045ae9d61Sreyk dh_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange) 41145ae9d61Sreyk { 41245ae9d61Sreyk return (group->shared(group, secret, exchange)); 41345ae9d61Sreyk } 41445ae9d61Sreyk 41545ae9d61Sreyk int 41645ae9d61Sreyk modp_init(struct group *group) 41745ae9d61Sreyk { 41845ae9d61Sreyk DH *dh; 41945ae9d61Sreyk 42045ae9d61Sreyk if ((dh = DH_new()) == NULL) 42145ae9d61Sreyk return (-1); 4227d7b0856Sreyk group->dh = dh; 42345ae9d61Sreyk 42445ae9d61Sreyk if (!BN_hex2bn(&dh->p, group->spec->prime) || 42545ae9d61Sreyk !BN_hex2bn(&dh->g, group->spec->generator)) 42645ae9d61Sreyk return (-1); 42745ae9d61Sreyk 42845ae9d61Sreyk return (0); 42945ae9d61Sreyk } 43045ae9d61Sreyk 43145ae9d61Sreyk int 43245ae9d61Sreyk modp_getlen(struct group *group) 43345ae9d61Sreyk { 43445ae9d61Sreyk if (group->spec == NULL) 43545ae9d61Sreyk return (0); 43645ae9d61Sreyk return (roundup(group->spec->bits, 8) / 8); 43745ae9d61Sreyk } 43845ae9d61Sreyk 43945ae9d61Sreyk int 44045ae9d61Sreyk modp_create_exchange(struct group *group, u_int8_t *buf) 44145ae9d61Sreyk { 44245ae9d61Sreyk DH *dh = group->dh; 44312abf43bSmikeb int len, ret; 44445ae9d61Sreyk 44545ae9d61Sreyk if (!DH_generate_key(dh)) 44645ae9d61Sreyk return (-1); 44712abf43bSmikeb ret = BN_bn2bin(dh->pub_key, buf); 44812abf43bSmikeb if (!ret) 44945ae9d61Sreyk return (-1); 45045ae9d61Sreyk 45112abf43bSmikeb len = dh_getlen(group); 45212abf43bSmikeb 45312abf43bSmikeb /* add zero padding */ 45412abf43bSmikeb if (ret < len) { 45512abf43bSmikeb bcopy(buf, buf + (len - ret), ret); 45612abf43bSmikeb bzero(buf, len - ret); 45712abf43bSmikeb } 45812abf43bSmikeb 4597d7b0856Sreyk return (0); 46045ae9d61Sreyk } 46145ae9d61Sreyk 46245ae9d61Sreyk int 46345ae9d61Sreyk modp_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange) 46445ae9d61Sreyk { 46545ae9d61Sreyk BIGNUM *ex; 46612abf43bSmikeb int len, ret; 46745ae9d61Sreyk 46812abf43bSmikeb len = dh_getlen(group); 46912abf43bSmikeb 47012abf43bSmikeb if ((ex = BN_bin2bn(exchange, len, NULL)) == NULL) 47145ae9d61Sreyk return (-1); 4727d7b0856Sreyk 4737d7b0856Sreyk ret = DH_compute_key(secret, ex, group->dh); 4747d7b0856Sreyk BN_clear_free(ex); 475*2ffa77eaSjsg if (ret <= 0) 47645ae9d61Sreyk return (-1); 47745ae9d61Sreyk 47812abf43bSmikeb /* add zero padding */ 47912abf43bSmikeb if (ret < len) { 48012abf43bSmikeb bcopy(secret, secret + (len - ret), ret); 48112abf43bSmikeb bzero(secret, len - ret); 48212abf43bSmikeb } 48312abf43bSmikeb 4847d7b0856Sreyk return (0); 48545ae9d61Sreyk } 48645ae9d61Sreyk 48745ae9d61Sreyk int 48845ae9d61Sreyk ec_init(struct group *group) 48945ae9d61Sreyk { 49045ae9d61Sreyk if ((group->ec = EC_KEY_new_by_curve_name(group->spec->nid)) == NULL) 49145ae9d61Sreyk return (-1); 49245ae9d61Sreyk if (!EC_KEY_generate_key(group->ec)) 49345ae9d61Sreyk return (-1); 494c900656bSmarkus if (!EC_KEY_check_key(group->ec)) { 495c900656bSmarkus EC_KEY_free(group->ec); 496c900656bSmarkus return (-1); 497c900656bSmarkus } 49845ae9d61Sreyk return (0); 49945ae9d61Sreyk } 50045ae9d61Sreyk 50145ae9d61Sreyk int 50245ae9d61Sreyk ec_getlen(struct group *group) 50345ae9d61Sreyk { 50445ae9d61Sreyk if (group->spec == NULL) 50545ae9d61Sreyk return (0); 50645b72fd1Smikeb /* NB: Return value will always be even */ 50745ae9d61Sreyk return ((roundup(group->spec->bits, 8) * 2) / 8); 50845ae9d61Sreyk } 50945ae9d61Sreyk 51045ae9d61Sreyk int 51145ae9d61Sreyk ec_create_exchange(struct group *group, u_int8_t *buf) 51245ae9d61Sreyk { 5130d5bf58dSreyk size_t len; 5140d5bf58dSreyk 5150d5bf58dSreyk len = ec_getlen(group); 5160d5bf58dSreyk bzero(buf, len); 5170d5bf58dSreyk 51845ae9d61Sreyk return (ec_point2raw(group, EC_KEY_get0_public_key(group->ec), 5190d5bf58dSreyk buf, len)); 52045ae9d61Sreyk } 52145ae9d61Sreyk 52245ae9d61Sreyk int 52345ae9d61Sreyk ec_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange) 52445ae9d61Sreyk { 52545ae9d61Sreyk const EC_GROUP *ecgroup = NULL; 52645ae9d61Sreyk const BIGNUM *privkey; 527c900656bSmarkus EC_KEY *exkey = NULL; 52845ae9d61Sreyk EC_POINT *exchangep = NULL, *secretp = NULL; 52945ae9d61Sreyk int ret = -1; 53045ae9d61Sreyk 53145ae9d61Sreyk if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL || 53245ae9d61Sreyk (privkey = EC_KEY_get0_private_key(group->ec)) == NULL) 53345ae9d61Sreyk goto done; 53445ae9d61Sreyk 53545ae9d61Sreyk if ((exchangep = 53645ae9d61Sreyk ec_raw2point(group, exchange, ec_getlen(group))) == NULL) 53745ae9d61Sreyk goto done; 53845ae9d61Sreyk 539c900656bSmarkus if ((exkey = EC_KEY_new()) == NULL) 540c900656bSmarkus goto done; 541c900656bSmarkus if (!EC_KEY_set_group(exkey, ecgroup)) 542c900656bSmarkus goto done; 543c900656bSmarkus if (!EC_KEY_set_public_key(exkey, exchangep)) 544c900656bSmarkus goto done; 545c900656bSmarkus 546c900656bSmarkus /* validate exchangep */ 547c900656bSmarkus if (!EC_KEY_check_key(exkey)) 548c900656bSmarkus goto done; 549c900656bSmarkus 55045ae9d61Sreyk if ((secretp = EC_POINT_new(ecgroup)) == NULL) 55145ae9d61Sreyk goto done; 55245ae9d61Sreyk 55345ae9d61Sreyk if (!EC_POINT_mul(ecgroup, secretp, NULL, exchangep, privkey, NULL)) 55445ae9d61Sreyk goto done; 55545ae9d61Sreyk 55645ae9d61Sreyk ret = ec_point2raw(group, secretp, secret, ec_getlen(group)); 55745ae9d61Sreyk 55845ae9d61Sreyk done: 559c900656bSmarkus if (exkey != NULL) 560c900656bSmarkus EC_KEY_free(exkey); 56145ae9d61Sreyk if (exchangep != NULL) 56245ae9d61Sreyk EC_POINT_clear_free(exchangep); 56345ae9d61Sreyk if (secretp != NULL) 56445ae9d61Sreyk EC_POINT_clear_free(secretp); 56545ae9d61Sreyk 56645ae9d61Sreyk return (ret); 56745ae9d61Sreyk } 56845ae9d61Sreyk 56945ae9d61Sreyk int 57045ae9d61Sreyk ec_point2raw(struct group *group, const EC_POINT *point, 57145ae9d61Sreyk u_int8_t *buf, size_t len) 57245ae9d61Sreyk { 57345ae9d61Sreyk const EC_GROUP *ecgroup = NULL; 57445ae9d61Sreyk BN_CTX *bnctx = NULL; 57545ae9d61Sreyk BIGNUM *x = NULL, *y = NULL; 57645ae9d61Sreyk int ret = -1; 57745b72fd1Smikeb size_t eclen, xlen, ylen; 57845ae9d61Sreyk off_t xoff, yoff; 57945ae9d61Sreyk 58045ae9d61Sreyk if ((bnctx = BN_CTX_new()) == NULL) 58145ae9d61Sreyk goto done; 58245ae9d61Sreyk BN_CTX_start(bnctx); 58345ae9d61Sreyk if ((x = BN_CTX_get(bnctx)) == NULL || 58445ae9d61Sreyk (y = BN_CTX_get(bnctx)) == NULL) 58545ae9d61Sreyk goto done; 58645ae9d61Sreyk 58745b72fd1Smikeb eclen = ec_getlen(group); 58845b72fd1Smikeb if (len < eclen) 58945b72fd1Smikeb goto done; 59045b72fd1Smikeb xlen = ylen = eclen / 2; 59145b72fd1Smikeb 59245ae9d61Sreyk if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL) 59345ae9d61Sreyk goto done; 59445ae9d61Sreyk 59545ae9d61Sreyk if (EC_METHOD_get_field_type(EC_GROUP_method_of(ecgroup)) == 59645ae9d61Sreyk NID_X9_62_prime_field) { 59745ae9d61Sreyk if (!EC_POINT_get_affine_coordinates_GFp(ecgroup, 59845ae9d61Sreyk point, x, y, bnctx)) 59945ae9d61Sreyk goto done; 60045ae9d61Sreyk } else { 60145ae9d61Sreyk if (!EC_POINT_get_affine_coordinates_GF2m(ecgroup, 60245ae9d61Sreyk point, x, y, bnctx)) 60345ae9d61Sreyk goto done; 60445ae9d61Sreyk } 60545ae9d61Sreyk 60645ae9d61Sreyk xoff = xlen - BN_num_bytes(x); 60745b72fd1Smikeb bzero(buf, xoff); 60845ae9d61Sreyk if (!BN_bn2bin(x, buf + xoff)) 60945ae9d61Sreyk goto done; 61045ae9d61Sreyk 61145ae9d61Sreyk yoff = (ylen - BN_num_bytes(y)) + xlen; 61245b72fd1Smikeb bzero(buf + xlen, yoff - xlen); 61345ae9d61Sreyk if (!BN_bn2bin(y, buf + yoff)) 61445ae9d61Sreyk goto done; 61545ae9d61Sreyk 61645ae9d61Sreyk ret = 0; 61745ae9d61Sreyk done: 618c900656bSmarkus /* Make sure to erase sensitive data */ 619c900656bSmarkus if (x != NULL) 620c900656bSmarkus BN_clear(x); 621c900656bSmarkus if (y != NULL) 622c900656bSmarkus BN_clear(y); 62345ae9d61Sreyk BN_CTX_end(bnctx); 62445ae9d61Sreyk BN_CTX_free(bnctx); 62545ae9d61Sreyk 62645ae9d61Sreyk return (ret); 62745ae9d61Sreyk } 62845ae9d61Sreyk 62945ae9d61Sreyk EC_POINT * 63045ae9d61Sreyk ec_raw2point(struct group *group, u_int8_t *buf, size_t len) 63145ae9d61Sreyk { 63245ae9d61Sreyk const EC_GROUP *ecgroup = NULL; 63345ae9d61Sreyk EC_POINT *point = NULL; 63445ae9d61Sreyk BN_CTX *bnctx = NULL; 63545ae9d61Sreyk BIGNUM *x = NULL, *y = NULL; 63645ae9d61Sreyk int ret = -1; 63745ae9d61Sreyk size_t eclen; 63845ae9d61Sreyk size_t xlen, ylen; 63945ae9d61Sreyk 64045ae9d61Sreyk if ((bnctx = BN_CTX_new()) == NULL) 64145ae9d61Sreyk goto done; 64245ae9d61Sreyk BN_CTX_start(bnctx); 64345ae9d61Sreyk if ((x = BN_CTX_get(bnctx)) == NULL || 64445ae9d61Sreyk (y = BN_CTX_get(bnctx)) == NULL) 64545ae9d61Sreyk goto done; 64645ae9d61Sreyk 64745ae9d61Sreyk eclen = ec_getlen(group); 64845ae9d61Sreyk if (len < eclen) 64945ae9d61Sreyk goto done; 65045ae9d61Sreyk xlen = ylen = eclen / 2; 65145ae9d61Sreyk if ((x = BN_bin2bn(buf, xlen, x)) == NULL || 65245ae9d61Sreyk (y = BN_bin2bn(buf + xlen, ylen, y)) == NULL) 65345ae9d61Sreyk goto done; 65445ae9d61Sreyk 65545ae9d61Sreyk if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL) 65645ae9d61Sreyk goto done; 65745ae9d61Sreyk 65845ae9d61Sreyk if ((point = EC_POINT_new(ecgroup)) == NULL) 65945ae9d61Sreyk goto done; 66045ae9d61Sreyk 66145ae9d61Sreyk if (EC_METHOD_get_field_type(EC_GROUP_method_of(ecgroup)) == 66245ae9d61Sreyk NID_X9_62_prime_field) { 66345ae9d61Sreyk if (!EC_POINT_set_affine_coordinates_GFp(ecgroup, 66445ae9d61Sreyk point, x, y, bnctx)) 66545ae9d61Sreyk goto done; 66645ae9d61Sreyk } else { 66745ae9d61Sreyk if (!EC_POINT_set_affine_coordinates_GF2m(ecgroup, 66845ae9d61Sreyk point, x, y, bnctx)) 66945ae9d61Sreyk goto done; 67045ae9d61Sreyk } 67145ae9d61Sreyk 67245ae9d61Sreyk ret = 0; 67345ae9d61Sreyk done: 67445ae9d61Sreyk if (ret != 0 && point != NULL) 67545ae9d61Sreyk EC_POINT_clear_free(point); 676c900656bSmarkus /* Make sure to erase sensitive data */ 677c900656bSmarkus if (x != NULL) 678c900656bSmarkus BN_clear(x); 679c900656bSmarkus if (y != NULL) 680c900656bSmarkus BN_clear(y); 68145ae9d61Sreyk BN_CTX_end(bnctx); 68245ae9d61Sreyk BN_CTX_free(bnctx); 68345ae9d61Sreyk 68445ae9d61Sreyk return (point); 68545ae9d61Sreyk } 68645135ebcSreyk 68745135ebcSreyk int 68845135ebcSreyk ec25519_init(struct group *group) 68945135ebcSreyk { 69045135ebcSreyk static const u_int8_t basepoint[CURVE25519_SIZE] = { 9 }; 69145135ebcSreyk struct curve25519_key *curve25519; 69245135ebcSreyk 69345135ebcSreyk if ((curve25519 = calloc(1, sizeof(*curve25519))) == NULL) 69445135ebcSreyk return (-1); 69545135ebcSreyk 69645135ebcSreyk group->curve25519 = curve25519; 69745135ebcSreyk 69845135ebcSreyk arc4random_buf(curve25519->secret, CURVE25519_SIZE); 69945135ebcSreyk crypto_scalarmult_curve25519(curve25519->public, 70045135ebcSreyk curve25519->secret, basepoint); 70145135ebcSreyk 70245135ebcSreyk return (0); 70345135ebcSreyk } 70445135ebcSreyk 70545135ebcSreyk int 70645135ebcSreyk ec25519_getlen(struct group *group) 70745135ebcSreyk { 70845135ebcSreyk if (group->spec == NULL) 70945135ebcSreyk return (0); 71045135ebcSreyk return (CURVE25519_SIZE); 71145135ebcSreyk } 71245135ebcSreyk 71345135ebcSreyk int 71445135ebcSreyk ec25519_create_exchange(struct group *group, u_int8_t *buf) 71545135ebcSreyk { 71645135ebcSreyk struct curve25519_key *curve25519 = group->curve25519; 71745135ebcSreyk 71845135ebcSreyk memcpy(buf, curve25519->public, ec25519_getlen(group)); 71945135ebcSreyk return (0); 72045135ebcSreyk } 72145135ebcSreyk 72245135ebcSreyk int 72345135ebcSreyk ec25519_create_shared(struct group *group, u_int8_t *shared, u_int8_t *public) 72445135ebcSreyk { 72545135ebcSreyk struct curve25519_key *curve25519 = group->curve25519; 72645135ebcSreyk 72745135ebcSreyk crypto_scalarmult_curve25519(shared, curve25519->secret, public); 72845135ebcSreyk return (0); 72945135ebcSreyk } 730