Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
dhm.c
00001 /* 00002 * Diffie-Hellman-Merkle key exchange 00003 * 00004 * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved 00005 * SPDX-License-Identifier: Apache-2.0 00006 * 00007 * Licensed under the Apache License, Version 2.0 (the "License"); you may 00008 * not use this file except in compliance with the License. 00009 * You may obtain a copy of the License at 00010 * 00011 * http://www.apache.org/licenses/LICENSE-2.0 00012 * 00013 * Unless required by applicable law or agreed to in writing, software 00014 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT 00015 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00016 * See the License for the specific language governing permissions and 00017 * limitations under the License. 00018 * 00019 * This file is part of mbed TLS (https://tls.mbed.org) 00020 */ 00021 /* 00022 * The following sources were referenced in the design of this implementation 00023 * of the Diffie-Hellman-Merkle algorithm: 00024 * 00025 * [1] Handbook of Applied Cryptography - 1997, Chapter 12 00026 * Menezes, van Oorschot and Vanstone 00027 * 00028 */ 00029 00030 #if !defined(MBEDTLS_CONFIG_FILE) 00031 #include "mbedtls/config.h" 00032 #else 00033 #include MBEDTLS_CONFIG_FILE 00034 #endif 00035 00036 #if defined(MBEDTLS_DHM_C) 00037 00038 #include "mbedtls/dhm.h" 00039 #include "mbedtls/platform_util.h" 00040 00041 #include <string.h> 00042 00043 #if defined(MBEDTLS_PEM_PARSE_C) 00044 #include "mbedtls/pem.h" 00045 #endif 00046 00047 #if defined(MBEDTLS_ASN1_PARSE_C) 00048 #include "mbedtls/asn1.h" 00049 #endif 00050 00051 #if defined(MBEDTLS_PLATFORM_C) 00052 #include "mbedtls/platform.h" 00053 #else 00054 #include <stdlib.h> 00055 #include <stdio.h> 00056 #define mbedtls_printf printf 00057 #define mbedtls_calloc calloc 00058 #define mbedtls_free free 00059 #endif 00060 00061 #if !defined(MBEDTLS_DHM_ALT) 00062 00063 #define DHM_VALIDATE_RET( cond ) \ 00064 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA ) 00065 #define DHM_VALIDATE( cond ) \ 00066 MBEDTLS_INTERNAL_VALIDATE( cond ) 00067 00068 /* 00069 * helper to validate the mbedtls_mpi size and import it 00070 */ 00071 static int dhm_read_bignum( mbedtls_mpi *X, 00072 unsigned char **p, 00073 const unsigned char *end ) 00074 { 00075 int ret, n; 00076 00077 if( end - *p < 2 ) 00078 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 00079 00080 n = ( (*p)[0] << 8 ) | (*p)[1]; 00081 (*p) += 2; 00082 00083 if( (int)( end - *p ) < n ) 00084 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 00085 00086 if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 ) 00087 return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret ); 00088 00089 (*p) += n; 00090 00091 return( 0 ); 00092 } 00093 00094 /* 00095 * Verify sanity of parameter with regards to P 00096 * 00097 * Parameter should be: 2 <= public_param <= P - 2 00098 * 00099 * This means that we need to return an error if 00100 * public_param < 2 or public_param > P-2 00101 * 00102 * For more information on the attack, see: 00103 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf 00104 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643 00105 */ 00106 static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P ) 00107 { 00108 mbedtls_mpi L, U; 00109 int ret = 0; 00110 00111 mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U ); 00112 00113 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) ); 00114 MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) ); 00115 00116 if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 || 00117 mbedtls_mpi_cmp_mpi( param, &U ) > 0 ) 00118 { 00119 ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA; 00120 } 00121 00122 cleanup: 00123 mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U ); 00124 return( ret ); 00125 } 00126 00127 void mbedtls_dhm_init( mbedtls_dhm_context *ctx ) 00128 { 00129 DHM_VALIDATE( ctx != NULL ); 00130 memset( ctx, 0, sizeof( mbedtls_dhm_context ) ); 00131 } 00132 00133 /* 00134 * Parse the ServerKeyExchange parameters 00135 */ 00136 int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx, 00137 unsigned char **p, 00138 const unsigned char *end ) 00139 { 00140 int ret; 00141 DHM_VALIDATE_RET( ctx != NULL ); 00142 DHM_VALIDATE_RET( p != NULL && *p != NULL ); 00143 DHM_VALIDATE_RET( end != NULL ); 00144 00145 if( ( ret = dhm_read_bignum( &ctx->P , p, end ) ) != 0 || 00146 ( ret = dhm_read_bignum( &ctx->G , p, end ) ) != 0 || 00147 ( ret = dhm_read_bignum( &ctx->GY , p, end ) ) != 0 ) 00148 return( ret ); 00149 00150 if( ( ret = dhm_check_range( &ctx->GY , &ctx->P ) ) != 0 ) 00151 return( ret ); 00152 00153 ctx->len = mbedtls_mpi_size( &ctx->P ); 00154 00155 return( 0 ); 00156 } 00157 00158 /* 00159 * Setup and write the ServerKeyExchange parameters 00160 */ 00161 int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size, 00162 unsigned char *output, size_t *olen, 00163 int (*f_rng)(void *, unsigned char *, size_t), 00164 void *p_rng ) 00165 { 00166 int ret, count = 0; 00167 size_t n1, n2, n3; 00168 unsigned char *p; 00169 DHM_VALIDATE_RET( ctx != NULL ); 00170 DHM_VALIDATE_RET( output != NULL ); 00171 DHM_VALIDATE_RET( olen != NULL ); 00172 DHM_VALIDATE_RET( f_rng != NULL ); 00173 00174 if( mbedtls_mpi_cmp_int( &ctx->P , 0 ) == 0 ) 00175 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 00176 00177 /* 00178 * Generate X as large as possible ( < P ) 00179 */ 00180 do 00181 { 00182 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X , x_size, f_rng, p_rng ) ); 00183 00184 while( mbedtls_mpi_cmp_mpi( &ctx->X , &ctx->P ) >= 0 ) 00185 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X , 1 ) ); 00186 00187 if( count++ > 10 ) 00188 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED ); 00189 } 00190 while( dhm_check_range( &ctx->X , &ctx->P ) != 0 ); 00191 00192 /* 00193 * Calculate GX = G^X mod P 00194 */ 00195 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX , &ctx->G , &ctx->X , 00196 &ctx->P , &ctx->RP ) ); 00197 00198 if( ( ret = dhm_check_range( &ctx->GX , &ctx->P ) ) != 0 ) 00199 return( ret ); 00200 00201 /* 00202 * export P, G, GX 00203 */ 00204 #define DHM_MPI_EXPORT( X, n ) \ 00205 do { \ 00206 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \ 00207 p + 2, \ 00208 ( n ) ) ); \ 00209 *p++ = (unsigned char)( ( n ) >> 8 ); \ 00210 *p++ = (unsigned char)( ( n ) ); \ 00211 p += ( n ); \ 00212 } while( 0 ) 00213 00214 n1 = mbedtls_mpi_size( &ctx->P ); 00215 n2 = mbedtls_mpi_size( &ctx->G ); 00216 n3 = mbedtls_mpi_size( &ctx->GX ); 00217 00218 p = output; 00219 DHM_MPI_EXPORT( &ctx->P , n1 ); 00220 DHM_MPI_EXPORT( &ctx->G , n2 ); 00221 DHM_MPI_EXPORT( &ctx->GX , n3 ); 00222 00223 *olen = p - output; 00224 00225 ctx->len = n1; 00226 00227 cleanup: 00228 00229 if( ret != 0 ) 00230 return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret ); 00231 00232 return( 0 ); 00233 } 00234 00235 /* 00236 * Set prime modulus and generator 00237 */ 00238 int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx, 00239 const mbedtls_mpi *P, 00240 const mbedtls_mpi *G ) 00241 { 00242 int ret; 00243 DHM_VALIDATE_RET( ctx != NULL ); 00244 DHM_VALIDATE_RET( P != NULL ); 00245 DHM_VALIDATE_RET( G != NULL ); 00246 00247 if( ( ret = mbedtls_mpi_copy( &ctx->P , P ) ) != 0 || 00248 ( ret = mbedtls_mpi_copy( &ctx->G , G ) ) != 0 ) 00249 { 00250 return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret ); 00251 } 00252 00253 ctx->len = mbedtls_mpi_size( &ctx->P ); 00254 return( 0 ); 00255 } 00256 00257 /* 00258 * Import the peer's public value G^Y 00259 */ 00260 int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx, 00261 const unsigned char *input, size_t ilen ) 00262 { 00263 int ret; 00264 DHM_VALIDATE_RET( ctx != NULL ); 00265 DHM_VALIDATE_RET( input != NULL ); 00266 00267 if( ilen < 1 || ilen > ctx->len ) 00268 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 00269 00270 if( ( ret = mbedtls_mpi_read_binary( &ctx->GY , input, ilen ) ) != 0 ) 00271 return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret ); 00272 00273 return( 0 ); 00274 } 00275 00276 /* 00277 * Create own private value X and export G^X 00278 */ 00279 int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size, 00280 unsigned char *output, size_t olen, 00281 int (*f_rng)(void *, unsigned char *, size_t), 00282 void *p_rng ) 00283 { 00284 int ret, count = 0; 00285 DHM_VALIDATE_RET( ctx != NULL ); 00286 DHM_VALIDATE_RET( output != NULL ); 00287 DHM_VALIDATE_RET( f_rng != NULL ); 00288 00289 if( olen < 1 || olen > ctx->len ) 00290 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 00291 00292 if( mbedtls_mpi_cmp_int( &ctx->P , 0 ) == 0 ) 00293 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 00294 00295 /* 00296 * generate X and calculate GX = G^X mod P 00297 */ 00298 do 00299 { 00300 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X , x_size, f_rng, p_rng ) ); 00301 00302 while( mbedtls_mpi_cmp_mpi( &ctx->X , &ctx->P ) >= 0 ) 00303 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X , 1 ) ); 00304 00305 if( count++ > 10 ) 00306 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED ); 00307 } 00308 while( dhm_check_range( &ctx->X , &ctx->P ) != 0 ); 00309 00310 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX , &ctx->G , &ctx->X , 00311 &ctx->P , &ctx->RP ) ); 00312 00313 if( ( ret = dhm_check_range( &ctx->GX , &ctx->P ) ) != 0 ) 00314 return( ret ); 00315 00316 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX , output, olen ) ); 00317 00318 cleanup: 00319 00320 if( ret != 0 ) 00321 return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret ); 00322 00323 return( 0 ); 00324 } 00325 00326 /* 00327 * Use the blinding method and optimisation suggested in section 10 of: 00328 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, 00329 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer 00330 * Berlin Heidelberg, 1996. p. 104-113. 00331 */ 00332 static int dhm_update_blinding( mbedtls_dhm_context *ctx, 00333 int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) 00334 { 00335 int ret, count; 00336 00337 /* 00338 * Don't use any blinding the first time a particular X is used, 00339 * but remember it to use blinding next time. 00340 */ 00341 if( mbedtls_mpi_cmp_mpi( &ctx->X , &ctx->pX ) != 0 ) 00342 { 00343 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX , &ctx->X ) ); 00344 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi , 1 ) ); 00345 MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf , 1 ) ); 00346 00347 return( 0 ); 00348 } 00349 00350 /* 00351 * Ok, we need blinding. Can we re-use existing values? 00352 * If yes, just update them by squaring them. 00353 */ 00354 if( mbedtls_mpi_cmp_int( &ctx->Vi , 1 ) != 0 ) 00355 { 00356 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi , &ctx->Vi , &ctx->Vi ) ); 00357 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi , &ctx->Vi , &ctx->P ) ); 00358 00359 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf , &ctx->Vf , &ctx->Vf ) ); 00360 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf , &ctx->Vf , &ctx->P ) ); 00361 00362 return( 0 ); 00363 } 00364 00365 /* 00366 * We need to generate blinding values from scratch 00367 */ 00368 00369 /* Vi = random( 2, P-1 ) */ 00370 count = 0; 00371 do 00372 { 00373 MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vi , mbedtls_mpi_size( &ctx->P ), f_rng, p_rng ) ); 00374 00375 while( mbedtls_mpi_cmp_mpi( &ctx->Vi , &ctx->P ) >= 0 ) 00376 MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi , 1 ) ); 00377 00378 if( count++ > 10 ) 00379 return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); 00380 } 00381 while( mbedtls_mpi_cmp_int( &ctx->Vi , 1 ) <= 0 ); 00382 00383 /* Vf = Vi^-X mod P */ 00384 MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf , &ctx->Vi , &ctx->P ) ); 00385 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf , &ctx->Vf , &ctx->X , &ctx->P , &ctx->RP ) ); 00386 00387 cleanup: 00388 return( ret ); 00389 } 00390 00391 /* 00392 * Derive and export the shared secret (G^Y)^X mod P 00393 */ 00394 int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx, 00395 unsigned char *output, size_t output_size, size_t *olen, 00396 int (*f_rng)(void *, unsigned char *, size_t), 00397 void *p_rng ) 00398 { 00399 int ret; 00400 mbedtls_mpi GYb; 00401 DHM_VALIDATE_RET( ctx != NULL ); 00402 DHM_VALIDATE_RET( output != NULL ); 00403 DHM_VALIDATE_RET( olen != NULL ); 00404 00405 if( output_size < ctx->len ) 00406 return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA ); 00407 00408 if( ( ret = dhm_check_range( &ctx->GY , &ctx->P ) ) != 0 ) 00409 return( ret ); 00410 00411 mbedtls_mpi_init( &GYb ); 00412 00413 /* Blind peer's value */ 00414 if( f_rng != NULL ) 00415 { 00416 MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) ); 00417 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY , &ctx->Vi ) ); 00418 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) ); 00419 } 00420 else 00421 MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) ); 00422 00423 /* Do modular exponentiation */ 00424 MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K , &GYb, &ctx->X , 00425 &ctx->P , &ctx->RP ) ); 00426 00427 /* Unblind secret value */ 00428 if( f_rng != NULL ) 00429 { 00430 MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K , &ctx->K , &ctx->Vf ) ); 00431 MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K , &ctx->K , &ctx->P ) ); 00432 } 00433 00434 *olen = mbedtls_mpi_size( &ctx->K ); 00435 00436 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K , output, *olen ) ); 00437 00438 cleanup: 00439 mbedtls_mpi_free( &GYb ); 00440 00441 if( ret != 0 ) 00442 return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret ); 00443 00444 return( 0 ); 00445 } 00446 00447 /* 00448 * Free the components of a DHM key 00449 */ 00450 void mbedtls_dhm_free( mbedtls_dhm_context *ctx ) 00451 { 00452 if( ctx == NULL ) 00453 return; 00454 00455 mbedtls_mpi_free( &ctx->pX ); 00456 mbedtls_mpi_free( &ctx->Vf ); 00457 mbedtls_mpi_free( &ctx->Vi ); 00458 mbedtls_mpi_free( &ctx->RP ); 00459 mbedtls_mpi_free( &ctx->K ); 00460 mbedtls_mpi_free( &ctx->GY ); 00461 mbedtls_mpi_free( &ctx->GX ); 00462 mbedtls_mpi_free( &ctx->X ); 00463 mbedtls_mpi_free( &ctx->G ); 00464 mbedtls_mpi_free( &ctx->P ); 00465 00466 mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) ); 00467 } 00468 00469 #if defined(MBEDTLS_ASN1_PARSE_C) 00470 /* 00471 * Parse DHM parameters 00472 */ 00473 int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin, 00474 size_t dhminlen ) 00475 { 00476 int ret; 00477 size_t len; 00478 unsigned char *p, *end; 00479 #if defined(MBEDTLS_PEM_PARSE_C) 00480 mbedtls_pem_context pem; 00481 #endif /* MBEDTLS_PEM_PARSE_C */ 00482 00483 DHM_VALIDATE_RET( dhm != NULL ); 00484 DHM_VALIDATE_RET( dhmin != NULL ); 00485 00486 #if defined(MBEDTLS_PEM_PARSE_C) 00487 mbedtls_pem_init( &pem ); 00488 00489 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ 00490 if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' ) 00491 ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; 00492 else 00493 ret = mbedtls_pem_read_buffer( &pem, 00494 "-----BEGIN DH PARAMETERS-----", 00495 "-----END DH PARAMETERS-----", 00496 dhmin, NULL, 0, &dhminlen ); 00497 00498 if( ret == 0 ) 00499 { 00500 /* 00501 * Was PEM encoded 00502 */ 00503 dhminlen = pem.buflen ; 00504 } 00505 else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) 00506 goto exit; 00507 00508 p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin; 00509 #else 00510 p = (unsigned char *) dhmin; 00511 #endif /* MBEDTLS_PEM_PARSE_C */ 00512 end = p + dhminlen; 00513 00514 /* 00515 * DHParams ::= SEQUENCE { 00516 * prime INTEGER, -- P 00517 * generator INTEGER, -- g 00518 * privateValueLength INTEGER OPTIONAL 00519 * } 00520 */ 00521 if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, 00522 MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) 00523 { 00524 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; 00525 goto exit; 00526 } 00527 00528 end = p + len; 00529 00530 if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 || 00531 ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 ) 00532 { 00533 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; 00534 goto exit; 00535 } 00536 00537 if( p != end ) 00538 { 00539 /* This might be the optional privateValueLength. 00540 * If so, we can cleanly discard it */ 00541 mbedtls_mpi rec; 00542 mbedtls_mpi_init( &rec ); 00543 ret = mbedtls_asn1_get_mpi( &p, end, &rec ); 00544 mbedtls_mpi_free( &rec ); 00545 if ( ret != 0 ) 00546 { 00547 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret; 00548 goto exit; 00549 } 00550 if ( p != end ) 00551 { 00552 ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + 00553 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; 00554 goto exit; 00555 } 00556 } 00557 00558 ret = 0; 00559 00560 dhm->len = mbedtls_mpi_size( &dhm->P ); 00561 00562 exit: 00563 #if defined(MBEDTLS_PEM_PARSE_C) 00564 mbedtls_pem_free( &pem ); 00565 #endif 00566 if( ret != 0 ) 00567 mbedtls_dhm_free( dhm ); 00568 00569 return( ret ); 00570 } 00571 00572 #if defined(MBEDTLS_FS_IO) 00573 /* 00574 * Load all data from a file into a given buffer. 00575 * 00576 * The file is expected to contain either PEM or DER encoded data. 00577 * A terminating null byte is always appended. It is included in the announced 00578 * length only if the data looks like it is PEM encoded. 00579 */ 00580 static int load_file( const char *path, unsigned char **buf, size_t *n ) 00581 { 00582 FILE *f; 00583 long size; 00584 00585 if( ( f = fopen( path, "rb" ) ) == NULL ) 00586 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); 00587 00588 fseek( f, 0, SEEK_END ); 00589 if( ( size = ftell( f ) ) == -1 ) 00590 { 00591 fclose( f ); 00592 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); 00593 } 00594 fseek( f, 0, SEEK_SET ); 00595 00596 *n = (size_t) size; 00597 00598 if( *n + 1 == 0 || 00599 ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) 00600 { 00601 fclose( f ); 00602 return( MBEDTLS_ERR_DHM_ALLOC_FAILED ); 00603 } 00604 00605 if( fread( *buf, 1, *n, f ) != *n ) 00606 { 00607 fclose( f ); 00608 00609 mbedtls_platform_zeroize( *buf, *n + 1 ); 00610 mbedtls_free( *buf ); 00611 00612 return( MBEDTLS_ERR_DHM_FILE_IO_ERROR ); 00613 } 00614 00615 fclose( f ); 00616 00617 (*buf)[*n] = '\0'; 00618 00619 if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) 00620 ++*n; 00621 00622 return( 0 ); 00623 } 00624 00625 /* 00626 * Load and parse DHM parameters 00627 */ 00628 int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path ) 00629 { 00630 int ret; 00631 size_t n; 00632 unsigned char *buf; 00633 DHM_VALIDATE_RET( dhm != NULL ); 00634 DHM_VALIDATE_RET( path != NULL ); 00635 00636 if( ( ret = load_file( path, &buf, &n ) ) != 0 ) 00637 return( ret ); 00638 00639 ret = mbedtls_dhm_parse_dhm( dhm, buf, n ); 00640 00641 mbedtls_platform_zeroize( buf, n ); 00642 mbedtls_free( buf ); 00643 00644 return( ret ); 00645 } 00646 #endif /* MBEDTLS_FS_IO */ 00647 #endif /* MBEDTLS_ASN1_PARSE_C */ 00648 #endif /* MBEDTLS_DHM_ALT */ 00649 00650 #if defined(MBEDTLS_SELF_TEST) 00651 00652 #if defined(MBEDTLS_PEM_PARSE_C) 00653 static const char mbedtls_test_dhm_params[] = 00654 "-----BEGIN DH PARAMETERS-----\r\n" 00655 "MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n" 00656 "1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n" 00657 "9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n" 00658 "-----END DH PARAMETERS-----\r\n"; 00659 #else /* MBEDTLS_PEM_PARSE_C */ 00660 static const char mbedtls_test_dhm_params[] = { 00661 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44, 00662 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d, 00663 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3, 00664 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1, 00665 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18, 00666 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a, 00667 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1, 00668 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6, 00669 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64, 00670 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8, 00671 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f, 00672 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 }; 00673 #endif /* MBEDTLS_PEM_PARSE_C */ 00674 00675 static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params ); 00676 00677 /* 00678 * Checkup routine 00679 */ 00680 int mbedtls_dhm_self_test( int verbose ) 00681 { 00682 int ret; 00683 mbedtls_dhm_context dhm; 00684 00685 mbedtls_dhm_init( &dhm ); 00686 00687 if( verbose != 0 ) 00688 mbedtls_printf( " DHM parameter load: " ); 00689 00690 if( ( ret = mbedtls_dhm_parse_dhm( &dhm, 00691 (const unsigned char *) mbedtls_test_dhm_params, 00692 mbedtls_test_dhm_params_len ) ) != 0 ) 00693 { 00694 if( verbose != 0 ) 00695 mbedtls_printf( "failed\n" ); 00696 00697 ret = 1; 00698 goto exit; 00699 } 00700 00701 if( verbose != 0 ) 00702 mbedtls_printf( "passed\n\n" ); 00703 00704 exit: 00705 mbedtls_dhm_free( &dhm ); 00706 00707 return( ret ); 00708 } 00709 00710 #endif /* MBEDTLS_SELF_TEST */ 00711 00712 #endif /* MBEDTLS_DHM_C */
Generated on Tue Jul 12 2022 13:54:16 by
1.7.2