-
Notifications
You must be signed in to change notification settings - Fork 792
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[sival/aes] Add aes_prng_reseed,aes_prng_force_reseed
This commit introduces the AES PRNG reseed test and AES FORCE PRNG reseed, to handle the reseed process by disabling entrpy complex and triggering PRNG reseed accordingly. The tests follows procedure as per description mentioned in chip_aes_testplan.hjson: aes_force_prng_reseed: https://github.com/github-gcontributor/opentitan/blob/master/hw/top_earlgrey/data/ip/chip_aes_testplan.hjson#L185 aes_prng_reseed: https://github.com/github-gcontributor/opentitan/blob/master/hw/top_earlgrey/data/ip/chip_aes_testplan.hjson#L145 Number of blocks set to 68 (4 more to see if tests auto generates reseed post 64Block) Added aes_process_data() functoin to process first two blocks of data as per test description Remove the trigger prng reseed (Not required for Auto test) Commenting out the enabling of the entropy complex at block 32 -- correct test procedure (Enable once entire 64 block of data is processed) Do not generate new key while running the test (as per auto mode should do it on its own) Enabling the entropy complex only after entire encryption process completes (after 68 blocks) -- correct procedure. Remove code dif_aes_end, new_key_generation and dif_aes_start - incorrect logic for auto mode Remove check for Stall signal bit set (remove Stall check logic from the code) -- as per correct procedure of the test After entropy disabled, wait for output valid normally Create CL for "Change of test case description-aes_prng_reseed_test" --> Ambiguity in interpreting encryption stalling with STALL register bit Created issue: #24857 Create CL for "Clarification needed on PRNG_RESEED_RATE PER_64 behavior in aes_prng_reseed_test" #24899 Signed-off-by: Varunkumar Trivedi <[email protected]>
- Loading branch information
1 parent
7fad7db
commit befede4
Showing
3 changed files
with
523 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,222 @@ | ||
// Copyright lowRISC contributors (OpenTitan project). | ||
// Licensed under the Apache License, Version 2.0, see LICENSE for details. | ||
// SPDX-License-Identifier: Apache-2.0 | ||
|
||
#include "hw/ip/aes/model/aes_modes.h" | ||
#include "sw/device/lib/base/memory.h" | ||
#include "sw/device/lib/base/mmio.h" | ||
#include "sw/device/lib/base/multibits.h" | ||
#include "sw/device/lib/dif/dif_aes.h" | ||
#include "sw/device/lib/dif/dif_csrng.h" | ||
#include "sw/device/lib/dif/dif_csrng_shared.h" | ||
#include "sw/device/lib/dif/dif_edn.h" | ||
#include "sw/device/lib/dif/dif_entropy_src.h" | ||
#include "sw/device/lib/dif/dif_rv_core_ibex.h" | ||
#include "sw/device/lib/runtime/hart.h" | ||
#include "sw/device/lib/runtime/log.h" | ||
#include "sw/device/lib/testing/aes_testutils.h" | ||
#include "sw/device/lib/testing/csrng_testutils.h" | ||
#include "sw/device/lib/testing/entropy_testutils.h" | ||
#include "sw/device/lib/testing/rv_core_ibex_testutils.h" | ||
#include "sw/device/lib/testing/test_framework/check.h" | ||
#include "sw/device/lib/testing/test_framework/ottf_main.h" | ||
#include "sw/device/sca/lib/simple_serial.h" | ||
|
||
#include "hw/top_earlgrey/sw/autogen/top_earlgrey.h" | ||
|
||
OTTF_DEFINE_TEST_CONFIG(); | ||
|
||
static dif_aes_t aes; | ||
dif_aes_transaction_t transaction; | ||
dif_aes_key_share_t key; | ||
enum { | ||
kAesNumBlocks = 8, | ||
// NumBytes in one block is 4x8 i.e. 32 bits in 1 block | ||
kDifAesBlockNumBytes = 4, | ||
disable_entropy_at_start_en = 1, | ||
}; | ||
|
||
static const uint8_t kKeyShare1[16] = { | ||
0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f, | ||
0x8f, 0x9f, 0xaf, 0xbf, 0xcf, 0xdf, 0xef, 0xff, | ||
}; | ||
|
||
/////////////////////////////////////////////////////////////////////////////// | ||
static dif_edn_t edn0, edn1; | ||
static dif_csrng_t csrng; | ||
static dif_entropy_src_t entropy_src; | ||
|
||
// Function to disable entropy complex | ||
status_t disable_entropy_complex(void) { | ||
// Using entropy test utility to stop all EDN0, EDN1, CSRNG, and the Entropy | ||
// Source | ||
TRY(entropy_testutils_stop_all()); | ||
LOG_INFO("The entire entropy complex is stopped"); | ||
return OK_STATUS(); | ||
} | ||
|
||
// Function to enable entropy complex | ||
status_t enable_entropy_complex(void) { | ||
// Using entropy test utility to enable all EDN0, EDN1, CSRNG, and the | ||
// Entropy Source | ||
TRY(entropy_testutils_auto_mode_init()); | ||
LOG_INFO("The entire entropy complex is enabled"); | ||
return OK_STATUS(); | ||
} | ||
|
||
// Function to generate a new key based on provided index value | ||
void generate_new_key(dif_aes_key_share_t *key, int index) { | ||
uint8_t new_key_share0[sizeof(kAesModesKey128)]; | ||
// Generate new key share0 by XOR-ing base key with kKeyShare1*index | ||
for (size_t i = 0; i < sizeof(kAesModesKey128); ++i) { | ||
new_key_share0[i] = kAesModesKey128[i] ^ kKeyShare1[i] * (uint8_t)(index); | ||
} | ||
// Update the key shares | ||
memcpy(key->share0, new_key_share0, sizeof(key->share0)); | ||
memcpy(key->share1, kKeyShare1, sizeof(key->share1)); | ||
} | ||
|
||
status_t execute_test(void) { | ||
bool aes_idle = false; | ||
bool input_ready = false; | ||
bool output_valid = false; | ||
|
||
LOG_INFO( | ||
"Testing aes_prng_reseed_test with number of blocks: %d (Block 0 to %d), " | ||
"and disabling entropy at start enable" | ||
": %d", | ||
kAesNumBlocks, kAesNumBlocks - 1, disable_entropy_at_start_en); | ||
// Initialize AES | ||
CHECK_DIF_OK( | ||
dif_aes_init(mmio_region_from_addr(TOP_EARLGREY_AES_BASE_ADDR), &aes)); | ||
CHECK_DIF_OK(dif_aes_reset(&aes)); | ||
// Initialize EDN0, EDN1, CSRNG and Entropy Source | ||
CHECK_DIF_OK( | ||
dif_edn_init(mmio_region_from_addr(TOP_EARLGREY_EDN0_BASE_ADDR), &edn0)); | ||
CHECK_DIF_OK( | ||
dif_edn_init(mmio_region_from_addr(TOP_EARLGREY_EDN1_BASE_ADDR), &edn1)); | ||
CHECK_DIF_OK(dif_csrng_init( | ||
mmio_region_from_addr(TOP_EARLGREY_CSRNG_BASE_ADDR), &csrng)); | ||
CHECK_DIF_OK(dif_entropy_src_init( | ||
mmio_region_from_addr(TOP_EARLGREY_ENTROPY_SRC_BASE_ADDR), &entropy_src)); | ||
|
||
// Generate key with index 0 | ||
generate_new_key(&key, 0); | ||
|
||
// Prepare transaction | ||
transaction.operation = kDifAesOperationEncrypt; | ||
transaction.mode = kDifAesModeEcb; | ||
transaction.key_len = kDifAesKey128; | ||
transaction.key_provider = kDifAesKeySoftwareProvided; | ||
transaction.mask_reseeding = kDifAesReseedPerBlock; | ||
transaction.manual_operation = kDifAesManualOperationManual; | ||
transaction.reseed_on_key_change = true; | ||
transaction.force_masks = true; | ||
transaction.ctrl_aux_lock = false; | ||
|
||
if (disable_entropy_at_start_en == 1) { | ||
LOG_INFO( | ||
"Disabling entropy complex to induce AES stall before starting AES"); | ||
CHECK_STATUS_OK(disable_entropy_complex()); | ||
busy_spin_micros(500); | ||
} | ||
|
||
// Start the AES operation | ||
// Wait for AES to be idle before starting encryption | ||
aes_idle = false; | ||
do { | ||
CHECK_DIF_OK(dif_aes_get_status(&aes, kDifAesStatusIdle, &aes_idle)); | ||
} while (!aes_idle); | ||
|
||
CHECK_DIF_OK(dif_aes_start(&aes, &transaction, &key, NULL)); | ||
|
||
dif_aes_data_t plain_text[kAesNumBlocks]; | ||
dif_aes_data_t cipher_text[kAesNumBlocks]; | ||
|
||
// Initialize plaintext data dynamically | ||
// Create plaintext with incremental data | ||
for (int i = 0; i < kAesNumBlocks; ++i) { | ||
for (int j = 0; j < kDifAesBlockNumBytes; ++j) { | ||
plain_text[i].data[j] = (uint8_t)((i * kDifAesBlockNumBytes + j) & 0xFF); | ||
} | ||
} | ||
|
||
// Start encryption process | ||
for (int i = 0; i < kAesNumBlocks; ++i) { | ||
if (transaction.manual_operation == kDifAesManualOperationManual) { | ||
// Wait for AES to be idle before starting encryption | ||
CHECK_DIF_OK(dif_aes_trigger(&aes, kDifAesTriggerPrngReseed)); | ||
} | ||
|
||
// Wait for input ready | ||
input_ready = false; | ||
do { | ||
CHECK_DIF_OK( | ||
dif_aes_get_status(&aes, kDifAesStatusInputReady, &input_ready)); | ||
} while (!input_ready); | ||
|
||
// Load data | ||
CHECK_DIF_OK(dif_aes_load_data(&aes, plain_text[i])); | ||
|
||
// Trigger AES reseed request, specific for manual operation case as per | ||
// documentation | ||
if (transaction.manual_operation == kDifAesManualOperationManual) { | ||
CHECK_DIF_OK(dif_aes_trigger(&aes, kDifAesTriggerStart)); | ||
} | ||
|
||
// Check for stall after entropy disabled | ||
if (i == 0 && disable_entropy_at_start_en == 1) { | ||
LOG_INFO( | ||
"Checking AES status OutputValid status after stopping " | ||
"EDN and CSRNG"); | ||
output_valid = false; | ||
CHECK_DIF_OK( | ||
dif_aes_get_status(&aes, kDifAesStatusOutputValid, &output_valid)); | ||
if (output_valid) { | ||
LOG_ERROR( | ||
"ERROR:AES encryption generated output_valid after stopping " | ||
"entropy indicating no stall!"); | ||
} else { | ||
LOG_INFO( | ||
"AES encryption is waiting for output_valid as expected at block " | ||
"%d", | ||
i); | ||
} | ||
|
||
CHECK_STATUS_OK(enable_entropy_complex()); | ||
busy_spin_micros(500); | ||
} | ||
|
||
// Wait for the AES module to resume and produce output valid | ||
output_valid = false; | ||
do { | ||
CHECK_DIF_OK( | ||
dif_aes_get_status(&aes, kDifAesStatusOutputValid, &output_valid)); | ||
} while (!output_valid); | ||
|
||
// Read output data | ||
CHECK_DIF_OK(dif_aes_read_output(&aes, &cipher_text[i])); | ||
// LOG_INFO("BLOCK completed: %d",i); | ||
} | ||
|
||
LOG_INFO("cipher_text data generated successfully"); | ||
|
||
// Finish the AES encryption operation | ||
LOG_INFO("End AES encryption operation"); | ||
CHECK_DIF_OK(dif_aes_end(&aes)); | ||
|
||
// Wait for AES to be idle before starting decryption | ||
aes_idle = false; | ||
do { | ||
CHECK_DIF_OK(dif_aes_get_status(&aes, kDifAesStatusIdle, &aes_idle)); | ||
} while (!aes_idle); | ||
LOG_INFO("AES module is idle"); | ||
|
||
return OK_STATUS(); | ||
} | ||
|
||
bool test_main(void) { | ||
LOG_INFO("Entering AES aes_force_prng_reseed_test Test"); | ||
|
||
return status_ok(execute_test()); | ||
} |
Oops, something went wrong.