diff --git a/runtime/src/drivers.rs b/runtime/src/drivers.rs index 7aad16b7cd..30965d3478 100644 --- a/runtime/src/drivers.rs +++ b/runtime/src/drivers.rs @@ -590,7 +590,8 @@ impl Drivers { /// * `flags` - Flags from manifest header /// * `locality` - Caller's locality pub fn is_caller_pl1(pl0_pauser: u32, flags: u32, locality: u32) -> bool { - flags & PL0_PAUSER_FLAG == 0 && locality != pl0_pauser + (flags & PL0_PAUSER_FLAG == 0) // There is no PL0 PAUSER + || (locality != pl0_pauser) // There is a PL0 PAUSER, but it's not the current user } /// Get the KeyId for the RT Alias CDI diff --git a/runtime/tests/runtime_integration_tests/test_pauser_privilege_levels.rs b/runtime/tests/runtime_integration_tests/test_pauser_privilege_levels.rs index cc4d888af0..daf7f6c2a3 100644 --- a/runtime/tests/runtime_integration_tests/test_pauser_privilege_levels.rs +++ b/runtime/tests/runtime_integration_tests/test_pauser_privilege_levels.rs @@ -1,6 +1,7 @@ // Licensed under the Apache-2.0 license use caliptra_builder::{ + build_firmware_elf, firmware::{APP_WITH_UART, FMC_WITH_UART}, ImageOptions, }; @@ -10,9 +11,13 @@ use caliptra_common::mailbox_api::{ }; use caliptra_error::CaliptraError; use caliptra_hw_model::{BootParams, Fuses, HwModel, InitParams, SecurityState}; +use caliptra_image_elf::ElfExecutable; +use caliptra_image_gen::{ImageGenerator, ImageGeneratorConfig}; +use caliptra_image_openssl::OsslCrypto; use caliptra_runtime::{ RtBootStatus, PL0_DPE_ACTIVE_CONTEXT_THRESHOLD, PL1_DPE_ACTIVE_CONTEXT_THRESHOLD, }; + use dpe::{ commands::{ CertifyKeyCmd, CertifyKeyFlags, Command, DeriveContextCmd, DeriveContextFlags, InitCtxCmd, @@ -453,3 +458,133 @@ fn test_measurement_log_pl_context_threshold() { == u32::from(CaliptraError::RUNTIME_PL0_USED_DPE_CONTEXT_THRESHOLD_REACHED) }); } + +#[test] +fn test_pl0_unset_in_header() { + let fuses = Fuses::default(); + let rom = caliptra_builder::rom_for_fw_integration_tests().unwrap(); + let mut model = caliptra_hw_model::new(BootParams { + init_params: InitParams { + rom: &rom, + security_state: SecurityState::from(fuses.life_cycle as u32), + ..Default::default() + }, + fuses, + ..Default::default() + }) + .unwrap(); + + let mut opts = ImageOptions::default(); + opts.vendor_config.pl0_pauser = None; + let mut image_bundle = + caliptra_builder::build_and_sign_image(&FMC_WITH_UART, &APP_WITH_UART, opts).unwrap(); + + // Change PL0 to 1 so that it matches the real PL0 PAUSER but don't set the + // flag bit to make it valid. Also need to re-generate and re-sign the image. + image_bundle.manifest.header.pl0_pauser = 1; + + let opts = ImageOptions::default(); + let ecc_index = opts.vendor_config.ecc_key_idx; + let lms_index = opts.vendor_config.lms_key_idx; + let gen = ImageGenerator::new(OsslCrypto::default()); + let header_digest_vendor = gen + .header_digest_vendor(&image_bundle.manifest.header) + .unwrap(); + let header_digest_owner = gen + .header_digest_owner(&image_bundle.manifest.header) + .unwrap(); + let fmc_elf = build_firmware_elf(&FMC_WITH_UART).unwrap(); + let app_elf = build_firmware_elf(&APP_WITH_UART).unwrap(); + let preamble = gen + .gen_preamble( + &ImageGeneratorConfig { + fmc: ElfExecutable::new( + &fmc_elf, + opts.fmc_version as u32, + opts.fmc_svn, + *b"~~~~~NO_GIT_REVISION", + ) + .unwrap(), + runtime: ElfExecutable::new( + &app_elf, + opts.app_version, + opts.app_svn, + *b"~~~~~NO_GIT_REVISION", + ) + .unwrap(), + vendor_config: opts.vendor_config, + owner_config: opts.owner_config, + }, + ecc_index, + lms_index, + &header_digest_vendor, + &header_digest_owner, + ) + .unwrap(); + image_bundle.manifest.preamble = preamble; + + model + .upload_firmware(&image_bundle.to_bytes().unwrap()) + .unwrap(); + + model.step_until(|m| { + m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) + }); + + // If PL0 PAUSER is unset, make sure PL0-only operation fails + let certify_key_cmd = CertifyKeyCmd { + handle: ContextHandle::default(), + label: TEST_LABEL, + flags: CertifyKeyFlags::empty(), + format: CertifyKeyCmd::FORMAT_X509, + }; + let resp = execute_dpe_cmd( + &mut model, + &mut Command::CertifyKey(certify_key_cmd), + DpeResult::MboxCmdFailure(CaliptraError::RUNTIME_INCORRECT_PAUSER_PRIVILEGE_LEVEL), + ); + assert!(resp.is_none()); +} + +#[test] +fn test_user_not_pl0() { + let fuses = Fuses::default(); + let rom = caliptra_builder::rom_for_fw_integration_tests().unwrap(); + let mut model = caliptra_hw_model::new(BootParams { + init_params: InitParams { + rom: &rom, + security_state: SecurityState::from(fuses.life_cycle as u32), + ..Default::default() + }, + fuses, + ..Default::default() + }) + .unwrap(); + + let mut opts = ImageOptions::default(); + opts.vendor_config.pl0_pauser = Some(0); // Caller PAUSER is always 1 for current models + let image_bundle = + caliptra_builder::build_and_sign_image(&FMC_WITH_UART, &APP_WITH_UART, opts).unwrap(); + + model + .upload_firmware(&image_bundle.to_bytes().unwrap()) + .unwrap(); + + model.step_until(|m| { + m.soc_ifc().cptra_boot_status().read() == u32::from(RtBootStatus::RtReadyForCommands) + }); + + // If PL0 PAUSER is unset, make sure PL0-only operation fails + let certify_key_cmd = CertifyKeyCmd { + handle: ContextHandle::default(), + label: TEST_LABEL, + flags: CertifyKeyFlags::empty(), + format: CertifyKeyCmd::FORMAT_X509, + }; + let resp = execute_dpe_cmd( + &mut model, + &mut Command::CertifyKey(certify_key_cmd), + DpeResult::MboxCmdFailure(CaliptraError::RUNTIME_INCORRECT_PAUSER_PRIVILEGE_LEVEL), + ); + assert!(resp.is_none()); +}