• 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::{
18     database::{KeyType, KeystoreDB},
19     key_parameter::KeyParameterValue,
20     raw_device::KeyMintDevice,
21 };
22 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
23     Algorithm::Algorithm, Digest::Digest, KeyParameter::KeyParameter as KmKeyParameter,
24     KeyParameterValue::KeyParameterValue as KmKeyParameterValue, KeyPurpose::KeyPurpose,
25     SecurityLevel::SecurityLevel, Tag::Tag,
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 
get_preferred_km_instance_for_level_zero_key() -> Result<KeyMintDevice>31 fn get_preferred_km_instance_for_level_zero_key() -> Result<KeyMintDevice> {
32     let tee = KeyMintDevice::get(SecurityLevel::TRUSTED_ENVIRONMENT)
33         .context("In get_preferred_km_instance_for_level_zero_key: Get TEE instance failed.")?;
34     if tee.version() >= KeyMintDevice::KEY_MASTER_V4_1 {
35         Ok(tee)
36     } else {
37         match KeyMintDevice::get_or_none(SecurityLevel::STRONGBOX).context(
38             "In get_preferred_km_instance_for_level_zero_key: Get Strongbox instance failed.",
39         )? {
40             Some(strongbox) if strongbox.version() >= KeyMintDevice::KEY_MASTER_V4_1 => {
41                 Ok(strongbox)
42             }
43             _ => Ok(tee),
44         }
45     }
46 }
47 
48 /// This is not thread safe; caller must hold a lock before calling.
49 /// In practice the caller is SuperKeyManager and the lock is the
50 /// Mutex on its internal state.
get_level_zero_key(db: &mut KeystoreDB) -> Result<ZVec>51 pub fn get_level_zero_key(db: &mut KeystoreDB) -> Result<ZVec> {
52     let km_dev = get_preferred_km_instance_for_level_zero_key()
53         .context("In get_level_zero_key: get preferred KM instance failed")?;
54 
55     let key_desc = KeyMintDevice::internal_descriptor("boot_level_key".to_string());
56     let mut params = vec![
57         KeyParameterValue::Algorithm(Algorithm::HMAC).into(),
58         KeyParameterValue::Digest(Digest::SHA_2_256).into(),
59         KeyParameterValue::KeySize(256).into(),
60         KeyParameterValue::MinMacLength(256).into(),
61         KeyParameterValue::KeyPurpose(KeyPurpose::SIGN).into(),
62         KeyParameterValue::NoAuthRequired.into(),
63     ];
64 
65     let has_early_boot_only = km_dev.version() >= KeyMintDevice::KEY_MASTER_V4_1;
66 
67     if has_early_boot_only {
68         params.push(KeyParameterValue::EarlyBootOnly.into());
69     } else {
70         params.push(KeyParameterValue::MaxUsesPerBoot(1).into())
71     }
72 
73     let (key_id_guard, key_entry) = km_dev
74         .lookup_or_generate_key(db, &key_desc, KeyType::Client, &params, |key_characteristics| {
75             key_characteristics.iter().any(|kc| {
76                 if kc.securityLevel == km_dev.security_level() {
77                     kc.authorizations.iter().any(|a| {
78                         matches!(
79                             (has_early_boot_only, a),
80                             (
81                                 true,
82                                 KmKeyParameter {
83                                     tag: Tag::EARLY_BOOT_ONLY,
84                                     value: KmKeyParameterValue::BoolValue(true)
85                                 }
86                             ) | (
87                                 false,
88                                 KmKeyParameter {
89                                     tag: Tag::MAX_USES_PER_BOOT,
90                                     value: KmKeyParameterValue::Integer(1)
91                                 }
92                             )
93                         )
94                     })
95                 } else {
96                     false
97                 }
98             })
99         })
100         .context("In get_level_zero_key: lookup_or_generate_key failed")?;
101 
102     let params = [
103         KeyParameterValue::MacLength(256).into(),
104         KeyParameterValue::Digest(Digest::SHA_2_256).into(),
105     ];
106     let level_zero_key = km_dev
107         .use_key_in_one_step(
108             db,
109             &key_id_guard,
110             &key_entry,
111             KeyPurpose::SIGN,
112             &params,
113             None,
114             b"Create boot level key",
115         )
116         .context("In get_level_zero_key: use_key_in_one_step failed")?;
117     // TODO: this is rather unsatisfactory, we need a better way to handle
118     // sensitive binder returns.
119     let level_zero_key = ZVec::try_from(level_zero_key)
120         .context("In get_level_zero_key: conversion to ZVec failed")?;
121     Ok(level_zero_key)
122 }
123 
124 /// Holds the key for the current boot level, and a cache of future keys generated as required.
125 /// When the boot level advances, keys prior to the current boot level are securely dropped.
126 pub struct BootLevelKeyCache {
127     /// Least boot level currently accessible, if any is.
128     current: usize,
129     /// Invariant: cache entry *i*, if it exists, holds the HKDF key for boot level
130     /// *i* + `current`. If the cache is non-empty it can be grown forwards, but it cannot be
131     /// grown backwards, so keys below `current` are inaccessible.
132     /// `cache.clear()` makes all keys inaccessible.
133     cache: VecDeque<ZVec>,
134 }
135 
136 impl BootLevelKeyCache {
137     const HKDF_ADVANCE: &'static [u8] = b"Advance KDF one step";
138     const HKDF_AES: &'static [u8] = b"Generate AES-256-GCM key";
139     const HKDF_KEY_SIZE: usize = 32;
140 
141     /// Initialize the cache with the level zero key.
new(level_zero_key: ZVec) -> Self142     pub fn new(level_zero_key: ZVec) -> Self {
143         let mut cache: VecDeque<ZVec> = VecDeque::new();
144         cache.push_back(level_zero_key);
145         Self { current: 0, cache }
146     }
147 
148     /// Report whether the key for the given level can be inferred.
level_accessible(&self, boot_level: usize) -> bool149     pub fn level_accessible(&self, boot_level: usize) -> bool {
150         // If the requested boot level is lower than the current boot level
151         // or if we have reached the end (`cache.empty()`) we can't retrieve
152         // the boot key.
153         boot_level >= self.current && !self.cache.is_empty()
154     }
155 
156     /// Get the HKDF key for boot level `boot_level`. The key for level *i*+1
157     /// is calculated from the level *i* key using `hkdf_expand`.
get_hkdf_key(&mut self, boot_level: usize) -> Result<Option<&ZVec>>158     fn get_hkdf_key(&mut self, boot_level: usize) -> Result<Option<&ZVec>> {
159         if !self.level_accessible(boot_level) {
160             return Ok(None);
161         }
162         // `self.cache.len()` represents the first entry not in the cache,
163         // so `self.current + self.cache.len()` is the first boot level not in the cache.
164         let first_not_cached = self.current + self.cache.len();
165 
166         // Grow the cache forwards until it contains the desired boot level.
167         for _level in first_not_cached..=boot_level {
168             // We check at the start that cache is non-empty and future iterations only push,
169             // so this must unwrap.
170             let highest_key = self.cache.back().unwrap();
171             let next_key = hkdf_expand(Self::HKDF_KEY_SIZE, highest_key, Self::HKDF_ADVANCE)
172                 .context("In BootLevelKeyCache::get_hkdf_key: Advancing key one step")?;
173             self.cache.push_back(next_key);
174         }
175 
176         // If we reach this point, we should have a key at index boot_level - current.
177         Ok(Some(self.cache.get(boot_level - self.current).unwrap()))
178     }
179 
180     /// Drop keys prior to the given boot level, while retaining the ability to generate keys for
181     /// that level and later.
advance_boot_level(&mut self, new_boot_level: usize) -> Result<()>182     pub fn advance_boot_level(&mut self, new_boot_level: usize) -> Result<()> {
183         if !self.level_accessible(new_boot_level) {
184             log::error!(
185                 concat!(
186                     "In BootLevelKeyCache::advance_boot_level: ",
187                     "Failed to advance boot level to {}, current is {}, cache size {}"
188                 ),
189                 new_boot_level,
190                 self.current,
191                 self.cache.len()
192             );
193             return Ok(());
194         }
195 
196         // We `get` the new boot level for the side effect of advancing the cache to a point
197         // where the new boot level is present.
198         self.get_hkdf_key(new_boot_level)
199             .context("In BootLevelKeyCache::advance_boot_level: Advancing cache")?;
200 
201         // Then we split the queue at the index of the new boot level and discard the front,
202         // keeping only the keys with the current boot level or higher.
203         self.cache = self.cache.split_off(new_boot_level - self.current);
204 
205         // The new cache has the new boot level at index 0, so we set `current` to
206         // `new_boot_level`.
207         self.current = new_boot_level;
208 
209         Ok(())
210     }
211 
212     /// Drop all keys, effectively raising the current boot level to infinity; no keys can
213     /// be inferred from this point on.
finish(&mut self)214     pub fn finish(&mut self) {
215         self.cache.clear();
216     }
217 
expand_key( &mut self, boot_level: usize, out_len: usize, info: &[u8], ) -> Result<Option<ZVec>>218     fn expand_key(
219         &mut self,
220         boot_level: usize,
221         out_len: usize,
222         info: &[u8],
223     ) -> Result<Option<ZVec>> {
224         self.get_hkdf_key(boot_level)
225             .context("In BootLevelKeyCache::expand_key: Looking up HKDF key")?
226             .map(|k| hkdf_expand(out_len, k, info))
227             .transpose()
228             .context("In BootLevelKeyCache::expand_key: Calling hkdf_expand")
229     }
230 
231     /// Return the AES-256-GCM key for the current boot level.
aes_key(&mut self, boot_level: usize) -> Result<Option<ZVec>>232     pub fn aes_key(&mut self, boot_level: usize) -> Result<Option<ZVec>> {
233         self.expand_key(boot_level, AES_256_KEY_LENGTH, BootLevelKeyCache::HKDF_AES)
234             .context("In BootLevelKeyCache::aes_key: expand_key failed")
235     }
236 }
237 
238 #[cfg(test)]
239 mod test {
240     use super::*;
241 
242     #[test]
test_output_is_consistent() -> Result<()>243     fn test_output_is_consistent() -> Result<()> {
244         let initial_key = b"initial key";
245         let mut blkc = BootLevelKeyCache::new(ZVec::try_from(initial_key as &[u8])?);
246         assert_eq!(true, blkc.level_accessible(0));
247         assert_eq!(true, blkc.level_accessible(9));
248         assert_eq!(true, blkc.level_accessible(10));
249         assert_eq!(true, blkc.level_accessible(100));
250         let v0 = blkc.aes_key(0).unwrap().unwrap();
251         let v10 = blkc.aes_key(10).unwrap().unwrap();
252         assert_eq!(Some(&v0), blkc.aes_key(0)?.as_ref());
253         assert_eq!(Some(&v10), blkc.aes_key(10)?.as_ref());
254         blkc.advance_boot_level(5)?;
255         assert_eq!(false, blkc.level_accessible(0));
256         assert_eq!(true, blkc.level_accessible(9));
257         assert_eq!(true, blkc.level_accessible(10));
258         assert_eq!(true, blkc.level_accessible(100));
259         assert_eq!(None, blkc.aes_key(0)?);
260         assert_eq!(Some(&v10), blkc.aes_key(10)?.as_ref());
261         blkc.advance_boot_level(10)?;
262         assert_eq!(false, blkc.level_accessible(0));
263         assert_eq!(false, blkc.level_accessible(9));
264         assert_eq!(true, blkc.level_accessible(10));
265         assert_eq!(true, blkc.level_accessible(100));
266         assert_eq!(None, blkc.aes_key(0)?);
267         assert_eq!(Some(&v10), blkc.aes_key(10)?.as_ref());
268         blkc.advance_boot_level(0)?;
269         assert_eq!(false, blkc.level_accessible(0));
270         assert_eq!(false, blkc.level_accessible(9));
271         assert_eq!(true, blkc.level_accessible(10));
272         assert_eq!(true, blkc.level_accessible(100));
273         assert_eq!(None, blkc.aes_key(0)?);
274         assert_eq!(Some(v10), blkc.aes_key(10)?);
275         blkc.finish();
276         assert_eq!(false, blkc.level_accessible(0));
277         assert_eq!(false, blkc.level_accessible(9));
278         assert_eq!(false, blkc.level_accessible(10));
279         assert_eq!(false, blkc.level_accessible(100));
280         assert_eq!(None, blkc.aes_key(0)?);
281         assert_eq!(None, blkc.aes_key(10)?);
282         Ok(())
283     }
284 }
285