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