From 121f291eea21cefeb81991b6f7a1cc8de07b4155 Mon Sep 17 00:00:00 2001 From: Brad Campbell Date: Fri, 5 Jul 2024 16:18:29 -0400 Subject: [PATCH] kernel: try to template on T --- kernel/src/process_binary.rs | 8 ++--- kernel/src/process_checker.rs | 61 +++++++++++++++++++++++------------ 2 files changed, 44 insertions(+), 25 deletions(-) diff --git a/kernel/src/process_binary.rs b/kernel/src/process_binary.rs index 16d750ae52..b328a510c6 100644 --- a/kernel/src/process_binary.rs +++ b/kernel/src/process_binary.rs @@ -113,7 +113,7 @@ impl fmt::Debug for ProcessBinaryError { } /// A process stored in flash. -pub struct ProcessBinary { +pub struct ProcessBinary { /// Process flash segment. This is the entire region of nonvolatile flash /// that the process occupies. pub flash: &'static [u8], @@ -129,10 +129,10 @@ pub struct ProcessBinary { /// Optional credential that was used to approve this application. This is /// set if the process is checked by a credential checker and a specific /// credential was used to approve this process. Otherwise this is `None`. - pub credential: OptionalCell, + pub credential: OptionalCell>, } -impl ProcessBinary { +impl ProcessBinary { pub(crate) fn create( app_flash: &'static [u8], header_length: usize, @@ -249,7 +249,7 @@ impl ProcessBinary { }) } - pub fn get_credential(&self) -> Option { + pub fn get_credential(&self) -> Option> { self.credential.get() } diff --git a/kernel/src/process_checker.rs b/kernel/src/process_checker.rs index 8e36730cd3..cac94bfbcf 100644 --- a/kernel/src/process_checker.rs +++ b/kernel/src/process_checker.rs @@ -56,14 +56,16 @@ impl fmt::Debug for ProcessCheckError { /// What a AppCredentialsChecker decided a particular application's credential /// indicates about the runnability of an application binary. -#[derive(Debug)] -pub enum CheckResult { +/// +/// The templated `AcceptedMetadata` type allows a credentials checking policy +/// to include additional metadata with an accepted credential. +pub enum CheckResult { /// Accept the credential and run the binary. /// /// The associated value is an optional opaque nonzero usize the credential /// checker can return to communication some information about the accepted /// credential. - Accept(Option), + Accept(AcceptedMetadata), /// Go to the next credential or in the case of the last one fall /// back to the default policy. Pass, @@ -71,13 +73,28 @@ pub enum CheckResult { Reject, } +// We manually implement debug so that `AcceptedMetadata` does not need to be +// `Debug`. +impl core::fmt::Debug for CheckResult { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + CheckResult::Accept(_) => write!(f, "Accept"), + CheckResult::Pass => write!(f, "Pass"), + CheckResult::Reject => write!(f, "Reject"), + } + } +} + /// Receives callbacks on whether a credential was accepted or not. -pub trait AppCredentialsPolicyClient<'a> { +/// +/// Accepted credentials include a generic `AcceptedMetadata` type which can +/// provide additional information about why that credential was accepted. +pub trait AppCredentialsPolicyClient<'a, AcceptedMetadata> { /// The check for a particular credential is complete. Result of the check /// is in `result`. fn check_done( &self, - result: Result, + result: Result, ErrorCode>, credentials: TbfFooterV2Credentials, integrity_region: &'a [u8], ); @@ -93,19 +110,19 @@ pub trait AppCredentialsPolicyClient<'a> { /// signatures, it might set the optional value to the index of the public key /// in this list. #[derive(Copy, Clone)] -pub struct AcceptedCredential { +pub struct AcceptedCredential { /// The credential stored in the footer that the credential checker /// accepted. pub credential: TbfFooterV2Credentials, /// An optional opaque value set by the credential checker to store metadata /// about the accepted credential. This is credential checker specific. - pub metadata: Option, + pub metadata: AcceptedMetadata, } /// Implements a Credentials Checking Policy. -pub trait AppCredentialsPolicy<'a> { +pub trait AppCredentialsPolicy<'a, AcceptedMetadata> { /// Set the client which gets notified after the credential check completes. - fn set_client(&self, client: &'a dyn AppCredentialsPolicyClient<'a>); + fn set_client(&self, client: &'a dyn AppCredentialsPolicyClient<'a, AcceptedMetadata>); /// Whether credentials are required or not. /// @@ -194,7 +211,7 @@ pub trait AppIdPolicy: AppUniqueness + Compress {} impl AppIdPolicy for T {} /// Client interface for the outcome of a process credential check. -pub trait ProcessCheckerMachineClient { +pub trait ProcessCheckerMachineClient { /// Check is finished, and the check result is in `result`.0 /// /// If `result` is `Ok(Option)`, the credentials were either @@ -206,7 +223,7 @@ pub trait ProcessCheckerMachineClient { fn done( &self, process_binary: ProcessBinary, - result: Result, ProcessCheckError>, + result: Result>, ProcessCheckError>, ); } @@ -227,19 +244,19 @@ enum FooterCheckResult { /// Checks the footers for a `ProcessBinary` and decides whether to continue /// loading the process based on the checking policy in `checker`. -pub struct ProcessCheckerMachine { +pub struct ProcessCheckerMachine { /// Client for receiving the outcome of the check. - client: OptionalCell<&'static dyn ProcessCheckerMachineClient>, + client: OptionalCell<&'static dyn ProcessCheckerMachineClient>, /// Policy for checking credentials. - policy: OptionalCell<&'static dyn AppCredentialsPolicy<'static>>, + policy: OptionalCell<&'static dyn AppCredentialsPolicy<'static, AcceptedMetadata>>, /// Hold the process binary during checking. process_binary: OptionalCell, /// Keep track of which footer is being parsed. footer_index: Cell, } -impl ProcessCheckerMachine { - pub fn new(policy: &'static dyn AppCredentialsPolicy<'static>) -> Self { +impl ProcessCheckerMachine { + pub fn new(policy: &'static dyn AppCredentialsPolicy<'static, AcceptedMetadata>) -> Self { Self { footer_index: Cell::new(0), policy: OptionalCell::new(policy), @@ -248,11 +265,11 @@ impl ProcessCheckerMachine { } } - pub fn set_client(&self, client: &'static dyn ProcessCheckerMachineClient) { + pub fn set_client(&self, client: &'static dyn ProcessCheckerMachineClient) { self.client.set(client); } - pub fn set_policy(&self, policy: &'static dyn AppCredentialsPolicy<'static>) { + pub fn set_policy(&self, policy: &'static dyn AppCredentialsPolicy<'static, AcceptedMetadata>) { self.policy.replace(policy); } @@ -329,7 +346,7 @@ impl ProcessCheckerMachine { // it reached the end of the footer region. fn check_footer( process_binary: &ProcessBinary, - policy: &'static dyn AppCredentialsPolicy<'static>, + policy: &'static dyn AppCredentialsPolicy<'static, AcceptedMetadata>, next_footer: usize, ) -> FooterCheckResult { if config::CONFIG.debug_process_credentials { @@ -443,10 +460,12 @@ impl ProcessCheckerMachine { } } -impl AppCredentialsPolicyClient<'static> for ProcessCheckerMachine { +impl AppCredentialsPolicyClient<'static, AcceptedMetadata> + for ProcessCheckerMachine +{ fn check_done( &self, - result: Result, + result: Result, ErrorCode>, credentials: TbfFooterV2Credentials, _integrity_region: &'static [u8], ) {