1*64449014Sreyk /* $OpenBSD: dh.c,v 1.9 2012/12/15 23:18:17 reyk Exp $ */ 245ae9d61Sreyk /* $vantronix: dh.c,v 1.13 2010/05/28 15:34:35 reyk Exp $ */ 345ae9d61Sreyk 445ae9d61Sreyk /* 53fbc3006Sreyk * Copyright (c) 2010 Reyk Floeter <reyk@openbsd.org> 645ae9d61Sreyk * 745ae9d61Sreyk * Permission to use, copy, modify, and distribute this software for any 845ae9d61Sreyk * purpose with or without fee is hereby granted, provided that the above 945ae9d61Sreyk * copyright notice and this permission notice appear in all copies. 1045ae9d61Sreyk * 1145ae9d61Sreyk * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 1245ae9d61Sreyk * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1345ae9d61Sreyk * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1445ae9d61Sreyk * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1545ae9d61Sreyk * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1645ae9d61Sreyk * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1745ae9d61Sreyk * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1845ae9d61Sreyk */ 1945ae9d61Sreyk 2045ae9d61Sreyk #include <sys/param.h> 2145ae9d61Sreyk #include <string.h> 2245ae9d61Sreyk 2345ae9d61Sreyk #include <openssl/obj_mac.h> 2445ae9d61Sreyk #include <openssl/dh.h> 2545ae9d61Sreyk #include <openssl/ec.h> 2645ae9d61Sreyk #include <openssl/ecdh.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; 301*64449014Sreyk 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); 45745ae9d61Sreyk return (0); 45845ae9d61Sreyk } 45945ae9d61Sreyk 46045ae9d61Sreyk int 46145ae9d61Sreyk ec_getlen(struct group *group) 46245ae9d61Sreyk { 46345ae9d61Sreyk if (group->spec == NULL) 46445ae9d61Sreyk return (0); 46545b72fd1Smikeb /* NB: Return value will always be even */ 46645ae9d61Sreyk return ((roundup(group->spec->bits, 8) * 2) / 8); 46745ae9d61Sreyk } 46845ae9d61Sreyk 46945ae9d61Sreyk int 47045ae9d61Sreyk ec_create_exchange(struct group *group, u_int8_t *buf) 47145ae9d61Sreyk { 4720d5bf58dSreyk size_t len; 4730d5bf58dSreyk 4740d5bf58dSreyk len = ec_getlen(group); 4750d5bf58dSreyk bzero(buf, len); 4760d5bf58dSreyk 47745ae9d61Sreyk return (ec_point2raw(group, EC_KEY_get0_public_key(group->ec), 4780d5bf58dSreyk buf, len)); 47945ae9d61Sreyk } 48045ae9d61Sreyk 48145ae9d61Sreyk int 48245ae9d61Sreyk ec_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange) 48345ae9d61Sreyk { 48445ae9d61Sreyk const EC_GROUP *ecgroup = NULL; 48545ae9d61Sreyk const BIGNUM *privkey; 48645ae9d61Sreyk EC_POINT *exchangep = NULL, *secretp = NULL; 48745ae9d61Sreyk int ret = -1; 48845ae9d61Sreyk 48945ae9d61Sreyk if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL || 49045ae9d61Sreyk (privkey = EC_KEY_get0_private_key(group->ec)) == NULL) 49145ae9d61Sreyk goto done; 49245ae9d61Sreyk 49345ae9d61Sreyk if ((exchangep = 49445ae9d61Sreyk ec_raw2point(group, exchange, ec_getlen(group))) == NULL) 49545ae9d61Sreyk goto done; 49645ae9d61Sreyk 49745ae9d61Sreyk if ((secretp = EC_POINT_new(ecgroup)) == NULL) 49845ae9d61Sreyk goto done; 49945ae9d61Sreyk 50045ae9d61Sreyk if (!EC_POINT_mul(ecgroup, secretp, NULL, exchangep, privkey, NULL)) 50145ae9d61Sreyk goto done; 50245ae9d61Sreyk 50345ae9d61Sreyk ret = ec_point2raw(group, secretp, secret, ec_getlen(group)); 50445ae9d61Sreyk 50545ae9d61Sreyk done: 50645ae9d61Sreyk if (exchangep != NULL) 50745ae9d61Sreyk EC_POINT_clear_free(exchangep); 50845ae9d61Sreyk if (secretp != NULL) 50945ae9d61Sreyk EC_POINT_clear_free(secretp); 51045ae9d61Sreyk 51145ae9d61Sreyk return (ret); 51245ae9d61Sreyk } 51345ae9d61Sreyk 51445ae9d61Sreyk int 51545ae9d61Sreyk ec_point2raw(struct group *group, const EC_POINT *point, 51645ae9d61Sreyk u_int8_t *buf, size_t len) 51745ae9d61Sreyk { 51845ae9d61Sreyk const EC_GROUP *ecgroup = NULL; 51945ae9d61Sreyk BN_CTX *bnctx = NULL; 52045ae9d61Sreyk BIGNUM *x = NULL, *y = NULL; 52145ae9d61Sreyk int ret = -1; 52245b72fd1Smikeb size_t eclen, xlen, ylen; 52345ae9d61Sreyk off_t xoff, yoff; 52445ae9d61Sreyk 52545ae9d61Sreyk if ((bnctx = BN_CTX_new()) == NULL) 52645ae9d61Sreyk goto done; 52745ae9d61Sreyk BN_CTX_start(bnctx); 52845ae9d61Sreyk if ((x = BN_CTX_get(bnctx)) == NULL || 52945ae9d61Sreyk (y = BN_CTX_get(bnctx)) == NULL) 53045ae9d61Sreyk goto done; 53145ae9d61Sreyk 53245b72fd1Smikeb eclen = ec_getlen(group); 53345b72fd1Smikeb if (len < eclen) 53445b72fd1Smikeb goto done; 53545b72fd1Smikeb xlen = ylen = eclen / 2; 53645b72fd1Smikeb 53745ae9d61Sreyk if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL) 53845ae9d61Sreyk goto done; 53945ae9d61Sreyk 54045ae9d61Sreyk if (EC_METHOD_get_field_type(EC_GROUP_method_of(ecgroup)) == 54145ae9d61Sreyk NID_X9_62_prime_field) { 54245ae9d61Sreyk if (!EC_POINT_get_affine_coordinates_GFp(ecgroup, 54345ae9d61Sreyk point, x, y, bnctx)) 54445ae9d61Sreyk goto done; 54545ae9d61Sreyk } else { 54645ae9d61Sreyk if (!EC_POINT_get_affine_coordinates_GF2m(ecgroup, 54745ae9d61Sreyk point, x, y, bnctx)) 54845ae9d61Sreyk goto done; 54945ae9d61Sreyk } 55045ae9d61Sreyk 55145ae9d61Sreyk xoff = xlen - BN_num_bytes(x); 55245b72fd1Smikeb bzero(buf, xoff); 55345ae9d61Sreyk if (!BN_bn2bin(x, buf + xoff)) 55445ae9d61Sreyk goto done; 55545ae9d61Sreyk 55645ae9d61Sreyk yoff = (ylen - BN_num_bytes(y)) + xlen; 55745b72fd1Smikeb bzero(buf + xlen, yoff - xlen); 55845ae9d61Sreyk if (!BN_bn2bin(y, buf + yoff)) 55945ae9d61Sreyk goto done; 56045ae9d61Sreyk 56145ae9d61Sreyk ret = 0; 56245ae9d61Sreyk done: 56345ae9d61Sreyk BN_CTX_end(bnctx); 56445ae9d61Sreyk BN_CTX_free(bnctx); 56545ae9d61Sreyk 56645ae9d61Sreyk return (ret); 56745ae9d61Sreyk } 56845ae9d61Sreyk 56945ae9d61Sreyk EC_POINT * 57045ae9d61Sreyk ec_raw2point(struct group *group, u_int8_t *buf, size_t len) 57145ae9d61Sreyk { 57245ae9d61Sreyk const EC_GROUP *ecgroup = NULL; 57345ae9d61Sreyk EC_POINT *point = NULL; 57445ae9d61Sreyk BN_CTX *bnctx = NULL; 57545ae9d61Sreyk BIGNUM *x = NULL, *y = NULL; 57645ae9d61Sreyk int ret = -1; 57745ae9d61Sreyk size_t eclen; 57845ae9d61Sreyk size_t xlen, ylen; 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 58745ae9d61Sreyk eclen = ec_getlen(group); 58845ae9d61Sreyk if (len < eclen) 58945ae9d61Sreyk goto done; 59045ae9d61Sreyk xlen = ylen = eclen / 2; 59145ae9d61Sreyk if ((x = BN_bin2bn(buf, xlen, x)) == NULL || 59245ae9d61Sreyk (y = BN_bin2bn(buf + xlen, ylen, y)) == NULL) 59345ae9d61Sreyk goto done; 59445ae9d61Sreyk 59545ae9d61Sreyk if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL) 59645ae9d61Sreyk goto done; 59745ae9d61Sreyk 59845ae9d61Sreyk if ((point = EC_POINT_new(ecgroup)) == NULL) 59945ae9d61Sreyk goto done; 60045ae9d61Sreyk 60145ae9d61Sreyk if (EC_METHOD_get_field_type(EC_GROUP_method_of(ecgroup)) == 60245ae9d61Sreyk NID_X9_62_prime_field) { 60345ae9d61Sreyk if (!EC_POINT_set_affine_coordinates_GFp(ecgroup, 60445ae9d61Sreyk point, x, y, bnctx)) 60545ae9d61Sreyk goto done; 60645ae9d61Sreyk } else { 60745ae9d61Sreyk if (!EC_POINT_set_affine_coordinates_GF2m(ecgroup, 60845ae9d61Sreyk point, x, y, bnctx)) 60945ae9d61Sreyk goto done; 61045ae9d61Sreyk } 61145ae9d61Sreyk 61245ae9d61Sreyk ret = 0; 61345ae9d61Sreyk done: 61445ae9d61Sreyk if (ret != 0 && point != NULL) 61545ae9d61Sreyk EC_POINT_clear_free(point); 61645ae9d61Sreyk BN_CTX_end(bnctx); 61745ae9d61Sreyk BN_CTX_free(bnctx); 61845ae9d61Sreyk 61945ae9d61Sreyk return (point); 62045ae9d61Sreyk } 621