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