capsules_system/process_checker/
signature.rs1use kernel::hil;
8use kernel::process_checker::CheckResult;
9use kernel::process_checker::{AppCredentialsPolicy, AppCredentialsPolicyClient};
10use kernel::utilities::cells::MapCell;
11use kernel::utilities::cells::OptionalCell;
12use kernel::utilities::leasable_buffer::{SubSlice, SubSliceMut};
13use kernel::ErrorCode;
14use tock_tbf::types::TbfFooterV2Credentials;
15use tock_tbf::types::TbfFooterV2CredentialsType;
16
17pub struct AppCheckerSignature<
26 'a,
27 S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>,
28 H: hil::digest::DigestDataHash<'a, HL>,
29 const HL: usize,
30 const SL: usize,
31> {
32 hasher: &'a H,
33 verifier: &'a S,
34 hash: MapCell<&'static mut [u8; HL]>,
35 signature: MapCell<&'static mut [u8; SL]>,
36 client: OptionalCell<&'static dyn AppCredentialsPolicyClient<'static>>,
37 credential_type: TbfFooterV2CredentialsType,
38 credentials: OptionalCell<TbfFooterV2Credentials>,
39 binary: OptionalCell<&'static [u8]>,
40}
41
42impl<
43 'a,
44 S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>,
45 H: hil::digest::DigestDataHash<'a, HL>,
46 const HL: usize,
47 const SL: usize,
48 > AppCheckerSignature<'a, S, H, HL, SL>
49{
50 pub fn new(
51 hasher: &'a H,
52 verifier: &'a S,
53 hash_buffer: &'static mut [u8; HL],
54 signature_buffer: &'static mut [u8; SL],
55 credential_type: TbfFooterV2CredentialsType,
56 ) -> AppCheckerSignature<'a, S, H, HL, SL> {
57 Self {
58 hasher,
59 verifier,
60 hash: MapCell::new(hash_buffer),
61 signature: MapCell::new(signature_buffer),
62 client: OptionalCell::empty(),
63 credential_type,
64 credentials: OptionalCell::empty(),
65 binary: OptionalCell::empty(),
66 }
67 }
68}
69
70impl<
71 'a,
72 S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>,
73 H: hil::digest::DigestDataHash<'a, HL>,
74 const HL: usize,
75 const SL: usize,
76 > hil::digest::ClientData<HL> for AppCheckerSignature<'a, S, H, HL, SL>
77{
78 fn add_mut_data_done(&self, _result: Result<(), ErrorCode>, _data: SubSliceMut<'static, u8>) {}
79
80 fn add_data_done(&self, result: Result<(), ErrorCode>, data: SubSlice<'static, u8>) {
81 self.binary.set(data.take());
82
83 match result {
85 Err(e) => {
86 self.client.map(|c| {
87 let binary = self.binary.take().unwrap();
88 let cred = self.credentials.take().unwrap();
89 c.check_done(Err(e), cred, binary)
90 });
91 }
92 Ok(()) => {
93 self.hash.take().map(|h| {
94 if let Err((e, _)) = self.hasher.run(h) {
95 self.client.map(|c| {
96 let binary = self.binary.take().unwrap();
97 let cred = self.credentials.take().unwrap();
98 c.check_done(Err(e), cred, binary)
99 });
100 }
101 });
102 }
103 }
104 }
105}
106
107impl<
108 'a,
109 S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>,
110 H: hil::digest::DigestDataHash<'a, HL>,
111 const HL: usize,
112 const SL: usize,
113 > hil::digest::ClientHash<HL> for AppCheckerSignature<'a, S, H, HL, SL>
114{
115 fn hash_done(&self, result: Result<(), ErrorCode>, digest: &'static mut [u8; HL]) {
116 match result {
117 Err(e) => {
118 self.hash.replace(digest);
119 self.client.map(|c| {
120 let binary = self.binary.take().unwrap();
121 let cred = self.credentials.take().unwrap();
122 c.check_done(Err(e), cred, binary)
123 });
124 }
125 Ok(()) => match self.signature.take() {
126 Some(sig) => {
127 if let Err((e, d, s)) = self.verifier.verify(digest, sig) {
128 self.hash.replace(d);
129 self.signature.replace(s);
130 self.client.map(|c| {
131 let binary = self.binary.take().unwrap();
132 let cred = self.credentials.take().unwrap();
133 c.check_done(Err(e), cred, binary)
134 });
135 }
136 }
137 None => {
138 self.hash.replace(digest);
139 self.client.map(|c| {
140 let binary = self.binary.take().unwrap();
141 let cred = self.credentials.take().unwrap();
142 c.check_done(Err(ErrorCode::FAIL), cred, binary)
143 });
144 }
145 },
146 }
147 }
148}
149
150impl<
151 'a,
152 S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>,
153 H: hil::digest::DigestDataHash<'a, HL>,
154 const HL: usize,
155 const SL: usize,
156 > hil::digest::ClientVerify<HL> for AppCheckerSignature<'a, S, H, HL, SL>
157{
158 fn verification_done(&self, _result: Result<bool, ErrorCode>, _compare: &'static mut [u8; HL]) {
159 }
162}
163
164impl<
165 'a,
166 S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>,
167 H: hil::digest::DigestDataHash<'a, HL>,
168 const HL: usize,
169 const SL: usize,
170 > hil::public_key_crypto::signature::ClientVerify<HL, SL>
171 for AppCheckerSignature<'a, S, H, HL, SL>
172{
173 fn verification_done(
174 &self,
175 result: Result<bool, ErrorCode>,
176 hash: &'static mut [u8; HL],
177 signature: &'static mut [u8; SL],
178 ) {
179 self.hash.replace(hash);
180 self.signature.replace(signature);
181
182 self.client.map(|c| {
183 let binary = self.binary.take().unwrap();
184 let cred = self.credentials.take().unwrap();
185 let check_result = if result.unwrap_or(false) {
186 Ok(CheckResult::Accept(None))
187 } else {
188 Ok(CheckResult::Pass)
189 };
190
191 c.check_done(check_result, cred, binary)
192 });
193 }
194}
195
196impl<
197 'a,
198 S: hil::public_key_crypto::signature::SignatureVerify<'static, HL, SL>,
199 H: hil::digest::DigestDataHash<'a, HL>,
200 const HL: usize,
201 const SL: usize,
202 > AppCredentialsPolicy<'static> for AppCheckerSignature<'a, S, H, HL, SL>
203{
204 fn require_credentials(&self) -> bool {
205 true
206 }
207
208 fn check_credentials(
209 &self,
210 credentials: TbfFooterV2Credentials,
211 binary: &'static [u8],
212 ) -> Result<(), (ErrorCode, TbfFooterV2Credentials, &'static [u8])> {
213 self.credentials.set(credentials);
214
215 if credentials.format() == self.credential_type {
216 self.signature.map(|b| {
218 b.as_mut_slice()[..SL].copy_from_slice(&credentials.data()[..SL]);
219 });
220
221 self.hasher.clear_data();
223 match self.hasher.add_data(SubSlice::new(binary)) {
224 Ok(()) => Ok(()),
225 Err((e, b)) => Err((e, credentials, b.take())),
226 }
227 } else {
228 Err((ErrorCode::NOSUPPORT, credentials, binary))
229 }
230 }
231
232 fn set_client(&self, client: &'static dyn AppCredentialsPolicyClient<'static>) {
233 self.client.replace(client);
234 }
235}