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