5 #include "sw/device/lib/crypto/drivers/entropy.h"
11 #include "sw/device/lib/base/multibits.h"
12 #include "sw/device/lib/crypto/impl/status.h"
14 #include "csrng_regs.h"
16 #include "entropy_src_regs.h"
20 #define MODULE_ID MAKE_MODULE_ID('d', 'e', 'n')
36 kEntropyCsrngBitsBufferNumWords = 4,
45 typedef enum entropy_csrng_op {
46 kEntropyDrbgOpInstantiate = 1,
47 kEntropyDrbgOpReseed = 2,
48 kEntropyDrbgOpGenerate = 3,
49 kEntropyDrbgOpUpdate = 4,
50 kEntropyDrbgOpUninstantiate = 5,
60 entropy_csrng_op_t
id;
79 typedef enum entropy_complex_config_id {
84 kEntropyComplexConfigIdContinuous,
85 kEntropyComplexConfigIdNumEntries,
86 } entropy_complex_config_id_t;
202 entropy_complex_config_id_t
id;
222 kEntropyComplexConfigs[kEntropyComplexConfigIdNumEntries] = {
223 [kEntropyComplexConfigIdContinuous] =
228 .fips_flag = kMultiBitBool4True,
229 .rng_fips = kMultiBitBool4True,
230 .route_to_firmware = kMultiBitBool4False,
231 .bypass_conditioner = kMultiBitBool4False,
232 .single_bit_mode = kMultiBitBool4False,
233 .fips_test_window_size = 0x200,
234 .alert_threshold = 2,
236 .repcnt_threshold = 0xffff,
237 .repcnts_threshold = 0xffff,
238 .adaptp_hi_threshold = 0xffff,
239 .adaptp_lo_threshold = 0x0,
240 .bucket_threshold = 0xffff,
241 .markov_hi_threshold = 0xffff,
242 .markov_lo_threshold = 0x0,
243 .extht_hi_threshold = 0xffff,
244 .extht_lo_threshold = 0x0,
248 .base_address = kBaseEdn0,
249 .reseed_interval = 128,
252 .id = kEntropyDrbgOpInstantiate,
254 .seed_material = NULL,
259 .id = kEntropyDrbgOpGenerate,
261 .seed_material = NULL,
266 .id = kEntropyDrbgOpReseed,
268 .seed_material = NULL,
274 .base_address = kBaseEdn1,
275 .reseed_interval = 4,
278 .id = kEntropyDrbgOpInstantiate,
280 .seed_material = NULL,
285 .id = kEntropyDrbgOpGenerate,
286 .seed_material = NULL,
291 .id = kEntropyDrbgOpReseed,
293 .seed_material = NULL,
306 static status_t csrng_send_app_cmd(uint32_t base_address,
308 entropy_csrng_send_app_cmd_type_t cmd_type,
309 bool check_completion) {
314 kMaxGenerateSizeIn128BitBlocks = 0x800,
316 if (cmd.
generate_len > kMaxGenerateSizeIn128BitBlocks) {
317 return OTCRYPTO_BAD_ARGS;
320 uint32_t cmd_reg_addr;
321 uint32_t sts_reg_addr;
322 uint32_t rdy_bit_offset;
323 uint32_t reg_rdy_bit_offset;
328 case kEntropyCsrngSendAppCmdTypeCsrng:
329 cmd_reg_addr = base_address + CSRNG_CMD_REQ_REG_OFFSET;
330 sts_reg_addr = base_address + CSRNG_SW_CMD_STS_REG_OFFSET;
331 rdy_bit_offset = CSRNG_SW_CMD_STS_CMD_RDY_BIT;
332 reg_rdy_bit_offset = CSRNG_SW_CMD_STS_CMD_RDY_BIT;
334 case kEntropyCsrngSendAppCmdTypeEdnSw:
335 cmd_reg_addr = base_address + EDN_SW_CMD_REQ_REG_OFFSET;
336 sts_reg_addr = base_address + EDN_SW_CMD_STS_REG_OFFSET;
337 rdy_bit_offset = EDN_SW_CMD_STS_CMD_RDY_BIT;
338 reg_rdy_bit_offset = EDN_SW_CMD_STS_CMD_REG_RDY_BIT;
340 case kEntropyCsrngSendAppCmdTypeEdnGen:
341 cmd_reg_addr = base_address + EDN_GENERATE_CMD_REG_OFFSET;
343 case kEntropyCsrngSendAppCmdTypeEdnRes:
344 cmd_reg_addr = base_address + EDN_RESEED_CMD_REG_OFFSET;
347 return OTCRYPTO_BAD_ARGS;
350 if ((cmd_type == kEntropyCsrngSendAppCmdTypeCsrng) ||
351 (cmd_type == kEntropyCsrngSendAppCmdTypeEdnSw)) {
354 reg = abs_mmio_read32(sts_reg_addr);
359 #define ENTROPY_CMD(m, i) ((bitfield_field32_t){.mask = m, .index = i})
369 uint32_t cmd_len = cmd.seed_material == NULL ? 0 : cmd.seed_material->
len;
371 if (cmd_len & ~kAppCmdFieldCmdLen.
mask) {
372 return OTCRYPTO_RECOV_ERR;
379 if (cmd.seed_material != NULL &&
381 return OTCRYPTO_RECOV_ERR;
384 if (check_completion && (cmd_type == kEntropyCsrngSendAppCmdTypeCsrng)) {
390 abs_mmio_write32(kBaseCsrng + CSRNG_INTR_STATE_REG_OFFSET, reg);
403 abs_mmio_write32(cmd_reg_addr, reg);
405 for (
size_t i = 0; i < cmd_len; ++i) {
409 if (cmd_type == kEntropyCsrngSendAppCmdTypeCsrng ||
410 cmd_type == kEntropyCsrngSendAppCmdTypeEdnSw) {
412 reg = abs_mmio_read32(sts_reg_addr);
416 abs_mmio_write32(cmd_reg_addr, cmd.seed_material->
data[i]);
419 if (check_completion && (cmd_type == kEntropyCsrngSendAppCmdTypeCsrng)) {
420 if (cmd.
id == kEntropyDrbgOpGenerate) {
425 reg = abs_mmio_read32(kBaseCsrng + CSRNG_GENBITS_VLD_REG_OFFSET);
433 reg = abs_mmio_read32(kBaseCsrng + CSRNG_INTR_STATE_REG_OFFSET);
437 reg = abs_mmio_read32(kBaseCsrng + CSRNG_SW_CMD_STS_REG_OFFSET);
439 return OTCRYPTO_RECOV_ERR;
444 if (check_completion && (cmd_type == kEntropyCsrngSendAppCmdTypeEdnSw)) {
448 if (cmd.
id != kEntropyDrbgOpGenerate) {
450 reg = abs_mmio_read32(sts_reg_addr);
455 return OTCRYPTO_RECOV_ERR;
467 static void csrng_configure(
void) {
475 kMultiBitBool4False);
476 abs_mmio_write32(kBaseCsrng + CSRNG_CTRL_REG_OFFSET, reg);
487 static void edn_stop(uint32_t edn_address) {
490 uint32_t reg = abs_mmio_read32(edn_address + EDN_CTRL_REG_OFFSET);
491 abs_mmio_write32(edn_address + EDN_CTRL_REG_OFFSET,
493 kMultiBitBool4True));
497 abs_mmio_write32(edn_address + EDN_CTRL_REG_OFFSET, EDN_CTRL_REG_RESVAL);
507 static status_t edn_ready_block(uint32_t edn_address) {
510 reg = abs_mmio_read32(edn_address + EDN_SW_CMD_STS_REG_OFFSET);
514 return OTCRYPTO_RECOV_ERR;
528 kEntropyCsrngSendAppCmdTypeEdnRes,
false));
530 kEntropyCsrngSendAppCmdTypeEdnGen,
false));
532 config->
base_address + EDN_MAX_NUM_REQS_BETWEEN_RESEEDS_REG_OFFSET,
539 abs_mmio_write32(config->
base_address + EDN_CTRL_REG_OFFSET, reg);
543 kEntropyCsrngSendAppCmdTypeEdnSw,
true));
553 static void entropy_src_stop(
void) {
554 abs_mmio_write32(kBaseEntropySrc + ENTROPY_SRC_MODULE_ENABLE_REG_OFFSET,
555 ENTROPY_SRC_MODULE_ENABLE_REG_RESVAL);
559 abs_mmio_write32(kBaseEntropySrc + ENTROPY_SRC_ENTROPY_CONTROL_REG_OFFSET,
560 ENTROPY_SRC_ENTROPY_CONTROL_REG_RESVAL);
561 abs_mmio_write32(kBaseEntropySrc + ENTROPY_SRC_CONF_REG_OFFSET,
562 ENTROPY_SRC_CONF_REG_RESVAL);
563 abs_mmio_write32(kBaseEntropySrc + ENTROPY_SRC_HEALTH_TEST_WINDOWS_REG_OFFSET,
564 ENTROPY_SRC_HEALTH_TEST_WINDOWS_REG_RESVAL);
565 abs_mmio_write32(kBaseEntropySrc + ENTROPY_SRC_ALERT_THRESHOLD_REG_OFFSET,
566 ENTROPY_SRC_ALERT_THRESHOLD_REG_RESVAL);
584 static void entropy_complex_stop_all(
void) {
587 abs_mmio_write32(kBaseCsrng + CSRNG_CTRL_REG_OFFSET, CSRNG_CTRL_REG_RESVAL);
601 #define SET_FIPS_THRESH(name, value) \
603 kBaseEntropySrc + ENTROPY_SRC_##name##_THRESHOLDS_REG_OFFSET, \
604 bitfield_field32_write( \
605 ENTROPY_SRC_##name##_THRESHOLDS_REG_RESVAL, \
606 ENTROPY_SRC_##name##_THRESHOLDS_FIPS_THRESH_FIELD, value));
618 return OTCRYPTO_BAD_ARGS;
626 abs_mmio_write32(kBaseEntropySrc + ENTROPY_SRC_ENTROPY_CONTROL_REG_OFFSET,
637 ENTROPY_SRC_CONF_ENTROPY_DATA_REG_ENABLE_FIELD,
640 kMultiBitBool4False);
644 abs_mmio_write32(kBaseEntropySrc + ENTROPY_SRC_CONF_REG_OFFSET, reg);
648 kBaseEntropySrc + ENTROPY_SRC_HEALTH_TEST_WINDOWS_REG_OFFSET,
650 ENTROPY_SRC_HEALTH_TEST_WINDOWS_FIPS_WINDOW_FIELD,
655 0, ENTROPY_SRC_ALERT_THRESHOLD_ALERT_THRESHOLD_FIELD,
658 reg, ENTROPY_SRC_ALERT_THRESHOLD_ALERT_THRESHOLD_INV_FIELD,
660 abs_mmio_write32(kBaseEntropySrc + ENTROPY_SRC_ALERT_THRESHOLD_REG_OFFSET,
675 abs_mmio_write32(kBaseEntropySrc + ENTROPY_SRC_MODULE_ENABLE_REG_OFFSET,
690 #define VERIFY_FIPS_THRESH(name, exp) \
692 uint32_t reg = abs_mmio_read32( \
693 kBaseEntropySrc + ENTROPY_SRC_##name##_THRESHOLDS_REG_OFFSET); \
694 uint32_t act = bitfield_field32_read( \
695 reg, ENTROPY_SRC_##name##_THRESHOLDS_FIPS_THRESH_FIELD); \
697 return OTCRYPTO_RECOV_ERR; \
718 return OTCRYPTO_BAD_ARGS;
723 abs_mmio_read32(kBaseEntropySrc + ENTROPY_SRC_MODULE_ENABLE_REG_OFFSET);
724 if (reg != kMultiBitBool4True) {
725 return OTCRYPTO_RECOV_ERR;
735 reg = abs_mmio_read32(kBaseEntropySrc + ENTROPY_SRC_CONF_REG_OFFSET);
736 uint32_t conf_fips_enable =
738 uint32_t conf_rng_bit_enable =
740 if (conf_fips_enable != kMultiBitBool4True ||
741 conf_rng_bit_enable != kMultiBitBool4False) {
742 return OTCRYPTO_RECOV_ERR;
745 abs_mmio_read32(kBaseEntropySrc + ENTROPY_SRC_ENTROPY_CONTROL_REG_OFFSET);
746 uint32_t control_es_type =
748 uint32_t control_es_route =
750 if (control_es_type != kMultiBitBool4False ||
751 control_es_route != kMultiBitBool4False) {
752 return OTCRYPTO_RECOV_ERR;
756 reg = abs_mmio_read32(kBaseEntropySrc +
757 ENTROPY_SRC_HEALTH_TEST_WINDOWS_REG_OFFSET);
759 reg, ENTROPY_SRC_HEALTH_TEST_WINDOWS_FIPS_WINDOW_FIELD) !=
761 return OTCRYPTO_RECOV_ERR;
766 0, ENTROPY_SRC_ALERT_THRESHOLD_ALERT_THRESHOLD_FIELD,
769 exp_reg, ENTROPY_SRC_ALERT_THRESHOLD_ALERT_THRESHOLD_INV_FIELD,
771 if (exp_reg != abs_mmio_read32(kBaseEntropySrc +
772 ENTROPY_SRC_ALERT_THRESHOLD_REG_OFFSET)) {
773 return OTCRYPTO_RECOV_ERR;
801 uint32_t reg = abs_mmio_read32(kBaseCsrng + CSRNG_CTRL_REG_OFFSET);
803 if (enable == kMultiBitBool4True) {
806 return OTCRYPTO_RECOV_ERR;
820 uint32_t reg = abs_mmio_read32(config->
base_address + EDN_CTRL_REG_OFFSET);
822 uint32_t auto_req_mode =
824 if (edn_enable == kMultiBitBool4True && auto_req_mode == kMultiBitBool4True) {
827 return OTCRYPTO_RECOV_ERR;
830 status_t entropy_complex_init(
void) {
831 entropy_complex_stop_all();
834 &kEntropyComplexConfigs[kEntropyComplexConfigIdContinuous];
835 if (launder32(config->
id) != kEntropyComplexConfigIdContinuous) {
836 return OTCRYPTO_RECOV_ERR;
839 HARDENED_TRY(entropy_src_configure(&config->
entropy_src));
841 HARDENED_TRY(edn_configure(&config->
edn0));
842 return edn_configure(&config->
edn1);
845 status_t entropy_complex_check(
void) {
847 &kEntropyComplexConfigs[kEntropyComplexConfigIdContinuous];
848 if (launder32(config->
id) != kEntropyComplexConfigIdContinuous) {
849 return OTCRYPTO_RECOV_ERR;
852 HARDENED_TRY(entropy_src_check(&config->
entropy_src));
853 HARDENED_TRY(csrng_check());
854 HARDENED_TRY(edn_check(&config->
edn0));
855 return edn_check(&config->
edn1);
861 return csrng_send_app_cmd(kBaseCsrng,
863 .id = kEntropyDrbgOpInstantiate,
864 .disable_trng_input = disable_trng_input,
865 .seed_material = seed_material,
868 kEntropyCsrngSendAppCmdTypeCsrng,
true);
873 return csrng_send_app_cmd(kBaseCsrng,
875 .id = kEntropyDrbgOpReseed,
876 .disable_trng_input = disable_trng_input,
877 .seed_material = seed_material,
880 kEntropyCsrngSendAppCmdTypeCsrng,
true);
884 return csrng_send_app_cmd(kBaseCsrng,
886 .id = kEntropyDrbgOpUpdate,
887 .seed_material = seed_material,
890 kEntropyCsrngSendAppCmdTypeCsrng,
true);
893 status_t entropy_csrng_generate_start(
897 const uint32_t num_128bit_blocks =
ceil_div(len, 4);
898 return csrng_send_app_cmd(kBaseCsrng,
900 .id = kEntropyDrbgOpGenerate,
901 .seed_material = seed_material,
902 .generate_len = num_128bit_blocks,
904 kEntropyCsrngSendAppCmdTypeCsrng,
true);
907 status_t entropy_csrng_generate_data_get(uint32_t *buf,
size_t len,
909 static_assert(kEntropyCsrngBitsBufferNumWords == 4,
910 "kEntropyCsrngBitsBufferNumWords must be 4.");
913 for (
size_t block_idx = 0; block_idx < nblocks; ++block_idx) {
918 reg = abs_mmio_read32(kBaseCsrng + CSRNG_GENBITS_VLD_REG_OFFSET);
925 res = OTCRYPTO_RECOV_ERR;
931 for (
size_t offset = 0; offset < kEntropyCsrngBitsBufferNumWords;
933 uint32_t word = abs_mmio_read32(kBaseCsrng + CSRNG_GENBITS_REG_OFFSET);
934 size_t word_idx = (block_idx * kEntropyCsrngBitsBufferNumWords) +
935 kEntropyCsrngBitsBufferNumWords - 1 - offset;
936 if (word_idx < len) {
937 buf[word_idx] = word;
946 uint32_t *buf,
size_t len,
948 HARDENED_TRY(entropy_csrng_generate_start(seed_material, len));
949 return entropy_csrng_generate_data_get(buf, len, fips_check);
952 status_t entropy_csrng_uninstantiate(
void) {
953 return csrng_send_app_cmd(kBaseCsrng,
955 .id = kEntropyDrbgOpUninstantiate,
956 .seed_material = NULL,
959 kEntropyCsrngSendAppCmdTypeCsrng,
true);