test_suite_bignum_random.function 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481
  1. /* BEGIN_HEADER */
  2. /* Dedicated test suite for mbedtls_mpi_core_random() and the upper-layer
  3. * functions. Due to the complexity of how these functions are tested,
  4. * we test all the layers in a single test suite, unlike the way other
  5. * functions are tested with each layer in its own test suite.
  6. *
  7. * Test strategy
  8. * =============
  9. *
  10. * There are three main goals for testing random() functions:
  11. * - Parameter validation.
  12. * - Correctness of outputs (well-formed, in range).
  13. * - Distribution of outputs.
  14. *
  15. * We test parameter validation in a standard way, with unit tests with
  16. * positive and negative cases:
  17. * - mbedtls_mpi_core_random(): negative cases for mpi_core_random_basic.
  18. * - mbedtls_mpi_mod_raw_random(), mbedtls_mpi_mod_random(): negative
  19. * cases for mpi_mod_random_validation.
  20. * - mbedtls_mpi_random(): mpi_random_fail.
  21. *
  22. * We test the correctness of outputs in positive tests:
  23. * - mbedtls_mpi_core_random(): positive cases for mpi_core_random_basic,
  24. * and mpi_random_many.
  25. * - mbedtls_mpi_mod_raw_random(), mbedtls_mpi_mod_random(): tested indirectly
  26. * via mpi_mod_random_values.
  27. * - mbedtls_mpi_random(): mpi_random_sizes, plus indirectly via
  28. * mpi_random_values.
  29. *
  30. * We test the distribution of outputs only for mbedtls_mpi_core_random(),
  31. * in mpi_random_many, which runs the function multiple times. This also
  32. * helps in validating the output range, through test cases with a small
  33. * range where any output out of range would be very likely to lead to a
  34. * test failure. For the other functions, we validate the distribution
  35. * indirectly by testing that these functions consume the random generator
  36. * in the same way as mbedtls_mpi_core_random(). This is done in
  37. * mpi_mod_random_values and mpi_legacy_random_values.
  38. */
  39. #include "mbedtls/bignum.h"
  40. #include "mbedtls/entropy.h"
  41. #include "bignum_core.h"
  42. #include "bignum_mod_raw.h"
  43. #include "constant_time_internal.h"
  44. /* This test suite only manipulates non-negative bignums. */
  45. static int sign_is_valid(const mbedtls_mpi *X)
  46. {
  47. return X->s == 1;
  48. }
  49. /* A common initializer for test functions that should generate the same
  50. * sequences for reproducibility and good coverage. */
  51. const mbedtls_test_rnd_pseudo_info rnd_pseudo_seed = {
  52. /* 16-word key */
  53. { 'T', 'h', 'i', 's', ' ', 'i', 's', ' ',
  54. 'a', ' ', 's', 'e', 'e', 'd', '!', 0 },
  55. /* 2-word initial state, should be zero */
  56. 0, 0
  57. };
  58. /* Test whether bytes represents (in big-endian base 256) a number b that
  59. * is significantly above a power of 2. That is, b must not have a long run
  60. * of unset bits after the most significant bit.
  61. *
  62. * Let n be the bit-size of b, i.e. the integer such that 2^n <= b < 2^{n+1}.
  63. * This function returns 1 if, when drawing a number between 0 and b,
  64. * the probability that this number is at least 2^n is not negligible.
  65. * This probability is (b - 2^n) / b and this function checks that this
  66. * number is above some threshold A. The threshold value is heuristic and
  67. * based on the needs of mpi_random_many().
  68. */
  69. static int is_significantly_above_a_power_of_2(data_t *bytes)
  70. {
  71. const uint8_t *p = bytes->x;
  72. size_t len = bytes->len;
  73. unsigned x;
  74. /* Skip leading null bytes */
  75. while (len > 0 && p[0] == 0) {
  76. ++p;
  77. --len;
  78. }
  79. /* 0 is not significantly above a power of 2 */
  80. if (len == 0) {
  81. return 0;
  82. }
  83. /* Extract the (up to) 2 most significant bytes */
  84. if (len == 1) {
  85. x = p[0];
  86. } else {
  87. x = (p[0] << 8) | p[1];
  88. }
  89. /* Shift the most significant bit of x to position 8 and mask it out */
  90. while ((x & 0xfe00) != 0) {
  91. x >>= 1;
  92. }
  93. x &= 0x00ff;
  94. /* At this point, x = floor((b - 2^n) / 2^(n-8)). b is significantly above
  95. * a power of 2 iff x is significantly above 0 compared to 2^8.
  96. * Testing x >= 2^4 amounts to picking A = 1/16 in the function
  97. * description above. */
  98. return x >= 0x10;
  99. }
  100. /* END_HEADER */
  101. /* BEGIN_DEPENDENCIES
  102. * depends_on:MBEDTLS_BIGNUM_C
  103. * END_DEPENDENCIES
  104. */
  105. /* BEGIN_CASE */
  106. void mpi_core_random_basic(int min, char *bound_bytes, int expected_ret)
  107. {
  108. /* Same RNG as in mpi_random_values */
  109. mbedtls_test_rnd_pseudo_info rnd = rnd_pseudo_seed;
  110. size_t limbs;
  111. mbedtls_mpi_uint *lower_bound = NULL;
  112. mbedtls_mpi_uint *upper_bound = NULL;
  113. mbedtls_mpi_uint *result = NULL;
  114. TEST_EQUAL(0, mbedtls_test_read_mpi_core(&upper_bound, &limbs,
  115. bound_bytes));
  116. ASSERT_ALLOC(lower_bound, limbs);
  117. lower_bound[0] = min;
  118. ASSERT_ALLOC(result, limbs);
  119. TEST_EQUAL(expected_ret,
  120. mbedtls_mpi_core_random(result, min, upper_bound, limbs,
  121. mbedtls_test_rnd_pseudo_rand, &rnd));
  122. if (expected_ret == 0) {
  123. TEST_EQUAL(0, mbedtls_mpi_core_lt_ct(result, lower_bound, limbs));
  124. TEST_EQUAL(1, mbedtls_mpi_core_lt_ct(result, upper_bound, limbs));
  125. }
  126. exit:
  127. mbedtls_free(lower_bound);
  128. mbedtls_free(upper_bound);
  129. mbedtls_free(result);
  130. }
  131. /* END_CASE */
  132. /* BEGIN_CASE */
  133. void mpi_legacy_random_values(int min, char *max_hex)
  134. {
  135. /* Same RNG as in mpi_core_random_basic */
  136. mbedtls_test_rnd_pseudo_info rnd_core = rnd_pseudo_seed;
  137. mbedtls_test_rnd_pseudo_info rnd_legacy;
  138. memcpy(&rnd_legacy, &rnd_core, sizeof(rnd_core));
  139. mbedtls_mpi max_legacy;
  140. mbedtls_mpi_init(&max_legacy);
  141. mbedtls_mpi_uint *R_core = NULL;
  142. mbedtls_mpi R_legacy;
  143. mbedtls_mpi_init(&R_legacy);
  144. TEST_EQUAL(0, mbedtls_test_read_mpi(&max_legacy, max_hex));
  145. size_t limbs = max_legacy.n;
  146. ASSERT_ALLOC(R_core, limbs);
  147. /* Call the legacy function and the core function with the same random
  148. * stream. */
  149. int core_ret = mbedtls_mpi_core_random(R_core, min, max_legacy.p, limbs,
  150. mbedtls_test_rnd_pseudo_rand,
  151. &rnd_core);
  152. int legacy_ret = mbedtls_mpi_random(&R_legacy, min, &max_legacy,
  153. mbedtls_test_rnd_pseudo_rand,
  154. &rnd_legacy);
  155. /* They must return the same status, and, on success, output the
  156. * same number, with the same limb count. */
  157. TEST_EQUAL(core_ret, legacy_ret);
  158. if (core_ret == 0) {
  159. ASSERT_COMPARE(R_core, limbs * ciL,
  160. R_legacy.p, R_legacy.n * ciL);
  161. }
  162. /* Also check that they have consumed the RNG in the same way. */
  163. /* This may theoretically fail on rare platforms with padding in
  164. * the structure! If this is a problem in practice, change to a
  165. * field-by-field comparison. */
  166. ASSERT_COMPARE(&rnd_core, sizeof(rnd_core),
  167. &rnd_legacy, sizeof(rnd_legacy));
  168. exit:
  169. mbedtls_mpi_free(&max_legacy);
  170. mbedtls_free(R_core);
  171. mbedtls_mpi_free(&R_legacy);
  172. }
  173. /* END_CASE */
  174. /* BEGIN_CASE */
  175. void mpi_mod_random_values(int min, char *max_hex, int rep)
  176. {
  177. /* Same RNG as in mpi_core_random_basic */
  178. mbedtls_test_rnd_pseudo_info rnd_core = rnd_pseudo_seed;
  179. mbedtls_test_rnd_pseudo_info rnd_mod_raw;
  180. memcpy(&rnd_mod_raw, &rnd_core, sizeof(rnd_core));
  181. mbedtls_test_rnd_pseudo_info rnd_mod;
  182. memcpy(&rnd_mod, &rnd_core, sizeof(rnd_core));
  183. mbedtls_mpi_uint *R_core = NULL;
  184. mbedtls_mpi_uint *R_mod_raw = NULL;
  185. mbedtls_mpi_uint *R_mod_digits = NULL;
  186. mbedtls_mpi_mod_residue R_mod;
  187. mbedtls_mpi_mod_modulus N;
  188. mbedtls_mpi_mod_modulus_init(&N);
  189. TEST_EQUAL(mbedtls_test_read_mpi_modulus(&N, max_hex, rep), 0);
  190. ASSERT_ALLOC(R_core, N.limbs);
  191. ASSERT_ALLOC(R_mod_raw, N.limbs);
  192. ASSERT_ALLOC(R_mod_digits, N.limbs);
  193. TEST_EQUAL(mbedtls_mpi_mod_residue_setup(&R_mod, &N,
  194. R_mod_digits, N.limbs),
  195. 0);
  196. /* Call the core and mod random() functions with the same random stream. */
  197. int core_ret = mbedtls_mpi_core_random(R_core,
  198. min, N.p, N.limbs,
  199. mbedtls_test_rnd_pseudo_rand,
  200. &rnd_core);
  201. int mod_raw_ret = mbedtls_mpi_mod_raw_random(R_mod_raw,
  202. min, &N,
  203. mbedtls_test_rnd_pseudo_rand,
  204. &rnd_mod_raw);
  205. int mod_ret = mbedtls_mpi_mod_random(&R_mod,
  206. min, &N,
  207. mbedtls_test_rnd_pseudo_rand,
  208. &rnd_mod);
  209. /* They must return the same status, and, on success, output the
  210. * same number, with the same limb count. */
  211. TEST_EQUAL(core_ret, mod_raw_ret);
  212. TEST_EQUAL(core_ret, mod_ret);
  213. if (core_ret == 0) {
  214. TEST_EQUAL(mbedtls_mpi_mod_raw_modulus_to_canonical_rep(R_mod_raw, &N),
  215. 0);
  216. ASSERT_COMPARE(R_core, N.limbs * ciL,
  217. R_mod_raw, N.limbs * ciL);
  218. TEST_EQUAL(mbedtls_mpi_mod_raw_modulus_to_canonical_rep(R_mod_digits, &N),
  219. 0);
  220. ASSERT_COMPARE(R_core, N.limbs * ciL,
  221. R_mod_digits, N.limbs * ciL);
  222. }
  223. /* Also check that they have consumed the RNG in the same way. */
  224. /* This may theoretically fail on rare platforms with padding in
  225. * the structure! If this is a problem in practice, change to a
  226. * field-by-field comparison. */
  227. ASSERT_COMPARE(&rnd_core, sizeof(rnd_core),
  228. &rnd_mod_raw, sizeof(rnd_mod_raw));
  229. ASSERT_COMPARE(&rnd_core, sizeof(rnd_core),
  230. &rnd_mod, sizeof(rnd_mod));
  231. exit:
  232. mbedtls_test_mpi_mod_modulus_free_with_limbs(&N);
  233. mbedtls_free(R_core);
  234. mbedtls_free(R_mod_raw);
  235. mbedtls_free(R_mod_digits);
  236. }
  237. /* END_CASE */
  238. /* BEGIN_CASE */
  239. void mpi_random_many(int min, char *bound_hex, int iterations)
  240. {
  241. /* Generate numbers in the range 1..bound-1. Do it iterations times.
  242. * This function assumes that the value of bound is at least 2 and
  243. * that iterations is large enough that a one-in-2^iterations chance
  244. * effectively never occurs.
  245. */
  246. data_t bound_bytes = { NULL, 0 };
  247. mbedtls_mpi_uint *upper_bound = NULL;
  248. size_t limbs;
  249. size_t n_bits;
  250. mbedtls_mpi_uint *result = NULL;
  251. size_t b;
  252. /* If upper_bound is small, stats[b] is the number of times the value b
  253. * has been generated. Otherwise stats[b] is the number of times a
  254. * value with bit b set has been generated. */
  255. size_t *stats = NULL;
  256. size_t stats_len;
  257. int full_stats;
  258. size_t i;
  259. TEST_EQUAL(0, mbedtls_test_read_mpi_core(&upper_bound, &limbs,
  260. bound_hex));
  261. ASSERT_ALLOC(result, limbs);
  262. n_bits = mbedtls_mpi_core_bitlen(upper_bound, limbs);
  263. /* Consider a bound "small" if it's less than 2^5. This value is chosen
  264. * to be small enough that the probability of missing one value is
  265. * negligible given the number of iterations. It must be less than
  266. * 256 because some of the code below assumes that "small" values
  267. * fit in a byte. */
  268. if (n_bits <= 5) {
  269. full_stats = 1;
  270. stats_len = (uint8_t) upper_bound[0];
  271. } else {
  272. full_stats = 0;
  273. stats_len = n_bits;
  274. }
  275. ASSERT_ALLOC(stats, stats_len);
  276. for (i = 0; i < (size_t) iterations; i++) {
  277. mbedtls_test_set_step(i);
  278. TEST_EQUAL(0, mbedtls_mpi_core_random(result,
  279. min, upper_bound, limbs,
  280. mbedtls_test_rnd_std_rand, NULL));
  281. /* Temporarily use a legacy MPI for analysis, because the
  282. * necessary auxiliary functions don't exist yet in core. */
  283. mbedtls_mpi B = { 1, limbs, upper_bound };
  284. mbedtls_mpi R = { 1, limbs, result };
  285. TEST_ASSERT(mbedtls_mpi_cmp_mpi(&R, &B) < 0);
  286. TEST_ASSERT(mbedtls_mpi_cmp_int(&R, min) >= 0);
  287. if (full_stats) {
  288. uint8_t value;
  289. TEST_EQUAL(0, mbedtls_mpi_write_binary(&R, &value, 1));
  290. TEST_ASSERT(value < stats_len);
  291. ++stats[value];
  292. } else {
  293. for (b = 0; b < n_bits; b++) {
  294. stats[b] += mbedtls_mpi_get_bit(&R, b);
  295. }
  296. }
  297. }
  298. if (full_stats) {
  299. for (b = min; b < stats_len; b++) {
  300. mbedtls_test_set_step(1000000 + b);
  301. /* Assert that each value has been reached at least once.
  302. * This is almost guaranteed if the iteration count is large
  303. * enough. This is a very crude way of checking the distribution.
  304. */
  305. TEST_ASSERT(stats[b] > 0);
  306. }
  307. } else {
  308. bound_bytes.len = limbs * sizeof(mbedtls_mpi_uint);
  309. ASSERT_ALLOC(bound_bytes.x, bound_bytes.len);
  310. mbedtls_mpi_core_write_be(upper_bound, limbs,
  311. bound_bytes.x, bound_bytes.len);
  312. int statistically_safe_all_the_way =
  313. is_significantly_above_a_power_of_2(&bound_bytes);
  314. for (b = 0; b < n_bits; b++) {
  315. mbedtls_test_set_step(1000000 + b);
  316. /* Assert that each bit has been set in at least one result and
  317. * clear in at least one result. Provided that iterations is not
  318. * too small, it would be extremely unlikely for this not to be
  319. * the case if the results are uniformly distributed.
  320. *
  321. * As an exception, the top bit may legitimately never be set
  322. * if bound is a power of 2 or only slightly above.
  323. */
  324. if (statistically_safe_all_the_way || b != n_bits - 1) {
  325. TEST_ASSERT(stats[b] > 0);
  326. }
  327. TEST_ASSERT(stats[b] < (size_t) iterations);
  328. }
  329. }
  330. exit:
  331. mbedtls_free(bound_bytes.x);
  332. mbedtls_free(upper_bound);
  333. mbedtls_free(result);
  334. mbedtls_free(stats);
  335. }
  336. /* END_CASE */
  337. /* BEGIN_CASE */
  338. void mpi_random_sizes(int min, data_t *bound_bytes, int nlimbs, int before)
  339. {
  340. mbedtls_mpi upper_bound;
  341. mbedtls_mpi result;
  342. mbedtls_mpi_init(&upper_bound);
  343. mbedtls_mpi_init(&result);
  344. if (before != 0) {
  345. /* Set result to sign(before) * 2^(|before|-1) */
  346. TEST_ASSERT(mbedtls_mpi_lset(&result, before > 0 ? 1 : -1) == 0);
  347. if (before < 0) {
  348. before = -before;
  349. }
  350. TEST_ASSERT(mbedtls_mpi_shift_l(&result, before - 1) == 0);
  351. }
  352. TEST_EQUAL(0, mbedtls_mpi_grow(&result, nlimbs));
  353. TEST_EQUAL(0, mbedtls_mpi_read_binary(&upper_bound,
  354. bound_bytes->x, bound_bytes->len));
  355. TEST_EQUAL(0, mbedtls_mpi_random(&result, min, &upper_bound,
  356. mbedtls_test_rnd_std_rand, NULL));
  357. TEST_ASSERT(sign_is_valid(&result));
  358. TEST_ASSERT(mbedtls_mpi_cmp_mpi(&result, &upper_bound) < 0);
  359. TEST_ASSERT(mbedtls_mpi_cmp_int(&result, min) >= 0);
  360. exit:
  361. mbedtls_mpi_free(&upper_bound);
  362. mbedtls_mpi_free(&result);
  363. }
  364. /* END_CASE */
  365. /* BEGIN_CASE */
  366. void mpi_mod_random_validation(int min, char *bound_hex,
  367. int result_limbs_delta,
  368. int expected_ret)
  369. {
  370. mbedtls_mpi_uint *result_digits = NULL;
  371. mbedtls_mpi_mod_modulus N;
  372. mbedtls_mpi_mod_modulus_init(&N);
  373. TEST_EQUAL(mbedtls_test_read_mpi_modulus(&N, bound_hex,
  374. MBEDTLS_MPI_MOD_REP_OPT_RED),
  375. 0);
  376. size_t result_limbs = N.limbs + result_limbs_delta;
  377. ASSERT_ALLOC(result_digits, result_limbs);
  378. /* Build a reside that might not match the modulus, to test that
  379. * the library function rejects that as expected. */
  380. mbedtls_mpi_mod_residue result = { result_digits, result_limbs };
  381. TEST_EQUAL(mbedtls_mpi_mod_random(&result, min, &N,
  382. mbedtls_test_rnd_std_rand, NULL),
  383. expected_ret);
  384. if (expected_ret == 0) {
  385. /* Success should only be expected when the result has the same
  386. * size as the modulus, otherwise it's a mistake in the test data. */
  387. TEST_EQUAL(result_limbs, N.limbs);
  388. /* Sanity check: check that the result is in range */
  389. TEST_EQUAL(mbedtls_mpi_core_lt_ct(result_digits, N.p, N.limbs),
  390. 1);
  391. /* Check result >= min (changes result) */
  392. TEST_EQUAL(mbedtls_mpi_core_sub_int(result_digits, result_digits, min,
  393. result_limbs),
  394. 0);
  395. }
  396. /* When the result has the right number of limbs, also test mod_raw
  397. * (for which this is an unchecked precondition). */
  398. if (result_limbs_delta == 0) {
  399. TEST_EQUAL(mbedtls_mpi_mod_raw_random(result_digits, min, &N,
  400. mbedtls_test_rnd_std_rand, NULL),
  401. expected_ret);
  402. if (expected_ret == 0) {
  403. TEST_EQUAL(mbedtls_mpi_core_lt_ct(result_digits, N.p, N.limbs),
  404. 1);
  405. TEST_EQUAL(mbedtls_mpi_core_sub_int(result_digits, result.p, min,
  406. result_limbs),
  407. 0);
  408. }
  409. }
  410. exit:
  411. mbedtls_test_mpi_mod_modulus_free_with_limbs(&N);
  412. mbedtls_free(result_digits);
  413. }
  414. /* END_CASE */
  415. /* BEGIN_CASE */
  416. void mpi_random_fail(int min, data_t *bound_bytes, int expected_ret)
  417. {
  418. mbedtls_mpi upper_bound;
  419. mbedtls_mpi result;
  420. int actual_ret;
  421. mbedtls_mpi_init(&upper_bound);
  422. mbedtls_mpi_init(&result);
  423. TEST_EQUAL(0, mbedtls_mpi_read_binary(&upper_bound,
  424. bound_bytes->x, bound_bytes->len));
  425. actual_ret = mbedtls_mpi_random(&result, min, &upper_bound,
  426. mbedtls_test_rnd_std_rand, NULL);
  427. TEST_EQUAL(expected_ret, actual_ret);
  428. exit:
  429. mbedtls_mpi_free(&upper_bound);
  430. mbedtls_mpi_free(&result);
  431. }
  432. /* END_CASE */