From 93b1692bcdbf58ddef09edcc00a8a7cb2b7209e4 Mon Sep 17 00:00:00 2001 From: Brad Campbell Date: Wed, 12 Jun 2024 14:19:48 -0400 Subject: [PATCH] appid: support opaque return value for accept If a credential checker accepts a credential, it may now return a nonzero usize with information about the accepted credential. --- capsules/system/src/process_checker/basic.rs | 4 ++-- capsules/system/src/process_checker/signature.rs | 2 +- doc/reference/trd-appid.md | 9 ++++++++- kernel/src/process.rs | 2 +- kernel/src/process_binary.rs | 6 ++++-- kernel/src/process_checker.rs | 15 +++++++++++---- kernel/src/process_loading.rs | 5 ++++- kernel/src/process_standard.rs | 4 ++-- 8 files changed, 33 insertions(+), 14 deletions(-) diff --git a/capsules/system/src/process_checker/basic.rs b/capsules/system/src/process_checker/basic.rs index c554a4b9fd..3544172d88 100644 --- a/capsules/system/src/process_checker/basic.rs +++ b/capsules/system/src/process_checker/basic.rs @@ -170,7 +170,7 @@ impl ClientVerify<32_usize> for AppCheckerSha256 { Ok(true) => { self.client.map(|c| { c.check_done( - Ok(CheckResult::Accept), + Ok(CheckResult::Accept(None)), self.credentials.take().unwrap(), self.binary.take().unwrap(), ); @@ -294,7 +294,7 @@ impl<'a> DeferredCallClient for AppCheckerRsaSimulated<'a> { let result = if cred.format() == TbfFooterV2CredentialsType::Rsa3072Key || cred.format() == TbfFooterV2CredentialsType::Rsa4096Key { - Ok(CheckResult::Accept) + Ok(CheckResult::Accept(None)) } else { Ok(CheckResult::Pass) }; diff --git a/capsules/system/src/process_checker/signature.rs b/capsules/system/src/process_checker/signature.rs index 72c3edeae1..a7afe1568f 100644 --- a/capsules/system/src/process_checker/signature.rs +++ b/capsules/system/src/process_checker/signature.rs @@ -183,7 +183,7 @@ impl< let binary = self.binary.take().unwrap(); let cred = self.credentials.take().unwrap(); let check_result = if result.unwrap_or(false) { - Ok(CheckResult::Accept) + Ok(CheckResult::Accept(None)) } else { Ok(CheckResult::Pass) }; diff --git a/doc/reference/trd-appid.md b/doc/reference/trd-appid.md index 69933549cf..dcb56243e7 100644 --- a/doc/reference/trd-appid.md +++ b/doc/reference/trd-appid.md @@ -549,7 +549,7 @@ which credentials, are acceptable and which are rejected. ```rust pub enum CheckResult { - Accept, + Accept(Option), Pass, Reject } @@ -581,6 +581,13 @@ each `TbfFooterV2Credentials` footer it encounters, the kernel calls `check_credentials` on the provided `AppCredentialsPolicy`. If `check_credentials` returns `CheckResult::Accept`, the kernel stops processing credentials and stores the process binary in the process binaries array. +When an `AppCredentialsPolicy` accepts a credential it may include an opaque +nonzero `usize` value. This will be stored along with the accepted credential +and allows the `AppCredentialsPolicy` to share information about the accepted +credential. For example, if `AppCredentialsPolicy` is checking signatures, the +opaque value may communicate the owner of the private key that validated the +signature. This information may be useful when assigning `ShortId`s. + If the `AppCredentialsPolicy` returns `CheckResult::Reject`, the kernel stops processing credentials and does not load the process binary. diff --git a/kernel/src/process.rs b/kernel/src/process.rs index cf583b63df..4f16b6771b 100644 --- a/kernel/src/process.rs +++ b/kernel/src/process.rs @@ -318,7 +318,7 @@ pub trait Process { /// Return the credential which the credential checker approved if the /// credential checker approved a credential. If the process was allowed to /// run without credentials, return `None`. - fn get_credential(&self) -> Option; + fn get_credential(&self) -> Option<(TbfFooterV2Credentials, Option)>; /// Returns how many times this process has been restarted. fn get_restart_count(&self) -> usize; diff --git a/kernel/src/process_binary.rs b/kernel/src/process_binary.rs index be753345e5..4302394bbf 100644 --- a/kernel/src/process_binary.rs +++ b/kernel/src/process_binary.rs @@ -129,7 +129,7 @@ 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<(TbfFooterV2Credentials, Option)>, } impl ProcessBinary { @@ -249,7 +249,9 @@ impl ProcessBinary { }) } - pub fn get_credential(&self) -> Option { + pub fn get_credential( + &self, + ) -> Option<(TbfFooterV2Credentials, Option)> { self.credential.get() } diff --git a/kernel/src/process_checker.rs b/kernel/src/process_checker.rs index 2ca22d8357..b362c825fb 100644 --- a/kernel/src/process_checker.rs +++ b/kernel/src/process_checker.rs @@ -59,7 +59,11 @@ impl fmt::Debug for ProcessCheckError { #[derive(Debug)] pub enum CheckResult { /// Accept the credential and run the binary. - Accept, + /// + /// The associated value is an optional opaque nonzero usize the credential + /// checker can return to communication some information about the accepted + /// credential. + Accept(Option), /// Go to the next credential or in the case of the last one fall /// back to the default policy. Pass, @@ -183,7 +187,10 @@ pub trait ProcessCheckerMachineClient { fn done( &self, process_binary: ProcessBinary, - result: Result, ProcessCheckError>, + result: Result< + Option<(TbfFooterV2Credentials, Option)>, + ProcessCheckError, + >, ); } @@ -431,10 +438,10 @@ impl AppCredentialsPolicyClient<'static> for ProcessCheckerMachine { debug!("Checking: check_done gave result {:?}", result); } let cont = match result { - Ok(CheckResult::Accept) => { + Ok(CheckResult::Accept(opaque)) => { self.client.map(|client| { if let Some(pb) = self.process_binary.take() { - client.done(pb, Ok(Some(credentials))) + client.done(pb, Ok(Some((credentials, opaque)))) } }); false diff --git a/kernel/src/process_loading.rs b/kernel/src/process_loading.rs index f840c09095..2417b203a3 100644 --- a/kernel/src/process_loading.rs +++ b/kernel/src/process_loading.rs @@ -906,7 +906,10 @@ impl<'a, C: Chip> crate::process_checker::ProcessCheckerMachineClient fn done( &self, process_binary: ProcessBinary, - result: Result, crate::process_checker::ProcessCheckError>, + result: Result< + Option<(TbfFooterV2Credentials, Option)>, + crate::process_checker::ProcessCheckError, + >, ) { // Check if this process was approved by the checker. match result { diff --git a/kernel/src/process_standard.rs b/kernel/src/process_standard.rs index 4d95077cf2..357bccdae6 100644 --- a/kernel/src/process_standard.rs +++ b/kernel/src/process_standard.rs @@ -188,7 +188,7 @@ pub struct ProcessStandard<'a, C: 'static + Chip> { /// Credential that was approved for this process, or `None` if the /// credential was permitted to run without an accepted credential. - credential: Option, + credential: Option<(TbfFooterV2Credentials, Option)>, /// State saved on behalf of the process each time the app switches to the /// kernel. @@ -261,7 +261,7 @@ impl Process for ProcessStandard<'_, C> { } } - fn get_credential(&self) -> Option { + fn get_credential(&self) -> Option<(TbfFooterV2Credentials, Option)> { self.credential }