Software APIs
rnd_unittest.cc
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 #include "sw/device/silicon_creator/lib/drivers/rnd.h"
5 
6 #include <utility>
7 #include <vector>
8 
9 #include "gtest/gtest.h"
10 #include "sw/device/lib/base/csr.h"
11 #include "sw/device/lib/base/mock_abs_mmio.h"
12 #include "sw/device/lib/base/mock_crc32.h"
13 #include "sw/device/silicon_creator/lib/base/mock_csr.h"
14 #include "sw/device/silicon_creator/lib/base/mock_sec_mmio.h"
15 #include "sw/device/silicon_creator/lib/drivers/mock_otp.h"
16 #include "sw/device/silicon_creator/testing/rom_test.h"
17 
18 #include "entropy_src_regs.h"
20 #include "otp_ctrl_regs.h"
21 #include "rv_core_ibex_regs.h"
22 
23 namespace rnd_unittest {
24 namespace {
25 using ::testing::NotNull;
26 using ::testing::Return;
27 
28 class RndTest : public rom_test::RomTest {
29  protected:
30  uint32_t base_rv_ = TOP_EARLGREY_RV_CORE_IBEX_CFG_BASE_ADDR;
31  uint32_t base_es_ = TOP_EARLGREY_ENTROPY_SRC_BASE_ADDR;
32 
33  rom_test::MockCrc32 crc32_;
34  rom_test::MockAbsMmio mmio_;
35  rom_test::MockSecMmio sec_mmio_;
36  rom_test::MockOtp otp_;
37  mock_csr::MockCsr csr_;
38 };
39 
40 TEST_F(RndTest, GetUint32Enabled) {
41  EXPECT_CALL(otp_, read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_RNG_EN_OFFSET))
42  .WillOnce(Return(kHardenedBoolTrue));
43 
44  EXPECT_ABS_READ32(base_rv_ + RV_CORE_IBEX_RND_STATUS_REG_OFFSET,
45  {{RV_CORE_IBEX_RND_STATUS_RND_DATA_VALID_BIT, false}});
46  EXPECT_ABS_READ32(base_rv_ + RV_CORE_IBEX_RND_STATUS_REG_OFFSET,
47  {{RV_CORE_IBEX_RND_STATUS_RND_DATA_VALID_BIT, true}});
48  EXPECT_CSR_READ(CSR_REG_MCYCLE, 67894);
49  EXPECT_ABS_READ32(base_rv_ + RV_CORE_IBEX_RND_DATA_REG_OFFSET, 12345);
50  EXPECT_EQ(rnd_uint32(), 67894 + 12345);
51 }
52 
53 TEST_F(RndTest, GetUint32Disabled) {
54  EXPECT_CALL(otp_, read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_RNG_EN_OFFSET))
55  .WillOnce(Return(kHardenedBoolFalse));
56 
57  EXPECT_CSR_READ(CSR_REG_MCYCLE, 978465);
58  EXPECT_ABS_READ32(base_rv_ + RV_CORE_IBEX_RND_DATA_REG_OFFSET, 193475837);
59  EXPECT_EQ(rnd_uint32(), 978465 + 193475837);
60 }
61 
63  lifecycle_state_t lc_state;
64  bool expect_error_ok;
65  bool mismatch_crc_vals;
66 };
67 
68 class RndtLcStateTest : public RndTest,
69  public testing::WithParamInterface<RndtLcStateTestCfg> {
70  protected:
71  void ExpectHealthCfgCrcCheck(lifecycle_state_t lc_state,
72  uint32_t expected_crc, uint32_t otp_crc) {
73  std::vector<std::pair<uint32_t, uint32_t>> regs = {
74  {ENTROPY_SRC_REPCNT_THRESHOLDS_REG_OFFSET, 0xffffffff},
75  {ENTROPY_SRC_REPCNTS_THRESHOLDS_REG_OFFSET, 0xffffffff},
76  {ENTROPY_SRC_ADAPTP_HI_THRESHOLDS_REG_OFFSET, 0xffffffff},
77  {ENTROPY_SRC_ADAPTP_LO_THRESHOLDS_REG_OFFSET, 0x0},
78  {ENTROPY_SRC_BUCKET_THRESHOLDS_REG_OFFSET, 0xffffffff},
79  {ENTROPY_SRC_MARKOV_HI_THRESHOLDS_REG_OFFSET, 0xffffffff},
80  {ENTROPY_SRC_MARKOV_LO_THRESHOLDS_REG_OFFSET, 0x0},
81  {ENTROPY_SRC_EXTHT_HI_THRESHOLDS_REG_OFFSET, 0xffffffff},
82  {ENTROPY_SRC_EXTHT_LO_THRESHOLDS_REG_OFFSET, 0x0},
83  {ENTROPY_SRC_ALERT_THRESHOLD_REG_OFFSET, 0xfffd0002},
84  };
85  EXPECT_CALL(crc32_, Init(NotNull()));
86  for (auto reg : regs) {
87  EXPECT_ABS_READ32(base_es_ + reg.first, reg.second);
88  EXPECT_CALL(crc32_, Add32(NotNull(), reg.second));
89  }
90  EXPECT_CALL(crc32_, Finish(NotNull())).WillOnce(Return(expected_crc));
91 
92  // The implementation does not check the OTP value for the following lc
93  // state. See implementation for `rnd_health_config_check()`.
94  if (lc_state == kLcStateTest) {
95  return;
96  }
97 
98  EXPECT_CALL(
99  otp_,
100  read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_RNG_HEALTH_CONFIG_DIGEST_OFFSET))
101  .WillOnce(Return(otp_crc));
102  }
103 };
104 
105 TEST_P(RndtLcStateTest, HealthCfgCrcEnabled) {
106  EXPECT_CALL(otp_, read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_RNG_EN_OFFSET))
107  .WillOnce(Return(kHardenedBoolTrue));
108 
109  enum {
110  kExpectedCrcValOk = 0x8264cf75,
111  kExpectedCrcValOkOtp = kExpectedCrcValOk ^ kErrorOk,
112  };
113  ExpectHealthCfgCrcCheck(
114  GetParam().lc_state, kExpectedCrcValOk,
115  GetParam().mismatch_crc_vals ? 0 : kExpectedCrcValOkOtp);
116  rom_error_t got = rnd_health_config_check(GetParam().lc_state);
117  if (GetParam().expect_error_ok) {
118  EXPECT_EQ(got, kErrorOk);
119  } else {
120  EXPECT_NE(got, kErrorOk);
121  }
122 }
123 
124 TEST_P(RndtLcStateTest, HealthCfgCrcDisabled) {
125  EXPECT_CALL(otp_, read32(OTP_CTRL_PARAM_CREATOR_SW_CFG_RNG_EN_OFFSET))
126  .WillOnce(Return(kHardenedBoolFalse));
127 
128  EXPECT_EQ(rnd_health_config_check(GetParam().lc_state), kErrorOk);
129 }
130 
131 INSTANTIATE_TEST_SUITE_P(NonTestLcStates, RndtLcStateTest,
132  testing::Values(
133  RndtLcStateTestCfg{
134  .lc_state = kLcStateTest,
135  .expect_error_ok = true,
136  .mismatch_crc_vals = false,
137  },
138  RndtLcStateTestCfg{
139  .lc_state = kLcStateTest,
140  .expect_error_ok = true,
141  .mismatch_crc_vals = true,
142  },
143  RndtLcStateTestCfg{
144  .lc_state = kLcStateDev,
145  .expect_error_ok = true,
146  .mismatch_crc_vals = false,
147  },
148  RndtLcStateTestCfg{
149  .lc_state = kLcStateDev,
150  .expect_error_ok = false,
151  .mismatch_crc_vals = true,
152  },
153  RndtLcStateTestCfg{
154  .lc_state = kLcStateProd,
155  .expect_error_ok = true,
156  .mismatch_crc_vals = false,
157  },
158  RndtLcStateTestCfg{
159  .lc_state = kLcStateProd,
160  .expect_error_ok = false,
161  .mismatch_crc_vals = true,
162  },
163  RndtLcStateTestCfg{
164  .lc_state = kLcStateProdEnd,
165  .expect_error_ok = true,
166  .mismatch_crc_vals = false,
167  },
168  RndtLcStateTestCfg{
169  .lc_state = kLcStateProdEnd,
170  .expect_error_ok = false,
171  .mismatch_crc_vals = true,
172  },
173  RndtLcStateTestCfg{
174  .lc_state = kLcStateRma,
175  .expect_error_ok = true,
176  .mismatch_crc_vals = false,
177  },
178  RndtLcStateTestCfg{
179  .lc_state = kLcStateRma,
180  .expect_error_ok = false,
181  .mismatch_crc_vals = true,
182  }));
183 
184 } // namespace
185 } // namespace rnd_unittest