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