Branch data Line data Source code
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 : :
49 : 8 : 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 : 8 : return( ctx->grp_id );
56 : : #endif
57 : : }
58 : :
59 : 0 : int mbedtls_ecdh_can_do( mbedtls_ecp_group_id gid )
60 : : {
61 : : /* At this time, all groups support ECDH. */
62 : 0 : (void) gid;
63 : 0 : 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 : : */
74 : 0 : 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 : 0 : 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 [ # # ]: 0 : MBEDTLS_MPI_CHK( mbedtls_ecp_gen_privkey( grp, d, f_rng, p_rng ) );
87 : :
88 [ # # ]: 0 : MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, Q, d, &grp->G,
89 : : f_rng, p_rng, rs_ctx ) );
90 : :
91 : 0 : cleanup:
92 : 0 : return( ret );
93 : : }
94 : :
95 : : /*
96 : : * Generate public key
97 : : */
98 : 0 : 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 : 0 : ECDH_VALIDATE_RET( grp != NULL );
103 : 0 : ECDH_VALIDATE_RET( d != NULL );
104 : 0 : ECDH_VALIDATE_RET( Q != NULL );
105 : 0 : ECDH_VALIDATE_RET( f_rng != NULL );
106 : 0 : 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 : : */
114 : 4 : 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 : 4 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
122 : 4 : mbedtls_ecp_point P;
123 : :
124 : 4 : mbedtls_ecp_point_init( &P );
125 : :
126 [ - + ]: 4 : MBEDTLS_MPI_CHK( mbedtls_ecp_mul_restartable( grp, &P, d, Q,
127 : : f_rng, p_rng, rs_ctx ) );
128 : :
129 [ - + ]: 4 : if( mbedtls_ecp_is_zero( &P ) )
130 : : {
131 : 0 : ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
132 : 0 : goto cleanup;
133 : : }
134 : :
135 [ + - ]: 4 : MBEDTLS_MPI_CHK( mbedtls_mpi_copy( z, &P.X ) );
136 : :
137 : 4 : cleanup:
138 : 4 : mbedtls_ecp_point_free( &P );
139 : :
140 : 4 : return( ret );
141 : : }
142 : :
143 : : /*
144 : : * Compute shared secret (SEC1 3.3.1)
145 : : */
146 : 4 : 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 : 4 : ECDH_VALIDATE_RET( grp != NULL );
152 : 4 : ECDH_VALIDATE_RET( Q != NULL );
153 : 4 : ECDH_VALIDATE_RET( d != NULL );
154 : 4 : ECDH_VALIDATE_RET( z != NULL );
155 : 4 : return( ecdh_compute_shared_restartable( grp, z, Q, d,
156 : : f_rng, p_rng, NULL ) );
157 : : }
158 : : #endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
159 : :
160 : 4 : static void ecdh_init_internal( mbedtls_ecdh_context_mbed *ctx )
161 : : {
162 : 4 : mbedtls_ecp_group_init( &ctx->grp );
163 : 4 : mbedtls_mpi_init( &ctx->d );
164 : 4 : mbedtls_ecp_point_init( &ctx->Q );
165 : 4 : mbedtls_ecp_point_init( &ctx->Qp );
166 : 4 : mbedtls_mpi_init( &ctx->z );
167 : :
168 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
169 : : mbedtls_ecp_restart_init( &ctx->rs );
170 : : #endif
171 : 4 : }
172 : :
173 : : /*
174 : : * Initialize context
175 : : */
176 : 4 : void mbedtls_ecdh_init( mbedtls_ecdh_context *ctx )
177 : : {
178 : 4 : 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 : 4 : memset( ctx, 0, sizeof( mbedtls_ecdh_context ) );
187 : :
188 : 4 : ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
189 : : #endif
190 : 4 : ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
191 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
192 : : ctx->restart_enabled = 0;
193 : : #endif
194 : 4 : }
195 : :
196 : 4 : static int ecdh_setup_internal( mbedtls_ecdh_context_mbed *ctx,
197 : : mbedtls_ecp_group_id grp_id )
198 : : {
199 : 4 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
200 : :
201 : 4 : ret = mbedtls_ecp_group_load( &ctx->grp, grp_id );
202 [ - + ]: 4 : if( ret != 0 )
203 : : {
204 : 0 : return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
205 : : }
206 : :
207 : : return( 0 );
208 : : }
209 : :
210 : : /*
211 : : * Setup context
212 : : */
213 : 4 : int mbedtls_ecdh_setup( mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id )
214 : : {
215 : 4 : ECDH_VALIDATE_RET( ctx != NULL );
216 : :
217 : : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
218 : : return( ecdh_setup_internal( ctx, grp_id ) );
219 : : #else
220 : 4 : 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 : 4 : ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
231 : 4 : ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
232 : 4 : ctx->grp_id = grp_id;
233 : 4 : ecdh_init_internal( &ctx->ctx.mbed_ecdh );
234 : 4 : return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) );
235 : : }
236 : : #endif
237 : : }
238 : :
239 : 4 : static void ecdh_free_internal( mbedtls_ecdh_context_mbed *ctx )
240 : : {
241 : 4 : mbedtls_ecp_group_free( &ctx->grp );
242 : 4 : mbedtls_mpi_free( &ctx->d );
243 : 4 : mbedtls_ecp_point_free( &ctx->Q );
244 : 4 : mbedtls_ecp_point_free( &ctx->Qp );
245 : 4 : mbedtls_mpi_free( &ctx->z );
246 : :
247 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
248 : : mbedtls_ecp_restart_free( &ctx->rs );
249 : : #endif
250 : 4 : }
251 : :
252 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
253 : : /*
254 : : * Enable restartable operations for context
255 : : */
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 : : */
267 : 4 : void mbedtls_ecdh_free( mbedtls_ecdh_context *ctx )
268 : : {
269 [ + - ]: 4 : 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 [ + - ]: 4 : 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 : 4 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
286 : 4 : ecdh_free_internal( &ctx->ctx.mbed_ecdh );
287 : 4 : break;
288 : : default:
289 : : break;
290 : : }
291 : :
292 : 4 : ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
293 : 4 : ctx->var = MBEDTLS_ECDH_VARIANT_NONE;
294 : 4 : ctx->grp_id = MBEDTLS_ECP_DP_NONE;
295 : : #endif
296 : : }
297 : :
298 : 0 : 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 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
308 : 0 : size_t grp_len, pt_len;
309 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
310 : : mbedtls_ecp_restart_ctx *rs_ctx = NULL;
311 : : #endif
312 : :
313 [ # # ]: 0 : 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 : 0 : (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 [ # # ]: 0 : 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 [ # # ]: 0 : if( ( ret = mbedtls_ecp_tls_write_group( &ctx->grp, &grp_len, buf,
335 : : blen ) ) != 0 )
336 : : return( ret );
337 : :
338 : 0 : buf += grp_len;
339 : 0 : blen -= grp_len;
340 : :
341 [ # # ]: 0 : if( ( ret = mbedtls_ecp_tls_write_point( &ctx->grp, &ctx->Q, point_format,
342 : : &pt_len, buf, blen ) ) != 0 )
343 : : return( ret );
344 : :
345 : 0 : *olen = grp_len + pt_len;
346 : 0 : 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 : : */
356 : 0 : 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 : 0 : int restart_enabled = 0;
362 : 0 : ECDH_VALIDATE_RET( ctx != NULL );
363 : 0 : ECDH_VALIDATE_RET( olen != NULL );
364 : 0 : ECDH_VALIDATE_RET( buf != NULL );
365 : 0 : ECDH_VALIDATE_RET( f_rng != NULL );
366 : :
367 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
368 : : restart_enabled = ctx->restart_enabled;
369 : : #else
370 : 0 : (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 [ # # ]: 0 : 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 : 0 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
385 : 0 : return( ecdh_make_params_internal( &ctx->ctx.mbed_ecdh, olen,
386 : 0 : 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 : :
395 : 0 : static int ecdh_read_params_internal( mbedtls_ecdh_context_mbed *ctx,
396 : : const unsigned char **buf,
397 : : const unsigned char *end )
398 : : {
399 : 0 : return( mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, buf,
400 : 0 : end - *buf ) );
401 : : }
402 : :
403 : : /*
404 : : * Read the ServerKeyExhange parameters (RFC 4492)
405 : : * struct {
406 : : * ECParameters curve_params;
407 : : * ECPoint public;
408 : : * } ServerECDHParams;
409 : : */
410 : 0 : int mbedtls_ecdh_read_params( mbedtls_ecdh_context *ctx,
411 : : const unsigned char **buf,
412 : : const unsigned char *end )
413 : : {
414 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
415 : 0 : mbedtls_ecp_group_id grp_id;
416 : 0 : ECDH_VALIDATE_RET( ctx != NULL );
417 : 0 : ECDH_VALIDATE_RET( buf != NULL );
418 : 0 : ECDH_VALIDATE_RET( *buf != NULL );
419 : 0 : ECDH_VALIDATE_RET( end != NULL );
420 : :
421 [ # # ]: 0 : if( ( ret = mbedtls_ecp_tls_read_group_id( &grp_id, buf, end - *buf ) )
422 : : != 0 )
423 : : return( ret );
424 : :
425 [ # # ]: 0 : 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 [ # # ]: 0 : 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 : 0 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
439 : 0 : 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 : :
447 : 8 : static int ecdh_get_params_internal( mbedtls_ecdh_context_mbed *ctx,
448 : : const mbedtls_ecp_keypair *key,
449 : : mbedtls_ecdh_side side )
450 : : {
451 : 8 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
452 : :
453 : : /* If it's not our key, just import the public part as Qp */
454 [ + + ]: 8 : if( side == MBEDTLS_ECDH_THEIRS )
455 : 4 : return( mbedtls_ecp_copy( &ctx->Qp, &key->Q ) );
456 : :
457 : : /* Our key: import public (as Q) and private parts */
458 [ + - ]: 4 : if( side != MBEDTLS_ECDH_OURS )
459 : : return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
460 : :
461 [ + - ]: 4 : if( ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ||
462 [ - + ]: 4 : ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 )
463 : 0 : return( ret );
464 : :
465 : : return( 0 );
466 : : }
467 : :
468 : : /*
469 : : * Get parameters from a keypair
470 : : */
471 : 8 : int mbedtls_ecdh_get_params( mbedtls_ecdh_context *ctx,
472 : : const mbedtls_ecp_keypair *key,
473 : : mbedtls_ecdh_side side )
474 : : {
475 : 8 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
476 : 8 : ECDH_VALIDATE_RET( ctx != NULL );
477 : 8 : ECDH_VALIDATE_RET( key != NULL );
478 : 8 : ECDH_VALIDATE_RET( side == MBEDTLS_ECDH_OURS ||
479 : : side == MBEDTLS_ECDH_THEIRS );
480 : :
481 [ + + ]: 8 : 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 [ + - ]: 4 : 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 [ + - ]: 4 : 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 [ + - ]: 8 : 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 : 8 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
513 : 8 : 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 : :
521 : 0 : 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 : 0 : 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 [ # # ]: 0 : 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 : 0 : (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 [ # # ]: 0 : 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 : 0 : 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 : : */
562 : 0 : 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 : 0 : int restart_enabled = 0;
568 : 0 : ECDH_VALIDATE_RET( ctx != NULL );
569 : 0 : ECDH_VALIDATE_RET( olen != NULL );
570 : 0 : ECDH_VALIDATE_RET( buf != NULL );
571 : 0 : 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 [ # # ]: 0 : 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 : 0 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
589 : 0 : return( ecdh_make_public_internal( &ctx->ctx.mbed_ecdh, olen,
590 : 0 : 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 : :
599 : 0 : static int ecdh_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
600 : : const unsigned char *buf, size_t blen )
601 : : {
602 : 0 : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
603 : 0 : const unsigned char *p = buf;
604 : :
605 [ # # ]: 0 : if( ( ret = mbedtls_ecp_tls_read_point( &ctx->grp, &ctx->Qp, &p,
606 : : blen ) ) != 0 )
607 : : return( ret );
608 : :
609 [ # # ]: 0 : if( (size_t)( p - buf ) != blen )
610 : 0 : return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
611 : :
612 : : return( 0 );
613 : : }
614 : :
615 : : /*
616 : : * Parse and import the client's public value
617 : : */
618 : 0 : int mbedtls_ecdh_read_public( mbedtls_ecdh_context *ctx,
619 : : const unsigned char *buf, size_t blen )
620 : : {
621 : 0 : ECDH_VALIDATE_RET( ctx != NULL );
622 : 0 : 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 [ # # ]: 0 : 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 : 0 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
635 : 0 : 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 : :
643 : 4 : 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 : 4 : 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 [ + - + - ]: 4 : 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 : 4 : (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 [ + - ]: 4 : if( ( ret = mbedtls_ecdh_compute_shared( &ctx->grp, &ctx->z, &ctx->Qp,
676 : 4 : &ctx->d, f_rng, p_rng ) ) != 0 )
677 : : {
678 : : return( ret );
679 : : }
680 : : #endif /* MBEDTLS_ECP_RESTARTABLE */
681 : :
682 [ + - ]: 4 : if( mbedtls_mpi_size( &ctx->z ) > blen )
683 : : return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
684 : :
685 : 4 : *olen = ctx->grp.pbits / 8 + ( ( ctx->grp.pbits % 8 ) != 0 );
686 : :
687 [ - + ]: 4 : if( mbedtls_ecp_get_type( &ctx->grp ) == MBEDTLS_ECP_TYPE_MONTGOMERY )
688 : 0 : return mbedtls_mpi_write_binary_le( &ctx->z, buf, *olen );
689 : :
690 : 4 : return mbedtls_mpi_write_binary( &ctx->z, buf, *olen );
691 : : }
692 : :
693 : : /*
694 : : * Derive and export the shared secret
695 : : */
696 : 4 : 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 : 4 : int restart_enabled = 0;
702 : 4 : ECDH_VALIDATE_RET( ctx != NULL );
703 : 4 : ECDH_VALIDATE_RET( olen != NULL );
704 : 4 : 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 [ + - ]: 4 : 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 : 4 : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
722 : 4 : 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)
732 : :
733 : : static int ecdh_tls13_make_params_internal( mbedtls_ecdh_context_mbed *ctx,
734 : : size_t *out_len, int point_format,
735 : : unsigned char *buf, size_t buf_len,
736 : : int ( *f_rng )( void *, unsigned char *, size_t), void *p_rng )
737 : : {
738 : : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
739 : :
740 : : if( ctx->grp.pbits == 0 )
741 : : return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
742 : :
743 : : if( ( ret = mbedtls_ecdh_gen_public( &ctx->grp, &ctx->d, &ctx->Q,
744 : : f_rng, p_rng ) ) != 0 )
745 : : return( ret );
746 : :
747 : : ret = mbedtls_ecp_point_write_binary( &ctx->grp, &ctx->Q, point_format,
748 : : out_len, buf, buf_len );
749 : : if( ret != 0 )
750 : : return( ret );
751 : :
752 : : return( 0 );
753 : : }
754 : :
755 : : int mbedtls_ecdh_tls13_make_params( mbedtls_ecdh_context *ctx, size_t *out_len,
756 : : unsigned char *buf, size_t buf_len,
757 : : int ( *f_rng )( void *, unsigned char *, size_t ),
758 : : void *p_rng )
759 : : {
760 : : ECDH_VALIDATE_RET( ctx != NULL );
761 : : ECDH_VALIDATE_RET( out_len != NULL );
762 : : ECDH_VALIDATE_RET( buf != NULL );
763 : : ECDH_VALIDATE_RET( f_rng != NULL );
764 : :
765 : :
766 : : #if defined(MBEDTLS_ECP_RESTARTABLE)
767 : : if( ctx-> restart_enabled )
768 : : return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
769 : : #endif
770 : :
771 : : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
772 : : return( ecdh_tls13_make_params_internal( ctx, out_len, ctx->point_format,
773 : : buf, buf_len, f_rng, p_rng ) );
774 : : #else
775 : : switch( ctx->var )
776 : : {
777 : : #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
778 : : case MBEDTLS_ECDH_VARIANT_EVEREST:
779 : : return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
780 : : #endif
781 : : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
782 : : return( ecdh_tls13_make_params_internal( &ctx->ctx.mbed_ecdh,
783 : : out_len, ctx->point_format,
784 : : buf, buf_len, f_rng, p_rng ) );
785 : : default:
786 : : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
787 : : }
788 : : #endif
789 : : }
790 : :
791 : : /*
792 : : * Setup context without Everest
793 : : */
794 : : int mbedtls_ecdh_setup_no_everest( mbedtls_ecdh_context *ctx,
795 : : mbedtls_ecp_group_id grp_id )
796 : : {
797 : : ECDH_VALIDATE_RET( ctx != NULL );
798 : :
799 : : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
800 : : return( ecdh_setup_internal( ctx, grp_id ) );
801 : : #else
802 : : ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
803 : : ctx->var = MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0;
804 : : ctx->grp_id = grp_id;
805 : : ecdh_init_internal( &ctx->ctx.mbed_ecdh );
806 : : return( ecdh_setup_internal( &ctx->ctx.mbed_ecdh, grp_id ) );
807 : : #endif
808 : : }
809 : :
810 : : static int ecdh_tls13_read_public_internal( mbedtls_ecdh_context_mbed *ctx,
811 : : const unsigned char *buf,
812 : : size_t buf_len )
813 : : {
814 : : int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
815 : : const unsigned char *p = buf;
816 : : size_t data_len;
817 : :
818 : : if( buf_len < 3 )
819 : : return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
820 : :
821 : : data_len = MBEDTLS_GET_UINT16_BE( p, 0 );
822 : : p += 2;
823 : :
824 : : if( data_len < 1 || data_len != ( buf_len - 2 ) )
825 : : return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA );
826 : :
827 : : if( ( ret = mbedtls_ecp_point_read_binary( &ctx->grp,
828 : : &ctx->Qp, p, data_len ) ) != 0)
829 : : {
830 : : return( ret );
831 : : }
832 : :
833 : : return( 0 );
834 : : }
835 : :
836 : : /*
837 : : * Parse and import the client's TLS 1.3 public value
838 : : */
839 : : int mbedtls_ecdh_tls13_read_public( mbedtls_ecdh_context *ctx,
840 : : const unsigned char *buf,
841 : : size_t buf_len )
842 : : {
843 : : ECDH_VALIDATE_RET( ctx != NULL );
844 : : ECDH_VALIDATE_RET( buf != NULL );
845 : :
846 : : #if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
847 : : return( ecdh_tls13_read_public_internal( ctx, buf, buf_len ) );
848 : : #else
849 : : switch( ctx->var )
850 : : {
851 : : #if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
852 : : case MBEDTLS_ECDH_VARIANT_EVEREST:
853 : : return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE );
854 : : #endif
855 : : case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
856 : : return( ecdh_tls13_read_public_internal( &ctx->ctx.mbed_ecdh,
857 : : buf, buf_len ) );
858 : : default:
859 : : return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
860 : : }
861 : : #endif
862 : : }
863 : :
864 : : #endif /* MBEDTLS_SSL_PROTO_TLS1_3 */
865 : :
866 : : #endif /* MBEDTLS_ECDH_C */
|