Software APIs
rom_e2e_static_critical_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 <stdbool.h>
6 #include <stdint.h>
7 
12 #include "sw/device/lib/testing/hmac_testutils.h"
13 #include "sw/device/lib/testing/test_framework/check.h"
15 #include "sw/device/silicon_creator/lib/base/boot_measurements.h"
17 #include "sw/device/silicon_creator/lib/manifest_def.h"
18 
20 
21 OTTF_DEFINE_TEST_CONFIG();
22 
23 #define RUN_TEST(test_) \
24  LOG_INFO("Starting test " #test_ "..."); \
25  test_(); \
26  LOG_INFO("Finished test " #test_ ": ok.");
27 
28 #define CHECK_WORD_ALIGNED(addr_) \
29  CHECK((uintptr_t)addr_ % sizeof(uint32_t) == 0, \
30  #addr_ " must be word aligned");
31 
32 void boot_measurements_test(void) {
33  const manifest_t *manifest = manifest_def_get();
35  const char *signed_region_start =
36  (const char *)manifest + offsetof(manifest_t, usage_constraints);
37  const char *manifest_end = (const char *)manifest + sizeof(manifest_t);
38  const char *image_end = (const char *)manifest + manifest->length;
39  ptrdiff_t signed_region_size = image_end - signed_region_start;
40 
41  CHECK_WORD_ALIGNED(manifest);
42  CHECK_WORD_ALIGNED(signed_region_start);
43  CHECK_WORD_ALIGNED(manifest_end);
44  CHECK_WORD_ALIGNED(image_end);
45  CHECK_WORD_ALIGNED(signed_region_size);
46 
47  dif_hmac_t hmac;
48  CHECK_DIF_OK(
49  dif_hmac_init(mmio_region_from_addr(TOP_EARLGREY_HMAC_BASE_ADDR), &hmac));
50  CHECK_DIF_OK(dif_hmac_mode_sha256_start(
51  &hmac, (dif_hmac_transaction_t){
52  .digest_endianness = kDifHmacEndiannessLittle,
53  .message_endianness = kDifHmacEndiannessLittle,
54  }));
55  CHECK(signed_region_size >= 0 && signed_region_size <= SIZE_MAX,
56  "signed_region_size must fit in a size_t");
57  CHECK_STATUS_OK(hmac_testutils_push_message(&hmac, signed_region_start,
58  (size_t)signed_region_size));
59  CHECK_DIF_OK(dif_hmac_process(&hmac));
60  dif_hmac_digest_t act_digest;
61  CHECK_STATUS_OK(hmac_testutils_finish_polled(&hmac, &act_digest));
62 
63  CHECK_ARRAYS_EQ(boot_measurements.rom_ext.data, act_digest.digest,
64  ARRAYSIZE(act_digest.digest));
65 }
66 
67 void sec_mmio_pos_test(void) {
68  enum {
69  kRndOffset = 13,
70  kRomCheckValue = 6,
71  };
72 
73  sec_mmio_check_values(kRndOffset);
74  sec_mmio_check_counters(kRomCheckValue + 1);
75 }
76 
77 static volatile bool exception_expected = false;
78 static volatile bool exception_observed = false;
79 
80 // Redeclaration of the addressable symbol in `sec_mmio_neg_test()` to be used
81 // in `ottf_exception_handler()`.
82 extern const char kSecMmioNegTestReturn[];
83 
84 void ottf_exception_handler(uint32_t *exc_info) {
85  CHECK(exception_expected == true);
86  CHECK(exception_observed == false);
87  exception_expected = false;
88  // The frame address is the address of the stack location that holds the
89  // `mepc`, since the OTTF exception handler entry code saves the `mepc` to
90  // the top of the stack before transferring control flow to the exception
91  // handler function (which is overridden here). See the `handler_exception`
92  // subroutine in `sw/device/lib/testing/testing/ottf_isrs.S` for more details.
93  uintptr_t *mepc_stack_addr = (uintptr_t *)OT_FRAME_ADDR();
94  ibex_exc_t exception = ibex_mcause_read();
95  switch (exception) {
96  case kIbexExcIllegalInstrFault:
97  LOG_INFO("Observed illegal instruction fault");
98  exception_observed = true;
99  *mepc_stack_addr = (uintptr_t)kSecMmioNegTestReturn;
100  break;
101  default:
102  LOG_FATAL("Unexpected exception id = 0x%x", exception);
103  abort();
104  }
105 }
106 
107 void sec_mmio_neg_test(void) {
108  exception_expected = true;
110  CHECK(false, "Should not be here");
111 
112  OT_ADDRESSABLE_LABEL(kSecMmioNegTestReturn);
113  CHECK(exception_observed == true);
114 }
115 
116 bool test_main(void) {
117  RUN_TEST(boot_measurements_test);
118  RUN_TEST(sec_mmio_pos_test);
119  RUN_TEST(sec_mmio_neg_test);
120  return true;
121 }