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