1/* 2 * Elliptic curve Diffie-Hellman 3 * 4 * Copyright The Mbed TLS Contributors 5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6 */ 7 8/* 9 * References: 10 * 11 * SEC1 https://www.secg.org/sec1-v2.pdf 12 * RFC 4492 13 */ 14 15#include "common.h" 16 17#if defined(MBEDTLS_ECDH_C) 18 19#include "mbedtls/ecdh.h" 20#include "mbedtls/platform_util.h" 21#include "mbedtls/error.h" 22 23#include <string.h> 24 25#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 26typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed; 27#endif 28 29static mbedtls_ecp_group_id mbedtls_ecdh_grp_id( 30 const mbedtls_ecdh_context *ctx) 31{ 32#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 33 return ctx->grp.id; 34#else 35 return ctx->grp_id; 36#endif 37} 38 39int mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid) 40{ 41 /* At this time, all groups support ECDH. */ 42 (void) gid; 43 return 1; 44} 45 46#if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) 47/* 48 * Generate public key (restartable version) 49 * 50 * Note: this internal function relies on its caller preserving the value of 51 * the output parameter 'd' across continuation calls. This would not be 52 * acceptable for a public function but is OK here as we control call sites. 53 */ 54static int ecdh_gen_public_restartable(mbedtls_ecp_group *grp, 55 mbedtls_mpi *d, mbedtls_ecp_point *Q, 56 int (*f_rng)(void *, unsigned char *, size_t), 57 void *p_rng, 58 mbedtls_ecp_restart_ctx *rs_ctx) 59{ 60 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 61 62 int restarting = 0; 63#if defined(MBEDTLS_ECP_RESTARTABLE) 64 restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL); 65#endif 66 /* If multiplication is in progress, we already generated a privkey */ 67 if (!restarting) { 68 MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng)); 69 } 70 71 MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G, 72 f_rng, p_rng, rs_ctx)); 73 74cleanup: 75 return ret; 76} 77 78/* 79 * Generate public key 80 */ 81int mbedtls_ecdh_gen_public(mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, 82 int (*f_rng)(void *, unsigned char *, size_t), 83 void *p_rng) 84{ 85 return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL); 86} 87#endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */ 88 89#if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) 90/* 91 * Compute shared secret (SEC1 3.3.1) 92 */ 93static int ecdh_compute_shared_restartable(mbedtls_ecp_group *grp, 94 mbedtls_mpi *z, 95 const mbedtls_ecp_point *Q, const mbedtls_mpi *d, 96 int (*f_rng)(void *, unsigned char *, size_t), 97 void *p_rng, 98 mbedtls_ecp_restart_ctx *rs_ctx) 99{ 100 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 101 mbedtls_ecp_point P; 102 103 mbedtls_ecp_point_init(&P); 104 105 MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &P, d, Q, 106 f_rng, p_rng, rs_ctx)); 107 108 if (mbedtls_ecp_is_zero(&P)) { 109 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 110 goto cleanup; 111 } 112 113 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X)); 114 115cleanup: 116 mbedtls_ecp_point_free(&P); 117 118 return ret; 119} 120 121/* 122 * Compute shared secret (SEC1 3.3.1) 123 */ 124int mbedtls_ecdh_compute_shared(mbedtls_ecp_group *grp, mbedtls_mpi *z, 125 const mbedtls_ecp_point *Q, const mbedtls_mpi *d, 126 int (*f_rng)(void *, unsigned char *, size_t), 127 void *p_rng) 128{ 129 return ecdh_compute_shared_restartable(grp, z, Q, d, 130 f_rng, p_rng, NULL); 131} 132#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ 133 134static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx) 135{ 136 mbedtls_ecp_group_init(&ctx->grp); 137 mbedtls_mpi_init(&ctx->d); 138 mbedtls_ecp_point_init(&ctx->Q); 139 mbedtls_ecp_point_init(&ctx->Qp); 140 mbedtls_mpi_init(&ctx->z); 141 142#if defined(MBEDTLS_ECP_RESTARTABLE) 143 mbedtls_ecp_restart_init(&ctx->rs); 144#endif 145} 146 147mbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx) 148{ 149#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 150 return ctx->MBEDTLS_PRIVATE(grp).id; 151#else 152 return ctx->MBEDTLS_PRIVATE(grp_id); 153#endif 154} 155 156/* 157 * Initialize context 158 */ 159void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx) 160{ 161#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 162 ecdh_init_internal(ctx); 163 mbedtls_ecp_point_init(&ctx->Vi); 164 mbedtls_ecp_point_init(&ctx->Vf); 165 mbedtls_mpi_init(&ctx->_d); 166#else 167 memset(ctx, 0, sizeof(mbedtls_ecdh_context)); 168 169 ctx->var = MBEDTLS_ECDH_VARIANT_NONE; 170#endif 171 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; 172#if defined(MBEDTLS_ECP_RESTARTABLE) 173 ctx->restart_enabled = 0; 174#endif 175} 176 177static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx, 178 mbedtls_ecp_group_id grp_id) 179{ 180 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 181 182 ret = mbedtls_ecp_group_load(&ctx->grp, grp_id); 183 if (ret != 0) { 184 return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; 185 } 186 187 return 0; 188} 189 190/* 191 * Setup context 192 */ 193int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id) 194{ 195#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 196 return ecdh_setup_internal(ctx, grp_id); 197#else 198 switch (grp_id) { 199#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 200 case MBEDTLS_ECP_DP_CURVE25519: 201 ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED; 202 ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST; 203 ctx->grp_id = grp_id; 204 return mbedtls_everest_setup(&ctx->ctx.everest_ecdh, grp_id); 205#endif 206 default: 207 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; 208 ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; 209 ctx->grp_id = grp_id; 210 ecdh_init_internal(&ctx->ctx.mbed_ecdh); 211 return ecdh_setup_internal(&ctx->ctx.mbed_ecdh, grp_id); 212 } 213#endif 214} 215 216static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx) 217{ 218 mbedtls_ecp_group_free(&ctx->grp); 219 mbedtls_mpi_free(&ctx->d); 220 mbedtls_ecp_point_free(&ctx->Q); 221 mbedtls_ecp_point_free(&ctx->Qp); 222 mbedtls_mpi_free(&ctx->z); 223 224#if defined(MBEDTLS_ECP_RESTARTABLE) 225 mbedtls_ecp_restart_free(&ctx->rs); 226#endif 227} 228 229#if defined(MBEDTLS_ECP_RESTARTABLE) 230/* 231 * Enable restartable operations for context 232 */ 233void mbedtls_ecdh_enable_restart(mbedtls_ecdh_context *ctx) 234{ 235 ctx->restart_enabled = 1; 236} 237#endif 238 239/* 240 * Free context 241 */ 242void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx) 243{ 244 if (ctx == NULL) { 245 return; 246 } 247 248#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 249 mbedtls_ecp_point_free(&ctx->Vi); 250 mbedtls_ecp_point_free(&ctx->Vf); 251 mbedtls_mpi_free(&ctx->_d); 252 ecdh_free_internal(ctx); 253#else 254 switch (ctx->var) { 255#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 256 case MBEDTLS_ECDH_VARIANT_EVEREST: 257 mbedtls_everest_free(&ctx->ctx.everest_ecdh); 258 break; 259#endif 260 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 261 ecdh_free_internal(&ctx->ctx.mbed_ecdh); 262 break; 263 default: 264 break; 265 } 266 267 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; 268 ctx->var = MBEDTLS_ECDH_VARIANT_NONE; 269 ctx->grp_id = MBEDTLS_ECP_DP_NONE; 270#endif 271} 272 273static int ecdh_make_params_internal(mbedtls_ecdh_context_mbed *ctx, 274 size_t *olen, int point_format, 275 unsigned char *buf, size_t blen, 276 int (*f_rng)(void *, 277 unsigned char *, 278 size_t), 279 void *p_rng, 280 int restart_enabled) 281{ 282 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 283 size_t grp_len, pt_len; 284#if defined(MBEDTLS_ECP_RESTARTABLE) 285 mbedtls_ecp_restart_ctx *rs_ctx = NULL; 286#endif 287 288 if (ctx->grp.pbits == 0) { 289 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 290 } 291 292#if defined(MBEDTLS_ECP_RESTARTABLE) 293 if (restart_enabled) { 294 rs_ctx = &ctx->rs; 295 } 296#else 297 (void) restart_enabled; 298#endif 299 300 301#if defined(MBEDTLS_ECP_RESTARTABLE) 302 if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q, 303 f_rng, p_rng, rs_ctx)) != 0) { 304 return ret; 305 } 306#else 307 if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q, 308 f_rng, p_rng)) != 0) { 309 return ret; 310 } 311#endif /* MBEDTLS_ECP_RESTARTABLE */ 312 313 if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf, 314 blen)) != 0) { 315 return ret; 316 } 317 318 buf += grp_len; 319 blen -= grp_len; 320 321 if ((ret = mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, 322 &pt_len, buf, blen)) != 0) { 323 return ret; 324 } 325 326 *olen = grp_len + pt_len; 327 return 0; 328} 329 330/* 331 * Setup and write the ServerKeyExchange parameters (RFC 4492) 332 * struct { 333 * ECParameters curve_params; 334 * ECPoint public; 335 * } ServerECDHParams; 336 */ 337int mbedtls_ecdh_make_params(mbedtls_ecdh_context *ctx, size_t *olen, 338 unsigned char *buf, size_t blen, 339 int (*f_rng)(void *, unsigned char *, size_t), 340 void *p_rng) 341{ 342 int restart_enabled = 0; 343#if defined(MBEDTLS_ECP_RESTARTABLE) 344 restart_enabled = ctx->restart_enabled; 345#else 346 (void) restart_enabled; 347#endif 348 349#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 350 return ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen, 351 f_rng, p_rng, restart_enabled); 352#else 353 switch (ctx->var) { 354#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 355 case MBEDTLS_ECDH_VARIANT_EVEREST: 356 return mbedtls_everest_make_params(&ctx->ctx.everest_ecdh, olen, 357 buf, blen, f_rng, p_rng); 358#endif 359 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 360 return ecdh_make_params_internal(&ctx->ctx.mbed_ecdh, olen, 361 ctx->point_format, buf, blen, 362 f_rng, p_rng, 363 restart_enabled); 364 default: 365 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 366 } 367#endif 368} 369 370static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx, 371 const unsigned char **buf, 372 const unsigned char *end) 373{ 374 return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf, 375 (size_t) (end - *buf)); 376} 377 378/* 379 * Read the ServerKeyExchange parameters (RFC 4492) 380 * struct { 381 * ECParameters curve_params; 382 * ECPoint public; 383 * } ServerECDHParams; 384 */ 385int mbedtls_ecdh_read_params(mbedtls_ecdh_context *ctx, 386 const unsigned char **buf, 387 const unsigned char *end) 388{ 389 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 390 mbedtls_ecp_group_id grp_id; 391 if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, (size_t) (end - *buf))) 392 != 0) { 393 return ret; 394 } 395 396 if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0) { 397 return ret; 398 } 399 400#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 401 return ecdh_read_params_internal(ctx, buf, end); 402#else 403 switch (ctx->var) { 404#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 405 case MBEDTLS_ECDH_VARIANT_EVEREST: 406 return mbedtls_everest_read_params(&ctx->ctx.everest_ecdh, 407 buf, end); 408#endif 409 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 410 return ecdh_read_params_internal(&ctx->ctx.mbed_ecdh, 411 buf, end); 412 default: 413 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 414 } 415#endif 416} 417 418static int ecdh_get_params_internal(mbedtls_ecdh_context_mbed *ctx, 419 const mbedtls_ecp_keypair *key, 420 mbedtls_ecdh_side side) 421{ 422 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 423 424 /* If it's not our key, just import the public part as Qp */ 425 if (side == MBEDTLS_ECDH_THEIRS) { 426 return mbedtls_ecp_copy(&ctx->Qp, &key->Q); 427 } 428 429 /* Our key: import public (as Q) and private parts */ 430 if (side != MBEDTLS_ECDH_OURS) { 431 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 432 } 433 434 if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 || 435 (ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) { 436 return ret; 437 } 438 439 return 0; 440} 441 442/* 443 * Get parameters from a keypair 444 */ 445int mbedtls_ecdh_get_params(mbedtls_ecdh_context *ctx, 446 const mbedtls_ecp_keypair *key, 447 mbedtls_ecdh_side side) 448{ 449 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 450 if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) { 451 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 452 } 453 454 if (mbedtls_ecdh_grp_id(ctx) == MBEDTLS_ECP_DP_NONE) { 455 /* This is the first call to get_params(). Set up the context 456 * for use with the group. */ 457 if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0) { 458 return ret; 459 } 460 } else { 461 /* This is not the first call to get_params(). Check that the 462 * current key's group is the same as the context's, which was set 463 * from the first key's group. */ 464 if (mbedtls_ecdh_grp_id(ctx) != key->grp.id) { 465 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 466 } 467 } 468 469#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 470 return ecdh_get_params_internal(ctx, key, side); 471#else 472 switch (ctx->var) { 473#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 474 case MBEDTLS_ECDH_VARIANT_EVEREST: 475 { 476 mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ? 477 MBEDTLS_EVEREST_ECDH_OURS : 478 MBEDTLS_EVEREST_ECDH_THEIRS; 479 return mbedtls_everest_get_params(&ctx->ctx.everest_ecdh, 480 key, s); 481 } 482#endif 483 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 484 return ecdh_get_params_internal(&ctx->ctx.mbed_ecdh, 485 key, side); 486 default: 487 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 488 } 489#endif 490} 491 492static int ecdh_make_public_internal(mbedtls_ecdh_context_mbed *ctx, 493 size_t *olen, int point_format, 494 unsigned char *buf, size_t blen, 495 int (*f_rng)(void *, 496 unsigned char *, 497 size_t), 498 void *p_rng, 499 int restart_enabled) 500{ 501 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 502#if defined(MBEDTLS_ECP_RESTARTABLE) 503 mbedtls_ecp_restart_ctx *rs_ctx = NULL; 504#endif 505 506 if (ctx->grp.pbits == 0) { 507 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 508 } 509 510#if defined(MBEDTLS_ECP_RESTARTABLE) 511 if (restart_enabled) { 512 rs_ctx = &ctx->rs; 513 } 514#else 515 (void) restart_enabled; 516#endif 517 518#if defined(MBEDTLS_ECP_RESTARTABLE) 519 if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q, 520 f_rng, p_rng, rs_ctx)) != 0) { 521 return ret; 522 } 523#else 524 if ((ret = mbedtls_ecdh_gen_public(&ctx->grp, &ctx->d, &ctx->Q, 525 f_rng, p_rng)) != 0) { 526 return ret; 527 } 528#endif /* MBEDTLS_ECP_RESTARTABLE */ 529 530 return mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, olen, 531 buf, blen); 532} 533 534/* 535 * Setup and export the client public value 536 */ 537int mbedtls_ecdh_make_public(mbedtls_ecdh_context *ctx, size_t *olen, 538 unsigned char *buf, size_t blen, 539 int (*f_rng)(void *, unsigned char *, size_t), 540 void *p_rng) 541{ 542 int restart_enabled = 0; 543#if defined(MBEDTLS_ECP_RESTARTABLE) 544 restart_enabled = ctx->restart_enabled; 545#endif 546 547#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 548 return ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen, 549 f_rng, p_rng, restart_enabled); 550#else 551 switch (ctx->var) { 552#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 553 case MBEDTLS_ECDH_VARIANT_EVEREST: 554 return mbedtls_everest_make_public(&ctx->ctx.everest_ecdh, olen, 555 buf, blen, f_rng, p_rng); 556#endif 557 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 558 return ecdh_make_public_internal(&ctx->ctx.mbed_ecdh, olen, 559 ctx->point_format, buf, blen, 560 f_rng, p_rng, 561 restart_enabled); 562 default: 563 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 564 } 565#endif 566} 567 568static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx, 569 const unsigned char *buf, size_t blen) 570{ 571 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 572 const unsigned char *p = buf; 573 574 if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p, 575 blen)) != 0) { 576 return ret; 577 } 578 579 if ((size_t) (p - buf) != blen) { 580 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 581 } 582 583 return 0; 584} 585 586/* 587 * Parse and import the client's public value 588 */ 589int mbedtls_ecdh_read_public(mbedtls_ecdh_context *ctx, 590 const unsigned char *buf, size_t blen) 591{ 592#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 593 return ecdh_read_public_internal(ctx, buf, blen); 594#else 595 switch (ctx->var) { 596#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 597 case MBEDTLS_ECDH_VARIANT_EVEREST: 598 return mbedtls_everest_read_public(&ctx->ctx.everest_ecdh, 599 buf, blen); 600#endif 601 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 602 return ecdh_read_public_internal(&ctx->ctx.mbed_ecdh, 603 buf, blen); 604 default: 605 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 606 } 607#endif 608} 609 610static int ecdh_calc_secret_internal(mbedtls_ecdh_context_mbed *ctx, 611 size_t *olen, unsigned char *buf, 612 size_t blen, 613 int (*f_rng)(void *, 614 unsigned char *, 615 size_t), 616 void *p_rng, 617 int restart_enabled) 618{ 619 int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED; 620#if defined(MBEDTLS_ECP_RESTARTABLE) 621 mbedtls_ecp_restart_ctx *rs_ctx = NULL; 622#endif 623 624 if (ctx == NULL || ctx->grp.pbits == 0) { 625 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 626 } 627 628#if defined(MBEDTLS_ECP_RESTARTABLE) 629 if (restart_enabled) { 630 rs_ctx = &ctx->rs; 631 } 632#else 633 (void) restart_enabled; 634#endif 635 636#if defined(MBEDTLS_ECP_RESTARTABLE) 637 if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp, 638 &ctx->d, f_rng, p_rng, 639 rs_ctx)) != 0) { 640 return ret; 641 } 642#else 643 if ((ret = mbedtls_ecdh_compute_shared(&ctx->grp, &ctx->z, &ctx->Qp, 644 &ctx->d, f_rng, p_rng)) != 0) { 645 return ret; 646 } 647#endif /* MBEDTLS_ECP_RESTARTABLE */ 648 649 if (mbedtls_mpi_size(&ctx->z) > blen) { 650 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 651 } 652 653 *olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0); 654 655 if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) { 656 return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen); 657 } 658 659 return mbedtls_mpi_write_binary(&ctx->z, buf, *olen); 660} 661 662/* 663 * Derive and export the shared secret 664 */ 665int mbedtls_ecdh_calc_secret(mbedtls_ecdh_context *ctx, size_t *olen, 666 unsigned char *buf, size_t blen, 667 int (*f_rng)(void *, unsigned char *, size_t), 668 void *p_rng) 669{ 670 int restart_enabled = 0; 671#if defined(MBEDTLS_ECP_RESTARTABLE) 672 restart_enabled = ctx->restart_enabled; 673#endif 674 675#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 676 return ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng, 677 restart_enabled); 678#else 679 switch (ctx->var) { 680#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 681 case MBEDTLS_ECDH_VARIANT_EVEREST: 682 return mbedtls_everest_calc_secret(&ctx->ctx.everest_ecdh, olen, 683 buf, blen, f_rng, p_rng); 684#endif 685 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 686 return ecdh_calc_secret_internal(&ctx->ctx.mbed_ecdh, olen, buf, 687 blen, f_rng, p_rng, 688 restart_enabled); 689 default: 690 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 691 } 692#endif 693} 694#endif /* MBEDTLS_ECDH_C */ 695