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