xref: /optee_os/lib/libmbedtls/mbedtls/library/ecdh.c (revision a1d5c81f8834a9d2c6f4372cce2e59e70e709121)
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