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