Software APIs
csrng_fuse_en_sw_app_read.c
1 // Copyright lowRISC contributors (OpenTitan project).
2 // Licensed under the Apache License, Version 2.0, see LICENSE for details.
3 // SPDX-License-Identifier: Apache-2.0
4 
11 #include "sw/device/lib/testing/csrng_testutils.h"
12 #include "sw/device/lib/testing/otp_ctrl_testutils.h"
13 #include "sw/device/lib/testing/rstmgr_testutils.h"
14 #include "sw/device/lib/testing/test_framework/check.h"
16 
17 #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" // Generated.
18 #include "otp_ctrl_regs.h" // Generated
19 
20 OTTF_DEFINE_TEST_CONFIG();
21 
22 /**
23  * OTP HW partition relative IFETCH offset in bytes.
24  */
25 static const uint32_t kOtpIfetchHwRelativeOffset =
26  OTP_CTRL_PARAM_EN_SRAM_IFETCH_OFFSET - OTP_CTRL_PARAM_HW_CFG1_OFFSET;
27 
28 /**
29  * OTP can only be accessed by 32b aligned addresses. As `csrng_sw_app_read` is
30  * not aligned, we read from the previous aligned address and use the following
31  * offset in bits to access the `csrng_sw_app_read` byte.
32  */
33 static const uint32_t kOtpCsrngFwReadBitOffset =
34  (OTP_CTRL_PARAM_EN_CSRNG_SW_APP_READ_OFFSET -
35  OTP_CTRL_PARAM_EN_SRAM_IFETCH_OFFSET) *
36  8;
37 
38 /**
39  * CTR DRBG Known-Answer-Test (KAT) for GENERATE command.
40  */
41 static void test_fuse_enable(const dif_csrng_t *csrng) {
42  CHECK_STATUS_OK(
43  csrng_testutils_fips_instantiate_kat(csrng, /*fail_expected=*/false));
44  CHECK_STATUS_OK(csrng_testutils_fips_generate_kat(csrng));
45 }
46 
47 /**
48  * Check that the internal states will read zero.
49  */
50 static void test_fuse_disable(const dif_csrng_t *csrng) {
51  LOG_INFO("%s", __func__);
52  CHECK_STATUS_OK(
53  csrng_testutils_fips_instantiate_kat(csrng, /*fail_expected=*/true));
54 }
55 
56 /**
57  * Read the otp at `HW_CFG1.OTP_CTRL_PARAM_EN_CSRNG_SW_APP_READ_OFFSET` address
58  * and check whether is configured by the `uvm_test_seq` as expected.
59  *
60  * @param expected Define the expected value for the
61  * HW_CFG.EN_ENTROPY_SRC_FW_READ flag.
62  */
63 static void check_csrng_fuse_enabled(bool expected) {
64  dif_otp_ctrl_t otp;
65  CHECK_DIF_OK(dif_otp_ctrl_init(
67 
68  dif_otp_ctrl_config_t config = {
69  .check_timeout = 100000,
70  .integrity_period_mask = 0x3ffff,
71  .consistency_period_mask = 0x3ffffff,
72  };
73  CHECK_DIF_OK(dif_otp_ctrl_configure(&otp, config));
74  CHECK_STATUS_OK(otp_ctrl_testutils_wait_for_dai(&otp));
75 
76  uint32_t value;
77  // Read the current value of the partition.
79  kOtpIfetchHwRelativeOffset));
80  CHECK_STATUS_OK(otp_ctrl_testutils_wait_for_dai(&otp));
81  CHECK_DIF_OK(dif_otp_ctrl_dai_read32_end(&otp, &value));
82  multi_bit_bool_t enable = bitfield_field32_read(
83  value,
84  (bitfield_field32_t){.mask = 0xff, .index = kOtpCsrngFwReadBitOffset});
85  CHECK((enable == kMultiBitBool8True) == expected,
86  "`fw_enable` not expected (%x)", enable);
87 }
88 
89 /**
90  * This test takes the following steps:
91  *
92  * - Initialize the OTP with `HW_CFG.OTP_CTRL_PARAM_EN_CSRNG_SW_APP_READ_OFFSET`
93  * fuse bit set to enabled in the `uvm_test_seq`.
94  * - Issue an instantiate command to request entropy.
95  * - Verify that SW can read the internal states.
96  * - Reset the chip and repeat the steps above, but this time, with
97  * `HW_CFG.OTP_CTRL_PARAM_EN_CSRNG_SW_APP_READ_OFFSET` fuse bit set to 0.
98  * - Verify that the SW reads back all zeros when reading the internal states.
99  */
100 bool test_main(void) {
101  dif_csrng_t csrng;
102  CHECK_DIF_OK(dif_csrng_init(
104  CHECK_DIF_OK(dif_csrng_configure(&csrng));
105 
106  dif_rstmgr_t rstmgr;
108  CHECK_DIF_OK(dif_rstmgr_init(
110  info = rstmgr_testutils_reason_get();
111 
112  if (info == kDifRstmgrResetInfoPor) {
113  LOG_INFO("Powered up for the first time");
114  check_csrng_fuse_enabled(true);
115  test_fuse_enable(&csrng);
116 
117  // Reboot device.
118  rstmgr_testutils_reason_clear();
119  CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
120  // This log message is extremely important for the test, as the
121  // `uvm_test_seq` uses it to change the otp values.
122  LOG_INFO("Software resetting!");
123  // Wait here until device reset.
125  } else if (info == kDifRstmgrResetInfoSw) {
126  LOG_INFO("Powered up for the second time");
127 
128  check_csrng_fuse_enabled(false);
129  test_fuse_disable(&csrng);
130  return true;
131  }
132  return false;
133 }