Software APIs
boot_svc_header_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/lib/boot_svc/boot_svc_header.h"
6 
7 #include <array>
8 #include <cstring>
9 
10 #include "gtest/gtest.h"
12 #include "sw/device/silicon_creator/lib/drivers/mock_hmac.h"
13 #include "sw/device/silicon_creator/testing/rom_test.h"
14 
15 bool operator==(boot_svc_header_t lhs, boot_svc_header_t rhs) {
16  return std::memcmp(&lhs, &rhs, sizeof(boot_svc_header_t)) == 0;
17 }
18 
19 namespace boot_svc_header_unittest {
20 namespace {
21 using ::testing::_;
22 using ::testing::ElementsAreArray;
23 using ::testing::SetArgPointee;
24 
26  protected:
27  rom_test::MockHmac hmac_;
28 };
29 
30 TEST_F(BootSvcHeaderTest, Init) {
31  struct BootSvcFakeMsg {
32  boot_svc_header_t header{};
33  uint32_t payload{0xbeefbeef};
34  };
35  BootSvcFakeMsg fake_msg;
36  constexpr uint32_t kType = 0xcafecafe;
37  constexpr uint32_t kDigestAreaByteCount =
38  sizeof(fake_msg) - sizeof(fake_msg.header.digest);
39  constexpr hmac_digest_t kFakeDigest = {
40  0x0b00000e, 0x0b01010e, 0x0b02020e, 0x0b03030e,
41  0x0b04040e, 0x0b05050e, 0x0b06060e, 0x0b07070e,
42  };
43 
44  EXPECT_CALL(hmac_,
45  sha256(&fake_msg.header.identifier, kDigestAreaByteCount, _))
46  .WillOnce(SetArgPointee<2>(kFakeDigest));
47 
48  boot_svc_header_finalize(kType, sizeof(fake_msg), &fake_msg.header);
49 
50  EXPECT_THAT(fake_msg.header.digest.digest,
51  ElementsAreArray(kFakeDigest.digest));
52  EXPECT_EQ(fake_msg.header.identifier, kBootSvcIdentifier);
53  EXPECT_EQ(fake_msg.header.type, kType);
54  EXPECT_EQ(fake_msg.header.length, sizeof(fake_msg));
55 }
56 
58  boot_svc_header_t header;
59  uint32_t payload;
60 };
61 
63  BootSvcTestMsg msg;
64  rom_error_t exp_error;
65 };
66 
68  : public BootSvcHeaderTest,
69  public testing::WithParamInterface<BootSvcHeaderCheckTestCase> {};
70 
71 constexpr std::array<BootSvcHeaderCheckTestCase, 7> kHeaderCheckTestCases{{
72  // A valid message.
73  {
74  .msg = {.header =
75  {
76  .digest = {},
77  .identifier = kBootSvcIdentifier,
78  .type = 0,
79  .length = sizeof(BootSvcTestMsg),
80  }},
81  .exp_error = kErrorOk,
82  },
83  // Valid message, lower bound of length.
84  {
85  .msg = {.header =
86  {
87  .digest = {},
88  .identifier = kBootSvcIdentifier,
89  .type = 0,
91  }},
92  .exp_error = kErrorOk,
93  },
94  // Valid message, upper bound of length.
95  {
96  .msg = {.header =
97  {
98  .digest = {},
99  .identifier = kBootSvcIdentifier,
100  .type = 0,
101  .length = CHIP_BOOT_SVC_MSG_SIZE_MAX,
102  }},
103  .exp_error = kErrorOk,
104  },
105  // Bad digest.
106  {
107  .msg = {.header =
108  {
109  .digest = {0x8aadda7a},
110  .identifier = kBootSvcIdentifier,
111  .type = 0,
112  .length = sizeof(BootSvcTestMsg),
113  }},
114  .exp_error = kErrorBootSvcBadHeader,
115  },
116  // Bad identifier.
117  {
118  .msg = {.header =
119  {
120  .digest = {},
121  .identifier = 0x8aadda7a,
122  .type = 0,
123  .length = sizeof(BootSvcTestMsg),
124  }},
125  .exp_error = kErrorBootSvcBadHeader,
126  },
127  // Bad length (too small).
128  {
129  .msg = {.header =
130  {
131  .digest = {},
132  .identifier = kBootSvcIdentifier,
133  .type = 0,
134  .length = CHIP_BOOT_SVC_MSG_HEADER_SIZE - 1,
135  }},
136  .exp_error = kErrorBootSvcBadHeader,
137  },
138  // Bad length (too big).
139  {
140  .msg = {.header =
141  {
142  .digest = {},
143  .identifier = kBootSvcIdentifier,
144  .type = 0,
145  .length = CHIP_BOOT_SVC_MSG_SIZE_MAX + 1,
146  }},
147  .exp_error = kErrorBootSvcBadHeader,
148  },
149 }};
150 
151 TEST_P(BootSvcHeaderCheckTest, Check) {
152  // Use an all-zero digest by default.
153  EXPECT_CALL(hmac_,
154  sha256(&GetParam().msg.header.identifier,
155  GetParam().msg.header.length - sizeof(hmac_digest_t), _))
156  .WillOnce(SetArgPointee<2>(hmac_digest_t{}));
157 
158  EXPECT_EQ(boot_svc_header_check(&GetParam().msg.header),
159  GetParam().exp_error);
160 }
161 
162 INSTANTIATE_TEST_SUITE_P(HeaderCheckTestCases, BootSvcHeaderCheckTest,
163  testing::ValuesIn(kHeaderCheckTestCases));
164 
165 } // namespace
166 } // namespace boot_svc_header_unittest