capsules_system/process_checker/
basic.rs1use kernel::deferred_call::{DeferredCall, DeferredCallClient};
10use kernel::hil::digest::{ClientData, ClientHash, ClientVerify};
11use kernel::hil::digest::{DigestDataVerify, Sha256};
12use kernel::process::{Process, ProcessBinary, ShortId};
13use kernel::process_checker::CheckResult;
14use kernel::process_checker::{AppCredentialsPolicy, AppCredentialsPolicyClient};
15use kernel::process_checker::{AppUniqueness, Compress};
16use kernel::utilities::cells::OptionalCell;
17use kernel::utilities::cells::TakeCell;
18use kernel::utilities::leasable_buffer::{SubSlice, SubSliceMut};
19use kernel::ErrorCode;
20use tock_tbf::types::TbfFooterV2Credentials;
21use tock_tbf::types::TbfFooterV2CredentialsType;
22
23pub struct AppCheckerNull {}
25
26impl AppCheckerNull {
27 pub fn new() -> Self {
28 Self {}
29 }
30}
31
32impl<'a> AppCredentialsPolicy<'a> for AppCheckerNull {
33 fn require_credentials(&self) -> bool {
34 false
35 }
36
37 fn check_credentials(
38 &self,
39 credentials: TbfFooterV2Credentials,
40 binary: &'a [u8],
41 ) -> Result<(), (ErrorCode, TbfFooterV2Credentials, &'a [u8])> {
42 Err((ErrorCode::NOSUPPORT, credentials, binary))
43 }
44
45 fn set_client(&self, _client: &'a dyn AppCredentialsPolicyClient<'a>) {}
46}
47
48pub struct AppIdAssignerSimulated {}
49
50impl AppUniqueness for AppIdAssignerSimulated {
51 fn different_identifier(&self, process_a: &ProcessBinary, process_b: &ProcessBinary) -> bool {
54 let a = process_a.header.get_package_name().unwrap_or("");
55 let b = process_b.header.get_package_name().unwrap_or("");
56 !a.eq(b)
57 }
58
59 fn different_identifier_process(
60 &self,
61 process_binary: &ProcessBinary,
62 process: &dyn Process,
63 ) -> bool {
64 let a = process_binary.header.get_package_name().unwrap_or("");
65 let b = process.get_process_name();
66 !a.eq(b)
67 }
68
69 fn different_identifier_processes(
70 &self,
71 process_a: &dyn Process,
72 process_b: &dyn Process,
73 ) -> bool {
74 let a = process_a.get_process_name();
75 let b = process_b.get_process_name();
76 !a.eq(b)
77 }
78}
79
80impl Compress for AppIdAssignerSimulated {
81 fn to_short_id(&self, _process: &ProcessBinary) -> ShortId {
82 ShortId::LocallyUnique
83 }
84}
85
86pub trait Sha256Verifier<'a>: DigestDataVerify<'a, 32_usize> + Sha256 {}
87impl<'a, T: DigestDataVerify<'a, 32_usize> + Sha256> Sha256Verifier<'a> for T {}
88
89pub struct AppCheckerSha256 {
96 hasher: &'static dyn Sha256Verifier<'static>,
97 client: OptionalCell<&'static dyn AppCredentialsPolicyClient<'static>>,
98 hash: TakeCell<'static, [u8; 32]>,
99 binary: OptionalCell<&'static [u8]>,
100 credentials: OptionalCell<TbfFooterV2Credentials>,
101}
102
103impl AppCheckerSha256 {
104 pub fn new(
105 hash: &'static dyn Sha256Verifier<'static>,
106 buffer: &'static mut [u8; 32],
107 ) -> AppCheckerSha256 {
108 AppCheckerSha256 {
109 hasher: hash,
110 client: OptionalCell::empty(),
111 hash: TakeCell::new(buffer),
112 credentials: OptionalCell::empty(),
113 binary: OptionalCell::empty(),
114 }
115 }
116}
117
118impl AppCredentialsPolicy<'static> for AppCheckerSha256 {
119 fn require_credentials(&self) -> bool {
120 true
121 }
122
123 fn check_credentials(
124 &self,
125 credentials: TbfFooterV2Credentials,
126 binary: &'static [u8],
127 ) -> Result<(), (ErrorCode, TbfFooterV2Credentials, &'static [u8])> {
128 self.credentials.set(credentials);
129 match credentials.format() {
130 TbfFooterV2CredentialsType::SHA256 => {
131 self.hash.map(|h| {
132 h[..32].copy_from_slice(&credentials.data()[..32]);
133 });
134 self.hasher.clear_data();
135 match self.hasher.add_data(SubSlice::new(binary)) {
136 Ok(()) => Ok(()),
137 Err((e, b)) => Err((e, credentials, b.take())),
138 }
139 }
140 _ => Err((ErrorCode::NOSUPPORT, credentials, binary)),
141 }
142 }
143
144 fn set_client(&self, client: &'static dyn AppCredentialsPolicyClient<'static>) {
145 self.client.replace(client);
146 }
147}
148
149impl ClientData<32_usize> for AppCheckerSha256 {
150 fn add_mut_data_done(&self, _result: Result<(), ErrorCode>, _data: SubSliceMut<'static, u8>) {}
151
152 fn add_data_done(&self, result: Result<(), ErrorCode>, data: SubSlice<'static, u8>) {
153 match result {
154 Err(e) => panic!("Internal error during application binary checking. SHA256 engine threw error in adding data: {:?}", e),
155 Ok(()) => {
156 self.binary.set(data.take());
157 let hash: &'static mut [u8; 32_usize] = self.hash.take().unwrap();
158 if let Err((e, _)) = self.hasher.verify(hash) { panic!("Failed invoke hash verification in process credential checking: {:?}", e) }
159 }
160 }
161 }
162}
163
164impl ClientVerify<32_usize> for AppCheckerSha256 {
165 fn verification_done(
166 &self,
167 result: Result<bool, ErrorCode>,
168 compare: &'static mut [u8; 32_usize],
169 ) {
170 self.hash.replace(compare);
171 match result {
172 Ok(true) => {
173 self.client.map(|c| {
174 c.check_done(
175 Ok(CheckResult::Accept(None)),
176 self.credentials.take().unwrap(),
177 self.binary.take().unwrap(),
178 );
179 });
180 }
181 Ok(false) => {
182 self.client.map(|c| {
183 c.check_done(
184 Ok(CheckResult::Reject),
185 self.credentials.take().unwrap(),
186 self.binary.take().unwrap(),
187 );
188 });
189 }
190 Err(e) => {
191 panic!("Error {:?} in processing application credentials.", e);
192 }
193 }
194 }
195}
196
197impl ClientHash<32_usize> for AppCheckerSha256 {
198 fn hash_done(&self, _result: Result<(), ErrorCode>, _digest: &'static mut [u8; 32_usize]) {}
199}
200
201pub struct AppIdAssignerNames<'a, F: Fn(&'static str) -> u32> {
218 hasher: &'a F,
219}
220
221impl<'a, F: Fn(&'static str) -> u32> AppIdAssignerNames<'a, F> {
222 pub fn new(hasher: &'a F) -> Self {
223 Self { hasher }
224 }
225}
226
227impl<F: Fn(&'static str) -> u32> AppUniqueness for AppIdAssignerNames<'_, F> {
228 fn different_identifier(&self, process_a: &ProcessBinary, process_b: &ProcessBinary) -> bool {
229 self.to_short_id(process_a) != self.to_short_id(process_b)
230 }
231
232 fn different_identifier_process(
233 &self,
234 process_a: &ProcessBinary,
235 process_b: &dyn Process,
236 ) -> bool {
237 self.to_short_id(process_a) != process_b.short_app_id()
238 }
239
240 fn different_identifier_processes(
241 &self,
242 process_a: &dyn Process,
243 process_b: &dyn Process,
244 ) -> bool {
245 process_a.short_app_id() != process_b.short_app_id()
246 }
247}
248
249impl<F: Fn(&'static str) -> u32> Compress for AppIdAssignerNames<'_, F> {
250 fn to_short_id(&self, process: &ProcessBinary) -> ShortId {
251 let name = process.header.get_package_name().unwrap_or("");
252 let sum = (self.hasher)(name);
253 core::num::NonZeroU32::new(sum).into()
254 }
255}
256
257pub struct AppCheckerRsaSimulated<'a> {
267 deferred_call: DeferredCall,
268 client: OptionalCell<&'a dyn AppCredentialsPolicyClient<'a>>,
269 credentials: OptionalCell<TbfFooterV2Credentials>,
270 binary: OptionalCell<&'a [u8]>,
271}
272
273impl<'a> AppCheckerRsaSimulated<'a> {
274 pub fn new() -> AppCheckerRsaSimulated<'a> {
275 Self {
276 deferred_call: DeferredCall::new(),
277 client: OptionalCell::empty(),
278 credentials: OptionalCell::empty(),
279 binary: OptionalCell::empty(),
280 }
281 }
282}
283
284impl DeferredCallClient for AppCheckerRsaSimulated<'_> {
285 fn handle_deferred_call(&self) {
286 self.client.map(|c| {
292 let binary = self.binary.take().unwrap();
293 let cred = self.credentials.take().unwrap();
294 let result = if cred.format() == TbfFooterV2CredentialsType::Rsa3072Key
295 || cred.format() == TbfFooterV2CredentialsType::Rsa4096Key
296 {
297 Ok(CheckResult::Accept(None))
298 } else {
299 Ok(CheckResult::Pass)
300 };
301
302 c.check_done(result, cred, binary)
303 });
304 }
305
306 fn register(&'static self) {
307 self.deferred_call.register(self);
308 }
309}
310
311impl<'a> AppCredentialsPolicy<'a> for AppCheckerRsaSimulated<'a> {
312 fn require_credentials(&self) -> bool {
313 true
314 }
315
316 fn check_credentials(
317 &self,
318 credentials: TbfFooterV2Credentials,
319 binary: &'a [u8],
320 ) -> Result<(), (ErrorCode, TbfFooterV2Credentials, &'a [u8])> {
321 if self.credentials.is_none() {
322 self.credentials.replace(credentials);
323 self.binary.replace(binary);
324 self.deferred_call.set();
325 Ok(())
326 } else {
327 Err((ErrorCode::BUSY, credentials, binary))
328 }
329 }
330
331 fn set_client(&self, client: &'a dyn AppCredentialsPolicyClient<'a>) {
332 self.client.replace(client);
333 }
334}