Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/mbedtls/library/ecdh.c
9898 views
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
{
32
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
33
return ctx->grp.id;
34
#else
35
return ctx->grp_id;
36
#endif
37
}
38
39
int mbedtls_ecdh_can_do(mbedtls_ecp_group_id gid)
40
{
41
/* At this time, all groups support ECDH. */
42
(void) gid;
43
return 1;
44
}
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
{
60
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
61
62
int restarting = 0;
63
#if defined(MBEDTLS_ECP_RESTARTABLE)
64
restarting = (rs_ctx != NULL && rs_ctx->rsm != NULL);
65
#endif
66
/* If multiplication is in progress, we already generated a privkey */
67
if (!restarting) {
68
MBEDTLS_MPI_CHK(mbedtls_ecp_gen_privkey(grp, d, f_rng, p_rng));
69
}
70
71
MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, Q, d, &grp->G,
72
f_rng, p_rng, rs_ctx));
73
74
cleanup:
75
return ret;
76
}
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
{
85
return ecdh_gen_public_restartable(grp, d, Q, f_rng, p_rng, NULL);
86
}
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
{
100
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
101
mbedtls_ecp_point P;
102
103
mbedtls_ecp_point_init(&P);
104
105
MBEDTLS_MPI_CHK(mbedtls_ecp_mul_restartable(grp, &P, d, Q,
106
f_rng, p_rng, rs_ctx));
107
108
if (mbedtls_ecp_is_zero(&P)) {
109
ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
110
goto cleanup;
111
}
112
113
MBEDTLS_MPI_CHK(mbedtls_mpi_copy(z, &P.X));
114
115
cleanup:
116
mbedtls_ecp_point_free(&P);
117
118
return ret;
119
}
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
{
129
return ecdh_compute_shared_restartable(grp, z, Q, d,
130
f_rng, p_rng, NULL);
131
}
132
#endif /* !MBEDTLS_ECDH_COMPUTE_SHARED_ALT */
133
134
static void ecdh_init_internal(mbedtls_ecdh_context_mbed *ctx)
135
{
136
mbedtls_ecp_group_init(&ctx->grp);
137
mbedtls_mpi_init(&ctx->d);
138
mbedtls_ecp_point_init(&ctx->Q);
139
mbedtls_ecp_point_init(&ctx->Qp);
140
mbedtls_mpi_init(&ctx->z);
141
142
#if defined(MBEDTLS_ECP_RESTARTABLE)
143
mbedtls_ecp_restart_init(&ctx->rs);
144
#endif
145
}
146
147
mbedtls_ecp_group_id mbedtls_ecdh_get_grp_id(mbedtls_ecdh_context *ctx)
148
{
149
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
150
return ctx->MBEDTLS_PRIVATE(grp).id;
151
#else
152
return ctx->MBEDTLS_PRIVATE(grp_id);
153
#endif
154
}
155
156
/*
157
* Initialize context
158
*/
159
void mbedtls_ecdh_init(mbedtls_ecdh_context *ctx)
160
{
161
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
162
ecdh_init_internal(ctx);
163
mbedtls_ecp_point_init(&ctx->Vi);
164
mbedtls_ecp_point_init(&ctx->Vf);
165
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
ctx->point_format = MBEDTLS_ECP_PF_UNCOMPRESSED;
172
#if defined(MBEDTLS_ECP_RESTARTABLE)
173
ctx->restart_enabled = 0;
174
#endif
175
}
176
177
static int ecdh_setup_internal(mbedtls_ecdh_context_mbed *ctx,
178
mbedtls_ecp_group_id grp_id)
179
{
180
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
181
182
ret = mbedtls_ecp_group_load(&ctx->grp, grp_id);
183
if (ret != 0) {
184
return MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE;
185
}
186
187
return 0;
188
}
189
190
/*
191
* Setup context
192
*/
193
int mbedtls_ecdh_setup(mbedtls_ecdh_context *ctx, mbedtls_ecp_group_id grp_id)
194
{
195
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
196
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
}
215
216
static void ecdh_free_internal(mbedtls_ecdh_context_mbed *ctx)
217
{
218
mbedtls_ecp_group_free(&ctx->grp);
219
mbedtls_mpi_free(&ctx->d);
220
mbedtls_ecp_point_free(&ctx->Q);
221
mbedtls_ecp_point_free(&ctx->Qp);
222
mbedtls_mpi_free(&ctx->z);
223
224
#if defined(MBEDTLS_ECP_RESTARTABLE)
225
mbedtls_ecp_restart_free(&ctx->rs);
226
#endif
227
}
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
{
235
ctx->restart_enabled = 1;
236
}
237
#endif
238
239
/*
240
* Free context
241
*/
242
void mbedtls_ecdh_free(mbedtls_ecdh_context *ctx)
243
{
244
if (ctx == NULL) {
245
return;
246
}
247
248
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
249
mbedtls_ecp_point_free(&ctx->Vi);
250
mbedtls_ecp_point_free(&ctx->Vf);
251
mbedtls_mpi_free(&ctx->_d);
252
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
}
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
{
282
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
283
size_t grp_len, pt_len;
284
#if defined(MBEDTLS_ECP_RESTARTABLE)
285
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
286
#endif
287
288
if (ctx->grp.pbits == 0) {
289
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
290
}
291
292
#if defined(MBEDTLS_ECP_RESTARTABLE)
293
if (restart_enabled) {
294
rs_ctx = &ctx->rs;
295
}
296
#else
297
(void) restart_enabled;
298
#endif
299
300
301
#if defined(MBEDTLS_ECP_RESTARTABLE)
302
if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
303
f_rng, p_rng, rs_ctx)) != 0) {
304
return ret;
305
}
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
if ((ret = mbedtls_ecp_tls_write_group(&ctx->grp, &grp_len, buf,
314
blen)) != 0) {
315
return ret;
316
}
317
318
buf += grp_len;
319
blen -= grp_len;
320
321
if ((ret = mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format,
322
&pt_len, buf, blen)) != 0) {
323
return ret;
324
}
325
326
*olen = grp_len + pt_len;
327
return 0;
328
}
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
{
342
int restart_enabled = 0;
343
#if defined(MBEDTLS_ECP_RESTARTABLE)
344
restart_enabled = ctx->restart_enabled;
345
#else
346
(void) restart_enabled;
347
#endif
348
349
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
350
return ecdh_make_params_internal(ctx, olen, ctx->point_format, buf, blen,
351
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
}
369
370
static int ecdh_read_params_internal(mbedtls_ecdh_context_mbed *ctx,
371
const unsigned char **buf,
372
const unsigned char *end)
373
{
374
return mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, buf,
375
(size_t) (end - *buf));
376
}
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
{
389
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
390
mbedtls_ecp_group_id grp_id;
391
if ((ret = mbedtls_ecp_tls_read_group_id(&grp_id, buf, (size_t) (end - *buf)))
392
!= 0) {
393
return ret;
394
}
395
396
if ((ret = mbedtls_ecdh_setup(ctx, grp_id)) != 0) {
397
return ret;
398
}
399
400
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
401
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
}
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
{
422
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
423
424
/* If it's not our key, just import the public part as Qp */
425
if (side == MBEDTLS_ECDH_THEIRS) {
426
return mbedtls_ecp_copy(&ctx->Qp, &key->Q);
427
}
428
429
/* Our key: import public (as Q) and private parts */
430
if (side != MBEDTLS_ECDH_OURS) {
431
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
432
}
433
434
if ((ret = mbedtls_ecp_copy(&ctx->Q, &key->Q)) != 0 ||
435
(ret = mbedtls_mpi_copy(&ctx->d, &key->d)) != 0) {
436
return ret;
437
}
438
439
return 0;
440
}
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
{
449
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
450
if (side != MBEDTLS_ECDH_OURS && side != MBEDTLS_ECDH_THEIRS) {
451
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
452
}
453
454
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
if ((ret = mbedtls_ecdh_setup(ctx, key->grp.id)) != 0) {
458
return ret;
459
}
460
} 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
if (mbedtls_ecdh_grp_id(ctx) != key->grp.id) {
465
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
466
}
467
}
468
469
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
470
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
}
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
{
501
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
502
#if defined(MBEDTLS_ECP_RESTARTABLE)
503
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
504
#endif
505
506
if (ctx->grp.pbits == 0) {
507
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
508
}
509
510
#if defined(MBEDTLS_ECP_RESTARTABLE)
511
if (restart_enabled) {
512
rs_ctx = &ctx->rs;
513
}
514
#else
515
(void) restart_enabled;
516
#endif
517
518
#if defined(MBEDTLS_ECP_RESTARTABLE)
519
if ((ret = ecdh_gen_public_restartable(&ctx->grp, &ctx->d, &ctx->Q,
520
f_rng, p_rng, rs_ctx)) != 0) {
521
return ret;
522
}
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
return mbedtls_ecp_tls_write_point(&ctx->grp, &ctx->Q, point_format, olen,
531
buf, blen);
532
}
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
{
542
int restart_enabled = 0;
543
#if defined(MBEDTLS_ECP_RESTARTABLE)
544
restart_enabled = ctx->restart_enabled;
545
#endif
546
547
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
548
return ecdh_make_public_internal(ctx, olen, ctx->point_format, buf, blen,
549
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
}
567
568
static int ecdh_read_public_internal(mbedtls_ecdh_context_mbed *ctx,
569
const unsigned char *buf, size_t blen)
570
{
571
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
572
const unsigned char *p = buf;
573
574
if ((ret = mbedtls_ecp_tls_read_point(&ctx->grp, &ctx->Qp, &p,
575
blen)) != 0) {
576
return ret;
577
}
578
579
if ((size_t) (p - buf) != blen) {
580
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
581
}
582
583
return 0;
584
}
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
{
592
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
593
return ecdh_read_public_internal(ctx, buf, blen);
594
#else
595
switch (ctx->var) {
596
#if defined(MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED)
597
case MBEDTLS_ECDH_VARIANT_EVEREST:
598
return mbedtls_everest_read_public(&ctx->ctx.everest_ecdh,
599
buf, blen);
600
#endif
601
case MBEDTLS_ECDH_VARIANT_MBEDTLS_2_0:
602
return ecdh_read_public_internal(&ctx->ctx.mbed_ecdh,
603
buf, blen);
604
default:
605
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
606
}
607
#endif
608
}
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
{
619
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
620
#if defined(MBEDTLS_ECP_RESTARTABLE)
621
mbedtls_ecp_restart_ctx *rs_ctx = NULL;
622
#endif
623
624
if (ctx == NULL || ctx->grp.pbits == 0) {
625
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
626
}
627
628
#if defined(MBEDTLS_ECP_RESTARTABLE)
629
if (restart_enabled) {
630
rs_ctx = &ctx->rs;
631
}
632
#else
633
(void) restart_enabled;
634
#endif
635
636
#if defined(MBEDTLS_ECP_RESTARTABLE)
637
if ((ret = ecdh_compute_shared_restartable(&ctx->grp, &ctx->z, &ctx->Qp,
638
&ctx->d, f_rng, p_rng,
639
rs_ctx)) != 0) {
640
return ret;
641
}
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
if (mbedtls_mpi_size(&ctx->z) > blen) {
650
return MBEDTLS_ERR_ECP_BAD_INPUT_DATA;
651
}
652
653
*olen = ctx->grp.pbits / 8 + ((ctx->grp.pbits % 8) != 0);
654
655
if (mbedtls_ecp_get_type(&ctx->grp) == MBEDTLS_ECP_TYPE_MONTGOMERY) {
656
return mbedtls_mpi_write_binary_le(&ctx->z, buf, *olen);
657
}
658
659
return mbedtls_mpi_write_binary(&ctx->z, buf, *olen);
660
}
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
{
670
int restart_enabled = 0;
671
#if defined(MBEDTLS_ECP_RESTARTABLE)
672
restart_enabled = ctx->restart_enabled;
673
#endif
674
675
#if defined(MBEDTLS_ECDH_LEGACY_CONTEXT)
676
return ecdh_calc_secret_internal(ctx, olen, buf, blen, f_rng, p_rng,
677
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
}
694
#endif /* MBEDTLS_ECDH_C */
695
696