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