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