1/* $OpenBSD: dh.c,v 1.33 2023/07/28 07:31:38 claudio Exp $ */ 2 3/* 4 * Copyright (c) 2010-2014 Reyk Floeter <reyk@openbsd.org> 5 * 6 * Permission to use, copy, modify, and distribute this software for any 7 * purpose with or without fee is hereby granted, provided that the above 8 * copyright notice and this permission notice appear in all copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 17 */ 18 19#include <sys/types.h> 20 21#include <sys/queue.h> 22#include <sys/socket.h> 23#include <sys/uio.h> 24#include <string.h> 25#include <event.h> 26#include <imsg.h> 27 28#include <openssl/evp.h> 29#include <openssl/sha.h> 30#include <openssl/obj_mac.h> 31#include <openssl/dh.h> 32#include <openssl/ec.h> 33#include <openssl/ecdh.h> 34#include <openssl/bn.h> 35 36#include "dh.h" 37#include "iked.h" 38#include "crypto_api.h" 39 40int dh_init(struct dh_group *); 41int dh_getlen(struct dh_group *); 42int dh_secretlen(struct dh_group *); 43 44/* MODP */ 45int modp_init(struct dh_group *); 46int modp_getlen(struct dh_group *); 47int modp_create_exchange(struct dh_group *, uint8_t *); 48int modp_create_shared(struct dh_group *, uint8_t *, uint8_t *); 49 50/* ECP */ 51int ec_init(struct dh_group *); 52int ec_getlen(struct dh_group *); 53int ec_secretlen(struct dh_group *); 54int ec_create_exchange(struct dh_group *, uint8_t *); 55int ec_create_shared(struct dh_group *, uint8_t *, uint8_t *); 56 57#define EC_POINT2RAW_FULL 0 58#define EC_POINT2RAW_XONLY 1 59int ec_point2raw(struct dh_group *, const EC_POINT *, uint8_t *, size_t, int); 60EC_POINT * 61 ec_raw2point(struct dh_group *, uint8_t *, size_t); 62 63/* curve25519 */ 64int ec25519_init(struct dh_group *); 65int ec25519_getlen(struct dh_group *); 66int ec25519_create_exchange(struct dh_group *, uint8_t *); 67int ec25519_create_shared(struct dh_group *, uint8_t *, uint8_t *); 68 69#define CURVE25519_SIZE 32 /* 256 bits */ 70struct curve25519_key { 71 uint8_t secret[CURVE25519_SIZE]; 72 uint8_t public[CURVE25519_SIZE]; 73}; 74extern int crypto_scalarmult_curve25519(unsigned char a[CURVE25519_SIZE], 75 const unsigned char b[CURVE25519_SIZE], 76 const unsigned char c[CURVE25519_SIZE]) 77 __attribute__((__bounded__(__minbytes__, 1, CURVE25519_SIZE))) 78 __attribute__((__bounded__(__minbytes__, 2, CURVE25519_SIZE))) 79 __attribute__((__bounded__(__minbytes__, 3, CURVE25519_SIZE))); 80 81/* SNTRUP761 with X25519 */ 82int kemsx_init(struct dh_group *); 83int kemsx_getlen(struct dh_group *); 84int kemsx_create_exchange2(struct dh_group *, struct ibuf **, struct ibuf *); 85int kemsx_create_shared2(struct dh_group *, struct ibuf **, struct ibuf *); 86 87struct kemsx_key { 88 uint8_t kemkey[crypto_kem_sntrup761_BYTES]; 89 uint8_t secret[crypto_kem_sntrup761_SECRETKEYBYTES]; 90 uint8_t public[crypto_kem_sntrup761_PUBLICKEYBYTES]; 91 uint8_t initiator; 92}; 93 94const struct group_id ike_groups[] = { 95 { GROUP_MODP, 1, 768, 96 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 97 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 98 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 99 "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF", 100 "02" 101 }, 102 { GROUP_MODP, 2, 1024, 103 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 104 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 105 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 106 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 107 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" 108 "FFFFFFFFFFFFFFFF", 109 "02" 110 }, 111 { GROUP_MODP, 5, 1536, 112 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 113 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 114 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 115 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 116 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" 117 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" 118 "83655D23DCA3AD961C62F356208552BB9ED529077096966D" 119 "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 120 "02" 121 }, 122 { GROUP_MODP, 14, 2048, 123 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 124 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 125 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 126 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 127 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" 128 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" 129 "83655D23DCA3AD961C62F356208552BB9ED529077096966D" 130 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" 131 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" 132 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" 133 "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 134 "02" 135 }, 136 { GROUP_MODP, 15, 3072, 137 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 138 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 139 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 140 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 141 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" 142 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" 143 "83655D23DCA3AD961C62F356208552BB9ED529077096966D" 144 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" 145 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" 146 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" 147 "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" 148 "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" 149 "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" 150 "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" 151 "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" 152 "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF", 153 "02" 154 }, 155 { GROUP_MODP, 16, 4096, 156 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 157 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 158 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 159 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 160 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" 161 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" 162 "83655D23DCA3AD961C62F356208552BB9ED529077096966D" 163 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" 164 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" 165 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" 166 "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" 167 "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" 168 "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" 169 "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" 170 "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" 171 "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" 172 "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" 173 "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" 174 "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" 175 "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" 176 "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" 177 "FFFFFFFFFFFFFFFF", 178 "02" 179 }, 180 { GROUP_MODP, 17, 6144, 181 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 182 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 183 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 184 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 185 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" 186 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" 187 "83655D23DCA3AD961C62F356208552BB9ED529077096966D" 188 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" 189 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" 190 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" 191 "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" 192 "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" 193 "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" 194 "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" 195 "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" 196 "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" 197 "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" 198 "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" 199 "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" 200 "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" 201 "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" 202 "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" 203 "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" 204 "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" 205 "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" 206 "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" 207 "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" 208 "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" 209 "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" 210 "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" 211 "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" 212 "12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF", 213 "02" 214 }, 215 { GROUP_MODP, 18, 8192, 216 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 217 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 218 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 219 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 220 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" 221 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" 222 "83655D23DCA3AD961C62F356208552BB9ED529077096966D" 223 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" 224 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" 225 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" 226 "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" 227 "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" 228 "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" 229 "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" 230 "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" 231 "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" 232 "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" 233 "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" 234 "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" 235 "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" 236 "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" 237 "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" 238 "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" 239 "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" 240 "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" 241 "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" 242 "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" 243 "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" 244 "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" 245 "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" 246 "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" 247 "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" 248 "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" 249 "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" 250 "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" 251 "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" 252 "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" 253 "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" 254 "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" 255 "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" 256 "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" 257 "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" 258 "60C980DD98EDD3DFFFFFFFFFFFFFFFFF", 259 "02" 260 }, 261 { GROUP_ECP, 19, 256, NULL, NULL, NID_X9_62_prime256v1 }, 262 { GROUP_ECP, 20, 384, NULL, NULL, NID_secp384r1 }, 263 { GROUP_ECP, 21, 521, NULL, NULL, NID_secp521r1 }, 264 { GROUP_ECP, 25, 192, NULL, NULL, NID_X9_62_prime192v1 }, 265 { GROUP_ECP, 26, 224, NULL, NULL, NID_secp224r1 }, 266 { GROUP_ECP, 27, 224, NULL, NULL, NID_brainpoolP224r1 }, 267 { GROUP_ECP, 28, 256, NULL, NULL, NID_brainpoolP256r1 }, 268 { GROUP_ECP, 29, 384, NULL, NULL, NID_brainpoolP384r1 }, 269 { GROUP_ECP, 30, 512, NULL, NULL, NID_brainpoolP512r1 }, 270 { GROUP_CURVE25519, 31, CURVE25519_SIZE * 8 }, 271 /* "Private use" extensions */ 272 /* PQC KEM */ 273 { GROUP_SNTRUP761X25519, 1035, 274 (MAXIMUM(crypto_kem_sntrup761_PUBLICKEYBYTES, 275 crypto_kem_sntrup761_CIPHERTEXTBYTES) + 276 CURVE25519_SIZE) * 8 } 277}; 278 279void 280group_init(void) 281{ 282 /* currently not used */ 283 return; 284} 285 286void 287group_free(struct dh_group *group) 288{ 289 if (group == NULL) 290 return; 291 if (group->dh != NULL) 292 DH_free(group->dh); 293 if (group->ec != NULL) 294 EC_KEY_free(group->ec); 295 freezero(group->curve25519, sizeof(struct curve25519_key)); 296 freezero(group->kemsx, sizeof(struct kemsx_key)); 297 group->spec = NULL; 298 free(group); 299} 300 301struct dh_group * 302group_get(uint32_t id) 303{ 304 const struct group_id *p; 305 struct dh_group *group; 306 307 if ((p = group_getid(id)) == NULL) 308 return (NULL); 309 310 if ((group = calloc(1, sizeof(*group))) == NULL) 311 return (NULL); 312 313 group->id = id; 314 group->spec = p; 315 316 switch (p->type) { 317 case GROUP_MODP: 318 group->init = modp_init; 319 group->getlen = modp_getlen; 320 group->exchange = modp_create_exchange; 321 group->shared = modp_create_shared; 322 break; 323 case GROUP_ECP: 324 group->init = ec_init; 325 group->getlen = ec_getlen; 326 group->secretlen = ec_secretlen; 327 group->exchange = ec_create_exchange; 328 group->shared = ec_create_shared; 329 break; 330 case GROUP_CURVE25519: 331 group->init = ec25519_init; 332 group->getlen = ec25519_getlen; 333 group->exchange = ec25519_create_exchange; 334 group->shared = ec25519_create_shared; 335 break; 336 case GROUP_SNTRUP761X25519: 337 group->init = kemsx_init; 338 group->getlen = kemsx_getlen; 339 group->exchange2 = kemsx_create_exchange2; 340 group->shared2 = kemsx_create_shared2; 341 break; 342 default: 343 group_free(group); 344 return (NULL); 345 } 346 347 if (dh_init(group) != 0) { 348 group_free(group); 349 return (NULL); 350 } 351 352 return (group); 353} 354 355const struct group_id * 356group_getid(uint32_t id) 357{ 358 const struct group_id *p = NULL; 359 unsigned int i, items; 360 361 items = sizeof(ike_groups) / sizeof(ike_groups[0]); 362 for (i = 0; i < items; i++) { 363 if (id == ike_groups[i].id) { 364 p = &ike_groups[i]; 365 break; 366 } 367 } 368 return (p); 369} 370 371int 372dh_init(struct dh_group *group) 373{ 374 return (group->init(group)); 375} 376 377int 378dh_getlen(struct dh_group *group) 379{ 380 return (group->getlen(group)); 381} 382 383int 384dh_secretlen(struct dh_group *group) 385{ 386 if (group->secretlen) 387 return (group->secretlen(group)); 388 else 389 return (group->getlen(group)); 390} 391 392int 393dh_create_exchange(struct dh_group *group, struct ibuf **bufp, struct ibuf *iexchange) 394{ 395 struct ibuf *buf; 396 397 *bufp = NULL; 398 if (group->exchange2) 399 return (group->exchange2(group, bufp, iexchange)); 400 buf = ibuf_new(NULL, dh_getlen(group)); 401 if (buf == NULL) 402 return -1; 403 *bufp = buf; 404 return (group->exchange(group, ibuf_data(buf))); 405} 406 407int 408dh_create_shared(struct dh_group *group, struct ibuf **secretp, struct ibuf *exchange) 409{ 410 struct ibuf *buf; 411 412 *secretp = NULL; 413 if (group->shared2) 414 return (group->shared2(group, secretp, exchange)); 415 if (exchange == NULL || 416 (ssize_t)ibuf_size(exchange) != dh_getlen(group)) 417 return -1; 418 buf = ibuf_new(NULL, dh_secretlen(group)); 419 if (buf == NULL) 420 return -1; 421 *secretp = buf; 422 return (group->shared(group, ibuf_data(buf), ibuf_data(exchange))); 423} 424 425int 426modp_init(struct dh_group *group) 427{ 428 BIGNUM *g = NULL, *p = NULL; 429 DH *dh; 430 int ret = -1; 431 432 if ((dh = DH_new()) == NULL) 433 return (-1); 434 435 if (!BN_hex2bn(&p, group->spec->prime) || 436 !BN_hex2bn(&g, group->spec->generator) || 437 DH_set0_pqg(dh, p, NULL, g) == 0) 438 goto done; 439 440 p = g = NULL; 441 group->dh = dh; 442 443 ret = 0; 444 done: 445 BN_clear_free(g); 446 BN_clear_free(p); 447 448 return (ret); 449} 450 451int 452modp_getlen(struct dh_group *group) 453{ 454 if (group->spec == NULL) 455 return (0); 456 return (roundup(group->spec->bits, 8) / 8); 457} 458 459int 460modp_create_exchange(struct dh_group *group, uint8_t *buf) 461{ 462 const BIGNUM *pub; 463 DH *dh = group->dh; 464 int len, ret; 465 466 if (!DH_generate_key(dh)) 467 return (-1); 468 DH_get0_key(group->dh, &pub, NULL); 469 ret = BN_bn2bin(pub, buf); 470 if (!ret) 471 return (-1); 472 473 len = dh_getlen(group); 474 475 /* add zero padding */ 476 if (ret < len) { 477 bcopy(buf, buf + (len - ret), ret); 478 bzero(buf, len - ret); 479 } 480 481 return (0); 482} 483 484int 485modp_create_shared(struct dh_group *group, uint8_t *secret, uint8_t *exchange) 486{ 487 BIGNUM *ex; 488 int len, ret; 489 490 len = dh_getlen(group); 491 492 if ((ex = BN_bin2bn(exchange, len, NULL)) == NULL) 493 return (-1); 494 495 ret = DH_compute_key(secret, ex, group->dh); 496 BN_clear_free(ex); 497 if (ret <= 0) 498 return (-1); 499 500 /* add zero padding */ 501 if (ret < len) { 502 bcopy(secret, secret + (len - ret), ret); 503 bzero(secret, len - ret); 504 } 505 506 return (0); 507} 508 509int 510ec_init(struct dh_group *group) 511{ 512 if ((group->ec = EC_KEY_new_by_curve_name(group->spec->nid)) == NULL) 513 return (-1); 514 if (!EC_KEY_generate_key(group->ec)) 515 return (-1); 516 if (!EC_KEY_check_key(group->ec)) 517 return (-1); 518 return (0); 519} 520 521int 522ec_getlen(struct dh_group *group) 523{ 524 if (group->spec == NULL) 525 return (0); 526 /* NB: Return value will always be even */ 527 return ((roundup(group->spec->bits, 8) * 2) / 8); 528} 529 530/* 531 * Note that the shared secret only includes the x value: 532 * 533 * See RFC 5903, 7. ECP Key Exchange Data Formats: 534 * The Diffie-Hellman shared secret value consists of the x value of the 535 * Diffie-Hellman common value. 536 * See also RFC 5903, 9. Changes from RFC 4753. 537 */ 538int 539ec_secretlen(struct dh_group *group) 540{ 541 return (ec_getlen(group) / 2); 542} 543 544int 545ec_create_exchange(struct dh_group *group, uint8_t *buf) 546{ 547 size_t len; 548 549 len = ec_getlen(group); 550 bzero(buf, len); 551 552 return (ec_point2raw(group, EC_KEY_get0_public_key(group->ec), 553 buf, len, EC_POINT2RAW_FULL)); 554} 555 556int 557ec_create_shared(struct dh_group *group, uint8_t *secret, uint8_t *exchange) 558{ 559 const EC_GROUP *ecgroup = NULL; 560 const BIGNUM *privkey; 561 EC_KEY *exkey = NULL; 562 EC_POINT *exchangep = NULL, *secretp = NULL; 563 int ret = -1; 564 565 if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL || 566 (privkey = EC_KEY_get0_private_key(group->ec)) == NULL) 567 goto done; 568 569 if ((exchangep = 570 ec_raw2point(group, exchange, ec_getlen(group))) == NULL) 571 goto done; 572 573 if ((exkey = EC_KEY_new()) == NULL) 574 goto done; 575 if (!EC_KEY_set_group(exkey, ecgroup)) 576 goto done; 577 if (!EC_KEY_set_public_key(exkey, exchangep)) 578 goto done; 579 580 /* validate exchangep */ 581 if (!EC_KEY_check_key(exkey)) 582 goto done; 583 584 if ((secretp = EC_POINT_new(ecgroup)) == NULL) 585 goto done; 586 587 if (!EC_POINT_mul(ecgroup, secretp, NULL, exchangep, privkey, NULL)) 588 goto done; 589 590 ret = ec_point2raw(group, secretp, secret, ec_secretlen(group), 591 EC_POINT2RAW_XONLY); 592 593 done: 594 if (exkey != NULL) 595 EC_KEY_free(exkey); 596 if (exchangep != NULL) 597 EC_POINT_clear_free(exchangep); 598 if (secretp != NULL) 599 EC_POINT_clear_free(secretp); 600 601 return (ret); 602} 603 604int 605ec_point2raw(struct dh_group *group, const EC_POINT *point, 606 uint8_t *buf, size_t len, int mode) 607{ 608 const EC_GROUP *ecgroup = NULL; 609 BN_CTX *bnctx = NULL; 610 BIGNUM *x = NULL, *y = NULL; 611 int ret = -1; 612 size_t eclen, xlen, ylen; 613 off_t xoff, yoff; 614 615 if ((bnctx = BN_CTX_new()) == NULL) 616 goto done; 617 BN_CTX_start(bnctx); 618 if ((x = BN_CTX_get(bnctx)) == NULL || 619 (y = BN_CTX_get(bnctx)) == NULL) 620 goto done; 621 622 eclen = ec_getlen(group); 623 switch (mode) { 624 case EC_POINT2RAW_XONLY: 625 xlen = eclen / 2; 626 ylen = 0; 627 break; 628 case EC_POINT2RAW_FULL: 629 xlen = ylen = eclen / 2; 630 break; 631 default: 632 goto done; 633 } 634 if (len < xlen + ylen) 635 goto done; 636 637 if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL) 638 goto done; 639 640 if (!EC_POINT_get_affine_coordinates(ecgroup, point, x, y, bnctx)) 641 goto done; 642 643 xoff = xlen - BN_num_bytes(x); 644 bzero(buf, xoff); 645 if (!BN_bn2bin(x, buf + xoff)) 646 goto done; 647 648 if (ylen > 0) { 649 yoff = (ylen - BN_num_bytes(y)) + xlen; 650 bzero(buf + xlen, yoff - xlen); 651 if (!BN_bn2bin(y, buf + yoff)) 652 goto done; 653 } 654 655 ret = 0; 656 done: 657 /* Make sure to erase sensitive data */ 658 if (x != NULL) 659 BN_clear(x); 660 if (y != NULL) 661 BN_clear(y); 662 BN_CTX_end(bnctx); 663 BN_CTX_free(bnctx); 664 665 return (ret); 666} 667 668EC_POINT * 669ec_raw2point(struct dh_group *group, uint8_t *buf, size_t len) 670{ 671 const EC_GROUP *ecgroup = NULL; 672 EC_POINT *point = NULL; 673 BN_CTX *bnctx = NULL; 674 BIGNUM *x = NULL, *y = NULL; 675 int ret = -1; 676 size_t eclen; 677 size_t xlen, ylen; 678 679 if ((bnctx = BN_CTX_new()) == NULL) 680 goto done; 681 BN_CTX_start(bnctx); 682 if ((x = BN_CTX_get(bnctx)) == NULL || 683 (y = BN_CTX_get(bnctx)) == NULL) 684 goto done; 685 686 eclen = ec_getlen(group); 687 if (len < eclen) 688 goto done; 689 xlen = ylen = eclen / 2; 690 if ((x = BN_bin2bn(buf, xlen, x)) == NULL || 691 (y = BN_bin2bn(buf + xlen, ylen, y)) == NULL) 692 goto done; 693 694 if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL) 695 goto done; 696 697 if ((point = EC_POINT_new(ecgroup)) == NULL) 698 goto done; 699 700 if (!EC_POINT_set_affine_coordinates(ecgroup, point, x, y, bnctx)) 701 goto done; 702 703 ret = 0; 704 done: 705 if (ret != 0 && point != NULL) 706 EC_POINT_clear_free(point); 707 /* Make sure to erase sensitive data */ 708 if (x != NULL) 709 BN_clear(x); 710 if (y != NULL) 711 BN_clear(y); 712 BN_CTX_end(bnctx); 713 BN_CTX_free(bnctx); 714 715 return (point); 716} 717 718int 719ec25519_init(struct dh_group *group) 720{ 721 static const uint8_t basepoint[CURVE25519_SIZE] = { 9 }; 722 struct curve25519_key *curve25519; 723 724 if ((curve25519 = calloc(1, sizeof(*curve25519))) == NULL) 725 return (-1); 726 727 group->curve25519 = curve25519; 728 729 arc4random_buf(curve25519->secret, CURVE25519_SIZE); 730 crypto_scalarmult_curve25519(curve25519->public, 731 curve25519->secret, basepoint); 732 733 return (0); 734} 735 736int 737ec25519_getlen(struct dh_group *group) 738{ 739 if (group->spec == NULL) 740 return (0); 741 return (CURVE25519_SIZE); 742} 743 744int 745ec25519_create_exchange(struct dh_group *group, uint8_t *buf) 746{ 747 struct curve25519_key *curve25519 = group->curve25519; 748 749 memcpy(buf, curve25519->public, ec25519_getlen(group)); 750 return (0); 751} 752 753int 754ec25519_create_shared(struct dh_group *group, uint8_t *shared, uint8_t *public) 755{ 756 struct curve25519_key *curve25519 = group->curve25519; 757 758 crypto_scalarmult_curve25519(shared, curve25519->secret, public); 759 return (0); 760} 761 762/* combine sntrup761 with curve25519 */ 763 764int 765kemsx_init(struct dh_group *group) 766{ 767 /* delayed until kemsx_create_exchange2 */ 768 return (0); 769} 770 771int 772kemsx_getlen(struct dh_group *group) 773{ 774 return (0); 775} 776 777int 778kemsx_create_exchange2(struct dh_group *group, struct ibuf **bufp, 779 struct ibuf *iexchange) 780{ 781 struct kemsx_key *kemsx; 782 struct curve25519_key *curve25519; 783 struct ibuf *buf = NULL; 784 u_char *cp, *pk; 785 size_t have, need; 786 787 if (ec25519_init(group) == -1) 788 return (-1); 789 if (group->curve25519 == NULL) 790 return (-1); 791 if ((kemsx = calloc(1, sizeof(*kemsx))) == NULL) 792 return (-1); 793 group->kemsx = kemsx; 794 795 if (iexchange == NULL) { 796 kemsx->initiator = 1; 797 crypto_kem_sntrup761_keypair(kemsx->public, kemsx->secret); 798 /* output */ 799 need = crypto_kem_sntrup761_PUBLICKEYBYTES + 800 CURVE25519_SIZE; 801 buf = ibuf_new(NULL, need); 802 if (buf == NULL) 803 return -1; 804 cp = ibuf_data(buf); 805 memcpy(cp, kemsx->public, 806 crypto_kem_sntrup761_PUBLICKEYBYTES); 807 cp += crypto_kem_sntrup761_PUBLICKEYBYTES; 808 } else { 809 kemsx->initiator = 0; 810 /* input */ 811 have = ibuf_size(iexchange); 812 need = crypto_kem_sntrup761_PUBLICKEYBYTES + 813 CURVE25519_SIZE; 814 if (have != need) 815 return -1; 816 /* output */ 817 need = crypto_kem_sntrup761_CIPHERTEXTBYTES + 818 CURVE25519_SIZE; 819 buf = ibuf_new(NULL, need); 820 if (buf == NULL) 821 return -1; 822 cp = ibuf_data(buf); 823 pk = ibuf_data(iexchange); 824 crypto_kem_sntrup761_enc(cp, kemsx->kemkey, pk); 825 cp += crypto_kem_sntrup761_CIPHERTEXTBYTES; 826 } 827 curve25519 = group->curve25519; 828 memcpy(cp, curve25519->public, CURVE25519_SIZE); 829 *bufp = buf; 830 return (0); 831} 832 833int 834kemsx_create_shared2(struct dh_group *group, struct ibuf **sharedp, 835 struct ibuf *exchange) 836{ 837 struct curve25519_key *curve25519 = group->curve25519; 838 struct kemsx_key *kemsx = group->kemsx; 839 struct ibuf *buf = NULL; 840 EVP_MD_CTX *ctx = NULL; 841 uint8_t *cp; 842 uint8_t shared[CURVE25519_SIZE]; 843 size_t have, need; 844 u_int len; 845 846 *sharedp = NULL; 847 if (kemsx == NULL) 848 return (-1); 849 if (exchange == NULL) 850 return (-1); 851 852 have = ibuf_size(exchange); 853 cp = ibuf_data(exchange); 854 if (kemsx->initiator) { 855 /* input */ 856 need = crypto_kem_sntrup761_CIPHERTEXTBYTES + 857 CURVE25519_SIZE; 858 if (have != need) 859 return (-1); 860 crypto_kem_sntrup761_dec(kemsx->kemkey, cp, kemsx->secret); 861 cp += crypto_kem_sntrup761_CIPHERTEXTBYTES; 862 } else { 863 /* input, should have been checked before */ 864 need = crypto_kem_sntrup761_PUBLICKEYBYTES + 865 CURVE25519_SIZE; 866 if (have != need) 867 return (-1); 868 cp += crypto_kem_sntrup761_PUBLICKEYBYTES; 869 } 870 crypto_scalarmult_curve25519(shared, curve25519->secret, cp); 871 872 /* result is hash of concatenation of KEM key and DH shared secret */ 873 len = SHA512_DIGEST_LENGTH; 874 buf = ibuf_new(NULL, len); 875 if (buf == NULL) 876 return (-1); 877 if ((ctx = EVP_MD_CTX_new()) == NULL || 878 EVP_DigestInit_ex(ctx, EVP_sha512(), NULL) != 1 || 879 EVP_DigestUpdate(ctx, kemsx->kemkey, sizeof(kemsx->kemkey)) != 1 || 880 EVP_DigestUpdate(ctx, shared, sizeof(shared)) != 1 || 881 EVP_DigestFinal_ex(ctx, ibuf_data(buf), &len) != 1) { 882 EVP_MD_CTX_free(ctx); 883 ibuf_free(buf); 884 return (-1); 885 } 886 EVP_MD_CTX_free(ctx); 887 *sharedp = buf; 888 return (0); 889} 890