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