dhm.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630
  1. /*
  2. * Diffie-Hellman-Merkle key exchange
  3. *
  4. * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
  5. * SPDX-License-Identifier: GPL-2.0
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License along
  18. * with this program; if not, write to the Free Software Foundation, Inc.,
  19. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  20. *
  21. * This file is part of mbed TLS (https://tls.mbed.org)
  22. */
  23. /*
  24. * The following sources were referenced in the design of this implementation
  25. * of the Diffie-Hellman-Merkle algorithm:
  26. *
  27. * [1] Handbook of Applied Cryptography - 1997, Chapter 12
  28. * Menezes, van Oorschot and Vanstone
  29. *
  30. */
  31. #if !defined(MBEDTLS_CONFIG_FILE)
  32. #include "mbedtls/config.h"
  33. #else
  34. #include MBEDTLS_CONFIG_FILE
  35. #endif
  36. #if defined(MBEDTLS_DHM_C)
  37. #include "mbedtls/dhm.h"
  38. #include <string.h>
  39. #if defined(MBEDTLS_PEM_PARSE_C)
  40. #include "mbedtls/pem.h"
  41. #endif
  42. #if defined(MBEDTLS_ASN1_PARSE_C)
  43. #include "mbedtls/asn1.h"
  44. #endif
  45. #if defined(MBEDTLS_PLATFORM_C)
  46. #include "mbedtls/platform.h"
  47. #else
  48. #include <stdlib.h>
  49. #include <stdio.h>
  50. #define mbedtls_printf printf
  51. #define mbedtls_calloc calloc
  52. #define mbedtls_free free
  53. #endif
  54. /* Implementation that should never be optimized out by the compiler */
  55. static void mbedtls_zeroize( void *v, size_t n ) {
  56. volatile unsigned char *p = v; while( n-- ) *p++ = 0;
  57. }
  58. /*
  59. * helper to validate the mbedtls_mpi size and import it
  60. */
  61. static int dhm_read_bignum( mbedtls_mpi *X,
  62. unsigned char **p,
  63. const unsigned char *end )
  64. {
  65. int ret, n;
  66. if( end - *p < 2 )
  67. return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
  68. n = ( (*p)[0] << 8 ) | (*p)[1];
  69. (*p) += 2;
  70. if( (int)( end - *p ) < n )
  71. return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
  72. if( ( ret = mbedtls_mpi_read_binary( X, *p, n ) ) != 0 )
  73. return( MBEDTLS_ERR_DHM_READ_PARAMS_FAILED + ret );
  74. (*p) += n;
  75. return( 0 );
  76. }
  77. /*
  78. * Verify sanity of parameter with regards to P
  79. *
  80. * Parameter should be: 2 <= public_param <= P - 2
  81. *
  82. * For more information on the attack, see:
  83. * http://www.cl.cam.ac.uk/~rja14/Papers/psandqs.pdf
  84. * http://web.nvd.nist.gov/view/vuln/detail?vulnId=CVE-2005-2643
  85. */
  86. static int dhm_check_range( const mbedtls_mpi *param, const mbedtls_mpi *P )
  87. {
  88. mbedtls_mpi L, U;
  89. int ret = MBEDTLS_ERR_DHM_BAD_INPUT_DATA;
  90. mbedtls_mpi_init( &L ); mbedtls_mpi_init( &U );
  91. MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &L, 2 ) );
  92. MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &U, P, 2 ) );
  93. if( mbedtls_mpi_cmp_mpi( param, &L ) >= 0 &&
  94. mbedtls_mpi_cmp_mpi( param, &U ) <= 0 )
  95. {
  96. ret = 0;
  97. }
  98. cleanup:
  99. mbedtls_mpi_free( &L ); mbedtls_mpi_free( &U );
  100. return( ret );
  101. }
  102. void mbedtls_dhm_init( mbedtls_dhm_context *ctx )
  103. {
  104. memset( ctx, 0, sizeof( mbedtls_dhm_context ) );
  105. }
  106. /*
  107. * Parse the ServerKeyExchange parameters
  108. */
  109. int mbedtls_dhm_read_params( mbedtls_dhm_context *ctx,
  110. unsigned char **p,
  111. const unsigned char *end )
  112. {
  113. int ret;
  114. if( ( ret = dhm_read_bignum( &ctx->P, p, end ) ) != 0 ||
  115. ( ret = dhm_read_bignum( &ctx->G, p, end ) ) != 0 ||
  116. ( ret = dhm_read_bignum( &ctx->GY, p, end ) ) != 0 )
  117. return( ret );
  118. if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
  119. return( ret );
  120. ctx->len = mbedtls_mpi_size( &ctx->P );
  121. return( 0 );
  122. }
  123. /*
  124. * Setup and write the ServerKeyExchange parameters
  125. */
  126. int mbedtls_dhm_make_params( mbedtls_dhm_context *ctx, int x_size,
  127. unsigned char *output, size_t *olen,
  128. int (*f_rng)(void *, unsigned char *, size_t),
  129. void *p_rng )
  130. {
  131. int ret, count = 0;
  132. size_t n1, n2, n3;
  133. unsigned char *p;
  134. if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
  135. return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
  136. /*
  137. * Generate X as large as possible ( < P )
  138. */
  139. do
  140. {
  141. mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng );
  142. while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
  143. MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
  144. if( count++ > 10 )
  145. return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED );
  146. }
  147. while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
  148. /*
  149. * Calculate GX = G^X mod P
  150. */
  151. MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
  152. &ctx->P , &ctx->RP ) );
  153. if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
  154. return( ret );
  155. /*
  156. * export P, G, GX
  157. */
  158. #define DHM_MPI_EXPORT(X,n) \
  159. MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, p + 2, n ) ); \
  160. *p++ = (unsigned char)( n >> 8 ); \
  161. *p++ = (unsigned char)( n ); p += n;
  162. n1 = mbedtls_mpi_size( &ctx->P );
  163. n2 = mbedtls_mpi_size( &ctx->G );
  164. n3 = mbedtls_mpi_size( &ctx->GX );
  165. p = output;
  166. DHM_MPI_EXPORT( &ctx->P , n1 );
  167. DHM_MPI_EXPORT( &ctx->G , n2 );
  168. DHM_MPI_EXPORT( &ctx->GX, n3 );
  169. *olen = p - output;
  170. ctx->len = n1;
  171. cleanup:
  172. if( ret != 0 )
  173. return( MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED + ret );
  174. return( 0 );
  175. }
  176. /*
  177. * Import the peer's public value G^Y
  178. */
  179. int mbedtls_dhm_read_public( mbedtls_dhm_context *ctx,
  180. const unsigned char *input, size_t ilen )
  181. {
  182. int ret;
  183. if( ctx == NULL || ilen < 1 || ilen > ctx->len )
  184. return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
  185. if( ( ret = mbedtls_mpi_read_binary( &ctx->GY, input, ilen ) ) != 0 )
  186. return( MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED + ret );
  187. return( 0 );
  188. }
  189. /*
  190. * Create own private value X and export G^X
  191. */
  192. int mbedtls_dhm_make_public( mbedtls_dhm_context *ctx, int x_size,
  193. unsigned char *output, size_t olen,
  194. int (*f_rng)(void *, unsigned char *, size_t),
  195. void *p_rng )
  196. {
  197. int ret, count = 0;
  198. if( ctx == NULL || olen < 1 || olen > ctx->len )
  199. return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
  200. if( mbedtls_mpi_cmp_int( &ctx->P, 0 ) == 0 )
  201. return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
  202. /*
  203. * generate X and calculate GX = G^X mod P
  204. */
  205. do
  206. {
  207. mbedtls_mpi_fill_random( &ctx->X, x_size, f_rng, p_rng );
  208. while( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) >= 0 )
  209. MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->X, 1 ) );
  210. if( count++ > 10 )
  211. return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED );
  212. }
  213. while( dhm_check_range( &ctx->X, &ctx->P ) != 0 );
  214. MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->GX, &ctx->G, &ctx->X,
  215. &ctx->P , &ctx->RP ) );
  216. if( ( ret = dhm_check_range( &ctx->GX, &ctx->P ) ) != 0 )
  217. return( ret );
  218. MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->GX, output, olen ) );
  219. cleanup:
  220. if( ret != 0 )
  221. return( MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED + ret );
  222. return( 0 );
  223. }
  224. /*
  225. * Use the blinding method and optimisation suggested in section 10 of:
  226. * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA,
  227. * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer
  228. * Berlin Heidelberg, 1996. p. 104-113.
  229. */
  230. static int dhm_update_blinding( mbedtls_dhm_context *ctx,
  231. int (*f_rng)(void *, unsigned char *, size_t), void *p_rng )
  232. {
  233. int ret, count;
  234. /*
  235. * Don't use any blinding the first time a particular X is used,
  236. * but remember it to use blinding next time.
  237. */
  238. if( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->pX ) != 0 )
  239. {
  240. MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &ctx->pX, &ctx->X ) );
  241. MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vi, 1 ) );
  242. MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->Vf, 1 ) );
  243. return( 0 );
  244. }
  245. /*
  246. * Ok, we need blinding. Can we re-use existing values?
  247. * If yes, just update them by squaring them.
  248. */
  249. if( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 )
  250. {
  251. MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) );
  252. MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->P ) );
  253. MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) );
  254. MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->P ) );
  255. return( 0 );
  256. }
  257. /*
  258. * We need to generate blinding values from scratch
  259. */
  260. /* Vi = random( 2, P-1 ) */
  261. count = 0;
  262. do
  263. {
  264. mbedtls_mpi_fill_random( &ctx->Vi, mbedtls_mpi_size( &ctx->P ), f_rng, p_rng );
  265. while( mbedtls_mpi_cmp_mpi( &ctx->Vi, &ctx->P ) >= 0 )
  266. MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &ctx->Vi, 1 ) );
  267. if( count++ > 10 )
  268. return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE );
  269. }
  270. while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) <= 0 );
  271. /* Vf = Vi^-X mod P */
  272. MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vf, &ctx->Vi, &ctx->P ) );
  273. MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vf, &ctx->Vf, &ctx->X, &ctx->P, &ctx->RP ) );
  274. cleanup:
  275. return( ret );
  276. }
  277. /*
  278. * Derive and export the shared secret (G^Y)^X mod P
  279. */
  280. int mbedtls_dhm_calc_secret( mbedtls_dhm_context *ctx,
  281. unsigned char *output, size_t output_size, size_t *olen,
  282. int (*f_rng)(void *, unsigned char *, size_t),
  283. void *p_rng )
  284. {
  285. int ret;
  286. mbedtls_mpi GYb;
  287. if( ctx == NULL || output_size < ctx->len )
  288. return( MBEDTLS_ERR_DHM_BAD_INPUT_DATA );
  289. if( ( ret = dhm_check_range( &ctx->GY, &ctx->P ) ) != 0 )
  290. return( ret );
  291. mbedtls_mpi_init( &GYb );
  292. /* Blind peer's value */
  293. if( f_rng != NULL )
  294. {
  295. MBEDTLS_MPI_CHK( dhm_update_blinding( ctx, f_rng, p_rng ) );
  296. MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &GYb, &ctx->GY, &ctx->Vi ) );
  297. MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &GYb, &GYb, &ctx->P ) );
  298. }
  299. else
  300. MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &GYb, &ctx->GY ) );
  301. /* Do modular exponentiation */
  302. MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->K, &GYb, &ctx->X,
  303. &ctx->P, &ctx->RP ) );
  304. /* Unblind secret value */
  305. if( f_rng != NULL )
  306. {
  307. MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->K, &ctx->K, &ctx->Vf ) );
  308. MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->K, &ctx->K, &ctx->P ) );
  309. }
  310. *olen = mbedtls_mpi_size( &ctx->K );
  311. MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->K, output, *olen ) );
  312. cleanup:
  313. mbedtls_mpi_free( &GYb );
  314. if( ret != 0 )
  315. return( MBEDTLS_ERR_DHM_CALC_SECRET_FAILED + ret );
  316. return( 0 );
  317. }
  318. /*
  319. * Free the components of a DHM key
  320. */
  321. void mbedtls_dhm_free( mbedtls_dhm_context *ctx )
  322. {
  323. mbedtls_mpi_free( &ctx->pX); mbedtls_mpi_free( &ctx->Vf ); mbedtls_mpi_free( &ctx->Vi );
  324. mbedtls_mpi_free( &ctx->RP ); mbedtls_mpi_free( &ctx->K ); mbedtls_mpi_free( &ctx->GY );
  325. mbedtls_mpi_free( &ctx->GX ); mbedtls_mpi_free( &ctx->X ); mbedtls_mpi_free( &ctx->G );
  326. mbedtls_mpi_free( &ctx->P );
  327. mbedtls_zeroize( ctx, sizeof( mbedtls_dhm_context ) );
  328. }
  329. #if defined(MBEDTLS_ASN1_PARSE_C)
  330. /*
  331. * Parse DHM parameters
  332. */
  333. int mbedtls_dhm_parse_dhm( mbedtls_dhm_context *dhm, const unsigned char *dhmin,
  334. size_t dhminlen )
  335. {
  336. int ret;
  337. size_t len;
  338. unsigned char *p, *end;
  339. #if defined(MBEDTLS_PEM_PARSE_C)
  340. mbedtls_pem_context pem;
  341. mbedtls_pem_init( &pem );
  342. /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */
  343. if( dhminlen == 0 || dhmin[dhminlen - 1] != '\0' )
  344. ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT;
  345. else
  346. ret = mbedtls_pem_read_buffer( &pem,
  347. "-----BEGIN DH PARAMETERS-----",
  348. "-----END DH PARAMETERS-----",
  349. dhmin, NULL, 0, &dhminlen );
  350. if( ret == 0 )
  351. {
  352. /*
  353. * Was PEM encoded
  354. */
  355. dhminlen = pem.buflen;
  356. }
  357. else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT )
  358. goto exit;
  359. p = ( ret == 0 ) ? pem.buf : (unsigned char *) dhmin;
  360. #else
  361. p = (unsigned char *) dhmin;
  362. #endif /* MBEDTLS_PEM_PARSE_C */
  363. end = p + dhminlen;
  364. /*
  365. * DHParams ::= SEQUENCE {
  366. * prime INTEGER, -- P
  367. * generator INTEGER, -- g
  368. * privateValueLength INTEGER OPTIONAL
  369. * }
  370. */
  371. if( ( ret = mbedtls_asn1_get_tag( &p, end, &len,
  372. MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 )
  373. {
  374. ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
  375. goto exit;
  376. }
  377. end = p + len;
  378. if( ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->P ) ) != 0 ||
  379. ( ret = mbedtls_asn1_get_mpi( &p, end, &dhm->G ) ) != 0 )
  380. {
  381. ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
  382. goto exit;
  383. }
  384. if( p != end )
  385. {
  386. /* This might be the optional privateValueLength.
  387. * If so, we can cleanly discard it */
  388. mbedtls_mpi rec;
  389. mbedtls_mpi_init( &rec );
  390. ret = mbedtls_asn1_get_mpi( &p, end, &rec );
  391. mbedtls_mpi_free( &rec );
  392. if ( ret != 0 )
  393. {
  394. ret = MBEDTLS_ERR_DHM_INVALID_FORMAT + ret;
  395. goto exit;
  396. }
  397. if ( p != end )
  398. {
  399. ret = MBEDTLS_ERR_DHM_INVALID_FORMAT +
  400. MBEDTLS_ERR_ASN1_LENGTH_MISMATCH;
  401. goto exit;
  402. }
  403. }
  404. ret = 0;
  405. dhm->len = mbedtls_mpi_size( &dhm->P );
  406. exit:
  407. #if defined(MBEDTLS_PEM_PARSE_C)
  408. mbedtls_pem_free( &pem );
  409. #endif
  410. if( ret != 0 )
  411. mbedtls_dhm_free( dhm );
  412. return( ret );
  413. }
  414. #if defined(MBEDTLS_FS_IO)
  415. /*
  416. * Load all data from a file into a given buffer.
  417. *
  418. * The file is expected to contain either PEM or DER encoded data.
  419. * A terminating null byte is always appended. It is included in the announced
  420. * length only if the data looks like it is PEM encoded.
  421. */
  422. static int load_file( const char *path, unsigned char **buf, size_t *n )
  423. {
  424. FILE *f;
  425. long size;
  426. if( ( f = fopen( path, "rb" ) ) == NULL )
  427. return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
  428. fseek( f, 0, SEEK_END );
  429. if( ( size = ftell( f ) ) == -1 )
  430. {
  431. fclose( f );
  432. return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
  433. }
  434. fseek( f, 0, SEEK_SET );
  435. *n = (size_t) size;
  436. if( *n + 1 == 0 ||
  437. ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL )
  438. {
  439. fclose( f );
  440. return( MBEDTLS_ERR_DHM_ALLOC_FAILED );
  441. }
  442. if( fread( *buf, 1, *n, f ) != *n )
  443. {
  444. fclose( f );
  445. mbedtls_free( *buf );
  446. return( MBEDTLS_ERR_DHM_FILE_IO_ERROR );
  447. }
  448. fclose( f );
  449. (*buf)[*n] = '\0';
  450. if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL )
  451. ++*n;
  452. return( 0 );
  453. }
  454. /*
  455. * Load and parse DHM parameters
  456. */
  457. int mbedtls_dhm_parse_dhmfile( mbedtls_dhm_context *dhm, const char *path )
  458. {
  459. int ret;
  460. size_t n;
  461. unsigned char *buf;
  462. if( ( ret = load_file( path, &buf, &n ) ) != 0 )
  463. return( ret );
  464. ret = mbedtls_dhm_parse_dhm( dhm, buf, n );
  465. mbedtls_zeroize( buf, n );
  466. mbedtls_free( buf );
  467. return( ret );
  468. }
  469. #endif /* MBEDTLS_FS_IO */
  470. #endif /* MBEDTLS_ASN1_PARSE_C */
  471. #if defined(MBEDTLS_SELF_TEST)
  472. static const char mbedtls_test_dhm_params[] =
  473. "-----BEGIN DH PARAMETERS-----\r\n"
  474. "MIGHAoGBAJ419DBEOgmQTzo5qXl5fQcN9TN455wkOL7052HzxxRVMyhYmwQcgJvh\r\n"
  475. "1sa18fyfR9OiVEMYglOpkqVoGLN7qd5aQNNi5W7/C+VBdHTBJcGZJyyP5B3qcz32\r\n"
  476. "9mLJKudlVudV0Qxk5qUJaPZ/xupz0NyoVpviuiBOI1gNi8ovSXWzAgEC\r\n"
  477. "-----END DH PARAMETERS-----\r\n";
  478. static const size_t mbedtls_test_dhm_params_len = sizeof( mbedtls_test_dhm_params );
  479. /*
  480. * Checkup routine
  481. */
  482. int mbedtls_dhm_self_test( int verbose )
  483. {
  484. int ret;
  485. mbedtls_dhm_context dhm;
  486. mbedtls_dhm_init( &dhm );
  487. if( verbose != 0 )
  488. mbedtls_printf( " DHM parameter load: " );
  489. if( ( ret = mbedtls_dhm_parse_dhm( &dhm,
  490. (const unsigned char *) mbedtls_test_dhm_params,
  491. mbedtls_test_dhm_params_len ) ) != 0 )
  492. {
  493. if( verbose != 0 )
  494. mbedtls_printf( "failed\n" );
  495. ret = 1;
  496. goto exit;
  497. }
  498. if( verbose != 0 )
  499. mbedtls_printf( "passed\n\n" );
  500. exit:
  501. mbedtls_dhm_free( &dhm );
  502. return( ret );
  503. }
  504. #endif /* MBEDTLS_SELF_TEST */
  505. #endif /* MBEDTLS_DHM_C */