• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021, 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 //! Offer keys based on the "boot level" for superencryption.
16 
17 use crate::ks_err;
18 use crate::{
19     database::{KeyType, KeystoreDB},
20     key_parameter::KeyParameterValue,
21     raw_device::KeyMintDevice,
22 };
23 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
24     Algorithm::Algorithm, Digest::Digest, KeyParameter::KeyParameter as KmKeyParameter,
25     KeyPurpose::KeyPurpose, SecurityLevel::SecurityLevel,
26 };
27 use anyhow::{Context, Result};
28 use keystore2_crypto::{hkdf_expand, ZVec, AES_256_KEY_LENGTH};
29 use std::{collections::VecDeque, convert::TryFrom};
30 
31 /// Strategies used to prevent later boot stages from using the KM key that protects the level 0
32 /// key
33 #[derive(Debug, PartialEq, Eq, Clone, Copy)]
34 enum DenyLaterStrategy {
35     /// set MaxUsesPerBoot to 1. This is much less secure, since the attacker can replace the key
36     /// itself, and therefore create artifacts which appear to come from early boot.
37     MaxUsesPerBoot,
38     /// set the EarlyBootOnly property. This property is only supported in KM from 4.1 on, but
39     /// it ensures that the level 0 key was genuinely created in early boot
40     EarlyBootOnly,
41 }
42 
43 /// Generally the L0 KM and strategy are chosen by probing KM versions in TEE and Strongbox.
44 /// However, once a device is launched the KM and strategy must never change, even if the
45 /// KM version in TEE or Strongbox is updated. Setting this property at build time using
46 /// `PRODUCT_VENDOR_PROPERTIES` means that the strategy can be fixed no matter what versions
47 /// of KM are present.
48 const PROPERTY_NAME: &str = "ro.keystore.boot_level_key.strategy";
49 
lookup_level_zero_km_and_strategy() -> Result<Option<(SecurityLevel, DenyLaterStrategy)>>50 fn lookup_level_zero_km_and_strategy() -> Result<Option<(SecurityLevel, DenyLaterStrategy)>> {
51     let property_val = rustutils::system_properties::read(PROPERTY_NAME)
52         .with_context(|| ks_err!("property read failed: {}", PROPERTY_NAME))?;
53     // TODO: use feature(let_else) when that's stabilized.
54     let property_val = if let Some(p) = property_val {
55         p
56     } else {
57         log::info!("{} not set, inferring from installed KM instances", PROPERTY_NAME);
58         return Ok(None);
59     };
60     let (level, strategy) = if let Some(c) = property_val.split_once(':') {
61         c
62     } else {
63         log::error!("Missing colon in {}: {:?}", PROPERTY_NAME, property_val);
64         return Ok(None);
65     };
66     let level = match level {
67         "TRUSTED_ENVIRONMENT" => SecurityLevel::TRUSTED_ENVIRONMENT,
68         "STRONGBOX" => SecurityLevel::STRONGBOX,
69         _ => {
70             log::error!("Unknown security level in {}: {:?}", PROPERTY_NAME, level);
71             return Ok(None);
72         }
73     };
74     let strategy = match strategy {
75         "EARLY_BOOT_ONLY" => DenyLaterStrategy::EarlyBootOnly,
76         "MAX_USES_PER_BOOT" => DenyLaterStrategy::MaxUsesPerBoot,
77         _ => {
78             log::error!("Unknown DenyLaterStrategy in {}: {:?}", PROPERTY_NAME, strategy);
79             return Ok(None);
80         }
81     };
82     log::info!("Set from {}: {}", PROPERTY_NAME, property_val);
83     Ok(Some((level, strategy)))
84 }
85 
get_level_zero_key_km_and_strategy() -> Result<(KeyMintDevice, DenyLaterStrategy)>86 fn get_level_zero_key_km_and_strategy() -> Result<(KeyMintDevice, DenyLaterStrategy)> {
87     if let Some((level, strategy)) = lookup_level_zero_km_and_strategy()? {
88         return Ok((
89             KeyMintDevice::get(level).context(ks_err!("Get KM instance failed."))?,
90             strategy,
91         ));
92     }
93     let tee = KeyMintDevice::get(SecurityLevel::TRUSTED_ENVIRONMENT)
94         .context(ks_err!("Get TEE instance failed."))?;
95     if tee.version() >= KeyMintDevice::KEY_MASTER_V4_1 {
96         Ok((tee, DenyLaterStrategy::EarlyBootOnly))
97     } else {
98         match KeyMintDevice::get_or_none(SecurityLevel::STRONGBOX)
99             .context(ks_err!("Get Strongbox instance failed."))?
100         {
101             Some(strongbox) if strongbox.version() >= KeyMintDevice::KEY_MASTER_V4_1 => {
102                 Ok((strongbox, DenyLaterStrategy::EarlyBootOnly))
103             }
104             _ => Ok((tee, DenyLaterStrategy::MaxUsesPerBoot)),
105         }
106     }
107 }
108 
109 /// This is not thread safe; caller must hold a lock before calling.
110 /// In practice the caller is SuperKeyManager and the lock is the
111 /// Mutex on its internal state.
get_level_zero_key(db: &mut KeystoreDB) -> Result<ZVec>112 pub fn get_level_zero_key(db: &mut KeystoreDB) -> Result<ZVec> {
113     let (km_dev, deny_later_strategy) = get_level_zero_key_km_and_strategy()
114         .context(ks_err!("get preferred KM instance failed"))?;
115     log::info!(
116         "In get_level_zero_key: security_level={:?}, deny_later_strategy={:?}",
117         km_dev.security_level(),
118         deny_later_strategy
119     );
120     let required_security_level = km_dev.security_level();
121     let required_param: KmKeyParameter = match deny_later_strategy {
122         DenyLaterStrategy::EarlyBootOnly => KeyParameterValue::EarlyBootOnly,
123         DenyLaterStrategy::MaxUsesPerBoot => KeyParameterValue::MaxUsesPerBoot(1),
124     }
125     .into();
126     let params = vec![
127         KeyParameterValue::Algorithm(Algorithm::HMAC).into(),
128         KeyParameterValue::Digest(Digest::SHA_2_256).into(),
129         KeyParameterValue::KeySize(256).into(),
130         KeyParameterValue::MinMacLength(256).into(),
131         KeyParameterValue::KeyPurpose(KeyPurpose::SIGN).into(),
132         KeyParameterValue::NoAuthRequired.into(),
133         required_param.clone(),
134     ];
135 
136     let key_desc = KeyMintDevice::internal_descriptor("boot_level_key".to_string());
137     let (key_id_guard, key_entry) = km_dev
138         .lookup_or_generate_key(db, &key_desc, KeyType::Client, &params, |key_characteristics| {
139             key_characteristics.iter().any(|kc| {
140                 if kc.securityLevel != required_security_level {
141                     log::error!(
142                         "In get_level_zero_key: security level expected={:?} got={:?}",
143                         required_security_level,
144                         kc.securityLevel
145                     );
146                     return false;
147                 }
148                 if !kc.authorizations.iter().any(|a| a == &required_param) {
149                     log::error!(
150                         "In get_level_zero_key: required param absent {:?}",
151                         required_param
152                     );
153                     return false;
154                 }
155                 true
156             })
157         })
158         .context(ks_err!("lookup_or_generate_key failed"))?;
159 
160     let params = [
161         KeyParameterValue::MacLength(256).into(),
162         KeyParameterValue::Digest(Digest::SHA_2_256).into(),
163     ];
164     let level_zero_key = km_dev
165         .use_key_in_one_step(
166             db,
167             &key_id_guard,
168             &key_entry,
169             KeyPurpose::SIGN,
170             &params,
171             None,
172             b"Create boot level key",
173         )
174         .context(ks_err!("use_key_in_one_step failed"))?;
175     // TODO: this is rather unsatisfactory, we need a better way to handle
176     // sensitive binder returns.
177     let level_zero_key =
178         ZVec::try_from(level_zero_key).context(ks_err!("conversion to ZVec failed"))?;
179     Ok(level_zero_key)
180 }
181 
182 /// Holds the key for the current boot level, and a cache of future keys generated as required.
183 /// When the boot level advances, keys prior to the current boot level are securely dropped.
184 pub struct BootLevelKeyCache {
185     /// Least boot level currently accessible, if any is.
186     current: usize,
187     /// Invariant: cache entry *i*, if it exists, holds the HKDF key for boot level
188     /// *i* + `current`. If the cache is non-empty it can be grown forwards, but it cannot be
189     /// grown backwards, so keys below `current` are inaccessible.
190     /// `cache.clear()` makes all keys inaccessible.
191     cache: VecDeque<ZVec>,
192 }
193 
194 impl BootLevelKeyCache {
195     const HKDF_ADVANCE: &'static [u8] = b"Advance KDF one step";
196     const HKDF_AES: &'static [u8] = b"Generate AES-256-GCM key";
197     const HKDF_KEY_SIZE: usize = 32;
198 
199     /// Initialize the cache with the level zero key.
new(level_zero_key: ZVec) -> Self200     pub fn new(level_zero_key: ZVec) -> Self {
201         let mut cache: VecDeque<ZVec> = VecDeque::new();
202         cache.push_back(level_zero_key);
203         Self { current: 0, cache }
204     }
205 
206     /// Report whether the key for the given level can be inferred.
level_accessible(&self, boot_level: usize) -> bool207     pub fn level_accessible(&self, boot_level: usize) -> bool {
208         // If the requested boot level is lower than the current boot level
209         // or if we have reached the end (`cache.empty()`) we can't retrieve
210         // the boot key.
211         boot_level >= self.current && !self.cache.is_empty()
212     }
213 
214     /// Get the HKDF key for boot level `boot_level`. The key for level *i*+1
215     /// is calculated from the level *i* key using `hkdf_expand`.
get_hkdf_key(&mut self, boot_level: usize) -> Result<Option<&ZVec>>216     fn get_hkdf_key(&mut self, boot_level: usize) -> Result<Option<&ZVec>> {
217         if !self.level_accessible(boot_level) {
218             return Ok(None);
219         }
220         // `self.cache.len()` represents the first entry not in the cache,
221         // so `self.current + self.cache.len()` is the first boot level not in the cache.
222         let first_not_cached = self.current + self.cache.len();
223 
224         // Grow the cache forwards until it contains the desired boot level.
225         for _level in first_not_cached..=boot_level {
226             // We check at the start that cache is non-empty and future iterations only push,
227             // so this must unwrap.
228             let highest_key = self.cache.back().unwrap();
229             let next_key = hkdf_expand(Self::HKDF_KEY_SIZE, highest_key, Self::HKDF_ADVANCE)
230                 .context(ks_err!("Advancing key one step"))?;
231             self.cache.push_back(next_key);
232         }
233 
234         // If we reach this point, we should have a key at index boot_level - current.
235         Ok(Some(self.cache.get(boot_level - self.current).unwrap()))
236     }
237 
238     /// Drop keys prior to the given boot level, while retaining the ability to generate keys for
239     /// that level and later.
advance_boot_level(&mut self, new_boot_level: usize) -> Result<()>240     pub fn advance_boot_level(&mut self, new_boot_level: usize) -> Result<()> {
241         if !self.level_accessible(new_boot_level) {
242             log::error!(
243                 "Failed to advance boot level to {}, current is {}, cache size {}",
244                 new_boot_level,
245                 self.current,
246                 self.cache.len()
247             );
248             return Ok(());
249         }
250 
251         // We `get` the new boot level for the side effect of advancing the cache to a point
252         // where the new boot level is present.
253         self.get_hkdf_key(new_boot_level).context(ks_err!("Advancing cache"))?;
254 
255         // Then we split the queue at the index of the new boot level and discard the front,
256         // keeping only the keys with the current boot level or higher.
257         self.cache = self.cache.split_off(new_boot_level - self.current);
258 
259         // The new cache has the new boot level at index 0, so we set `current` to
260         // `new_boot_level`.
261         self.current = new_boot_level;
262 
263         Ok(())
264     }
265 
266     /// Drop all keys, effectively raising the current boot level to infinity; no keys can
267     /// be inferred from this point on.
finish(&mut self)268     pub fn finish(&mut self) {
269         self.cache.clear();
270     }
271 
expand_key( &mut self, boot_level: usize, out_len: usize, info: &[u8], ) -> Result<Option<ZVec>>272     fn expand_key(
273         &mut self,
274         boot_level: usize,
275         out_len: usize,
276         info: &[u8],
277     ) -> Result<Option<ZVec>> {
278         self.get_hkdf_key(boot_level)
279             .context(ks_err!("Looking up HKDF key"))?
280             .map(|k| hkdf_expand(out_len, k, info))
281             .transpose()
282             .context(ks_err!("Calling hkdf_expand"))
283     }
284 
285     /// Return the AES-256-GCM key for the current boot level.
aes_key(&mut self, boot_level: usize) -> Result<Option<ZVec>>286     pub fn aes_key(&mut self, boot_level: usize) -> Result<Option<ZVec>> {
287         self.expand_key(boot_level, AES_256_KEY_LENGTH, BootLevelKeyCache::HKDF_AES)
288             .context(ks_err!("expand_key failed"))
289     }
290 }
291 
292 #[cfg(test)]
293 mod test {
294     use super::*;
295 
296     #[test]
test_output_is_consistent() -> Result<()>297     fn test_output_is_consistent() -> Result<()> {
298         let initial_key = b"initial key";
299         let mut blkc = BootLevelKeyCache::new(ZVec::try_from(initial_key as &[u8])?);
300         assert!(blkc.level_accessible(0));
301         assert!(blkc.level_accessible(9));
302         assert!(blkc.level_accessible(10));
303         assert!(blkc.level_accessible(100));
304         let v0 = blkc.aes_key(0).unwrap().unwrap();
305         let v10 = blkc.aes_key(10).unwrap().unwrap();
306         assert_eq!(Some(&v0), blkc.aes_key(0)?.as_ref());
307         assert_eq!(Some(&v10), blkc.aes_key(10)?.as_ref());
308         blkc.advance_boot_level(5)?;
309         assert!(!blkc.level_accessible(0));
310         assert!(blkc.level_accessible(9));
311         assert!(blkc.level_accessible(10));
312         assert!(blkc.level_accessible(100));
313         assert_eq!(None, blkc.aes_key(0)?);
314         assert_eq!(Some(&v10), blkc.aes_key(10)?.as_ref());
315         blkc.advance_boot_level(10)?;
316         assert!(!blkc.level_accessible(0));
317         assert!(!blkc.level_accessible(9));
318         assert!(blkc.level_accessible(10));
319         assert!(blkc.level_accessible(100));
320         assert_eq!(None, blkc.aes_key(0)?);
321         assert_eq!(Some(&v10), blkc.aes_key(10)?.as_ref());
322         blkc.advance_boot_level(0)?;
323         assert!(!blkc.level_accessible(0));
324         assert!(!blkc.level_accessible(9));
325         assert!(blkc.level_accessible(10));
326         assert!(blkc.level_accessible(100));
327         assert_eq!(None, blkc.aes_key(0)?);
328         assert_eq!(Some(v10), blkc.aes_key(10)?);
329         blkc.finish();
330         assert!(!blkc.level_accessible(0));
331         assert!(!blkc.level_accessible(9));
332         assert!(!blkc.level_accessible(10));
333         assert!(!blkc.level_accessible(100));
334         assert_eq!(None, blkc.aes_key(0)?);
335         assert_eq!(None, blkc.aes_key(10)?);
336         Ok(())
337     }
338 }
339