| // 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; |
| } |