Coverage Report

Created: 2025-03-01 06:26

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