1 /* 2 * Diffie-Hellman-Merkle key exchange 3 * 4 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 5 * SPDX-License-Identifier: GPL-2.0 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program; if not, write to the Free Software Foundation, Inc., 19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * This file is part of mbed TLS (https://tls.mbed.org) 22 */ 23 /* 24 * The following sources were referenced in the design of this implementation 25 * of the Diffie-Hellman-Merkle algorithm: 26 * 27 * [1] Handbook of Applied Cryptography - 1997, Chapter 12 28 * Menezes, van Oorschot and Vanstone 29 * 30 */ 31 32 #if !defined(MBEDTLS_CONFIG_FILE) 33 #include "mbedtls/config.h" 34 #else 35 #include MBEDTLS_CONFIG_FILE 36 #endif 37 38 #if defined(MBEDTLS_DHM_C) 39 40 #include "mbedtls/dhm.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 /* Implementation that should never be optimized out by the compiler */ 64 static void mbedtls_zeroize( void *v, size_t n ) { 65 volatile unsigned char *p = v; while( n-- ) *p++ = 0; 66 } 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 memset( ctx, 0, sizeof( mbedtls_dhm_context ) ); 130 } 131 132 /* 133 * Parse the ServerKeyExchange parameters 134 */ 135 int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, 136 unsigned char **p, 137 const unsigned char *end ) 138 { 139 int ret; 140 141 if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 || 142 ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 || 143 ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 ) 144 return( ret ); 145 146 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) 147 return( ret ); 148 149 ctx->len = mbedtls_mpi_size( &ctx->P ); 150 151 return( 0 ); 152 } 153 154 /* 155 * Setup and write the ServerKeyExchange parameters 156 */ 157 int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, 158 unsigned char *output, size_t *olen, 159 int (*f_rng)(void *, unsigned char *, size_t), 160 void *p_rng ) 161 { 162 int ret, count = 0; 163 size_t n1, n2, n3; 164 unsigned char *p; 165 166 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) 167 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 168 169 /* 170 * Generate X as large as possible ( < P ) 171 */ 172 do 173 { 174 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); 175 176 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) 177 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); 178 179 if( count++ > 10 ) 180 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ); 181 } 182 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); 183 184 /* 185 * Calculate GX = G^X mod P 186 */ 187 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, 188 &ctx->P , &ctx->RP ) ); 189 190 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) 191 return( ret ); 192 193 /* 194 * export P, G, GX 195 */ 196 #define DHM_MPI_EXPORT( X, n ) \ 197 do { \ 198 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \ 199 p + 2, \ 200 ( n ) ) ); \ 201 *p++ = (unsigned char)( ( n ) >> 8 ); \ 202 *p++ = (unsigned char)( ( n ) ); \ 203 p += ( n ); \ 204 } while( 0 ) 205 206 n1 = mbedtls_mpi_size( &ctx->P ); 207 n2 = mbedtls_mpi_size( &ctx->G ); 208 n3 = mbedtls_mpi_size( &ctx->GX ); 209 210 p = output; 211 DHM_MPI_EXPORT( &ctx->P , n1 ); 212 DHM_MPI_EXPORT( &ctx->G , n2 ); 213 DHM_MPI_EXPORT( &ctx->GX, n3 ); 214 215 *olen = p - output; 216 217 ctx->len = n1; 218 219 cleanup: 220 221 if( ret != 0 ) 222 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret ); 223 224 return( 0 ); 225 } 226 227 /* 228 * Set prime modulus and generator 229 */ 230 int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, 231 const mbedtls_mpi *P, 232 const mbedtls_mpi *G ) 233 { 234 int ret; 235 236 if( ctx == NULL || P == NULL || G == NULL ) 237 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 238 239 if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 || 240 ( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 ) 241 { 242 return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret ); 243 } 244 245 ctx->len = mbedtls_mpi_size( &ctx->P ); 246 return( 0 ); 247 } 248 249 /* 250 * Import the peer's public value G^Y 251 */ 252 int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, 253 const unsigned char *input, size_t ilen ) 254 { 255 int ret; 256 257 if( ctx == NULL || ilen < 1 || ilen > ctx->len ) 258 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 259 260 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 ) 261 return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret ); 262 263 return( 0 ); 264 } 265 266 /* 267 * Create own private value X and export G^X 268 */ 269 int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, 270 unsigned char *output, size_t olen, 271 int (*f_rng)(void *, unsigned char *, size_t), 272 void *p_rng ) 273 { 274 int ret, count = 0; 275 276 if( ctx == NULL || olen < 1 || olen > ctx->len ) 277 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 278 279 if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 ) 280 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 281 282 /* 283 * generate X and calculate GX = G^X mod P 284 */ 285 do 286 { 287 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) ); 288 289 while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 ) 290 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) ); 291 292 if( count++ > 10 ) 293 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ); 294 } 295 while( dhm_check_range( &ctx->X, &ctx->P ) != 0 ); 296 297 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X, 298 &ctx->P , &ctx->RP ) ); 299 300 if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 ) 301 return( ret ); 302 303 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) ); 304 305 cleanup: 306 307 if( ret != 0 ) 308 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret ); 309 310 return( 0 ); 311 } 312 313 /* 314 * Use the blinding method and optimisation suggested in section 10 of: 315 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, 316 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer 317 * Berlin Heidelberg, 1996. p. 104-113. 318 */ 319 static int dhm_update_blinding( mbedtls_dhm_context *ctx, 320 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) 321 { 322 int ret, count; 323 324 /* 325 * Don't use any blinding the first time a particular X is used, 326 * but remember it to use blinding next time. 327 */ 328 if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 ) 329 { 330 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) ); 331 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) ); 332 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) ); 333 334 return( 0 ); 335 } 336 337 /* 338 * Ok, we need blinding. Can we re-use existing values? 339 * If yes, just update them by squaring them. 340 */ 341 if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ) 342 { 343 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); 344 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) ); 345 346 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); 347 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) ); 348 349 return( 0 ); 350 } 351 352 /* 353 * We need to generate blinding values from scratch 354 */ 355 356 /* Vi = random( 2, P-1 ) */ 357 count = 0; 358 do 359 { 360 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vi, mbedtls_mpi_size( &ctx->P ), f_rng, p_rng ) ); 361 362 while( mbedtls_mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 ) 363 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi, 1 ) ); 364 365 if( count++ > 10 ) 366 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); 367 } 368 while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) <= 0 ); 369 370 /* Vf = Vi^-X mod P */ 371 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) ); 372 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) ); 373 374 cleanup: 375 return( ret ); 376 } 377 378 /* 379 * Derive and export the shared secret (G^Y)^X mod P 380 */ 381 int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, 382 unsigned char *output, size_t output_size, size_t *olen, 383 int (*f_rng)(void *, unsigned char *, size_t), 384 void *p_rng ) 385 { 386 int ret; 387 mbedtls_mpi GYb; 388 389 if( ctx == NULL || output_size < ctx->len ) 390 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 391 392 if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 ) 393 return( ret ); 394 395 mbedtls_mpi_init( &GYb ); 396 397 /* Blind peer's value */ 398 if( f_rng != NULL ) 399 { 400 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) ); 401 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) ); 402 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) ); 403 } 404 else 405 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) ); 406 407 /* Do modular exponentiation */ 408 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X, 409 &ctx->P, &ctx->RP ) ); 410 411 /* Unblind secret value */ 412 if( f_rng != NULL ) 413 { 414 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) ); 415 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) ); 416 } 417 418 *olen = mbedtls_mpi_size( &ctx->K ); 419 420 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) ); 421 422 cleanup: 423 mbedtls_mpi_free( &GYb ); 424 425 if( ret != 0 ) 426 return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret ); 427 428 return( 0 ); 429 } 430 431 /* 432 * Free the components of a DHM key 433 */ 434 void mbedtls_dhm_free( mbedtls_dhm_context *ctx ) 435 { 436 mbedtls_mpi_free( &ctx->pX ); mbedtls_mpi_free( &ctx->Vf ); 437 mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->RP ); 438 mbedtls_mpi_free( &ctx->K ); mbedtls_mpi_free( &ctx->GY ); 439 mbedtls_mpi_free( &ctx->GX ); mbedtls_mpi_free( &ctx->X ); 440 mbedtls_mpi_free( &ctx->G ); mbedtls_mpi_free( &ctx->P ); 441 442 mbedtls_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); 443 } 444 445 #if defined(MBEDTLS_ASN1_PARSE_C) 446 /* 447 * Parse DHM parameters 448 */ 449 int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, 450 size_t dhminlen ) 451 { 452 int ret; 453 size_t len; 454 unsigned char *p, *end; 455 #if defined(MBEDTLS_PEM_PARSE_C) 456 mbedtls_pem_context pem; 457 458 mbedtls_pem_init( &pem ); 459 460 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 461 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' ) 462 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 463 else 464 ret = mbedtls_pem_read_buffer( &pem, 465 "-----BEGIN DH PARAMETERS-----", 466 "-----END DH PARAMETERS-----", 467 dhmin, NULL, 0, &dhminlen ); 468 469 if( ret == 0 ) 470 { 471 /* 472 * Was PEM encoded 473 */ 474 dhminlen = pem.buflen; 475 } 476 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) 477 goto exit; 478 479 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin; 480 #else 481 p = (unsigned char *) dhmin; 482 #endif /* MBEDTLS_PEM_PARSE_C */ 483 end = p + dhminlen; 484 485 /* 486 * DHParams ::= SEQUENCE { 487 * prime INTEGER, -- P 488 * generator INTEGER, -- g 489 * privateValueLength INTEGER OPTIONAL 490 * } 491 */ 492 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 493 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 494 { 495 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; 496 goto exit; 497 } 498 499 end = p + len; 500 501 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 || 502 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 ) 503 { 504 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; 505 goto exit; 506 } 507 508 if( p != end ) 509 { 510 /* This might be the optional privateValueLength. 511 * If so, we can cleanly discard it */ 512 mbedtls_mpi rec; 513 mbedtls_mpi_init( &rec ); 514 ret = mbedtls_asn1_get_mpi( &p, end, &rec ); 515 mbedtls_mpi_free( &rec ); 516 if ( ret != 0 ) 517 { 518 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; 519 goto exit; 520 } 521 if ( p != end ) 522 { 523 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + 524 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; 525 goto exit; 526 } 527 } 528 529 ret = 0; 530 531 dhm->len = mbedtls_mpi_size( &dhm->P ); 532 533 exit: 534 #if defined(MBEDTLS_PEM_PARSE_C) 535 mbedtls_pem_free( &pem ); 536 #endif 537 if( ret != 0 ) 538 mbedtls_dhm_free( dhm ); 539 540 return( ret ); 541 } 542 543 #if defined(MBEDTLS_FS_IO) 544 /* 545 * Load all data from a file into a given buffer. 546 * 547 * The file is expected to contain either PEM or DER encoded data. 548 * A terminating null byte is always appended. It is included in the announced 549 * length only if the data looks like it is PEM encoded. 550 */ 551 static int load_file( const char *path, unsigned char **buf, size_t *n ) 552 { 553 FILE *f; 554 long size; 555 556 if( ( f = fopen( path, "rb" ) ) == NULL ) 557 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); 558 559 fseek( f, 0, SEEK_END ); 560 if( ( size = ftell( f ) ) == -1 ) 561 { 562 fclose( f ); 563 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); 564 } 565 fseek( f, 0, SEEK_SET ); 566 567 *n = (size_t) size; 568 569 if( *n + 1 == 0 || 570 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) 571 { 572 fclose( f ); 573 return( MBEDTLS_ERR_DHM_ALLOC_FAILED ); 574 } 575 576 if( fread( *buf, 1, *n, f ) != *n ) 577 { 578 fclose( f ); 579 580 mbedtls_zeroize( *buf, *n + 1 ); 581 mbedtls_free( *buf ); 582 583 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); 584 } 585 586 fclose( f ); 587 588 (*buf)[*n] = '\0'; 589 590 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) 591 ++*n; 592 593 return( 0 ); 594 } 595 596 /* 597 * Load and parse DHM parameters 598 */ 599 int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ) 600 { 601 int ret; 602 size_t n; 603 unsigned char *buf; 604 605 if( ( ret = load_file( path, &buf, &n ) ) != 0 ) 606 return( ret ); 607 608 ret = mbedtls_dhm_parse_dhm( dhm, buf, n ); 609 610 mbedtls_zeroize( buf, n ); 611 mbedtls_free( buf ); 612 613 return( ret ); 614 } 615 #endif /* MBEDTLS_FS_IO */ 616 #endif /* MBEDTLS_ASN1_PARSE_C */ 617 #endif /* MBEDTLS_DHM_ALT */ 618 619 #if defined(MBEDTLS_SELF_TEST) 620 621 static const char mbedtls_test_dhm_params[] = 622 "-----BEGIN DH PARAMETERS-----\r\n" 623 "MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n" 624 "1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n" 625 "9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n" 626 "-----END DH PARAMETERS-----\r\n"; 627 628 static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params ); 629 630 /* 631 * Checkup routine 632 */ 633 int mbedtls_dhm_self_test( int verbose ) 634 { 635 int ret; 636 mbedtls_dhm_context dhm; 637 638 mbedtls_dhm_init( &dhm ); 639 640 if( verbose != 0 ) 641 mbedtls_printf( " DHM parameter load: " ); 642 643 if( ( ret = mbedtls_dhm_parse_dhm( &dhm, 644 (const unsigned char *) mbedtls_test_dhm_params, 645 mbedtls_test_dhm_params_len ) ) != 0 ) 646 { 647 if( verbose != 0 ) 648 mbedtls_printf( "failed\n" ); 649 650 ret = 1; 651 goto exit; 652 } 653 654 if( verbose != 0 ) 655 mbedtls_printf( "passed\n\n" ); 656 657 exit: 658 mbedtls_dhm_free( &dhm ); 659 660 return( ret ); 661 } 662 663 #endif /* MBEDTLS_SELF_TEST */ 664 665 #endif /* MBEDTLS_DHM_C */ 666