1
#pragma clang diagnostic ignored "-Wunknown-warning-option"
2
#pragma clang diagnostic ignored "-Wimplicit-int-conversion"
3
#pragma clang diagnostic ignored "-Wsign-conversion"
5
#pragma GCC diagnostic ignored "-Wconversion"
7
#pragma clang diagnostic ignored "-Wimplicit-int-conversion"
8
#pragma clang diagnostic ignored "-Wsign-conversion"
10
#pragma GCC diagnostic ignored "-Wconversion"
12
#pragma clang diagnostic ignored "-Wimplicit-int-conversion"
13
#pragma clang diagnostic ignored "-Wsign-conversion"
15
* Diffie-Hellman-Merkle key exchange
17
* Copyright The Mbed TLS Contributors
18
* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
20
* This file is provided under the Apache License 2.0, or the
21
* GNU General Public License v2.0 or later.
26
* Licensed under the Apache License, Version 2.0 (the "License"); you may
27
* not use this file except in compliance with the License.
28
* You may obtain a copy of the License at
30
* http://www.apache.org/licenses/LICENSE-2.0
32
* Unless required by applicable law or agreed to in writing, software
33
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
34
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
35
* See the License for the specific language governing permissions and
36
* limitations under the License.
41
* GNU General Public License v2.0 or later:
43
* This program is free software; you can redistribute it and/or modify
44
* it under the terms of the GNU General Public License as published by
45
* the Free Software Foundation; either version 2 of the License, or
46
* (at your option) any later version.
48
* This program is distributed in the hope that it will be useful,
49
* but WITHOUT ANY WARRANTY; without even the implied warranty of
50
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
51
* GNU General Public License for more details.
53
* You should have received a copy of the GNU General Public License along
54
* with this program; if not, write to the Free Software Foundation, Inc.,
55
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
60
* The following sources were referenced in the design of this implementation
61
* of the Diffie-Hellman-Merkle algorithm:
63
* [1] Handbook of Applied Cryptography - 1997, Chapter 12
64
* Menezes, van Oorschot and Vanstone
68
#if !defined(MBEDTLS_CONFIG_FILE)
69
#include "mbedtls/config.h"
71
#include MBEDTLS_CONFIG_FILE
74
#if defined(MBEDTLS_DHM_C)
76
#include "mbedtls/dhm.h"
77
#include "mbedtls/platform_util.h"
81
#if defined(MBEDTLS_PEM_PARSE_C)
82
#include "mbedtls/pem.h"
85
#if defined(MBEDTLS_ASN1_PARSE_C)
86
#include "mbedtls/asn1.h"
89
#if defined(MBEDTLS_PLATFORM_C)
90
#include "mbedtls/platform.h"
94
#define mbedtls_printf printf
95
#define mbedtls_calloc calloc
96
#define mbedtls_free free
99
#if !defined(MBEDTLS_DHM_ALT)
101
#define DHM_VALIDATE_RET( cond ) \
102
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA )
103
#define DHM_VALIDATE( cond ) \
104
MBEDTLS_INTERNAL_VALIDATE( cond )
107
* helper to validate the mbedtls_mpi size and import it
109
static int dhm_read_bignum( mbedtls_mpi *X,
111
const unsigned char *end )
116
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
118
n = ( (*p)[0] << 8 ) | (*p)[1];
121
if( (int)( end - *p ) < n )
122
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
124
if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 )
125
return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret );
133
* Verify sanity of parameter with regards to P
135
* Parameter should be: 2 <= public_param <= P - 2
137
* This means that we need to return an error if
138
* public_param < 2 or public_param > P-2
140
* For more information on the attack, see:
141
* http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
142
* http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
144
static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
149
mbedtls_mpi_init( &U );
151
MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
153
if( mbedtls_mpi_cmp_int( param, 2 ) < 0 ||
154
mbedtls_mpi_cmp_mpi( param, &U ) > 0 )
156
ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
160
mbedtls_mpi_free( &U );
164
void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
166
DHM_VALIDATE( ctx != NULL );
167
memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
171
* Parse the ServerKeyExchange parameters
173
int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
175
const unsigned char *end )
178
DHM_VALIDATE_RET( ctx != NULL );
179
DHM_VALIDATE_RET( p != NULL && *p != NULL );
180
DHM_VALIDATE_RET( end != NULL );
182
if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
183
( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
184
( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
187
if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
190
ctx->len = mbedtls_mpi_size( &ctx->P );
196
* Pick a random R in the range [2, M-2] for blinding or key generation.
198
static int dhm_random_below( mbedtls_mpi *R, const mbedtls_mpi *M,
199
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
202
size_t m_size = mbedtls_mpi_size( M );
203
size_t m_bitlen = mbedtls_mpi_bitlen( M );
209
return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
211
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( R, m_size, f_rng, p_rng ) );
212
MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( R, ( m_size * 8 ) - m_bitlen ) );
214
while( dhm_check_range( R, M ) != 0 );
220
static int dhm_make_common( mbedtls_dhm_context *ctx, int x_size,
221
int (*f_rng)(void *, unsigned char *, size_t),
226
if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
227
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
229
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
231
if( (unsigned) x_size < mbedtls_mpi_size( &ctx->P ) )
233
MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng ) );
237
/* Generate X as large as possible ( <= P - 2 ) */
238
ret = dhm_random_below( &ctx->X, &ctx->P, f_rng, p_rng );
239
if( ret == MBEDTLS_ERR_MPI_NOT_ACCEPTABLE )
240
return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
246
* Calculate GX = G^X mod P
248
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
249
&ctx->P , &ctx->RP ) );
251
if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
259
* Setup and write the ServerKeyExchange parameters
261
int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
262
unsigned char *output, size_t *olen,
263
int (*f_rng)(void *, unsigned char *, size_t),
269
DHM_VALIDATE_RET( ctx != NULL );
270
DHM_VALIDATE_RET( output != NULL );
271
DHM_VALIDATE_RET( olen != NULL );
272
DHM_VALIDATE_RET( f_rng != NULL );
274
ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
279
* Export P, G, GX. RFC 5246 §4.4 states that "leading zero octets are
280
* not required". We omit leading zeros for compactness.
282
#define DHM_MPI_EXPORT( X, n ) \
284
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
287
*p++ = (unsigned char)( ( n ) >> 8 ); \
288
*p++ = (unsigned char)( ( n ) ); \
292
n1 = mbedtls_mpi_size( &ctx->P );
293
n2 = mbedtls_mpi_size( &ctx->G );
294
n3 = mbedtls_mpi_size( &ctx->GX );
297
DHM_MPI_EXPORT( &ctx->P , n1 );
298
DHM_MPI_EXPORT( &ctx->G , n2 );
299
DHM_MPI_EXPORT( &ctx->GX, n3 );
306
if( ret != 0 && ret > -128 )
307
return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
312
* Set prime modulus and generator
314
int mbedtls_dhm_set_group( mbedtls_dhm_context *ctx,
315
const mbedtls_mpi *P,
316
const mbedtls_mpi *G )
319
DHM_VALIDATE_RET( ctx != NULL );
320
DHM_VALIDATE_RET( P != NULL );
321
DHM_VALIDATE_RET( G != NULL );
323
if( ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ||
324
( ret = mbedtls_mpi_copy( &ctx->G, G ) ) != 0 )
326
return( MBEDTLS_ERR_DHM_SET_GROUP_FAILED + ret );
329
ctx->len = mbedtls_mpi_size( &ctx->P );
334
* Import the peer's public value G^Y
336
int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
337
const unsigned char *input, size_t ilen )
340
DHM_VALIDATE_RET( ctx != NULL );
341
DHM_VALIDATE_RET( input != NULL );
343
if( ilen < 1 || ilen > ctx->len )
344
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
346
if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
347
return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret );
353
* Create own private value X and export G^X
355
int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
356
unsigned char *output, size_t olen,
357
int (*f_rng)(void *, unsigned char *, size_t),
361
DHM_VALIDATE_RET( ctx != NULL );
362
DHM_VALIDATE_RET( output != NULL );
363
DHM_VALIDATE_RET( f_rng != NULL );
365
if( olen < 1 || olen > ctx->len )
366
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
368
ret = dhm_make_common( ctx, x_size, f_rng, p_rng );
369
if( ret == MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED )
370
return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
374
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
377
if( ret != 0 && ret > -128 )
378
return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
385
* Use the blinding method and optimisation suggested in section 10 of:
386
* KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
387
* DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
388
* Berlin Heidelberg, 1996. p. 104-113.
390
static int dhm_update_blinding( mbedtls_dhm_context *ctx,
391
int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
396
mbedtls_mpi_init( &R );
399
* Don't use any blinding the first time a particular X is used,
400
* but remember it to use blinding next time.
402
if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
404
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
405
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
406
MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
412
* Ok, we need blinding. Can we re-use existing values?
413
* If yes, just update them by squaring them.
415
if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
417
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
418
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
420
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
421
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
427
* We need to generate blinding values from scratch
430
/* Vi = random( 2, P-2 ) */
431
MBEDTLS_MPI_CHK( dhm_random_below( &ctx->Vi, &ctx->P, f_rng, p_rng ) );
434
* First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
435
* then elevate to the Xth power. */
436
MBEDTLS_MPI_CHK( dhm_random_below( &R, &ctx->P, f_rng, p_rng ) );
437
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vi, &R ) );
438
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
439
MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vf, &ctx->P ) );
440
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &R ) );
441
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
443
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) );
446
mbedtls_mpi_free( &R );
452
* Derive and export the shared secret (G^Y)^X mod P
454
int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
455
unsigned char *output, size_t output_size, size_t *olen,
456
int (*f_rng)(void *, unsigned char *, size_t),
461
DHM_VALIDATE_RET( ctx != NULL );
462
DHM_VALIDATE_RET( output != NULL );
463
DHM_VALIDATE_RET( olen != NULL );
465
if( output_size < ctx->len )
466
return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
468
if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
471
mbedtls_mpi_init( &GYb );
473
/* Blind peer's value */
476
MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
477
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
478
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
481
MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
483
/* Do modular exponentiation */
484
MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
485
&ctx->P, &ctx->RP ) );
487
/* Unblind secret value */
490
MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
491
MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
494
/* Output the secret without any leading zero byte. This is mandatory
495
* for TLS per RFC 5246 §8.1.2. */
496
*olen = mbedtls_mpi_size( &ctx->K );
497
MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
500
mbedtls_mpi_free( &GYb );
503
return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret );
509
* Free the components of a DHM key
511
void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
516
mbedtls_mpi_free( &ctx->pX );
517
mbedtls_mpi_free( &ctx->Vf );
518
mbedtls_mpi_free( &ctx->Vi );
519
mbedtls_mpi_free( &ctx->RP );
520
mbedtls_mpi_free( &ctx->K );
521
mbedtls_mpi_free( &ctx->GY );
522
mbedtls_mpi_free( &ctx->GX );
523
mbedtls_mpi_free( &ctx->X );
524
mbedtls_mpi_free( &ctx->G );
525
mbedtls_mpi_free( &ctx->P );
527
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
530
#if defined(MBEDTLS_ASN1_PARSE_C)
532
* Parse DHM parameters
534
int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
539
unsigned char *p, *end;
540
#if defined(MBEDTLS_PEM_PARSE_C)
541
mbedtls_pem_context pem;
542
#endif /* MBEDTLS_PEM_PARSE_C */
544
DHM_VALIDATE_RET( dhm != NULL );
545
DHM_VALIDATE_RET( dhmin != NULL );
547
#if defined(MBEDTLS_PEM_PARSE_C)
548
mbedtls_pem_init( &pem );
550
/* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
551
if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
552
ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
554
ret = mbedtls_pem_read_buffer( &pem,
555
"-----BEGIN DH PARAMETERS-----",
556
"-----END DH PARAMETERS-----",
557
dhmin, NULL, 0, &dhminlen );
564
dhminlen = pem.buflen;
566
else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
569
p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
571
p = (unsigned char *) dhmin;
572
#endif /* MBEDTLS_PEM_PARSE_C */
576
* DHParams ::= SEQUENCE {
577
* prime INTEGER, -- P
578
* generator INTEGER, -- g
579
* privateValueLength INTEGER OPTIONAL
582
if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
583
MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
585
ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
591
if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
592
( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
594
ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
600
/* This might be the optional privateValueLength.
601
* If so, we can cleanly discard it */
603
mbedtls_mpi_init( &rec );
604
ret = mbedtls_asn1_get_mpi( &p, end, &rec );
605
mbedtls_mpi_free( &rec );
608
ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
613
ret = MBEDTLS_ERR_DHM_INVALID_FORMAT +
614
MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
621
dhm->len = mbedtls_mpi_size( &dhm->P );
624
#if defined(MBEDTLS_PEM_PARSE_C)
625
mbedtls_pem_free( &pem );
628
mbedtls_dhm_free( dhm );
633
#if defined(MBEDTLS_FS_IO)
635
* Load all data from a file into a given buffer.
637
* The file is expected to contain either PEM or DER encoded data.
638
* A terminating null byte is always appended. It is included in the announced
639
* length only if the data looks like it is PEM encoded.
641
static int load_file( const char *path, unsigned char **buf, size_t *n )
646
if( ( f = fopen( path, "rb" ) ) == NULL )
647
return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
649
fseek( f, 0, SEEK_END );
650
if( ( size = ftell( f ) ) == -1 )
653
return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
655
fseek( f, 0, SEEK_SET );
660
( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
663
return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
666
if( fread( *buf, 1, *n, f ) != *n )
670
mbedtls_platform_zeroize( *buf, *n + 1 );
671
mbedtls_free( *buf );
673
return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
680
if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
687
* Load and parse DHM parameters
689
int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
694
DHM_VALIDATE_RET( dhm != NULL );
695
DHM_VALIDATE_RET( path != NULL );
697
if( ( ret = load_file( path, &buf, &n ) ) != 0 )
700
ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
702
mbedtls_platform_zeroize( buf, n );
707
#endif /* MBEDTLS_FS_IO */
708
#endif /* MBEDTLS_ASN1_PARSE_C */
709
#endif /* MBEDTLS_DHM_ALT */
711
#if defined(MBEDTLS_SELF_TEST)
713
#if defined(MBEDTLS_PEM_PARSE_C)
714
static const char mbedtls_test_dhm_params[] =
715
"-----BEGIN DH PARAMETERS-----\r\n"
716
"MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
717
"1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
718
"9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
719
"-----END DH PARAMETERS-----\r\n";
720
#else /* MBEDTLS_PEM_PARSE_C */
721
static const char mbedtls_test_dhm_params[] = {
722
0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
723
0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
724
0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
725
0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
726
0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
727
0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
728
0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
729
0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
730
0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
731
0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
732
0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
733
0x49, 0x75, 0xb3, 0x02, 0x01, 0x02 };
734
#endif /* MBEDTLS_PEM_PARSE_C */
736
static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
741
int mbedtls_dhm_self_test( int verbose )
744
mbedtls_dhm_context dhm;
746
mbedtls_dhm_init( &dhm );
749
mbedtls_printf( " DHM parameter load: " );
751
if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
752
(const unsigned char *) mbedtls_test_dhm_params,
753
mbedtls_test_dhm_params_len ) ) != 0 )
756
mbedtls_printf( "failed\n" );
763
mbedtls_printf( "passed\n\n" );
766
mbedtls_dhm_free( &dhm );
771
#endif /* MBEDTLS_SELF_TEST */
773
#endif /* MBEDTLS_DHM_C */