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