Software APIs
hmac_secure_wipe_test.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 
8 #include "sw/device/lib/testing/hmac_testutils.h"
9 #include "sw/device/lib/testing/test_framework/check.h"
11 
13 
14 OTTF_DEFINE_TEST_CONFIG();
15 
16 static const char kData[142] =
17  "Every one suspects himself of at least one of "
18  "the cardinal virtues, and this is mine: I am "
19  "one of the few honest people that I have ever "
20  "known";
21 
22 static uint32_t kHmacKey[8] = {
23  0xec4e6c89, 0x082efa98, 0x299f31d0, 0xa4093822,
24  0x03707344, 0x13198a2e, 0x85a308d3, 0x243f6a88,
25 };
26 
27 static const dif_hmac_digest_t kExpectedHmacDigest = {
28  .digest =
29  {
30  0xebce4019,
31  0x284d39f1,
32  0x5eae12b0,
33  0x0c48fb23,
34  0xfadb9531,
35  0xafbbf3c2,
36  0x90d3833f,
37  0x397b98e4,
38  },
39 };
40 
41 // Polls for HMAC to finish and returns the digest.
42 status_t hmac_finish_polled(const dif_hmac_t *hmac,
43  dif_hmac_digest_t *digest_out) {
44  uint32_t usec;
45  TRY(compute_hmac_testutils_finish_timeout_usec(&usec));
47  dif_hmac_finish(hmac, /*disable_after_done=*/false, digest_out) == kDifOk,
48  usec);
49  return OK_STATUS();
50 }
51 
52 // Processes a message and checks the HMAC FIFO.
53 static void hmac_process_message(const dif_hmac_t *hmac, const char *data,
54  size_t len) {
55  CHECK_STATUS_OK(hmac_testutils_push_message(hmac, data, len));
56  CHECK_STATUS_OK(hmac_testutils_fifo_empty_polled(hmac));
57  CHECK_STATUS_OK(hmac_testutils_check_message_length(hmac, len * 8));
58  CHECK_DIF_OK(dif_hmac_process(hmac));
59 }
60 
61 bool test_main(void) {
62  dif_hmac_t hmac;
63  CHECK_DIF_OK(
64  dif_hmac_init(mmio_region_from_addr(TOP_EARLGREY_HMAC_BASE_ADDR), &hmac));
65 
66  static const dif_hmac_transaction_t kHmacTransactionConfig = {
68  .message_endianness = kDifHmacEndiannessLittle,
69  };
70 
71  CHECK_DIF_OK(dif_hmac_mode_hmac_start(&hmac, (uint8_t *)(&kHmacKey[0]),
72  kHmacTransactionConfig));
73  hmac_process_message(&hmac, kData, sizeof(kData));
74 
75  dif_hmac_digest_t digest;
76  CHECK_STATUS_OK(hmac_finish_polled(&hmac, &digest));
77  CHECK_ARRAYS_EQ(digest.digest, kExpectedHmacDigest.digest,
78  ARRAYSIZE(digest.digest));
79 
80  // The digest should not longer match after secure wipe.
81  const uint32_t kSecureWipeValue = UINT32_MAX;
82  CHECK_DIF_OK(dif_hmac_wipe_secret(&hmac, kSecureWipeValue, &digest));
83 
84  // Secure wipe is kSecureWipeValue overwritten to the digest words.
85  for (size_t i = 0; i < ARRAYSIZE(digest.digest); ++i) {
86  uint32_t expected_value = kSecureWipeValue;
87  CHECK(digest.digest[i] == expected_value,
88  "Expected digest[%d] = %x, actual = %x", i, expected_value,
89  digest.digest[i]);
90  }
91 
92  // HMAC should no longer have the key configured after secure wipe.
93  CHECK_DIF_OK(
94  dif_hmac_mode_hmac_start(&hmac, /*key=*/NULL, kHmacTransactionConfig));
95  hmac_process_message(&hmac, kData, sizeof(kData));
96  CHECK_STATUS_OK(hmac_testutils_finish_polled(&hmac, &digest));
97  CHECK_ARRAYS_NE(digest.digest, kExpectedHmacDigest.digest,
98  ARRAYSIZE(digest.digest));
99  return true;
100 }