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 */ 41static 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 */ 79static 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 93cleanup: 94 mbedtls_mpi_free(&U); 95 return ret; 96} 97 98void mbedtls_dhm_init(mbedtls_dhm_context *ctx) 99{ 100 memset(ctx, 0, sizeof(mbedtls_dhm_context)); 101} 102 103size_t mbedtls_dhm_get_bitlen(const mbedtls_dhm_context *ctx) 104{ 105 return mbedtls_mpi_bitlen(&ctx->P); 106} 107 108size_t mbedtls_dhm_get_len(const mbedtls_dhm_context *ctx) 109{ 110 return mbedtls_mpi_size(&ctx->P); 111} 112 113int 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 */ 146int 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 */ 168static 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 176cleanup: 177 return ret; 178} 179 180static 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 216cleanup: 217 return ret; 218} 219 220/* 221 * Setup and write the ServerKeyExchange parameters 222 */ 223int 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 262cleanup: 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 */ 272int 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 */ 289int 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 */ 308int 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 329cleanup: 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 */ 343static 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 396cleanup: 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 */ 405int 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 445cleanup: 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 */ 458void 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 */ 482int 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 561exit: 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 */ 580static 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 */ 627int 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) 650static 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 */ 657static 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 673static const size_t mbedtls_test_dhm_params_len = sizeof(mbedtls_test_dhm_params); 674 675/* 676 * Checkup routine 677 */ 678int 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 704exit: 705 mbedtls_dhm_free(&dhm); 706 707 return ret; 708} 709 710#endif /* MBEDTLS_SELF_TEST */ 711 712#endif /* MBEDTLS_DHM_C */ 713