Knight KE / Mbed OS Game_Master
Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dhm.c Source File

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 /*
00064  * helper to validate the mbedtls_mpi size and import it
00065  */
00066 static int dhm_read_bignum( mbedtls_mpi *X,
00067                             unsigned char **p,
00068                             const unsigned char *end )
00069 {
00070     int ret, n;
00071 
00072     if( end - *p < 2 )
00073         return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
00074 
00075     n = ( (*p)[0] << 8 ) | (*p)[1];
00076     (*p) += 2;
00077 
00078     if( (int)( end - *p ) < n )
00079         return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
00080 
00081     if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 )
00082         return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret );
00083 
00084     (*p) += n;
00085 
00086     return( 0 );
00087 }
00088 
00089 /*
00090  * Verify sanity of parameter with regards to P
00091  *
00092  * Parameter should be: 2 <= public_param <= P - 2
00093  *
00094  * This means that we need to return an error if
00095  *              public_param < 2 or public_param > P-2
00096  *
00097  * For more information on the attack, see:
00098  *  http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
00099  *  http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
00100  */
00101 static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
00102 {
00103     mbedtls_mpi L, U;
00104     int ret = 0;
00105 
00106     mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U );
00107 
00108     MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) );
00109     MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
00110 
00111     if( mbedtls_mpi_cmp_mpi( param, &L ) < 0 ||
00112         mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
00113     {
00114         ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
00115     }
00116 
00117 cleanup:
00118     mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U );
00119     return( ret );
00120 }
00121 
00122 void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
00123 {
00124     memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
00125 }
00126 
00127 /*
00128  * Parse the ServerKeyExchange parameters
00129  */
00130 int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
00131                      unsigned char **p,
00132                      const unsigned char *end )
00133 {
00134     int ret;
00135 
00136     if( ( ret = dhm_read_bignum( &ctx->P ,  p, end ) ) != 0 ||
00137         ( ret = dhm_read_bignum( &ctx->G ,  p, end ) ) != 0 ||
00138         ( ret = dhm_read_bignum( &ctx->GY , p, end ) ) != 0 )
00139         return( ret );
00140 
00141     if( ( ret = dhm_check_range( &ctx->GY , &ctx->P  ) ) != 0 )
00142         return( ret );
00143 
00144     ctx->len  = mbedtls_mpi_size( &ctx->P  );
00145 
00146     return( 0 );
00147 }
00148 
00149 /*
00150  * Setup and write the ServerKeyExchange parameters
00151  */
00152 int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
00153                      unsigned char *output, size_t *olen,
00154                      int (*f_rng)(void *, unsigned char *, size_t),
00155                      void *p_rng )
00156 {
00157     int ret, count = 0;
00158     size_t n1, n2, n3;
00159     unsigned char *p;
00160 
00161     if( mbedtls_mpi_cmp_int( &ctx->P , 0 ) == 0 )
00162         return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
00163 
00164     /*
00165      * Generate X as large as possible ( < P )
00166      */
00167     do
00168     {
00169         MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X , x_size, f_rng, p_rng ) );
00170 
00171         while( mbedtls_mpi_cmp_mpi( &ctx->X , &ctx->P  ) >= 0 )
00172             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X , 1 ) );
00173 
00174         if( count++ > 10 )
00175             return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
00176     }
00177     while( dhm_check_range( &ctx->X , &ctx->P  ) != 0 );
00178 
00179     /*
00180      * Calculate GX = G^X mod P
00181      */
00182     MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX , &ctx->G , &ctx->X ,
00183                           &ctx->P  , &ctx->RP  ) );
00184 
00185     if( ( ret = dhm_check_range( &ctx->GX , &ctx->P  ) ) != 0 )
00186         return( ret );
00187 
00188     /*
00189      * export P, G, GX
00190      */
00191 #define DHM_MPI_EXPORT( X, n )                                          \
00192     do {                                                                \
00193         MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ),               \
00194                                                    p + 2,               \
00195                                                    ( n ) ) );           \
00196         *p++ = (unsigned char)( ( n ) >> 8 );                           \
00197         *p++ = (unsigned char)( ( n )      );                           \
00198         p += ( n );                                                     \
00199     } while( 0 )
00200 
00201     n1 = mbedtls_mpi_size( &ctx->P   );
00202     n2 = mbedtls_mpi_size( &ctx->G   );
00203     n3 = mbedtls_mpi_size( &ctx->GX  );
00204 
00205     p = output;
00206     DHM_MPI_EXPORT( &ctx->P  , n1 );
00207     DHM_MPI_EXPORT( &ctx->G  , n2 );
00208     DHM_MPI_EXPORT( &ctx->GX , n3 );
00209 
00210     *olen = p - output;
00211 
00212     ctx->len  = n1;
00213 
00214 cleanup:
00215 
00216     if( ret != 0 )
00217         return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
00218 
00219     return( 0 );
00220 }
00221 
00222 /*
00223  * Set prime modulus and generator
00224  */
00225 int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
00226                            const mbedtls_mpi *P,
00227                            const mbedtls_mpi *G )
00228 {
00229     int ret;
00230 
00231     if( ctx == NULL || P == NULL || G == NULL )
00232         return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
00233 
00234     if( ( ret = mbedtls_mpi_copy( &ctx->P , P ) ) != 0 ||
00235         ( ret = mbedtls_mpi_copy( &ctx->G , G ) ) != 0 )
00236     {
00237         return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret );
00238     }
00239 
00240     ctx->len  = mbedtls_mpi_size( &ctx->P  );
00241     return( 0 );
00242 }
00243 
00244 /*
00245  * Import the peer's public value G^Y
00246  */
00247 int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
00248                      const unsigned char *input, size_t ilen )
00249 {
00250     int ret;
00251 
00252     if( ctx == NULL || ilen < 1 || ilen > ctx->len  )
00253         return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
00254 
00255     if( ( ret = mbedtls_mpi_read_binary( &ctx->GY , input, ilen ) ) != 0 )
00256         return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret );
00257 
00258     return( 0 );
00259 }
00260 
00261 /*
00262  * Create own private value X and export G^X
00263  */
00264 int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
00265                      unsigned char *output, size_t olen,
00266                      int (*f_rng)(void *, unsigned char *, size_t),
00267                      void *p_rng )
00268 {
00269     int ret, count = 0;
00270 
00271     if( ctx == NULL || olen < 1 || olen > ctx->len  )
00272         return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
00273 
00274     if( mbedtls_mpi_cmp_int( &ctx->P , 0 ) == 0 )
00275         return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
00276 
00277     /*
00278      * generate X and calculate GX = G^X mod P
00279      */
00280     do
00281     {
00282         MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X , x_size, f_rng, p_rng ) );
00283 
00284         while( mbedtls_mpi_cmp_mpi( &ctx->X , &ctx->P  ) >= 0 )
00285             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X , 1 ) );
00286 
00287         if( count++ > 10 )
00288             return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
00289     }
00290     while( dhm_check_range( &ctx->X , &ctx->P  ) != 0 );
00291 
00292     MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX , &ctx->G , &ctx->X ,
00293                           &ctx->P  , &ctx->RP  ) );
00294 
00295     if( ( ret = dhm_check_range( &ctx->GX , &ctx->P  ) ) != 0 )
00296         return( ret );
00297 
00298     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX , output, olen ) );
00299 
00300 cleanup:
00301 
00302     if( ret != 0 )
00303         return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
00304 
00305     return( 0 );
00306 }
00307 
00308 /*
00309  * Use the blinding method and optimisation suggested in section 10 of:
00310  *  KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
00311  *  DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
00312  *  Berlin Heidelberg, 1996. p. 104-113.
00313  */
00314 static int dhm_update_blinding( mbedtls_dhm_context *ctx,
00315                     int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
00316 {
00317     int ret, count;
00318 
00319     /*
00320      * Don't use any blinding the first time a particular X is used,
00321      * but remember it to use blinding next time.
00322      */
00323     if( mbedtls_mpi_cmp_mpi( &ctx->X , &ctx->pX  ) != 0 )
00324     {
00325         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX , &ctx->X  ) );
00326         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi , 1 ) );
00327         MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf , 1 ) );
00328 
00329         return( 0 );
00330     }
00331 
00332     /*
00333      * Ok, we need blinding. Can we re-use existing values?
00334      * If yes, just update them by squaring them.
00335      */
00336     if( mbedtls_mpi_cmp_int( &ctx->Vi , 1 ) != 0 )
00337     {
00338         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi , &ctx->Vi , &ctx->Vi  ) );
00339         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi , &ctx->Vi , &ctx->P  ) );
00340 
00341         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf , &ctx->Vf , &ctx->Vf  ) );
00342         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf , &ctx->Vf , &ctx->P  ) );
00343 
00344         return( 0 );
00345     }
00346 
00347     /*
00348      * We need to generate blinding values from scratch
00349      */
00350 
00351     /* Vi = random( 2, P-1 ) */
00352     count = 0;
00353     do
00354     {
00355         MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vi , mbedtls_mpi_size( &ctx->P  ), f_rng, p_rng ) );
00356 
00357         while( mbedtls_mpi_cmp_mpi( &ctx->Vi , &ctx->P  ) >= 0 )
00358             MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi , 1 ) );
00359 
00360         if( count++ > 10 )
00361             return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
00362     }
00363     while( mbedtls_mpi_cmp_int( &ctx->Vi , 1 ) <= 0 );
00364 
00365     /* Vf = Vi^-X mod P */
00366     MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf , &ctx->Vi , &ctx->P  ) );
00367     MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf , &ctx->Vf , &ctx->X , &ctx->P , &ctx->RP  ) );
00368 
00369 cleanup:
00370     return( ret );
00371 }
00372 
00373 /*
00374  * Derive and export the shared secret (G^Y)^X mod P
00375  */
00376 int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
00377                      unsigned char *output, size_t output_size, size_t *olen,
00378                      int (*f_rng)(void *, unsigned char *, size_t),
00379                      void *p_rng )
00380 {
00381     int ret;
00382     mbedtls_mpi GYb;
00383 
00384     if( ctx == NULL || output_size < ctx->len )
00385         return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
00386 
00387     if( ( ret = dhm_check_range( &ctx->GY , &ctx->P  ) ) != 0 )
00388         return( ret );
00389 
00390     mbedtls_mpi_init( &GYb );
00391 
00392     /* Blind peer's value */
00393     if( f_rng != NULL )
00394     {
00395         MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
00396         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY , &ctx->Vi  ) );
00397         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P  ) );
00398     }
00399     else
00400         MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY  ) );
00401 
00402     /* Do modular exponentiation */
00403     MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K , &GYb, &ctx->X ,
00404                           &ctx->P , &ctx->RP  ) );
00405 
00406     /* Unblind secret value */
00407     if( f_rng != NULL )
00408     {
00409         MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K , &ctx->K , &ctx->Vf  ) );
00410         MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K , &ctx->K , &ctx->P  ) );
00411     }
00412 
00413     *olen = mbedtls_mpi_size( &ctx->K  );
00414 
00415     MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K , output, *olen ) );
00416 
00417 cleanup:
00418     mbedtls_mpi_free( &GYb );
00419 
00420     if( ret != 0 )
00421         return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret );
00422 
00423     return( 0 );
00424 }
00425 
00426 /*
00427  * Free the components of a DHM key
00428  */
00429 void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
00430 {
00431     mbedtls_mpi_free( &ctx->pX  ); mbedtls_mpi_free( &ctx->Vf  );
00432     mbedtls_mpi_free( &ctx->Vi  ); mbedtls_mpi_free( &ctx->RP  );
00433     mbedtls_mpi_free( &ctx->K   ); mbedtls_mpi_free( &ctx->GY  );
00434     mbedtls_mpi_free( &ctx->GX  ); mbedtls_mpi_free( &ctx->X   );
00435     mbedtls_mpi_free( &ctx->G   ); mbedtls_mpi_free( &ctx->P   );
00436 
00437     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
00438 }
00439 
00440 #if defined(MBEDTLS_ASN1_PARSE_C)
00441 /*
00442  * Parse DHM parameters
00443  */
00444 int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
00445                    size_t dhminlen )
00446 {
00447     int ret;
00448     size_t len;
00449     unsigned char *p, *end;
00450 #if defined(MBEDTLS_PEM_PARSE_C)
00451     mbedtls_pem_context pem;
00452 
00453     mbedtls_pem_init( &pem );
00454 
00455     /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
00456     if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
00457         ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
00458     else
00459         ret = mbedtls_pem_read_buffer( &pem,
00460                                "-----BEGIN DH PARAMETERS-----",
00461                                "-----END DH PARAMETERS-----",
00462                                dhmin, NULL, 0, &dhminlen );
00463 
00464     if( ret == 0 )
00465     {
00466         /*
00467          * Was PEM encoded
00468          */
00469         dhminlen = pem.buflen ;
00470     }
00471     else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
00472         goto exit;
00473 
00474     p = ( ret == 0 ) ? pem.buf  : (unsigned char *) dhmin;
00475 #else
00476     p = (unsigned char *) dhmin;
00477 #endif /* MBEDTLS_PEM_PARSE_C */
00478     end = p + dhminlen;
00479 
00480     /*
00481      *  DHParams ::= SEQUENCE {
00482      *      prime              INTEGER,  -- P
00483      *      generator          INTEGER,  -- g
00484      *      privateValueLength INTEGER OPTIONAL
00485      *  }
00486      */
00487     if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
00488             MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
00489     {
00490         ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
00491         goto exit;
00492     }
00493 
00494     end = p + len;
00495 
00496     if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P   ) ) != 0 ||
00497         ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G  ) ) != 0 )
00498     {
00499         ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
00500         goto exit;
00501     }
00502 
00503     if( p != end )
00504     {
00505         /* This might be the optional privateValueLength.
00506          * If so, we can cleanly discard it */
00507         mbedtls_mpi rec;
00508         mbedtls_mpi_init( &rec );
00509         ret = mbedtls_asn1_get_mpi( &p, end, &rec );
00510         mbedtls_mpi_free( &rec );
00511         if ( ret != 0 )
00512         {
00513             ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
00514             goto exit;
00515         }
00516         if ( p != end )
00517         {
00518             ret = MBEDTLS_ERR_DHM_INVALID_FORMAT +
00519                 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
00520             goto exit;
00521         }
00522     }
00523 
00524     ret = 0;
00525 
00526     dhm->len  = mbedtls_mpi_size( &dhm->P  );
00527 
00528 exit:
00529 #if defined(MBEDTLS_PEM_PARSE_C)
00530     mbedtls_pem_free( &pem );
00531 #endif
00532     if( ret != 0 )
00533         mbedtls_dhm_free( dhm );
00534 
00535     return( ret );
00536 }
00537 
00538 #if defined(MBEDTLS_FS_IO)
00539 /*
00540  * Load all data from a file into a given buffer.
00541  *
00542  * The file is expected to contain either PEM or DER encoded data.
00543  * A terminating null byte is always appended. It is included in the announced
00544  * length only if the data looks like it is PEM encoded.
00545  */
00546 static int load_file( const char *path, unsigned char **buf, size_t *n )
00547 {
00548     FILE *f;
00549     long size;
00550 
00551     if( ( f = fopen( path, "rb" ) ) == NULL )
00552         return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
00553 
00554     fseek( f, 0, SEEK_END );
00555     if( ( size = ftell( f ) ) == -1 )
00556     {
00557         fclose( f );
00558         return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
00559     }
00560     fseek( f, 0, SEEK_SET );
00561 
00562     *n = (size_t) size;
00563 
00564     if( *n + 1 == 0 ||
00565         ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
00566     {
00567         fclose( f );
00568         return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
00569     }
00570 
00571     if( fread( *buf, 1, *n, f ) != *n )
00572     {
00573         fclose( f );
00574 
00575         mbedtls_platform_zeroize( *buf, *n + 1 );
00576         mbedtls_free( *buf );
00577 
00578         return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
00579     }
00580 
00581     fclose( f );
00582 
00583     (*buf)[*n] = '\0';
00584 
00585     if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
00586         ++*n;
00587 
00588     return( 0 );
00589 }
00590 
00591 /*
00592  * Load and parse DHM parameters
00593  */
00594 int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
00595 {
00596     int ret;
00597     size_t n;
00598     unsigned char *buf;
00599 
00600     if( ( ret = load_file( path, &buf, &n ) ) != 0 )
00601         return( ret );
00602 
00603     ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
00604 
00605     mbedtls_platform_zeroize( buf, n );
00606     mbedtls_free( buf );
00607 
00608     return( ret );
00609 }
00610 #endif /* MBEDTLS_FS_IO */
00611 #endif /* MBEDTLS_ASN1_PARSE_C */
00612 #endif /* MBEDTLS_DHM_ALT */
00613 
00614 #if defined(MBEDTLS_SELF_TEST)
00615 
00616 static const char mbedtls_test_dhm_params[] =
00617 "-----BEGIN DH PARAMETERS-----\r\n"
00618 "MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
00619 "1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
00620 "9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
00621 "-----END DH PARAMETERS-----\r\n";
00622 
00623 static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
00624 
00625 /*
00626  * Checkup routine
00627  */
00628 int mbedtls_dhm_self_test( int verbose )
00629 {
00630     int ret;
00631     mbedtls_dhm_context dhm;
00632 
00633     mbedtls_dhm_init( &dhm );
00634 
00635     if( verbose != 0 )
00636         mbedtls_printf( "  DHM parameter load: " );
00637 
00638     if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
00639                     (const unsigned char *) mbedtls_test_dhm_params,
00640                     mbedtls_test_dhm_params_len ) ) != 0 )
00641     {
00642         if( verbose != 0 )
00643             mbedtls_printf( "failed\n" );
00644 
00645         ret = 1;
00646         goto exit;
00647     }
00648 
00649     if( verbose != 0 )
00650         mbedtls_printf( "passed\n\n" );
00651 
00652 exit:
00653     mbedtls_dhm_free( &dhm );
00654 
00655     return( ret );
00656 }
00657 
00658 #endif /* MBEDTLS_SELF_TEST */
00659 
00660 #endif /* MBEDTLS_DHM_C */