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