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