blob: 1361adf7aecc7c81d5821a7c6fecd97e9e3e3288 [file] [log] [blame]
// Copyright lowRISC contributors.
// Licensed under the Apache License, Version 2.0, see LICENSE for details.
// SPDX-License-Identifier: Apache-2.0
#include <stdbool.h>
#include "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_hmac.h"
#include "sw/device/lib/runtime/ibex.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/testing/hmac_testutils.h"
#include "sw/device/lib/testing/test_framework/check.h"
#include "sw/device/lib/testing/test_framework/ottf_main.h"
#include "sw/device/silicon_creator/lib/base/boot_measurements.h"
#include "sw/device/silicon_creator/lib/base/sec_mmio.h"
#include "sw/device/silicon_creator/lib/manifest_def.h"
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
OTTF_DEFINE_TEST_CONFIG();
#define RUN_TEST(test_) \
LOG_INFO("Starting test " #test_ "..."); \
test_(); \
LOG_INFO("Finished test " #test_ ": ok.");
#define CHECK_WORD_ALIGNED(addr_) \
CHECK((uintptr_t)addr_ % sizeof(uint32_t) == 0, \
#addr_ " must be word aligned");
void boot_measurements_test(void) {
const manifest_t *manifest = manifest_def_get();
CHECK(manifest->usage_constraints.selector_bits == 0);
const char *signed_region_start =
(const char *)manifest + sizeof(sigverify_rsa_buffer_t);
const char *manifest_end = (const char *)manifest + sizeof(manifest_t);
const char *image_end = (const char *)manifest + manifest->length;
size_t signed_region_size = image_end - signed_region_start;
CHECK_WORD_ALIGNED(manifest);
CHECK_WORD_ALIGNED(signed_region_start);
CHECK_WORD_ALIGNED(manifest_end);
CHECK_WORD_ALIGNED(image_end);
CHECK_WORD_ALIGNED(signed_region_size);
dif_hmac_t hmac;
CHECK_DIF_OK(
dif_hmac_init(mmio_region_from_addr(TOP_EARLGREY_HMAC_BASE_ADDR), &hmac));
CHECK_DIF_OK(dif_hmac_mode_sha256_start(
&hmac, (dif_hmac_transaction_t){
.digest_endianness = kDifHmacEndiannessLittle,
.message_endianness = kDifHmacEndiannessLittle,
}));
hmac_testutils_push_message(&hmac, signed_region_start, signed_region_size);
CHECK_DIF_OK(dif_hmac_process(&hmac));
dif_hmac_digest_t act_digest;
hmac_testutils_finish_polled(&hmac, &act_digest);
CHECK_ARRAYS_EQ(boot_measurements.rom_ext.data, act_digest.digest,
ARRAYSIZE(act_digest.digest));
}
void sec_mmio_pos_test(void) {
enum {
kRndOffset = 13,
kRomCheckValue = 6,
};
sec_mmio_check_values(kRndOffset);
sec_mmio_check_counters(kRomCheckValue + 1);
}
static volatile bool exception_expected = false;
static volatile bool exception_observed = false;
// Redeclaration of the addressable symbol in `sec_mmio_neg_test()` to be used
// in `ottf_exception_handler()`.
extern const char kSecMmioNegTestReturn[];
void ottf_exception_handler(void) {
CHECK(exception_expected == true);
CHECK(exception_observed == false);
exception_expected = false;
// The frame address is the address of the stack location that holds the
// `mepc`, since the OTTF exception handler entry code saves the `mepc` to
// the top of the stack before transferring control flow to the exception
// handler function (which is overridden here). See the `handler_exception`
// subroutine in `sw/device/lib/testing/testing/ottf_isrs.S` for more details.
uintptr_t *mepc_stack_addr = (uintptr_t *)OT_FRAME_ADDR();
ibex_exc_t exception = ibex_mcause_read();
switch (exception) {
case kIbexExcIllegalInstrFault:
LOG_INFO("Observed illegal instruction fault");
exception_observed = true;
*mepc_stack_addr = (uintptr_t)kSecMmioNegTestReturn;
break;
default:
LOG_FATAL("Unexpected exception id = 0x%x", exception);
abort();
}
}
void sec_mmio_neg_test(void) {
exception_expected = true;
sec_mmio_check_counters(0);
CHECK(false, "Should not be here");
OT_ADDRESSABLE_LABEL(kSecMmioNegTestReturn);
CHECK(exception_observed == true);
}
bool test_main(void) {
RUN_TEST(boot_measurements_test);
RUN_TEST(sec_mmio_pos_test);
RUN_TEST(sec_mmio_neg_test);
return true;
}