2 * Diffie-Hellman-Merkle key exchange
4 * Copyright The Mbed TLS Contributors
5 * SPDX-License-Identifier: Apache-2.0
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
11 * http://www.apache.org/licenses/LICENSE-2.0
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.
20 * The following sources were referenced in the design of this implementation
21 * of the Diffie-Hellman-Merkle algorithm:
23 * [1] Handbook of Applied Cryptography - 1997, Chapter 12
24 * Menezes, van Oorschot and Vanstone
30 #if defined(MBEDTLS_DHM_C)
32 #include "mbedtls/dhm.h"
33 #include "mbedtls/platform_util.h"
34 #include "mbedtls/error.h"
38 #if defined(MBEDTLS_PEM_PARSE_C)
39 #include "mbedtls/pem.h"
42 #if defined(MBEDTLS_ASN1_PARSE_C)
43 #include "mbedtls/asn1.h"
46 #if defined(MBEDTLS_PLATFORM_C)
47 #include "mbedtls/platform.h"
51 #define mbedtls_printf printf
52 #define mbedtls_calloc calloc
53 #define mbedtls_free free
56 #if !defined(MBEDTLS_DHM_ALT)
58 #define DHM_VALIDATE_RET( cond ) \
59 MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_DHM_BAD_INPUT_DATA )
60 #define DHM_VALIDATE( cond ) \
61 MBEDTLS_INTERNAL_VALIDATE( cond )
64 * helper to validate the mbedtls_mpi size and import it
66 static int dhm_read_bignum(mbedtls_mpi
*X
,
68 const unsigned char *end
) {
72 return (MBEDTLS_ERR_DHM_BAD_INPUT_DATA
);
74 n
= ((*p
)[0] << 8) | (*p
)[1];
77 if ((int)(end
- *p
) < n
)
78 return (MBEDTLS_ERR_DHM_BAD_INPUT_DATA
);
80 if ((ret
= mbedtls_mpi_read_binary(X
, *p
, n
)) != 0)
81 return (MBEDTLS_ERR_DHM_READ_PARAMS_FAILED
+ ret
);
89 * Verify sanity of parameter with regards to P
91 * Parameter should be: 2 <= public_param <= P - 2
93 * This means that we need to return an error if
94 * public_param < 2 or public_param > P-2
96 * For more information on the attack, see:
97 * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
98 * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
100 static int dhm_check_range(const mbedtls_mpi
*param
, const mbedtls_mpi
*P
) {
104 mbedtls_mpi_init(&L
);
105 mbedtls_mpi_init(&U
);
107 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&L
, 2));
108 MBEDTLS_MPI_CHK(mbedtls_mpi_sub_int(&U
, P
, 2));
110 if (mbedtls_mpi_cmp_mpi(param
, &L
) < 0 ||
111 mbedtls_mpi_cmp_mpi(param
, &U
) > 0) {
112 ret
= MBEDTLS_ERR_DHM_BAD_INPUT_DATA
;
116 mbedtls_mpi_free(&L
);
117 mbedtls_mpi_free(&U
);
121 void mbedtls_dhm_init(mbedtls_dhm_context
*ctx
) {
122 DHM_VALIDATE(ctx
!= NULL
);
123 memset(ctx
, 0, sizeof(mbedtls_dhm_context
));
127 * Parse the ServerKeyExchange parameters
129 int mbedtls_dhm_read_params(mbedtls_dhm_context
*ctx
,
131 const unsigned char *end
) {
132 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
133 DHM_VALIDATE_RET(ctx
!= NULL
);
134 DHM_VALIDATE_RET(p
!= NULL
&& *p
!= NULL
);
135 DHM_VALIDATE_RET(end
!= NULL
);
137 if ((ret
= dhm_read_bignum(&ctx
->P
, p
, end
)) != 0 ||
138 (ret
= dhm_read_bignum(&ctx
->G
, p
, end
)) != 0 ||
139 (ret
= dhm_read_bignum(&ctx
->GY
, p
, end
)) != 0)
142 if ((ret
= dhm_check_range(&ctx
->GY
, &ctx
->P
)) != 0)
145 ctx
->len
= mbedtls_mpi_size(&ctx
->P
);
151 * Setup and write the ServerKeyExchange parameters
153 int mbedtls_dhm_make_params(mbedtls_dhm_context
*ctx
, int x_size
,
154 unsigned char *output
, size_t *olen
,
155 int (*f_rng
)(void *, unsigned char *, size_t),
160 DHM_VALIDATE_RET(ctx
!= NULL
);
161 DHM_VALIDATE_RET(output
!= NULL
);
162 DHM_VALIDATE_RET(olen
!= NULL
);
163 DHM_VALIDATE_RET(f_rng
!= NULL
);
165 if (mbedtls_mpi_cmp_int(&ctx
->P
, 0) == 0)
166 return (MBEDTLS_ERR_DHM_BAD_INPUT_DATA
);
169 * Generate X as large as possible ( < P )
172 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx
->X
, x_size
, f_rng
, p_rng
));
174 while (mbedtls_mpi_cmp_mpi(&ctx
->X
, &ctx
->P
) >= 0)
175 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&ctx
->X
, 1));
178 return (MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED
);
179 } while (dhm_check_range(&ctx
->X
, &ctx
->P
) != 0);
182 * Calculate GX = G^X mod P
184 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx
->GX
, &ctx
->G
, &ctx
->X
,
187 if ((ret
= dhm_check_range(&ctx
->GX
, &ctx
->P
)) != 0)
193 #define DHM_MPI_EXPORT( X, n ) \
195 MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( ( X ), \
198 *p++ = (unsigned char)( ( n ) >> 8 ); \
199 *p++ = (unsigned char)( ( n ) ); \
203 n1
= mbedtls_mpi_size(&ctx
->P
);
204 n2
= mbedtls_mpi_size(&ctx
->G
);
205 n3
= mbedtls_mpi_size(&ctx
->GX
);
208 DHM_MPI_EXPORT(&ctx
->P
, n1
);
209 DHM_MPI_EXPORT(&ctx
->G
, n2
);
210 DHM_MPI_EXPORT(&ctx
->GX
, n3
);
219 return (MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED
+ ret
);
225 * Set prime modulus and generator
227 int mbedtls_dhm_set_group(mbedtls_dhm_context
*ctx
,
228 const mbedtls_mpi
*P
,
229 const mbedtls_mpi
*G
) {
230 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
231 DHM_VALIDATE_RET(ctx
!= NULL
);
232 DHM_VALIDATE_RET(P
!= NULL
);
233 DHM_VALIDATE_RET(G
!= NULL
);
235 if ((ret
= mbedtls_mpi_copy(&ctx
->P
, P
)) != 0 ||
236 (ret
= mbedtls_mpi_copy(&ctx
->G
, G
)) != 0) {
237 return (MBEDTLS_ERR_DHM_SET_GROUP_FAILED
+ ret
);
240 ctx
->len
= mbedtls_mpi_size(&ctx
->P
);
245 * Import the peer's public value G^Y
247 int mbedtls_dhm_read_public(mbedtls_dhm_context
*ctx
,
248 const unsigned char *input
, size_t ilen
) {
249 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
250 DHM_VALIDATE_RET(ctx
!= NULL
);
251 DHM_VALIDATE_RET(input
!= NULL
);
253 if (ilen
< 1 || ilen
> ctx
->len
)
254 return (MBEDTLS_ERR_DHM_BAD_INPUT_DATA
);
256 if ((ret
= mbedtls_mpi_read_binary(&ctx
->GY
, input
, ilen
)) != 0)
257 return (MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED
+ ret
);
263 * Create own private value X and export G^X
265 int mbedtls_dhm_make_public(mbedtls_dhm_context
*ctx
, int x_size
,
266 unsigned char *output
, size_t olen
,
267 int (*f_rng
)(void *, unsigned char *, size_t),
270 DHM_VALIDATE_RET(ctx
!= NULL
);
271 DHM_VALIDATE_RET(output
!= NULL
);
272 DHM_VALIDATE_RET(f_rng
!= NULL
);
274 if (olen
< 1 || olen
> ctx
->len
)
275 return (MBEDTLS_ERR_DHM_BAD_INPUT_DATA
);
277 if (mbedtls_mpi_cmp_int(&ctx
->P
, 0) == 0)
278 return (MBEDTLS_ERR_DHM_BAD_INPUT_DATA
);
281 * generate X and calculate GX = G^X mod P
284 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(&ctx
->X
, x_size
, f_rng
, p_rng
));
286 while (mbedtls_mpi_cmp_mpi(&ctx
->X
, &ctx
->P
) >= 0)
287 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(&ctx
->X
, 1));
290 return (MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED
);
291 } while (dhm_check_range(&ctx
->X
, &ctx
->P
) != 0);
293 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx
->GX
, &ctx
->G
, &ctx
->X
,
296 if ((ret
= dhm_check_range(&ctx
->GX
, &ctx
->P
)) != 0)
299 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx
->GX
, output
, olen
));
304 return (MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED
+ ret
);
310 * Pick a random R in the range [2, M) for blinding purposes
312 static int dhm_random_below(mbedtls_mpi
*R
, const mbedtls_mpi
*M
,
313 int (*f_rng
)(void *, unsigned char *, size_t), void *p_rng
) {
318 MBEDTLS_MPI_CHK(mbedtls_mpi_fill_random(R
, mbedtls_mpi_size(M
), f_rng
, p_rng
));
320 while (mbedtls_mpi_cmp_mpi(R
, M
) >= 0)
321 MBEDTLS_MPI_CHK(mbedtls_mpi_shift_r(R
, 1));
324 return (MBEDTLS_ERR_MPI_NOT_ACCEPTABLE
);
325 } while (mbedtls_mpi_cmp_int(R
, 1) <= 0);
333 * Use the blinding method and optimisation suggested in section 10 of:
334 * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
335 * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
336 * Berlin Heidelberg, 1996. p. 104-113.
338 static int dhm_update_blinding(mbedtls_dhm_context
*ctx
,
339 int (*f_rng
)(void *, unsigned char *, size_t), void *p_rng
) {
343 mbedtls_mpi_init(&R
);
346 * Don't use any blinding the first time a particular X is used,
347 * but remember it to use blinding next time.
349 if (mbedtls_mpi_cmp_mpi(&ctx
->X
, &ctx
->pX
) != 0) {
350 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&ctx
->pX
, &ctx
->X
));
351 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx
->Vi
, 1));
352 MBEDTLS_MPI_CHK(mbedtls_mpi_lset(&ctx
->Vf
, 1));
358 * Ok, we need blinding. Can we re-use existing values?
359 * If yes, just update them by squaring them.
361 if (mbedtls_mpi_cmp_int(&ctx
->Vi
, 1) != 0) {
362 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx
->Vi
, &ctx
->Vi
, &ctx
->Vi
));
363 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx
->Vi
, &ctx
->Vi
, &ctx
->P
));
365 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx
->Vf
, &ctx
->Vf
, &ctx
->Vf
));
366 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx
->Vf
, &ctx
->Vf
, &ctx
->P
));
372 * We need to generate blinding values from scratch
375 /* Vi = random( 2, P-1 ) */
376 MBEDTLS_MPI_CHK(dhm_random_below(&ctx
->Vi
, &ctx
->P
, f_rng
, p_rng
));
379 * First compute Vi^-1 = R * (R Vi)^-1, (avoiding leaks from inv_mod),
380 * then elevate to the Xth power. */
381 MBEDTLS_MPI_CHK(dhm_random_below(&R
, &ctx
->P
, f_rng
, p_rng
));
382 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx
->Vf
, &ctx
->Vi
, &R
));
383 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx
->Vf
, &ctx
->Vf
, &ctx
->P
));
384 MBEDTLS_MPI_CHK(mbedtls_mpi_inv_mod(&ctx
->Vf
, &ctx
->Vf
, &ctx
->P
));
385 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx
->Vf
, &ctx
->Vf
, &R
));
386 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx
->Vf
, &ctx
->Vf
, &ctx
->P
));
388 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx
->Vf
, &ctx
->Vf
, &ctx
->X
, &ctx
->P
, &ctx
->RP
));
391 mbedtls_mpi_free(&R
);
397 * Derive and export the shared secret (G^Y)^X mod P
399 int mbedtls_dhm_calc_secret(mbedtls_dhm_context
*ctx
,
400 unsigned char *output
, size_t output_size
, size_t *olen
,
401 int (*f_rng
)(void *, unsigned char *, size_t),
403 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
405 DHM_VALIDATE_RET(ctx
!= NULL
);
406 DHM_VALIDATE_RET(output
!= NULL
);
407 DHM_VALIDATE_RET(olen
!= NULL
);
409 if (output_size
< ctx
->len
)
410 return (MBEDTLS_ERR_DHM_BAD_INPUT_DATA
);
412 if ((ret
= dhm_check_range(&ctx
->GY
, &ctx
->P
)) != 0)
415 mbedtls_mpi_init(&GYb
);
417 /* Blind peer's value */
419 MBEDTLS_MPI_CHK(dhm_update_blinding(ctx
, f_rng
, p_rng
));
420 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&GYb
, &ctx
->GY
, &ctx
->Vi
));
421 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&GYb
, &GYb
, &ctx
->P
));
423 MBEDTLS_MPI_CHK(mbedtls_mpi_copy(&GYb
, &ctx
->GY
));
425 /* Do modular exponentiation */
426 MBEDTLS_MPI_CHK(mbedtls_mpi_exp_mod(&ctx
->K
, &GYb
, &ctx
->X
,
429 /* Unblind secret value */
431 MBEDTLS_MPI_CHK(mbedtls_mpi_mul_mpi(&ctx
->K
, &ctx
->K
, &ctx
->Vf
));
432 MBEDTLS_MPI_CHK(mbedtls_mpi_mod_mpi(&ctx
->K
, &ctx
->K
, &ctx
->P
));
435 *olen
= mbedtls_mpi_size(&ctx
->K
);
437 MBEDTLS_MPI_CHK(mbedtls_mpi_write_binary(&ctx
->K
, output
, *olen
));
440 mbedtls_mpi_free(&GYb
);
443 return (MBEDTLS_ERR_DHM_CALC_SECRET_FAILED
+ ret
);
449 * Free the components of a DHM key
451 void mbedtls_dhm_free(mbedtls_dhm_context
*ctx
) {
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
);
466 mbedtls_platform_zeroize(ctx
, sizeof(mbedtls_dhm_context
));
469 #if defined(MBEDTLS_ASN1_PARSE_C)
471 * Parse DHM parameters
473 int mbedtls_dhm_parse_dhm(mbedtls_dhm_context
*dhm
, const unsigned char *dhmin
,
475 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
477 unsigned char *p
, *end
;
478 #if defined(MBEDTLS_PEM_PARSE_C)
479 mbedtls_pem_context pem
;
480 #endif /* MBEDTLS_PEM_PARSE_C */
482 DHM_VALIDATE_RET(dhm
!= NULL
);
483 DHM_VALIDATE_RET(dhmin
!= NULL
);
485 #if defined(MBEDTLS_PEM_PARSE_C)
486 mbedtls_pem_init(&pem
);
488 /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
489 if (dhminlen
== 0 || dhmin
[dhminlen
- 1] != '\0')
490 ret
= MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT
;
492 ret
= mbedtls_pem_read_buffer(&pem
,
493 "-----BEGIN DH PARAMETERS-----",
494 "-----END DH PARAMETERS-----",
495 dhmin
, NULL
, 0, &dhminlen
);
501 dhminlen
= pem
.buflen
;
502 } else if (ret
!= MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT
)
505 p
= (ret
== 0) ? pem
.buf
: (unsigned char *) dhmin
;
507 p
= (unsigned char *) dhmin
;
508 #endif /* MBEDTLS_PEM_PARSE_C */
512 * DHParams ::= SEQUENCE {
513 * prime INTEGER, -- P
514 * generator INTEGER, -- g
515 * privateValueLength INTEGER OPTIONAL
518 if ((ret
= mbedtls_asn1_get_tag(&p
, end
, &len
,
519 MBEDTLS_ASN1_CONSTRUCTED
| MBEDTLS_ASN1_SEQUENCE
)) != 0) {
520 ret
= MBEDTLS_ERR_DHM_INVALID_FORMAT
+ ret
;
526 if ((ret
= mbedtls_asn1_get_mpi(&p
, end
, &dhm
->P
)) != 0 ||
527 (ret
= mbedtls_asn1_get_mpi(&p
, end
, &dhm
->G
)) != 0) {
528 ret
= MBEDTLS_ERR_DHM_INVALID_FORMAT
+ ret
;
533 /* This might be the optional privateValueLength.
534 * If so, we can cleanly discard it */
536 mbedtls_mpi_init(&rec
);
537 ret
= mbedtls_asn1_get_mpi(&p
, end
, &rec
);
538 mbedtls_mpi_free(&rec
);
540 ret
= MBEDTLS_ERR_DHM_INVALID_FORMAT
+ ret
;
544 ret
= MBEDTLS_ERR_DHM_INVALID_FORMAT
+
545 MBEDTLS_ERR_ASN1_LENGTH_MISMATCH
;
552 dhm
->len
= mbedtls_mpi_size(&dhm
->P
);
555 #if defined(MBEDTLS_PEM_PARSE_C)
556 mbedtls_pem_free(&pem
);
559 mbedtls_dhm_free(dhm
);
564 #if defined(MBEDTLS_FS_IO)
566 * Load all data from a file into a given buffer.
568 * The file is expected to contain either PEM or DER encoded data.
569 * A terminating null byte is always appended. It is included in the announced
570 * length only if the data looks like it is PEM encoded.
572 static int load_file(const char *path
, unsigned char **buf
, size_t *n
) {
576 if ((f
= fopen(path
, "rb")) == NULL
)
577 return (MBEDTLS_ERR_DHM_FILE_IO_ERROR
);
579 fseek(f
, 0, SEEK_END
);
580 if ((size
= ftell(f
)) == -1) {
582 return (MBEDTLS_ERR_DHM_FILE_IO_ERROR
);
584 fseek(f
, 0, SEEK_SET
);
589 (*buf
= mbedtls_calloc(1, *n
+ 1)) == NULL
) {
591 return (MBEDTLS_ERR_DHM_ALLOC_FAILED
);
594 if (fread(*buf
, 1, *n
, f
) != *n
) {
597 mbedtls_platform_zeroize(*buf
, *n
+ 1);
600 return (MBEDTLS_ERR_DHM_FILE_IO_ERROR
);
607 if (strstr((const char *) *buf
, "-----BEGIN ") != NULL
)
614 * Load and parse DHM parameters
616 int mbedtls_dhm_parse_dhmfile(mbedtls_dhm_context
*dhm
, const char *path
) {
617 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
620 DHM_VALIDATE_RET(dhm
!= NULL
);
621 DHM_VALIDATE_RET(path
!= NULL
);
623 if ((ret
= load_file(path
, &buf
, &n
)) != 0)
626 ret
= mbedtls_dhm_parse_dhm(dhm
, buf
, n
);
628 mbedtls_platform_zeroize(buf
, n
);
633 #endif /* MBEDTLS_FS_IO */
634 #endif /* MBEDTLS_ASN1_PARSE_C */
635 #endif /* MBEDTLS_DHM_ALT */
637 #if defined(MBEDTLS_SELF_TEST)
639 #if defined(MBEDTLS_PEM_PARSE_C)
640 static const char mbedtls_test_dhm_params
[] =
641 "-----BEGIN DH PARAMETERS-----\r\n"
642 "MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
643 "1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
644 "9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
645 "-----END DH PARAMETERS-----\r\n";
646 #else /* MBEDTLS_PEM_PARSE_C */
647 static const char mbedtls_test_dhm_params
[] = {
648 0x30, 0x81, 0x87, 0x02, 0x81, 0x81, 0x00, 0x9e, 0x35, 0xf4, 0x30, 0x44,
649 0x3a, 0x09, 0x90, 0x4f, 0x3a, 0x39, 0xa9, 0x79, 0x79, 0x7d, 0x07, 0x0d,
650 0xf5, 0x33, 0x78, 0xe7, 0x9c, 0x24, 0x38, 0xbe, 0xf4, 0xe7, 0x61, 0xf3,
651 0xc7, 0x14, 0x55, 0x33, 0x28, 0x58, 0x9b, 0x04, 0x1c, 0x80, 0x9b, 0xe1,
652 0xd6, 0xc6, 0xb5, 0xf1, 0xfc, 0x9f, 0x47, 0xd3, 0xa2, 0x54, 0x43, 0x18,
653 0x82, 0x53, 0xa9, 0x92, 0xa5, 0x68, 0x18, 0xb3, 0x7b, 0xa9, 0xde, 0x5a,
654 0x40, 0xd3, 0x62, 0xe5, 0x6e, 0xff, 0x0b, 0xe5, 0x41, 0x74, 0x74, 0xc1,
655 0x25, 0xc1, 0x99, 0x27, 0x2c, 0x8f, 0xe4, 0x1d, 0xea, 0x73, 0x3d, 0xf6,
656 0xf6, 0x62, 0xc9, 0x2a, 0xe7, 0x65, 0x56, 0xe7, 0x55, 0xd1, 0x0c, 0x64,
657 0xe6, 0xa5, 0x09, 0x68, 0xf6, 0x7f, 0xc6, 0xea, 0x73, 0xd0, 0xdc, 0xa8,
658 0x56, 0x9b, 0xe2, 0xba, 0x20, 0x4e, 0x23, 0x58, 0x0d, 0x8b, 0xca, 0x2f,
659 0x49, 0x75, 0xb3, 0x02, 0x01, 0x02
661 #endif /* MBEDTLS_PEM_PARSE_C */
663 static const size_t mbedtls_test_dhm_params_len
= sizeof(mbedtls_test_dhm_params
);
668 int mbedtls_dhm_self_test(int verbose
) {
669 int ret
= MBEDTLS_ERR_ERROR_CORRUPTION_DETECTED
;
670 mbedtls_dhm_context dhm
;
672 mbedtls_dhm_init(&dhm
);
675 mbedtls_printf(" DHM parameter load: ");
677 if ((ret
= mbedtls_dhm_parse_dhm(&dhm
,
678 (const unsigned char *) mbedtls_test_dhm_params
,
679 mbedtls_test_dhm_params_len
)) != 0) {
681 mbedtls_printf("failed\n");
688 mbedtls_printf("passed\n\n");
691 mbedtls_dhm_free(&dhm
);
696 #endif /* MBEDTLS_SELF_TEST */
698 #endif /* MBEDTLS_DHM_C */