1/* BEGIN_HEADER */ 2#include "mbedtls/dhm.h" 3 4/* Sanity checks on a Diffie-Hellman parameter: check the length-value 5 * syntax and check that the value is the expected one (taken from the 6 * DHM context by the caller). */ 7static int check_dhm_param_output( const mbedtls_mpi *expected, 8 const unsigned char *buffer, 9 size_t size, 10 size_t *offset ) 11{ 12 size_t n; 13 mbedtls_mpi actual; 14 int ok = 0; 15 mbedtls_mpi_init( &actual ); 16 17 ++mbedtls_test_info.step; 18 19 TEST_ASSERT( size >= *offset + 2 ); 20 n = ( buffer[*offset] << 8 ) | buffer[*offset + 1]; 21 *offset += 2; 22 /* The DHM param output from Mbed TLS has leading zeros stripped, as 23 * permitted but not required by RFC 5246 \S4.4. */ 24 TEST_EQUAL( n, mbedtls_mpi_size( expected ) ); 25 TEST_ASSERT( size >= *offset + n ); 26 TEST_EQUAL( 0, mbedtls_mpi_read_binary( &actual, buffer + *offset, n ) ); 27 TEST_EQUAL( 0, mbedtls_mpi_cmp_mpi( expected, &actual ) ); 28 *offset += n; 29 30 ok = 1; 31exit: 32 mbedtls_mpi_free( &actual ); 33 return( ok ); 34} 35 36/* Sanity checks on Diffie-Hellman parameters: syntax, range, and comparison 37 * against the context. */ 38static int check_dhm_params( const mbedtls_dhm_context *ctx, 39 size_t x_size, 40 const unsigned char *ske, size_t ske_len ) 41{ 42 size_t offset = 0; 43 44 /* Check that ctx->X and ctx->GX are within range. */ 45 TEST_ASSERT( mbedtls_mpi_cmp_int( &ctx->X, 1 ) > 0 ); 46 TEST_ASSERT( mbedtls_mpi_cmp_mpi( &ctx->X, &ctx->P ) < 0 ); 47 TEST_ASSERT( mbedtls_mpi_size( &ctx->X ) <= x_size ); 48 TEST_ASSERT( mbedtls_mpi_cmp_int( &ctx->GX, 1 ) > 0 ); 49 TEST_ASSERT( mbedtls_mpi_cmp_mpi( &ctx->GX, &ctx->P ) < 0 ); 50 51 /* Check ske: it must contain P, G and G^X, each prefixed with a 52 * 2-byte size. */ 53 if( !check_dhm_param_output( &ctx->P, ske, ske_len, &offset ) ) 54 goto exit; 55 if( !check_dhm_param_output( &ctx->G, ske, ske_len, &offset ) ) 56 goto exit; 57 if( !check_dhm_param_output( &ctx->GX, ske, ske_len, &offset ) ) 58 goto exit; 59 TEST_EQUAL( offset, ske_len ); 60 61 return( 1 ); 62exit: 63 return( 0 ); 64} 65 66/* END_HEADER */ 67 68/* BEGIN_DEPENDENCIES 69 * depends_on:MBEDTLS_DHM_C:MBEDTLS_BIGNUM_C 70 * END_DEPENDENCIES 71 */ 72 73/* BEGIN_CASE depends_on:MBEDTLS_CHECK_PARAMS:!MBEDTLS_PARAM_FAILED_ALT */ 74void dhm_invalid_params( ) 75{ 76 mbedtls_dhm_context ctx; 77 unsigned char buf[42] = { 0 }; 78 unsigned char *buf_null = NULL; 79 mbedtls_mpi X; 80 size_t const buflen = sizeof( buf ); 81 size_t len; 82 83 TEST_INVALID_PARAM( mbedtls_dhm_init( NULL ) ); 84 TEST_VALID_PARAM( mbedtls_dhm_free( NULL ) ); 85 86 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 87 mbedtls_dhm_read_params( NULL, 88 (unsigned char**) &buf, 89 buf ) ); 90 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 91 mbedtls_dhm_read_params( &ctx, &buf_null, buf ) ); 92 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 93 mbedtls_dhm_read_params( &ctx, NULL, buf ) ); 94 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 95 mbedtls_dhm_read_params( &ctx, 96 (unsigned char**) &buf, 97 NULL ) ); 98 99 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 100 mbedtls_dhm_make_params( NULL, buflen, 101 buf, &len, 102 mbedtls_test_rnd_std_rand, 103 NULL ) ); 104 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 105 mbedtls_dhm_make_params( &ctx, buflen, 106 NULL, &len, 107 mbedtls_test_rnd_std_rand, 108 NULL ) ); 109 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 110 mbedtls_dhm_make_params( &ctx, buflen, 111 buf, NULL, 112 mbedtls_test_rnd_std_rand, 113 NULL ) ); 114 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 115 mbedtls_dhm_make_params( &ctx, buflen, 116 buf, &len, 117 NULL, 118 NULL ) ); 119 120 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 121 mbedtls_dhm_set_group( NULL, &X, &X ) ); 122 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 123 mbedtls_dhm_set_group( &ctx, NULL, &X ) ); 124 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 125 mbedtls_dhm_set_group( &ctx, &X, NULL ) ); 126 127 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 128 mbedtls_dhm_read_public( NULL, buf, buflen ) ); 129 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 130 mbedtls_dhm_read_public( &ctx, NULL, buflen ) ); 131 132 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 133 mbedtls_dhm_make_public( NULL, buflen, 134 buf, buflen, 135 mbedtls_test_rnd_std_rand, 136 NULL ) ); 137 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 138 mbedtls_dhm_make_public( &ctx, buflen, 139 NULL, buflen, 140 mbedtls_test_rnd_std_rand, 141 NULL ) ); 142 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 143 mbedtls_dhm_make_public( &ctx, buflen, 144 buf, buflen, 145 NULL, 146 NULL ) ); 147 148 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 149 mbedtls_dhm_calc_secret( NULL, buf, buflen, &len, 150 mbedtls_test_rnd_std_rand, 151 NULL ) ); 152 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 153 mbedtls_dhm_calc_secret( &ctx, NULL, buflen, &len, 154 mbedtls_test_rnd_std_rand, 155 NULL ) ); 156 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 157 mbedtls_dhm_calc_secret( &ctx, buf, buflen, NULL, 158 mbedtls_test_rnd_std_rand, 159 NULL ) ); 160 161#if defined(MBEDTLS_ASN1_PARSE_C) 162 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 163 mbedtls_dhm_parse_dhm( NULL, buf, buflen ) ); 164 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 165 mbedtls_dhm_parse_dhm( &ctx, NULL, buflen ) ); 166 167#if defined(MBEDTLS_FS_IO) 168 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 169 mbedtls_dhm_parse_dhmfile( NULL, "" ) ); 170 TEST_INVALID_PARAM_RET( MBEDTLS_ERR_DHM_BAD_INPUT_DATA, 171 mbedtls_dhm_parse_dhmfile( &ctx, NULL ) ); 172#endif /* MBEDTLS_FS_IO */ 173#endif /* MBEDTLS_ASN1_PARSE_C */ 174 175exit: 176 return; 177} 178/* END_CASE */ 179 180/* BEGIN_CASE */ 181void dhm_do_dhm( int radix_P, char *input_P, int x_size, 182 int radix_G, char *input_G, int result ) 183{ 184 mbedtls_dhm_context ctx_srv; 185 mbedtls_dhm_context ctx_cli; 186 unsigned char ske[1000]; 187 unsigned char *p = ske; 188 unsigned char pub_cli[1000]; 189 unsigned char sec_srv[1000]; 190 unsigned char sec_cli[1000]; 191 size_t ske_len = 0; 192 size_t pub_cli_len = 0; 193 size_t sec_srv_len; 194 size_t sec_cli_len; 195 int i; 196 mbedtls_test_rnd_pseudo_info rnd_info; 197 198 mbedtls_dhm_init( &ctx_srv ); 199 mbedtls_dhm_init( &ctx_cli ); 200 memset( ske, 0x00, 1000 ); 201 memset( pub_cli, 0x00, 1000 ); 202 memset( sec_srv, 0x00, 1000 ); 203 memset( sec_cli, 0x00, 1000 ); 204 memset( &rnd_info, 0x00, sizeof( mbedtls_test_rnd_pseudo_info ) ); 205 206 /* 207 * Set params 208 */ 209 TEST_ASSERT( mbedtls_test_read_mpi( &ctx_srv.P, radix_P, input_P ) == 0 ); 210 TEST_ASSERT( mbedtls_test_read_mpi( &ctx_srv.G, radix_G, input_G ) == 0 ); 211 pub_cli_len = mbedtls_mpi_size( &ctx_srv.P ); 212 213 /* 214 * First key exchange 215 */ 216 mbedtls_test_set_step( 10 ); 217 TEST_ASSERT( mbedtls_dhm_make_params( &ctx_srv, x_size, ske, &ske_len, 218 &mbedtls_test_rnd_pseudo_rand, 219 &rnd_info ) == result ); 220 if ( result != 0 ) 221 goto exit; 222 if( !check_dhm_params( &ctx_srv, x_size, ske, ske_len ) ) 223 goto exit; 224 225 ske[ske_len++] = 0; 226 ske[ske_len++] = 0; 227 TEST_ASSERT( mbedtls_dhm_read_params( &ctx_cli, &p, ske + ske_len ) == 0 ); 228 229 TEST_ASSERT( mbedtls_dhm_make_public( &ctx_cli, x_size, pub_cli, pub_cli_len, 230 &mbedtls_test_rnd_pseudo_rand, 231 &rnd_info ) == 0 ); 232 TEST_ASSERT( mbedtls_dhm_read_public( &ctx_srv, pub_cli, pub_cli_len ) == 0 ); 233 234 TEST_ASSERT( mbedtls_dhm_calc_secret( &ctx_srv, sec_srv, sizeof( sec_srv ), 235 &sec_srv_len, 236 &mbedtls_test_rnd_pseudo_rand, 237 &rnd_info ) == 0 ); 238 TEST_ASSERT( mbedtls_dhm_calc_secret( &ctx_cli, sec_cli, sizeof( sec_cli ), &sec_cli_len, NULL, NULL ) == 0 ); 239 240 TEST_ASSERT( sec_srv_len == sec_cli_len ); 241 TEST_ASSERT( sec_srv_len != 0 ); 242 TEST_ASSERT( memcmp( sec_srv, sec_cli, sec_srv_len ) == 0 ); 243 244 /* Re-do calc_secret on server a few times to test update of blinding values */ 245 for( i = 0; i < 3; i++ ) 246 { 247 mbedtls_test_set_step( 20 + i ); 248 sec_srv_len = 1000; 249 TEST_ASSERT( mbedtls_dhm_calc_secret( &ctx_srv, sec_srv, 250 sizeof( sec_srv ), &sec_srv_len, 251 &mbedtls_test_rnd_pseudo_rand, 252 &rnd_info ) == 0 ); 253 254 TEST_ASSERT( sec_srv_len == sec_cli_len ); 255 TEST_ASSERT( sec_srv_len != 0 ); 256 TEST_ASSERT( memcmp( sec_srv, sec_cli, sec_srv_len ) == 0 ); 257 } 258 259 /* 260 * Second key exchange to test change of blinding values on server 261 */ 262 p = ske; 263 264 mbedtls_test_set_step( 30 ); 265 TEST_ASSERT( mbedtls_dhm_make_params( &ctx_srv, x_size, ske, &ske_len, 266 &mbedtls_test_rnd_pseudo_rand, 267 &rnd_info ) == 0 ); 268 if( !check_dhm_params( &ctx_srv, x_size, ske, ske_len ) ) 269 goto exit; 270 ske[ske_len++] = 0; 271 ske[ske_len++] = 0; 272 TEST_ASSERT( mbedtls_dhm_read_params( &ctx_cli, &p, ske + ske_len ) == 0 ); 273 274 TEST_ASSERT( mbedtls_dhm_make_public( &ctx_cli, x_size, pub_cli, pub_cli_len, 275 &mbedtls_test_rnd_pseudo_rand, 276 &rnd_info ) == 0 ); 277 TEST_ASSERT( mbedtls_dhm_read_public( &ctx_srv, pub_cli, pub_cli_len ) == 0 ); 278 279 TEST_ASSERT( mbedtls_dhm_calc_secret( &ctx_srv, sec_srv, sizeof( sec_srv ), 280 &sec_srv_len, 281 &mbedtls_test_rnd_pseudo_rand, 282 &rnd_info ) == 0 ); 283 TEST_ASSERT( mbedtls_dhm_calc_secret( &ctx_cli, sec_cli, sizeof( sec_cli ), &sec_cli_len, NULL, NULL ) == 0 ); 284 285 TEST_ASSERT( sec_srv_len == sec_cli_len ); 286 TEST_ASSERT( sec_srv_len != 0 ); 287 TEST_ASSERT( memcmp( sec_srv, sec_cli, sec_srv_len ) == 0 ); 288 289exit: 290 mbedtls_dhm_free( &ctx_srv ); 291 mbedtls_dhm_free( &ctx_cli ); 292} 293/* END_CASE */ 294 295/* BEGIN_CASE */ 296void dhm_make_public( int P_bytes, int radix_G, char *input_G, int result ) 297{ 298 mbedtls_mpi P, G; 299 mbedtls_dhm_context ctx; 300 unsigned char output[MBEDTLS_MPI_MAX_SIZE]; 301 302 mbedtls_mpi_init( &P ); 303 mbedtls_mpi_init( &G ); 304 mbedtls_dhm_init( &ctx ); 305 306 TEST_ASSERT( mbedtls_mpi_lset( &P, 1 ) == 0 ); 307 TEST_ASSERT( mbedtls_mpi_shift_l( &P, ( P_bytes * 8 ) - 1 ) == 0 ); 308 TEST_ASSERT( mbedtls_mpi_set_bit( &P, 0, 1 ) == 0 ); 309 310 TEST_ASSERT( mbedtls_test_read_mpi( &G, radix_G, input_G ) == 0 ); 311 312 TEST_ASSERT( mbedtls_dhm_set_group( &ctx, &P, &G ) == 0 ); 313 TEST_ASSERT( mbedtls_dhm_make_public( &ctx, (int) mbedtls_mpi_size( &P ), 314 output, sizeof(output), 315 &mbedtls_test_rnd_pseudo_rand, 316 NULL ) == result ); 317 318exit: 319 mbedtls_mpi_free( &P ); 320 mbedtls_mpi_free( &G ); 321 mbedtls_dhm_free( &ctx ); 322} 323/* END_CASE */ 324 325/* BEGIN_CASE depends_on:MBEDTLS_FS_IO */ 326void dhm_file( char * filename, char * p, char * g, int len ) 327{ 328 mbedtls_dhm_context ctx; 329 mbedtls_mpi P, G; 330 331 mbedtls_dhm_init( &ctx ); 332 mbedtls_mpi_init( &P ); mbedtls_mpi_init( &G ); 333 334 TEST_ASSERT( mbedtls_test_read_mpi( &P, 16, p ) == 0 ); 335 TEST_ASSERT( mbedtls_test_read_mpi( &G, 16, g ) == 0 ); 336 337 TEST_ASSERT( mbedtls_dhm_parse_dhmfile( &ctx, filename ) == 0 ); 338 339 TEST_ASSERT( ctx.len == (size_t) len ); 340 TEST_ASSERT( mbedtls_mpi_cmp_mpi( &ctx.P, &P ) == 0 ); 341 TEST_ASSERT( mbedtls_mpi_cmp_mpi( &ctx.G, &G ) == 0 ); 342 343exit: 344 mbedtls_mpi_free( &P ); mbedtls_mpi_free( &G ); 345 mbedtls_dhm_free( &ctx ); 346} 347/* END_CASE */ 348 349/* BEGIN_CASE depends_on:MBEDTLS_SELF_TEST */ 350void dhm_selftest( ) 351{ 352 TEST_ASSERT( mbedtls_dhm_self_test( 1 ) == 0 ); 353} 354/* END_CASE */ 355