Coverage Report

Created: 2023-09-24 16:03

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