blob: d0959820c706e5d20ac32914bafcf8013a0b62bc [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_kmac.h"
#include "sw/device/lib/runtime/log.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"
static dif_clkmgr_t clkmgr;
static dif_kmac_t kmac;
OTTF_DEFINE_TEST_CONFIG();
const dif_clkmgr_hintable_clock_t kmac_clock =
kTopEarlgreyHintableClocksMainKmac;
// Digest lengths in 32-bit words.
#define DIGEST_LEN_SHA3_256 (256 / 32)
#define DIGEST_LEN_SHA3_512 (512 / 32)
#define DIGEST_LEN_SHA3_MAX DIGEST_LEN_SHA3_512
// SHA-3 test description.
typedef struct sha3_test {
dif_kmac_mode_sha3_t mode;
const char *message;
size_t message_len;
const uint32_t digest[DIGEST_LEN_SHA3_MAX];
size_t digest_len;
} sha3_test_t;
// SHA-3 test.
const sha3_test_t sha3_256_test = {
// Example taken from NIST FIPS-202 Algorithm Test Vectors:
// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Algorithm-Validation-Program/documents/sha3/sha-3bytetestvectors.zip
.mode = kDifKmacModeSha3Len256,
.message = "\xe7\x37\x21\x05",
.message_len = 4,
.digest = {0x8ab6423a, 0x8cf279b0, 0x52c7a34c, 0x90276f29, 0x78fec406,
0xd979ebb1, 0x057f7789, 0xae46401e},
.digest_len = DIGEST_LEN_SHA3_256};
static void check_clock_state(dif_toggle_t expected_clock_state) {
dif_toggle_t clock_state;
CHECK_DIF_OK(
dif_clkmgr_hintable_clock_get_enabled(&clkmgr, kmac_clock, &clock_state));
CHECK(clock_state == expected_clock_state,
"Clock enabled state is not as expected (%d).", expected_clock_state);
}
static void do_sha3_test(void) {
dif_kmac_operation_state_t kmac_operation_state;
// Run SHA3 test case using single blocking absorb/squeeze operations.
CHECK_DIF_OK(dif_kmac_mode_sha3_start(&kmac, &kmac_operation_state,
sha3_256_test.mode));
// Set hint and check clk state remains enabled as KMAC is now not idle.
CHECK_DIF_OK(dif_clkmgr_hintable_clock_set_hint(&clkmgr, kmac_clock,
kDifToggleDisabled));
check_clock_state(kDifToggleEnabled);
CHECK_DIF_OK(dif_kmac_absorb(&kmac, &kmac_operation_state,
sha3_256_test.message, sha3_256_test.message_len,
NULL));
uint32_t out[DIGEST_LEN_SHA3_MAX];
CHECK_DIF_OK(dif_kmac_squeeze(&kmac, &kmac_operation_state, out,
sha3_256_test.digest_len, NULL));
// Check clock state again which should still be enabled.
check_clock_state(kDifToggleEnabled);
CHECK_DIF_OK(dif_kmac_end(&kmac, &kmac_operation_state));
// Check the clock is now stopped.
check_clock_state(kDifToggleDisabled);
// Check the result to be sure the SHA3 operation completed correctly.
CHECK_ARRAYS_EQ(out, sha3_256_test.digest, sha3_256_test.digest_len,
"Digest mismatch for test SHA3 256.");
// Set hint to enabled again to check that clock can be re-enabled.
CHECK_DIF_OK(dif_clkmgr_hintable_clock_set_hint(&clkmgr, kmac_clock,
kDifToggleEnabled));
check_clock_state(kDifToggleEnabled);
}
bool test_main(void) {
CHECK_DIF_OK(dif_clkmgr_init(
mmio_region_from_addr(TOP_EARLGREY_CLKMGR_AON_BASE_ADDR), &clkmgr));
// Get initial hint and enable for KMAC clock and check both are enabled.
dif_toggle_t clock_hint_state;
CHECK_DIF_OK(dif_clkmgr_hintable_clock_get_hint(&clkmgr, kmac_clock,
&clock_hint_state));
CHECK(clock_hint_state == kDifToggleEnabled);
check_clock_state(kDifToggleEnabled);
// While KMAC is not in use, set disabled hint for KMAC clock
// then check clock state, set back to enabled and check again.
// Note: disabled means the clock can be disabled.
CHECK_DIF_OK(dif_clkmgr_hintable_clock_set_hint(&clkmgr, kmac_clock,
kDifToggleDisabled));
check_clock_state(kDifToggleDisabled);
CHECK_DIF_OK(dif_clkmgr_hintable_clock_set_hint(&clkmgr, kmac_clock,
kDifToggleEnabled));
check_clock_state(kDifToggleEnabled);
// Initialize KMAC hardware.
CHECK_DIF_OK(
dif_kmac_init(mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR), &kmac));
// Configure KMAC hardware using software entropy.
dif_kmac_config_t config = (dif_kmac_config_t){
.entropy_mode = kDifKmacEntropyModeSoftware,
.entropy_seed = {0xaa25b4bf, 0x48ce8fff, 0x5a78282a, 0x48465647,
0x70410fef},
.entropy_fast_process = kDifToggleEnabled,
};
CHECK_DIF_OK(dif_kmac_configure(&kmac, config));
// call sha3 test twice to check that when clock
// is enabled again after the first call
// that all still works for the second call.
do_sha3_test();
do_sha3_test();
return true;
}