1 /*
2  * Copyright (C) 2022 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 //! Module that implements the [`SecureDeletionSecretManager`] trait.
18 use alloc::rc::Rc;
19 use core::{cell::RefCell, cmp, ops::DerefMut};
20 use kmr_common::{
21     crypto,
22     keyblob::{SecureDeletionData, SecureDeletionSecretManager, SecureDeletionSlot, SlotPurpose},
23     km_err, Error,
24 };
25 use log::{debug, error, info, warn};
26 use storage::{self as storage_session, OpenMode, Port, SecureFile, Session, Transaction};
27 use zeroize::{Zeroize, ZeroizeOnDrop};
28 
29 // Maximum number of attempts to perform a secure storage transaction to read or
30 // delete a secure deletion secret.  Because the storageproxy may be restarted
31 // while this code is running, it may be necessary to retry.  But because it's
32 // unclear exactly what error codes may be returned when the proxy is shut down,
33 // we conservatively retry all unexpected errors.  To avoid an infinite loop, we
34 // set a limit on the number of retries (though hitting the limit and returning
35 // an error will likely break the boot anyway).  Ideally, we should never need
36 // more than one retry.  We allow three.
37 const MAX_TRIES: usize = 3;
38 
39 // Each secret is 16 bytes.
40 const SECRET_SIZE: usize = 16;
41 // The factory reset secret is composed of two secrets, so 32 bytes, and it is
42 // stored at offset 0. After this position (offset 32), all the secrets are
43 // stored one after the other. On each secret a single bit on the first byte is
44 // set to indicate that the secret is valid (mask 0x80). Any unused secret/newly
45 // allocated space on the file is set to 0
46 const FACTORY_RESET_SECRET_SIZE: usize = SECRET_SIZE * 2;
47 const FACTORY_RESET_SECRET_POS: usize = 0;
48 const FACTORY_FIRST_SECURE_DELETION_SECRET_POS: usize =
49     FACTORY_RESET_SECRET_POS + FACTORY_RESET_SECRET_SIZE;
50 
51 // We read secrets in blocks of 32, so 512 bytes.
52 const BLOCK_SIZE: usize = SECRET_SIZE * 32;
53 
54 // Limit file size to 16 KiB (except for key upgrades, see
55 // MAX_SECRET_FILE_SIZE_FOR_UPGRADES).
56 const MAX_SECRET_FILE_SIZE: usize = BLOCK_SIZE * 32;
57 
58 // This is a higher file size limit, with the space above MAX_SECRET_FILE_SIZE
59 // usable only for key IDs that need to be written as part of a key upgrade.
60 // This is to reduce the probability that keys are degraded as a result of
61 // upgrading.
62 const MAX_SECRET_FILE_SIZE_FOR_UPGRADES: usize = MAX_SECRET_FILE_SIZE + 8 * BLOCK_SIZE;
63 
64 // We set a bit in the first byte of each slot to indicate that the slot is in
65 // use. This reduces the maximum entropy of each slot to 127 bits.
66 const IN_USE_FLAG: u8 = 0x80;
67 
68 // Name of the file to store secrets. The "_1" suffix is to allow for new file
69 // formats/versions in the future.
70 const SECURE_DELETION_SECRET_FILENAME: &str = "SecureDeletionSecrets_1";
71 
72 // TODO: Add crate static_assertions to trusty to replace these with static_assert!
73 const _: () = assert!(
74     BLOCK_SIZE >= FACTORY_RESET_SECRET_SIZE,
75     "BLOCK_SIZE should be bigger than FACTORY_RESET_SECRET_SIZE"
76 );
77 const _: () = assert!((BLOCK_SIZE % SECRET_SIZE) == 0, "Broke find_empty_slot assumption");
78 const _: () =
79     assert!((FACTORY_RESET_SECRET_SIZE % SECRET_SIZE) == 0, "Broke find_empty_slot assumption");
80 
get_secure_deletion_secret_file_session(wait_on_port: bool) -> Result<Session, Error>81 fn get_secure_deletion_secret_file_session(wait_on_port: bool) -> Result<Session, Error> {
82     let session = Session::new(Port::TamperProof, wait_on_port).map_err(|e| {
83         km_err!(
84             SecureHwCommunicationFailed,
85             "failed to connect to secure storage port for opening secure deletion file: {:?}",
86             e
87         )
88     })?;
89     Ok(session)
90 }
91 
delete_secure_deletion_secret_file() -> Result<(), Error>92 fn delete_secure_deletion_secret_file() -> Result<(), Error> {
93     let mut session = get_secure_deletion_secret_file_session(true)?;
94     // We do not consider the file not existing an error when trying to delete it because the
95     // end result is the same.
96     match session.remove(SECURE_DELETION_SECRET_FILENAME) {
97         Ok(_) => Ok(()),
98         Err(storage_session::Error::Code(trusty_sys::Error::NotFound)) => Ok(()),
99         Err(e) => Err(km_err!(
100             SecureHwCommunicationFailed,
101             "couldn't delete secure secrets file: {:?}",
102             e
103         )),
104     }
105 }
106 
107 enum RetrieveSecureDeletionSecretFileData<'a> {
108     EmptyFileFound(SecureDeletionSecretFile<'a>),
109     CachedDataFound(SecureDeletionData),
110     DataFoundOnFile(SecureDeletionData),
111 }
112 
113 struct SecureDeletionSecretFile<'a> {
114     file: SecureFile,
115     transaction: Transaction<'a>,
116 }
117 
118 impl<'a> SecureDeletionSecretFile<'a> {
open_or_create(session: &'a mut Session) -> Result<SecureDeletionSecretFile<'a>, Error>119     fn open_or_create(session: &'a mut Session) -> Result<SecureDeletionSecretFile<'a>, Error> {
120         let mut transaction = session.begin_transaction();
121         let file = transaction
122             .open_file(SECURE_DELETION_SECRET_FILENAME, OpenMode::Create)
123             .map_err(|e| {
124                 km_err!(
125                     SecureHwCommunicationFailed,
126                     "failed to open secure deletion secret file: {:?}",
127                     e
128                 )
129             })?;
130         Ok(SecureDeletionSecretFile { transaction, file })
131     }
132 
read_block<'buf>( &mut self, start: usize, buffer: &'buf mut [u8], ) -> Result<&'buf [u8], Error>133     fn read_block<'buf>(
134         &mut self,
135         start: usize,
136         buffer: &'buf mut [u8],
137     ) -> Result<&'buf [u8], Error> {
138         let req_len = buffer.len();
139         let data = self.transaction.read_at(&self.file, start, buffer).map_err(|e| {
140             km_err!(
141                 SecureHwCommunicationFailed,
142                 "failed to read secure deletion secret file at offset {} with len {}: {:?}",
143                 start,
144                 req_len,
145                 e
146             )
147         })?;
148         if data.len() != req_len {
149             Err(km_err!(
150                 UnknownError,
151                 "couldn't read {} bytes of secure deletion secret file at offset {}. Read {} bytes",
152                 req_len,
153                 start,
154                 data.len()
155             ))
156         } else {
157             Ok(data)
158         }
159     }
160 
161     // Find empty slot is used to find the first [SECRET_SIZE] position on the secure file that
162     // isn't currently in use. For this it will read the secure file in [BLOCK_SIZE] chunks and
163     // move in [SECRET_SIZE] increments; checking if the IN_USE_FLAG is set on that position.
find_empty_slot(&mut self, is_upgrade: bool) -> Result<Option<usize>, Error>164     fn find_empty_slot(&mut self, is_upgrade: bool) -> Result<Option<usize>, Error> {
165         let end = SecureDeletionSecretFile::get_max_file_size(is_upgrade);
166         let file_size = self.get_file_size()?;
167         let end = cmp::min(end, file_size);
168         let mut block_buffer = [0; BLOCK_SIZE];
169         for start_pos in (0..end).step_by(BLOCK_SIZE) {
170             let read_data = match self.read_block(start_pos, &mut block_buffer) {
171                 Ok(read_data) => read_data,
172                 Err(e) => {
173                     error!("Failed to read block of secrets");
174                     return Err(e);
175                 }
176             };
177             // Code assumes that we always read a complete block. API called could potentially
178             // return less data.
179             if read_data.len() != BLOCK_SIZE {
180                 return Err(km_err!(
181                     SecureHwCommunicationFailed,
182                     "failed to read complete block from storage. Received {} bytes",
183                     read_data.len()
184                 ));
185             }
186 
187             let block_start = match start_pos {
188                 FACTORY_RESET_SECRET_POS => FACTORY_FIRST_SECURE_DELETION_SECRET_POS,
189                 _ => 0,
190             };
191 
192             for (chunk_num, secret) in read_data[block_start..].chunks(SECRET_SIZE).enumerate() {
193                 if (secret[0] & IN_USE_FLAG) == 0 {
194                     let key_slot =
195                         (start_pos + block_start + (chunk_num * SECRET_SIZE)) / SECRET_SIZE;
196                     return Ok(Some(key_slot));
197                 }
198             }
199         }
200         Ok(None)
201     }
202 
write_block(&mut self, start: usize, buffer: &[u8]) -> Result<(), Error>203     fn write_block(&mut self, start: usize, buffer: &[u8]) -> Result<(), Error> {
204         self.transaction.write_at(&mut self.file, start, buffer).map_err(|e| {
205             km_err!(
206                 SecureHwCommunicationFailed,
207                 "failed to write to deletion secret file at pos {}: {:?}",
208                 start,
209                 e
210             )
211         })
212     }
213 
get_file_size(&mut self) -> Result<usize, Error>214     fn get_file_size(&mut self) -> Result<usize, Error> {
215         self.transaction.get_size(&self.file).map_err(|e| {
216             km_err!(
217                 SecureHwCommunicationFailed,
218                 "couldn't get secure deletion secret file size: {:?}",
219                 e
220             )
221         })
222     }
223 
get_max_file_size(is_upgrade: bool) -> usize224     fn get_max_file_size(is_upgrade: bool) -> usize {
225         match is_upgrade {
226             true => MAX_SECRET_FILE_SIZE_FOR_UPGRADES,
227             false => MAX_SECRET_FILE_SIZE,
228         }
229     }
230 
resize(&mut self, new_size: usize) -> Result<(), Error>231     fn resize(&mut self, new_size: usize) -> Result<(), Error> {
232         self.transaction.set_size(&mut self.file, new_size).map_err(|e| {
233             km_err!(
234                 SecureHwCommunicationFailed,
235                 "failed to resize secure deletion secret file to {}: {:?}",
236                 new_size,
237                 e
238             )
239         })?;
240         Ok(())
241     }
242 
zero_entries(&mut self, begin: usize, end: usize) -> Result<(), Error>243     fn zero_entries(&mut self, begin: usize, end: usize) -> Result<(), Error> {
244         if (begin % SECRET_SIZE) != 0 {
245             return Err(km_err!(
246                 InvalidArgument,
247                 "zero_entries called with invalid offset {}",
248                 begin
249             ));
250         }
251         let zero_buff = [0; SECRET_SIZE];
252         for start_pos in (begin..end).step_by(SECRET_SIZE) {
253             self.write_block(start_pos, &zero_buff)?;
254         }
255         Ok(())
256     }
257 
finish_transaction(self) -> Result<(), Error>258     fn finish_transaction(self) -> Result<(), Error> {
259         self.transaction.commit().map_err(|e| {
260             km_err!(
261                 SecureHwCommunicationFailed,
262                 "failed to commit transaction on secure deletion secret file: {:?}",
263                 e
264             )
265         })
266     }
267 }
268 
269 #[derive(Clone, PartialEq, Eq, Zeroize, ZeroizeOnDrop)]
270 struct FactoryResetSecret([u8; FACTORY_RESET_SECRET_SIZE]);
271 
272 #[derive(Clone, PartialEq, Eq, Default)]
273 pub struct TrustySecureDeletionSecretManager {
274     factory_reset_secret: RefCell<Option<FactoryResetSecret>>,
275 }
276 
277 impl TrustySecureDeletionSecretManager {
new() -> Self278     pub fn new() -> Self {
279         TrustySecureDeletionSecretManager { factory_reset_secret: RefCell::new(None) }
280     }
281 
282     // TODO: Check if this code can be refactored to not pass session as an option
283     // get_factory_reset_secret_impl will just try to get the factory reset secret either from cache
284     // or from the file if it exists. If the secret is read and not cached, it will cache it.
285     // If the file doesn't exist, or if it is empty, it will return a File object/session; so the
286     // caller can initialize it. In case the caller doesn't initialize it, we will end up with an
287     // empty file on the file system, but this should be fine because we treat an empty file in the
288     // same way we treat a non-existing file.
get_factory_reset_secret_impl<'a>( &'a self, session: Option<&'a mut Session>, ) -> Result<RetrieveSecureDeletionSecretFileData, Error>289     fn get_factory_reset_secret_impl<'a>(
290         &'a self,
291         session: Option<&'a mut Session>,
292     ) -> Result<RetrieveSecureDeletionSecretFileData, Error> {
293         // Checking if we already have a cached secret we can return
294         if let Some(secret) = self.factory_reset_secret.borrow_mut().deref_mut() {
295             return Ok(RetrieveSecureDeletionSecretFileData::CachedDataFound(SecureDeletionData {
296                 factory_reset_secret: secret.0,
297                 secure_deletion_secret: [0; SECRET_SIZE],
298             }));
299         }
300 
301         // Looking now if we can read the secret from file
302         debug!("Trying to open a session to read factory reset secret");
303         let session = session.ok_or(km_err!(
304             SecureHwCommunicationFailed,
305             "couldn't get a session to open the secure deletion secret file"
306         ))?;
307         let mut sdsf_file = SecureDeletionSecretFile::open_or_create(session)?;
308         let file_size = sdsf_file.get_file_size().map_err(|e| {
309             km_err!(
310                 SecureHwCommunicationFailed,
311                 "couldn't get secure deletion secret file size: {:?}",
312                 e
313             )
314         })?;
315 
316         // Found an empty file
317         if file_size == 0 {
318             return Ok(RetrieveSecureDeletionSecretFileData::EmptyFileFound(sdsf_file));
319         }
320 
321         // The file isn't empty, read the secret and cache it before returning the data
322         debug!("Opened non-empty secure secrets file");
323         let mut buffer = [0; FACTORY_RESET_SECRET_SIZE];
324         let block = sdsf_file.read_block(FACTORY_RESET_SECRET_POS, &mut buffer)?;
325         debug!("Read factory-reset secret, size {}", block.len());
326         if block.len() != FACTORY_RESET_SECRET_SIZE {
327             return Err(km_err!(
328                 SecureHwCommunicationFailed,
329                 "failed to read complete secret data from storage. Received {} bytes",
330                 block.len()
331             ));
332         }
333         self.factory_reset_secret.borrow_mut().deref_mut().replace(FactoryResetSecret(buffer));
334         Ok(RetrieveSecureDeletionSecretFileData::DataFoundOnFile(SecureDeletionData {
335             factory_reset_secret: buffer,
336             secure_deletion_secret: [0; SECRET_SIZE],
337         }))
338     }
339 
340     // get_or_create_factory_reset_secret_impl will use get_factory_reset_secret_impl to try to get
341     // the factory reset secret. If the secure deletion secret file doesn't exist on secure storage,
342     // it will create it and will also initialize it.
get_or_create_factory_reset_secret_impl( &mut self, rng: &mut dyn crypto::Rng, wait_for_port: bool, ) -> Result<SecureDeletionData, Error>343     fn get_or_create_factory_reset_secret_impl(
344         &mut self,
345         rng: &mut dyn crypto::Rng,
346         wait_for_port: bool,
347     ) -> Result<SecureDeletionData, Error> {
348         let mut session = get_secure_deletion_secret_file_session(wait_for_port).ok();
349         let secret_file_data = self.get_factory_reset_secret_impl(session.as_mut())?;
350         match secret_file_data {
351             RetrieveSecureDeletionSecretFileData::CachedDataFound(data) => Ok(data),
352             RetrieveSecureDeletionSecretFileData::DataFoundOnFile(data) => Ok(data),
353             RetrieveSecureDeletionSecretFileData::EmptyFileFound(mut sdsf_file) => {
354                 sdsf_file.resize(BLOCK_SIZE)?;
355                 debug!("Resized secure secrets file to size {}", BLOCK_SIZE);
356                 let mut buffer = [0; FACTORY_RESET_SECRET_SIZE];
357                 rng.fill_bytes(&mut buffer);
358                 sdsf_file.write_block(FACTORY_RESET_SECRET_POS, &buffer)?;
359                 debug!("Wrote new factory reset secret");
360                 sdsf_file.zero_entries(FACTORY_FIRST_SECURE_DELETION_SECRET_POS, BLOCK_SIZE)?;
361                 debug!("Zeroed secrets");
362                 sdsf_file.finish_transaction()?;
363                 debug!("Committed new secrets file");
364                 self.factory_reset_secret
365                     .borrow_mut()
366                     .deref_mut()
367                     .replace(FactoryResetSecret(buffer));
368                 Ok(SecureDeletionData {
369                     factory_reset_secret: buffer,
370                     secure_deletion_secret: [0; SECRET_SIZE],
371                 })
372             }
373         }
374     }
375 
read_slot_data(&self, slot: SecureDeletionSlot, buffer: &mut [u8]) -> Result<(), Error>376     fn read_slot_data(&self, slot: SecureDeletionSlot, buffer: &mut [u8]) -> Result<(), Error> {
377         let buffer_size = buffer.len();
378         if buffer_size != SECRET_SIZE {
379             return Err(km_err!(
380                 InsufficientBufferSpace,
381                 "needed {} bytes to read slot, received {}",
382                 SECRET_SIZE,
383                 buffer.len()
384             ));
385         }
386         let requested_slot = slot.0 as usize;
387         let key_slot_pos = requested_slot * SECRET_SIZE;
388         let mut session = match get_secure_deletion_secret_file_session(true) {
389             Ok(session) => session,
390             Err(e) => {
391                 error!("Failed to open session to get secure deletion data: {:?}", e);
392                 return Err(e);
393             }
394         };
395         let mut sdsf_file = match SecureDeletionSecretFile::open_or_create(&mut session) {
396             Ok(sdsf_file) => sdsf_file,
397             Err(e) => {
398                 error!("Failed to open file to get secure deletion data: {:?}", e);
399                 return Err(e);
400             }
401         };
402         let file_size = match sdsf_file.get_file_size() {
403             Ok(file_size) => file_size,
404             Err(e) => {
405                 error!("Failed to read secure deletion data file size: {:?}", e);
406                 return Err(e);
407             }
408         };
409         if (key_slot_pos + SECRET_SIZE) > file_size {
410             return Err(km_err!(
411                 InvalidArgument,
412                 "invalid key slot {} would read past end of file of size {}",
413                 requested_slot,
414                 file_size
415             ));
416         }
417         match sdsf_file.read_block(key_slot_pos, buffer) {
418             Ok(read_data) => {
419                 if buffer_size == read_data.len() {
420                     Ok(())
421                 } else {
422                     Err(km_err!(
423                         SecureHwCommunicationFailed,
424                         "failed to read complete slot data from storage. Received {} bytes",
425                         read_data.len()
426                     ))
427                 }
428             }
429             Err(e) => {
430                 error!("Failed to read secret from slot {}: {:?}", requested_slot, e);
431                 Err(e)
432             }
433         }
434     }
435 }
436 
437 impl Drop for TrustySecureDeletionSecretManager {
drop(&mut self)438     fn drop(&mut self) {
439         self.factory_reset_secret.borrow_mut().deref_mut().zeroize();
440     }
441 }
442 
443 impl ZeroizeOnDrop for TrustySecureDeletionSecretManager {}
444 
445 impl SecureDeletionSecretManager for TrustySecureDeletionSecretManager {
get_or_create_factory_reset_secret( &mut self, rng: &mut dyn crypto::Rng, ) -> Result<SecureDeletionData, Error>446     fn get_or_create_factory_reset_secret(
447         &mut self,
448         rng: &mut dyn crypto::Rng,
449     ) -> Result<SecureDeletionData, Error> {
450         self.get_or_create_factory_reset_secret_impl(rng, true)
451     }
452 
get_factory_reset_secret(&self) -> Result<SecureDeletionData, Error>453     fn get_factory_reset_secret(&self) -> Result<SecureDeletionData, Error> {
454         let mut session = get_secure_deletion_secret_file_session(true).ok();
455         let secret_file_data = self.get_factory_reset_secret_impl(session.as_mut())?;
456         match secret_file_data {
457             RetrieveSecureDeletionSecretFileData::CachedDataFound(data) => Ok(data),
458             RetrieveSecureDeletionSecretFileData::DataFoundOnFile(data) => Ok(data),
459             RetrieveSecureDeletionSecretFileData::EmptyFileFound(_) => {
460                 Err(km_err!(UnknownError, "factory reset secret not found"))
461             }
462         }
463     }
464 
new_secret( &mut self, rng: &mut dyn crypto::Rng, slot_purpose: SlotPurpose, ) -> Result<(SecureDeletionSlot, SecureDeletionData), Error>465     fn new_secret(
466         &mut self,
467         rng: &mut dyn crypto::Rng,
468         slot_purpose: SlotPurpose,
469     ) -> Result<(SecureDeletionSlot, SecureDeletionData), Error> {
470         let is_upgrade = slot_purpose == SlotPurpose::KeyUpgrade;
471         // We are not waiting on the connection if the TA port is not available. This follows the
472         // behavior of the original code.
473         let mut secure_deletion_data =
474             match self.get_or_create_factory_reset_secret_impl(rng, false) {
475                 Ok(data) => data,
476                 Err(e) => {
477                     info!("Unable to get factory reset secret: {:?}", e);
478                     return Err(e);
479                 }
480             };
481         rng.fill_bytes(&mut secure_deletion_data.secure_deletion_secret);
482         secure_deletion_data.secure_deletion_secret[0] |= IN_USE_FLAG;
483         // Next call will block on the port. It should be fine, because if we reach this point, the
484         // TA should have been available before. Also, the original code follows a similar flow on
485         // which they use a blocking call if this point is reached.
486         let mut session = get_secure_deletion_secret_file_session(true)?;
487         let mut sdsf_file = SecureDeletionSecretFile::open_or_create(&mut session)?;
488         let empty_slot = match sdsf_file.find_empty_slot(is_upgrade) {
489             Ok(slot) => slot,
490             Err(e) => {
491                 error!("Error while searching for key slot: {:?}", e);
492                 return Err(e);
493             }
494         };
495 
496         let original_file_size = sdsf_file.get_file_size()?;
497         let empty_slot = match empty_slot {
498             Some(slot_number) => slot_number,
499             None => {
500                 // No empty slot found, try to increase file size
501                 let max_file_size = SecureDeletionSecretFile::get_max_file_size(is_upgrade);
502                 if original_file_size >= max_file_size {
503                     error!(
504                         "Didn't find a slot and can't grow the file larger than {}",
505                         original_file_size
506                     );
507                     return Err(km_err!(
508                         UnknownError,
509                         "didn't find a slot and can't grow the file larger than {}",
510                         original_file_size
511                     ));
512                 }
513                 let new_size = original_file_size + BLOCK_SIZE;
514                 debug!("Attempting to resize file from {} to {}", original_file_size, new_size);
515                 if let Err(e) = sdsf_file.resize(new_size) {
516                     error!("Failed to grow file to make room for a key slot: {:?}", e);
517                     return Err(e);
518                 }
519                 debug!("Resized file to {}", new_size);
520                 if let Err(e) = sdsf_file.zero_entries(original_file_size, new_size) {
521                     error!("Error zeroing space in extended file: {:?}", e);
522                     return Err(e);
523                 }
524                 original_file_size / SECRET_SIZE
525             }
526         };
527 
528         debug!("Writing new deletion secret to key slot {}", empty_slot);
529         if let Err(e) = sdsf_file
530             .write_block(empty_slot * SECRET_SIZE, &secure_deletion_data.secure_deletion_secret)
531         {
532             error!("Failed to write new deletion secret to key slot {}: {:?}", empty_slot, e);
533             return Err(e);
534         }
535         if let Err(e) = sdsf_file.finish_transaction() {
536             error!(
537                 "Failed to commit transaction writing new deletion secret to slot {}: {:?}",
538                 empty_slot, e
539             );
540             return Err(e);
541         }
542         debug!("Committed new secret");
543         Ok((SecureDeletionSlot(empty_slot as u32), secure_deletion_data))
544     }
545 
get_secret(&self, slot: SecureDeletionSlot) -> Result<SecureDeletionData, Error>546     fn get_secret(&self, slot: SecureDeletionSlot) -> Result<SecureDeletionData, Error> {
547         let mut current_try = 0;
548         let mut secure_deletion_data = loop {
549             let data = self.get_factory_reset_secret();
550             if (data.is_ok()) || (current_try >= MAX_TRIES) {
551                 break data?;
552             }
553             current_try += 1;
554         };
555         let requested_slot = slot.0 as usize;
556         if requested_slot == 0 || requested_slot == 1 {
557             warn!("Requested slot {} which corresponds to factory reset secret", requested_slot);
558             return Err(km_err!(
559                 InvalidArgument,
560                 "requested slot {} which does not contain a per-key secret",
561                 requested_slot
562             ));
563         }
564 
565         current_try = 0;
566         loop {
567             match self.read_slot_data(slot, &mut secure_deletion_data.secure_deletion_secret) {
568                 Ok(_) => {
569                     debug!(
570                         "Read secure deletion secret, size: {}",
571                         secure_deletion_data.secure_deletion_secret.len()
572                     );
573                     break Ok(secure_deletion_data);
574                 }
575                 Err(e) => {
576                     if current_try >= MAX_TRIES {
577                         break Err(e);
578                     }
579                 }
580             }
581             current_try += 1;
582         }
583     }
584 
delete_secret(&mut self, slot: SecureDeletionSlot) -> Result<(), Error>585     fn delete_secret(&mut self, slot: SecureDeletionSlot) -> Result<(), Error> {
586         let requested_slot = slot.0 as usize;
587         if requested_slot == 0 || requested_slot == 1 {
588             debug!("key_slot == {}, nothing to delete", requested_slot);
589             return Err(km_err!(
590                 InvalidArgument,
591                 "requested slot {} which does not contain a per-key secret",
592                 requested_slot
593             ));
594         }
595         let key_slot_start = requested_slot * SECRET_SIZE;
596         let key_slot_end = key_slot_start + SECRET_SIZE;
597         if key_slot_start < FACTORY_FIRST_SECURE_DELETION_SECRET_POS {
598             // This should be unhittable (the test for slot 0 or 1 above will trigger) but keep
599             // in just in case of future arithmetic errors.
600             return Err(km_err!(
601                 InvalidArgument,
602                 "attempted to delete invalid key slot {}",
603                 requested_slot
604             ));
605         }
606         // TODO: Check if we should also stop trying to delete the key after some number of retries.
607         //       C++ code doesn't stop retrying, which is the current behavior here.
608         loop {
609             let mut session = match get_secure_deletion_secret_file_session(true) {
610                 Ok(session) => session,
611                 Err(e) => {
612                     error!("Failed to open session to retrieve secure deletion data: {:?}", e);
613                     continue;
614                 }
615             };
616             let mut sdsf_file = match SecureDeletionSecretFile::open_or_create(&mut session) {
617                 Ok(sdsf_file) => sdsf_file,
618                 Err(e) => {
619                     error!("Failed to open file to retrieve secure deletion data: {:?}", e);
620                     continue;
621                 }
622             };
623             let file_size = match sdsf_file.get_file_size() {
624                 Ok(size) => size,
625                 Err(_) => continue,
626             };
627             if key_slot_end > file_size {
628                 return Err(km_err!(
629                     InvalidArgument,
630                     "attempted to delete invalid key slot {}",
631                     requested_slot
632                 ));
633             }
634             if sdsf_file.zero_entries(key_slot_start, key_slot_end).is_err() {
635                 continue;
636             }
637             debug!(
638                 "Deleted secure key slot {}, zeroing {} to {}",
639                 requested_slot, key_slot_start, key_slot_end
640             );
641             if let Err(e) = sdsf_file.finish_transaction() {
642                 error!(
643                     "Failed to commit transaction deleting key at slot {}: {:?}",
644                     requested_slot, e
645                 );
646                 continue;
647             }
648             debug!("Committed deletion");
649             break;
650         }
651         Ok(())
652     }
653 
delete_all(&mut self)654     fn delete_all(&mut self) {
655         // TODO: Check if we should also stop trying to delete all keys after some number of
656         //       retries. C++ code doesn't stop retrying, which is the current behavior here.
657         loop {
658             match delete_secure_deletion_secret_file() {
659                 Ok(_) => break,
660                 Err(e) => error!("Couldn't delete file. Received error: {:?}", e),
661             }
662         }
663     }
664 }
665 
666 #[allow(dead_code)]
667 #[cfg(test)]
668 mod tests {
669     use super::*;
670     use kmr_crypto_boring::rng::BoringRng;
671     use test::{expect, expect_eq, expect_ne};
672 
secret_manager_file_exists() -> bool673     fn secret_manager_file_exists() -> bool {
674         let mut session =
675             Session::new(Port::TamperProof, true).expect("Couldn't connect to storage");
676         session.open_file(SECURE_DELETION_SECRET_FILENAME, OpenMode::Open).is_ok()
677     }
678 
679     // This test should be run manually as it writes to storage.
680     // #[test]
secret_data_is_cached()681     fn secret_data_is_cached() {
682         let mut sdsf = TrustySecureDeletionSecretManager::new();
683         sdsf.delete_all();
684         expect!(!secret_manager_file_exists(), "Couldn't delete secret manager file");
685         let mut rng = BoringRng::default();
686         let secret1 =
687             sdsf.get_or_create_factory_reset_secret(&mut rng).expect("Couldn't create secret");
688         let mut session = get_secure_deletion_secret_file_session(true).ok();
689         let secret2 = match sdsf.get_factory_reset_secret_impl(session.as_mut()) {
690             Ok(RetrieveSecureDeletionSecretFileData::CachedDataFound(secret)) => secret,
691             _ => panic!("Data should have been cached"),
692         };
693         let secret3 =
694             sdsf.get_or_create_factory_reset_secret(&mut rng).expect("Couldn't get secret");
695         expect_eq!(
696             secret1.factory_reset_secret,
697             secret2.factory_reset_secret,
698             "Should have retrieved the same secret"
699         );
700         expect_eq!(
701             secret1.secure_deletion_secret,
702             secret2.secure_deletion_secret,
703             "Should have retrieved the same secret"
704         );
705         expect_eq!(secret1.secure_deletion_secret, [0; SECRET_SIZE], "Deletion secret should be 0");
706         expect_ne!(
707             secret1.factory_reset_secret,
708             [0; FACTORY_RESET_SECRET_SIZE],
709             "Factory reset secret should not be 0"
710         );
711         expect_eq!(
712             secret1.factory_reset_secret,
713             secret3.factory_reset_secret,
714             "Should have retrieved the same secret"
715         );
716         sdsf.factory_reset_secret.replace(None);
717         let secret3 = match sdsf.get_factory_reset_secret_impl(session.as_mut()) {
718             Ok(RetrieveSecureDeletionSecretFileData::DataFoundOnFile(secret)) => secret,
719             _ => panic!("Data couldn't be read from file."),
720         };
721         expect_eq!(
722             secret1.factory_reset_secret,
723             secret3.factory_reset_secret,
724             "Should have retrieved the same secret"
725         );
726         sdsf.delete_all();
727         expect!(!secret_manager_file_exists(), "Couldn't delete secret manager file");
728     }
729 
730     // This test should be run manually as it writes to storage.
731     // #[test]
new_secret_data_file_is_clean()732     fn new_secret_data_file_is_clean() {
733         let mut sdsf = TrustySecureDeletionSecretManager::new();
734         sdsf.delete_all();
735         expect!(!secret_manager_file_exists(), "Couldn't delete secret manager file");
736         let mut rng = BoringRng::default();
737         let secret1 =
738             sdsf.get_or_create_factory_reset_secret(&mut rng).expect("Couldn't create secret");
739         let num_initial_slots = BLOCK_SIZE / SECRET_SIZE;
740         for slot_num in 2..num_initial_slots {
741             let secret =
742                 sdsf.get_secret(SecureDeletionSlot(slot_num as u32)).expect("Couldn't read slot");
743             expect_eq!(
744                 secret.secure_deletion_secret,
745                 [0; SECRET_SIZE],
746                 "Deletion secret should be 0"
747             );
748             expect_eq!(
749                 secret.factory_reset_secret,
750                 secret1.factory_reset_secret,
751                 "Factory reset secret should match"
752             );
753         }
754         let secret = sdsf.get_secret(SecureDeletionSlot(num_initial_slots as u32));
755         expect!(secret.is_err(), "Read outside of initial range should fail");
756         sdsf.delete_all();
757         expect!(!secret_manager_file_exists(), "Couldn't delete secret manager file");
758     }
759 
760     // Not running next test because it takes too long when run on build server, which causes unit
761     // tests to timeout sometimes. Also not using #[ignore] because it doesn't seem to be supported
762     // yet.
763     // Also, this test should be run manually as it writes to storage.
764 
765     // #[test]
766     #[allow(dead_code)]
new_secret_data_file_expands()767     fn new_secret_data_file_expands() {
768         let mut sdsf = TrustySecureDeletionSecretManager::new();
769         sdsf.delete_all();
770         expect!(!secret_manager_file_exists(), "Couldn't delete secret manager file");
771         let mut rng = BoringRng::default();
772         let _secret1 =
773             sdsf.get_or_create_factory_reset_secret(&mut rng).expect("Couldn't create secret");
774         let max_num_slots = MAX_SECRET_FILE_SIZE / SECRET_SIZE;
775         for slot_num in 2..max_num_slots {
776             let (deletion_slot, deletion_data) = sdsf
777                 .new_secret(&mut rng, SlotPurpose::KeyGeneration)
778                 .expect("Couldn't create secret");
779             // This test assumes order of secret creation on an empty file; next line can be changed
780             // to something like a map (to check that an empty slot if chosen every time) if order
781             // is not sequential anymore.
782             expect_eq!(deletion_slot.0 as usize, slot_num, "Wrong slot used for new secret");
783             expect_ne!(
784                 deletion_data.secure_deletion_secret,
785                 [0; SECRET_SIZE],
786                 "Deletion secret should not be 0"
787             );
788             expect_ne!(
789                 deletion_data.secure_deletion_secret[0] & IN_USE_FLAG,
790                 0,
791                 "Slot should be marked as in use"
792             );
793             let slot_data = sdsf.get_secret(deletion_slot).expect("Couldn't read back secret");
794             expect_eq!(
795                 deletion_data.secure_deletion_secret,
796                 slot_data.secure_deletion_secret,
797                 "Secret data should match"
798             );
799             expect_eq!(
800                 deletion_data.factory_reset_secret,
801                 slot_data.factory_reset_secret,
802                 "Factory reset secret should match"
803             );
804         }
805         let size_failure = sdsf.new_secret(&mut rng, SlotPurpose::KeyGeneration);
806         expect!(size_failure.is_err(), "Shouldn't be able to increase secret file size any larger");
807         // Testing upgrade flow
808         let max_num_upgrade_slots = (MAX_SECRET_FILE_SIZE_FOR_UPGRADES) / SECRET_SIZE;
809         for slot_num in max_num_slots..max_num_upgrade_slots {
810             let (deletion_slot, deletion_data) = sdsf
811                 .new_secret(&mut rng, SlotPurpose::KeyUpgrade)
812                 .expect("Couldn't create secret for upgrade flow");
813             expect_eq!(deletion_slot.0 as usize, slot_num, "Wrong slot used for new secret");
814             expect_ne!(
815                 deletion_data.secure_deletion_secret,
816                 [0; SECRET_SIZE],
817                 "Deletion secret should not be 0"
818             );
819             expect_ne!(
820                 deletion_data.secure_deletion_secret[0] & IN_USE_FLAG,
821                 0,
822                 "Slot should be marked as in use"
823             );
824             let slot_data = sdsf.get_secret(deletion_slot).expect("Couldn't read back secret");
825             expect_eq!(
826                 deletion_data.secure_deletion_secret,
827                 slot_data.secure_deletion_secret,
828                 "Secret data should match"
829             );
830             expect_eq!(
831                 deletion_data.factory_reset_secret,
832                 slot_data.factory_reset_secret,
833                 "Factory reset secret should match"
834             );
835         }
836         let size_failure = sdsf.new_secret(&mut rng, SlotPurpose::KeyUpgrade);
837         expect!(size_failure.is_err(), "Shouldn't be able to increase secret file size any larger");
838         // Testing deletion
839         for slot_num in (2..max_num_upgrade_slots).rev() {
840             let slot = SecureDeletionSlot(slot_num as u32);
841             sdsf.delete_secret(slot).expect("Couldn't delete secret");
842             let slot_data = sdsf.get_secret(slot).expect("Couldn't read back secret");
843             expect_eq!(
844                 slot_data.secure_deletion_secret,
845                 [0; SECRET_SIZE],
846                 "Deletion secret should be 0"
847             );
848             let (deletion_slot, deletion_data) =
849                 sdsf.new_secret(&mut rng, SlotPurpose::KeyUpgrade).expect("Couldn't create secret");
850             expect_eq!(deletion_slot.0 as usize, slot_num, "Wrong slot used for new secret");
851             expect_ne!(
852                 deletion_data.secure_deletion_secret,
853                 [0; SECRET_SIZE],
854                 "Deletion secret should not be 0"
855             );
856             expect_ne!(
857                 deletion_data.secure_deletion_secret[0] & IN_USE_FLAG,
858                 0,
859                 "Slot should be marked as in use"
860             );
861         }
862         sdsf.delete_all();
863         expect!(!secret_manager_file_exists(), "Couldn't delete secret manager file");
864     }
865 
866     // This test should be run manually as it writes to storage.
867     // #[test]
new_secret_data_dont_affect_neighbors()868     fn new_secret_data_dont_affect_neighbors() {
869         let mut sdsf = TrustySecureDeletionSecretManager::new();
870         sdsf.delete_all();
871         expect!(!secret_manager_file_exists(), "Couldn't delete secret manager file");
872         let mut rng = BoringRng::default();
873         let reset_secret = sdsf
874             .get_or_create_factory_reset_secret(&mut rng)
875             .expect("Couldn't create factory reset secret");
876         let (deletion_slot_1, _deletion_data_1) =
877             sdsf.new_secret(&mut rng, SlotPurpose::KeyGeneration).expect("Couldn't create secret");
878         sdsf.delete_secret(deletion_slot_1).expect("Couldn't delete secret");
879         // Delete cached data
880         sdsf.factory_reset_secret.replace(None);
881         let reset_secret_1 =
882             sdsf.get_factory_reset_secret().expect("Couldn't get factory reset secret");
883         expect_eq!(
884             reset_secret.factory_reset_secret,
885             reset_secret_1.factory_reset_secret,
886             "Factory reset secret should match"
887         );
888         let (deletion_slot_1, deletion_data_1) =
889             sdsf.new_secret(&mut rng, SlotPurpose::KeyGeneration).expect("Couldn't create secret");
890         let (deletion_slot_2, deletion_data_2) =
891             sdsf.new_secret(&mut rng, SlotPurpose::KeyGeneration).expect("Couldn't create secret");
892         let (deletion_slot_3, deletion_data_3) =
893             sdsf.new_secret(&mut rng, SlotPurpose::KeyGeneration).expect("Couldn't create secret");
894         let (deletion_slot_4, deletion_data_4) =
895             sdsf.new_secret(&mut rng, SlotPurpose::KeyGeneration).expect("Couldn't create secret");
896         let (deletion_slot_5, deletion_data_5) =
897             sdsf.new_secret(&mut rng, SlotPurpose::KeyGeneration).expect("Couldn't create secret");
898         let slot_data = sdsf.get_secret(deletion_slot_1).expect("Couldn't read back secret");
899         expect_eq!(
900             slot_data.secure_deletion_secret,
901             deletion_data_1.secure_deletion_secret,
902             "Secret data should match"
903         );
904         let slot_data = sdsf.get_secret(deletion_slot_2).expect("Couldn't read back secret");
905         expect_eq!(
906             slot_data.secure_deletion_secret,
907             deletion_data_2.secure_deletion_secret,
908             "Secret data should match"
909         );
910         let slot_data = sdsf.get_secret(deletion_slot_3).expect("Couldn't read back secret");
911         expect_eq!(
912             slot_data.secure_deletion_secret,
913             deletion_data_3.secure_deletion_secret,
914             "Secret data should match"
915         );
916         let slot_data = sdsf.get_secret(deletion_slot_4).expect("Couldn't read back secret");
917         expect_eq!(
918             slot_data.secure_deletion_secret,
919             deletion_data_4.secure_deletion_secret,
920             "Secret data should match"
921         );
922         let slot_data = sdsf.get_secret(deletion_slot_5).expect("Couldn't read back secret");
923         expect_eq!(
924             slot_data.secure_deletion_secret,
925             deletion_data_5.secure_deletion_secret,
926             "Secret data should match"
927         );
928         sdsf.delete_secret(deletion_slot_3).expect("Couldn't delete secret");
929         let slot_data = sdsf.get_secret(deletion_slot_1).expect("Couldn't read back secret");
930         expect_eq!(
931             slot_data.secure_deletion_secret,
932             deletion_data_1.secure_deletion_secret,
933             "Secret data should match"
934         );
935         let slot_data = sdsf.get_secret(deletion_slot_2).expect("Couldn't read back secret");
936         expect_eq!(
937             slot_data.secure_deletion_secret,
938             deletion_data_2.secure_deletion_secret,
939             "Secret data should match"
940         );
941         let slot_data = sdsf.get_secret(deletion_slot_3).expect("Couldn't read back secret");
942         expect_ne!(
943             slot_data.secure_deletion_secret,
944             deletion_data_3.secure_deletion_secret,
945             "Secret data should not match anymore"
946         );
947         let slot_data = sdsf.get_secret(deletion_slot_4).expect("Couldn't read back secret");
948         expect_eq!(
949             slot_data.secure_deletion_secret,
950             deletion_data_4.secure_deletion_secret,
951             "Secret data should match"
952         );
953         let slot_data = sdsf.get_secret(deletion_slot_5).expect("Couldn't read back secret");
954         expect_eq!(
955             slot_data.secure_deletion_secret,
956             deletion_data_5.secure_deletion_secret,
957             "Secret data should match"
958         );
959         // Delete cached data
960         sdsf.factory_reset_secret.replace(None);
961         let reset_secret_1 =
962             sdsf.get_factory_reset_secret().expect("Couldn't get factory reset secret");
963         expect_eq!(
964             reset_secret.factory_reset_secret,
965             reset_secret_1.factory_reset_secret,
966             "Factory reset secret should match"
967         );
968         sdsf.delete_all();
969         expect!(!secret_manager_file_exists(), "Couldn't delete secret manager file");
970     }
971 }
972 
973 /// Wrapper to allow a single instance of [`SecureDeletionSecretManager`] to be shared.
974 #[derive(Clone)]
975 pub struct SharedSddManager<T> {
976     inner: Rc<RefCell<T>>,
977 }
978 
979 impl<T> SharedSddManager<T> {
980     /// Move a [`SecureDeletionSecretManager`] into a shareable wrapper.
new(inner: T) -> Self981     pub fn new(inner: T) -> Self {
982         Self { inner: Rc::new(RefCell::new(inner)) }
983     }
984 }
985 
986 impl<T: SecureDeletionSecretManager> SecureDeletionSecretManager for SharedSddManager<T> {
get_or_create_factory_reset_secret( &mut self, rng: &mut dyn crypto::Rng, ) -> Result<SecureDeletionData, Error>987     fn get_or_create_factory_reset_secret(
988         &mut self,
989         rng: &mut dyn crypto::Rng,
990     ) -> Result<SecureDeletionData, Error> {
991         self.inner.borrow_mut().get_or_create_factory_reset_secret(rng)
992     }
993 
get_factory_reset_secret(&self) -> Result<SecureDeletionData, Error>994     fn get_factory_reset_secret(&self) -> Result<SecureDeletionData, Error> {
995         self.inner.borrow_mut().get_factory_reset_secret()
996     }
997 
new_secret( &mut self, rng: &mut dyn crypto::Rng, purpose: kmr_common::keyblob::SlotPurpose, ) -> Result<(SecureDeletionSlot, SecureDeletionData), Error>998     fn new_secret(
999         &mut self,
1000         rng: &mut dyn crypto::Rng,
1001         purpose: kmr_common::keyblob::SlotPurpose,
1002     ) -> Result<(SecureDeletionSlot, SecureDeletionData), Error> {
1003         self.inner.borrow_mut().new_secret(rng, purpose)
1004     }
1005 
get_secret(&self, slot: SecureDeletionSlot) -> Result<SecureDeletionData, Error>1006     fn get_secret(&self, slot: SecureDeletionSlot) -> Result<SecureDeletionData, Error> {
1007         self.inner.borrow().get_secret(slot)
1008     }
1009 
delete_secret(&mut self, slot: SecureDeletionSlot) -> Result<(), Error>1010     fn delete_secret(&mut self, slot: SecureDeletionSlot) -> Result<(), Error> {
1011         self.inner.borrow_mut().delete_secret(slot)
1012     }
1013 
delete_all(&mut self)1014     fn delete_all(&mut self) {
1015         self.inner.borrow_mut().delete_all()
1016     }
1017 }
1018