1use core::cell::Cell;
8use kernel::hil;
9use kernel::process_checker::CheckResult;
10use kernel::process_checker::{AppCredentialsPolicy, AppCredentialsPolicyClient};
11use kernel::utilities::cells::MapCell;
12use kernel::utilities::cells::OptionalCell;
13use kernel::utilities::leasable_buffer::{SubSlice, SubSliceMut};
14use kernel::ErrorCode;
15use tock_tbf::types::TbfFooterV2Credentials;
16use tock_tbf::types::TbfFooterV2CredentialsType;
17
18pub struct AppCheckerSignature<
27 'a,
28 S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>
29 + hil::public_key_crypto::keys::SelectKey<'a>,
30 H: hil::digest::DigestDataHash<'a, HL>,
31 const HL: usize,
32 const SL: usize,
33> {
34 hasher: &'a H,
35 verifier: &'a S,
36 hash: MapCell<&'static mut [u8; HL]>,
37 signature: MapCell<&'static mut [u8; SL]>,
38 client: OptionalCell<&'static dyn AppCredentialsPolicyClient<'static>>,
39 credential_type: TbfFooterV2CredentialsType,
40 credentials: OptionalCell<TbfFooterV2Credentials>,
41 binary: OptionalCell<&'static [u8]>,
42 active_key_index: Cell<(usize, usize)>,
43}
44
45impl<
46 'a,
47 S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>
48 + hil::public_key_crypto::keys::SelectKey<'a>,
49 H: hil::digest::DigestDataHash<'a, HL>,
50 const HL: usize,
51 const SL: usize,
52 > AppCheckerSignature<'a, S, H, HL, SL>
53{
54 pub fn new(
55 hasher: &'a H,
56 verifier: &'a S,
57 hash_buffer: &'static mut [u8; HL],
58 signature_buffer: &'static mut [u8; SL],
59 credential_type: TbfFooterV2CredentialsType,
60 ) -> AppCheckerSignature<'a, S, H, HL, SL> {
61 Self {
62 hasher,
63 verifier,
64 hash: MapCell::new(hash_buffer),
65 signature: MapCell::new(signature_buffer),
66 client: OptionalCell::empty(),
67 credential_type,
68 credentials: OptionalCell::empty(),
69 binary: OptionalCell::empty(),
70 active_key_index: Cell::new((0, 0)),
71 }
72 }
73
74 fn do_verify(&self) {
75 match (self.signature.take(), self.hash.take()) {
76 (Some(sig), Some(digest)) => {
79 if let Err((e, d, s)) = self.verifier.verify(digest, sig) {
80 self.hash.replace(d);
81 self.signature.replace(s);
82 self.client.map(|c| {
83 let binary = self.binary.take().unwrap();
84 let cred = self.credentials.take().unwrap();
85 c.check_done(Err(e), cred, binary)
86 });
87 }
88 }
89 (sig_option, digest_option) => {
90 if let Some(sig) = sig_option {
91 self.signature.replace(sig);
92 }
93 if let Some(digest) = digest_option {
94 self.hash.replace(digest);
95 }
96 self.client.map(|c| {
97 let binary = self.binary.take().unwrap();
98 let cred = self.credentials.take().unwrap();
99 c.check_done(Err(ErrorCode::FAIL), cred, binary)
100 });
101 }
102 }
103 }
104}
105
106impl<
107 'a,
108 S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>
109 + hil::public_key_crypto::keys::SelectKey<'a>,
110 H: hil::digest::DigestDataHash<'a, HL>,
111 const HL: usize,
112 const SL: usize,
113 > hil::digest::ClientData<HL> for AppCheckerSignature<'a, S, H, HL, SL>
114{
115 fn add_mut_data_done(&self, _result: Result<(), ErrorCode>, _data: SubSliceMut<'static, u8>) {}
116
117 fn add_data_done(&self, result: Result<(), ErrorCode>, data: SubSlice<'static, u8>) {
118 self.binary.set(data.take());
119
120 match result {
122 Err(e) => {
123 self.client.map(|c| {
124 let binary = self.binary.take().unwrap();
125 let cred = self.credentials.take().unwrap();
126 c.check_done(Err(e), cred, binary)
127 });
128 }
129 Ok(()) => {
130 self.hash.take().map(|h| {
131 if let Err((e, _)) = self.hasher.run(h) {
132 self.client.map(|c| {
133 let binary = self.binary.take().unwrap();
134 let cred = self.credentials.take().unwrap();
135 c.check_done(Err(e), cred, binary)
136 });
137 }
138 });
139 }
140 }
141 }
142}
143
144impl<
145 'a,
146 S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>
147 + hil::public_key_crypto::keys::SelectKey<'a>,
148 H: hil::digest::DigestDataHash<'a, HL>,
149 const HL: usize,
150 const SL: usize,
151 > hil::public_key_crypto::keys::SelectKeyClient for AppCheckerSignature<'a, S, H, HL, SL>
152{
153 fn get_key_count_done(&self, count: usize) {
154 self.active_key_index.set((0, count));
157 if let Err(_e) = self.verifier.select_key(0) {
158 self.client.map(|c| {
159 let binary = self.binary.take().unwrap();
160 let cred = self.credentials.take().unwrap();
161 c.check_done(Err(ErrorCode::FAIL), cred, binary)
162 });
163 }
164 }
165
166 fn select_key_done(&self, _index: usize, error: Result<(), ErrorCode>) {
167 match error {
168 Err(e) => {
169 self.client.map(|c| {
171 let binary = self.binary.take().unwrap();
172 let cred = self.credentials.take().unwrap();
173 c.check_done(Err(e), cred, binary)
174 });
175 }
176 Ok(()) => self.do_verify(),
177 }
178 }
179}
180
181impl<
182 'a,
183 S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>
184 + hil::public_key_crypto::keys::SelectKey<'a>,
185 H: hil::digest::DigestDataHash<'a, HL>,
186 const HL: usize,
187 const SL: usize,
188 > hil::digest::ClientHash<HL> for AppCheckerSignature<'a, S, H, HL, SL>
189{
190 fn hash_done(&self, result: Result<(), ErrorCode>, digest: &'static mut [u8; HL]) {
191 self.hash.replace(digest);
195
196 match result {
197 Err(e) => {
198 self.client.map(|c| {
200 let binary = self.binary.take().unwrap();
201 let cred = self.credentials.take().unwrap();
202 c.check_done(Err(e), cred, binary)
203 });
204 }
205 Ok(()) => {
206 match self.verifier.get_key_count() {
209 Err(_) => {
210 self.client.map(|c| {
211 let binary = self.binary.take().unwrap();
212 let cred = self.credentials.take().unwrap();
213 c.check_done(Err(ErrorCode::FAIL), cred, binary)
214 });
215 }
216 Ok(()) => {}
217 }
218 }
219 }
220 }
221}
222
223impl<
224 'a,
225 S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>
226 + hil::public_key_crypto::keys::SelectKey<'a>,
227 H: hil::digest::DigestDataHash<'a, HL>,
228 const HL: usize,
229 const SL: usize,
230 > hil::digest::ClientVerify<HL> for AppCheckerSignature<'a, S, H, HL, SL>
231{
232 fn verification_done(&self, _result: Result<bool, ErrorCode>, _compare: &'static mut [u8; HL]) {
233 }
236}
237
238impl<
239 'a,
240 S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>
241 + hil::public_key_crypto::keys::SelectKey<'a>,
242 H: hil::digest::DigestDataHash<'a, HL>,
243 const HL: usize,
244 const SL: usize,
245 > hil::public_key_crypto::signature::ClientVerify<HL, SL>
246 for AppCheckerSignature<'a, S, H, HL, SL>
247{
248 fn verification_done(
249 &self,
250 result: Result<bool, ErrorCode>,
251 hash: &'static mut [u8; HL],
252 signature: &'static mut [u8; SL],
253 ) {
254 self.hash.replace(hash);
255 self.signature.replace(signature);
256
257 let (current_key, number_keys) = self.active_key_index.get();
258
259 if result.unwrap_or(false) {
262 self.client.map(|c| {
263 let binary = self.binary.take().unwrap();
264 let cred = self.credentials.take().unwrap();
265 c.check_done(
266 Ok(CheckResult::Accept(Some(
267 kernel::process_checker::CheckResultAcceptMetadata {
268 metadata: current_key,
269 },
270 ))),
271 cred,
272 binary,
273 )
274 });
275 } else {
276 let next_key = current_key + 1;
280 if next_key == number_keys {
281 self.client.map(|c| {
284 let binary = self.binary.take().unwrap();
285 let cred = self.credentials.take().unwrap();
286 c.check_done(Ok(CheckResult::Pass), cred, binary)
287 });
288 } else {
289 self.active_key_index.set((next_key, number_keys));
291 match self.verifier.select_key(next_key) {
292 Err(_) => {
293 self.client.map(|c| {
294 let binary = self.binary.take().unwrap();
295 let cred = self.credentials.take().unwrap();
296 c.check_done(Err(ErrorCode::FAIL), cred, binary)
297 });
298 }
299 Ok(()) => {}
300 }
301 }
302 }
303 }
304}
305
306impl<
307 'a,
308 S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>
309 + hil::public_key_crypto::keys::SelectKey<'a>,
310 H: hil::digest::DigestDataHash<'a, HL>,
311 const HL: usize,
312 const SL: usize,
313 > AppCredentialsPolicy<'static> for AppCheckerSignature<'a, S, H, HL, SL>
314{
315 fn require_credentials(&self) -> bool {
316 true
317 }
318
319 fn check_credentials(
320 &self,
321 credentials: TbfFooterV2Credentials,
322 binary: &'static [u8],
323 ) -> Result<(), (ErrorCode, TbfFooterV2Credentials, &'static [u8])> {
324 self.credentials.set(credentials);
325
326 if credentials.format() == self.credential_type {
327 self.signature.map(|b| {
329 b.as_mut_slice()[..SL].copy_from_slice(&credentials.data()[..SL]);
330 });
331
332 self.hasher.clear_data();
334 match self.hasher.add_data(SubSlice::new(binary)) {
335 Ok(()) => Ok(()),
336 Err((e, b)) => Err((e, credentials, b.take())),
337 }
338 } else {
339 Err((ErrorCode::NOSUPPORT, credentials, binary))
340 }
341 }
342
343 fn set_client(&self, client: &'static dyn AppCredentialsPolicyClient<'static>) {
344 self.client.replace(client);
345 }
346}