blob: 26d6ec6470092a2c78c6f4973ef22dc0445e638e [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 "sw/device/lib/base/mmio.h"
#include "sw/device/lib/dif/dif_clkmgr.h"
#include "sw/device/lib/dif/dif_hmac.h"
#include "sw/device/lib/runtime/log.h"
#include "sw/device/lib/testing/clkmgr_testutils.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 "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
#define TIMEOUT (1000 * 1000)
OTTF_DEFINE_TEST_CONFIG();
static dif_clkmgr_t clkmgr;
static const dif_clkmgr_hintable_clock_t kHmacClock =
kTopEarlgreyHintableClocksMainHmac;
static const dif_hmac_transaction_t kHmacTransactionConfig = {
.digest_endianness = kDifHmacEndiannessLittle,
.message_endianness = kDifHmacEndiannessLittle,
};
static bool is_hintable_clock_enabled(const dif_clkmgr_t *clkmgr,
dif_clkmgr_hintable_clock_t clock) {
dif_toggle_t clock_state;
CHECK_DIF_OK(
dif_clkmgr_hintable_clock_get_enabled(clkmgr, clock, &clock_state));
return clock_state == kDifToggleEnabled;
}
static void initialize_clkmgr(dif_clkmgr_hintable_clock_t clock) {
mmio_region_t addr = mmio_region_from_addr(TOP_EARLGREY_CLKMGR_AON_BASE_ADDR);
CHECK_DIF_OK(dif_clkmgr_init(addr, &clkmgr));
// Get initial hint and enable for AES clock and check both are enabled.
dif_toggle_t clock_hint_state;
CHECK_DIF_OK(
dif_clkmgr_hintable_clock_get_hint(&clkmgr, clock, &clock_hint_state));
CHECK(clock_hint_state == kDifToggleEnabled);
CLKMGR_TESTUTILS_CHECK_CLOCK_HINT(clkmgr, clock, kDifToggleEnabled);
}
// This waits for the process to end with a looming hint, checks the hint status
// shows the clock is disabled, and reanable it. The check for process
// completion cannot be done using hmac registers since the clock will be
// disabled as soon as the process ends, so we just wait for the clkmgr hint
// status to indicate the clock is off, implying the process actually ended.
static void handle_end_of_process(dif_clkmgr_hintable_clock_t clock) {
IBEX_SPIN_FOR(!is_hintable_clock_enabled(&clkmgr, clock), TIMEOUT);
LOG_INFO("Done");
// After the AES operation is complete verify that the AES clk hint status
// within clkmgr now reads 0 again (AES is idle).
CLKMGR_TESTUTILS_SET_AND_CHECK_CLOCK_HINT(clkmgr, clock, kDifToggleDisabled,
kDifToggleDisabled);
// Write the HMAC clk hint to 1, read and check the HMAC output for
// correctness.
CLKMGR_TESTUTILS_SET_AND_CHECK_CLOCK_HINT(clkmgr, clock, kDifToggleEnabled,
kDifToggleEnabled);
}
bool test_main(void) {
dif_hmac_t hmac;
initialize_clkmgr(kHmacClock);
mmio_region_t base_addr = mmio_region_from_addr(TOP_EARLGREY_HMAC_BASE_ADDR);
CHECK_DIF_OK(dif_hmac_init(base_addr, &hmac));
// With the HMAC unit idle, write the HMAC clk hint to 0 within clkmgr to
// indicate HMAC clk can be gated and verify that the HMAC clk hint status
// within clkmgr reads 0 (HMAC is disabled).
CLKMGR_TESTUTILS_SET_AND_CHECK_CLOCK_HINT(
clkmgr, kHmacClock, kDifToggleDisabled, kDifToggleDisabled);
// Write the HMAC clk hint to 1 within clkmgr to indicate HMAC clk can be
// enabled.
CLKMGR_TESTUTILS_SET_AND_CHECK_CLOCK_HINT(
clkmgr, kHmacClock, kDifToggleEnabled, kDifToggleEnabled);
// Use HMAC in SHA256 mode to generate a 256bit key from `kHmacRefLongKey`.
CHECK_DIF_OK(dif_hmac_mode_sha256_start(&hmac, kHmacTransactionConfig));
hmac_testutils_push_message(&hmac, (char *)kHmacRefLongKey,
sizeof(kHmacRefLongKey));
LOG_INFO("Pushed message");
hmac_testutils_check_message_length(&hmac, sizeof(kHmacRefLongKey) * 8);
CLKMGR_TESTUTILS_SET_AND_CHECK_CLOCK_HINT(
clkmgr, kHmacClock, kDifToggleDisabled, kDifToggleEnabled);
LOG_INFO("Cleared hints");
CHECK_DIF_OK(dif_hmac_process(&hmac));
LOG_INFO("Process");
handle_end_of_process(kHmacClock);
dif_hmac_digest_t key_digest;
hmac_testutils_finish_polled(&hmac, &key_digest);
CHECK_ARRAYS_EQ(key_digest.digest, kHmacRefExpectedLongKeyDigest.digest,
ARRAYSIZE(key_digest.digest));
// Generate HMAC final digest, using the resulted SHA256 digest over the
// `kHmacRefLongKey`.
CHECK_DIF_OK(dif_hmac_mode_hmac_start(&hmac, (uint8_t *)&key_digest.digest[0],
kHmacTransactionConfig));
CLKMGR_TESTUTILS_SET_AND_CHECK_CLOCK_HINT(
clkmgr, kHmacClock, kDifToggleDisabled, kDifToggleEnabled);
LOG_INFO("Cleared hints");
hmac_testutils_push_message(&hmac, kHmacRefData, sizeof(kHmacRefData));
hmac_testutils_check_message_length(&hmac, sizeof(kHmacRefData) * 8);
CHECK_DIF_OK(dif_hmac_process(&hmac));
LOG_INFO("Process");
handle_end_of_process(kHmacClock);
hmac_testutils_finish_and_check_polled(&hmac, &kHmacRefExpectedDigest);
return true;
}