1 /* 2 * Diffie-Hellman-Merkle key exchange 3 * 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 5 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later 6 * 7 * This file is provided under the Apache License 2.0, or the 8 * GNU General Public License v2.0 or later. 9 * 10 * ********** 11 * Apache License 2.0: 12 * 13 * Licensed under the Apache License, Version 2.0 (the "License"); you may 14 * not use this file except in compliance with the License. 15 * You may obtain a copy of the License at 16 * 17 * http://www.apache.org/licenses/LICENSE-2.0 18 * 19 * Unless required by applicable law or agreed to in writing, software 20 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 21 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 22 * See the License for the specific language governing permissions and 23 * limitations under the License. 24 * 25 * ********** 26 * 27 * ********** 28 * GNU General Public License v2.0 or later: 29 * 30 * This program is free software; you can redistribute it and/or modify 31 * it under the terms of the GNU General Public License as published by 32 * the Free Software Foundation; either version 2 of the License, or 33 * (at your option) any later version. 34 * 35 * This program is distributed in the hope that it will be useful, 36 * but WITHOUT ANY WARRANTY; without even the implied warranty of 37 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 38 * GNU General Public License for more details. 39 * 40 * You should have received a copy of the GNU General Public License along 41 * with this program; if not, write to the Free Software Foundation, Inc., 42 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 43 * 44 * ********** 45 * 46 * This file is part of mbed TLS (https://tls.mbed.org) 47 */ 48 /* 49 * The following sources were referenced in the design of this implementation 50 * of the Diffie-Hellman-Merkle algorithm: 51 * 52 * [1] Handbook of Applied Cryptography - 1997, Chapter 12 53 * Menezes, van Oorschot and Vanstone 54 * 55 */ 56 57 #if !defined(MBEDTLS_CONFIG_FILE) 58 #include "mbedtls/config.h" 59 #else 60 #include MBEDTLS_CONFIG_FILE 61 #endif 62 63 #if defined(MBEDTLS_DHM_C) 64 65 #include "mbedtls/dhm.h" 66 67 #include <string.h> 68 69 #if defined(MBEDTLS_PEM_PARSE_C) 70 #include "mbedtls/pem.h" 71 #endif 72 73 #if defined(MBEDTLS_ASN1_PARSE_C) 74 #include "mbedtls/asn1.h" 75 #endif 76 77 #if defined(MBEDTLS_PLATFORM_C) 78 #include "mbedtls/platform.h" 79 #else 80 #include <stdlib.h> 81 #include <stdio.h> 82 #define mbedtls_printf printf 83 #define mbedtls_calloc calloc 84 #define mbedtls_free free 85 #endif 86 87 #if !defined(MBEDTLS_DHM_ALT) 88 /* Implementation that should never be optimized out by the compiler */ 89 static void mbedtls_zeroize( void *v, size_t n ) { 90 volatile unsigned char *p = v; while( n-- ) *p++ = 0; 91 } 92 93 /* 94 * helper to validate the mbedtls_mpi size and import it 95 */ 96 static int dhm_read_bignum( mbedtls_mpi *X, 97 unsigned char **p, 98 const unsigned char *end ) 99 { 100 int ret, n; 101 102 if( end - *p < 2 ) 103 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 104 105 n = ( (*p)[0] << 8 ) | (*p)[1]; 106 (*p) += 2; 107 108 if( (int)( end - *p ) < n ) 109 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 110 111 if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 ) 112 return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret ); 113 114 (*p) += n; 115 116 return( 0 ); 117 } 118 119 /* 120 * Verify sanity of parameter with regards to P 121 * 122 * Parameter should be: 2 <= public_param <= P - 2 123 * 124 * This means that we need to return an error if 125 * public_param < 2 or public_param > P-2 126 * 127 * For more information on the attack, see: 128 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf 129 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 130 */ 131 static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P ) 132 { 133 mbedtls_mpi L, U; 134 int ret = 0; 135 136 mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U ); 137 138 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) ); 139 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) ); 140 141 if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 || 142 mbedtls_mpi_cmp_mpi( param, &U ) > 0 ) 143 { 144 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; 145 } 146 147 cleanup: 148 mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U ); 149 return( ret ); 150 } 151 152 void mbedtls_dhm_init( mbedtls_dhm_context *ctx ) 153 { 154 memset( ctx, 0, sizeof( mbedtls_dhm_context ) ); 155 } 156 157 /* 158 * Parse the ServerKeyExchange parameters 159 */ 160 int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, 161 unsigned char **p, 162 const unsigned char *end ) 163 { 164 int ret; 165 166 if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 || 167 ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 || 168 ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 ) 169 return( ret ); 170 171 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) 172 return( ret ); 173 174 ctx->len = mbedtls_mpi_size( &ctx->P ); 175 176 return( 0 ); 177 } 178 179 /* 180 * Setup and write the ServerKeyExchange parameters 181 */ 182 int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, 183 unsigned char *output, size_t *olen, 184 int (*f_rng)(void *, unsigned char *, size_t), 185 void *p_rng ) 186 { 187 int ret, count = 0; 188 size_t n1, n2, n3; 189 unsigned char *p; 190 191 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) 192 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 193 194 /* 195 * Generate X as large as possible ( < P ) 196 */ 197 do 198 { 199 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); 200 201 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) 202 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); 203 204 if( count++ > 10 ) 205 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ); 206 } 207 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); 208 209 /* 210 * Calculate GX = G^X mod P 211 */ 212 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, 213 &ctx->P , &ctx->RP ) ); 214 215 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) 216 return( ret ); 217 218 /* 219 * export P, G, GX 220 */ 221 #define DHM_MPI_EXPORT( X, n ) \ 222 do { \ 223 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \ 224 p + 2, \ 225 ( n ) ) ); \ 226 *p++ = (unsigned char)( ( n ) >> 8 ); \ 227 *p++ = (unsigned char)( ( n ) ); \ 228 p += ( n ); \ 229 } while( 0 ) 230 231 n1 = mbedtls_mpi_size( &ctx->P ); 232 n2 = mbedtls_mpi_size( &ctx->G ); 233 n3 = mbedtls_mpi_size( &ctx->GX ); 234 235 p = output; 236 DHM_MPI_EXPORT( &ctx->P , n1 ); 237 DHM_MPI_EXPORT( &ctx->G , n2 ); 238 DHM_MPI_EXPORT( &ctx->GX, n3 ); 239 240 *olen = p - output; 241 242 ctx->len = n1; 243 244 cleanup: 245 246 if( ret != 0 ) 247 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret ); 248 249 return( 0 ); 250 } 251 252 /* 253 * Set prime modulus and generator 254 */ 255 int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, 256 const mbedtls_mpi *P, 257 const mbedtls_mpi *G ) 258 { 259 int ret; 260 261 if( ctx == NULL || P == NULL || G == NULL ) 262 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 263 264 if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 || 265 ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 ) 266 { 267 return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret ); 268 } 269 270 ctx->len = mbedtls_mpi_size( &ctx->P ); 271 return( 0 ); 272 } 273 274 /* 275 * Import the peer's public value G^Y 276 */ 277 int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, 278 const unsigned char *input, size_t ilen ) 279 { 280 int ret; 281 282 if( ctx == NULL || ilen < 1 || ilen > ctx->len ) 283 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 284 285 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 ) 286 return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret ); 287 288 return( 0 ); 289 } 290 291 /* 292 * Create own private value X and export G^X 293 */ 294 int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, 295 unsigned char *output, size_t olen, 296 int (*f_rng)(void *, unsigned char *, size_t), 297 void *p_rng ) 298 { 299 int ret, count = 0; 300 301 if( ctx == NULL || olen < 1 || olen > ctx->len ) 302 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 303 304 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) 305 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 306 307 /* 308 * generate X and calculate GX = G^X mod P 309 */ 310 do 311 { 312 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); 313 314 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) 315 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); 316 317 if( count++ > 10 ) 318 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ); 319 } 320 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); 321 322 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, 323 &ctx->P , &ctx->RP ) ); 324 325 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) 326 return( ret ); 327 328 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) ); 329 330 cleanup: 331 332 if( ret != 0 ) 333 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret ); 334 335 return( 0 ); 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, count; 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 { 355 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) ); 356 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) ); 357 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) ); 358 359 return( 0 ); 360 } 361 362 /* 363 * Ok, we need blinding. Can we re-use existing values? 364 * If yes, just update them by squaring them. 365 */ 366 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ) 367 { 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-1 ) */ 382 count = 0; 383 do 384 { 385 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vi, mbedtls_mpi_size( &ctx->P ), f_rng, p_rng ) ); 386 387 while( mbedtls_mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 ) 388 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi, 1 ) ); 389 390 if( count++ > 10 ) 391 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); 392 } 393 while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) <= 0 ); 394 395 /* Vf = Vi^-X mod P */ 396 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) ); 397 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) ); 398 399 cleanup: 400 return( ret ); 401 } 402 403 /* 404 * Derive and export the shared secret (G^Y)^X mod P 405 */ 406 int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, 407 unsigned char *output, size_t output_size, size_t *olen, 408 int (*f_rng)(void *, unsigned char *, size_t), 409 void *p_rng ) 410 { 411 int ret; 412 mbedtls_mpi GYb; 413 414 if( ctx == NULL || output_size < ctx->len ) 415 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 416 417 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) 418 return( ret ); 419 420 mbedtls_mpi_init( &GYb ); 421 422 /* Blind peer's value */ 423 if( f_rng != NULL ) 424 { 425 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) ); 426 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) ); 427 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) ); 428 } 429 else 430 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) ); 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 if( f_rng != NULL ) 438 { 439 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) ); 440 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) ); 441 } 442 443 *olen = mbedtls_mpi_size( &ctx->K ); 444 445 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) ); 446 447 cleanup: 448 mbedtls_mpi_free( &GYb ); 449 450 if( ret != 0 ) 451 return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret ); 452 453 return( 0 ); 454 } 455 456 /* 457 * Free the components of a DHM key 458 */ 459 void mbedtls_dhm_free( mbedtls_dhm_context *ctx ) 460 { 461 mbedtls_mpi_free( &ctx->pX ); mbedtls_mpi_free( &ctx->Vf ); 462 mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->RP ); 463 mbedtls_mpi_free( &ctx->K ); mbedtls_mpi_free( &ctx->GY ); 464 mbedtls_mpi_free( &ctx->GX ); mbedtls_mpi_free( &ctx->X ); 465 mbedtls_mpi_free( &ctx->G ); mbedtls_mpi_free( &ctx->P ); 466 467 mbedtls_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; 478 size_t len; 479 unsigned char *p, *end; 480 #if defined(MBEDTLS_PEM_PARSE_C) 481 mbedtls_pem_context pem; 482 483 mbedtls_pem_init( &pem ); 484 485 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 486 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' ) 487 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 488 else 489 ret = mbedtls_pem_read_buffer( &pem, 490 "-----BEGIN DH PARAMETERS-----", 491 "-----END DH PARAMETERS-----", 492 dhmin, NULL, 0, &dhminlen ); 493 494 if( ret == 0 ) 495 { 496 /* 497 * Was PEM encoded 498 */ 499 dhminlen = pem.buflen; 500 } 501 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) 502 goto exit; 503 504 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin; 505 #else 506 p = (unsigned char *) dhmin; 507 #endif /* MBEDTLS_PEM_PARSE_C */ 508 end = p + dhminlen; 509 510 /* 511 * DHParams ::= SEQUENCE { 512 * prime INTEGER, -- P 513 * generator INTEGER, -- g 514 * privateValueLength INTEGER OPTIONAL 515 * } 516 */ 517 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 518 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 519 { 520 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; 521 goto exit; 522 } 523 524 end = p + len; 525 526 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 || 527 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 ) 528 { 529 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; 530 goto exit; 531 } 532 533 if( p != end ) 534 { 535 /* This might be the optional privateValueLength. 536 * If so, we can cleanly discard it */ 537 mbedtls_mpi rec; 538 mbedtls_mpi_init( &rec ); 539 ret = mbedtls_asn1_get_mpi( &p, end, &rec ); 540 mbedtls_mpi_free( &rec ); 541 if ( ret != 0 ) 542 { 543 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; 544 goto exit; 545 } 546 if ( p != end ) 547 { 548 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + 549 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; 550 goto exit; 551 } 552 } 553 554 ret = 0; 555 556 dhm->len = mbedtls_mpi_size( &dhm->P ); 557 558 exit: 559 #if defined(MBEDTLS_PEM_PARSE_C) 560 mbedtls_pem_free( &pem ); 561 #endif 562 if( ret != 0 ) 563 mbedtls_dhm_free( dhm ); 564 565 return( ret ); 566 } 567 568 #if defined(MBEDTLS_FS_IO) 569 /* 570 * Load all data from a file into a given buffer. 571 * 572 * The file is expected to contain either PEM or DER encoded data. 573 * A terminating null byte is always appended. It is included in the announced 574 * length only if the data looks like it is PEM encoded. 575 */ 576 static int load_file( const char *path, unsigned char **buf, size_t *n ) 577 { 578 FILE *f; 579 long size; 580 581 if( ( f = fopen( path, "rb" ) ) == NULL ) 582 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); 583 584 fseek( f, 0, SEEK_END ); 585 if( ( size = ftell( f ) ) == -1 ) 586 { 587 fclose( f ); 588 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); 589 } 590 fseek( f, 0, SEEK_SET ); 591 592 *n = (size_t) size; 593 594 if( *n + 1 == 0 || 595 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) 596 { 597 fclose( f ); 598 return( MBEDTLS_ERR_DHM_ALLOC_FAILED ); 599 } 600 601 if( fread( *buf, 1, *n, f ) != *n ) 602 { 603 fclose( f ); 604 605 mbedtls_zeroize( *buf, *n + 1 ); 606 mbedtls_free( *buf ); 607 608 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); 609 } 610 611 fclose( f ); 612 613 (*buf)[*n] = '\0'; 614 615 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) 616 ++*n; 617 618 return( 0 ); 619 } 620 621 /* 622 * Load and parse DHM parameters 623 */ 624 int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ) 625 { 626 int ret; 627 size_t n; 628 unsigned char *buf; 629 630 if( ( ret = load_file( path, &buf, &n ) ) != 0 ) 631 return( ret ); 632 633 ret = mbedtls_dhm_parse_dhm( dhm, buf, n ); 634 635 mbedtls_zeroize( buf, n ); 636 mbedtls_free( buf ); 637 638 return( ret ); 639 } 640 #endif /* MBEDTLS_FS_IO */ 641 #endif /* MBEDTLS_ASN1_PARSE_C */ 642 #endif /* MBEDTLS_DHM_ALT */ 643 644 #if defined(MBEDTLS_SELF_TEST) 645 646 static const char mbedtls_test_dhm_params[] = 647 "-----BEGIN DH PARAMETERS-----\r\n" 648 "MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n" 649 "1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n" 650 "9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n" 651 "-----END DH PARAMETERS-----\r\n"; 652 653 static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params ); 654 655 /* 656 * Checkup routine 657 */ 658 int mbedtls_dhm_self_test( int verbose ) 659 { 660 int ret; 661 mbedtls_dhm_context dhm; 662 663 mbedtls_dhm_init( &dhm ); 664 665 if( verbose != 0 ) 666 mbedtls_printf( " DHM parameter load: " ); 667 668 if( ( ret = mbedtls_dhm_parse_dhm( &dhm, 669 (const unsigned char *) mbedtls_test_dhm_params, 670 mbedtls_test_dhm_params_len ) ) != 0 ) 671 { 672 if( verbose != 0 ) 673 mbedtls_printf( "failed\n" ); 674 675 ret = 1; 676 goto exit; 677 } 678 679 if( verbose != 0 ) 680 mbedtls_printf( "passed\n\n" ); 681 682 exit: 683 mbedtls_dhm_free( &dhm ); 684 685 return( ret ); 686 } 687 688 #endif /* MBEDTLS_SELF_TEST */ 689 690 #endif /* MBEDTLS_DHM_C */ 691