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