dh.c revision 1.25
1/* $OpenBSD: dh.c,v 1.25 2022/01/14 09:19:19 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 EC_KEY_free(group->ec); 425 return (-1); 426 } 427 return (0); 428} 429 430int 431ec_getlen(struct group *group) 432{ 433 if (group->spec == NULL) 434 return (0); 435 /* NB: Return value will always be even */ 436 return ((roundup(group->spec->bits, 8) * 2) / 8); 437} 438 439/* 440 * Note that the shared secret only includes the x value: 441 * 442 * See RFC 5903, 7. ECP Key Exchange Data Formats: 443 * The Diffie-Hellman shared secret value consists of the x value of the 444 * Diffie-Hellman common value. 445 * See also RFC 5903, 9. Changes from RFC 4753. 446 */ 447int 448ec_secretlen(struct group *group) 449{ 450 return (ec_getlen(group) / 2); 451} 452 453int 454ec_create_exchange(struct group *group, u_int8_t *buf) 455{ 456 size_t len; 457 458 len = ec_getlen(group); 459 bzero(buf, len); 460 461 return (ec_point2raw(group, EC_KEY_get0_public_key(group->ec), 462 buf, len, EC_POINT2RAW_FULL)); 463} 464 465int 466ec_create_shared(struct group *group, u_int8_t *secret, u_int8_t *exchange) 467{ 468 const EC_GROUP *ecgroup = NULL; 469 const BIGNUM *privkey; 470 EC_KEY *exkey = NULL; 471 EC_POINT *exchangep = NULL, *secretp = NULL; 472 int ret = -1; 473 474 if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL || 475 (privkey = EC_KEY_get0_private_key(group->ec)) == NULL) 476 goto done; 477 478 if ((exchangep = 479 ec_raw2point(group, exchange, ec_getlen(group))) == NULL) 480 goto done; 481 482 if ((exkey = EC_KEY_new()) == NULL) 483 goto done; 484 if (!EC_KEY_set_group(exkey, ecgroup)) 485 goto done; 486 if (!EC_KEY_set_public_key(exkey, exchangep)) 487 goto done; 488 489 /* validate exchangep */ 490 if (!EC_KEY_check_key(exkey)) 491 goto done; 492 493 if ((secretp = EC_POINT_new(ecgroup)) == NULL) 494 goto done; 495 496 if (!EC_POINT_mul(ecgroup, secretp, NULL, exchangep, privkey, NULL)) 497 goto done; 498 499 ret = ec_point2raw(group, secretp, secret, ec_secretlen(group), 500 EC_POINT2RAW_XONLY); 501 502 done: 503 if (exkey != NULL) 504 EC_KEY_free(exkey); 505 if (exchangep != NULL) 506 EC_POINT_clear_free(exchangep); 507 if (secretp != NULL) 508 EC_POINT_clear_free(secretp); 509 510 return (ret); 511} 512 513int 514ec_point2raw(struct group *group, const EC_POINT *point, 515 u_int8_t *buf, size_t len, int mode) 516{ 517 const EC_GROUP *ecgroup = NULL; 518 BN_CTX *bnctx = NULL; 519 BIGNUM *x = NULL, *y = NULL; 520 int ret = -1; 521 size_t eclen, xlen, ylen; 522 off_t xoff, yoff; 523 524 if ((bnctx = BN_CTX_new()) == NULL) 525 goto done; 526 BN_CTX_start(bnctx); 527 if ((x = BN_CTX_get(bnctx)) == NULL || 528 (y = BN_CTX_get(bnctx)) == NULL) 529 goto done; 530 531 eclen = ec_getlen(group); 532 switch (mode) { 533 case EC_POINT2RAW_XONLY: 534 xlen = eclen / 2; 535 ylen = 0; 536 break; 537 case EC_POINT2RAW_FULL: 538 xlen = ylen = eclen / 2; 539 break; 540 default: 541 goto done; 542 } 543 if (len < xlen + ylen) 544 goto done; 545 546 if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL) 547 goto done; 548 549 if (!EC_POINT_get_affine_coordinates(ecgroup, point, x, y, bnctx)) 550 goto done; 551 552 xoff = xlen - BN_num_bytes(x); 553 bzero(buf, xoff); 554 if (!BN_bn2bin(x, buf + xoff)) 555 goto done; 556 557 if (ylen > 0) { 558 yoff = (ylen - BN_num_bytes(y)) + xlen; 559 bzero(buf + xlen, yoff - xlen); 560 if (!BN_bn2bin(y, buf + yoff)) 561 goto done; 562 } 563 564 ret = 0; 565 done: 566 /* Make sure to erase sensitive data */ 567 if (x != NULL) 568 BN_clear(x); 569 if (y != NULL) 570 BN_clear(y); 571 BN_CTX_end(bnctx); 572 BN_CTX_free(bnctx); 573 574 return (ret); 575} 576 577EC_POINT * 578ec_raw2point(struct group *group, u_int8_t *buf, size_t len) 579{ 580 const EC_GROUP *ecgroup = NULL; 581 EC_POINT *point = NULL; 582 BN_CTX *bnctx = NULL; 583 BIGNUM *x = NULL, *y = NULL; 584 int ret = -1; 585 size_t eclen; 586 size_t xlen, ylen; 587 588 if ((bnctx = BN_CTX_new()) == NULL) 589 goto done; 590 BN_CTX_start(bnctx); 591 if ((x = BN_CTX_get(bnctx)) == NULL || 592 (y = BN_CTX_get(bnctx)) == NULL) 593 goto done; 594 595 eclen = ec_getlen(group); 596 if (len < eclen) 597 goto done; 598 xlen = ylen = eclen / 2; 599 if ((x = BN_bin2bn(buf, xlen, x)) == NULL || 600 (y = BN_bin2bn(buf + xlen, ylen, y)) == NULL) 601 goto done; 602 603 if ((ecgroup = EC_KEY_get0_group(group->ec)) == NULL) 604 goto done; 605 606 if ((point = EC_POINT_new(ecgroup)) == NULL) 607 goto done; 608 609 if (!EC_POINT_set_affine_coordinates(ecgroup, point, x, y, bnctx)) 610 goto done; 611 612 ret = 0; 613 done: 614 if (ret != 0 && point != NULL) 615 EC_POINT_clear_free(point); 616 /* Make sure to erase sensitive data */ 617 if (x != NULL) 618 BN_clear(x); 619 if (y != NULL) 620 BN_clear(y); 621 BN_CTX_end(bnctx); 622 BN_CTX_free(bnctx); 623 624 return (point); 625} 626