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 #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) 53 /* 54 * Generate public key (restartable version) 55 * 56 * Note: this internal function relies on its caller preserving the value of 57 * the output parameter 'd' across continuation calls. This would not be 58 * acceptable for a public function but is OK here as we control call sites. 59 */ 60 static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp, 61 mbedtls_mpi *d, mbedtls_ecp_point *Q, 62 int (*f_rng)(void *, unsigned char *, size_t), 63 void *p_rng, 64 mbedtls_ecp_restart_ctx *rs_ctx ) 65 { 66 int ret; 67 68 /* If multiplication is in progress, we already generated a privkey */ 69 #if defined(MBEDTLS_ECP_RESTARTABLE) 70 if( rs_ctx == NULL || rs_ctx->rsm == NULL ) 71 #endif 72 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); 73 74 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G, 75 f_rng, p_rng, rs_ctx ) ); 76 77 cleanup: 78 return( ret ); 79 } 80 81 /* 82 * Generate public key 83 */ 84 int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, 85 int (*f_rng)(void *, unsigned char *, size_t), 86 void *p_rng ) 87 { 88 ECDH_VALIDATE_RET( grp != NULL ); 89 ECDH_VALIDATE_RET( d != NULL ); 90 ECDH_VALIDATE_RET( Q != NULL ); 91 ECDH_VALIDATE_RET( f_rng != NULL ); 92 return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) ); 93 } 94 #endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */ 95 96 #if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) 97 /* 98 * Compute shared secret (SEC1 3.3.1) 99 */ 100 static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp, 101 mbedtls_mpi *z, 102 const mbedtls_ecp_point *Q, const mbedtls_mpi *d, 103 int (*f_rng)(void *, unsigned char *, size_t), 104 void *p_rng, 105 mbedtls_ecp_restart_ctx *rs_ctx ) 106 { 107 int ret; 108 mbedtls_ecp_point P; 109 110 mbedtls_ecp_point_init( &P ); 111 112 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q, 113 f_rng, p_rng, rs_ctx ) ); 114 115 if( mbedtls_ecp_is_zero( &P ) ) 116 { 117 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 118 goto cleanup; 119 } 120 121 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) ); 122 123 cleanup: 124 mbedtls_ecp_point_free( &P ); 125 126 return( ret ); 127 } 128 129 /* 130 * Compute shared secret (SEC1 3.3.1) 131 */ 132 int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, 133 const mbedtls_ecp_point *Q, const mbedtls_mpi *d, 134 int (*f_rng)(void *, unsigned char *, size_t), 135 void *p_rng ) 136 { 137 ECDH_VALIDATE_RET( grp != NULL ); 138 ECDH_VALIDATE_RET( Q != NULL ); 139 ECDH_VALIDATE_RET( d != NULL ); 140 ECDH_VALIDATE_RET( z != NULL ); 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 ECDH_VALIDATE( ctx != NULL ); 165 166 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 167 ecdh_init_internal( ctx ); 168 mbedtls_ecp_point_init( &ctx->Vi ); 169 mbedtls_ecp_point_init( &ctx->Vf ); 170 mbedtls_mpi_init( &ctx->_d ); 171 #else 172 memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); 173 174 ctx->var = MBEDTLS_ECDH_VARIANT_NONE; 175 #endif 176 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; 177 #if defined(MBEDTLS_ECP_RESTARTABLE) 178 ctx->restart_enabled = 0; 179 #endif 180 } 181 182 static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx, 183 mbedtls_ecp_group_id grp_id ) 184 { 185 int ret; 186 187 ret = mbedtls_ecp_group_load( &ctx->grp, grp_id ); 188 if( ret != 0 ) 189 { 190 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); 191 } 192 193 return( 0 ); 194 } 195 196 /* 197 * Setup context 198 */ 199 int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id ) 200 { 201 ECDH_VALIDATE_RET( ctx != NULL ); 202 203 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 204 return( ecdh_setup_internal( ctx, grp_id ) ); 205 #else 206 switch( grp_id ) 207 { 208 default: 209 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; 210 ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0; 211 ctx->grp_id = grp_id; 212 ecdh_init_internal( &ctx->ctx.mbed_ecdh ); 213 return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) ); 214 } 215 #endif 216 } 217 218 static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx ) 219 { 220 mbedtls_ecp_group_free( &ctx->grp ); 221 mbedtls_mpi_free( &ctx->d ); 222 mbedtls_ecp_point_free( &ctx->Q ); 223 mbedtls_ecp_point_free( &ctx->Qp ); 224 mbedtls_mpi_free( &ctx->z ); 225 226 #if defined(MBEDTLS_ECP_RESTARTABLE) 227 mbedtls_ecp_restart_free( &ctx->rs ); 228 #endif 229 } 230 231 #if defined(MBEDTLS_ECP_RESTARTABLE) 232 /* 233 * Enable restartable operations for context 234 */ 235 void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ) 236 { 237 ECDH_VALIDATE( ctx != NULL ); 238 239 ctx->restart_enabled = 1; 240 } 241 #endif 242 243 /* 244 * Free context 245 */ 246 void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) 247 { 248 if( ctx == NULL ) 249 return; 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 { 259 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 260 ecdh_free_internal( &ctx->ctx.mbed_ecdh ); 261 break; 262 default: 263 break; 264 } 265 266 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; 267 ctx->var = MBEDTLS_ECDH_VARIANT_NONE; 268 ctx->grp_id = MBEDTLS_ECP_DP_NONE; 269 #endif 270 } 271 272 static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx, 273 size_t *olen, int point_format, 274 unsigned char *buf, size_t blen, 275 int (*f_rng)(void *, 276 unsigned char *, 277 size_t), 278 void *p_rng, 279 int restart_enabled ) 280 { 281 int ret; 282 size_t grp_len, pt_len; 283 #if defined(MBEDTLS_ECP_RESTARTABLE) 284 mbedtls_ecp_restart_ctx *rs_ctx = NULL; 285 #endif 286 287 if( ctx->grp.pbits == 0 ) 288 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 289 290 #if defined(MBEDTLS_ECP_RESTARTABLE) 291 if( restart_enabled ) 292 rs_ctx = &ctx->rs; 293 #else 294 (void) restart_enabled; 295 #endif 296 297 298 #if defined(MBEDTLS_ECP_RESTARTABLE) 299 if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, 300 f_rng, p_rng, rs_ctx ) ) != 0 ) 301 return( ret ); 302 #else 303 if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, 304 f_rng, p_rng ) ) != 0 ) 305 return( ret ); 306 #endif /* MBEDTLS_ECP_RESTARTABLE */ 307 308 if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf, 309 blen ) ) != 0 ) 310 return( ret ); 311 312 buf += grp_len; 313 blen -= grp_len; 314 315 if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, 316 &pt_len, buf, blen ) ) != 0 ) 317 return( ret ); 318 319 *olen = grp_len + pt_len; 320 return( 0 ); 321 } 322 323 /* 324 * Setup and write the ServerKeyExhange parameters (RFC 4492) 325 * struct { 326 * ECParameters curve_params; 327 * ECPoint public; 328 * } ServerECDHParams; 329 */ 330 int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, 331 unsigned char *buf, size_t blen, 332 int (*f_rng)(void *, unsigned char *, size_t), 333 void *p_rng ) 334 { 335 int restart_enabled = 0; 336 ECDH_VALIDATE_RET( ctx != NULL ); 337 ECDH_VALIDATE_RET( olen != NULL ); 338 ECDH_VALIDATE_RET( buf != NULL ); 339 ECDH_VALIDATE_RET( f_rng != NULL ); 340 341 #if defined(MBEDTLS_ECP_RESTARTABLE) 342 restart_enabled = ctx->restart_enabled; 343 #else 344 (void) restart_enabled; 345 #endif 346 347 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 348 return( ecdh_make_params_internal( ctx, olen, ctx->point_format, buf, blen, 349 f_rng, p_rng, restart_enabled ) ); 350 #else 351 switch( ctx->var ) 352 { 353 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 354 return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen, 355 ctx->point_format, buf, blen, 356 f_rng, p_rng, 357 restart_enabled ) ); 358 default: 359 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 360 } 361 #endif 362 } 363 364 static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx, 365 const unsigned char **buf, 366 const unsigned char *end ) 367 { 368 return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf, 369 end - *buf ) ); 370 } 371 372 /* 373 * Read the ServerKeyExhange parameters (RFC 4492) 374 * struct { 375 * ECParameters curve_params; 376 * ECPoint public; 377 * } ServerECDHParams; 378 */ 379 int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, 380 const unsigned char **buf, 381 const unsigned char *end ) 382 { 383 int ret; 384 mbedtls_ecp_group_id grp_id; 385 ECDH_VALIDATE_RET( ctx != NULL ); 386 ECDH_VALIDATE_RET( buf != NULL ); 387 ECDH_VALIDATE_RET( *buf != NULL ); 388 ECDH_VALIDATE_RET( end != NULL ); 389 390 if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) ) 391 != 0 ) 392 return( ret ); 393 394 if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 ) 395 return( ret ); 396 397 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 398 return( ecdh_read_params_internal( ctx, buf, end ) ); 399 #else 400 switch( ctx->var ) 401 { 402 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 403 return( ecdh_read_params_internal( &ctx->ctx.mbed_ecdh, 404 buf, end ) ); 405 default: 406 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 407 } 408 #endif 409 } 410 411 static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx, 412 const mbedtls_ecp_keypair *key, 413 mbedtls_ecdh_side side ) 414 { 415 int ret; 416 417 /* If it's not our key, just import the public part as Qp */ 418 if( side == MBEDTLS_ECDH_THEIRS ) 419 return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) ); 420 421 /* Our key: import public (as Q) and private parts */ 422 if( side != MBEDTLS_ECDH_OURS ) 423 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 424 425 if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 || 426 ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 ) 427 return( ret ); 428 429 return( 0 ); 430 } 431 432 /* 433 * Get parameters from a keypair 434 */ 435 int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, 436 const mbedtls_ecp_keypair *key, 437 mbedtls_ecdh_side side ) 438 { 439 int ret; 440 ECDH_VALIDATE_RET( ctx != NULL ); 441 ECDH_VALIDATE_RET( key != NULL ); 442 ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS || 443 side == MBEDTLS_ECDH_THEIRS ); 444 445 if( ( ret = mbedtls_ecdh_setup( ctx, key->grp.id ) ) != 0 ) 446 return( ret ); 447 448 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 449 return( ecdh_get_params_internal( ctx, key, side ) ); 450 #else 451 switch( ctx->var ) 452 { 453 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 454 return( ecdh_get_params_internal( &ctx->ctx.mbed_ecdh, 455 key, side ) ); 456 default: 457 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 458 } 459 #endif 460 } 461 462 static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx, 463 size_t *olen, int point_format, 464 unsigned char *buf, size_t blen, 465 int (*f_rng)(void *, 466 unsigned char *, 467 size_t), 468 void *p_rng, 469 int restart_enabled ) 470 { 471 int ret; 472 #if defined(MBEDTLS_ECP_RESTARTABLE) 473 mbedtls_ecp_restart_ctx *rs_ctx = NULL; 474 #endif 475 476 if( ctx->grp.pbits == 0 ) 477 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 478 479 #if defined(MBEDTLS_ECP_RESTARTABLE) 480 if( restart_enabled ) 481 rs_ctx = &ctx->rs; 482 #else 483 (void) restart_enabled; 484 #endif 485 486 #if defined(MBEDTLS_ECP_RESTARTABLE) 487 if( ( ret = ecdh_gen_public_restartable( &ctx->grp, &ctx->d, &ctx->Q, 488 f_rng, p_rng, rs_ctx ) ) != 0 ) 489 return( ret ); 490 #else 491 if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q, 492 f_rng, p_rng ) ) != 0 ) 493 return( ret ); 494 #endif /* MBEDTLS_ECP_RESTARTABLE */ 495 496 return mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format, olen, 497 buf, blen ); 498 } 499 500 /* 501 * Setup and export the client public value 502 */ 503 int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, 504 unsigned char *buf, size_t blen, 505 int (*f_rng)(void *, unsigned char *, size_t), 506 void *p_rng ) 507 { 508 int restart_enabled = 0; 509 ECDH_VALIDATE_RET( ctx != NULL ); 510 ECDH_VALIDATE_RET( olen != NULL ); 511 ECDH_VALIDATE_RET( buf != NULL ); 512 ECDH_VALIDATE_RET( f_rng != NULL ); 513 514 #if defined(MBEDTLS_ECP_RESTARTABLE) 515 restart_enabled = ctx->restart_enabled; 516 #endif 517 518 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 519 return( ecdh_make_public_internal( ctx, olen, ctx->point_format, buf, blen, 520 f_rng, p_rng, restart_enabled ) ); 521 #else 522 switch( ctx->var ) 523 { 524 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 525 return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen, 526 ctx->point_format, buf, blen, 527 f_rng, p_rng, 528 restart_enabled ) ); 529 default: 530 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 531 } 532 #endif 533 } 534 535 static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx, 536 const unsigned char *buf, size_t blen ) 537 { 538 int ret; 539 const unsigned char *p = buf; 540 541 if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p, 542 blen ) ) != 0 ) 543 return( ret ); 544 545 if( (size_t)( p - buf ) != blen ) 546 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 547 548 return( 0 ); 549 } 550 551 /* 552 * Parse and import the client's public value 553 */ 554 int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, 555 const unsigned char *buf, size_t blen ) 556 { 557 ECDH_VALIDATE_RET( ctx != NULL ); 558 ECDH_VALIDATE_RET( buf != NULL ); 559 560 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 561 return( ecdh_read_public_internal( ctx, buf, blen ) ); 562 #else 563 switch( ctx->var ) 564 { 565 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 566 return( ecdh_read_public_internal( &ctx->ctx.mbed_ecdh, 567 buf, blen ) ); 568 default: 569 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 570 } 571 #endif 572 } 573 574 static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx, 575 size_t *olen, unsigned char *buf, 576 size_t blen, 577 int (*f_rng)(void *, 578 unsigned char *, 579 size_t), 580 void *p_rng, 581 int restart_enabled ) 582 { 583 int ret; 584 #if defined(MBEDTLS_ECP_RESTARTABLE) 585 mbedtls_ecp_restart_ctx *rs_ctx = NULL; 586 #endif 587 588 if( ctx == NULL || ctx->grp.pbits == 0 ) 589 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 590 591 #if defined(MBEDTLS_ECP_RESTARTABLE) 592 if( restart_enabled ) 593 rs_ctx = &ctx->rs; 594 #else 595 (void) restart_enabled; 596 #endif 597 598 #if defined(MBEDTLS_ECP_RESTARTABLE) 599 if( ( ret = ecdh_compute_shared_restartable( &ctx->grp, &ctx->z, &ctx->Qp, 600 &ctx->d, f_rng, p_rng, 601 rs_ctx ) ) != 0 ) 602 { 603 return( ret ); 604 } 605 #else 606 if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp, 607 &ctx->d, f_rng, p_rng ) ) != 0 ) 608 { 609 return( ret ); 610 } 611 #endif /* MBEDTLS_ECP_RESTARTABLE */ 612 613 if( mbedtls_mpi_size( &ctx->z ) > blen ) 614 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 615 616 *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 ); 617 return mbedtls_mpi_write_binary( &ctx->z, buf, *olen ); 618 } 619 620 /* 621 * Derive and export the shared secret 622 */ 623 int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, 624 unsigned char *buf, size_t blen, 625 int (*f_rng)(void *, unsigned char *, size_t), 626 void *p_rng ) 627 { 628 int restart_enabled = 0; 629 ECDH_VALIDATE_RET( ctx != NULL ); 630 ECDH_VALIDATE_RET( olen != NULL ); 631 ECDH_VALIDATE_RET( buf != NULL ); 632 633 #if defined(MBEDTLS_ECP_RESTARTABLE) 634 restart_enabled = ctx->restart_enabled; 635 #endif 636 637 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 638 return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng, 639 restart_enabled ) ); 640 #else 641 switch( ctx->var ) 642 { 643 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0: 644 return( ecdh_calc_secret_internal( &ctx->ctx.mbed_ecdh, olen, buf, 645 blen, f_rng, p_rng, 646 restart_enabled ) ); 647 default: 648 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 649 } 650 #endif 651 } 652 653 #endif /* MBEDTLS_ECDH_C */ 654