Software APIs
hmac_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/drivers/hmac.h"
6 
7 #include <array>
8 #include <limits>
9 
10 #include "gtest/gtest.h"
12 #include "sw/device/lib/base/mock_abs_mmio.h"
13 #include "sw/device/silicon_creator/lib/error.h"
14 #include "sw/device/silicon_creator/testing/rom_test.h"
15 
16 #include "hmac_regs.h" // Generated.
18 
19 namespace hmac_unittest {
20 namespace {
21 using ::testing::ElementsAreArray;
22 
23 class HmacTest : public rom_test::RomTest {
24  protected:
25  void ExpectInit() {
26  EXPECT_ABS_WRITE32(base_ + HMAC_CFG_REG_OFFSET, 0u);
27  EXPECT_ABS_WRITE32(base_ + HMAC_INTR_ENABLE_REG_OFFSET, 0u);
28  EXPECT_ABS_WRITE32(base_ + HMAC_INTR_STATE_REG_OFFSET,
29  std::numeric_limits<uint32_t>::max());
30 
31  uint32_t key_len_256 = HMAC_CFG_KEY_LENGTH_VALUE_KEY_256;
32  uint32_t digest_256 = HMAC_CFG_DIGEST_SIZE_VALUE_SHA2_256;
33 
34  EXPECT_ABS_WRITE32(base_ + HMAC_CFG_REG_OFFSET,
35  {
36  {HMAC_CFG_DIGEST_SWAP_BIT, false},
37  {HMAC_CFG_ENDIAN_SWAP_BIT, false},
38  {HMAC_CFG_SHA_EN_BIT, true},
39  {HMAC_CFG_HMAC_EN_BIT, false},
40  {HMAC_CFG_DIGEST_SIZE_OFFSET, digest_256},
41  {HMAC_CFG_KEY_LENGTH_OFFSET, key_len_256},
42  });
43  EXPECT_ABS_WRITE32(base_ + HMAC_CMD_REG_OFFSET,
44  {{HMAC_CMD_HASH_START_BIT, true}});
45  }
46 
47  void ExpectDigest(const std::array<uint32_t, 8> &digest) {
48  // Request digest.
49  EXPECT_ABS_WRITE32(base_ + HMAC_CMD_REG_OFFSET,
50  {{HMAC_CMD_HASH_PROCESS_BIT, true}});
51 
52  // Poll a couple of times before returning the result
53  EXPECT_ABS_READ32(base_ + HMAC_INTR_STATE_REG_OFFSET,
54  {
55  {HMAC_INTR_STATE_HMAC_DONE_BIT, false},
56  });
57  EXPECT_ABS_READ32(base_ + HMAC_INTR_STATE_REG_OFFSET,
58  {
59  {HMAC_INTR_STATE_HMAC_DONE_BIT, true},
60  });
61  EXPECT_ABS_WRITE32(base_ + HMAC_INTR_STATE_REG_OFFSET,
62  {
63  {HMAC_INTR_STATE_HMAC_DONE_BIT, true},
64  });
65  // The `final` function checks the DIGEST_SWAP bit to know
66  // the endianness of the result. We're testing little-endian
67  // in the unit test.
68  EXPECT_ABS_READ32(base_ + HMAC_CFG_REG_OFFSET, 0u);
69 
70  // Set expectations explicitly to ensure that the registers
71  // are contiguous.
72  EXPECT_ABS_READ32(base_ + HMAC_DIGEST_7_REG_OFFSET, digest[0]);
73  EXPECT_ABS_READ32(base_ + HMAC_DIGEST_6_REG_OFFSET, digest[1]);
74  EXPECT_ABS_READ32(base_ + HMAC_DIGEST_5_REG_OFFSET, digest[2]);
75  EXPECT_ABS_READ32(base_ + HMAC_DIGEST_4_REG_OFFSET, digest[3]);
76  EXPECT_ABS_READ32(base_ + HMAC_DIGEST_3_REG_OFFSET, digest[4]);
77  EXPECT_ABS_READ32(base_ + HMAC_DIGEST_2_REG_OFFSET, digest[5]);
78  EXPECT_ABS_READ32(base_ + HMAC_DIGEST_1_REG_OFFSET, digest[6]);
79  EXPECT_ABS_READ32(base_ + HMAC_DIGEST_0_REG_OFFSET, digest[7]);
80  }
81 
82  uint32_t base_ = TOP_EARLGREY_HMAC_BASE_ADDR;
83  rom_test::MockAbsMmio mmio_;
84 };
85 
86 class Sha256InitTest : public HmacTest {};
87 
88 TEST_F(Sha256InitTest, Initialize) {
89  ExpectInit();
90 
91  hmac_sha256_init();
92 }
93 
94 class Sha256UpdateTest : public HmacTest {};
95 
96 TEST_F(Sha256UpdateTest, SendData) {
97  constexpr std::array<uint8_t, 16> kData = {
98  0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
99  0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
100  };
101 
102  // Trigger 8bit aligned writes.
103  EXPECT_ABS_WRITE8(base_ + HMAC_MSG_FIFO_REG_OFFSET, 0x01);
104  EXPECT_ABS_WRITE8(base_ + HMAC_MSG_FIFO_REG_OFFSET, 0x02);
105  hmac_sha256_update(&kData[1], 2);
106 
107  // Trigger a single 32bit aligned write.
108  EXPECT_ABS_WRITE32(base_ + HMAC_MSG_FIFO_REG_OFFSET, 0x03020100);
109  hmac_sha256_update(&kData[0], 4);
110 
111  // Trigger 8bit/32bit/8bit sequence.
112  EXPECT_ABS_WRITE8(base_ + HMAC_MSG_FIFO_REG_OFFSET, 0x02);
113  EXPECT_ABS_WRITE8(base_ + HMAC_MSG_FIFO_REG_OFFSET, 0x03);
114  EXPECT_ABS_WRITE32(base_ + HMAC_MSG_FIFO_REG_OFFSET, 0x07060504);
115  EXPECT_ABS_WRITE8(base_ + HMAC_MSG_FIFO_REG_OFFSET, 0x08);
116  EXPECT_ABS_WRITE8(base_ + HMAC_MSG_FIFO_REG_OFFSET, 0x09);
117  hmac_sha256_update(&kData[2], 8);
118 }
119 
120 class Sha256FinalTest : public HmacTest {};
121 
122 TEST_F(Sha256FinalTest, GetDigest) {
123  constexpr std::array<uint32_t, 8> kExpectedDigest = {
124  0x00000000, 0x11111111, 0x22222222, 0x33333333,
125  0x44444444, 0x55555555, 0x66666666, 0x77777777,
126  };
127  ExpectDigest(kExpectedDigest);
128 
129  hmac_sha256_process();
130  hmac_digest_t got_digest;
131  hmac_sha256_final(&got_digest);
132  EXPECT_THAT(got_digest.digest, ElementsAreArray(kExpectedDigest));
133 }
134 
135 class Sha256Test : public HmacTest {};
136 
137 TEST_F(Sha256Test, Sha256) {
138  constexpr std::array<uint32_t, 2> kData = {
139  0x0a0b0c0d,
140  0x01020304,
141  };
142  constexpr std::array<uint32_t, 8> kExpectedDigest = {
143  0x00000000, 0x11111111, 0x22222222, 0x33333333,
144  0x44444444, 0x55555555, 0x66666666, 0x77777777,
145  };
146  ExpectInit();
147  EXPECT_ABS_WRITE32(base_ + HMAC_MSG_FIFO_REG_OFFSET, 0x0a0b0c0d);
148  EXPECT_ABS_WRITE32(base_ + HMAC_MSG_FIFO_REG_OFFSET, 0x01020304);
149  ExpectDigest(kExpectedDigest);
150 
151  hmac_digest_t act_digest;
152  hmac_sha256(&kData, sizeof(kData), &act_digest);
153  EXPECT_THAT(act_digest.digest, ElementsAreArray(kExpectedDigest));
154 }
155 
156 } // namespace
157 } // namespace hmac_unittest