1/* BEGIN_HEADER */ 2#include "mbedtls/bignum.h" 3#include "mbedtls/entropy.h" 4#include "bignum_core.h" 5#include "constant_time_internal.h" 6#include "test/constant_flow.h" 7 8/** Verifies mbedtls_mpi_core_add(). 9 * 10 * \param[in] A Little-endian presentation of the left operand. 11 * \param[in] B Little-endian presentation of the right operand. 12 * \param limbs Number of limbs in each MPI (\p A, \p B, \p S and \p X). 13 * \param[in] S Little-endian presentation of the expected sum. 14 * \param carry Expected carry from the addition. 15 * \param[in,out] X Temporary storage to be used for results. 16 * 17 * \return 1 if mbedtls_mpi_core_add() passes this test, otherwise 0. 18 */ 19static int mpi_core_verify_add(mbedtls_mpi_uint *A, 20 mbedtls_mpi_uint *B, 21 size_t limbs, 22 mbedtls_mpi_uint *S, 23 int carry, 24 mbedtls_mpi_uint *X) 25{ 26 int ret = 0; 27 28 size_t bytes = limbs * sizeof(*A); 29 30 /* The test cases have A <= B to avoid repetition, so we test A + B then, 31 * if A != B, B + A. If A == B, we can test when A and B are aliased */ 32 33 /* A + B */ 34 35 /* A + B => correct result and carry */ 36 TEST_EQUAL(carry, mbedtls_mpi_core_add(X, A, B, limbs)); 37 TEST_MEMORY_COMPARE(X, bytes, S, bytes); 38 39 /* A + B; alias output and first operand => correct result and carry */ 40 memcpy(X, A, bytes); 41 TEST_EQUAL(carry, mbedtls_mpi_core_add(X, X, B, limbs)); 42 TEST_MEMORY_COMPARE(X, bytes, S, bytes); 43 44 /* A + B; alias output and second operand => correct result and carry */ 45 memcpy(X, B, bytes); 46 TEST_EQUAL(carry, mbedtls_mpi_core_add(X, A, X, limbs)); 47 TEST_MEMORY_COMPARE(X, bytes, S, bytes); 48 49 if (memcmp(A, B, bytes) == 0) { 50 /* A == B, so test where A and B are aliased */ 51 52 /* A + A => correct result and carry */ 53 TEST_EQUAL(carry, mbedtls_mpi_core_add(X, A, A, limbs)); 54 TEST_MEMORY_COMPARE(X, bytes, S, bytes); 55 56 /* A + A, output aliased to both operands => correct result and carry */ 57 memcpy(X, A, bytes); 58 TEST_EQUAL(carry, mbedtls_mpi_core_add(X, X, X, limbs)); 59 TEST_MEMORY_COMPARE(X, bytes, S, bytes); 60 } else { 61 /* A != B, so test B + A */ 62 63 /* B + A => correct result and carry */ 64 TEST_EQUAL(carry, mbedtls_mpi_core_add(X, B, A, limbs)); 65 TEST_MEMORY_COMPARE(X, bytes, S, bytes); 66 67 /* B + A; alias output and first operand => correct result and carry */ 68 memcpy(X, B, bytes); 69 TEST_EQUAL(carry, mbedtls_mpi_core_add(X, X, A, limbs)); 70 TEST_MEMORY_COMPARE(X, bytes, S, bytes); 71 72 /* B + A; alias output and second operand => correct result and carry */ 73 memcpy(X, A, bytes); 74 TEST_EQUAL(carry, mbedtls_mpi_core_add(X, B, X, limbs)); 75 TEST_MEMORY_COMPARE(X, bytes, S, bytes); 76 } 77 78 ret = 1; 79 80exit: 81 return ret; 82} 83 84/** Verifies mbedtls_mpi_core_add_if(). 85 * 86 * \param[in] A Little-endian presentation of the left operand. 87 * \param[in] B Little-endian presentation of the right operand. 88 * \param limbs Number of limbs in each MPI (\p A, \p B, \p S and \p X). 89 * \param[in] S Little-endian presentation of the expected sum. 90 * \param carry Expected carry from the addition. 91 * \param[in,out] X Temporary storage to be used for results. 92 * 93 * \return 1 if mbedtls_mpi_core_add_if() passes this test, otherwise 0. 94 */ 95static int mpi_core_verify_add_if(mbedtls_mpi_uint *A, 96 mbedtls_mpi_uint *B, 97 size_t limbs, 98 mbedtls_mpi_uint *S, 99 int carry, 100 mbedtls_mpi_uint *X) 101{ 102 int ret = 0; 103 104 size_t bytes = limbs * sizeof(*A); 105 106 /* The test cases have A <= B to avoid repetition, so we test A + B then, 107 * if A != B, B + A. If A == B, we can test when A and B are aliased */ 108 109 /* A + B */ 110 111 /* cond = 0 => X unchanged, no carry */ 112 memcpy(X, A, bytes); 113 TEST_EQUAL(0, mbedtls_mpi_core_add_if(X, B, limbs, 0)); 114 TEST_MEMORY_COMPARE(X, bytes, A, bytes); 115 116 /* cond = 1 => correct result and carry */ 117 TEST_EQUAL(carry, mbedtls_mpi_core_add_if(X, B, limbs, 1)); 118 TEST_MEMORY_COMPARE(X, bytes, S, bytes); 119 120 if (memcmp(A, B, bytes) == 0) { 121 /* A == B, so test where A and B are aliased */ 122 123 /* cond = 0 => X unchanged, no carry */ 124 memcpy(X, B, bytes); 125 TEST_EQUAL(0, mbedtls_mpi_core_add_if(X, X, limbs, 0)); 126 TEST_MEMORY_COMPARE(X, bytes, B, bytes); 127 128 /* cond = 1 => correct result and carry */ 129 TEST_EQUAL(carry, mbedtls_mpi_core_add_if(X, X, limbs, 1)); 130 TEST_MEMORY_COMPARE(X, bytes, S, bytes); 131 } else { 132 /* A != B, so test B + A */ 133 134 /* cond = 0 => d unchanged, no carry */ 135 memcpy(X, B, bytes); 136 TEST_EQUAL(0, mbedtls_mpi_core_add_if(X, A, limbs, 0)); 137 TEST_MEMORY_COMPARE(X, bytes, B, bytes); 138 139 /* cond = 1 => correct result and carry */ 140 TEST_EQUAL(carry, mbedtls_mpi_core_add_if(X, A, limbs, 1)); 141 TEST_MEMORY_COMPARE(X, bytes, S, bytes); 142 } 143 144 ret = 1; 145 146exit: 147 return ret; 148} 149 150/* END_HEADER */ 151 152/* BEGIN_DEPENDENCIES 153 * depends_on:MBEDTLS_BIGNUM_C 154 * END_DEPENDENCIES 155 */ 156 157/* BEGIN_CASE */ 158void mpi_core_io_null() 159{ 160 mbedtls_mpi_uint X = 0; 161 int ret; 162 163 ret = mbedtls_mpi_core_read_be(&X, 1, NULL, 0); 164 TEST_EQUAL(ret, 0); 165 ret = mbedtls_mpi_core_write_be(&X, 1, NULL, 0); 166 TEST_EQUAL(ret, 0); 167 168 ret = mbedtls_mpi_core_read_be(NULL, 0, NULL, 0); 169 TEST_EQUAL(ret, 0); 170 ret = mbedtls_mpi_core_write_be(NULL, 0, NULL, 0); 171 TEST_EQUAL(ret, 0); 172 173 ret = mbedtls_mpi_core_read_le(&X, 1, NULL, 0); 174 TEST_EQUAL(ret, 0); 175 ret = mbedtls_mpi_core_write_le(&X, 1, NULL, 0); 176 TEST_EQUAL(ret, 0); 177 178 ret = mbedtls_mpi_core_read_le(NULL, 0, NULL, 0); 179 TEST_EQUAL(ret, 0); 180 ret = mbedtls_mpi_core_write_le(NULL, 0, NULL, 0); 181 TEST_EQUAL(ret, 0); 182 183exit: 184 ; 185} 186/* END_CASE */ 187 188/* BEGIN_CASE */ 189void mpi_core_io_be(data_t *input, int nb_int, int nx_32_int, int iret, 190 int oret) 191{ 192 if (iret != 0) { 193 TEST_ASSERT(oret == 0); 194 } 195 196 TEST_LE_S(0, nb_int); 197 size_t nb = nb_int; 198 199 unsigned char buf[1024]; 200 TEST_LE_U(nb, sizeof(buf)); 201 202 /* nx_32_int is the number of 32 bit limbs, if we have 64 bit limbs we need 203 * to halve the number of limbs to have the same size. */ 204 size_t nx; 205 TEST_LE_S(0, nx_32_int); 206 if (sizeof(mbedtls_mpi_uint) == 8) { 207 nx = nx_32_int / 2 + nx_32_int % 2; 208 } else { 209 nx = nx_32_int; 210 } 211 212 mbedtls_mpi_uint X[sizeof(buf) / sizeof(mbedtls_mpi_uint)]; 213 TEST_LE_U(nx, sizeof(X) / sizeof(X[0])); 214 215 int ret = mbedtls_mpi_core_read_be(X, nx, input->x, input->len); 216 TEST_EQUAL(ret, iret); 217 218 if (iret == 0) { 219 ret = mbedtls_mpi_core_write_be(X, nx, buf, nb); 220 TEST_EQUAL(ret, oret); 221 } 222 223 if ((iret == 0) && (oret == 0)) { 224 if (nb > input->len) { 225 size_t leading_zeroes = nb - input->len; 226 TEST_ASSERT(memcmp(buf + nb - input->len, input->x, input->len) == 0); 227 for (size_t i = 0; i < leading_zeroes; i++) { 228 TEST_EQUAL(buf[i], 0); 229 } 230 } else { 231 size_t leading_zeroes = input->len - nb; 232 TEST_ASSERT(memcmp(input->x + input->len - nb, buf, nb) == 0); 233 for (size_t i = 0; i < leading_zeroes; i++) { 234 TEST_EQUAL(input->x[i], 0); 235 } 236 } 237 } 238 239exit: 240 ; 241} 242/* END_CASE */ 243 244/* BEGIN_CASE */ 245void mpi_core_io_le(data_t *input, int nb_int, int nx_32_int, int iret, 246 int oret) 247{ 248 if (iret != 0) { 249 TEST_ASSERT(oret == 0); 250 } 251 252 TEST_LE_S(0, nb_int); 253 size_t nb = nb_int; 254 255 unsigned char buf[1024]; 256 TEST_LE_U(nb, sizeof(buf)); 257 258 /* nx_32_int is the number of 32 bit limbs, if we have 64 bit limbs we need 259 * to halve the number of limbs to have the same size. */ 260 size_t nx; 261 TEST_LE_S(0, nx_32_int); 262 if (sizeof(mbedtls_mpi_uint) == 8) { 263 nx = nx_32_int / 2 + nx_32_int % 2; 264 } else { 265 nx = nx_32_int; 266 } 267 268 mbedtls_mpi_uint X[sizeof(buf) / sizeof(mbedtls_mpi_uint)]; 269 TEST_LE_U(nx, sizeof(X) / sizeof(X[0])); 270 271 int ret = mbedtls_mpi_core_read_le(X, nx, input->x, input->len); 272 TEST_EQUAL(ret, iret); 273 274 if (iret == 0) { 275 ret = mbedtls_mpi_core_write_le(X, nx, buf, nb); 276 TEST_EQUAL(ret, oret); 277 } 278 279 if ((iret == 0) && (oret == 0)) { 280 if (nb > input->len) { 281 TEST_ASSERT(memcmp(buf, input->x, input->len) == 0); 282 for (size_t i = input->len; i < nb; i++) { 283 TEST_EQUAL(buf[i], 0); 284 } 285 } else { 286 TEST_ASSERT(memcmp(input->x, buf, nb) == 0); 287 for (size_t i = nb; i < input->len; i++) { 288 TEST_EQUAL(input->x[i], 0); 289 } 290 } 291 } 292 293exit: 294 ; 295} 296/* END_CASE */ 297 298/* BEGIN_CASE */ 299void mpi_core_bitlen(char *input_X, int nr_bits) 300{ 301 mbedtls_mpi_uint *X = NULL; 302 size_t limbs; 303 304 TEST_EQUAL(mbedtls_test_read_mpi_core(&X, &limbs, input_X), 0); 305 TEST_EQUAL(mbedtls_mpi_core_bitlen(X, limbs), nr_bits); 306 307exit: 308 mbedtls_free(X); 309} 310/* END_CASE */ 311 312 313/* BEGIN_CASE */ 314void mpi_core_clz(int leading_zeros, int trailing_zeros) 315{ 316 if ((size_t) (leading_zeros + trailing_zeros) >= (sizeof(mbedtls_mpi_uint) * 8)) { 317 // can't fit required number of leading and trailing zeros - skip test 318 goto exit; 319 } 320 321 // Construct a test input value where the count of leading zeros and 322 // trailing zeros is given in the test case, and we add ones to fill 323 // the gap. 324 mbedtls_mpi_uint x; 325 if ((leading_zeros + trailing_zeros) > 0) { 326 // some zero bits 327 uint32_t s = (sizeof(mbedtls_mpi_uint) * 8 - leading_zeros - trailing_zeros); 328 x = ((((mbedtls_mpi_uint) 1) << s) - 1) << trailing_zeros; 329 } else { 330 // all bits set 331 x = ~((mbedtls_mpi_uint) 0); 332 } 333 334 size_t n = mbedtls_mpi_core_clz(x); 335 TEST_EQUAL(n, leading_zeros); 336exit: 337 ; 338} 339/* END_CASE */ 340 341 342/* BEGIN_CASE */ 343void mpi_core_lt_ct(char *input_X, char *input_Y, int exp_ret) 344{ 345 mbedtls_mpi_uint *X = NULL; 346 size_t X_limbs; 347 mbedtls_mpi_uint *Y = NULL; 348 size_t Y_limbs; 349 int ret; 350 351 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &X_limbs, input_X)); 352 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&Y, &Y_limbs, input_Y)); 353 354 /* We need two same-length limb arrays */ 355 TEST_EQUAL(X_limbs, Y_limbs); 356 357 TEST_CF_SECRET(X, X_limbs * sizeof(mbedtls_mpi_uint)); 358 TEST_CF_SECRET(Y, X_limbs * sizeof(mbedtls_mpi_uint)); 359 360 ret = mbedtls_mpi_core_lt_ct(X, Y, X_limbs); 361 TEST_EQUAL(!!ret, exp_ret); 362 363exit: 364 mbedtls_free(X); 365 mbedtls_free(Y); 366} 367/* END_CASE */ 368 369/* BEGIN_CASE */ 370void mpi_core_uint_le_mpi(char *input_A) 371{ 372 mbedtls_mpi_uint *A = NULL; 373 size_t A_limbs = 0; 374 375 TEST_EQUAL(mbedtls_test_read_mpi_core(&A, &A_limbs, input_A), 0); 376 377 int is_large = 0; /* nonzero limbs beyond the lowest-order one? */ 378 for (size_t i = 1; i < A_limbs; i++) { 379 if (A[i] != 0) { 380 is_large = 1; 381 break; 382 } 383 } 384 385 TEST_CF_SECRET(A, A_limbs * sizeof(*A)); 386 387 TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi(0, A, A_limbs), 1); 388 TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi(A[0], A, A_limbs), 1); 389 390 if (is_large) { 391 TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi(A[0] + 1, 392 A, A_limbs), 1); 393 TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi((mbedtls_mpi_uint) (-1) >> 1, 394 A, A_limbs), 1); 395 TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi((mbedtls_mpi_uint) (-1), 396 A, A_limbs), 1); 397 } else { 398 TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi(A[0] + 1, 399 A, A_limbs), 400 A[0] + 1 <= A[0]); 401 TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi((mbedtls_mpi_uint) (-1) >> 1, 402 A, A_limbs), 403 (mbedtls_mpi_uint) (-1) >> 1 <= A[0]); 404 TEST_EQUAL(!!mbedtls_mpi_core_uint_le_mpi((mbedtls_mpi_uint) (-1), 405 A, A_limbs), 406 (mbedtls_mpi_uint) (-1) <= A[0]); 407 } 408 409exit: 410 mbedtls_free(A); 411} 412/* END_CASE */ 413 414/* BEGIN_CASE */ 415void mpi_core_cond_assign(char *input_X, 416 char *input_Y, 417 int input_bytes) 418{ 419 mbedtls_mpi_uint *X = NULL; 420 mbedtls_mpi_uint *Y = NULL; 421 size_t limbs_X; 422 size_t limbs_Y; 423 424 TEST_EQUAL(mbedtls_test_read_mpi_core(&X, &limbs_X, input_X), 0); 425 TEST_EQUAL(mbedtls_test_read_mpi_core(&Y, &limbs_Y, input_Y), 0); 426 427 size_t limbs = limbs_X; 428 size_t copy_limbs = CHARS_TO_LIMBS(input_bytes); 429 size_t bytes = limbs * sizeof(mbedtls_mpi_uint); 430 size_t copy_bytes = copy_limbs * sizeof(mbedtls_mpi_uint); 431 432 TEST_EQUAL(limbs_X, limbs_Y); 433 TEST_ASSERT(copy_limbs <= limbs); 434 435 /* condition is false */ 436 TEST_CF_SECRET(X, bytes); 437 TEST_CF_SECRET(Y, bytes); 438 439 mbedtls_mpi_core_cond_assign(X, Y, copy_limbs, 0); 440 441 TEST_CF_PUBLIC(X, bytes); 442 TEST_CF_PUBLIC(Y, bytes); 443 444 TEST_ASSERT(memcmp(X, Y, bytes) != 0); 445 446 /* condition is true */ 447 TEST_CF_SECRET(X, bytes); 448 TEST_CF_SECRET(Y, bytes); 449 450 mbedtls_mpi_core_cond_assign(X, Y, copy_limbs, mbedtls_ct_bool(1)); 451 452 TEST_CF_PUBLIC(X, bytes); 453 TEST_CF_PUBLIC(Y, bytes); 454 455 /* Check if the given length is copied even it is smaller 456 than the length of the given MPIs. */ 457 if (copy_limbs < limbs) { 458 TEST_CF_PUBLIC(X, bytes); 459 TEST_CF_PUBLIC(Y, bytes); 460 461 TEST_MEMORY_COMPARE(X, copy_bytes, Y, copy_bytes); 462 TEST_ASSERT(memcmp(X, Y, bytes) != 0); 463 } else { 464 TEST_MEMORY_COMPARE(X, bytes, Y, bytes); 465 } 466 467exit: 468 mbedtls_free(X); 469 mbedtls_free(Y); 470} 471/* END_CASE */ 472 473/* BEGIN_CASE */ 474void mpi_core_cond_swap(char *input_X, 475 char *input_Y, 476 int input_bytes) 477{ 478 mbedtls_mpi_uint *tmp_X = NULL; 479 mbedtls_mpi_uint *tmp_Y = NULL; 480 mbedtls_mpi_uint *X = NULL; 481 mbedtls_mpi_uint *Y = NULL; 482 size_t limbs_X; 483 size_t limbs_Y; 484 485 TEST_EQUAL(mbedtls_test_read_mpi_core(&tmp_X, &limbs_X, input_X), 0); 486 TEST_EQUAL(mbedtls_test_read_mpi_core(&tmp_Y, &limbs_Y, input_Y), 0); 487 488 size_t limbs = limbs_X; 489 size_t copy_limbs = CHARS_TO_LIMBS(input_bytes); 490 size_t bytes = limbs * sizeof(mbedtls_mpi_uint); 491 size_t copy_bytes = copy_limbs * sizeof(mbedtls_mpi_uint); 492 493 TEST_EQUAL(limbs_X, limbs_Y); 494 TEST_ASSERT(copy_limbs <= limbs); 495 496 TEST_CALLOC(X, limbs); 497 memcpy(X, tmp_X, bytes); 498 499 TEST_CALLOC(Y, limbs); 500 memcpy(Y, tmp_Y, bytes); 501 502 /* condition is false */ 503 TEST_CF_SECRET(X, bytes); 504 TEST_CF_SECRET(Y, bytes); 505 506 mbedtls_mpi_core_cond_swap(X, Y, copy_limbs, 0); 507 508 TEST_CF_PUBLIC(X, bytes); 509 TEST_CF_PUBLIC(Y, bytes); 510 511 TEST_MEMORY_COMPARE(X, bytes, tmp_X, bytes); 512 TEST_MEMORY_COMPARE(Y, bytes, tmp_Y, bytes); 513 514 /* condition is true */ 515 TEST_CF_SECRET(X, bytes); 516 TEST_CF_SECRET(Y, bytes); 517 518 mbedtls_mpi_core_cond_swap(X, Y, copy_limbs, mbedtls_ct_bool(1)); 519 520 TEST_CF_PUBLIC(X, bytes); 521 TEST_CF_PUBLIC(Y, bytes); 522 523 /* Check if the given length is copied even it is smaller 524 than the length of the given MPIs. */ 525 if (copy_limbs < limbs) { 526 TEST_MEMORY_COMPARE(X, copy_bytes, tmp_Y, copy_bytes); 527 TEST_MEMORY_COMPARE(Y, copy_bytes, tmp_X, copy_bytes); 528 TEST_ASSERT(memcmp(X, tmp_X, bytes) != 0); 529 TEST_ASSERT(memcmp(X, tmp_Y, bytes) != 0); 530 TEST_ASSERT(memcmp(Y, tmp_X, bytes) != 0); 531 TEST_ASSERT(memcmp(Y, tmp_Y, bytes) != 0); 532 } else { 533 TEST_MEMORY_COMPARE(X, bytes, tmp_Y, bytes); 534 TEST_MEMORY_COMPARE(Y, bytes, tmp_X, bytes); 535 } 536 537exit: 538 mbedtls_free(tmp_X); 539 mbedtls_free(tmp_Y); 540 mbedtls_free(X); 541 mbedtls_free(Y); 542} 543/* END_CASE */ 544 545/* BEGIN_CASE */ 546void mpi_core_shift_r(char *input, int count, char *result) 547{ 548 mbedtls_mpi_uint *X = NULL; 549 mbedtls_mpi_uint *Y = NULL; 550 size_t limbs, n; 551 552 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &limbs, input)); 553 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&Y, &n, result)); 554 TEST_EQUAL(limbs, n); 555 556 mbedtls_mpi_core_shift_r(X, limbs, count); 557 TEST_MEMORY_COMPARE(X, limbs * ciL, Y, limbs * ciL); 558 559exit: 560 mbedtls_free(X); 561 mbedtls_free(Y); 562} 563/* END_CASE */ 564 565/* BEGIN_CASE */ 566void mpi_core_shift_l(char *input, int count, char *result) 567{ 568 mbedtls_mpi_uint *X = NULL; 569 mbedtls_mpi_uint *Y = NULL; 570 size_t limbs, n; 571 572 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &limbs, input)); 573 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&Y, &n, result)); 574 TEST_EQUAL(limbs, n); 575 576 mbedtls_mpi_core_shift_l(X, limbs, count); 577 TEST_MEMORY_COMPARE(X, limbs * ciL, Y, limbs * ciL); 578 579exit: 580 mbedtls_free(X); 581 mbedtls_free(Y); 582} 583/* END_CASE */ 584 585/* BEGIN_CASE */ 586void mpi_core_add_and_add_if(char *input_A, char *input_B, 587 char *input_S, int carry) 588{ 589 mbedtls_mpi_uint *A = NULL; /* first value to add */ 590 mbedtls_mpi_uint *B = NULL; /* second value to add */ 591 mbedtls_mpi_uint *S = NULL; /* expected result */ 592 mbedtls_mpi_uint *X = NULL; /* destination - the in/out first operand */ 593 size_t A_limbs, B_limbs, S_limbs; 594 595 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&A, &A_limbs, input_A)); 596 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&B, &B_limbs, input_B)); 597 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&S, &S_limbs, input_S)); 598 599 /* add and add_if expect all operands to be the same length */ 600 TEST_EQUAL(A_limbs, B_limbs); 601 TEST_EQUAL(A_limbs, S_limbs); 602 603 size_t limbs = A_limbs; 604 TEST_CALLOC(X, limbs); 605 606 TEST_ASSERT(mpi_core_verify_add(A, B, limbs, S, carry, X)); 607 TEST_ASSERT(mpi_core_verify_add_if(A, B, limbs, S, carry, X)); 608 609exit: 610 mbedtls_free(A); 611 mbedtls_free(B); 612 mbedtls_free(S); 613 mbedtls_free(X); 614} 615/* END_CASE */ 616 617/* BEGIN_CASE */ 618void mpi_core_sub(char *input_A, char *input_B, 619 char *input_X, int carry) 620{ 621 mbedtls_mpi A, B, X; 622 mbedtls_mpi_uint *a = NULL; 623 mbedtls_mpi_uint *b = NULL; 624 mbedtls_mpi_uint *x = NULL; /* expected */ 625 mbedtls_mpi_uint *r = NULL; /* result */ 626 627 mbedtls_mpi_init(&A); 628 mbedtls_mpi_init(&B); 629 mbedtls_mpi_init(&X); 630 631 TEST_EQUAL(0, mbedtls_test_read_mpi(&A, input_A)); 632 TEST_EQUAL(0, mbedtls_test_read_mpi(&B, input_B)); 633 TEST_EQUAL(0, mbedtls_test_read_mpi(&X, input_X)); 634 635 /* All of the inputs are +ve (or zero) */ 636 TEST_EQUAL(1, A.s); 637 TEST_EQUAL(1, B.s); 638 TEST_EQUAL(1, X.s); 639 640 /* Get the number of limbs we will need */ 641 size_t limbs = MAX(A.n, B.n); 642 size_t bytes = limbs * sizeof(mbedtls_mpi_uint); 643 644 /* The result shouldn't have more limbs than the longest input */ 645 TEST_LE_U(X.n, limbs); 646 647 /* Now let's get arrays of mbedtls_mpi_uints, rather than MPI structures */ 648 649 /* TEST_CALLOC() uses calloc() under the hood, so these do get zeroed */ 650 TEST_CALLOC(a, bytes); 651 TEST_CALLOC(b, bytes); 652 TEST_CALLOC(x, bytes); 653 TEST_CALLOC(r, bytes); 654 655 /* Populate the arrays. As the mbedtls_mpi_uint[]s in mbedtls_mpis (and as 656 * processed by mbedtls_mpi_core_sub()) are little endian, we can just 657 * copy what we have as long as MSBs are 0 (which they are from TEST_CALLOC()) 658 */ 659 memcpy(a, A.p, A.n * sizeof(mbedtls_mpi_uint)); 660 memcpy(b, B.p, B.n * sizeof(mbedtls_mpi_uint)); 661 memcpy(x, X.p, X.n * sizeof(mbedtls_mpi_uint)); 662 663 /* 1a) r = a - b => we should get the correct carry */ 664 TEST_EQUAL(carry, mbedtls_mpi_core_sub(r, a, b, limbs)); 665 666 /* 1b) r = a - b => we should get the correct result */ 667 TEST_MEMORY_COMPARE(r, bytes, x, bytes); 668 669 /* 2 and 3 test "r may be aliased to a or b" */ 670 /* 2a) r = a; r -= b => we should get the correct carry (use r to avoid clobbering a) */ 671 memcpy(r, a, bytes); 672 TEST_EQUAL(carry, mbedtls_mpi_core_sub(r, r, b, limbs)); 673 674 /* 2b) r -= b => we should get the correct result */ 675 TEST_MEMORY_COMPARE(r, bytes, x, bytes); 676 677 /* 3a) r = b; r = a - r => we should get the correct carry (use r to avoid clobbering b) */ 678 memcpy(r, b, bytes); 679 TEST_EQUAL(carry, mbedtls_mpi_core_sub(r, a, r, limbs)); 680 681 /* 3b) r = a - b => we should get the correct result */ 682 TEST_MEMORY_COMPARE(r, bytes, x, bytes); 683 684 /* 4 tests "r may be aliased to [...] both" */ 685 if (A.n == B.n && memcmp(A.p, B.p, bytes) == 0) { 686 memcpy(r, b, bytes); 687 TEST_EQUAL(carry, mbedtls_mpi_core_sub(r, r, r, limbs)); 688 TEST_MEMORY_COMPARE(r, bytes, x, bytes); 689 } 690 691exit: 692 mbedtls_free(a); 693 mbedtls_free(b); 694 mbedtls_free(x); 695 mbedtls_free(r); 696 697 mbedtls_mpi_free(&A); 698 mbedtls_mpi_free(&B); 699 mbedtls_mpi_free(&X); 700} 701/* END_CASE */ 702 703/* BEGIN_CASE */ 704void mpi_core_mla(char *input_A, char *input_B, char *input_S, 705 char *input_X4, char *input_cy4, 706 char *input_X8, char *input_cy8) 707{ 708 /* We are testing A += B * s; A, B are MPIs, s is a scalar. 709 * 710 * However, we encode s as an MPI in the .data file as the test framework 711 * currently only supports `int`-typed scalars, and that doesn't cover the 712 * full range of `mbedtls_mpi_uint`. 713 * 714 * We also have the different results for sizeof(mbedtls_mpi_uint) == 4 or 8. 715 */ 716 mbedtls_mpi A, B, S, X4, X8, cy4, cy8; 717 mbedtls_mpi_uint *a = NULL; 718 mbedtls_mpi_uint *x = NULL; 719 720 mbedtls_mpi_init(&A); 721 mbedtls_mpi_init(&B); 722 mbedtls_mpi_init(&S); 723 mbedtls_mpi_init(&X4); 724 mbedtls_mpi_init(&X8); 725 mbedtls_mpi_init(&cy4); 726 mbedtls_mpi_init(&cy8); 727 728 TEST_EQUAL(0, mbedtls_test_read_mpi(&A, input_A)); 729 TEST_EQUAL(0, mbedtls_test_read_mpi(&B, input_B)); 730 TEST_EQUAL(0, mbedtls_test_read_mpi(&S, input_S)); 731 TEST_EQUAL(0, mbedtls_test_read_mpi(&X4, input_X4)); 732 TEST_EQUAL(0, mbedtls_test_read_mpi(&cy4, input_cy4)); 733 TEST_EQUAL(0, mbedtls_test_read_mpi(&X8, input_X8)); 734 TEST_EQUAL(0, mbedtls_test_read_mpi(&cy8, input_cy8)); 735 736 /* The MPI encoding of scalar s must be only 1 limb */ 737 TEST_EQUAL(1, S.n); 738 739 /* We only need to work with X4 or X8, and cy4 or cy8, depending on sizeof(mbedtls_mpi_uint) */ 740 mbedtls_mpi *X = (sizeof(mbedtls_mpi_uint) == 4) ? &X4 : &X8; 741 mbedtls_mpi *cy = (sizeof(mbedtls_mpi_uint) == 4) ? &cy4 : &cy8; 742 743 /* The carry should only have one limb */ 744 TEST_EQUAL(1, cy->n); 745 746 /* All of the inputs are +ve (or zero) */ 747 TEST_EQUAL(1, A.s); 748 TEST_EQUAL(1, B.s); 749 TEST_EQUAL(1, S.s); 750 TEST_EQUAL(1, X->s); 751 TEST_EQUAL(1, cy->s); 752 753 /* Get the (max) number of limbs we will need */ 754 size_t limbs = MAX(A.n, B.n); 755 size_t bytes = limbs * sizeof(mbedtls_mpi_uint); 756 757 /* The result shouldn't have more limbs than the longest input */ 758 TEST_LE_U(X->n, limbs); 759 760 /* Now let's get arrays of mbedtls_mpi_uints, rather than MPI structures */ 761 762 /* TEST_CALLOC() uses calloc() under the hood, so these do get zeroed */ 763 TEST_CALLOC(a, bytes); 764 TEST_CALLOC(x, bytes); 765 766 /* Populate the arrays. As the mbedtls_mpi_uint[]s in mbedtls_mpis (and as 767 * processed by mbedtls_mpi_core_mla()) are little endian, we can just 768 * copy what we have as long as MSBs are 0 (which they are from TEST_CALLOC()). 769 */ 770 memcpy(a, A.p, A.n * sizeof(mbedtls_mpi_uint)); 771 memcpy(x, X->p, X->n * sizeof(mbedtls_mpi_uint)); 772 773 /* 1a) A += B * s => we should get the correct carry */ 774 TEST_EQUAL(mbedtls_mpi_core_mla(a, limbs, B.p, B.n, *S.p), *cy->p); 775 776 /* 1b) A += B * s => we should get the correct result */ 777 TEST_MEMORY_COMPARE(a, bytes, x, bytes); 778 779 if (A.n == B.n && memcmp(A.p, B.p, bytes) == 0) { 780 /* Check when A and B are aliased */ 781 memcpy(a, A.p, A.n * sizeof(mbedtls_mpi_uint)); 782 TEST_EQUAL(mbedtls_mpi_core_mla(a, limbs, a, limbs, *S.p), *cy->p); 783 TEST_MEMORY_COMPARE(a, bytes, x, bytes); 784 } 785 786exit: 787 mbedtls_free(a); 788 mbedtls_free(x); 789 790 mbedtls_mpi_free(&A); 791 mbedtls_mpi_free(&B); 792 mbedtls_mpi_free(&S); 793 mbedtls_mpi_free(&X4); 794 mbedtls_mpi_free(&X8); 795 mbedtls_mpi_free(&cy4); 796 mbedtls_mpi_free(&cy8); 797} 798/* END_CASE */ 799 800 801/* BEGIN_CASE */ 802void mpi_montg_init(char *input_N, char *input_mm) 803{ 804 mbedtls_mpi N, mm; 805 806 mbedtls_mpi_init(&N); 807 mbedtls_mpi_init(&mm); 808 809 TEST_EQUAL(0, mbedtls_test_read_mpi(&N, input_N)); 810 TEST_EQUAL(0, mbedtls_test_read_mpi(&mm, input_mm)); 811 812 /* The MPI encoding of mm should be 1 limb (sizeof(mbedtls_mpi_uint) == 8) or 813 * 2 limbs (sizeof(mbedtls_mpi_uint) == 4). 814 * 815 * The data file contains the expected result for sizeof(mbedtls_mpi_uint) == 8; 816 * for sizeof(mbedtls_mpi_uint) == 4 it's just the LSW of this. 817 */ 818 TEST_ASSERT(mm.n == 1 || mm.n == 2); 819 820 /* All of the inputs are +ve (or zero) */ 821 TEST_EQUAL(1, N.s); 822 TEST_EQUAL(1, mm.s); 823 824 /* mbedtls_mpi_core_montmul_init() only returns a result, no error possible */ 825 mbedtls_mpi_uint result = mbedtls_mpi_core_montmul_init(N.p); 826 827 /* Check we got the correct result */ 828 TEST_EQUAL(result, mm.p[0]); 829 830exit: 831 mbedtls_mpi_free(&N); 832 mbedtls_mpi_free(&mm); 833} 834/* END_CASE */ 835 836/* BEGIN_CASE */ 837void mpi_core_montmul(int limbs_AN4, int limbs_B4, 838 int limbs_AN8, int limbs_B8, 839 char *input_A, 840 char *input_B, 841 char *input_N, 842 char *input_X4, 843 char *input_X8) 844{ 845 mbedtls_mpi A, B, N, X4, X8, T, R; 846 847 mbedtls_mpi_init(&A); 848 mbedtls_mpi_init(&B); 849 mbedtls_mpi_init(&N); 850 mbedtls_mpi_init(&X4); /* expected result, sizeof(mbedtls_mpi_uint) == 4 */ 851 mbedtls_mpi_init(&X8); /* expected result, sizeof(mbedtls_mpi_uint) == 8 */ 852 mbedtls_mpi_init(&T); 853 mbedtls_mpi_init(&R); /* for the result */ 854 855 TEST_EQUAL(0, mbedtls_test_read_mpi(&A, input_A)); 856 TEST_EQUAL(0, mbedtls_test_read_mpi(&B, input_B)); 857 TEST_EQUAL(0, mbedtls_test_read_mpi(&N, input_N)); 858 TEST_EQUAL(0, mbedtls_test_read_mpi(&X4, input_X4)); 859 TEST_EQUAL(0, mbedtls_test_read_mpi(&X8, input_X8)); 860 861 mbedtls_mpi *X = (sizeof(mbedtls_mpi_uint) == 4) ? &X4 : &X8; 862 863 int limbs_AN = (sizeof(mbedtls_mpi_uint) == 4) ? limbs_AN4 : limbs_AN8; 864 int limbs_B = (sizeof(mbedtls_mpi_uint) == 4) ? limbs_B4 : limbs_B8; 865 866 TEST_LE_U(A.n, (size_t) limbs_AN); 867 TEST_LE_U(X->n, (size_t) limbs_AN); 868 TEST_LE_U(B.n, (size_t) limbs_B); 869 TEST_LE_U(limbs_B, limbs_AN); 870 871 /* All of the inputs are +ve (or zero) */ 872 TEST_EQUAL(1, A.s); 873 TEST_EQUAL(1, B.s); 874 TEST_EQUAL(1, N.s); 875 TEST_EQUAL(1, X->s); 876 877 TEST_EQUAL(0, mbedtls_mpi_grow(&A, limbs_AN)); 878 TEST_EQUAL(0, mbedtls_mpi_grow(&N, limbs_AN)); 879 TEST_EQUAL(0, mbedtls_mpi_grow(X, limbs_AN)); 880 TEST_EQUAL(0, mbedtls_mpi_grow(&B, limbs_B)); 881 882 size_t working_limbs = mbedtls_mpi_core_montmul_working_limbs(limbs_AN); 883 TEST_EQUAL(working_limbs, limbs_AN * 2 + 1); 884 TEST_EQUAL(0, mbedtls_mpi_grow(&T, working_limbs)); 885 886 /* Calculate the Montgomery constant (this is unit tested separately) */ 887 mbedtls_mpi_uint mm = mbedtls_mpi_core_montmul_init(N.p); 888 889 TEST_EQUAL(0, mbedtls_mpi_grow(&R, limbs_AN)); /* ensure it's got the right number of limbs */ 890 891 mbedtls_mpi_core_montmul(R.p, A.p, B.p, B.n, N.p, N.n, mm, T.p); 892 size_t bytes = N.n * sizeof(mbedtls_mpi_uint); 893 TEST_MEMORY_COMPARE(R.p, bytes, X->p, bytes); 894 895 /* The output (R, above) may be aliased to A - use R to save the value of A */ 896 897 memcpy(R.p, A.p, bytes); 898 899 mbedtls_mpi_core_montmul(A.p, A.p, B.p, B.n, N.p, N.n, mm, T.p); 900 TEST_MEMORY_COMPARE(A.p, bytes, X->p, bytes); 901 902 memcpy(A.p, R.p, bytes); /* restore A */ 903 904 /* The output may be aliased to N - use R to save the value of N */ 905 906 memcpy(R.p, N.p, bytes); 907 908 mbedtls_mpi_core_montmul(N.p, A.p, B.p, B.n, N.p, N.n, mm, T.p); 909 TEST_MEMORY_COMPARE(N.p, bytes, X->p, bytes); 910 911 memcpy(N.p, R.p, bytes); 912 913 if (limbs_AN == limbs_B) { 914 /* Test when A aliased to B (requires A == B on input values) */ 915 if (memcmp(A.p, B.p, bytes) == 0) { 916 /* Test with A aliased to B and output, since this is permitted - 917 * don't bother with yet another test with only A and B aliased */ 918 919 mbedtls_mpi_core_montmul(B.p, B.p, B.p, B.n, N.p, N.n, mm, T.p); 920 TEST_MEMORY_COMPARE(B.p, bytes, X->p, bytes); 921 922 memcpy(B.p, A.p, bytes); /* restore B from equal value A */ 923 } 924 925 /* The output may be aliased to B - last test, so we don't save B */ 926 927 mbedtls_mpi_core_montmul(B.p, A.p, B.p, B.n, N.p, N.n, mm, T.p); 928 TEST_MEMORY_COMPARE(B.p, bytes, X->p, bytes); 929 } 930 931exit: 932 mbedtls_mpi_free(&A); 933 mbedtls_mpi_free(&B); 934 mbedtls_mpi_free(&N); 935 mbedtls_mpi_free(&X4); 936 mbedtls_mpi_free(&X8); 937 mbedtls_mpi_free(&T); 938 mbedtls_mpi_free(&R); 939} 940/* END_CASE */ 941 942/* BEGIN_CASE */ 943void mpi_core_get_mont_r2_unsafe_neg() 944{ 945 mbedtls_mpi N, RR; 946 mbedtls_mpi_init(&N); 947 mbedtls_mpi_init(&RR); 948 const char *n = "7ffffffffffffff1"; 949 950 /* Test for zero divisor */ 951 TEST_EQUAL(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO, 952 mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N)); 953 954 /* Test for negative input */ 955 TEST_EQUAL(0, mbedtls_test_read_mpi(&N, n)); 956 N.s = -1; 957 TEST_EQUAL(MBEDTLS_ERR_MPI_NEGATIVE_VALUE, 958 mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N)); 959 N.s = 1; 960 961exit: 962 mbedtls_mpi_free(&N); 963 mbedtls_mpi_free(&RR); 964} 965/* END_CASE */ 966 967/* BEGIN_CASE */ 968void mpi_core_get_mont_r2_unsafe(char *input_N, 969 char *input_RR_X4, 970 char *input_RR_X8) 971{ 972 mbedtls_mpi N, RR, RR_REF; 973 974 /* Select the appropriate output */ 975 char *input_rr = (sizeof(mbedtls_mpi_uint) == 4) ? input_RR_X4 : input_RR_X8; 976 977 mbedtls_mpi_init(&N); 978 mbedtls_mpi_init(&RR); 979 mbedtls_mpi_init(&RR_REF); 980 981 /* Read inputs */ 982 TEST_EQUAL(0, mbedtls_test_read_mpi(&N, input_N)); 983 TEST_EQUAL(0, mbedtls_test_read_mpi(&RR_REF, input_rr)); 984 985 /* All of the inputs are +ve (or zero) */ 986 TEST_EQUAL(1, N.s); 987 TEST_EQUAL(1, RR_REF.s); 988 989 /* Test valid input */ 990 TEST_EQUAL(0, mbedtls_mpi_core_get_mont_r2_unsafe(&RR, &N)); 991 992 /* Test that the moduli is odd */ 993 TEST_EQUAL(N.p[0] ^ 1, N.p[0] - 1); 994 995 /* Output is +ve (or zero) */ 996 TEST_EQUAL(1, RR_REF.s); 997 998 /* rr is updated to a valid pointer */ 999 TEST_ASSERT(RR.p != NULL); 1000 1001 /* Calculated rr matches expected value */ 1002 TEST_ASSERT(mbedtls_mpi_cmp_mpi(&RR, &RR_REF) == 0); 1003 1004exit: 1005 mbedtls_mpi_free(&N); 1006 mbedtls_mpi_free(&RR); 1007 mbedtls_mpi_free(&RR_REF); 1008} 1009/* END_CASE */ 1010 1011/* BEGIN_CASE depends_on:MBEDTLS_TEST_HOOKS */ 1012void mpi_core_ct_uint_table_lookup(int bitlen, int window_size) 1013{ 1014 size_t limbs = BITS_TO_LIMBS(bitlen); 1015 size_t count = ((size_t) 1) << window_size; 1016 1017 mbedtls_mpi_uint *table = NULL; 1018 mbedtls_mpi_uint *dest = NULL; 1019 1020 TEST_CALLOC(table, limbs * count); 1021 TEST_CALLOC(dest, limbs); 1022 1023 /* 1024 * Fill the table with a unique counter so that differences are easily 1025 * detected. (And have their relationship to the index relatively non-trivial just 1026 * to be sure.) 1027 */ 1028 for (size_t i = 0; i < count * limbs; i++) { 1029 table[i] = ~i - 1; 1030 } 1031 1032 for (size_t i = 0; i < count; i++) { 1033 mbedtls_mpi_uint *current = table + i * limbs; 1034 memset(dest, 0x00, limbs * sizeof(*dest)); 1035 1036 /* 1037 * We shouldn't leak anything through timing. 1038 * We need to set these in every loop as we need to make the loop 1039 * variable public for the loop head and the buffers for comparison. 1040 */ 1041 TEST_CF_SECRET(&i, sizeof(i)); 1042 TEST_CF_SECRET(dest, limbs * sizeof(*dest)); 1043 TEST_CF_SECRET(table, count * limbs * sizeof(*table)); 1044 1045 mbedtls_mpi_core_ct_uint_table_lookup(dest, table, limbs, count, i); 1046 1047 TEST_CF_PUBLIC(dest, limbs * sizeof(*dest)); 1048 TEST_CF_PUBLIC(table, count * limbs * sizeof(*table)); 1049 TEST_MEMORY_COMPARE(dest, limbs * sizeof(*dest), 1050 current, limbs * sizeof(*current)); 1051 TEST_CF_PUBLIC(&i, sizeof(i)); 1052 } 1053 1054exit: 1055 mbedtls_free(table); 1056 mbedtls_free(dest); 1057} 1058/* END_CASE */ 1059 1060/* BEGIN_CASE */ 1061void mpi_core_fill_random(int wanted_bytes_arg, int extra_rng_bytes, 1062 int extra_limbs, int before, int expected_ret) 1063{ 1064 size_t wanted_bytes = wanted_bytes_arg; 1065 mbedtls_mpi_uint *X = NULL; 1066 size_t X_limbs = CHARS_TO_LIMBS(wanted_bytes) + extra_limbs; 1067 size_t rng_bytes = wanted_bytes + extra_rng_bytes; 1068 unsigned char *rnd_data = NULL; 1069 mbedtls_test_rnd_buf_info rnd_info = { NULL, rng_bytes, NULL, NULL }; 1070 int ret; 1071 1072 /* Prepare an RNG with known output, limited to rng_bytes. */ 1073 TEST_CALLOC(rnd_data, rng_bytes); 1074 TEST_EQUAL(0, mbedtls_test_rnd_std_rand(NULL, rnd_data, rng_bytes)); 1075 rnd_info.buf = rnd_data; 1076 1077 /* Allocate an MPI with room for wanted_bytes plus extra_limbs. 1078 * extra_limbs may be negative but the total limb count must be positive. 1079 * Fill the MPI with the byte value in before. */ 1080 TEST_LE_U(1, X_limbs); 1081 TEST_CALLOC(X, X_limbs); 1082 memset(X, before, X_limbs * sizeof(*X)); 1083 1084 ret = mbedtls_mpi_core_fill_random(X, X_limbs, wanted_bytes, 1085 mbedtls_test_rnd_buffer_rand, 1086 &rnd_info); 1087 TEST_EQUAL(expected_ret, ret); 1088 1089 if (expected_ret == 0) { 1090 /* mbedtls_mpi_core_fill_random is documented to use bytes from the 1091 * RNG as a big-endian representation of the number. We used an RNG 1092 * with known output, so check that the output contains the 1093 * expected value. Bytes above wanted_bytes must be zero. */ 1094 for (size_t i = 0; i < wanted_bytes; i++) { 1095 mbedtls_test_set_step(i); 1096 TEST_EQUAL(GET_BYTE(X, i), rnd_data[wanted_bytes - 1 - i]); 1097 } 1098 for (size_t i = wanted_bytes; i < X_limbs * ciL; i++) { 1099 mbedtls_test_set_step(i); 1100 TEST_EQUAL(GET_BYTE(X, i), 0); 1101 } 1102 } 1103 1104exit: 1105 mbedtls_free(rnd_data); 1106 mbedtls_free(X); 1107} 1108/* END_CASE */ 1109 1110/* BEGIN_CASE */ 1111void mpi_core_mul(char *input_A, 1112 char *input_B, 1113 char *result) 1114{ 1115 mbedtls_mpi_uint *A = NULL; 1116 mbedtls_mpi_uint *A_orig = NULL; 1117 mbedtls_mpi_uint *B = NULL; 1118 mbedtls_mpi_uint *B_orig = NULL; 1119 mbedtls_mpi_uint *R = NULL; 1120 mbedtls_mpi_uint *X = NULL; 1121 size_t A_limbs, B_limbs, R_limbs; 1122 1123 TEST_EQUAL(mbedtls_test_read_mpi_core(&A, &A_limbs, input_A), 0); 1124 TEST_EQUAL(mbedtls_test_read_mpi_core(&B, &B_limbs, input_B), 0); 1125 TEST_EQUAL(mbedtls_test_read_mpi_core(&R, &R_limbs, result), 0); 1126 1127 TEST_EQUAL(R_limbs, A_limbs + B_limbs); 1128 1129 const size_t X_limbs = A_limbs + B_limbs; 1130 const size_t X_bytes = X_limbs * sizeof(mbedtls_mpi_uint); 1131 TEST_CALLOC(X, X_limbs); 1132 1133 const size_t A_bytes = A_limbs * sizeof(mbedtls_mpi_uint); 1134 TEST_CALLOC(A_orig, A_limbs); 1135 memcpy(A_orig, A, A_bytes); 1136 1137 const size_t B_bytes = B_limbs * sizeof(mbedtls_mpi_uint); 1138 TEST_CALLOC(B_orig, B_limbs); 1139 memcpy(B_orig, B, B_bytes); 1140 1141 /* Set result to something that is unlikely to be correct */ 1142 memset(X, '!', X_bytes); 1143 1144 /* 1. X = A * B - result should be correct, A and B unchanged */ 1145 mbedtls_mpi_core_mul(X, A, A_limbs, B, B_limbs); 1146 TEST_MEMORY_COMPARE(X, X_bytes, R, X_bytes); 1147 TEST_MEMORY_COMPARE(A, A_bytes, A_orig, A_bytes); 1148 TEST_MEMORY_COMPARE(B, B_bytes, B_orig, B_bytes); 1149 1150 /* 2. A == B: alias A and B - result should be correct, A and B unchanged */ 1151 if (A_bytes == B_bytes && memcmp(A, B, A_bytes) == 0) { 1152 memset(X, '!', X_bytes); 1153 mbedtls_mpi_core_mul(X, A, A_limbs, A, A_limbs); 1154 TEST_MEMORY_COMPARE(X, X_bytes, R, X_bytes); 1155 TEST_MEMORY_COMPARE(A, A_bytes, A_orig, A_bytes); 1156 } 1157 /* 3. X = B * A - result should be correct, A and B unchanged */ 1158 else { 1159 memset(X, '!', X_bytes); 1160 mbedtls_mpi_core_mul(X, B, B_limbs, A, A_limbs); 1161 TEST_MEMORY_COMPARE(X, X_bytes, R, X_bytes); 1162 TEST_MEMORY_COMPARE(A, A_bytes, A_orig, A_bytes); 1163 TEST_MEMORY_COMPARE(B, B_bytes, B_orig, B_bytes); 1164 } 1165 1166exit: 1167 mbedtls_free(A); 1168 mbedtls_free(A_orig); 1169 mbedtls_free(B); 1170 mbedtls_free(B_orig); 1171 mbedtls_free(R); 1172 mbedtls_free(X); 1173} 1174/* END_CASE */ 1175 1176/* BEGIN_CASE */ 1177void mpi_core_exp_mod(char *input_N, char *input_A, 1178 char *input_E, char *input_X) 1179{ 1180 mbedtls_mpi_uint *A = NULL; 1181 mbedtls_mpi_uint *E = NULL; 1182 mbedtls_mpi_uint *N = NULL; 1183 mbedtls_mpi_uint *X = NULL; 1184 size_t A_limbs, E_limbs, N_limbs, X_limbs; 1185 const mbedtls_mpi_uint *R2 = NULL; 1186 mbedtls_mpi_uint *Y = NULL; 1187 mbedtls_mpi_uint *T = NULL; 1188 /* Legacy MPIs for computing R2 */ 1189 mbedtls_mpi N_mpi; 1190 mbedtls_mpi_init(&N_mpi); 1191 mbedtls_mpi R2_mpi; 1192 mbedtls_mpi_init(&R2_mpi); 1193 1194 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&A, &A_limbs, input_A)); 1195 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&E, &E_limbs, input_E)); 1196 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&N, &N_limbs, input_N)); 1197 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &X_limbs, input_X)); 1198 TEST_CALLOC(Y, N_limbs); 1199 1200 TEST_EQUAL(A_limbs, N_limbs); 1201 TEST_EQUAL(X_limbs, N_limbs); 1202 1203 TEST_EQUAL(0, mbedtls_mpi_grow(&N_mpi, N_limbs)); 1204 memcpy(N_mpi.p, N, N_limbs * sizeof(*N)); 1205 N_mpi.n = N_limbs; 1206 TEST_EQUAL(0, 1207 mbedtls_mpi_core_get_mont_r2_unsafe(&R2_mpi, &N_mpi)); 1208 TEST_EQUAL(0, mbedtls_mpi_grow(&R2_mpi, N_limbs)); 1209 R2 = R2_mpi.p; 1210 1211 size_t working_limbs = mbedtls_mpi_core_exp_mod_working_limbs(N_limbs, 1212 E_limbs); 1213 1214 /* No point exactly duplicating the code in mbedtls_mpi_core_exp_mod_working_limbs() 1215 * to see if the output is correct, but we can check that it's in a 1216 * reasonable range. The current calculation works out as 1217 * `1 + N_limbs * (welem + 3)`, where welem is the number of elements in 1218 * the window (1 << 1 up to 1 << 6). 1219 */ 1220 size_t min_expected_working_limbs = 1 + N_limbs * 4; 1221 size_t max_expected_working_limbs = 1 + N_limbs * 67; 1222 1223 TEST_LE_U(min_expected_working_limbs, working_limbs); 1224 TEST_LE_U(working_limbs, max_expected_working_limbs); 1225 1226 /* Should also be at least mbedtls_mpi_core_montmul_working_limbs() */ 1227 TEST_LE_U(mbedtls_mpi_core_montmul_working_limbs(N_limbs), 1228 working_limbs); 1229 1230 TEST_CALLOC(T, working_limbs); 1231 1232 mbedtls_mpi_core_exp_mod(Y, A, N, N_limbs, E, E_limbs, R2, T); 1233 1234 TEST_EQUAL(0, memcmp(X, Y, N_limbs * sizeof(mbedtls_mpi_uint))); 1235 1236 /* Check when output aliased to input */ 1237 1238 mbedtls_mpi_core_exp_mod(A, A, N, N_limbs, E, E_limbs, R2, T); 1239 1240 TEST_EQUAL(0, memcmp(X, A, N_limbs * sizeof(mbedtls_mpi_uint))); 1241 1242exit: 1243 mbedtls_free(T); 1244 mbedtls_free(A); 1245 mbedtls_free(E); 1246 mbedtls_free(N); 1247 mbedtls_free(X); 1248 mbedtls_free(Y); 1249 mbedtls_mpi_free(&N_mpi); 1250 mbedtls_mpi_free(&R2_mpi); 1251 // R2 doesn't need to be freed as it is only aliasing R2_mpi 1252} 1253/* END_CASE */ 1254 1255/* BEGIN_CASE */ 1256void mpi_core_sub_int(char *input_A, char *input_B, 1257 char *input_X, int borrow) 1258{ 1259 /* We are testing A - b, where A is an MPI and b is a scalar, expecting 1260 * result X with borrow borrow. However, for ease of handling we encode b 1261 * as a 1-limb MPI (B) in the .data file. */ 1262 1263 mbedtls_mpi_uint *A = NULL; 1264 mbedtls_mpi_uint *B = NULL; 1265 mbedtls_mpi_uint *X = NULL; 1266 mbedtls_mpi_uint *R = NULL; 1267 size_t A_limbs, B_limbs, X_limbs; 1268 1269 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&A, &A_limbs, input_A)); 1270 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&B, &B_limbs, input_B)); 1271 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &X_limbs, input_X)); 1272 1273 /* The MPI encoding of scalar b must be only 1 limb */ 1274 TEST_EQUAL(B_limbs, 1); 1275 1276 /* The subtraction is fixed-width, so A and X must have the same number of limbs */ 1277 TEST_EQUAL(A_limbs, X_limbs); 1278 size_t limbs = A_limbs; 1279 1280 TEST_CALLOC(R, limbs); 1281 1282#define TEST_COMPARE_CORE_MPIS(A, B, limbs) \ 1283 TEST_MEMORY_COMPARE(A, (limbs) * sizeof(mbedtls_mpi_uint), \ 1284 B, (limbs) * sizeof(mbedtls_mpi_uint)) 1285 1286 /* 1. R = A - b. Result and borrow should be correct */ 1287 TEST_EQUAL(mbedtls_mpi_core_sub_int(R, A, B[0], limbs), borrow); 1288 TEST_COMPARE_CORE_MPIS(R, X, limbs); 1289 1290 /* 2. A = A - b. Result and borrow should be correct */ 1291 TEST_EQUAL(mbedtls_mpi_core_sub_int(A, A, B[0], limbs), borrow); 1292 TEST_COMPARE_CORE_MPIS(A, X, limbs); 1293 1294exit: 1295 mbedtls_free(A); 1296 mbedtls_free(B); 1297 mbedtls_free(X); 1298 mbedtls_free(R); 1299} 1300/* END_CASE */ 1301 1302/* BEGIN_CASE */ 1303void mpi_core_check_zero_ct(char *input_X, int expected_is_zero) 1304{ 1305 mbedtls_mpi_uint *X = NULL; 1306 size_t X_limbs; 1307 1308 TEST_EQUAL(0, mbedtls_test_read_mpi_core(&X, &X_limbs, input_X)); 1309 1310 TEST_CF_SECRET(X, X_limbs * sizeof(mbedtls_mpi_uint)); 1311 1312 mbedtls_mpi_uint check = mbedtls_mpi_core_check_zero_ct(X, X_limbs); 1313 int is_zero = (check == 0); 1314 TEST_EQUAL(is_zero, expected_is_zero); 1315 1316exit: 1317 mbedtls_free(X); 1318} 1319/* END_CASE */ 1320