Software APIs
kmac_smoketest.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 
5 #include "dt/dt_kmac.h"
10 #include "sw/device/lib/testing/test_framework/check.h"
12 
13 #include "kmac_regs.h" // Generated.
14 
15 static_assert(kDtKmacCount >= 1,
16  "This test requires at least one KMAC instance");
17 
18 static dt_kmac_t kTestKmac = (dt_kmac_t)0;
19 
20 OTTF_DEFINE_TEST_CONFIG();
21 
22 /**
23  * Digest lengths in 32-bit words.
24  */
25 #define DIGEST_LEN_SHA3_224 (224 / 32)
26 #define DIGEST_LEN_SHA3_256 (256 / 32)
27 #define DIGEST_LEN_SHA3_384 (384 / 32)
28 #define DIGEST_LEN_SHA3_512 (512 / 32)
29 #define DIGEST_LEN_SHA3_MAX DIGEST_LEN_SHA3_512
30 
31 /**
32  * SHA-3 test description.
33  */
34 typedef struct sha3_test {
36 
37  const char *message;
38  size_t message_len;
39 
40  const uint32_t digest[DIGEST_LEN_SHA3_MAX];
41  size_t digest_len;
42 } sha3_test_t;
43 
44 /**
45  * SHA-3 tests.
46  */
47 const sha3_test_t sha3_tests[] = {
48  // Examples taken from NIST FIPS-202 Algorithm Test Vectors:
49  // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/sha3/sha-3bytetestvectors.zip
50  {
51  .mode = kDifKmacModeSha3Len224,
52  .message = NULL,
53  .message_len = 0,
54  .digest = {0x42034e6b, 0xb7db6736, 0x45156e3b, 0xabb10e4f, 0x9a7f59d4,
55  0x3f8e071b, 0xc76b5a5b},
56  .digest_len = DIGEST_LEN_SHA3_224,
57  },
58  {
59  .mode = kDifKmacModeSha3Len256,
60  .message = "\xe7\x37\x21\x05",
61  .message_len = 32 / 8,
62  .digest = {0x8ab6423a, 0x8cf279b0, 0x52c7a34c, 0x90276f29, 0x78fec406,
63  0xd979ebb1, 0x057f7789, 0xae46401e},
64  .digest_len = DIGEST_LEN_SHA3_256,
65  },
66  {
67  .mode = kDifKmacModeSha3Len384,
68  .message = "\xa7\x48\x47\x93\x0a\x03\xab\xee\xa4\x73\xe1\xf3\xdc\x30"
69  "\xb8\x88\x15",
70  .message_len = 136 / 8,
71  .digest = {0x29f9a6db, 0xd6f955fe, 0xc0675f6c, 0xf1823baf, 0xb358cf7b,
72  0x16f35267, 0x3f08165c, 0x78d48fea, 0xf20369ee, 0xd20a827f,
73  0xaf5099dd, 0x00678cb4},
74  .digest_len = DIGEST_LEN_SHA3_384,
75  },
76  {
77  .mode = kDifKmacModeSha3Len512,
78  .message =
79  "\x66\x4e\xf2\xe3\xa7\x05\x9d\xaf\x1c\x58\xca\xf5\x20\x08\xc5\x22"
80  "\x7e\x85\xcd\xcb\x83\xb4\xc5\x94\x57\xf0\x2c\x50\x8d\x4f\x4f\x69"
81  "\xf8\x26\xbd\x82\xc0\xcf\xfc\x5c\xb6\xa9\x7a\xf6\xe5\x61\xc6\xf9"
82  "\x69\x70\x00\x52\x85\xe5\x8f\x21\xef\x65\x11\xd2\x6e\x70\x98\x89"
83  "\xa7\xe5\x13\xc4\x34\xc9\x0a\x3c\xf7\x44\x8f\x0c\xae\xec\x71\x14"
84  "\xc7\x47\xb2\xa0\x75\x8a\x3b\x45\x03\xa7\xcf\x0c\x69\x87\x3e\xd3"
85  "\x1d\x94\xdb\xef\x2b\x7b\x2f\x16\x88\x30\xef\x7d\xa3\x32\x2c\x3d"
86  "\x3e\x10\xca\xfb\x7c\x2c\x33\xc8\x3b\xbf\x4c\x46\xa3\x1d\xa9\x0c"
87  "\xff\x3b\xfd\x4c\xcc\x6e\xd4\xb3\x10\x75\x84\x91\xee\xba\x60\x3a"
88  "\x76",
89  .message_len = 1160 / 8,
90  .digest = {0xf15f82e5, 0xd570c0a3, 0xe7bb2fa5, 0x444a8511, 0x5f295405,
91  0x69797afb, 0xd10879a1, 0xbebf6301, 0xa6521d8f, 0x13a0e876,
92  0x1ca1567b, 0xb4fb0fdf, 0x9f89bc56, 0x4bd127c7, 0x322288d8,
93  0x4e919d54},
94  .digest_len = DIGEST_LEN_SHA3_512,
95  },
96 };
97 
98 #define DIGEST_LEN_SHAKE_MAX 102
99 
100 /**
101  * SHAKE test description.
102  */
103 typedef struct shake_test {
105 
106  const char *message;
107  size_t message_len;
108 
109  const uint32_t digest[DIGEST_LEN_SHAKE_MAX];
110  size_t digest_len;
111 } shake_test_t;
112 
113 /**
114  * SHAKE tests.
115  */
116 // Examples generated using a custom Go program importing package
117 // `golang.org/x/crypto/sha3`
118 const shake_test_t shake_tests[] = {
119  {
120  .mode = kDifKmacModeShakeLen128,
121  .message = "OpenTitan",
122  .message_len = 9,
123  .digest = {0x235a6522, 0x3bd735ac, 0x77832247, 0xc6b12919, 0xfb80eff0,
124  0xb8308a5a, 0xcb25db1f, 0xc5ce4cf2, 0x349730fc, 0xcedf024c,
125  0xff0eefec, 0x6985fe35, 0x3c46a736, 0x0084044b, 0x6d9f9920,
126  0x7c0ab055, 0x19d1d3ce, 0xb4353949, 0xfe8ffbcd, 0x5a7f2ec6,
127  0xc3cf795f, 0xa56d0d7b, 0x520c3358, 0x11237ec9, 0x4ca5ed53,
128  0x2999edc0, 0x6c59c68f, 0x54d9890c, 0x89a33092, 0xf406c674,
129  0xe2b4ebf1, 0x14e68bb2, 0x898ceb72, 0x1878875f, 0x9d7bb8d2,
130  0x268e4a5a, 0xe5da510f, 0x97e5d3bc, 0xaae1b7bc, 0xa337f70b,
131  0xeae3cc65, 0xb8429058, 0xe4319c08, 0xd35e2786, 0xbc99af6e,
132  0x19a04aa8, 0xccbf18bf, 0xf681ebd4, 0x3d6da575, 0x2f0b9406},
133  .digest_len = 1600 / 8 / 4, // Rate (r) is 42 words.
134  },
135  {
136  .mode = kDifKmacModeShakeLen256,
137  .message = "OpenTitan",
138  .message_len = 9,
139  .digest = {0x6a0faccd, 0xbf29cb1a, 0xb631f604, 0xdbcab36, 0xa15d167b,
140  0x18dc668b, 0x272e411b, 0x865e651a, 0x8abedb2a, 0x8db38e78,
141  0xe503c9a2, 0xe64faca9, 0xcbd867d0, 0xdba6f20f, 0xbe129db9,
142  0x842dc15c, 0x1406410b, 0x014ce621, 0x5d24eaf2, 0x63bdf816,
143  0xfb236f50, 0xbdba910c, 0xf4ba0e9a, 0x74b5a51f, 0xd644dffd,
144  0xcd650165, 0xe4ec5e7d, 0x64df5448, 0xdcf7b5e7, 0x68709c07,
145  0x47eed1db, 0xc1e55b24, 0x3c02fad9, 0xd72db62e, 0xc5a48eaf,
146  0xd14bb0c4, 0x0f7143ba, 0x4071b63e, 0x21f0ec4b, 0x41065039,
147  0x1b3e41c0, 0xd0d3b1d0, 0xca16acb9, 0xa06f55aa, 0x7bc7ce75,
148  0x08da25ce, 0x596a654b, 0x0b57ae54, 0x4b88c863, 0x199202d7,
149  0x88c112b6, 0xf6dc4a95, 0xe1cfeffa, 0xa7809e6f, 0x3a796dcd,
150  0xb5962e44, 0x179d6ff0, 0xc898c5a9, 0xd3f02195, 0x43623028,
151  0x4c3a4fe7, 0x2fab7bda, 0x04e5b4d4, 0xe0420692, 0x32fcaa2a,
152  0x05e92f07, 0xba0564ea, 0x7b169778, 0x61d4ca3e, 0x4a5d92ec,
153  0x079cb3ba, 0x9a784e40, 0x6381498c, 0xed6d8b6a, 0x2be74d42,
154  0xa234a3db, 0x60d10de8, 0xf0c77dda, 0xc8f94b72, 0x239a2bdf,
155  0xbfeba4a6, 0xc91042e9, 0xa5a11310, 0x8b44d66a, 0xea9bff2f,
156  0x441a445f, 0xe88ee35d, 0x89386c12, 0x1a8de11e, 0x46aff650,
157  0x423323c9, 0xba7b8db4, 0x06c36eb0, 0x4fd75b36, 0xf0c70001,
158  0x0aefb1df, 0x6ae399e6, 0xf71930a6, 0xdef2206, 0x5ce2a640,
159  0x6a82fcf4, 0xa91b0815},
160  .digest_len = 3264 / 8 / 4, // Rate (r) is 34 words.
161  },
162 };
163 
164 /**
165  * Run SHA-3 test cases using single blocking absorb/squeeze operations.
166  */
167 void run_sha3_test(dif_kmac_t *kmac) {
168  dif_kmac_operation_state_t operation_state;
169  for (int i = 0; i < ARRAYSIZE(sha3_tests); ++i) {
170  sha3_test_t test = sha3_tests[i];
171 
172  CHECK_DIF_OK(dif_kmac_mode_sha3_start(kmac, &operation_state, test.mode));
173  if (test.message_len > 0) {
174  CHECK_DIF_OK(dif_kmac_absorb(kmac, &operation_state, test.message,
175  test.message_len, NULL));
176  }
177  uint32_t out[DIGEST_LEN_SHA3_MAX];
178  CHECK(DIGEST_LEN_SHA3_MAX >= test.digest_len);
179  CHECK_DIF_OK(dif_kmac_squeeze(kmac, &operation_state, out, test.digest_len,
180  /*processed=*/NULL, /*capacity=*/NULL));
181  CHECK_DIF_OK(dif_kmac_end(kmac, &operation_state));
182 
183  // Wait for the hardware engine to actually finish. On FPGA, it may take
184  // a while until the DONE command gets actually executed (see SecCmdDelay
185  // SystemVerilog parameter).
186  CHECK_DIF_OK(dif_kmac_poll_status(kmac, KMAC_STATUS_SHA3_IDLE_BIT));
187 
188  for (int j = 0; j < test.digest_len; ++j) {
189  CHECK(out[j] == test.digest[j],
190  "test %d: mismatch at %d got=0x%x want=0x%x", i, j, out[j],
191  test.digest[j]);
192  }
193  }
194 }
195 
196 /**
197  * Run a SHA-3 test case with varying alignments.
198  */
199 void run_sha3_alignment_test(dif_kmac_t *kmac) {
200  // Examples taken from NIST FIPS-202 Algorithm Test Vectors:
201  // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/sha3/sha-3bytetestvectors.zip
202  const char kMsg[] =
203  "\xa7\x48\x47\x93\x0a\x03\xab\xee\xa4\x73\xe1\xf3\xdc\x30"
204  "\xb8\x88\x15";
205  const size_t kSize = ARRAYSIZE(kMsg);
206  const uint32_t kExpect = 0x29f9a6db;
208  dif_kmac_operation_state_t operation_state;
209 
210  for (size_t i = 0; i < sizeof(uint32_t); ++i) {
211  char buffer[ARRAYSIZE(kMsg) + sizeof(uint32_t)] = {0};
212  memcpy(&buffer[i], kMsg, kSize);
213 
214  CHECK_DIF_OK(dif_kmac_mode_sha3_start(kmac, &operation_state, kMode));
215  CHECK_DIF_OK(
216  dif_kmac_absorb(kmac, &operation_state, &buffer[i], kSize, NULL));
217 
218  // Checking the first 32-bits of the digest is sufficient.
219  uint32_t out;
220  CHECK_DIF_OK(dif_kmac_squeeze(kmac, &operation_state, &out,
221  sizeof(uint32_t), /*processed=*/NULL,
222  /*capacity=*/NULL));
223  CHECK_DIF_OK(dif_kmac_end(kmac, &operation_state));
224 
225  // Wait for the hardware engine to actually finish. On FPGA, it may take
226  // a while until the DONE command gets actually executed (see SecCmdDelay
227  // SystemVerilog parameter).
228  CHECK_DIF_OK(dif_kmac_poll_status(kmac, KMAC_STATUS_SHA3_IDLE_BIT));
229 
230  CHECK_DIF_OK((out == kExpect),
231  "mismatch at alignment %u got 0x%u want 0x%x", i, out,
232  kExpect);
233  }
234 
235  // Run a SHA-3 test case using multiple absorb calls.
236  {
237  CHECK_DIF_OK(dif_kmac_mode_sha3_start(kmac, &operation_state, kMode));
238  CHECK_DIF_OK(dif_kmac_absorb(kmac, &operation_state, &kMsg[0], 1, NULL));
239  CHECK_DIF_OK(dif_kmac_absorb(kmac, &operation_state, &kMsg[1], 2, NULL));
240  CHECK_DIF_OK(dif_kmac_absorb(kmac, &operation_state, &kMsg[3], 5, NULL));
241  CHECK_DIF_OK(dif_kmac_absorb(kmac, &operation_state, &kMsg[8], 4, NULL));
242  CHECK_DIF_OK(
243  dif_kmac_absorb(kmac, &operation_state, &kMsg[12], kSize - 12, NULL));
244 
245  // Checking the first 32-bits of the digest is sufficient.
246  uint32_t out;
247  CHECK_DIF_OK(dif_kmac_squeeze(kmac, &operation_state, &out,
248  sizeof(uint32_t), /*processed=*/NULL,
249  /*capacity=*/NULL));
250  CHECK_DIF_OK(dif_kmac_end(kmac, &operation_state));
251 
252  // Wait for the hardware engine to actually finish. On FPGA, it may take
253  // a while until the DONE command gets actually executed (see SecCmdDelay
254  // SystemVerilog parameter).
255  CHECK_DIF_OK(dif_kmac_poll_status(kmac, KMAC_STATUS_SHA3_IDLE_BIT));
256 
257  CHECK_DIF_OK((out == kExpect), "mismatch got 0x%u want 0x%x", out, kExpect);
258  }
259 }
260 
261 /**
262  * Run SHAKE test cases using single blocking absorb/squeeze operations.
263  */
264 void run_shake_test(dif_kmac_t *kmac) {
265  dif_kmac_operation_state_t operation_state;
266 
267  for (int i = 0; i < ARRAYSIZE(shake_tests); ++i) {
268  shake_test_t test = shake_tests[i];
269 
270  CHECK_DIF_OK(dif_kmac_mode_shake_start(kmac, &operation_state, test.mode));
271  if (test.message_len > 0) {
272  CHECK_DIF_OK(dif_kmac_absorb(kmac, &operation_state, test.message,
273  test.message_len, NULL));
274  }
275  uint32_t out[DIGEST_LEN_SHAKE_MAX];
276  CHECK(DIGEST_LEN_SHAKE_MAX >= test.digest_len);
277  CHECK_DIF_OK(dif_kmac_squeeze(kmac, &operation_state, out, test.digest_len,
278  /*processed=*/NULL, /*capacity=*/NULL));
279  CHECK_DIF_OK(dif_kmac_end(kmac, &operation_state));
280 
281  // Wait for the hardware engine to actually finish. On FPGA, it may take
282  // a while until the DONE command gets actually executed (see SecCmdDelay
283  // SystemVerilog parameter).
284  CHECK_DIF_OK(dif_kmac_poll_status(kmac, KMAC_STATUS_SHA3_IDLE_BIT));
285 
286  for (int j = 0; j < test.digest_len; ++j) {
287  CHECK(out[j] == test.digest[j],
288  "test %d: mismatch at %d got=0x%x want=0x%x", i, j, out[j],
289  test.digest[j]);
290  }
291  }
292 }
293 
294 bool test_main(void) {
295  LOG_INFO("Running KMAC DIF test...");
296 
297  // Intialize KMAC hardware.
298  dif_kmac_t kmac;
299  CHECK_DIF_OK(dif_kmac_init_from_dt(kTestKmac, &kmac));
300 
301  // Configure KMAC hardware using software entropy. The seed has been randomnly
302  // chosen and is genrated using enerated using
303  // ./util/design/gen-lfsr-seed.py --width 192 --seed 2034386436 --prefix ""
305  .entropy_mode = kDifKmacEntropyModeSoftware,
306  .entropy_seed = {0xb153e3fe, 0x09596819, 0x3e85a6e8, 0xb6dcdaba,
307  0x50dc409c, 0x11e1ebd1},
308  .entropy_fast_process = kDifToggleEnabled,
309  };
310  CHECK_DIF_OK(dif_kmac_configure(&kmac, config));
311 
312  run_sha3_test(&kmac);
313  run_sha3_alignment_test(&kmac);
314  run_shake_test(&kmac);
315 
316  return true;
317 }