xref: /aosp_15_r20/system/keymint/common/src/keyblob/sdd_mem.rs (revision 9860b7637a5f185913c70aa0caabe3ecb78441e4)
1*9860b763SAndroid Build Coastguard Worker // Copyright 2022, The Android Open Source Project
2*9860b763SAndroid Build Coastguard Worker //
3*9860b763SAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License");
4*9860b763SAndroid Build Coastguard Worker // you may not use this file except in compliance with the License.
5*9860b763SAndroid Build Coastguard Worker // You may obtain a copy of the License at
6*9860b763SAndroid Build Coastguard Worker //
7*9860b763SAndroid Build Coastguard Worker //     http://www.apache.org/licenses/LICENSE-2.0
8*9860b763SAndroid Build Coastguard Worker //
9*9860b763SAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*9860b763SAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS,
11*9860b763SAndroid Build Coastguard Worker // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12*9860b763SAndroid Build Coastguard Worker // See the License for the specific language governing permissions and
13*9860b763SAndroid Build Coastguard Worker // limitations under the License.
14*9860b763SAndroid Build Coastguard Worker 
15*9860b763SAndroid Build Coastguard Worker //! In-memory secure deletion secret manager.
16*9860b763SAndroid Build Coastguard Worker //!
17*9860b763SAndroid Build Coastguard Worker //! Only suitable for development/testing (as secrets are lost on restart).
18*9860b763SAndroid Build Coastguard Worker 
19*9860b763SAndroid Build Coastguard Worker use super::{SecureDeletionData, SecureDeletionSecretManager, SecureDeletionSlot, SlotPurpose};
20*9860b763SAndroid Build Coastguard Worker use crate::{crypto, km_err, Error};
21*9860b763SAndroid Build Coastguard Worker 
22*9860b763SAndroid Build Coastguard Worker /// Secure deletion secret manager that keeps state in memory. Provided as an example only; do not
23*9860b763SAndroid Build Coastguard Worker /// use in a real system (keys will not survive reboot if you do).
24*9860b763SAndroid Build Coastguard Worker pub struct InMemorySlotManager<const N: usize> {
25*9860b763SAndroid Build Coastguard Worker     factory_secret: Option<[u8; 32]>,
26*9860b763SAndroid Build Coastguard Worker     slots: [Option<SecureDeletionData>; N],
27*9860b763SAndroid Build Coastguard Worker }
28*9860b763SAndroid Build Coastguard Worker 
29*9860b763SAndroid Build Coastguard Worker impl<const N: usize> Default for InMemorySlotManager<N> {
default() -> Self30*9860b763SAndroid Build Coastguard Worker     fn default() -> Self {
31*9860b763SAndroid Build Coastguard Worker         Self {
32*9860b763SAndroid Build Coastguard Worker             factory_secret: None,
33*9860b763SAndroid Build Coastguard Worker             // Work around Rust limitation that `[None; N]` doesn't work.
34*9860b763SAndroid Build Coastguard Worker             slots: [(); N].map(|_| Option::<SecureDeletionData>::default()),
35*9860b763SAndroid Build Coastguard Worker         }
36*9860b763SAndroid Build Coastguard Worker     }
37*9860b763SAndroid Build Coastguard Worker }
38*9860b763SAndroid Build Coastguard Worker 
39*9860b763SAndroid Build Coastguard Worker impl<const N: usize> SecureDeletionSecretManager for InMemorySlotManager<N> {
get_or_create_factory_reset_secret( &mut self, rng: &mut dyn crypto::Rng, ) -> Result<SecureDeletionData, Error>40*9860b763SAndroid Build Coastguard Worker     fn get_or_create_factory_reset_secret(
41*9860b763SAndroid Build Coastguard Worker         &mut self,
42*9860b763SAndroid Build Coastguard Worker         rng: &mut dyn crypto::Rng,
43*9860b763SAndroid Build Coastguard Worker     ) -> Result<SecureDeletionData, Error> {
44*9860b763SAndroid Build Coastguard Worker         if self.factory_secret.is_none() {
45*9860b763SAndroid Build Coastguard Worker             // No factory reset secret created yet, so do so now.
46*9860b763SAndroid Build Coastguard Worker             let mut secret = [0; 32];
47*9860b763SAndroid Build Coastguard Worker             rng.fill_bytes(&mut secret[..]);
48*9860b763SAndroid Build Coastguard Worker             self.factory_secret = Some(secret);
49*9860b763SAndroid Build Coastguard Worker         }
50*9860b763SAndroid Build Coastguard Worker         self.get_factory_reset_secret()
51*9860b763SAndroid Build Coastguard Worker     }
52*9860b763SAndroid Build Coastguard Worker 
get_factory_reset_secret(&self) -> Result<SecureDeletionData, Error>53*9860b763SAndroid Build Coastguard Worker     fn get_factory_reset_secret(&self) -> Result<SecureDeletionData, Error> {
54*9860b763SAndroid Build Coastguard Worker         match self.factory_secret {
55*9860b763SAndroid Build Coastguard Worker             Some(secret) => Ok(SecureDeletionData {
56*9860b763SAndroid Build Coastguard Worker                 factory_reset_secret: secret,
57*9860b763SAndroid Build Coastguard Worker                 secure_deletion_secret: [0; 16],
58*9860b763SAndroid Build Coastguard Worker             }),
59*9860b763SAndroid Build Coastguard Worker             None => Err(km_err!(UnknownError, "no factory secret available!")),
60*9860b763SAndroid Build Coastguard Worker         }
61*9860b763SAndroid Build Coastguard Worker     }
62*9860b763SAndroid Build Coastguard Worker 
new_secret( &mut self, rng: &mut dyn crypto::Rng, _purpose: SlotPurpose, ) -> Result<(SecureDeletionSlot, SecureDeletionData), Error>63*9860b763SAndroid Build Coastguard Worker     fn new_secret(
64*9860b763SAndroid Build Coastguard Worker         &mut self,
65*9860b763SAndroid Build Coastguard Worker         rng: &mut dyn crypto::Rng,
66*9860b763SAndroid Build Coastguard Worker         _purpose: SlotPurpose,
67*9860b763SAndroid Build Coastguard Worker     ) -> Result<(SecureDeletionSlot, SecureDeletionData), Error> {
68*9860b763SAndroid Build Coastguard Worker         for idx in 0..N {
69*9860b763SAndroid Build Coastguard Worker             if self.slots[idx].is_none() {
70*9860b763SAndroid Build Coastguard Worker                 let mut sdd = self.get_or_create_factory_reset_secret(rng)?;
71*9860b763SAndroid Build Coastguard Worker                 rng.fill_bytes(&mut sdd.secure_deletion_secret[..]);
72*9860b763SAndroid Build Coastguard Worker                 self.slots[idx] = Some(sdd.clone());
73*9860b763SAndroid Build Coastguard Worker                 return Ok((SecureDeletionSlot(idx as u32), sdd));
74*9860b763SAndroid Build Coastguard Worker             }
75*9860b763SAndroid Build Coastguard Worker         }
76*9860b763SAndroid Build Coastguard Worker         Err(km_err!(RollbackResistanceUnavailable, "full"))
77*9860b763SAndroid Build Coastguard Worker     }
78*9860b763SAndroid Build Coastguard Worker 
get_secret(&self, slot: SecureDeletionSlot) -> Result<SecureDeletionData, Error>79*9860b763SAndroid Build Coastguard Worker     fn get_secret(&self, slot: SecureDeletionSlot) -> Result<SecureDeletionData, Error> {
80*9860b763SAndroid Build Coastguard Worker         let idx = slot.0 as usize;
81*9860b763SAndroid Build Coastguard Worker         if !(0..N).contains(&idx) {
82*9860b763SAndroid Build Coastguard Worker             return Err(km_err!(InvalidKeyBlob, "slot idx out of bounds"));
83*9860b763SAndroid Build Coastguard Worker         }
84*9860b763SAndroid Build Coastguard Worker         match &self.slots[idx] {
85*9860b763SAndroid Build Coastguard Worker             Some(data) => Ok(data.clone()),
86*9860b763SAndroid Build Coastguard Worker             None => Err(km_err!(InvalidKeyBlob, "slot idx empty")),
87*9860b763SAndroid Build Coastguard Worker         }
88*9860b763SAndroid Build Coastguard Worker     }
89*9860b763SAndroid Build Coastguard Worker 
delete_secret(&mut self, slot: SecureDeletionSlot) -> Result<(), Error>90*9860b763SAndroid Build Coastguard Worker     fn delete_secret(&mut self, slot: SecureDeletionSlot) -> Result<(), Error> {
91*9860b763SAndroid Build Coastguard Worker         match self.slots[slot.0 as usize].take() {
92*9860b763SAndroid Build Coastguard Worker             Some(_data) => Ok(()),
93*9860b763SAndroid Build Coastguard Worker             None => Err(km_err!(InvalidKeyBlob, "slot idx empty")),
94*9860b763SAndroid Build Coastguard Worker         }
95*9860b763SAndroid Build Coastguard Worker     }
96*9860b763SAndroid Build Coastguard Worker 
delete_all(&mut self)97*9860b763SAndroid Build Coastguard Worker     fn delete_all(&mut self) {
98*9860b763SAndroid Build Coastguard Worker         self.factory_secret = None;
99*9860b763SAndroid Build Coastguard Worker         for idx in 0..N {
100*9860b763SAndroid Build Coastguard Worker             self.slots[idx] = None;
101*9860b763SAndroid Build Coastguard Worker         }
102*9860b763SAndroid Build Coastguard Worker     }
103*9860b763SAndroid Build Coastguard Worker }
104