Kenji Arai / mbed-os_TYBLE16

Dependents:   TYBLE16_simple_data_logger TYBLE16_MP3_Air

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 #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 */