@@ -7,7 +7,7 @@ use crate::api_types::{DeviceLifecycle, Fuses};
77use crate :: bmc:: Bmc ;
88use crate :: fpga_regs:: {
99 Control , FifoData , FifoRegs , FifoStatus , FlashControl , FlashCtrlRegs , FlashOpStatus ,
10- ItrngFifoStatus , WrapperRegs ,
10+ ItrngFifoStatus , WrapperRegs , EncryptionEngineControl ,
1111} ;
1212use crate :: keys:: { DEFAULT_LIFECYCLE_RAW_TOKENS , DEFAULT_MANUF_DEBUG_UNLOCK_RAW_TOKEN } ;
1313use crate :: mcu_boot_status:: McuBootMilestones ;
@@ -24,11 +24,13 @@ use crate::{
2424use crate :: { OcpLockState , SecurityState } ;
2525use anyhow:: Result ;
2626use 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 } ;
2728use caliptra_emu_bus:: { Bus , BusError , BusMmio , Device , Event , EventData , RecoveryCommandCode } ;
2829use caliptra_emu_types:: { RvAddr , RvData , RvSize } ;
2930use caliptra_hw_model_types:: HexSlice ;
3031use caliptra_image_types:: FwVerificationPqcKeyType ;
3132use sensitive_mmio:: { SensitiveMmio , SensitiveMmioArgs } ;
33+ use std:: collections:: HashMap ;
3234use std:: io:: Write ;
3335use std:: marker:: PhantomData ;
3436use 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
474481impl 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
0 commit comments