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