1 // Copyright (C) 2023 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 //      http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 //! Secure deletion data manager for Cuttlefish.
16 //! This implementetation is "secure" in the sense that the underlying storage can not be accessed
17 //! by Android. However, it is does not provide any protections against the host, i.e. anyone with
18 //! access to the host can read and alter the contents of deletion data.
19 
20 use kmr_common::{crypto, keyblob, km_err, Error};
21 use kmr_proto::storage;
22 use log::{error, info};
23 use protobuf::Message;
24 use std::fs;
25 use std::path;
26 
27 const SECURE_DELETION_DATA_FILE: &str = "keymint_secure_deletion_data";
28 
read_sdd_file() -> Result<storage::SecureDeletionData, Error>29 fn read_sdd_file() -> Result<storage::SecureDeletionData, Error> {
30     let mut f = fs::File::open(SECURE_DELETION_DATA_FILE).map_err(|e| {
31         km_err!(SecureHwCommunicationFailed, "failed to open secure deletion data file: {:?}", e)
32     })?;
33     storage::SecureDeletionData::parse_from_reader(&mut f).map_err(|e| {
34         km_err!(SecureHwCommunicationFailed, "failed to parse secure deletion data: {:?}", e)
35     })
36 }
37 
write_sdd_file(data: &storage::SecureDeletionData) -> Result<(), Error>38 fn write_sdd_file(data: &storage::SecureDeletionData) -> Result<(), Error> {
39     let mut f = fs::File::create(SECURE_DELETION_DATA_FILE).map_err(|e| {
40         km_err!(SecureHwCommunicationFailed, "failed to create secure deletion data file: {:?}", e)
41     })?;
42     data.write_to_writer(&mut f).map_err(|e| {
43         km_err!(
44             SecureHwCommunicationFailed,
45             "failed to write to secure deletion data file: {:?}",
46             e
47         )
48     })
49 }
50 
51 pub struct HostSddManager {
52     // Local cache of data stored on disk.
53     data: storage::SecureDeletionData,
54 }
55 
56 impl HostSddManager {
init(&mut self, rng: &mut dyn crypto::Rng) -> Result<(), Error>57     fn init(&mut self, rng: &mut dyn crypto::Rng) -> Result<(), Error> {
58         // Restore data from disk if it was previously saved.
59         if path::Path::new(SECURE_DELETION_DATA_FILE).exists() {
60             info!("Secure deletion data file found. Parsing.");
61             self.data = read_sdd_file()?;
62             return Ok(());
63         }
64 
65         info!("No secure deletion data file found. Creating one.");
66 
67         // Initialize factory reset secret.
68         self.data.factory_secret.resize(32, 0);
69         rng.fill_bytes(&mut self.data.factory_secret[..]);
70 
71         // Create secure deletion data file.
72         write_sdd_file(&self.data)
73     }
74 
new(rng: &mut dyn crypto::Rng) -> Result<Self, Error>75     pub fn new(rng: &mut dyn crypto::Rng) -> Result<Self, Error> {
76         let mut sdd_mgr = Self { data: storage::SecureDeletionData::default() };
77         sdd_mgr.init(rng).map(|_| sdd_mgr)
78     }
79 }
80 
81 impl keyblob::SecureDeletionSecretManager for HostSddManager {
get_or_create_factory_reset_secret( &mut self, rng: &mut dyn crypto::Rng, ) -> Result<keyblob::SecureDeletionData, Error>82     fn get_or_create_factory_reset_secret(
83         &mut self,
84         rng: &mut dyn crypto::Rng,
85     ) -> Result<keyblob::SecureDeletionData, Error> {
86         if self.data.factory_secret.is_empty() {
87             self.init(rng)?;
88         }
89         self.get_factory_reset_secret()
90     }
91 
get_factory_reset_secret(&self) -> Result<keyblob::SecureDeletionData, Error>92     fn get_factory_reset_secret(&self) -> Result<keyblob::SecureDeletionData, Error> {
93         if self.data.factory_secret.is_empty() {
94             return Err(km_err!(UnknownError, "no factory secret available"));
95         }
96         Ok(keyblob::SecureDeletionData {
97             factory_reset_secret: self.data.factory_secret.clone().try_into().unwrap(),
98             secure_deletion_secret: [0; 16],
99         })
100     }
101 
new_secret( &mut self, rng: &mut dyn crypto::Rng, _purpose: keyblob::SlotPurpose, ) -> Result<(keyblob::SecureDeletionSlot, keyblob::SecureDeletionData), Error>102     fn new_secret(
103         &mut self,
104         rng: &mut dyn crypto::Rng,
105         _purpose: keyblob::SlotPurpose,
106     ) -> Result<(keyblob::SecureDeletionSlot, keyblob::SecureDeletionData), Error> {
107         // Allocate new slot ID.
108         let slot_id = self
109             .data
110             .last_free_slot
111             .checked_add(1)
112             .ok_or(km_err!(RollbackResistanceUnavailable, "ran out of slot IDs"))?;
113 
114         info!("Generating new secret with slot ID: {:?}", slot_id);
115 
116         assert!(
117             !self.data.secure_deletion_secrets.contains_key(&slot_id),
118             "Slot ID already in use: {:?}",
119             slot_id
120         );
121 
122         // Generate new sdd.
123         let mut sdd = self.get_or_create_factory_reset_secret(rng)?;
124         rng.fill_bytes(&mut sdd.secure_deletion_secret[..]);
125 
126         // Cache the secure deletion secret locally.
127         self.data.secure_deletion_secrets.insert(slot_id, sdd.secure_deletion_secret.to_vec());
128         self.data.last_free_slot = slot_id;
129 
130         // Save the secure deletion secret on disk.
131         match write_sdd_file(&self.data) {
132             Ok(_) => Ok((keyblob::SecureDeletionSlot(slot_id), sdd)),
133             Err(e) => {
134                 // Restore cached state.
135                 self.data.secure_deletion_secrets.remove(&slot_id).unwrap();
136                 self.data.last_free_slot = slot_id - 1;
137                 Err(e)
138             }
139         }
140     }
141 
get_secret( &self, slot: keyblob::SecureDeletionSlot, ) -> Result<keyblob::SecureDeletionData, Error>142     fn get_secret(
143         &self,
144         slot: keyblob::SecureDeletionSlot,
145     ) -> Result<keyblob::SecureDeletionData, Error> {
146         let slot_id = slot.0;
147         info!("Fetching secret with slot ID: {:?}", slot_id);
148 
149         let secret = self.data.secure_deletion_secrets.get(&slot_id).ok_or(km_err!(
150             InvalidKeyBlob,
151             "slot ID: {:?} not found.",
152             slot_id
153         ))?;
154         Ok(keyblob::SecureDeletionData {
155             factory_reset_secret: self.data.factory_secret.clone().try_into().unwrap(),
156             secure_deletion_secret: secret.clone().try_into().unwrap(),
157         })
158     }
159 
delete_secret(&mut self, slot: keyblob::SecureDeletionSlot) -> Result<(), Error>160     fn delete_secret(&mut self, slot: keyblob::SecureDeletionSlot) -> Result<(), Error> {
161         let slot_id = slot.0;
162         info!("Deleting secret with slot ID: {:?}", slot_id);
163 
164         let secret = self
165             .data
166             .secure_deletion_secrets
167             .remove(&slot_id)
168             .ok_or(km_err!(InvalidKeyBlob, "slot ID not found."))?;
169 
170         // Save the secure deletion secret on disk.
171         if let Err(e) = write_sdd_file(&self.data) {
172             // Restore cached state.
173             self.data.secure_deletion_secrets.insert(slot_id, secret).unwrap();
174             return Err(e);
175         }
176         Ok(())
177     }
178 
delete_all(&mut self)179     fn delete_all(&mut self) {
180         info!("Deleting all secrets");
181         self.data = storage::SecureDeletionData::default();
182         if path::Path::new(SECURE_DELETION_DATA_FILE).exists() {
183             // We want to guarantee that if this function returns, all secrets have been
184             // successfully deleted. So, panic if we fail to delete the file.
185             for _ in 0..5 {
186                 match fs::remove_file(SECURE_DELETION_DATA_FILE) {
187                     Ok(_) => return,
188                     Err(e) => error!("Couldn't delete file: {:?}", e),
189                 }
190             }
191             panic!("FATAL: Failed to delete secure deletion data file.");
192         }
193     }
194 }
195