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