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