Software APIs
hmac_enc_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 
5 #include "dt/dt_hmac.h" // Generated
6 #include "dt/dt_rv_plic.h" // Generated
10 #include "sw/device/lib/runtime/irq.h"
12 #include "sw/device/lib/testing/hmac_testutils.h"
13 #include "sw/device/lib/testing/rv_plic_testutils.h"
14 #include "sw/device/lib/testing/test_framework/check.h"
16 
17 static const uint32_t kPlicTarget = 0;
18 static dif_rv_plic_t rv_plic;
19 static dt_rv_plic_t kRvPlicDt = kDtRvPlic;
20 static dif_hmac_t hmac;
21 static dt_hmac_t kHmacDt = (dt_hmac_t)0;
22 static_assert(kDtHmacCount >= 1,
23  "This test requires at least one HMAC instance");
24 
25 static volatile dt_hmac_irq_t irq_serviced;
26 
27 OTTF_DEFINE_TEST_CONFIG();
28 
29 static const dif_hmac_transaction_t kHmacTransactionConfig = {
31  .message_endianness = kDifHmacEndiannessLittle,
32 };
33 
34 /**
35  * Catch HMAC IRQs so they can be checked by the test body.
36  */
37 bool ottf_handle_irq(uint32_t *exc_info, dt_instance_id_t devid,
38  dif_rv_plic_irq_id_t irq_id) {
39  if (devid == dt_hmac_instance_id(kHmacDt)) {
40  irq_serviced = dt_hmac_irq_from_plic_id(kHmacDt, irq_id);
41 
42  // Acknowledge the IRQ at the peripheral if the IRQ is of the event type.
43  dif_irq_type_t type;
44  CHECK_DIF_OK(dif_hmac_irq_get_type(&hmac, irq_serviced, &type));
45  if (type == kDifIrqTypeEvent) {
46  CHECK_DIF_OK(dif_hmac_irq_acknowledge(&hmac, irq_serviced));
47  }
48 
49  return true;
50  }
51  return false;
52 }
53 
54 /**
55  * Enables interrupts required by this test.
56  */
57 static void irqs_init(void) {
58  CHECK_DIF_OK(dif_rv_plic_init_from_dt(kRvPlicDt, &rv_plic));
59 
60  // Enable interrupts in HMAC IP.
61  CHECK_DIF_OK(
62  dif_hmac_irq_set_enabled(&hmac, kDtHmacIrqHmacDone, kDifToggleEnabled));
63  CHECK_DIF_OK(
64  dif_hmac_irq_set_enabled(&hmac, kDtHmacIrqFifoEmpty, kDifToggleEnabled));
65 
66  // Enable interrupts in PLIC.
67  rv_plic_testutils_irq_range_enable(
68  &rv_plic, kPlicTarget,
69  dt_hmac_irq_to_plic_id(kHmacDt, kDtHmacIrqHmacDone),
70  dt_hmac_irq_to_plic_id(kHmacDt, kDtHmacIrqFifoEmpty));
71  // Enable interrupts in Ibex.
72  irq_external_ctrl(true);
73  irq_global_ctrl(true);
74 }
75 
76 bool test_main(void) {
77  CHECK_DIF_OK(dif_hmac_init_from_dt(kHmacDt, &hmac));
78 
79  irqs_init();
80 
81  // Use HMAC in SHA256 mode to generate a 256bit key from `kHmacRefLongKey`.
82  CHECK_DIF_OK(dif_hmac_mode_sha256_start(&hmac, kHmacTransactionConfig));
83  CHECK_STATUS_OK(hmac_testutils_push_message(&hmac, (char *)kHmacRefLongKey,
84  sizeof(kHmacRefLongKey)));
85  CHECK_STATUS_OK(
86  hmac_testutils_check_message_length(&hmac, sizeof(kHmacRefLongKey) * 8));
87 
88  // Expect the done irq after processing data.
89  dt_hmac_irq_t expected_irq = kDtHmacIrqHmacDone;
90  irq_serviced = UINT32_MAX;
91 
92  CHECK_DIF_OK(dif_hmac_process(&hmac));
93  dif_hmac_digest_t key_digest;
94  CHECK_STATUS_OK(hmac_testutils_finish_polled(&hmac, &key_digest));
95  CHECK_ARRAYS_EQ(key_digest.digest, kHmacRefExpectedLongKeyDigest.digest,
96  ARRAYSIZE(key_digest.digest));
97 
98  CHECK(irq_serviced == expected_irq);
99 
100  // Generate HMAC final digest, using the resulted SHA256 digest over the
101  // `kHmacRefLongKey`.
102  CHECK_DIF_OK(dif_hmac_mode_hmac_start(&hmac, (uint8_t *)&key_digest.digest[0],
103  kHmacTransactionConfig));
104  CHECK_STATUS_OK(
105  hmac_testutils_push_message(&hmac, kHmacRefData, sizeof(kHmacRefData)));
106  CHECK_STATUS_OK(
107  hmac_testutils_check_message_length(&hmac, sizeof(kHmacRefData) * 8));
108  CHECK_DIF_OK(dif_hmac_process(&hmac));
109  LOG_INFO("Waiting for HMAC pooling to finish");
110  return status_ok(
111  hmac_testutils_finish_and_check_polled(&hmac, &kHmacRefExpectedDigest));
112 }