Software APIs
boot_policy_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 
5 #include "sw/device/silicon_creator/rom/boot_policy.h"
6 
7 #include "gtest/gtest.h"
9 #include "sw/device/silicon_creator/lib/mock_manifest.h"
10 #include "sw/device/silicon_creator/lib/mock_shutdown.h"
11 #include "sw/device/silicon_creator/rom/mock_boot_policy_ptrs.h"
12 #include "sw/device/silicon_creator/testing/rom_test.h"
13 
14 namespace manifest_unittest {
15 namespace {
16 using ::testing::Return;
17 
19  protected:
20  rom_test::MockBootPolicyPtrs boot_policy_ptrs_;
21  rom_test::MockManifest mock_manifest_;
22 };
23 
25  uint32_t length;
26  rom_error_t result;
27 };
28 
30  : public BootPolicyTest,
31  public testing::WithParamInterface<ManifestLengthTestCase> {};
32 
33 TEST_P(ManifestCheckLengthTest, ManifestCheckLength) {
36  manifest.length = GetParam().length;
38 
39  if (GetParam().result == kErrorOk) {
40  EXPECT_CALL(mock_manifest_, Check(&manifest)).WillOnce(Return(kErrorOk));
41  }
42 
43  EXPECT_EQ(boot_policy_manifest_check(&manifest, &boot_data),
44  GetParam().result);
45 }
46 
47 INSTANTIATE_TEST_SUITE_P(
48  GoodLengths, ManifestCheckLengthTest,
49  testing::Values(
50  ManifestLengthTestCase{CHIP_ROM_EXT_SIZE_MIN, kErrorOk},
51  ManifestLengthTestCase{CHIP_ROM_EXT_SIZE_MAX >> 1, kErrorOk},
52  ManifestLengthTestCase{CHIP_ROM_EXT_SIZE_MAX, kErrorOk},
53  ManifestLengthTestCase{CHIP_ROM_EXT_RESIZABLE_SIZE_MAX, kErrorOk},
54  ManifestLengthTestCase{CHIP_ROM_EXT_SIZE_MIN - 1,
55  kErrorBootPolicyBadLength},
56  ManifestLengthTestCase{CHIP_ROM_EXT_RESIZABLE_SIZE_MAX + 1,
57  kErrorBootPolicyBadLength}));
58 
59 TEST_F(BootPolicyTest, ManifestCheckBadIdentifier) {
62 
63  EXPECT_EQ(boot_policy_manifest_check(&manifest, &boot_data),
64  kErrorBootPolicyBadIdentifier);
65 }
66 
67 TEST_F(BootPolicyTest, ManifestCheckBadManifest) {
70  manifest.length = CHIP_ROM_EXT_SIZE_MAX;
72 
73  EXPECT_CALL(mock_manifest_, Check(&manifest))
74  .WillOnce(Return(kErrorManifestBadEntryPoint));
75  EXPECT_EQ(boot_policy_manifest_check(&manifest, &boot_data),
76  kErrorManifestBadEntryPoint);
77 }
78 
79 TEST_F(BootPolicyTest, ManifestCheckRollback) {
82  manifest.length = CHIP_ROM_EXT_SIZE_MAX;
85 
86  EXPECT_CALL(mock_manifest_, Check(&manifest)).WillOnce(Return(kErrorOk));
87  EXPECT_EQ(boot_policy_manifest_check(&manifest, &boot_data),
88  kErrorBootPolicyRollback);
89 }
90 
91 struct Versions {
92  uint32_t security;
93  uint32_t major;
94  uint32_t minor;
95 };
96 
98  Versions version_a;
99  Versions version_b;
100  bool is_a_first;
101 };
102 
104  : public BootPolicyTest,
105  public testing::WithParamInterface<ManifestOrderTestCase> {};
106 
107 TEST_P(ManifestOrderTest, ManifestsGet) {
108  const ManifestOrderTestCase &param = GetParam();
109  manifest_t manifest_a{
110  .version_major = param.version_a.major,
111  .version_minor = param.version_a.minor,
112  .security_version = param.version_a.security,
113  };
114  manifest_t manifest_b{
115  .version_major = param.version_b.major,
116  .version_minor = param.version_b.minor,
117  .security_version = param.version_b.security,
118  };
119 
120  EXPECT_CALL(boot_policy_ptrs_, ManifestA).WillOnce(Return(&manifest_a));
121  EXPECT_CALL(boot_policy_ptrs_, ManifestB).WillOnce(Return(&manifest_b));
122 
123  boot_policy_manifests_t res = boot_policy_manifests_get();
124  if (param.is_a_first) {
125  EXPECT_EQ(res.ordered[0], &manifest_a);
126  EXPECT_EQ(res.ordered[1], &manifest_b);
127  } else {
128  EXPECT_EQ(res.ordered[0], &manifest_b);
129  EXPECT_EQ(res.ordered[1], &manifest_a);
130  }
131 }
132 
133 INSTANTIATE_TEST_SUITE_P(
134  SecurityVersionCases, ManifestOrderTest,
135  testing::Values(
136  // Versions equal, choose A.
137  ManifestOrderTestCase{
138  .version_a = {0, 0, 0},
139  .version_b = {0, 0, 0},
140  .is_a_first = true,
141  },
142  // A.secver > B.secver, choose A.
143  ManifestOrderTestCase{
144  .version_a = {1, 0, 0},
145  .version_b = {0, 0, 0},
146  .is_a_first = true,
147  },
148  // A.secver < B.secver, choose B.
149  ManifestOrderTestCase{
150  .version_a = {0, 0, 0},
151  .version_b = {1, 0, 0},
152  .is_a_first = false,
153  },
154  // Secver equal, A.major > B.major, choose A.
155  ManifestOrderTestCase{
156  .version_a = {0, 1, 0},
157  .version_b = {0, 0, 0},
158  .is_a_first = true,
159  },
160  // Secver equal, B.major > A.major, choose B.
161  ManifestOrderTestCase{
162  .version_a = {0, 1, 0},
163  .version_b = {0, 2, 0},
164  .is_a_first = false,
165  },
166  // Secver equal, major equal, A.minor > B.minor, choose A.
167  ManifestOrderTestCase{
168  .version_a = {0, 3, 1},
169  .version_b = {0, 3, 0},
170  .is_a_first = true,
171  },
172  // Secver equal, major equal, A.minor < B.minor, choose B.
173  ManifestOrderTestCase{
174  .version_a = {0, 3, 1},
175  .version_b = {0, 3, 5},
176  .is_a_first = false,
177  },
178  // Signed integer limit wraparound. B is larger; choose B.
179  ManifestOrderTestCase{
180  .version_a = {std::numeric_limits<int32_t>::max(), 0, 0},
181  .version_b =
182  {static_cast<uint32_t>(std::numeric_limits<int32_t>::max()) + 1,
183  0, 0},
184  .is_a_first = false,
185  }));
186 
187 } // namespace
188 } // namespace manifest_unittest