Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/thirdparty/mbedtls/library/dhm.c
9903 views
1
/*
2
* Diffie-Hellman-Merkle key exchange
3
*
4
* Copyright The Mbed TLS Contributors
5
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
6
*/
7
/*
8
* The following sources were referenced in the design of this implementation
9
* of the Diffie-Hellman-Merkle algorithm:
10
*
11
* [1] Handbook of Applied Cryptography - 1997, Chapter 12
12
* Menezes, van Oorschot and Vanstone
13
*
14
*/
15
16
#include "common.h"
17
18
#if defined(MBEDTLS_DHM_C)
19
20
#include "mbedtls/dhm.h"
21
#include "mbedtls/platform_util.h"
22
#include "mbedtls/error.h"
23
24
#include <string.h>
25
26
#if defined(MBEDTLS_PEM_PARSE_C)
27
#include "mbedtls/pem.h"
28
#endif
29
30
#if defined(MBEDTLS_ASN1_PARSE_C)
31
#include "mbedtls/asn1.h"
32
#endif
33
34
#include "mbedtls/platform.h"
35
36
#if !defined(MBEDTLS_DHM_ALT)
37
38
/*
39
* helper to validate the mbedtls_mpi size and import it
40
*/
41
static int dhm_read_bignum(mbedtls_mpi *X,
42
unsigned char **p,
43
const unsigned char *end)
44
{
45
int ret, n;
46
47
if (end - *p < 2) {
48
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
49
}
50
51
n = MBEDTLS_GET_UINT16_BE(*p, 0);
52
(*p) += 2;
53
54
if ((size_t) (end - *p) < (size_t) n) {
55
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
56
}
57
58
if ((ret = mbedtls_mpi_read_binary(X, *p, n)) != 0) {
59
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED, ret);
60
}
61
62
(*p) += n;
63
64
return 0;
65
}
66
67
/*
68
* Verify sanity of parameter with regards to P
69
*
70
* Parameter should be: 2 <= public_param <= P - 2
71
*
72
* This means that we need to return an error if
73
* public_param < 2 or public_param > P-2
74
*
75
* For more information on the attack, see:
76
* http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
77
* http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
78
*/
79
static int dhm_check_range(const mbedtls_mpi *param, const mbedtls_mpi *P)
80
{
81
mbedtls_mpi U;
82
int ret = 0;
83
84
mbedtls_mpi_init(&U);
85
86
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&U, P, 2));
87
88
if (mbedtls_mpi_cmp_int(param, 2) < 0 ||
89
mbedtls_mpi_cmp_mpi(param, &U) > 0) {
90
ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
91
}
92
93
cleanup:
94
mbedtls_mpi_free(&U);
95
return ret;
96
}
97
98
void mbedtls_dhm_init(mbedtls_dhm_context *ctx)
99
{
100
memset(ctx, 0, sizeof(mbedtls_dhm_context));
101
}
102
103
size_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx)
104
{
105
return mbedtls_mpi_bitlen(&ctx->P);
106
}
107
108
size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx)
109
{
110
return mbedtls_mpi_size(&ctx->P);
111
}
112
113
int mbedtls_dhm_get_value(const mbedtls_dhm_context *ctx,
114
mbedtls_dhm_parameter param,
115
mbedtls_mpi *dest)
116
{
117
const mbedtls_mpi *src = NULL;
118
switch (param) {
119
case MBEDTLS_DHM_PARAM_P:
120
src = &ctx->P;
121
break;
122
case MBEDTLS_DHM_PARAM_G:
123
src = &ctx->G;
124
break;
125
case MBEDTLS_DHM_PARAM_X:
126
src = &ctx->X;
127
break;
128
case MBEDTLS_DHM_PARAM_GX:
129
src = &ctx->GX;
130
break;
131
case MBEDTLS_DHM_PARAM_GY:
132
src = &ctx->GY;
133
break;
134
case MBEDTLS_DHM_PARAM_K:
135
src = &ctx->K;
136
break;
137
default:
138
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
139
}
140
return mbedtls_mpi_copy(dest, src);
141
}
142
143
/*
144
* Parse the ServerKeyExchange parameters
145
*/
146
int mbedtls_dhm_read_params(mbedtls_dhm_context *ctx,
147
unsigned char **p,
148
const unsigned char *end)
149
{
150
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
151
152
if ((ret = dhm_read_bignum(&ctx->P, p, end)) != 0 ||
153
(ret = dhm_read_bignum(&ctx->G, p, end)) != 0 ||
154
(ret = dhm_read_bignum(&ctx->GY, p, end)) != 0) {
155
return ret;
156
}
157
158
if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
159
return ret;
160
}
161
162
return 0;
163
}
164
165
/*
166
* Pick a random R in the range [2, M-2] for blinding or key generation.
167
*/
168
static int dhm_random_below(mbedtls_mpi *R, const mbedtls_mpi *M,
169
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
170
{
171
int ret;
172
173
MBEDTLS_MPI_CHK(mbedtls_mpi_random(R, 3, M, f_rng, p_rng));
174
MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(R, R, 1));
175
176
cleanup:
177
return ret;
178
}
179
180
static int dhm_make_common(mbedtls_dhm_context *ctx, int x_size,
181
int (*f_rng)(void *, unsigned char *, size_t),
182
void *p_rng)
183
{
184
int ret = 0;
185
186
if (mbedtls_mpi_cmp_int(&ctx->P, 0) == 0) {
187
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
188
}
189
if (x_size < 0) {
190
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
191
}
192
193
if ((unsigned) x_size < mbedtls_mpi_size(&ctx->P)) {
194
MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx->X, x_size, f_rng, p_rng));
195
} else {
196
/* Generate X as large as possible ( <= P - 2 ) */
197
ret = dhm_random_below(&ctx->X, &ctx->P, f_rng, p_rng);
198
if (ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) {
199
return MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED;
200
}
201
if (ret != 0) {
202
return ret;
203
}
204
}
205
206
/*
207
* Calculate GX = G^X mod P
208
*/
209
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->GX, &ctx->G, &ctx->X,
210
&ctx->P, &ctx->RP));
211
212
if ((ret = dhm_check_range(&ctx->GX, &ctx->P)) != 0) {
213
return ret;
214
}
215
216
cleanup:
217
return ret;
218
}
219
220
/*
221
* Setup and write the ServerKeyExchange parameters
222
*/
223
int mbedtls_dhm_make_params(mbedtls_dhm_context *ctx, int x_size,
224
unsigned char *output, size_t *olen,
225
int (*f_rng)(void *, unsigned char *, size_t),
226
void *p_rng)
227
{
228
int ret;
229
size_t n1, n2, n3;
230
unsigned char *p;
231
232
ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
233
if (ret != 0) {
234
goto cleanup;
235
}
236
237
/*
238
* Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
239
* not required". We omit leading zeros for compactness.
240
*/
241
#define DHM_MPI_EXPORT(X, n) \
242
do { \
243
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary((X), \
244
p + 2, \
245
(n))); \
246
*p++ = MBEDTLS_BYTE_1(n); \
247
*p++ = MBEDTLS_BYTE_0(n); \
248
p += (n); \
249
} while (0)
250
251
n1 = mbedtls_mpi_size(&ctx->P);
252
n2 = mbedtls_mpi_size(&ctx->G);
253
n3 = mbedtls_mpi_size(&ctx->GX);
254
255
p = output;
256
DHM_MPI_EXPORT(&ctx->P, n1);
257
DHM_MPI_EXPORT(&ctx->G, n2);
258
DHM_MPI_EXPORT(&ctx->GX, n3);
259
260
*olen = (size_t) (p - output);
261
262
cleanup:
263
if (ret != 0 && ret > -128) {
264
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED, ret);
265
}
266
return ret;
267
}
268
269
/*
270
* Set prime modulus and generator
271
*/
272
int mbedtls_dhm_set_group(mbedtls_dhm_context *ctx,
273
const mbedtls_mpi *P,
274
const mbedtls_mpi *G)
275
{
276
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
277
278
if ((ret = mbedtls_mpi_copy(&ctx->P, P)) != 0 ||
279
(ret = mbedtls_mpi_copy(&ctx->G, G)) != 0) {
280
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_SET_GROUP_FAILED, ret);
281
}
282
283
return 0;
284
}
285
286
/*
287
* Import the peer's public value G^Y
288
*/
289
int mbedtls_dhm_read_public(mbedtls_dhm_context *ctx,
290
const unsigned char *input, size_t ilen)
291
{
292
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
293
294
if (ilen < 1 || ilen > mbedtls_dhm_get_len(ctx)) {
295
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
296
}
297
298
if ((ret = mbedtls_mpi_read_binary(&ctx->GY, input, ilen)) != 0) {
299
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED, ret);
300
}
301
302
return 0;
303
}
304
305
/*
306
* Create own private value X and export G^X
307
*/
308
int mbedtls_dhm_make_public(mbedtls_dhm_context *ctx, int x_size,
309
unsigned char *output, size_t olen,
310
int (*f_rng)(void *, unsigned char *, size_t),
311
void *p_rng)
312
{
313
int ret;
314
315
if (olen < 1 || olen > mbedtls_dhm_get_len(ctx)) {
316
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
317
}
318
319
ret = dhm_make_common(ctx, x_size, f_rng, p_rng);
320
if (ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) {
321
return MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED;
322
}
323
if (ret != 0) {
324
goto cleanup;
325
}
326
327
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->GX, output, olen));
328
329
cleanup:
330
if (ret != 0 && ret > -128) {
331
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED, ret);
332
}
333
return ret;
334
}
335
336
337
/*
338
* Use the blinding method and optimisation suggested in section 10 of:
339
* KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
340
* DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
341
* Berlin Heidelberg, 1996. p. 104-113.
342
*/
343
static int dhm_update_blinding(mbedtls_dhm_context *ctx,
344
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng)
345
{
346
int ret;
347
mbedtls_mpi R;
348
349
mbedtls_mpi_init(&R);
350
351
/*
352
* Don't use any blinding the first time a particular X is used,
353
* but remember it to use blinding next time.
354
*/
355
if (mbedtls_mpi_cmp_mpi(&ctx->X, &ctx->pX) != 0) {
356
MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&ctx->pX, &ctx->X));
357
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vi, 1));
358
MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx->Vf, 1));
359
360
return 0;
361
}
362
363
/*
364
* Ok, we need blinding. Can we re-use existing values?
365
* If yes, just update them by squaring them.
366
*/
367
if (mbedtls_mpi_cmp_int(&ctx->Vi, 1) != 0) {
368
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vi, &ctx->Vi, &ctx->Vi));
369
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vi, &ctx->Vi, &ctx->P));
370
371
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &ctx->Vf));
372
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
373
374
return 0;
375
}
376
377
/*
378
* We need to generate blinding values from scratch
379
*/
380
381
/* Vi = random( 2, P-2 ) */
382
MBEDTLS_MPI_CHK(dhm_random_below(&ctx->Vi, &ctx->P, f_rng, p_rng));
383
384
/* Vf = Vi^-X mod P
385
* First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
386
* then elevate to the Xth power. */
387
MBEDTLS_MPI_CHK(dhm_random_below(&R, &ctx->P, f_rng, p_rng));
388
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vi, &R));
389
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
390
MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&ctx->Vf, &ctx->Vf, &ctx->P));
391
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->Vf, &ctx->Vf, &R));
392
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->Vf, &ctx->Vf, &ctx->P));
393
394
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP));
395
396
cleanup:
397
mbedtls_mpi_free(&R);
398
399
return ret;
400
}
401
402
/*
403
* Derive and export the shared secret (G^Y)^X mod P
404
*/
405
int mbedtls_dhm_calc_secret(mbedtls_dhm_context *ctx,
406
unsigned char *output, size_t output_size, size_t *olen,
407
int (*f_rng)(void *, unsigned char *, size_t),
408
void *p_rng)
409
{
410
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
411
mbedtls_mpi GYb;
412
413
if (f_rng == NULL) {
414
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
415
}
416
417
if (output_size < mbedtls_dhm_get_len(ctx)) {
418
return MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
419
}
420
421
if ((ret = dhm_check_range(&ctx->GY, &ctx->P)) != 0) {
422
return ret;
423
}
424
425
mbedtls_mpi_init(&GYb);
426
427
/* Blind peer's value */
428
MBEDTLS_MPI_CHK(dhm_update_blinding(ctx, f_rng, p_rng));
429
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&GYb, &ctx->GY, &ctx->Vi));
430
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&GYb, &GYb, &ctx->P));
431
432
/* Do modular exponentiation */
433
MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx->K, &GYb, &ctx->X,
434
&ctx->P, &ctx->RP));
435
436
/* Unblind secret value */
437
MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx->K, &ctx->K, &ctx->Vf));
438
MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx->K, &ctx->K, &ctx->P));
439
440
/* Output the secret without any leading zero byte. This is mandatory
441
* for TLS per RFC 5246 §8.1.2. */
442
*olen = mbedtls_mpi_size(&ctx->K);
443
MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx->K, output, *olen));
444
445
cleanup:
446
mbedtls_mpi_free(&GYb);
447
448
if (ret != 0) {
449
return MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED, ret);
450
}
451
452
return 0;
453
}
454
455
/*
456
* Free the components of a DHM key
457
*/
458
void mbedtls_dhm_free(mbedtls_dhm_context *ctx)
459
{
460
if (ctx == NULL) {
461
return;
462
}
463
464
mbedtls_mpi_free(&ctx->pX);
465
mbedtls_mpi_free(&ctx->Vf);
466
mbedtls_mpi_free(&ctx->Vi);
467
mbedtls_mpi_free(&ctx->RP);
468
mbedtls_mpi_free(&ctx->K);
469
mbedtls_mpi_free(&ctx->GY);
470
mbedtls_mpi_free(&ctx->GX);
471
mbedtls_mpi_free(&ctx->X);
472
mbedtls_mpi_free(&ctx->G);
473
mbedtls_mpi_free(&ctx->P);
474
475
mbedtls_platform_zeroize(ctx, sizeof(mbedtls_dhm_context));
476
}
477
478
#if defined(MBEDTLS_ASN1_PARSE_C)
479
/*
480
* Parse DHM parameters
481
*/
482
int mbedtls_dhm_parse_dhm(mbedtls_dhm_context *dhm, const unsigned char *dhmin,
483
size_t dhminlen)
484
{
485
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
486
size_t len;
487
unsigned char *p, *end;
488
#if defined(MBEDTLS_PEM_PARSE_C)
489
mbedtls_pem_context pem;
490
#endif /* MBEDTLS_PEM_PARSE_C */
491
492
#if defined(MBEDTLS_PEM_PARSE_C)
493
mbedtls_pem_init(&pem);
494
495
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
496
if (dhminlen == 0 || dhmin[dhminlen - 1] != '\0') {
497
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
498
} else {
499
ret = mbedtls_pem_read_buffer(&pem,
500
"-----BEGIN DH PARAMETERS-----",
501
"-----END DH PARAMETERS-----",
502
dhmin, NULL, 0, &dhminlen);
503
}
504
505
if (ret == 0) {
506
/*
507
* Was PEM encoded
508
*/
509
dhminlen = pem.buflen;
510
} else if (ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) {
511
goto exit;
512
}
513
514
p = (ret == 0) ? pem.buf : (unsigned char *) dhmin;
515
#else
516
p = (unsigned char *) dhmin;
517
#endif /* MBEDTLS_PEM_PARSE_C */
518
end = p + dhminlen;
519
520
/*
521
* DHParams ::= SEQUENCE {
522
* prime INTEGER, -- P
523
* generator INTEGER, -- g
524
* privateValueLength INTEGER OPTIONAL
525
* }
526
*/
527
if ((ret = mbedtls_asn1_get_tag(&p, end, &len,
528
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) != 0) {
529
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
530
goto exit;
531
}
532
533
end = p + len;
534
535
if ((ret = mbedtls_asn1_get_mpi(&p, end, &dhm->P)) != 0 ||
536
(ret = mbedtls_asn1_get_mpi(&p, end, &dhm->G)) != 0) {
537
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
538
goto exit;
539
}
540
541
if (p != end) {
542
/* This might be the optional privateValueLength.
543
* If so, we can cleanly discard it */
544
mbedtls_mpi rec;
545
mbedtls_mpi_init(&rec);
546
ret = mbedtls_asn1_get_mpi(&p, end, &rec);
547
mbedtls_mpi_free(&rec);
548
if (ret != 0) {
549
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT, ret);
550
goto exit;
551
}
552
if (p != end) {
553
ret = MBEDTLS_ERROR_ADD(MBEDTLS_ERR_DHM_INVALID_FORMAT,
554
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH);
555
goto exit;
556
}
557
}
558
559
ret = 0;
560
561
exit:
562
#if defined(MBEDTLS_PEM_PARSE_C)
563
mbedtls_pem_free(&pem);
564
#endif
565
if (ret != 0) {
566
mbedtls_dhm_free(dhm);
567
}
568
569
return ret;
570
}
571
572
#if defined(MBEDTLS_FS_IO)
573
/*
574
* Load all data from a file into a given buffer.
575
*
576
* The file is expected to contain either PEM or DER encoded data.
577
* A terminating null byte is always appended. It is included in the announced
578
* length only if the data looks like it is PEM encoded.
579
*/
580
static int load_file(const char *path, unsigned char **buf, size_t *n)
581
{
582
FILE *f;
583
long size;
584
585
if ((f = fopen(path, "rb")) == NULL) {
586
return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
587
}
588
/* The data loaded here is public, so don't bother disabling buffering. */
589
590
fseek(f, 0, SEEK_END);
591
if ((size = ftell(f)) == -1) {
592
fclose(f);
593
return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
594
}
595
fseek(f, 0, SEEK_SET);
596
597
*n = (size_t) size;
598
599
if (*n + 1 == 0 ||
600
(*buf = mbedtls_calloc(1, *n + 1)) == NULL) {
601
fclose(f);
602
return MBEDTLS_ERR_DHM_ALLOC_FAILED;
603
}
604
605
if (fread(*buf, 1, *n, f) != *n) {
606
fclose(f);
607
608
mbedtls_zeroize_and_free(*buf, *n + 1);
609
610
return MBEDTLS_ERR_DHM_FILE_IO_ERROR;
611
}
612
613
fclose(f);
614
615
(*buf)[*n] = '\0';
616
617
if (strstr((const char *) *buf, "-----BEGIN ") != NULL) {
618
++*n;
619
}
620
621
return 0;
622
}
623
624
/*
625
* Load and parse DHM parameters
626
*/
627
int mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context *dhm, const char *path)
628
{
629
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
630
size_t n;
631
unsigned char *buf;
632
633
if ((ret = load_file(path, &buf, &n)) != 0) {
634
return ret;
635
}
636
637
ret = mbedtls_dhm_parse_dhm(dhm, buf, n);
638
639
mbedtls_zeroize_and_free(buf, n);
640
641
return ret;
642
}
643
#endif /* MBEDTLS_FS_IO */
644
#endif /* MBEDTLS_ASN1_PARSE_C */
645
#endif /* MBEDTLS_DHM_ALT */
646
647
#if defined(MBEDTLS_SELF_TEST)
648
649
#if defined(MBEDTLS_PEM_PARSE_C)
650
static const char mbedtls_test_dhm_params[] =
651
"-----BEGIN DH PARAMETERS-----\r\n"
652
"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
653
"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
654
"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
655
"-----END DH PARAMETERS-----\r\n";
656
#else /* MBEDTLS_PEM_PARSE_C */
657
static const char mbedtls_test_dhm_params[] = {
658
0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
659
0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
660
0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
661
0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
662
0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
663
0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
664
0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
665
0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
666
0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
667
0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
668
0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
669
0x49, 0x75, 0xb3, 0x02, 0x01, 0x02
670
};
671
#endif /* MBEDTLS_PEM_PARSE_C */
672
673
static const size_t mbedtls_test_dhm_params_len = sizeof(mbedtls_test_dhm_params);
674
675
/*
676
* Checkup routine
677
*/
678
int mbedtls_dhm_self_test(int verbose)
679
{
680
int ret = MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED;
681
mbedtls_dhm_context dhm;
682
683
mbedtls_dhm_init(&dhm);
684
685
if (verbose != 0) {
686
mbedtls_printf(" DHM parameter load: ");
687
}
688
689
if ((ret = mbedtls_dhm_parse_dhm(&dhm,
690
(const unsigned char *) mbedtls_test_dhm_params,
691
mbedtls_test_dhm_params_len)) != 0) {
692
if (verbose != 0) {
693
mbedtls_printf("failed\n");
694
}
695
696
ret = 1;
697
goto exit;
698
}
699
700
if (verbose != 0) {
701
mbedtls_printf("passed\n\n");
702
}
703
704
exit:
705
mbedtls_dhm_free(&dhm);
706
707
return ret;
708
}
709
710
#endif /* MBEDTLS_SELF_TEST */
711
712
#endif /* MBEDTLS_DHM_C */
713
714