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