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