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, HASH_LEN, SIGNATURE_LEN>
29 + hil::public_key_crypto::keys::SelectKey<'a>,
30 H: hil::digest::DigestDataHash<'a, HASH_LEN>,
31 const HASH_LEN: usize,
32 const SIGNATURE_LEN: usize,
33> {
34 hasher: &'a H,
35 verifier: &'a S,
36 hash: MapCell<&'static mut [u8; HASH_LEN]>,
37 signature: MapCell<&'static mut [u8; SIGNATURE_LEN]>,
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, HASH_LEN, SIGNATURE_LEN>
48 + hil::public_key_crypto::keys::SelectKey<'a>,
49 H: hil::digest::DigestDataHash<'a, HASH_LEN>,
50 const HASH_LEN: usize,
51 const SIGNATURE_LEN: usize,
52 > AppCheckerSignature<'a, S, H, HASH_LEN, SIGNATURE_LEN>
53{
54 pub fn new(
55 hasher: &'a H,
56 verifier: &'a S,
57 hash_buffer: &'static mut [u8; HASH_LEN],
58 signature_buffer: &'static mut [u8; SIGNATURE_LEN],
59 credential_type: TbfFooterV2CredentialsType,
60 ) -> AppCheckerSignature<'a, S, H, HASH_LEN, SIGNATURE_LEN> {
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, HASH_LEN, SIGNATURE_LEN>
109 + hil::public_key_crypto::keys::SelectKey<'a>,
110 H: hil::digest::DigestDataHash<'a, HASH_LEN>,
111 const HASH_LEN: usize,
112 const SIGNATURE_LEN: usize,
113 > hil::digest::ClientData<HASH_LEN> for AppCheckerSignature<'a, S, H, HASH_LEN, SIGNATURE_LEN>
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, HASH_LEN, SIGNATURE_LEN>
147 + hil::public_key_crypto::keys::SelectKey<'a>,
148 H: hil::digest::DigestDataHash<'a, HASH_LEN>,
149 const HASH_LEN: usize,
150 const SIGNATURE_LEN: usize,
151 > hil::public_key_crypto::keys::SelectKeyClient
152 for AppCheckerSignature<'a, S, H, HASH_LEN, SIGNATURE_LEN>
153{
154 fn get_key_count_done(&self, count: usize) {
155 self.active_key_index.set((0, count));
158 if let Err(_e) = self.verifier.select_key(0) {
159 self.client.map(|c| {
160 let binary = self.binary.take().unwrap();
161 let cred = self.credentials.take().unwrap();
162 c.check_done(Err(ErrorCode::FAIL), cred, binary)
163 });
164 }
165 }
166
167 fn select_key_done(&self, _index: usize, error: Result<(), ErrorCode>) {
168 match error {
169 Err(e) => {
170 self.client.map(|c| {
172 let binary = self.binary.take().unwrap();
173 let cred = self.credentials.take().unwrap();
174 c.check_done(Err(e), cred, binary)
175 });
176 }
177 Ok(()) => self.do_verify(),
178 }
179 }
180}
181
182impl<
183 'a,
184 S: hil::public_key_crypto::signature::SignatureVerify<'static, HASH_LEN, SIGNATURE_LEN>
185 + hil::public_key_crypto::keys::SelectKey<'a>,
186 H: hil::digest::DigestDataHash<'a, HASH_LEN>,
187 const HASH_LEN: usize,
188 const SIGNATURE_LEN: usize,
189 > hil::digest::ClientHash<HASH_LEN> for AppCheckerSignature<'a, S, H, HASH_LEN, SIGNATURE_LEN>
190{
191 fn hash_done(&self, result: Result<(), ErrorCode>, digest: &'static mut [u8; HASH_LEN]) {
192 self.hash.replace(digest);
196
197 match result {
198 Err(e) => {
199 self.client.map(|c| {
201 let binary = self.binary.take().unwrap();
202 let cred = self.credentials.take().unwrap();
203 c.check_done(Err(e), cred, binary)
204 });
205 }
206 Ok(()) => {
207 if self.verifier.get_key_count().is_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 }
217 }
218 }
219}
220
221impl<
222 'a,
223 S: hil::public_key_crypto::signature::SignatureVerify<'static, HASH_LEN, SIGNATURE_LEN>
224 + hil::public_key_crypto::keys::SelectKey<'a>,
225 H: hil::digest::DigestDataHash<'a, HASH_LEN>,
226 const HASH_LEN: usize,
227 const SIGNATURE_LEN: usize,
228 > hil::digest::ClientVerify<HASH_LEN>
229 for AppCheckerSignature<'a, S, H, HASH_LEN, SIGNATURE_LEN>
230{
231 fn verification_done(
232 &self,
233 _result: Result<bool, ErrorCode>,
234 _compare: &'static mut [u8; HASH_LEN],
235 ) {
236 }
239}
240
241impl<
242 'a,
243 S: hil::public_key_crypto::signature::SignatureVerify<'static, HASH_LEN, SIGNATURE_LEN>
244 + hil::public_key_crypto::keys::SelectKey<'a>,
245 H: hil::digest::DigestDataHash<'a, HASH_LEN>,
246 const HASH_LEN: usize,
247 const SIGNATURE_LEN: usize,
248 > hil::public_key_crypto::signature::ClientVerify<HASH_LEN, SIGNATURE_LEN>
249 for AppCheckerSignature<'a, S, H, HASH_LEN, SIGNATURE_LEN>
250{
251 fn verification_done(
252 &self,
253 result: Result<bool, ErrorCode>,
254 hash: &'static mut [u8; HASH_LEN],
255 signature: &'static mut [u8; SIGNATURE_LEN],
256 ) {
257 self.hash.replace(hash);
258 self.signature.replace(signature);
259
260 let (current_key, number_keys) = self.active_key_index.get();
261
262 if result.unwrap_or(false) {
265 self.client.map(|c| {
266 let binary = self.binary.take().unwrap();
267 let cred = self.credentials.take().unwrap();
268 c.check_done(
269 Ok(CheckResult::Accept(Some(
270 kernel::process_checker::CheckResultAcceptMetadata {
271 metadata: current_key,
272 },
273 ))),
274 cred,
275 binary,
276 )
277 });
278 } else {
279 let next_key = current_key + 1;
283 if next_key == number_keys {
284 self.client.map(|c| {
287 let binary = self.binary.take().unwrap();
288 let cred = self.credentials.take().unwrap();
289 c.check_done(Ok(CheckResult::Pass), cred, binary)
290 });
291 } else {
292 self.active_key_index.set((next_key, number_keys));
294 if self.verifier.select_key(next_key).is_err() {
295 self.client.map(|c| {
296 let binary = self.binary.take().unwrap();
297 let cred = self.credentials.take().unwrap();
298 c.check_done(Err(ErrorCode::FAIL), cred, binary)
299 });
300 }
301 }
302 }
303 }
304}
305
306impl<
307 'a,
308 S: hil::public_key_crypto::signature::SignatureVerify<'static, HASH_LEN, SIGNATURE_LEN>
309 + hil::public_key_crypto::keys::SelectKey<'a>,
310 H: hil::digest::DigestDataHash<'a, HASH_LEN>,
311 const HASH_LEN: usize,
312 const SIGNATURE_LEN: usize,
313 > AppCredentialsPolicy<'static> for AppCheckerSignature<'a, S, H, HASH_LEN, SIGNATURE_LEN>
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()[..SIGNATURE_LEN]
330 .copy_from_slice(&credentials.data()[..SIGNATURE_LEN]);
331 });
332
333 self.hasher.clear_data();
335 match self.hasher.add_data(SubSlice::new(binary)) {
336 Ok(()) => Ok(()),
337 Err((e, b)) => Err((e, credentials, b.take())),
338 }
339 } else {
340 Err((ErrorCode::NOSUPPORT, credentials, binary))
341 }
342 }
343
344 fn set_client(&self, client: &'static dyn AppCredentialsPolicyClient<'static>) {
345 self.client.replace(client);
346 }
347}