|
36 | 36 | kEntropyCsrngBitsBufferNumWords = 4, |
37 | 37 |
|
38 | 38 | // Fast timeout for checking if hardware is ready to accept a command word |
39 | | - kEntropyPollReadyTimeout = 100, |
| 39 | + kEntropyPollReadyTimeout = 1000000, |
40 | 40 | // Longer timeout for waiting for a command to finish executing |
41 | 41 | kEntropyPollCmdDoneTimeout = 1000000, |
42 | 42 | // Timeout for waiting for GenBits to become valid |
@@ -228,80 +228,82 @@ typedef struct entropy_complex_config { |
228 | 228 | static const entropy_complex_config_t |
229 | 229 | kEntropyComplexConfigs[kEntropyComplexConfigIdNumEntries] = { |
230 | 230 | [kEntropyComplexConfigIdContinuous] = |
231 | | - { |
232 | | - .entropy_src = |
233 | | - { |
234 | | - .fips_enable = kMultiBitBool4True, |
235 | | - .fips_flag = kMultiBitBool4True, |
236 | | - .rng_fips = kMultiBitBool4True, |
237 | | - .route_to_firmware = kMultiBitBool4False, |
238 | | - .bypass_conditioner = kMultiBitBool4False, |
239 | | - .single_bit_mode = kMultiBitBool4False, |
240 | | - .fips_test_window_size = 0x200, |
241 | | - .alert_threshold = 2, |
242 | | - // TODO(#19392): Figure out appropriate thresholds. |
243 | | - .repcnt_threshold = 0xffff, |
244 | | - .repcnts_threshold = 0xffff, |
245 | | - .adaptp_hi_threshold = 0xffff, |
246 | | - .adaptp_lo_threshold = 0x0, |
247 | | - .bucket_threshold = 0xffff, |
248 | | - .markov_hi_threshold = 0xffff, |
249 | | - .markov_lo_threshold = 0x0, |
250 | | - .extht_hi_threshold = 0xffff, |
251 | | - .extht_lo_threshold = 0x0, |
252 | | - }, |
253 | | - .edn0 = |
254 | | - { |
255 | | - .base_address = kBaseEdn0, |
256 | | - .reseed_interval = 128, |
257 | | - .instantiate = |
258 | | - { |
259 | | - .id = kEntropyDrbgOpInstantiate, |
260 | | - .disable_trng_input = kHardenedBoolFalse, |
261 | | - .seed_material = NULL, |
262 | | - .generate_len = 0, |
263 | | - }, |
264 | | - .generate = |
265 | | - { |
266 | | - .id = kEntropyDrbgOpGenerate, |
267 | | - .disable_trng_input = kHardenedBoolFalse, |
268 | | - .seed_material = NULL, |
269 | | - .generate_len = 32, |
270 | | - }, |
271 | | - .reseed = |
272 | | - { |
273 | | - .id = kEntropyDrbgOpReseed, |
274 | | - .disable_trng_input = kHardenedBoolFalse, |
275 | | - .seed_material = NULL, |
276 | | - .generate_len = 0, |
277 | | - }, |
278 | | - }, |
279 | | - .edn1 = |
280 | | - { |
281 | | - .base_address = kBaseEdn1, |
282 | | - .reseed_interval = 4, |
283 | | - .instantiate = |
284 | | - { |
285 | | - .id = kEntropyDrbgOpInstantiate, |
286 | | - .disable_trng_input = kHardenedBoolFalse, |
287 | | - .seed_material = NULL, |
288 | | - .generate_len = 0, |
289 | | - }, |
290 | | - .generate = |
291 | | - { |
292 | | - .id = kEntropyDrbgOpGenerate, |
293 | | - .seed_material = NULL, |
294 | | - .generate_len = 4, |
295 | | - }, |
296 | | - .reseed = |
297 | | - { |
298 | | - .id = kEntropyDrbgOpReseed, |
299 | | - .disable_trng_input = kHardenedBoolFalse, |
300 | | - .seed_material = NULL, |
301 | | - .generate_len = 0, |
302 | | - }, |
303 | | - }, |
304 | | - }, |
| 231 | + // All cut off values are calculated with the assumption that: |
| 232 | + // H=0.5 per bit => H=2 for 4-bit symbols |
| 233 | + // α = 2⁻⁴⁰ (alpha = 2^-40), false positive probability |
| 234 | + { |
| 235 | + .entropy_src = |
| 236 | + { |
| 237 | + .fips_enable = kMultiBitBool4True, |
| 238 | + .fips_flag = kMultiBitBool4True, |
| 239 | + .rng_fips = kMultiBitBool4True, |
| 240 | + .route_to_firmware = kMultiBitBool4False, |
| 241 | + .bypass_conditioner = kMultiBitBool4False, |
| 242 | + .single_bit_mode = kMultiBitBool4False, |
| 243 | + .fips_test_window_size = 2048, |
| 244 | + .alert_threshold = 4, |
| 245 | + .repcnt_threshold = 81, |
| 246 | + .repcnts_threshold = 21, |
| 247 | + .adaptp_hi_threshold = 1591, |
| 248 | + .adaptp_lo_threshold = 2048 - 1591, // 457 |
| 249 | + .bucket_threshold = 201, |
| 250 | + .markov_hi_threshold = 824, |
| 251 | + .markov_lo_threshold = 1024 - 824, // 200 |
| 252 | + .extht_hi_threshold = 0xffff, |
| 253 | + .extht_lo_threshold = 0x0, |
| 254 | + }, |
| 255 | + .edn0 = |
| 256 | + { |
| 257 | + .base_address = kBaseEdn0, |
| 258 | + .reseed_interval = 128, |
| 259 | + .instantiate = |
| 260 | + { |
| 261 | + .id = kEntropyDrbgOpInstantiate, |
| 262 | + .disable_trng_input = kHardenedBoolFalse, |
| 263 | + .seed_material = NULL, |
| 264 | + .generate_len = 0, |
| 265 | + }, |
| 266 | + .generate = |
| 267 | + { |
| 268 | + .id = kEntropyDrbgOpGenerate, |
| 269 | + .disable_trng_input = kHardenedBoolFalse, |
| 270 | + .seed_material = NULL, |
| 271 | + .generate_len = 32, |
| 272 | + }, |
| 273 | + .reseed = |
| 274 | + { |
| 275 | + .id = kEntropyDrbgOpReseed, |
| 276 | + .disable_trng_input = kHardenedBoolFalse, |
| 277 | + .seed_material = NULL, |
| 278 | + .generate_len = 0, |
| 279 | + }, |
| 280 | + }, |
| 281 | + .edn1 = |
| 282 | + { |
| 283 | + .base_address = kBaseEdn1, |
| 284 | + .reseed_interval = 4, |
| 285 | + .instantiate = |
| 286 | + { |
| 287 | + .id = kEntropyDrbgOpInstantiate, |
| 288 | + .disable_trng_input = kHardenedBoolFalse, |
| 289 | + .seed_material = NULL, |
| 290 | + .generate_len = 0, |
| 291 | + }, |
| 292 | + .generate = |
| 293 | + { |
| 294 | + .id = kEntropyDrbgOpGenerate, |
| 295 | + .seed_material = NULL, |
| 296 | + .generate_len = 4, |
| 297 | + }, |
| 298 | + .reseed = |
| 299 | + { |
| 300 | + .id = kEntropyDrbgOpReseed, |
| 301 | + .disable_trng_input = kHardenedBoolFalse, |
| 302 | + .seed_material = NULL, |
| 303 | + .generate_len = 0, |
| 304 | + }, |
| 305 | + }, |
| 306 | + }, |
305 | 307 | }; |
306 | 308 |
|
307 | 309 | // Write a CSRNG command to a register. That register can be the SW interface |
@@ -464,9 +466,7 @@ static status_t csrng_send_app_cmd(uint32_t base_address, |
464 | 466 | // The non-Generate commands complete earlier, so poll the "command |
465 | 467 | // request done" interrupt bit. Once it is set, the "status" bit is |
466 | 468 | // updated. |
467 | | - uint32_t timeout = (cmd.id == kEntropyDrbgOpInstantiate) |
468 | | - ? kEntropyPollCmdDoneTimeout |
469 | | - : kEntropyPollReadyTimeout; |
| 469 | + uint32_t timeout = kEntropyPollCmdDoneTimeout; |
470 | 470 | do { |
471 | 471 | reg = abs_mmio_read32(kBaseCsrng + CSRNG_INTR_STATE_REG_OFFSET); |
472 | 472 | } while ( |
@@ -668,19 +668,19 @@ static void entropy_complex_stop_all(void) { |
668 | 668 | /** |
669 | 669 | * Set the value of an entropy_src threshold register. |
670 | 670 | * |
671 | | - * Only sets the FIPS threshold value, not the bypass threshold field; for the |
672 | | - * bypass threshold we use the reset value, which is ignored if looser than the |
673 | | - * thresholds already set. |
| 671 | + * Sets both the FIPS and BYPASS threshold fields to the same value. |
674 | 672 | * |
675 | 673 | * @param name Name of register (e.g. REPCNT, BUCKET). |
676 | | - * @param value Value to set for the FIPS_THRESH field. |
| 674 | + * @param value Value to set for the FIPS_THRESH and BYPASS_THRESH fields. |
677 | 675 | */ |
678 | | -#define SET_FIPS_THRESH(name, value) \ |
679 | | - abs_mmio_write32( \ |
680 | | - kBaseEntropySrc + ENTROPY_SRC_##name##_THRESHOLDS_REG_OFFSET, \ |
681 | | - bitfield_field32_write( \ |
682 | | - ENTROPY_SRC_##name##_THRESHOLDS_REG_RESVAL, \ |
683 | | - ENTROPY_SRC_##name##_THRESHOLDS_FIPS_THRESH_FIELD, value)); |
| 676 | +#define SET_FIPS_THRESH(name, value) \ |
| 677 | + abs_mmio_write32( \ |
| 678 | + kBaseEntropySrc + ENTROPY_SRC_##name##_THRESHOLDS_REG_OFFSET, \ |
| 679 | + bitfield_field32_write( \ |
| 680 | + bitfield_field32_write( \ |
| 681 | + ENTROPY_SRC_##name##_THRESHOLDS_REG_RESVAL, \ |
| 682 | + ENTROPY_SRC_##name##_THRESHOLDS_FIPS_THRESH_FIELD, value), \ |
| 683 | + ENTROPY_SRC_##name##_THRESHOLDS_BYPASS_THRESH_FIELD, value)); |
684 | 684 |
|
685 | 685 | /** |
686 | 686 | * Configures the entropy_src with based on `config` options. |
@@ -727,6 +727,10 @@ static status_t entropy_src_configure(const entropy_src_config_t *config) { |
727 | 727 | bitfield_field32_write(ENTROPY_SRC_HEALTH_TEST_WINDOWS_REG_RESVAL, |
728 | 728 | ENTROPY_SRC_HEALTH_TEST_WINDOWS_FIPS_WINDOW_FIELD, |
729 | 729 | config->fips_test_window_size); |
| 730 | + health_test_windows = bitfield_field32_write( |
| 731 | + health_test_windows, ENTROPY_SRC_HEALTH_TEST_WINDOWS_BYPASS_WINDOW_FIELD, |
| 732 | + 0x60); |
| 733 | + |
730 | 734 | abs_mmio_write32(kBaseEntropySrc + ENTROPY_SRC_HEALTH_TEST_WINDOWS_REG_OFFSET, |
731 | 735 | health_test_windows); |
732 | 736 |
|
@@ -777,18 +781,20 @@ static status_t entropy_src_configure(const entropy_src_config_t *config) { |
777 | 781 | /** |
778 | 782 | * Verify the value of an entropy_src threshold register. |
779 | 783 | * |
780 | | - * Only checks the FIPS threshold value, not the bypass threshold field. |
| 784 | + * Checks both the FIPS and BYPASS threshold values. |
781 | 785 | * |
782 | 786 | * @param name Name of register (e.g. REPCNT, BUCKET). |
783 | | - * @param exp Expected value of the FIPS_THRESH field. |
| 787 | + * @param exp Expected value of the FIPS_THRESH and BYPASS_THRESH fields. |
784 | 788 | */ |
785 | 789 | #define VERIFY_FIPS_THRESH(name, exp) \ |
786 | 790 | do { \ |
787 | 791 | uint32_t reg = abs_mmio_read32( \ |
788 | 792 | kBaseEntropySrc + ENTROPY_SRC_##name##_THRESHOLDS_REG_OFFSET); \ |
789 | | - uint32_t act = bitfield_field32_read( \ |
| 793 | + uint32_t act_fips = bitfield_field32_read( \ |
790 | 794 | reg, ENTROPY_SRC_##name##_THRESHOLDS_FIPS_THRESH_FIELD); \ |
791 | | - if (act != exp) { \ |
| 795 | + uint32_t act_bypass = bitfield_field32_read( \ |
| 796 | + reg, ENTROPY_SRC_##name##_THRESHOLDS_BYPASS_THRESH_FIELD); \ |
| 797 | + if (act_fips != exp || act_bypass != exp) { \ |
792 | 798 | return OTCRYPTO_RECOV_ERR; \ |
793 | 799 | } \ |
794 | 800 | } while (false); |
@@ -847,12 +853,16 @@ static status_t entropy_src_check(const entropy_src_config_t *config) { |
847 | 853 | return OTCRYPTO_RECOV_ERR; |
848 | 854 | } |
849 | 855 |
|
850 | | - // Check health test window register. |
| 856 | + // Check health test window register for fips and bypass. |
851 | 857 | reg = abs_mmio_read32(kBaseEntropySrc + |
852 | 858 | ENTROPY_SRC_HEALTH_TEST_WINDOWS_REG_OFFSET); |
853 | | - if (bitfield_field32_read( |
854 | | - reg, ENTROPY_SRC_HEALTH_TEST_WINDOWS_FIPS_WINDOW_FIELD) != |
855 | | - config->fips_test_window_size) { |
| 859 | + uint32_t act_fips_window = bitfield_field32_read( |
| 860 | + reg, ENTROPY_SRC_HEALTH_TEST_WINDOWS_FIPS_WINDOW_FIELD); |
| 861 | + uint32_t act_bypass_window = bitfield_field32_read( |
| 862 | + reg, ENTROPY_SRC_HEALTH_TEST_WINDOWS_BYPASS_WINDOW_FIELD); |
| 863 | + |
| 864 | + if (act_fips_window != config->fips_test_window_size || |
| 865 | + act_bypass_window != 0x60) { |
856 | 866 | return OTCRYPTO_RECOV_ERR; |
857 | 867 | } |
858 | 868 |
|
|
0 commit comments