You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

458 lines
14 KiB

  1. /* Jitter RNG: Health Tests
  2. *
  3. * Copyright (C) 2021 - 2022, Joshua E. Hill <josh@keypair.us>
  4. * Copyright (C) 2021 - 2022, Stephan Mueller <smueller@chronox.de>
  5. *
  6. * License: see LICENSE file in root directory
  7. *
  8. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
  9. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  10. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF
  11. * WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
  12. * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  13. * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
  14. * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
  15. * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
  16. * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  17. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
  18. * USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH
  19. * DAMAGE.
  20. */
  21. #include "jitterentropy-health.h"
  22. static jent_fips_failure_cb fips_cb = NULL;
  23. static int jent_health_cb_switch_blocked = 0;
  24. void jent_health_cb_block_switch(void)
  25. {
  26. jent_health_cb_switch_blocked = 1;
  27. }
  28. int jent_set_fips_failure_callback_internal(jent_fips_failure_cb cb)
  29. {
  30. if (jent_health_cb_switch_blocked)
  31. return -EAGAIN;
  32. fips_cb = cb;
  33. return 0;
  34. }
  35. /***************************************************************************
  36. * Lag Predictor Test
  37. *
  38. * This test is a vendor-defined conditional test that is designed to detect
  39. * a known failure mode where the result becomes mostly deterministic
  40. * Note that (lag_observations & JENT_LAG_MASK) is the index where the next
  41. * value provided will be stored.
  42. ***************************************************************************/
  43. #ifdef JENT_HEALTH_LAG_PREDICTOR
  44. /*
  45. * These cutoffs are configured using an entropy estimate of 1/osr under an
  46. * alpha=2^(-22) for a window size of 131072. The other health tests use
  47. * alpha=2^-30, but operate on much smaller window sizes. This larger selection
  48. * of alpha makes the behavior per-lag-window similar to the APT test.
  49. *
  50. * The global cutoffs are calculated using the
  51. * InverseBinomialCDF(n=(JENT_LAG_WINDOW_SIZE-JENT_LAG_HISTORY_SIZE), p=2^(-1/osr); 1-alpha)
  52. * The local cutoffs are somewhat more complicated. For background, see Feller's
  53. * _Introduction to Probability Theory and It's Applications_ Vol. 1,
  54. * Chapter 13, section 7 (in particular see equation 7.11, where x is a root
  55. * of the denominator of equation 7.6).
  56. *
  57. * We'll proceed using the notation of SP 800-90B Section 6.3.8 (which is
  58. * developed in Kelsey-McKay-Turan paper "Predictive Models for Min-entropy
  59. * Estimation".)
  60. *
  61. * Here, we set p=2^(-1/osr), seeking a run of successful guesses (r) with
  62. * probability of less than (1-alpha). That is, it is very very likely
  63. * (probability 1-alpha) that there is _no_ run of length r in a block of size
  64. * JENT_LAG_WINDOW_SIZE-JENT_LAG_HISTORY_SIZE.
  65. *
  66. * We have to iteratively look for an appropriate value for the cutoff r.
  67. */
  68. static const unsigned int jent_lag_global_cutoff_lookup[20] =
  69. { 66443, 93504, 104761, 110875, 114707, 117330, 119237, 120686, 121823,
  70. 122739, 123493, 124124, 124660, 125120, 125520, 125871, 126181, 126457,
  71. 126704, 126926 };
  72. static const unsigned int jent_lag_local_cutoff_lookup[20] =
  73. { 38, 75, 111, 146, 181, 215, 250, 284, 318, 351,
  74. 385, 419, 452, 485, 518, 551, 584, 617, 650, 683 };
  75. void jent_lag_init(struct rand_data *ec, unsigned int osr)
  76. {
  77. /*
  78. * Establish the lag global and local cutoffs based on the presumed
  79. * entropy rate of 1/osr.
  80. */
  81. if (osr > ARRAY_SIZE(jent_lag_global_cutoff_lookup)) {
  82. ec->lag_global_cutoff =
  83. jent_lag_global_cutoff_lookup[
  84. ARRAY_SIZE(jent_lag_global_cutoff_lookup) - 1];
  85. } else {
  86. ec->lag_global_cutoff = jent_lag_global_cutoff_lookup[osr - 1];
  87. }
  88. if (osr > ARRAY_SIZE(jent_lag_local_cutoff_lookup)) {
  89. ec->lag_local_cutoff =
  90. jent_lag_local_cutoff_lookup[
  91. ARRAY_SIZE(jent_lag_local_cutoff_lookup) - 1];
  92. } else {
  93. ec->lag_local_cutoff = jent_lag_local_cutoff_lookup[osr - 1];
  94. }
  95. }
  96. /**
  97. * Reset the lag counters
  98. *
  99. * @ec [in] Reference to entropy collector
  100. */
  101. static void jent_lag_reset(struct rand_data *ec)
  102. {
  103. unsigned int i;
  104. /* Reset Lag counters */
  105. ec->lag_prediction_success_count = 0;
  106. ec->lag_prediction_success_run = 0;
  107. ec->lag_best_predictor = 0; /* The first guess is basically arbitrary. */
  108. ec->lag_observations = 0;
  109. for (i = 0; i < JENT_LAG_HISTORY_SIZE; i++) {
  110. ec->lag_scoreboard[i] = 0;
  111. ec->lag_delta_history[i] = 0;
  112. }
  113. }
  114. /*
  115. * A macro for accessing the history. Index 0 is the last observed symbol
  116. * index 1 is the symbol observed two inputs ago, etc.
  117. */
  118. #define JENT_LAG_HISTORY(EC,LOC) \
  119. ((EC)->lag_delta_history[((EC)->lag_observations - (LOC) - 1) & \
  120. JENT_LAG_MASK])
  121. /**
  122. * Insert a new entropy event into the lag predictor test
  123. *
  124. * @ec [in] Reference to entropy collector
  125. * @current_delta [in] Current time delta
  126. */
  127. static void jent_lag_insert(struct rand_data *ec, uint64_t current_delta)
  128. {
  129. uint64_t prediction;
  130. unsigned int i;
  131. /* Initialize the delta_history */
  132. if (ec->lag_observations < JENT_LAG_HISTORY_SIZE) {
  133. ec->lag_delta_history[ec->lag_observations] = current_delta;
  134. ec->lag_observations++;
  135. return;
  136. }
  137. /*
  138. * The history is initialized. First make a guess and examine the
  139. * results.
  140. */
  141. prediction = JENT_LAG_HISTORY(ec, ec->lag_best_predictor);
  142. if (prediction == current_delta) {
  143. /* The prediction was correct. */
  144. ec->lag_prediction_success_count++;
  145. ec->lag_prediction_success_run++;
  146. if ((ec->lag_prediction_success_run >= ec->lag_local_cutoff) ||
  147. (ec->lag_prediction_success_count >= ec->lag_global_cutoff))
  148. ec->health_failure |= JENT_LAG_FAILURE;
  149. } else {
  150. /* The prediction wasn't correct. End any run of successes.*/
  151. ec->lag_prediction_success_run = 0;
  152. }
  153. /* Now update the predictors using the current data. */
  154. for (i = 0; i < JENT_LAG_HISTORY_SIZE; i++) {
  155. if (JENT_LAG_HISTORY(ec, i) == current_delta) {
  156. /*
  157. * The ith predictor (which guesses i + 1 symbols in
  158. * the past) successfully guessed.
  159. */
  160. ec->lag_scoreboard[i] ++;
  161. /*
  162. * Keep track of the best predictor (tie goes to the
  163. * shortest lag)
  164. */
  165. if (ec->lag_scoreboard[i] >
  166. ec->lag_scoreboard[ec->lag_best_predictor])
  167. ec->lag_best_predictor = i;
  168. }
  169. }
  170. /*
  171. * Finally, update the lag_delta_history array with the newly input
  172. * value.
  173. */
  174. ec->lag_delta_history[(ec->lag_observations) & JENT_LAG_MASK] =
  175. current_delta;
  176. ec->lag_observations++;
  177. /*
  178. * lag_best_predictor now is the index of the predictor with the largest
  179. * number of correct guesses.
  180. * This establishes our next guess.
  181. */
  182. /* Do we now need a new window? */
  183. if (ec->lag_observations >= JENT_LAG_WINDOW_SIZE)
  184. jent_lag_reset(ec);
  185. }
  186. static inline uint64_t jent_delta2(struct rand_data *ec, uint64_t current_delta)
  187. {
  188. /* Note that delta2_n = delta_n - delta_{n-1} */
  189. return jent_delta(JENT_LAG_HISTORY(ec, 0), current_delta);
  190. }
  191. static inline uint64_t jent_delta3(struct rand_data *ec, uint64_t delta2)
  192. {
  193. /*
  194. * Note that delta3_n = delta2_n - delta2_{n-1}
  195. * = delta2_n - (delta_{n-1} - delta_{n-2})
  196. */
  197. return jent_delta(jent_delta(JENT_LAG_HISTORY(ec, 1),
  198. JENT_LAG_HISTORY(ec, 0)), delta2);
  199. }
  200. #else /* JENT_HEALTH_LAG_PREDICTOR */
  201. static inline void jent_lag_insert(struct rand_data *ec, uint64_t current_delta)
  202. {
  203. (void)ec;
  204. (void)current_delta;
  205. }
  206. static inline uint64_t jent_delta2(struct rand_data *ec, uint64_t current_delta)
  207. {
  208. uint64_t delta2 = jent_delta(ec->last_delta, current_delta);
  209. ec->last_delta = current_delta;
  210. return delta2;
  211. }
  212. static inline uint64_t jent_delta3(struct rand_data *ec, uint64_t delta2)
  213. {
  214. uint64_t delta3 = jent_delta(ec->last_delta2, delta2);
  215. ec->last_delta2 = delta2;
  216. return delta3;
  217. }
  218. #endif /* JENT_HEALTH_LAG_PREDICTOR */
  219. /***************************************************************************
  220. * Adaptive Proportion Test
  221. *
  222. * This test complies with SP800-90B section 4.4.2.
  223. ***************************************************************************/
  224. /*
  225. * See the SP 800-90B comment #10b for the corrected cutoff for the SP 800-90B
  226. * APT.
  227. * http://www.untruth.org/~josh/sp80090b/UL%20SP800-90B-final%20comments%20v1.9%2020191212.pdf
  228. * In in the syntax of R, this is C = 2 + qbinom(1 − 2^(−30), 511, 2^(-1/osr)).
  229. * (The original formula wasn't correct because the first symbol must
  230. * necessarily have been observed, so there is no chance of observing 0 of these
  231. * symbols.)
  232. *
  233. * For any value above 14, this yields the maximal allowable value of 512
  234. * (by FIPS 140-2 IG 7.19 Resolution # 16, we cannot choose a cutoff value that
  235. * renders the test unable to fail).
  236. */
  237. static const unsigned int jent_apt_cutoff_lookup[15]=
  238. { 325, 422, 459, 477, 488, 494, 499, 502,
  239. 505, 507, 508, 509, 510, 511, 512 };
  240. void jent_apt_init(struct rand_data *ec, unsigned int osr)
  241. {
  242. /*
  243. * Establish the apt_cutoff based on the presumed entropy rate of
  244. * 1/osr.
  245. */
  246. if (osr >= ARRAY_SIZE(jent_apt_cutoff_lookup)) {
  247. ec->apt_cutoff = jent_apt_cutoff_lookup[
  248. ARRAY_SIZE(jent_apt_cutoff_lookup) - 1];
  249. } else {
  250. ec->apt_cutoff = jent_apt_cutoff_lookup[osr - 1];
  251. }
  252. }
  253. /**
  254. * Reset the APT counter
  255. *
  256. * @ec [in] Reference to entropy collector
  257. */
  258. static void jent_apt_reset(struct rand_data *ec)
  259. {
  260. /* When reset, accept the _next_ value input as the new base. */
  261. ec->apt_base_set = 0;
  262. }
  263. /**
  264. * Insert a new entropy event into APT
  265. *
  266. * @ec [in] Reference to entropy collector
  267. * @current_delta [in] Current time delta
  268. */
  269. static void jent_apt_insert(struct rand_data *ec, uint64_t current_delta)
  270. {
  271. /* Initialize the base reference */
  272. if (!ec->apt_base_set) {
  273. ec->apt_base = current_delta; /* APT Step 1 */
  274. ec->apt_base_set = 1; /* APT Step 2 */
  275. /*
  276. * Reset APT counter
  277. * Note that we've taken in the first symbol in the window.
  278. */
  279. ec->apt_count = 1; /* B = 1 */
  280. ec->apt_observations = 1;
  281. return;
  282. }
  283. if (current_delta == ec->apt_base) {
  284. ec->apt_count++; /* B = B + 1 */
  285. /* Note, ec->apt_count starts with one. */
  286. if (ec->apt_count >= ec->apt_cutoff)
  287. ec->health_failure |= JENT_APT_FAILURE;
  288. }
  289. ec->apt_observations++;
  290. /* Completed one window, the next symbol input will be new apt_base. */
  291. if (ec->apt_observations >= JENT_APT_WINDOW_SIZE)
  292. jent_apt_reset(ec); /* APT Step 4 */
  293. }
  294. /***************************************************************************
  295. * Stuck Test and its use as Repetition Count Test
  296. *
  297. * The Jitter RNG uses an enhanced version of the Repetition Count Test
  298. * (RCT) specified in SP800-90B section 4.4.1. Instead of counting identical
  299. * back-to-back values, the input to the RCT is the counting of the stuck
  300. * values during the generation of one Jitter RNG output block.
  301. *
  302. * The RCT is applied with an alpha of 2^{-30} compliant to FIPS 140-2 IG 9.8.
  303. *
  304. * During the counting operation, the Jitter RNG always calculates the RCT
  305. * cut-off value of C. If that value exceeds the allowed cut-off value,
  306. * the Jitter RNG output block will be calculated completely but discarded at
  307. * the end. The caller of the Jitter RNG is informed with an error code.
  308. ***************************************************************************/
  309. /**
  310. * Repetition Count Test as defined in SP800-90B section 4.4.1
  311. *
  312. * @ec [in] Reference to entropy collector
  313. * @stuck [in] Indicator whether the value is stuck
  314. */
  315. static void jent_rct_insert(struct rand_data *ec, int stuck)
  316. {
  317. /*
  318. * If we have a count less than zero, a previous RCT round identified
  319. * a failure. We will not overwrite it.
  320. */
  321. if (ec->rct_count < 0)
  322. return;
  323. if (stuck) {
  324. ec->rct_count++;
  325. /*
  326. * The cutoff value is based on the following consideration:
  327. * alpha = 2^-30 as recommended in FIPS 140-2 IG 9.8.
  328. * In addition, we require an entropy value H of 1/osr as this
  329. * is the minimum entropy required to provide full entropy.
  330. * Note, we collect (DATA_SIZE_BITS + ENTROPY_SAFETY_FACTOR)*osr
  331. * deltas for inserting them into the entropy pool which should
  332. * then have (close to) DATA_SIZE_BITS bits of entropy in the
  333. * conditioned output.
  334. *
  335. * Note, ec->rct_count (which equals to value B in the pseudo
  336. * code of SP800-90B section 4.4.1) starts with zero. Hence
  337. * we need to subtract one from the cutoff value as calculated
  338. * following SP800-90B. Thus C = ceil(-log_2(alpha)/H) = 30*osr.
  339. */
  340. if ((unsigned int)ec->rct_count >= (30 * ec->osr)) {
  341. ec->rct_count = -1;
  342. ec->health_failure |= JENT_RCT_FAILURE;
  343. }
  344. } else {
  345. ec->rct_count = 0;
  346. }
  347. }
  348. /**
  349. * Stuck test by checking the:
  350. * 1st derivative of the jitter measurement (time delta)
  351. * 2nd derivative of the jitter measurement (delta of time deltas)
  352. * 3rd derivative of the jitter measurement (delta of delta of time deltas)
  353. *
  354. * All values must always be non-zero.
  355. *
  356. * @ec [in] Reference to entropy collector
  357. * @current_delta [in] Jitter time delta
  358. *
  359. * @return
  360. * 0 jitter measurement not stuck (good bit)
  361. * 1 jitter measurement stuck (reject bit)
  362. */
  363. unsigned int jent_stuck(struct rand_data *ec, uint64_t current_delta)
  364. {
  365. uint64_t delta2 = jent_delta2(ec, current_delta);
  366. uint64_t delta3 = jent_delta3(ec, delta2);
  367. /*
  368. * Insert the result of the comparison of two back-to-back time
  369. * deltas.
  370. */
  371. jent_apt_insert(ec, current_delta);
  372. jent_lag_insert(ec, current_delta);
  373. if (!current_delta || !delta2 || !delta3) {
  374. /* RCT with a stuck bit */
  375. jent_rct_insert(ec, 1);
  376. return 1;
  377. }
  378. /* RCT with a non-stuck bit */
  379. jent_rct_insert(ec, 0);
  380. return 0;
  381. }
  382. /**
  383. * Report any health test failures
  384. *
  385. * @ec [in] Reference to entropy collector
  386. *
  387. * @return a bitmask indicating which tests failed
  388. * 0 No health test failure
  389. * 1 RCT failure
  390. * 2 APT failure
  391. * 4 Lag predictor test failure
  392. */
  393. unsigned int jent_health_failure(struct rand_data *ec)
  394. {
  395. /* Test is only enabled in FIPS mode */
  396. if (!ec->fips_enabled)
  397. return 0;
  398. if (fips_cb && ec->health_failure) {
  399. fips_cb(ec, ec->health_failure);
  400. }
  401. return ec->health_failure;
  402. }