Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
ecdh.c
00001 /* 00002 * Elliptic curve Diffie-Hellman 00003 * 00004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 00005 * SPDX-License-Identifier: Apache-2.0 00006 * 00007 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00008 * not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00015 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * See the License for the specific language governing permissions and 00017 * limitations under the License. 00018 * 00019 * This file is part of mbed TLS (https://tls.mbed.org) 00020 */ 00021 00022 /* 00023 * References: 00024 * 00025 * SEC1 http://www.secg.org/index.php?action=secg,docs_secg 00026 * RFC 4492 00027 */ 00028 00029 #if !defined(MBEDTLS_CONFIG_FILE) 00030 #include "mbedtls/config.h" 00031 #else 00032 #include MBEDTLS_CONFIG_FILE 00033 #endif 00034 00035 #if defined(MBEDTLS_ECDH_C) 00036 00037 #include "mbedtls/ecdh.h" 00038 #include "mbedtls/platform_util.h" 00039 00040 #include <string.h> 00041 00042 /* Parameter validation macros based on platform_util.h */ 00043 #define ECDH_VALIDATE_RET( cond ) \ 00044 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_ECP_BAD_INPUT_DATA ) 00045 #define ECDH_VALIDATE( cond ) \ 00046 MBEDTLS_INTERNAL_VALIDATE( cond ) 00047 00048 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 00049 typedef mbedtls_ecdh_context mbedtls_ecdh_context_mbed; 00050 #endif 00051 00052 static mbedtls_ecp_group_id mbedtls_ecdh_grp_id( 00053 const mbedtls_ecdh_context *ctx ) 00054 { 00055 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 00056 return( ctx->grp .id ); 00057 #else 00058 return( ctx->grp_id ); 00059 #endif 00060 } 00061 00062 int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid ) 00063 { 00064 /* At this time, all groups support ECDH. */ 00065 (void) gid; 00066 return( 1 ); 00067 } 00068 00069 #if !defined(MBEDTLS_ECDH_GEN_PUBLIC_ALT) 00070 /* 00071 * Generate public key (restartable version) 00072 * 00073 * Note: this internal function relies on its caller preserving the value of 00074 * the output parameter 'd' across continuation calls. This would not be 00075 * acceptable for a public function but is OK here as we control call sites. 00076 */ 00077 static int ecdh_gen_public_restartable( mbedtls_ecp_group *grp, 00078 mbedtls_mpi *d, mbedtls_ecp_point *Q, 00079 int (*f_rng)(void *, unsigned char *, size_t), 00080 void *p_rng, 00081 mbedtls_ecp_restart_ctx *rs_ctx ) 00082 { 00083 int ret; 00084 00085 /* If multiplication is in progress, we already generated a privkey */ 00086 #if defined(MBEDTLS_ECP_RESTARTABLE) 00087 if( rs_ctx == NULL || rs_ctx->rsm == NULL ) 00088 #endif 00089 MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) ); 00090 00091 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G , 00092 f_rng, p_rng, rs_ctx ) ); 00093 00094 cleanup: 00095 return( ret ); 00096 } 00097 00098 /* 00099 * Generate public key 00100 */ 00101 int mbedtls_ecdh_gen_public( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, 00102 int (*f_rng)(void *, unsigned char *, size_t), 00103 void *p_rng ) 00104 { 00105 ECDH_VALIDATE_RET( grp != NULL ); 00106 ECDH_VALIDATE_RET( d != NULL ); 00107 ECDH_VALIDATE_RET( Q != NULL ); 00108 ECDH_VALIDATE_RET( f_rng != NULL ); 00109 return( ecdh_gen_public_restartable( grp, d, Q, f_rng, p_rng, NULL ) ); 00110 } 00111 #endif /* !MBEDTLS_ECDH_GEN_PUBLIC_ALT */ 00112 00113 #if !defined(MBEDTLS_ECDH_COMPUTE_SHARED_ALT) 00114 /* 00115 * Compute shared secret (SEC1 3.3.1) 00116 */ 00117 static int ecdh_compute_shared_restartable( mbedtls_ecp_group *grp, 00118 mbedtls_mpi *z, 00119 const mbedtls_ecp_point *Q, const mbedtls_mpi *d, 00120 int (*f_rng)(void *, unsigned char *, size_t), 00121 void *p_rng, 00122 mbedtls_ecp_restart_ctx *rs_ctx ) 00123 { 00124 int ret; 00125 mbedtls_ecp_point P; 00126 00127 mbedtls_ecp_point_init( &P ); 00128 00129 MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q, 00130 f_rng, p_rng, rs_ctx ) ); 00131 00132 if( mbedtls_ecp_is_zero( &P ) ) 00133 { 00134 ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 00135 goto cleanup; 00136 } 00137 00138 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) ); 00139 00140 cleanup: 00141 mbedtls_ecp_point_free( &P ); 00142 00143 return( ret ); 00144 } 00145 00146 /* 00147 * Compute shared secret (SEC1 3.3.1) 00148 */ 00149 int mbedtls_ecdh_compute_shared( mbedtls_ecp_group *grp, mbedtls_mpi *z, 00150 const mbedtls_ecp_point *Q, const mbedtls_mpi *d, 00151 int (*f_rng)(void *, unsigned char *, size_t), 00152 void *p_rng ) 00153 { 00154 ECDH_VALIDATE_RET( grp != NULL ); 00155 ECDH_VALIDATE_RET( Q != NULL ); 00156 ECDH_VALIDATE_RET( d != NULL ); 00157 ECDH_VALIDATE_RET( z != NULL ); 00158 return( ecdh_compute_shared_restartable( grp, z, Q, d, 00159 f_rng, p_rng, NULL ) ); 00160 } 00161 #endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */ 00162 00163 static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx ) 00164 { 00165 mbedtls_ecp_group_init( &ctx->grp ); 00166 mbedtls_mpi_init( &ctx->d ); 00167 mbedtls_ecp_point_init( &ctx->Q ); 00168 mbedtls_ecp_point_init( &ctx->Qp ); 00169 mbedtls_mpi_init( &ctx->z ); 00170 00171 #if defined(MBEDTLS_ECP_RESTARTABLE) 00172 mbedtls_ecp_restart_init( &ctx->rs ); 00173 #endif 00174 } 00175 00176 /* 00177 * Initialize context 00178 */ 00179 void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx ) 00180 { 00181 ECDH_VALIDATE( ctx != NULL ); 00182 00183 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 00184 ecdh_init_internal( ctx ); 00185 mbedtls_ecp_point_init( &ctx->Vi ); 00186 mbedtls_ecp_point_init( &ctx->Vf ); 00187 mbedtls_mpi_init( &ctx->_d ); 00188 #else 00189 memset( ctx, 0, sizeof( mbedtls_ecdh_context ) ); 00190 00191 ctx->var = MBEDTLS_ECDH_VARIANT_NONE ; 00192 #endif 00193 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; 00194 #if defined(MBEDTLS_ECP_RESTARTABLE) 00195 ctx->restart_enabled = 0; 00196 #endif 00197 } 00198 00199 static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx, 00200 mbedtls_ecp_group_id grp_id ) 00201 { 00202 int ret; 00203 00204 ret = mbedtls_ecp_group_load( &ctx->grp , grp_id ); 00205 if( ret != 0 ) 00206 { 00207 return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); 00208 } 00209 00210 return( 0 ); 00211 } 00212 00213 /* 00214 * Setup context 00215 */ 00216 int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id ) 00217 { 00218 ECDH_VALIDATE_RET( ctx != NULL ); 00219 00220 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 00221 return( ecdh_setup_internal( ctx, grp_id ) ); 00222 #else 00223 switch( grp_id ) 00224 { 00225 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 00226 case MBEDTLS_ECP_DP_CURVE25519: 00227 ctx->point_format = MBEDTLS_ECP_PF_COMPRESSED; 00228 ctx->var = MBEDTLS_ECDH_VARIANT_EVEREST ; 00229 ctx->grp_id = grp_id; 00230 return( mbedtls_everest_setup( &ctx->ctx .everest_ecdh, grp_id ) ); 00231 #endif 00232 default: 00233 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; 00234 ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0 ; 00235 ctx->grp_id = grp_id; 00236 ecdh_init_internal( &ctx->ctx .mbed_ecdh ); 00237 return( ecdh_setup_internal( &ctx->ctx .mbed_ecdh, grp_id ) ); 00238 } 00239 #endif 00240 } 00241 00242 static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx ) 00243 { 00244 mbedtls_ecp_group_free( &ctx->grp ); 00245 mbedtls_mpi_free( &ctx->d ); 00246 mbedtls_ecp_point_free( &ctx->Q ); 00247 mbedtls_ecp_point_free( &ctx->Qp ); 00248 mbedtls_mpi_free( &ctx->z ); 00249 00250 #if defined(MBEDTLS_ECP_RESTARTABLE) 00251 mbedtls_ecp_restart_free( &ctx->rs ); 00252 #endif 00253 } 00254 00255 #if defined(MBEDTLS_ECP_RESTARTABLE) 00256 /* 00257 * Enable restartable operations for context 00258 */ 00259 void mbedtls_ecdh_enable_restart( mbedtls_ecdh_context *ctx ) 00260 { 00261 ECDH_VALIDATE( ctx != NULL ); 00262 00263 ctx->restart_enabled = 1; 00264 } 00265 #endif 00266 00267 /* 00268 * Free context 00269 */ 00270 void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx ) 00271 { 00272 if( ctx == NULL ) 00273 return; 00274 00275 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 00276 mbedtls_ecp_point_free( &ctx->Vi ); 00277 mbedtls_ecp_point_free( &ctx->Vf ); 00278 mbedtls_mpi_free( &ctx->_d ); 00279 ecdh_free_internal( ctx ); 00280 #else 00281 switch( ctx->var ) 00282 { 00283 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 00284 case MBEDTLS_ECDH_VARIANT_EVEREST : 00285 mbedtls_everest_free( &ctx->ctx .everest_ecdh ); 00286 break; 00287 #endif 00288 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0 : 00289 ecdh_free_internal( &ctx->ctx .mbed_ecdh ); 00290 break; 00291 default: 00292 break; 00293 } 00294 00295 ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED; 00296 ctx->var = MBEDTLS_ECDH_VARIANT_NONE ; 00297 ctx->grp_id = MBEDTLS_ECP_DP_NONE; 00298 #endif 00299 } 00300 00301 static int ecdh_make_params_internal( mbedtls_ecdh_context_mbed *ctx, 00302 size_t *olen, int point_format, 00303 unsigned char *buf, size_t blen, 00304 int (*f_rng)(void *, 00305 unsigned char *, 00306 size_t), 00307 void *p_rng, 00308 int restart_enabled ) 00309 { 00310 int ret; 00311 size_t grp_len, pt_len; 00312 #if defined(MBEDTLS_ECP_RESTARTABLE) 00313 mbedtls_ecp_restart_ctx *rs_ctx = NULL; 00314 #endif 00315 00316 if( ctx->grp .pbits == 0 ) 00317 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 00318 00319 #if defined(MBEDTLS_ECP_RESTARTABLE) 00320 if( restart_enabled ) 00321 rs_ctx = &ctx->rs ; 00322 #else 00323 (void) restart_enabled; 00324 #endif 00325 00326 00327 #if defined(MBEDTLS_ECP_RESTARTABLE) 00328 if( ( ret = ecdh_gen_public_restartable( &ctx->grp , &ctx->d , &ctx->Q , 00329 f_rng, p_rng, rs_ctx ) ) != 0 ) 00330 return( ret ); 00331 #else 00332 if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp , &ctx->d , &ctx->Q , 00333 f_rng, p_rng ) ) != 0 ) 00334 return( ret ); 00335 #endif /* MBEDTLS_ECP_RESTARTABLE */ 00336 00337 if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp , &grp_len, buf, 00338 blen ) ) != 0 ) 00339 return( ret ); 00340 00341 buf += grp_len; 00342 blen -= grp_len; 00343 00344 if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp , &ctx->Q , point_format, 00345 &pt_len, buf, blen ) ) != 0 ) 00346 return( ret ); 00347 00348 *olen = grp_len + pt_len; 00349 return( 0 ); 00350 } 00351 00352 /* 00353 * Setup and write the ServerKeyExchange parameters (RFC 4492) 00354 * struct { 00355 * ECParameters curve_params; 00356 * ECPoint public; 00357 * } ServerECDHParams; 00358 */ 00359 int mbedtls_ecdh_make_params( mbedtls_ecdh_context *ctx, size_t *olen, 00360 unsigned char *buf, size_t blen, 00361 int (*f_rng)(void *, unsigned char *, size_t), 00362 void *p_rng ) 00363 { 00364 int restart_enabled = 0; 00365 ECDH_VALIDATE_RET( ctx != NULL ); 00366 ECDH_VALIDATE_RET( olen != NULL ); 00367 ECDH_VALIDATE_RET( buf != NULL ); 00368 ECDH_VALIDATE_RET( f_rng != NULL ); 00369 00370 #if defined(MBEDTLS_ECP_RESTARTABLE) 00371 restart_enabled = ctx->restart_enabled ; 00372 #else 00373 (void) restart_enabled; 00374 #endif 00375 00376 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 00377 return( ecdh_make_params_internal( ctx, olen, ctx->point_format , buf, blen, 00378 f_rng, p_rng, restart_enabled ) ); 00379 #else 00380 switch( ctx->var ) 00381 { 00382 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 00383 case MBEDTLS_ECDH_VARIANT_EVEREST : 00384 return( mbedtls_everest_make_params( &ctx->ctx .everest_ecdh, olen, 00385 buf, blen, f_rng, p_rng ) ); 00386 #endif 00387 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0 : 00388 return( ecdh_make_params_internal( &ctx->ctx .mbed_ecdh, olen, 00389 ctx->point_format , buf, blen, 00390 f_rng, p_rng, 00391 restart_enabled ) ); 00392 default: 00393 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 00394 } 00395 #endif 00396 } 00397 00398 static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx, 00399 const unsigned char **buf, 00400 const unsigned char *end ) 00401 { 00402 return( mbedtls_ecp_tls_read_point( &ctx->grp , &ctx->Qp , buf, 00403 end - *buf ) ); 00404 } 00405 00406 /* 00407 * Read the ServerKeyExhange parameters (RFC 4492) 00408 * struct { 00409 * ECParameters curve_params; 00410 * ECPoint public; 00411 * } ServerECDHParams; 00412 */ 00413 int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx, 00414 const unsigned char **buf, 00415 const unsigned char *end ) 00416 { 00417 int ret; 00418 mbedtls_ecp_group_id grp_id; 00419 ECDH_VALIDATE_RET( ctx != NULL ); 00420 ECDH_VALIDATE_RET( buf != NULL ); 00421 ECDH_VALIDATE_RET( *buf != NULL ); 00422 ECDH_VALIDATE_RET( end != NULL ); 00423 00424 if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) ) 00425 != 0 ) 00426 return( ret ); 00427 00428 if( ( ret = mbedtls_ecdh_setup( ctx, grp_id ) ) != 0 ) 00429 return( ret ); 00430 00431 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 00432 return( ecdh_read_params_internal( ctx, buf, end ) ); 00433 #else 00434 switch( ctx->var ) 00435 { 00436 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 00437 case MBEDTLS_ECDH_VARIANT_EVEREST : 00438 return( mbedtls_everest_read_params( &ctx->ctx .everest_ecdh, 00439 buf, end) ); 00440 #endif 00441 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0 : 00442 return( ecdh_read_params_internal( &ctx->ctx .mbed_ecdh, 00443 buf, end ) ); 00444 default: 00445 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 00446 } 00447 #endif 00448 } 00449 00450 static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx, 00451 const mbedtls_ecp_keypair *key, 00452 mbedtls_ecdh_side side ) 00453 { 00454 int ret; 00455 00456 /* If it's not our key, just import the public part as Qp */ 00457 if( side == MBEDTLS_ECDH_THEIRS ) 00458 return( mbedtls_ecp_copy( &ctx->Qp , &key->Q ) ); 00459 00460 /* Our key: import public (as Q) and private parts */ 00461 if( side != MBEDTLS_ECDH_OURS ) 00462 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 00463 00464 if( ( ret = mbedtls_ecp_copy( &ctx->Q , &key->Q ) ) != 0 || 00465 ( ret = mbedtls_mpi_copy( &ctx->d , &key->d ) ) != 0 ) 00466 return( ret ); 00467 00468 return( 0 ); 00469 } 00470 00471 /* 00472 * Get parameters from a keypair 00473 */ 00474 int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx, 00475 const mbedtls_ecp_keypair *key, 00476 mbedtls_ecdh_side side ) 00477 { 00478 int ret; 00479 ECDH_VALIDATE_RET( ctx != NULL ); 00480 ECDH_VALIDATE_RET( key != NULL ); 00481 ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS || 00482 side == MBEDTLS_ECDH_THEIRS ); 00483 00484 if( mbedtls_ecdh_grp_id( ctx ) == MBEDTLS_ECP_DP_NONE ) 00485 { 00486 /* This is the first call to get_params(). Set up the context 00487 * for use with the group. */ 00488 if( ( ret = mbedtls_ecdh_setup( ctx, key->grp .id ) ) != 0 ) 00489 return( ret ); 00490 } 00491 else 00492 { 00493 /* This is not the first call to get_params(). Check that the 00494 * current key's group is the same as the context's, which was set 00495 * from the first key's group. */ 00496 if( mbedtls_ecdh_grp_id( ctx ) != key->grp .id ) 00497 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 00498 } 00499 00500 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 00501 return( ecdh_get_params_internal( ctx, key, side ) ); 00502 #else 00503 switch( ctx->var ) 00504 { 00505 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 00506 case MBEDTLS_ECDH_VARIANT_EVEREST : 00507 { 00508 mbedtls_everest_ecdh_side s = side == MBEDTLS_ECDH_OURS ? 00509 MBEDTLS_EVEREST_ECDH_OURS : 00510 MBEDTLS_EVEREST_ECDH_THEIRS; 00511 return( mbedtls_everest_get_params( &ctx->ctx .everest_ecdh, 00512 key, s) ); 00513 } 00514 #endif 00515 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0 : 00516 return( ecdh_get_params_internal( &ctx->ctx .mbed_ecdh, 00517 key, side ) ); 00518 default: 00519 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 00520 } 00521 #endif 00522 } 00523 00524 static int ecdh_make_public_internal( mbedtls_ecdh_context_mbed *ctx, 00525 size_t *olen, int point_format, 00526 unsigned char *buf, size_t blen, 00527 int (*f_rng)(void *, 00528 unsigned char *, 00529 size_t), 00530 void *p_rng, 00531 int restart_enabled ) 00532 { 00533 int ret; 00534 #if defined(MBEDTLS_ECP_RESTARTABLE) 00535 mbedtls_ecp_restart_ctx *rs_ctx = NULL; 00536 #endif 00537 00538 if( ctx->grp .pbits == 0 ) 00539 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 00540 00541 #if defined(MBEDTLS_ECP_RESTARTABLE) 00542 if( restart_enabled ) 00543 rs_ctx = &ctx->rs ; 00544 #else 00545 (void) restart_enabled; 00546 #endif 00547 00548 #if defined(MBEDTLS_ECP_RESTARTABLE) 00549 if( ( ret = ecdh_gen_public_restartable( &ctx->grp , &ctx->d , &ctx->Q , 00550 f_rng, p_rng, rs_ctx ) ) != 0 ) 00551 return( ret ); 00552 #else 00553 if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp , &ctx->d , &ctx->Q , 00554 f_rng, p_rng ) ) != 0 ) 00555 return( ret ); 00556 #endif /* MBEDTLS_ECP_RESTARTABLE */ 00557 00558 return mbedtls_ecp_tls_write_point( &ctx->grp , &ctx->Q , point_format, olen, 00559 buf, blen ); 00560 } 00561 00562 /* 00563 * Setup and export the client public value 00564 */ 00565 int mbedtls_ecdh_make_public( mbedtls_ecdh_context *ctx, size_t *olen, 00566 unsigned char *buf, size_t blen, 00567 int (*f_rng)(void *, unsigned char *, size_t), 00568 void *p_rng ) 00569 { 00570 int restart_enabled = 0; 00571 ECDH_VALIDATE_RET( ctx != NULL ); 00572 ECDH_VALIDATE_RET( olen != NULL ); 00573 ECDH_VALIDATE_RET( buf != NULL ); 00574 ECDH_VALIDATE_RET( f_rng != NULL ); 00575 00576 #if defined(MBEDTLS_ECP_RESTARTABLE) 00577 restart_enabled = ctx->restart_enabled ; 00578 #endif 00579 00580 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 00581 return( ecdh_make_public_internal( ctx, olen, ctx->point_format , buf, blen, 00582 f_rng, p_rng, restart_enabled ) ); 00583 #else 00584 switch( ctx->var ) 00585 { 00586 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 00587 case MBEDTLS_ECDH_VARIANT_EVEREST : 00588 return( mbedtls_everest_make_public( &ctx->ctx .everest_ecdh, olen, 00589 buf, blen, f_rng, p_rng ) ); 00590 #endif 00591 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0 : 00592 return( ecdh_make_public_internal( &ctx->ctx .mbed_ecdh, olen, 00593 ctx->point_format , buf, blen, 00594 f_rng, p_rng, 00595 restart_enabled ) ); 00596 default: 00597 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 00598 } 00599 #endif 00600 } 00601 00602 static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx, 00603 const unsigned char *buf, size_t blen ) 00604 { 00605 int ret; 00606 const unsigned char *p = buf; 00607 00608 if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp , &ctx->Qp , &p, 00609 blen ) ) != 0 ) 00610 return( ret ); 00611 00612 if( (size_t)( p - buf ) != blen ) 00613 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 00614 00615 return( 0 ); 00616 } 00617 00618 /* 00619 * Parse and import the client's public value 00620 */ 00621 int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx, 00622 const unsigned char *buf, size_t blen ) 00623 { 00624 ECDH_VALIDATE_RET( ctx != NULL ); 00625 ECDH_VALIDATE_RET( buf != NULL ); 00626 00627 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 00628 return( ecdh_read_public_internal( ctx, buf, blen ) ); 00629 #else 00630 switch( ctx->var ) 00631 { 00632 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 00633 case MBEDTLS_ECDH_VARIANT_EVEREST : 00634 return( mbedtls_everest_read_public( &ctx->ctx .everest_ecdh, 00635 buf, blen ) ); 00636 #endif 00637 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0 : 00638 return( ecdh_read_public_internal( &ctx->ctx .mbed_ecdh, 00639 buf, blen ) ); 00640 default: 00641 return MBEDTLS_ERR_ECP_BAD_INPUT_DATA; 00642 } 00643 #endif 00644 } 00645 00646 static int ecdh_calc_secret_internal( mbedtls_ecdh_context_mbed *ctx, 00647 size_t *olen, unsigned char *buf, 00648 size_t blen, 00649 int (*f_rng)(void *, 00650 unsigned char *, 00651 size_t), 00652 void *p_rng, 00653 int restart_enabled ) 00654 { 00655 int ret; 00656 #if defined(MBEDTLS_ECP_RESTARTABLE) 00657 mbedtls_ecp_restart_ctx *rs_ctx = NULL; 00658 #endif 00659 00660 if( ctx == NULL || ctx->grp .pbits == 0 ) 00661 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 00662 00663 #if defined(MBEDTLS_ECP_RESTARTABLE) 00664 if( restart_enabled ) 00665 rs_ctx = &ctx->rs ; 00666 #else 00667 (void) restart_enabled; 00668 #endif 00669 00670 #if defined(MBEDTLS_ECP_RESTARTABLE) 00671 if( ( ret = ecdh_compute_shared_restartable( &ctx->grp , &ctx->z , &ctx->Qp , 00672 &ctx->d , f_rng, p_rng, 00673 rs_ctx ) ) != 0 ) 00674 { 00675 return( ret ); 00676 } 00677 #else 00678 if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp , &ctx->z , &ctx->Qp , 00679 &ctx->d , f_rng, p_rng ) ) != 0 ) 00680 { 00681 return( ret ); 00682 } 00683 #endif /* MBEDTLS_ECP_RESTARTABLE */ 00684 00685 if( mbedtls_mpi_size( &ctx->z ) > blen ) 00686 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 00687 00688 *olen = ctx->grp .pbits / 8 + ( ( ctx->grp .pbits % 8 ) != 0 ); 00689 00690 if( mbedtls_ecp_get_type( &ctx->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY ) 00691 return mbedtls_mpi_write_binary_le( &ctx->z , buf, *olen ); 00692 00693 return mbedtls_mpi_write_binary( &ctx->z , buf, *olen ); 00694 } 00695 00696 /* 00697 * Derive and export the shared secret 00698 */ 00699 int mbedtls_ecdh_calc_secret( mbedtls_ecdh_context *ctx, size_t *olen, 00700 unsigned char *buf, size_t blen, 00701 int (*f_rng)(void *, unsigned char *, size_t), 00702 void *p_rng ) 00703 { 00704 int restart_enabled = 0; 00705 ECDH_VALIDATE_RET( ctx != NULL ); 00706 ECDH_VALIDATE_RET( olen != NULL ); 00707 ECDH_VALIDATE_RET( buf != NULL ); 00708 00709 #if defined(MBEDTLS_ECP_RESTARTABLE) 00710 restart_enabled = ctx->restart_enabled ; 00711 #endif 00712 00713 #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT) 00714 return( ecdh_calc_secret_internal( ctx, olen, buf, blen, f_rng, p_rng, 00715 restart_enabled ) ); 00716 #else 00717 switch( ctx->var ) 00718 { 00719 #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED) 00720 case MBEDTLS_ECDH_VARIANT_EVEREST : 00721 return( mbedtls_everest_calc_secret( &ctx->ctx .everest_ecdh, olen, 00722 buf, blen, f_rng, p_rng ) ); 00723 #endif 00724 case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0 : 00725 return( ecdh_calc_secret_internal( &ctx->ctx .mbed_ecdh, olen, buf, 00726 blen, f_rng, p_rng, 00727 restart_enabled ) ); 00728 default: 00729 return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); 00730 } 00731 #endif 00732 } 00733 00734 #endif /* MBEDTLS_ECDH_C */
Generated on Tue Jul 12 2022 13:54:17 by
