[test] Add KMAC sideloading test.

Add a test from the test plan that sideloads a key to KMAC. For now, all
it does is check that the software key isn't used.

Signed-off-by: Jade Philipoom <jadep@google.com>
diff --git a/hw/top_earlgrey/data/chip_testplan.hjson b/hw/top_earlgrey/data/chip_testplan.hjson
index f0565b8..a28f118 100644
--- a/hw/top_earlgrey/data/chip_testplan.hjson
+++ b/hw/top_earlgrey/data/chip_testplan.hjson
@@ -2118,7 +2118,7 @@
             X-ref'ed with chip_kmac_app_keymgr test.
             '''
       milestone: V2
-      tests: []
+      tests: ["chip_sw_keymgr_sideload_kmac"]
     }
     {
       name: chip_sw_keymgr_sideload_aes
diff --git a/hw/top_earlgrey/dv/chip_sim_cfg.hjson b/hw/top_earlgrey/dv/chip_sim_cfg.hjson
index e082f71..6a81546 100644
--- a/hw/top_earlgrey/dv/chip_sim_cfg.hjson
+++ b/hw/top_earlgrey/dv/chip_sim_cfg.hjson
@@ -846,6 +846,13 @@
       run_opts: ["+sw_test_timeout_ns=20_000_000", "+en_jitter=1"]
     }
     {
+      name: chip_sw_keymgr_sideload_kmac
+      uvm_test_seq: chip_sw_base_vseq
+      sw_images: ["//sw/device/tests/sim_dv:keymgr_sideload_kmac_test:1"]
+      en_run_modes: ["sw_test_mode_test_rom"]
+      run_opts: ["+sw_test_timeout_ns=20_000_000"]
+    }
+    {
       name: chip_sw_kmac_mode_cshake
       uvm_test_seq: chip_sw_base_vseq
       sw_images: ["//sw/device/tests:kmac_mode_cshake_test:1"]
diff --git a/sw/device/lib/testing/BUILD b/sw/device/lib/testing/BUILD
index 8630dbd..96f6068 100644
--- a/sw/device/lib/testing/BUILD
+++ b/sw/device/lib/testing/BUILD
@@ -156,8 +156,24 @@
         "//sw/device/lib/base:mmio",
         "//sw/device/lib/dif:flash_ctrl",
         "//sw/device/lib/dif:keymgr",
+        "//sw/device/lib/dif:otp_ctrl",
+        "//sw/device/lib/dif:rstmgr",
         "//sw/device/lib/runtime:ibex",
         "//sw/device/lib/testing:flash_ctrl_testutils",
+        "//sw/device/lib/testing:kmac_testutils",
+        "//sw/device/lib/testing:otp_ctrl_testutils",
+        "//sw/device/lib/testing:rstmgr_testutils",
+        "//sw/device/lib/testing/test_framework:check",
+    ],
+)
+
+cc_library(
+    name = "kmac_testutils",
+    srcs = ["kmac_testutils.c"],
+    hdrs = ["kmac_testutils.h"],
+    target_compatible_with = [OPENTITAN_CPU],
+    deps = [
+        "//sw/device/lib/dif:kmac",
         "//sw/device/lib/testing/test_framework:check",
     ],
 )
diff --git a/sw/device/lib/testing/keymgr_testutils.c b/sw/device/lib/testing/keymgr_testutils.c
index c7cc57b..1763202 100644
--- a/sw/device/lib/testing/keymgr_testutils.c
+++ b/sw/device/lib/testing/keymgr_testutils.c
@@ -6,9 +6,15 @@
 
 #include "sw/device/lib/dif/dif_flash_ctrl.h"
 #include "sw/device/lib/dif/dif_keymgr.h"
+#include "sw/device/lib/dif/dif_kmac.h"
+#include "sw/device/lib/dif/dif_otp_ctrl.h"
+#include "sw/device/lib/dif/dif_rstmgr.h"
 #include "sw/device/lib/runtime/ibex.h"
 #include "sw/device/lib/runtime/log.h"
 #include "sw/device/lib/testing/flash_ctrl_testutils.h"
+#include "sw/device/lib/testing/kmac_testutils.h"
+#include "sw/device/lib/testing/otp_ctrl_testutils.h"
+#include "sw/device/lib/testing/rstmgr_testutils.h"
 #include "sw/device/lib/testing/test_framework/check.h"
 
 #include "hw/top_earlgrey/sw/autogen/top_earlgrey.h"
@@ -61,7 +67,7 @@
   CHECK_ARRAYS_EQ(data, readback_data, kSecretWordSize);
 }
 
-void keymgr_testutils_init_flash(void) {
+static void init_flash(void) {
   dif_flash_ctrl_state_t flash;
 
   CHECK_DIF_OK(dif_flash_ctrl_init_state(
@@ -72,6 +78,64 @@
   write_info_page(&flash, kFlashInfoPageIdOwnerSecret, kOwnerSecret);
 }
 
+void keymgr_testutils_startup(dif_keymgr_t *keymgr, dif_kmac_t *kmac) {
+  dif_rstmgr_t rstmgr;
+  dif_rstmgr_reset_info_bitfield_t info;
+
+  CHECK_DIF_OK(dif_rstmgr_init(
+      mmio_region_from_addr(TOP_EARLGREY_RSTMGR_AON_BASE_ADDR), &rstmgr));
+  info = rstmgr_testutils_reason_get();
+
+  // POR reset.
+  if (info == kDifRstmgrResetInfoPor) {
+    LOG_INFO("Powered up for the first time, program flash");
+
+    init_flash();
+
+    // Lock otp secret partition.
+    dif_otp_ctrl_t otp;
+    CHECK_DIF_OK(dif_otp_ctrl_init(
+        mmio_region_from_addr(TOP_EARLGREY_OTP_CTRL_CORE_BASE_ADDR), &otp));
+    otp_ctrl_testutils_lock_partition(&otp, kDifOtpCtrlPartitionSecret2, 0);
+
+    // Reboot device.
+    rstmgr_testutils_reason_clear();
+    CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
+
+    // Wait here until device reset.
+    wait_for_interrupt();
+
+  } else {
+    CHECK(info == kDifRstmgrResetInfoSw, "Unexpected reset reason: %0x", info);
+    LOG_INFO(
+        "Powered up for the second time, actuate keymgr and perform test.");
+
+    // Initialize KMAC in preparation for keymgr use.
+    CHECK_DIF_OK(dif_kmac_init(
+        mmio_region_from_addr(TOP_EARLGREY_KMAC_BASE_ADDR), kmac));
+
+    // We shouldn't use the KMAC block's default entropy setting for keymgr, so
+    // configure it to use software entropy (and a sideloaded key, although it
+    // shouldn't matter here and tests should reconfigure if needed).
+    kmac_testutils_config(kmac, true);
+
+    // Initialize keymgr context.
+    CHECK_DIF_OK(dif_keymgr_init(
+        mmio_region_from_addr(TOP_EARLGREY_KEYMGR_BASE_ADDR), keymgr));
+
+    // Advance to Initialized state.
+    keymgr_testutils_check_state(keymgr, kDifKeymgrStateReset);
+    keymgr_testutils_advance_state(keymgr, NULL);
+    keymgr_testutils_check_state(keymgr, kDifKeymgrStateInitialized);
+    LOG_INFO("Keymgr entered Init State");
+
+    // Advance to CreatorRootKey state.
+    keymgr_testutils_advance_state(keymgr, &kCreatorParams);
+    keymgr_testutils_check_state(keymgr, kDifKeymgrStateCreatorRootKey);
+    LOG_INFO("Keymgr entered CreatorRootKey State");
+  }
+}
+
 void keymgr_testutils_advance_state(const dif_keymgr_t *keymgr,
                                     const dif_keymgr_state_params_t *params) {
   CHECK_DIF_OK(dif_keymgr_advance_state(keymgr, params));
diff --git a/sw/device/lib/testing/keymgr_testutils.h b/sw/device/lib/testing/keymgr_testutils.h
index 20132ce..b88974d 100644
--- a/sw/device/lib/testing/keymgr_testutils.h
+++ b/sw/device/lib/testing/keymgr_testutils.h
@@ -6,6 +6,7 @@
 #define OPENTITAN_SW_DEVICE_LIB_TESTING_KEYMGR_TESTUTILS_H_
 
 #include "sw/device/lib/dif/dif_keymgr.h"
+#include "sw/device/lib/dif/dif_kmac.h"
 
 /**
  * Versioned key parameters for testing.
@@ -47,9 +48,31 @@
 };
 
 /**
- * Initialize flash for key manager operation.
+ * Programs flash, restarts, and advances keymgr to CreatorRootKey state.
+ *
+ * This procedure essentially gets the keymgr into the first state where it can
+ * be used for tests. Tests should call it before anything else, like below:
+ *
+ * void test_main(void) {
+ *   // Set up and advance to CreatorRootKey state.
+ *   dif_keymgr_t keymgr;
+ *   dif_kmac_t kmac;
+ *   keymgr_testutils_startup(&keymgr, &kmac);
+ *
+ *   // Remainder of test; optionally advance to OwnerIntKey state, generate
+ *   // keys and identities.
+ *   ...
+ * }
+ *
+ * Because the key manager uses KMAC, this procedure also initializes and
+ * configures KMAC. Software should not rely on the configuration here and
+ * should reconfigure KMAC if needed. The purpose of configuring KMAC in this
+ * procedure is so that the key manager will not use KMAC with the default
+ * entropy settings.
+ *
+ * @param keymgr A key manager handle.
  */
-void keymgr_testutils_init_flash(void);
+void keymgr_testutils_startup(dif_keymgr_t *keymgr, dif_kmac_t *kmac);
 
 /**
  * Issues a keymgr advance operation and wait for it to complete
diff --git a/sw/device/lib/testing/kmac_testutils.c b/sw/device/lib/testing/kmac_testutils.c
new file mode 100644
index 0000000..fc17dab
--- /dev/null
+++ b/sw/device/lib/testing/kmac_testutils.c
@@ -0,0 +1,66 @@
+// 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/testing/kmac_testutils.h"
+
+#include "sw/device/lib/dif/dif_kmac.h"
+#include "sw/device/lib/testing/test_framework/check.h"
+
+void kmac_testutils_config(dif_kmac_t *kmac, bool sideload) {
+  dif_kmac_config_t config = {
+      // Use software-provided "entropy" to avoid waiting for EDN.
+      .entropy_mode = kDifKmacEntropyModeSoftware,
+      // This option minimizes masking to improve speed.
+      .entropy_fast_process = true,
+      // No need to have real entropy for tests.
+      .entropy_seed = {0},
+      // Ignored because the entropy source is software.
+      .entropy_reseed_interval = 0,
+      // Ignored because the entropy source is software.
+      .entropy_wait_timer = 0,
+      // Leave message as the little-endian default.
+      .message_big_endian = false,
+      // Leave output as the little-endian default.
+      .output_big_endian = false,
+      // Use a sideloaded key if the caller requested to.
+      .sideload = sideload,
+      // Avoid masking the message to improve speed.
+      .msg_mask = false,
+  };
+
+  CHECK_DIF_OK(dif_kmac_configure(kmac, config));
+}
+
+void kmac_testutils_kmac(const dif_kmac_t *kmac,
+                         const dif_kmac_mode_kmac_t mode,
+                         const dif_kmac_key_t *key, const char *custom_string,
+                         const size_t custom_string_len, const char *message,
+                         const size_t message_len, const size_t output_len,
+                         uint32_t *output) {
+  // Initialize customization string.
+  dif_kmac_customization_string_t kmac_custom_string;
+  CHECK_DIF_OK(dif_kmac_customization_string_init(
+      custom_string, custom_string_len, &kmac_custom_string));
+
+  // Start the KMAC operation.
+  dif_kmac_operation_state_t operation_state;
+  CHECK_DIF_OK(dif_kmac_mode_kmac_start(kmac, &operation_state, mode,
+                                        output_len, key, &kmac_custom_string));
+
+  // Pass the entire message to KMAC ("absorb" stage).
+  CHECK_DIF_OK(
+      dif_kmac_absorb(kmac, &operation_state, message, message_len, NULL));
+
+  // Get the output ("squeeze" stage).
+  CHECK_DIF_OK(
+      dif_kmac_squeeze(kmac, &operation_state, output, output_len, NULL));
+
+  // End the operation.
+  CHECK_DIF_OK(dif_kmac_end(kmac, &operation_state));
+
+  // Double-check that there were no errors.
+  dif_kmac_error_t err;
+  CHECK_DIF_OK(dif_kmac_get_error(kmac, &err));
+  CHECK(err == kDifErrorNone);
+}
diff --git a/sw/device/lib/testing/kmac_testutils.h b/sw/device/lib/testing/kmac_testutils.h
new file mode 100644
index 0000000..b5f4d00
--- /dev/null
+++ b/sw/device/lib/testing/kmac_testutils.h
@@ -0,0 +1,45 @@
+// Copyright lowRISC contributors.
+// Licensed under the Apache License, Version 2.0, see LICENSE for details.
+// SPDX-License-Identifier: Apache-2.0
+
+#ifndef OPENTITAN_SW_DEVICE_LIB_TESTING_KMAC_TESTUTILS_H_
+#define OPENTITAN_SW_DEVICE_LIB_TESTING_KMAC_TESTUTILS_H_
+
+#include "sw/device/lib/dif/dif_kmac.h"
+
+/**
+ * Configure the KMAC block.
+ *
+ * This is a thin wrapper around `dif_kmac_configure`. It sets up a testing
+ * configuration that prioritizes speed over security, since we don't care
+ * about protecting test keys. For instance, it sets the entropy source to
+ * software so KMAC doesn't wait for fresh entropy, and minimizes masking.
+ *
+ * @param kmac KMAC context
+ * @param sideload Whether to configure KMAC to read a sideloaded key.
+ */
+void kmac_testutils_config(dif_kmac_t *kmac, bool sideload);
+
+/**
+ * Runs the full KMAC operation.
+ *
+ * Assumes that the KMAC block has already been initialized and configured, and
+ * that the sideloaded key has been loaded (if applicable).
+ *
+ * @param kmac KMAC block context
+ * @param mode Mode (security strength) for KMAC
+ * @param key KMAC key
+ * @param custom_string Customization string
+ * @param custom_string_len Length of customization string
+ * @param message Input message
+ * @param message_len Length of message in bytes
+ * @param output_len Requested length of output in words
+ * @param output Pre-allocated output buffer (length must match output_len)
+ */
+void kmac_testutils_kmac(const dif_kmac_t *kmac, dif_kmac_mode_kmac_t mode,
+                         const dif_kmac_key_t *key, const char *custom_string,
+                         const size_t custom_string_len, const char *message,
+                         const size_t message_len, const size_t output_len,
+                         uint32_t *output);
+
+#endif  // OPENTITAN_SW_DEVICE_LIB_TESTING_KMAC_TESTUTILS_H_
diff --git a/sw/device/tests/BUILD b/sw/device/tests/BUILD
index 7f58a7e..e658757 100644
--- a/sw/device/tests/BUILD
+++ b/sw/device/tests/BUILD
@@ -55,15 +55,10 @@
         "//sw/device/lib/base:mmio",
         "//sw/device/lib/dif:aes",
         "//sw/device/lib/dif:keymgr",
-        "//sw/device/lib/dif:kmac",
-        "//sw/device/lib/dif:otp_ctrl",
-        "//sw/device/lib/dif:rstmgr",
         "//sw/device/lib/runtime:log",
         "//sw/device/lib/testing:aes_testutils",
         "//sw/device/lib/testing:entropy_testutils",
         "//sw/device/lib/testing:keymgr_testutils",
-        "//sw/device/lib/testing:otp_ctrl_testutils",
-        "//sw/device/lib/testing:rstmgr_testutils",
         "//sw/device/lib/testing/test_framework:ottf_main",
     ],
 )
diff --git a/sw/device/tests/aes_sideload_test.c b/sw/device/tests/aes_sideload_test.c
index cfcbe50..d88eead 100644
--- a/sw/device/tests/aes_sideload_test.c
+++ b/sw/device/tests/aes_sideload_test.c
@@ -7,14 +7,11 @@
 #include "sw/device/lib/dif/dif_aes.h"
 #include "sw/device/lib/dif/dif_keymgr.h"
 #include "sw/device/lib/dif/dif_kmac.h"
-#include "sw/device/lib/dif/dif_otp_ctrl.h"
-#include "sw/device/lib/dif/dif_rstmgr.h"
 #include "sw/device/lib/runtime/log.h"
 #include "sw/device/lib/testing/aes_testutils.h"
 #include "sw/device/lib/testing/entropy_testutils.h"
 #include "sw/device/lib/testing/keymgr_testutils.h"
-#include "sw/device/lib/testing/otp_ctrl_testutils.h"
-#include "sw/device/lib/testing/rstmgr_testutils.h"
+#include "sw/device/lib/testing/kmac_testutils.h"
 #include "sw/device/lib/testing/test_framework/check.h"
 #include "sw/device/lib/testing/test_framework/ottf_main.h"
 
@@ -30,37 +27,18 @@
     0xffeeddcc,
 };
 static dif_keymgr_t keymgr;
+static dif_kmac_t kmac;
 
 OTTF_DEFINE_TEST_CONFIG();
 
 static void keymgr_initialize(void) {
-  mmio_region_t base_addr =
-      mmio_region_from_addr(TOP_EARLGREY_KEYMGR_BASE_ADDR);
-  CHECK_DIF_OK(dif_keymgr_init(base_addr, &keymgr));
-
-  keymgr_testutils_check_state(&keymgr, kDifKeymgrStateReset);
-
-  keymgr_testutils_advance_state(&keymgr, NULL);
-  keymgr_testutils_check_state(&keymgr, kDifKeymgrStateInitialized);
-  LOG_INFO("Keymgr entered Init State");
-
-  keymgr_testutils_advance_state(&keymgr, &kCreatorParams);
-  keymgr_testutils_check_state(&keymgr, kDifKeymgrStateCreatorRootKey);
-  LOG_INFO("Keymgr entered CreatorRootKey State");
-
-  keymgr_testutils_generate_identity(&keymgr);
-  LOG_INFO("Keymgr generated identity at CreatorRootKey State");
+  // Initialize keymgr and advance to CreatorRootKey state.
+  keymgr_testutils_startup(&keymgr, &kmac);
 
   keymgr_testutils_advance_state(&keymgr, &kOwnerIntParams);
   keymgr_testutils_check_state(&keymgr, kDifKeymgrStateOwnerIntermediateKey);
   LOG_INFO("Keymgr entered OwnerIntKey State");
 
-  keymgr_testutils_generate_identity(&keymgr);
-  LOG_INFO("Keymgr generated identity at OwnerIntKey State");
-
-  keymgr_testutils_generate_versioned_key(&keymgr, kKeyVersionedParams);
-  LOG_INFO("Keymgr generated SW output at OwnerIntKey State");
-
   dif_keymgr_versioned_key_params_t sideload_params = kKeyVersionedParams;
   sideload_params.dest = kDifKeymgrVersionedKeyDestAes;
   keymgr_testutils_generate_versioned_key(&keymgr, sideload_params);
@@ -143,42 +121,11 @@
 }
 
 bool test_main(void) {
-  dif_rstmgr_t rstmgr;
-  dif_rstmgr_reset_info_bitfield_t info;
+  // Configure the keymgr to generate an AES key.
+  keymgr_initialize();
 
-  CHECK_DIF_OK(dif_rstmgr_init(
-      mmio_region_from_addr(TOP_EARLGREY_RSTMGR_AON_BASE_ADDR), &rstmgr));
-  info = rstmgr_testutils_reason_get();
+  // Run the AES test.
+  aes_test();
 
-  // POR reset.
-  if (info == kDifRstmgrResetInfoPor) {
-    LOG_INFO("Powered up for the first time, program flash");
-
-    keymgr_testutils_init_flash();
-
-    // Lock otp secret partition.
-    dif_otp_ctrl_t otp;
-    CHECK_DIF_OK(dif_otp_ctrl_init(
-        mmio_region_from_addr(TOP_EARLGREY_OTP_CTRL_CORE_BASE_ADDR), &otp));
-    otp_ctrl_testutils_lock_partition(&otp, kDifOtpCtrlPartitionSecret2, 0);
-
-    // Reboot device.
-    rstmgr_testutils_reason_clear();
-    CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
-
-    // Wait here until device reset.
-    wait_for_interrupt();
-
-  } else if (info == kDifRstmgrResetInfoSw) {
-    LOG_INFO(
-        "Powered up for the second time, actuate keymgr and perform aes test.");
-
-    // Configure the keymgr to generate an aes key.
-    keymgr_initialize();
-
-    aes_test();
-    return true;
-  }
-
-  return false;
+  return true;
 }
diff --git a/sw/device/tests/sim_dv/BUILD b/sw/device/tests/sim_dv/BUILD
index 5e6e0f5..dd6f152 100644
--- a/sw/device/tests/sim_dv/BUILD
+++ b/sw/device/tests/sim_dv/BUILD
@@ -181,14 +181,30 @@
         "//sw/device/lib/base:macros",
         "//sw/device/lib/dif:keymgr",
         "//sw/device/lib/dif:kmac",
-        "//sw/device/lib/dif:otp_ctrl",
-        "//sw/device/lib/dif:rstmgr",
         "//sw/device/lib/runtime:hart",
         "//sw/device/lib/runtime:log",
         "//sw/device/lib/runtime:print",
         "//sw/device/lib/testing:keymgr_testutils",
-        "//sw/device/lib/testing:otp_ctrl_testutils",
-        "//sw/device/lib/testing:rstmgr_testutils",
+        "//sw/device/lib/testing/test_framework:ottf_main",
+    ],
+)
+
+opentitan_functest(
+    name = "keymgr_sideload_kmac_test",
+    srcs = ["keymgr_sideload_kmac_test.c"],
+    targets = ["dv"],
+    deps = [
+        "//hw/ip/keymgr/data:keymgr_regs",
+        "//hw/ip/kmac/data:kmac_regs",
+        "//sw/device/lib/arch:device",
+        "//sw/device/lib/base:macros",
+        "//sw/device/lib/dif:keymgr",
+        "//sw/device/lib/dif:kmac",
+        "//sw/device/lib/runtime:hart",
+        "//sw/device/lib/runtime:log",
+        "//sw/device/lib/runtime:print",
+        "//sw/device/lib/testing:keymgr_testutils",
+        "//sw/device/lib/testing:kmac_testutils",
         "//sw/device/lib/testing/test_framework:ottf_main",
     ],
 )
diff --git a/sw/device/tests/sim_dv/keymgr_key_derivation_test.c b/sw/device/tests/sim_dv/keymgr_key_derivation_test.c
index 47a7aca..110fa84 100644
--- a/sw/device/tests/sim_dv/keymgr_key_derivation_test.c
+++ b/sw/device/tests/sim_dv/keymgr_key_derivation_test.c
@@ -15,6 +15,7 @@
 #include "sw/device/lib/runtime/log.h"
 #include "sw/device/lib/runtime/print.h"
 #include "sw/device/lib/testing/keymgr_testutils.h"
+#include "sw/device/lib/testing/kmac_testutils.h"
 #include "sw/device/lib/testing/otp_ctrl_testutils.h"
 #include "sw/device/lib/testing/rstmgr_testutils.h"
 #include "sw/device/lib/testing/test_framework/check.h"
@@ -26,103 +27,42 @@
 
 OTTF_DEFINE_TEST_CONFIG();
 
-/** Place kmac into sideload mode for correct keymgr operation */
-static void init_kmac_for_keymgr(void) {
-  dif_kmac_t kmac;
-  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,
-      .sideload = true,
-  };
-  CHECK_DIF_OK(dif_kmac_configure(&kmac, config));
-}
-
 bool test_main(void) {
-  dif_rstmgr_t rstmgr;
-  dif_rstmgr_reset_info_bitfield_t info;
+  // Initialize keymgr and advance to CreatorRootKey state.
+  dif_keymgr_t keymgr;
+  dif_kmac_t kmac;
+  keymgr_testutils_startup(&keymgr, &kmac);
 
-  // Initialize pwrmgr
-  CHECK_DIF_OK(dif_rstmgr_init(
-      mmio_region_from_addr(TOP_EARLGREY_RSTMGR_AON_BASE_ADDR), &rstmgr));
-  info = rstmgr_testutils_reason_get();
+  keymgr_testutils_generate_identity(&keymgr);
+  LOG_INFO("Keymgr generated identity at CreatorRootKey State");
 
-  // POR reset
-  if (info == kDifRstmgrResetInfoPor) {
-    LOG_INFO("Powered up for the first time, program flash");
+  keymgr_testutils_advance_state(&keymgr, &kOwnerIntParams);
+  keymgr_testutils_check_state(&keymgr, kDifKeymgrStateOwnerIntermediateKey);
+  LOG_INFO("Keymgr entered OwnerIntKey State");
 
-    // Initialize flash
-    keymgr_testutils_init_flash();
+  keymgr_testutils_generate_identity(&keymgr);
+  LOG_INFO("Keymgr generated identity at OwnerIntKey State");
 
-    // Lock otp secret partition
-    dif_otp_ctrl_t otp;
-    CHECK_DIF_OK(dif_otp_ctrl_init(
-        mmio_region_from_addr(TOP_EARLGREY_OTP_CTRL_CORE_BASE_ADDR), &otp));
-    otp_ctrl_testutils_lock_partition(&otp, kDifOtpCtrlPartitionSecret2, 0);
+  keymgr_testutils_generate_versioned_key(&keymgr, kKeyVersionedParams);
+  LOG_INFO("Keymgr generated SW output at OwnerIntKey State");
 
-    // reboot device
-    rstmgr_testutils_reason_clear();
-    CHECK_DIF_OK(dif_rstmgr_software_device_reset(&rstmgr));
+  // Generate sideload keys for 3 HW interfaces - Kmac, Aes, Otbn.
+  dif_keymgr_versioned_key_params_t sideload_params = kKeyVersionedParams;
+  sideload_params.dest = kDifKeymgrVersionedKeyDestKmac;
+  keymgr_testutils_generate_versioned_key(&keymgr, sideload_params);
+  LOG_INFO("Keymgr generated HW output for Kmac at OwnerIntKey State");
 
-    // wait here until device reset
-    wait_for_interrupt();
+  sideload_params.dest = kDifKeymgrVersionedKeyDestAes;
+  keymgr_testutils_generate_versioned_key(&keymgr, sideload_params);
+  LOG_INFO("Keymgr generated HW output for Aes at OwnerIntKey State");
 
-  } else if (info == kDifRstmgrResetInfoSw) {
-    LOG_INFO("Powered up for the second time, actuate keymgr");
+  sideload_params.dest = kDifKeymgrVersionedKeyDestOtbn;
+  keymgr_testutils_generate_versioned_key(&keymgr, sideload_params);
+  LOG_INFO("Keymgr generated HW output for Otbn at OwnerIntKey State");
 
-    init_kmac_for_keymgr();
+  keymgr_testutils_disable(&keymgr);
+  keymgr_testutils_check_state(&keymgr, kDifKeymgrStateDisabled);
+  LOG_INFO("Keymgr entered Disabled state");
 
-    dif_keymgr_t keymgr;
-    CHECK_DIF_OK(dif_keymgr_init(
-        mmio_region_from_addr(TOP_EARLGREY_KEYMGR_BASE_ADDR), &keymgr));
-
-    keymgr_testutils_check_state(&keymgr, kDifKeymgrStateReset);
-
-    keymgr_testutils_advance_state(&keymgr, NULL);
-    keymgr_testutils_check_state(&keymgr, kDifKeymgrStateInitialized);
-    LOG_INFO("Keymgr entered Init State");
-
-    keymgr_testutils_advance_state(&keymgr, &kCreatorParams);
-    keymgr_testutils_check_state(&keymgr, kDifKeymgrStateCreatorRootKey);
-    LOG_INFO("Keymgr entered CreatorRootKey State");
-
-    keymgr_testutils_generate_identity(&keymgr);
-    LOG_INFO("Keymgr generated identity at CreatorRootKey State");
-
-    keymgr_testutils_advance_state(&keymgr, &kOwnerIntParams);
-    keymgr_testutils_check_state(&keymgr, kDifKeymgrStateOwnerIntermediateKey);
-    LOG_INFO("Keymgr entered OwnerIntKey State");
-
-    keymgr_testutils_generate_identity(&keymgr);
-    LOG_INFO("Keymgr generated identity at OwnerIntKey State");
-
-    keymgr_testutils_generate_versioned_key(&keymgr, kKeyVersionedParams);
-    LOG_INFO("Keymgr generated SW output at OwnerIntKey State");
-
-    // Generate sideload keys for 3 HW interfaces - Kmac, Aes, Otbn.
-    dif_keymgr_versioned_key_params_t sideload_params = kKeyVersionedParams;
-    sideload_params.dest = kDifKeymgrVersionedKeyDestKmac;
-    keymgr_testutils_generate_versioned_key(&keymgr, sideload_params);
-    LOG_INFO("Keymgr generated HW output for Kmac at OwnerIntKey State");
-
-    sideload_params.dest = kDifKeymgrVersionedKeyDestAes;
-    keymgr_testutils_generate_versioned_key(&keymgr, sideload_params);
-    LOG_INFO("Keymgr generated HW output for Aes at OwnerIntKey State");
-
-    sideload_params.dest = kDifKeymgrVersionedKeyDestOtbn;
-    keymgr_testutils_generate_versioned_key(&keymgr, sideload_params);
-    LOG_INFO("Keymgr generated HW output for Otbn at OwnerIntKey State");
-
-    keymgr_testutils_disable(&keymgr);
-    keymgr_testutils_check_state(&keymgr, kDifKeymgrStateDisabled);
-    LOG_INFO("Keymgr entered Disabled state");
-
-    return true;
-  } else {
-    LOG_FATAL("Unexpected reset reason unexpected: %0x", info);
-  }
-
-  return false;
+  return true;
 }
diff --git a/sw/device/tests/sim_dv/keymgr_sideload_kmac_test.c b/sw/device/tests/sim_dv/keymgr_sideload_kmac_test.c
new file mode 100644
index 0000000..7992df8
--- /dev/null
+++ b/sw/device/tests/sim_dv/keymgr_sideload_kmac_test.c
@@ -0,0 +1,108 @@
+// 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 <stdint.h>
+
+#include "sw/device/lib/arch/device.h"
+#include "sw/device/lib/base/macros.h"
+#include "sw/device/lib/dif/dif_keymgr.h"
+#include "sw/device/lib/dif/dif_kmac.h"
+#include "sw/device/lib/runtime/hart.h"
+#include "sw/device/lib/runtime/log.h"
+#include "sw/device/lib/runtime/print.h"
+#include "sw/device/lib/testing/keymgr_testutils.h"
+#include "sw/device/lib/testing/kmac_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"
+#include "keymgr_regs.h"  // Generated.
+#include "kmac_regs.h"    // Generated.
+
+// The KMAC dif expects a secret key, even though if the configuration is set
+// to use the sideloaded key then it will be ignored. We will write a software
+// key and then ensure that the output does NOT match the expected value for
+// this key when sideloading is used.
+//
+// Test taken from sample #1 here:
+// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/KMAC_samples.pdf
+static const dif_kmac_key_t kSoftwareKey = {
+    .share0 = {0x43424140, 0x47464544, 0x4B4A4948, 0x4F4E4D4C, 0x53525150,
+               0x57565554, 0x5B5A5958, 0x5F5E5D5C},
+    .share1 = {0},
+    .length = kDifKmacKeyLen256,
+};
+static const dif_kmac_mode_kmac_t kKmacMode = kDifKmacModeKmacLen128;
+static const size_t kKmacOutputLen = 8;
+static const uint32_t kSoftwareKeyExpectedOutput[8] = {
+    0x0D0B78E5, 0xD3F7A63E, 0x70C529A4, 0x003AA46A,
+    0xD4D7DBFA, 0x9E832896, 0x3F248731, 0x4EE16E45};
+static const char *kCustomString = NULL;
+static const size_t kCustomStringLen = 0;
+static const char kKmacMessage[] = "\x00\x01\x02\x03";
+static const size_t kKmacMessageLen = 4;
+
+OTTF_DEFINE_TEST_CONFIG();
+
+/**
+ * Initialize and run KMAC using a sideloaded key.
+ *
+ * First, checks that KMAC works with the software key. Next, checks that when
+ * sideload=true, KMAC produces a different result.
+ */
+static void test_kmac_with_sideloaded_key(dif_keymgr_t *keymgr,
+                                          dif_kmac_t *kmac) {
+  // Configure KMAC hardware (using software key and software entropy).
+  kmac_testutils_config(kmac, false);
+
+  uint32_t output[kKmacOutputLen];
+  kmac_testutils_kmac(kmac, kKmacMode, &kSoftwareKey, kCustomString,
+                      kCustomStringLen, kKmacMessage, kKmacMessageLen,
+                      kKmacOutputLen, output);
+  LOG_INFO("Computed KMAC output for software key.");
+
+  // Check that the output matches the expected output.
+  CHECK_ARRAYS_EQ(output, kSoftwareKeyExpectedOutput, kKmacOutputLen);
+
+  // Reconfigure KMAC to use the sideloaded key.
+  kmac_testutils_config(kmac, true);
+
+  // Generate the sideloaded key.
+  dif_keymgr_versioned_key_params_t sideload_params = kKeyVersionedParams;
+  sideload_params.dest = kDifKeymgrVersionedKeyDestKmac;
+  keymgr_testutils_generate_versioned_key(keymgr, sideload_params);
+  LOG_INFO("Keymgr generated HW output for KMAC.");
+
+  kmac_testutils_kmac(kmac, kKmacMode, &kSoftwareKey, kCustomString,
+                      kCustomStringLen, kKmacMessage, kKmacMessageLen,
+                      kKmacOutputLen, output);
+  LOG_INFO("Computed KMAC output for sideloaded key.");
+
+  // Check that the output is different from the software key output
+  // (indicating the software key was not used).
+  //
+  // TODO(weicai): also check in SV sequence that the KMAC output is correct.
+  CHECK_ARRAYS_NE(output, kSoftwareKeyExpectedOutput, kKmacOutputLen);
+}
+
+bool test_main(void) {
+  // Initialize keymgr and advance to CreatorRootKey state.
+  dif_keymgr_t keymgr;
+  dif_kmac_t kmac;
+  keymgr_testutils_startup(&keymgr, &kmac);
+
+  // Test KMAC sideloading.
+  test_kmac_with_sideloaded_key(&keymgr, &kmac);
+
+  // Advance to OwnerIntKey state.
+  keymgr_testutils_advance_state(&keymgr, &kOwnerIntParams);
+  keymgr_testutils_check_state(&keymgr, kDifKeymgrStateOwnerIntermediateKey);
+  LOG_INFO("Keymgr entered OwnerIntKey State");
+
+  // Test KMAC sideloading.
+  test_kmac_with_sideloaded_key(&keymgr, &kmac);
+
+  return true;
+}