Skip to content

Commit c2beaf4

Browse files
committed
[OCP-LOCK] Enable encryption engine interacting tests on subsystem FPGA
- Enable DERIVE_MEK tests (#3362) - Enable CLEAR_KEY_CACHE tests - Enable LOAD_MEK tests - Enable UNLOAD_MEK tests
1 parent e093107 commit c2beaf4

7 files changed

Lines changed: 183 additions & 28 deletions

File tree

drivers/src/dma.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,18 +1176,31 @@ bitfield! {
11761176
command_code, set_command_code: 5, 2;
11771177
error_code, _: 19, 16;
11781178
ready_bit, _: 31;
1179+
1180+
#[cfg(any(feature = "fpga_realtime", feature = "fpga_subsystem"))]
1181+
_, set_ready_bit: 31;
11791182
}
11801183
impl EncryptionEngineCtrl {
11811184
fn clear() -> Self {
11821185
let mut ctrl = Self(0);
11831186
ctrl.set_done_bit(true);
1187+
1188+
// To maintain the RDY bit to be set
1189+
#[cfg(any(feature = "fpga_realtime", feature = "fpga_subsystem"))]
1190+
ctrl.set_ready_bit(true);
1191+
11841192
ctrl
11851193
}
11861194

11871195
fn execute(cmd: EncryptionEngineCommandCode) -> Self {
11881196
let mut ctrl = Self(0);
11891197
ctrl.set_command_code(cmd.into());
11901198
ctrl.set_execute_bit(true);
1199+
1200+
// To maintain the RDY bit to be set
1201+
#[cfg(any(feature = "fpga_realtime", feature = "fpga_subsystem"))]
1202+
ctrl.set_ready_bit(true);
1203+
11911204
ctrl
11921205
}
11931206
}

hw-model/src/fpga_regs.rs

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,27 @@ register_bitfields! {
6969
pub FlashCtrlRegwen [
7070
EN OFFSET(0) NUMBITS(1) [],
7171
],
72+
pub EncryptionEngineControl [
73+
EXE OFFSET(0) NUMBITS(1) [
74+
IDLE = 0,
75+
RUN = 1,
76+
],
77+
DONE OFFSET(1) NUMBITS(1) [
78+
DONE = 1,
79+
],
80+
CMD OFFSET(2) NUMBITS(4) [
81+
LOAD_MEK = 1,
82+
UNLOAD_MEK = 2,
83+
ZEROIZE = 3,
84+
],
85+
ERR OFFSET(16) NUMBITS(4) [
86+
NO_ERROR = 0,
87+
INVALID_COMMAND = 1,
88+
],
89+
RDY OFFSET(31) NUMBITS(1) [
90+
READY = 1,
91+
]
92+
],
7293
}
7394

7495
register_structs! {
@@ -131,6 +152,10 @@ register_structs! {
131152
(0x14c => pub cptr_ss_raw_unlock_token_hash: [ReadWrite<u32>; 4]),
132153
(0x15c => _reserved1),
133154
(0x200 => pub ocp_lock_key_release_reg: [ReadWrite<u32>; 16]),
134-
(0x240 => @END),
155+
(0x240 => pub ocp_lock_metadata_reg: [ReadWrite<u32>; 5]),
156+
(0x254 => _reserved2),
157+
(0x260 => pub ocp_lock_auxiliary_data_reg: [ReadWrite<u32>; 8]),
158+
(0x280 => pub ocp_lock_control_reg: ReadWrite<u32, EncryptionEngineControl::Register>),
159+
(0x284 => @END),
135160
}
136161
}

hw-model/src/model_fpga_subsystem.rs

Lines changed: 118 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use crate::api_types::{DeviceLifecycle, Fuses};
77
use crate::bmc::Bmc;
88
use crate::fpga_regs::{
99
Control, FifoData, FifoRegs, FifoStatus, FlashControl, FlashCtrlRegs, FlashOpStatus,
10-
ItrngFifoStatus, WrapperRegs,
10+
ItrngFifoStatus, WrapperRegs, EncryptionEngineControl,
1111
};
1212
use crate::keys::{DEFAULT_LIFECYCLE_RAW_TOKENS, DEFAULT_MANUF_DEBUG_UNLOCK_RAW_TOKEN};
1313
use crate::mcu_boot_status::McuBootMilestones;
@@ -24,11 +24,13 @@ use crate::{
2424
use crate::{OcpLockState, SecurityState};
2525
use anyhow::Result;
2626
use caliptra_api::SocManager;
27+
use caliptra_api::mailbox::{OCP_LOCK_ENCRYPTION_ENGINE_MAX_MEK_SIZE, OCP_LOCK_ENCRYPTION_ENGINE_METADATA_SIZE, OCP_LOCK_ENCRYPTION_ENGINE_AUX_SIZE};
2728
use caliptra_emu_bus::{Bus, BusError, BusMmio, Device, Event, EventData, RecoveryCommandCode};
2829
use caliptra_emu_types::{RvAddr, RvData, RvSize};
2930
use caliptra_hw_model_types::HexSlice;
3031
use caliptra_image_types::FwVerificationPqcKeyType;
3132
use sensitive_mmio::{SensitiveMmio, SensitiveMmioArgs};
33+
use std::collections::HashMap;
3234
use std::io::Write;
3335
use std::marker::PhantomData;
3436
use std::sync::atomic::{AtomicBool, Ordering};
@@ -469,6 +471,11 @@ pub struct ModelFpgaSubsystem {
469471
saved_ocp_lock_en: bool,
470472
saved_security_state: SecurityState,
471473
saved_lc_state: Option<LifecycleControllerState>,
474+
475+
// OCP LOCK encryption engine FPGA emulator
476+
pub realtime_encryption_engine: Option<thread::JoinHandle<()>>,
477+
pub realtime_encryption_engine_exit_flag: Arc<AtomicBool>,
478+
pub realtime_encryption_engine_paused: Arc<AtomicBool>,
472479
}
473480

474481
impl ModelFpgaSubsystem {
@@ -902,6 +909,93 @@ impl ModelFpgaSubsystem {
902909
}
903910
}
904911

912+
fn realtime_encryption_engine_register_handler(
913+
wrapper: Arc<Wrapper>,
914+
running: Arc<AtomicBool>,
915+
paused: Arc<AtomicBool>,
916+
) {
917+
type Mek = [u32; OCP_LOCK_ENCRYPTION_ENGINE_MAX_MEK_SIZE / size_of::<u32>()];
918+
type Metadata = [u32; OCP_LOCK_ENCRYPTION_ENGINE_METADATA_SIZE / size_of::<u32>()];
919+
type Aux = [u32; OCP_LOCK_ENCRYPTION_ENGINE_AUX_SIZE / size_of::<u32>()];
920+
921+
enum EncryptionEngineState {
922+
WaitCommand,
923+
WaitClear,
924+
}
925+
926+
let mut key_cache: HashMap<Metadata, (Aux, Mek)> = HashMap::new();
927+
let mut internal_state: EncryptionEngineState = EncryptionEngineState::WaitCommand;
928+
let mut prev_cmd: u32 = 0;
929+
930+
wrapper
931+
.regs()
932+
.ocp_lock_control_reg
933+
.write(EncryptionEngineControl::RDY::READY);
934+
935+
// Small delay to allow reset to complete
936+
thread::sleep(Duration::from_millis(1));
937+
938+
while running.load(Ordering::Relaxed) {
939+
// To maintain the ready bit
940+
wrapper
941+
.regs()
942+
.ocp_lock_control_reg
943+
.modify(EncryptionEngineControl::RDY::READY);
944+
945+
// If paused, sleep and check again
946+
if paused.load(Ordering::Relaxed) {
947+
thread::sleep(Duration::from_millis(1));
948+
continue;
949+
}
950+
951+
match internal_state {
952+
EncryptionEngineState::WaitCommand => {
953+
let mut cmd = wrapper.regs().ocp_lock_control_reg.extract();
954+
if cmd.is_set(EncryptionEngineControl::EXE) {
955+
match cmd.read_as_enum::<EncryptionEngineControl::CMD::Value>(EncryptionEngineControl::CMD) {
956+
Some(EncryptionEngineControl::CMD::Value::LOAD_MEK) => {
957+
let metadata: Metadata = wrapper.regs().ocp_lock_metadata_reg.each_ref().map(|r| r.get());
958+
let aux: Aux = wrapper.regs().ocp_lock_auxiliary_data_reg.each_ref().map(|r| r.get());
959+
let mek: Mek = wrapper.regs().ocp_lock_key_release_reg.each_ref().map(|r| r.get());
960+
key_cache.insert(metadata, (aux, mek));
961+
962+
cmd.modify(EncryptionEngineControl::ERR::NO_ERROR);
963+
},
964+
Some(EncryptionEngineControl::CMD::Value::UNLOAD_MEK) => {
965+
let metadata: Metadata = wrapper.regs().ocp_lock_metadata_reg.each_ref().map(|r| r.get());
966+
key_cache.remove(&metadata);
967+
968+
cmd.modify(EncryptionEngineControl::ERR::NO_ERROR);
969+
},
970+
Some(EncryptionEngineControl::CMD::Value::ZEROIZE) => {
971+
key_cache.clear();
972+
973+
cmd.modify(EncryptionEngineControl::ERR::NO_ERROR);
974+
},
975+
_ => {
976+
cmd.modify(EncryptionEngineControl::ERR::INVALID_COMMAND);
977+
},
978+
};
979+
cmd.modify(EncryptionEngineControl::DONE::DONE + EncryptionEngineControl::EXE::IDLE + EncryptionEngineControl::RDY::READY);
980+
981+
prev_cmd = cmd.get();
982+
wrapper.regs().ocp_lock_control_reg.set(prev_cmd);
983+
internal_state = EncryptionEngineState::WaitClear;
984+
}
985+
},
986+
EncryptionEngineState::WaitClear => {
987+
let cmd = wrapper.regs().ocp_lock_control_reg.extract();
988+
if cmd.get() != prev_cmd && cmd.is_set(EncryptionEngineControl::DONE) {
989+
wrapper.regs().ocp_lock_control_reg.write(EncryptionEngineControl::RDY::READY);
990+
internal_state = EncryptionEngineState::WaitCommand;
991+
}
992+
},
993+
}
994+
995+
thread::sleep(Duration::from_millis(1));
996+
}
997+
}
998+
905999
pub fn i3c_core(
9061000
&mut self,
9071001
) -> Option<caliptra_registers::i3ccsr::RegisterBlock<BusMmio<FpgaRealtimeBus<'_>>>> {
@@ -1852,6 +1946,12 @@ impl HwModel for ModelFpgaSubsystem {
18521946
let realtime_thread_paused2 = realtime_thread_paused.clone();
18531947
let realtime_wrapper = wrapper.clone();
18541948

1949+
let realtime_encryption_engine_exit_flag = Arc::new(AtomicBool::new(true));
1950+
let realtime_encryption_engine_exit_flag2 = realtime_encryption_engine_exit_flag.clone();
1951+
let realtime_encryption_engine_paused = Arc::new(AtomicBool::new(false));
1952+
let realtime_encryption_engine_paused2 = realtime_encryption_engine_paused.clone();
1953+
let realtime_wrapper_for_encryption_engine = wrapper.clone();
1954+
18551955
let xi3c_config = xi3c::Config {
18561956
device_id: 0,
18571957
base_address: i3c_controller_mmio,
@@ -1954,6 +2054,10 @@ impl HwModel for ModelFpgaSubsystem {
19542054
saved_ocp_lock_en: params.ocp_lock_en,
19552055
saved_security_state: params.security_state,
19562056
saved_lc_state: params.ss_init_params.lc_state,
2057+
2058+
realtime_encryption_engine: None,
2059+
realtime_encryption_engine_exit_flag,
2060+
realtime_encryption_engine_paused,
19572061
};
19582062

19592063
println!("AXI reset");
@@ -1970,6 +2074,14 @@ impl HwModel for ModelFpgaSubsystem {
19702074
)
19712075
}));
19722076

2077+
m.realtime_encryption_engine = Some(std::thread::spawn(move || {
2078+
Self::realtime_encryption_engine_register_handler(
2079+
realtime_wrapper_for_encryption_engine,
2080+
realtime_encryption_engine_exit_flag2,
2081+
realtime_encryption_engine_paused2,
2082+
)
2083+
}));
2084+
19732085
// Copy the ROM data (only needed on first init; survives AXI reset)
19742086
println!("Writing Caliptra ROM");
19752087
let mut caliptra_rom_data = vec![0; caliptra_rom_size];
@@ -2498,6 +2610,7 @@ impl HwModel for ModelFpgaSubsystem {
24982610

24992611
// Pause the TRNG thread so it doesn't access the AXI bus during reset
25002612
self.realtime_thread_paused.store(true, Ordering::Relaxed);
2613+
self.realtime_encryption_engine_paused.store(true, Ordering::Relaxed);
25012614
std::thread::sleep(Duration::from_millis(2));
25022615

25032616
// Full AXI reset to clear all subsystem state including MCU
@@ -2509,6 +2622,7 @@ impl HwModel for ModelFpgaSubsystem {
25092622

25102623
// Resume the TRNG thread
25112624
self.realtime_thread_paused.store(false, Ordering::Relaxed);
2625+
self.realtime_encryption_engine_paused.store(false, Ordering::Relaxed);
25122626
}
25132627

25142628
fn fuses(&self) -> &Fuses {
@@ -2619,6 +2733,9 @@ impl Drop for ModelFpgaSubsystem {
26192733
.lock()
26202734
.unwrap()
26212735
.off();
2736+
self.realtime_encryption_engine_exit_flag
2737+
.store(false, Ordering::Relaxed);
2738+
self.realtime_encryption_engine.take().unwrap().join().unwrap();
26222739

26232740
self.set_subsystem_reset(true);
26242741

runtime/tests/runtime_integration_tests/test_ocp_lock/test_clear_key_cache.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use super::{
1212
boot_ocp_lock_runtime, validate_ocp_lock_response, InitializeMekSecretParams, OcpLockBootParams,
1313
};
1414

15-
#[cfg(not(any(feature = "fpga_realtime", feature = "fpga_subsystem")))]
15+
#[cfg(not(feature = "fpga_realtime"))]
1616
#[test]
1717
fn test_clear_key_cache_success() {
1818
let mut model = boot_ocp_lock_runtime(OcpLockBootParams {
@@ -60,7 +60,7 @@ fn test_clear_key_cache_success() {
6060
});
6161
}
6262

63-
#[cfg(not(any(feature = "fpga_realtime", feature = "fpga_subsystem")))]
63+
#[cfg(not(feature = "fpga_realtime"))]
6464
#[test]
6565
fn test_clear_key_cache_command_timeout() {
6666
let mut model = boot_ocp_lock_runtime(OcpLockBootParams {

runtime/tests/runtime_integration_tests/test_ocp_lock/test_derive_mek.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ static EXPECTED_MEK: LazyLock<Mek> = LazyLock::new(|| {
4444
});
4545

4646
// TODO(clundin): Make tests work on emulator.
47-
#[cfg(not(any(feature = "fpga_realtime", feature = "fpga_subsystem")))]
47+
#[cfg(not(feature = "fpga_realtime"))]
4848
#[test]
4949
fn test_derive_mek_hitless_update() {
5050
let mut model = boot_ocp_lock_runtime(OcpLockBootParams {
@@ -63,7 +63,7 @@ fn test_derive_mek_hitless_update() {
6363
verify_derive_mek(&mut model, &EXPECTED_MEK);
6464
}
6565

66-
#[cfg(not(any(feature = "fpga_realtime", feature = "fpga_subsystem")))]
66+
#[cfg(not(feature = "fpga_realtime"))]
6767
#[test]
6868
fn test_derive_mek_mix_mpk_hitless_update() {
6969
let mut model = boot_ocp_lock_runtime(OcpLockBootParams {
@@ -261,7 +261,7 @@ fn mix_mpk_flow(
261261
result_mpks
262262
}
263263

264-
#[cfg(not(any(feature = "fpga_realtime", feature = "fpga_subsystem")))]
264+
#[cfg(not(feature = "fpga_realtime"))]
265265
#[test]
266266
fn test_derive_mek() {
267267
let mut model = boot_ocp_lock_runtime(OcpLockBootParams {
@@ -297,7 +297,7 @@ fn test_derive_mek() {
297297
});
298298
}
299299

300-
#[cfg(not(any(feature = "fpga_realtime", feature = "fpga_subsystem")))]
300+
#[cfg(not(feature = "fpga_realtime"))]
301301
#[test]
302302
fn test_derive_mek_mix_mpk() {
303303
let mut model = boot_ocp_lock_runtime(OcpLockBootParams {
@@ -383,7 +383,7 @@ fn test_derive_mek_mix_mpk() {
383383
});
384384
}
385385

386-
#[cfg(not(any(feature = "fpga_realtime", feature = "fpga_subsystem")))]
386+
#[cfg(not(feature = "fpga_realtime"))]
387387
#[test]
388388
/// Verifies MEK does not change after a warm reset.
389389
fn test_derive_mek_warm_reset() {
@@ -454,7 +454,7 @@ fn test_derive_mek_warm_reset() {
454454
});
455455
}
456456

457-
#[cfg(not(any(feature = "fpga_realtime", feature = "fpga_subsystem")))]
457+
#[cfg(not(feature = "fpga_realtime"))]
458458
#[test]
459459
fn test_derive_mek_warm_reset_wipes_intermediate_secret() {
460460
let mut model = boot_ocp_lock_runtime(OcpLockBootParams {
@@ -492,7 +492,7 @@ fn test_derive_mek_warm_reset_wipes_intermediate_secret() {
492492
});
493493
}
494494

495-
#[cfg(not(any(feature = "fpga_realtime", feature = "fpga_subsystem")))]
495+
#[cfg(not(feature = "fpga_realtime"))]
496496
#[test]
497497
fn test_derive_mek_debug_unlocked() {
498498
let debug_unlocked_doe_out = DoeOutput::generate(&DoeInput::debug_unlocked());
@@ -544,7 +544,7 @@ fn test_derive_mek_debug_unlocked() {
544544
});
545545
}
546546

547-
#[cfg(not(any(feature = "fpga_realtime", feature = "fpga_subsystem")))]
547+
#[cfg(not(feature = "fpga_realtime"))]
548548
#[test]
549549
fn test_derive_corrupted_sek() {
550550
let mut model = boot_ocp_lock_runtime(OcpLockBootParams {
@@ -579,7 +579,7 @@ fn test_derive_corrupted_sek() {
579579
});
580580
}
581581

582-
#[cfg(not(any(feature = "fpga_realtime", feature = "fpga_subsystem")))]
582+
#[cfg(not(feature = "fpga_realtime"))]
583583
#[test]
584584
fn test_derive_corrupted_sek_no_checksum() {
585585
let mut model = boot_ocp_lock_runtime(OcpLockBootParams {
@@ -613,7 +613,7 @@ fn test_derive_corrupted_sek_no_checksum() {
613613
});
614614
}
615615

616-
#[cfg(not(any(feature = "fpga_realtime", feature = "fpga_subsystem")))]
616+
#[cfg(not(feature = "fpga_realtime"))]
617617
#[test]
618618
fn test_derive_missing_secret_seed() {
619619
let mut model = boot_ocp_lock_runtime(OcpLockBootParams {
@@ -646,7 +646,7 @@ fn test_derive_missing_secret_seed() {
646646
});
647647
}
648648

649-
#[cfg(not(any(feature = "fpga_realtime", feature = "fpga_subsystem")))]
649+
#[cfg(not(feature = "fpga_realtime"))]
650650
#[test]
651651
fn test_derive_consumed_secret_seed() {
652652
let mut model = boot_ocp_lock_runtime(OcpLockBootParams {
@@ -696,7 +696,7 @@ fn test_derive_consumed_secret_seed() {
696696
});
697697
}
698698

699-
#[cfg(not(any(feature = "fpga_realtime", feature = "fpga_subsystem")))]
699+
#[cfg(not(feature = "fpga_realtime"))]
700700
#[test]
701701
fn test_derive_mek_missing_hek() {
702702
let mut model = boot_ocp_lock_runtime(OcpLockBootParams {

0 commit comments

Comments
 (0)