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