1/* $OpenBSD: dh.c,v 1.27 2023/03/31 07:28:46 tb 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 <string.h> 20 21#include <openssl/obj_mac.h> 22#include <openssl/dh.h> 23#include <openssl/ec.h> 24#include <openssl/ecdh.h> 25#include <openssl/bn.h> 26 27#include "dh.h" 28 29#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) 30 31int dh_init(struct group *); 32 33int modp_init(struct group *); 34int modp_getlen(struct group *); 35int modp_create_exchange(struct group *, u_int8_t *); 36int modp_create_shared(struct group *, u_int8_t *, u_int8_t *); 37 38int ec_init(struct group *); 39int ec_getlen(struct group *); 40int ec_secretlen(struct group *); 41int ec_create_exchange(struct group *, u_int8_t *); 42int ec_create_shared(struct group *, u_int8_t *, u_int8_t *); 43 44#define EC_POINT2RAW_FULL 0 45#define EC_POINT2RAW_XONLY 1 46int ec_point2raw(struct group *, const EC_POINT *, uint8_t *, size_t, int); 47EC_POINT * 48 ec_raw2point(struct group *, u_int8_t *, size_t); 49 50struct group_id ike_groups[] = { 51 { GROUP_MODP, 1, 768, 52 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 53 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 54 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 55 "E485B576625E7EC6F44C42E9A63A3620FFFFFFFFFFFFFFFF", 56 "02" 57 }, 58 { GROUP_MODP, 2, 1024, 59 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 60 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 61 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 62 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 63 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381" 64 "FFFFFFFFFFFFFFFF", 65 "02" 66 }, 67#ifndef OPENSSL_NO_EC2M 68 { GROUP_EC2N, 3, 155, NULL, NULL, NID_ipsec3 }, 69 { GROUP_EC2N, 4, 185, NULL, NULL, NID_ipsec4 }, 70#endif 71 { GROUP_MODP, 5, 1536, 72 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 73 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 74 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 75 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 76 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" 77 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" 78 "83655D23DCA3AD961C62F356208552BB9ED529077096966D" 79 "670C354E4ABC9804F1746C08CA237327FFFFFFFFFFFFFFFF", 80 "02" 81 }, 82 { GROUP_MODP, 14, 2048, 83 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 84 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 85 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 86 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 87 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" 88 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" 89 "83655D23DCA3AD961C62F356208552BB9ED529077096966D" 90 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" 91 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" 92 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" 93 "15728E5A8AACAA68FFFFFFFFFFFFFFFF", 94 "02" 95 }, 96 { GROUP_MODP, 15, 3072, 97 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 98 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 99 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 100 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 101 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" 102 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" 103 "83655D23DCA3AD961C62F356208552BB9ED529077096966D" 104 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" 105 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" 106 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" 107 "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" 108 "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" 109 "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" 110 "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" 111 "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" 112 "43DB5BFCE0FD108E4B82D120A93AD2CAFFFFFFFFFFFFFFFF", 113 "02" 114 }, 115 { GROUP_MODP, 16, 4096, 116 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 117 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 118 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 119 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 120 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" 121 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" 122 "83655D23DCA3AD961C62F356208552BB9ED529077096966D" 123 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" 124 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" 125 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" 126 "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" 127 "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" 128 "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" 129 "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" 130 "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" 131 "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" 132 "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" 133 "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" 134 "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" 135 "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" 136 "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934063199" 137 "FFFFFFFFFFFFFFFF", 138 "02" 139 }, 140 { GROUP_MODP, 17, 6144, 141 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 142 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 143 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 144 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 145 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" 146 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" 147 "83655D23DCA3AD961C62F356208552BB9ED529077096966D" 148 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" 149 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" 150 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" 151 "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" 152 "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" 153 "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" 154 "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" 155 "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" 156 "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" 157 "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" 158 "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" 159 "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" 160 "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" 161 "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" 162 "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" 163 "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" 164 "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" 165 "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" 166 "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" 167 "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" 168 "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" 169 "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" 170 "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" 171 "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" 172 "12BF2D5B0B7474D6E694F91E6DCC4024FFFFFFFFFFFFFFFF", 173 "02" 174 }, 175 { GROUP_MODP, 18, 8192, 176 "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD1" 177 "29024E088A67CC74020BBEA63B139B22514A08798E3404DD" 178 "EF9519B3CD3A431B302B0A6DF25F14374FE1356D6D51C245" 179 "E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED" 180 "EE386BFB5A899FA5AE9F24117C4B1FE649286651ECE45B3D" 181 "C2007CB8A163BF0598DA48361C55D39A69163FA8FD24CF5F" 182 "83655D23DCA3AD961C62F356208552BB9ED529077096966D" 183 "670C354E4ABC9804F1746C08CA18217C32905E462E36CE3B" 184 "E39E772C180E86039B2783A2EC07A28FB5C55DF06F4C52C9" 185 "DE2BCBF6955817183995497CEA956AE515D2261898FA0510" 186 "15728E5A8AAAC42DAD33170D04507A33A85521ABDF1CBA64" 187 "ECFB850458DBEF0A8AEA71575D060C7DB3970F85A6E1E4C7" 188 "ABF5AE8CDB0933D71E8C94E04A25619DCEE3D2261AD2EE6B" 189 "F12FFA06D98A0864D87602733EC86A64521F2B18177B200C" 190 "BBE117577A615D6C770988C0BAD946E208E24FA074E5AB31" 191 "43DB5BFCE0FD108E4B82D120A92108011A723C12A787E6D7" 192 "88719A10BDBA5B2699C327186AF4E23C1A946834B6150BDA" 193 "2583E9CA2AD44CE8DBBBC2DB04DE8EF92E8EFC141FBECAA6" 194 "287C59474E6BC05D99B2964FA090C3A2233BA186515BE7ED" 195 "1F612970CEE2D7AFB81BDD762170481CD0069127D5B05AA9" 196 "93B4EA988D8FDDC186FFB7DC90A6C08F4DF435C934028492" 197 "36C3FAB4D27C7026C1D4DCB2602646DEC9751E763DBA37BD" 198 "F8FF9406AD9E530EE5DB382F413001AEB06A53ED9027D831" 199 "179727B0865A8918DA3EDBEBCF9B14ED44CE6CBACED4BB1B" 200 "DB7F1447E6CC254B332051512BD7AF426FB8F401378CD2BF" 201 "5983CA01C64B92ECF032EA15D1721D03F482D7CE6E74FEF6" 202 "D55E702F46980C82B5A84031900B1C9E59E7C97FBEC7E8F3" 203 "23A97A7E36CC88BE0F1D45B7FF585AC54BD407B22B4154AA" 204 "CC8F6D7EBF48E1D814CC5ED20F8037E0A79715EEF29BE328" 205 "06A1D58BB7C5DA76F550AA3D8A1FBFF0EB19CCB1A313D55C" 206 "DA56C9EC2EF29632387FE8D76E3C0468043E8F663F4860EE" 207 "12BF2D5B0B7474D6E694F91E6DBE115974A3926F12FEE5E4" 208 "38777CB6A932DF8CD8BEC4D073B931BA3BC832B68D9DD300" 209 "741FA7BF8AFC47ED2576F6936BA424663AAB639C5AE4F568" 210 "3423B4742BF1C978238F16CBE39D652DE3FDB8BEFC848AD9" 211 "22222E04A4037C0713EB57A81A23F0C73473FC646CEA306B" 212 "4BCBC8862F8385DDFA9D4B7FA2C087E879683303ED5BDD3A" 213 "062B3CF5B3A278A66D2A13F83F44F82DDF310EE074AB6A36" 214 "4597E899A0255DC164F31CC50846851DF9AB48195DED7EA1" 215 "B1D510BD7EE74D73FAF36BC31ECFA268359046F4EB879F92" 216 "4009438B481C6CD7889A002ED5EE382BC9190DA6FC026E47" 217 "9558E4475677E9AA9E3050E2765694DFC81F56E880B96E71" 218 "60C980DD98EDD3DFFFFFFFFFFFFFFFFF", 219 "02" 220 }, 221 { GROUP_ECP, 19, 256, NULL, NULL, NID_X9_62_prime256v1 }, 222 { GROUP_ECP, 20, 384, NULL, NULL, NID_secp384r1 }, 223 { GROUP_ECP, 21, 521, NULL, NULL, NID_secp521r1 }, 224 { GROUP_ECP, 25, 192, NULL, NULL, NID_X9_62_prime192v1 }, 225 { GROUP_ECP, 26, 224, NULL, NULL, NID_secp224r1 }, 226 { GROUP_ECP, 27, 224, NULL, NULL, NID_brainpoolP224r1 }, 227 { GROUP_ECP, 28, 256, NULL, NULL, NID_brainpoolP256r1 }, 228 { GROUP_ECP, 29, 384, NULL, NULL, NID_brainpoolP384r1 }, 229 { GROUP_ECP, 30, 512, NULL, NULL, NID_brainpoolP512r1 } 230}; 231 232void 233group_init(void) 234{ 235 /* currently not used */ 236 return; 237} 238 239void 240group_free(struct group *group) 241{ 242 if (group == NULL) 243 return; 244 if (group->dh != NULL) 245 DH_free(group->dh); 246 if (group->ec != NULL) 247 EC_KEY_free(group->ec); 248 group->spec = NULL; 249 free(group); 250} 251 252struct group * 253group_get(u_int32_t id) 254{ 255 struct group_id *p = NULL; 256 struct group *group; 257 u_int i, items; 258 259 items = sizeof(ike_groups) / sizeof(ike_groups[0]); 260 for (i = 0; i < items; i++) { 261 if (id == ike_groups[i].id) { 262 p = &ike_groups[i]; 263 break; 264 } 265 } 266 if (p == NULL) 267 return (NULL); 268 269 if ((group = calloc(1, sizeof(*group))) == NULL) 270 return (NULL); 271 272 group->id = id; 273 group->spec = p; 274 275 switch (p->type) { 276 case GROUP_MODP: 277 group->init = modp_init; 278 group->getlen = modp_getlen; 279 group->exchange = modp_create_exchange; 280 group->shared = modp_create_shared; 281 break; 282#ifndef OPENSSL_NO_EC2M 283 case GROUP_EC2N: 284#endif 285 case GROUP_ECP: 286 group->init = ec_init; 287 group->getlen = ec_getlen; 288 group->secretlen = ec_secretlen; 289 group->exchange = ec_create_exchange; 290 group->shared = ec_create_shared; 291 break; 292 default: 293 group_free(group); 294 return (NULL); 295 } 296 297 if (dh_init(group) != 0) { 298 group_free(group); 299 return (NULL); 300 } 301 302 return (group); 303} 304 305int 306dh_init(struct group *group) 307{ 308 return (group->init(group)); 309} 310 311int 312dh_getlen(struct group *group) 313{ 314 return (group->getlen(group)); 315} 316 317int 318dh_secretlen(struct group *group) 319{ 320 if (group->secretlen) 321 return (group->secretlen(group)); 322 else 323 return (group->getlen(group)); 324} 325 326int 327dh_create_exchange(struct group *group, u_int8_t *buf) 328{ 329 return (group->exchange(group, buf)); 330} 331 332int 333dh_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange) 334{ 335 return (group->shared(group, secret, exchange)); 336} 337 338int 339modp_init(struct group *group) 340{ 341 DH *dh; 342 BIGNUM *p = NULL, *g = NULL; 343 344 if ((dh = DH_new()) == NULL) 345 return (-1); 346 group->dh = dh; 347 348 if (!BN_hex2bn(&p, group->spec->prime) || 349 !BN_hex2bn(&g, group->spec->generator)) { 350 BN_free(p); 351 BN_free(g); 352 return (-1); 353 } 354 355 if (!DH_set0_pqg(dh, p, NULL, g)) { 356 BN_free(p); 357 BN_free(g); 358 return (-1); 359 } 360 361 return (0); 362} 363 364int 365modp_getlen(struct group *group) 366{ 367 if (group->spec == NULL) 368 return (0); 369 return (roundup(group->spec->bits, 8) / 8); 370} 371 372int 373modp_create_exchange(struct group *group, u_int8_t *buf) 374{ 375 DH *dh = group->dh; 376 int len, ret; 377 378 if (!DH_generate_key(dh)) 379 return (-1); 380 ret = BN_bn2bin(DH_get0_pub_key(dh), buf); 381 if (!ret) 382 return (-1); 383 384 len = dh_getlen(group); 385 386 /* add zero padding */ 387 if (ret < len) { 388 bcopy(buf, buf + (len - ret), ret); 389 bzero(buf, len - ret); 390 } 391 392 return (0); 393} 394 395int 396modp_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange) 397{ 398 BIGNUM *ex; 399 int len, ret; 400 401 len = dh_getlen(group); 402 403 if ((ex = BN_bin2bn(exchange, len, NULL)) == NULL) 404 return (-1); 405 406 ret = DH_compute_key(secret, ex, group->dh); 407 BN_clear_free(ex); 408 if (ret <= 0) 409 return (-1); 410 411 /* add zero padding */ 412 if (ret < len) { 413 bcopy(secret, secret + (len - ret), ret); 414 bzero(secret, len - ret); 415 } 416 417 return (0); 418} 419 420int 421ec_init(struct group *group) 422{ 423 if ((group->ec = EC_KEY_new_by_curve_name(group->spec->nid)) == NULL) 424 return (-1); 425 if (!EC_KEY_generate_key(group->ec)) 426 return (-1); 427 if (!EC_KEY_check_key(group->ec)) 428 return (-1); 429 return (0); 430} 431 432int 433ec_getlen(struct group *group) 434{ 435 if (group->spec == NULL) 436 return (0); 437 /* NB: Return value will always be even */ 438 return ((roundup(group->spec->bits, 8) * 2) / 8); 439} 440 441/* 442 * Note that the shared secret only includes the x value: 443 * 444 * See RFC 5903, 7. ECP Key Exchange Data Formats: 445 * The Diffie-Hellman shared secret value consists of the x value of the 446 * Diffie-Hellman common value. 447 * See also RFC 5903, 9. Changes from RFC 4753. 448 */ 449int 450ec_secretlen(struct group *group) 451{ 452 return (ec_getlen(group) / 2); 453} 454 455int 456ec_create_exchange(struct group *group, u_int8_t *buf) 457{ 458 size_t len; 459 460 len = ec_getlen(group); 461 bzero(buf, len); 462 463 return (ec_point2raw(group, EC_KEY_get0_public_key(group->ec), 464 buf, len, EC_POINT2RAW_FULL)); 465} 466 467int 468ec_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange) 469{ 470 const EC_GROUP *ecgroup = NULL; 471 const BIGNUM *privkey; 472 EC_KEY *exkey = NULL; 473 EC_POINT *exchangep = NULL, *secretp = NULL; 474 int ret = -1; 475 476 if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL || 477 (privkey = EC_KEY_get0_private_key(group->ec)) == NULL) 478 goto done; 479 480 if ((exchangep = 481 ec_raw2point(group, exchange, ec_getlen(group))) == NULL) 482 goto done; 483 484 if ((exkey = EC_KEY_new()) == NULL) 485 goto done; 486 if (!EC_KEY_set_group(exkey, ecgroup)) 487 goto done; 488 if (!EC_KEY_set_public_key(exkey, exchangep)) 489 goto done; 490 491 /* validate exchangep */ 492 if (!EC_KEY_check_key(exkey)) 493 goto done; 494 495 if ((secretp = EC_POINT_new(ecgroup)) == NULL) 496 goto done; 497 498 if (!EC_POINT_mul(ecgroup, secretp, NULL, exchangep, privkey, NULL)) 499 goto done; 500 501 ret = ec_point2raw(group, secretp, secret, ec_secretlen(group), 502 EC_POINT2RAW_XONLY); 503 504 done: 505 if (exkey != NULL) 506 EC_KEY_free(exkey); 507 if (exchangep != NULL) 508 EC_POINT_clear_free(exchangep); 509 if (secretp != NULL) 510 EC_POINT_clear_free(secretp); 511 512 return (ret); 513} 514 515int 516ec_point2raw(struct group *group, const EC_POINT *point, 517 u_int8_t *buf, size_t len, int mode) 518{ 519 const EC_GROUP *ecgroup = NULL; 520 BN_CTX *bnctx = NULL; 521 BIGNUM *x = NULL, *y = NULL; 522 int ret = -1; 523 size_t eclen, xlen, ylen; 524 off_t xoff, yoff; 525 526 if ((bnctx = BN_CTX_new()) == NULL) 527 goto done; 528 BN_CTX_start(bnctx); 529 if ((x = BN_CTX_get(bnctx)) == NULL || 530 (y = BN_CTX_get(bnctx)) == NULL) 531 goto done; 532 533 eclen = ec_getlen(group); 534 switch (mode) { 535 case EC_POINT2RAW_XONLY: 536 xlen = eclen / 2; 537 ylen = 0; 538 break; 539 case EC_POINT2RAW_FULL: 540 xlen = ylen = eclen / 2; 541 break; 542 default: 543 goto done; 544 } 545 if (len < xlen + ylen) 546 goto done; 547 548 if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL) 549 goto done; 550 551 if (!EC_POINT_get_affine_coordinates(ecgroup, point, x, y, bnctx)) 552 goto done; 553 554 xoff = xlen - BN_num_bytes(x); 555 bzero(buf, xoff); 556 if (!BN_bn2bin(x, buf + xoff)) 557 goto done; 558 559 if (ylen > 0) { 560 yoff = (ylen - BN_num_bytes(y)) + xlen; 561 bzero(buf + xlen, yoff - xlen); 562 if (!BN_bn2bin(y, buf + yoff)) 563 goto done; 564 } 565 566 ret = 0; 567 done: 568 /* Make sure to erase sensitive data */ 569 if (x != NULL) 570 BN_clear(x); 571 if (y != NULL) 572 BN_clear(y); 573 BN_CTX_end(bnctx); 574 BN_CTX_free(bnctx); 575 576 return (ret); 577} 578 579EC_POINT * 580ec_raw2point(struct group *group, u_int8_t *buf, size_t len) 581{ 582 const EC_GROUP *ecgroup = NULL; 583 EC_POINT *point = NULL; 584 BN_CTX *bnctx = NULL; 585 BIGNUM *x = NULL, *y = NULL; 586 int ret = -1; 587 size_t eclen; 588 size_t xlen, ylen; 589 590 if ((bnctx = BN_CTX_new()) == NULL) 591 goto done; 592 BN_CTX_start(bnctx); 593 if ((x = BN_CTX_get(bnctx)) == NULL || 594 (y = BN_CTX_get(bnctx)) == NULL) 595 goto done; 596 597 eclen = ec_getlen(group); 598 if (len < eclen) 599 goto done; 600 xlen = ylen = eclen / 2; 601 if ((x = BN_bin2bn(buf, xlen, x)) == NULL || 602 (y = BN_bin2bn(buf + xlen, ylen, y)) == NULL) 603 goto done; 604 605 if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL) 606 goto done; 607 608 if ((point = EC_POINT_new(ecgroup)) == NULL) 609 goto done; 610 611 if (!EC_POINT_set_affine_coordinates(ecgroup, point, x, y, bnctx)) 612 goto done; 613 614 ret = 0; 615 done: 616 if (ret != 0 && point != NULL) 617 EC_POINT_clear_free(point); 618 /* Make sure to erase sensitive data */ 619 if (x != NULL) 620 BN_clear(x); 621 if (y != NULL) 622 BN_clear(y); 623 BN_CTX_end(bnctx); 624 BN_CTX_free(bnctx); 625 626 return (point); 627} 628