blob: dd69ed79be45cd48acf5a0b331529e9455593d68 [file] [log] [blame]
Paul Crowley44c02da2021-04-08 17:04:43 +00001// 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
17use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
18 Algorithm::Algorithm, BeginResult::BeginResult, Digest::Digest, ErrorCode::ErrorCode,
19 IKeyMintDevice::IKeyMintDevice, IKeyMintOperation::IKeyMintOperation,
20 KeyParameter::KeyParameter, KeyPurpose::KeyPurpose, SecurityLevel::SecurityLevel,
21};
22use android_system_keystore2::aidl::android::system::keystore2::{
23 Domain::Domain, KeyDescriptor::KeyDescriptor, ResponseCode::ResponseCode,
24};
25use anyhow::{Context, Result};
26use binder::Strong;
27use keystore2_crypto::{hkdf_expand, ZVec, AES_256_KEY_LENGTH};
28use std::{collections::VecDeque, convert::TryFrom};
29
30use crate::{
31 database::{
32 BlobMetaData, BlobMetaEntry, CertificateInfo, DateTime, KeyEntry, KeyEntryLoadBits,
33 KeyIdGuard, KeyMetaData, KeyMetaEntry, KeyType, KeystoreDB, SubComponentType, Uuid,
34 },
35 error::{map_km_error, Error},
36 globals::get_keymint_device,
37 key_parameter::KeyParameterValue,
38 super_key::KeyBlob,
39 utils::{key_characteristics_to_internal, Asp, AID_KEYSTORE},
40};
41
42/// Wrapper for operating directly on a KeyMint device.
43/// These methods often mirror methods in [`crate::security_level`]. However
44/// the functions in [`crate::security_level`] make assumptions that hold, and has side effects
45/// that make sense, only if called by an external client through binder.
46/// In addition we are trying to maintain a separation between interface services
47/// so that the architecture is compatible with a future move to multiple thread pools.
48/// So the simplest approach today is to write new implementations of them for internal use.
49/// Because these methods run very early, we don't even try to cooperate with
50/// the operation slot database; we assume there will be plenty of slots.
51struct KeyMintDevice {
52 asp: Asp,
53 km_uuid: Uuid,
54}
55
56impl KeyMintDevice {
57 fn get(security_level: SecurityLevel) -> Result<KeyMintDevice> {
58 let (asp, _hw_info, km_uuid) = get_keymint_device(&security_level)
59 .context("In KeyMintDevice::get: get_keymint_device failed")?;
60 Ok(KeyMintDevice { asp, km_uuid })
61 }
62
63 /// Generate a KM key and store in the database.
64 fn generate_and_store_key(
65 &self,
66 db: &mut KeystoreDB,
67 key_desc: &KeyDescriptor,
68 params: &[KeyParameter],
69 ) -> Result<()> {
70 let km_dev: Strong<dyn IKeyMintDevice> = self
71 .asp
72 .get_interface()
73 .context("In generate_and_store_key: Failed to get KeyMint device")?;
74 let creation_result = map_km_error(km_dev.generateKey(params, None))
75 .context("In generate_and_store_key: generateKey failed")?;
76 let key_parameters = key_characteristics_to_internal(creation_result.keyCharacteristics);
77
78 let creation_date =
79 DateTime::now().context("In generate_and_store_key: DateTime::now() failed")?;
80
81 let mut key_metadata = KeyMetaData::new();
82 key_metadata.add(KeyMetaEntry::CreationDate(creation_date));
83 let mut blob_metadata = BlobMetaData::new();
84 blob_metadata.add(BlobMetaEntry::KmUuid(self.km_uuid));
85
86 db.store_new_key(
87 &key_desc,
88 &key_parameters,
89 &(&creation_result.keyBlob, &blob_metadata),
90 &CertificateInfo::new(None, None),
91 &key_metadata,
92 &self.km_uuid,
93 )
94 .context("In generate_and_store_key: store_new_key failed")?;
95 Ok(())
96 }
97
98 /// This does the lookup and store in separate transactions; caller must
99 /// hold a lock before calling.
100 fn lookup_or_generate_key(
101 &self,
102 db: &mut KeystoreDB,
103 key_desc: &KeyDescriptor,
104 params: &[KeyParameter],
105 ) -> Result<(KeyIdGuard, KeyEntry)> {
106 // We use a separate transaction for the lookup than for the store
107 // - to keep the code simple
108 // - because the caller needs to hold a lock in any case
109 // - because it avoids holding database locks during slow
110 // KeyMint operations
111 let lookup = db.load_key_entry(
112 &key_desc,
113 KeyType::Client,
114 KeyEntryLoadBits::KM,
115 AID_KEYSTORE,
116 |_, _| Ok(()),
117 );
118 match lookup {
119 Ok(result) => return Ok(result),
120 Err(e) => match e.root_cause().downcast_ref::<Error>() {
121 Some(&Error::Rc(ResponseCode::KEY_NOT_FOUND)) => {}
122 _ => return Err(e),
123 },
124 }
125 self.generate_and_store_key(db, &key_desc, &params)
126 .context("In lookup_or_generate_key: generate_and_store_key failed")?;
127 db.load_key_entry(&key_desc, KeyType::Client, KeyEntryLoadBits::KM, AID_KEYSTORE, |_, _| {
128 Ok(())
129 })
130 .context("In lookup_or_generate_key: load_key_entry failed")
131 }
132
133 /// Call the passed closure; if it returns `KEY_REQUIRES_UPGRADE`, call upgradeKey, and
134 /// write the upgraded key to the database.
135 fn upgrade_keyblob_if_required_with<T, F>(
136 &self,
137 db: &mut KeystoreDB,
138 km_dev: &Strong<dyn IKeyMintDevice>,
139 key_id_guard: KeyIdGuard,
140 key_blob: &KeyBlob,
141 f: F,
142 ) -> Result<T>
143 where
144 F: Fn(&[u8]) -> Result<T, Error>,
145 {
146 match f(key_blob) {
147 Err(Error::Km(ErrorCode::KEY_REQUIRES_UPGRADE)) => {
148 let upgraded_blob = map_km_error(km_dev.upgradeKey(key_blob, &[]))
149 .context("In upgrade_keyblob_if_required_with: Upgrade failed")?;
150
151 let mut new_blob_metadata = BlobMetaData::new();
152 new_blob_metadata.add(BlobMetaEntry::KmUuid(self.km_uuid));
153
154 db.set_blob(
155 &key_id_guard,
156 SubComponentType::KEY_BLOB,
157 Some(&upgraded_blob),
158 Some(&new_blob_metadata),
159 )
160 .context(concat!(
161 "In upgrade_keyblob_if_required_with: ",
162 "Failed to insert upgraded blob into the database"
163 ))?;
164
165 Ok(f(&upgraded_blob).context(concat!(
166 "In upgrade_keyblob_if_required_with: ",
167 "Closure failed after upgrade"
168 ))?)
169 }
170 result => Ok(result.context("In upgrade_keyblob_if_required_with: Closure failed")?),
171 }
172 }
173
174 /// Use the created key in an operation that can be done with
175 /// a call to begin followed by a call to finish.
176 fn use_key_in_one_step(
177 &self,
178 db: &mut KeystoreDB,
179 key_id_guard: KeyIdGuard,
180 key_entry: &KeyEntry,
181 purpose: KeyPurpose,
182 operation_parameters: &[KeyParameter],
183 input: &[u8],
184 ) -> Result<Vec<u8>> {
185 let km_dev: Strong<dyn IKeyMintDevice> = self
186 .asp
187 .get_interface()
188 .context("In use_key_in_one_step: Failed to get KeyMint device")?;
189
190 let (key_blob, _blob_metadata) = key_entry
191 .key_blob_info()
192 .as_ref()
193 .ok_or_else(Error::sys)
194 .context("use_key_in_one_step: Keyblob missing")?;
195 let key_blob = KeyBlob::Ref(&key_blob);
196
197 let begin_result: BeginResult = self
198 .upgrade_keyblob_if_required_with(db, &km_dev, key_id_guard, &key_blob, |blob| {
199 map_km_error(km_dev.begin(purpose, blob, operation_parameters, &Default::default()))
200 })
201 .context("In use_key_in_one_step: Failed to begin operation.")?;
202 let operation: Strong<dyn IKeyMintOperation> = begin_result
203 .operation
204 .ok_or_else(Error::sys)
205 .context("In use_key_in_one_step: Operation missing")?;
206 map_km_error(operation.finish(Some(input), None, None, None, None))
207 .context("In use_key_in_one_step: Failed to finish operation.")
208 }
209}
210
211/// This is not thread safe; caller must hold a lock before calling.
212/// In practice the caller is SuperKeyManager and the lock is the
213/// Mutex on its internal state.
214pub fn get_level_zero_key(db: &mut KeystoreDB) -> Result<ZVec> {
215 let key_desc = KeyDescriptor {
216 domain: Domain::APP,
217 nspace: AID_KEYSTORE as i64,
218 alias: Some("boot_level_key".to_string()),
219 blob: None,
220 };
221 let params = [
222 KeyParameterValue::Algorithm(Algorithm::HMAC).into(),
223 KeyParameterValue::Digest(Digest::SHA_2_256).into(),
224 KeyParameterValue::KeySize(256).into(),
225 KeyParameterValue::MinMacLength(256).into(),
226 KeyParameterValue::KeyPurpose(KeyPurpose::SIGN).into(),
Paul Crowleyeb964cf2021-04-19 18:14:15 -0700227 KeyParameterValue::NoAuthRequired.into(),
Paul Crowley44c02da2021-04-08 17:04:43 +0000228 KeyParameterValue::MaxUsesPerBoot(1).into(),
229 ];
230 // We use TRUSTED_ENVIRONMENT here because it is the authority on when
231 // the device has rebooted.
232 let km_dev: KeyMintDevice = KeyMintDevice::get(SecurityLevel::TRUSTED_ENVIRONMENT)
233 .context("In get_level_zero_key: KeyMintDevice::get failed")?;
234 let (key_id_guard, key_entry) = km_dev
235 .lookup_or_generate_key(db, &key_desc, &params)
236 .context("In get_level_zero_key: lookup_or_generate_key failed")?;
237
238 let params = [KeyParameterValue::MacLength(256).into()];
239 let level_zero_key = km_dev
240 .use_key_in_one_step(
241 db,
242 key_id_guard,
243 &key_entry,
244 KeyPurpose::SIGN,
245 &params,
246 b"Create boot level key",
247 )
248 .context("In get_level_zero_key: use_key_in_one_step failed")?;
249 // TODO: this is rather unsatisfactory, we need a better way to handle
250 // sensitive binder returns.
251 let level_zero_key = ZVec::try_from(level_zero_key)
252 .context("In get_level_zero_key: conversion to ZVec failed")?;
253 Ok(level_zero_key)
254}
255
256/// Holds the key for the current boot level, and a cache of future keys generated as required.
257/// When the boot level advances, keys prior to the current boot level are securely dropped.
258pub struct BootLevelKeyCache {
259 /// Least boot level currently accessible, if any is.
260 current: usize,
261 /// Invariant: cache entry *i*, if it exists, holds the HKDF key for boot level
262 /// *i* + `current`. If the cache is non-empty it can be grown forwards, but it cannot be
263 /// grown backwards, so keys below `current` are inaccessible.
264 /// `cache.clear()` makes all keys inaccessible.
265 cache: VecDeque<ZVec>,
266}
267
268impl BootLevelKeyCache {
269 const HKDF_ADVANCE: &'static [u8] = b"Advance KDF one step";
270 const HKDF_AES: &'static [u8] = b"Generate AES-256-GCM key";
271 const HKDF_KEY_SIZE: usize = 32;
272
273 /// Initialize the cache with the level zero key.
274 pub fn new(level_zero_key: ZVec) -> Self {
275 let mut cache: VecDeque<ZVec> = VecDeque::new();
276 cache.push_back(level_zero_key);
277 Self { current: 0, cache }
278 }
279
280 /// Report whether the key for the given level can be inferred.
281 pub fn level_accessible(&self, boot_level: usize) -> bool {
282 // If the requested boot level is lower than the current boot level
283 // or if we have reached the end (`cache.empty()`) we can't retrieve
284 // the boot key.
285 boot_level >= self.current && !self.cache.is_empty()
286 }
287
288 /// Get the HKDF key for boot level `boot_level`. The key for level *i*+1
289 /// is calculated from the level *i* key using `hkdf_expand`.
290 fn get_hkdf_key(&mut self, boot_level: usize) -> Result<Option<&ZVec>> {
291 if !self.level_accessible(boot_level) {
292 return Ok(None);
293 }
294 // `self.cache.len()` represents the first entry not in the cache,
295 // so `self.current + self.cache.len()` is the first boot level not in the cache.
296 let first_not_cached = self.current + self.cache.len();
297
298 // Grow the cache forwards until it contains the desired boot level.
299 for _level in first_not_cached..=boot_level {
300 // We check at the start that cache is non-empty and future iterations only push,
301 // so this must unwrap.
302 let highest_key = self.cache.back().unwrap();
303 let next_key = hkdf_expand(Self::HKDF_KEY_SIZE, highest_key, Self::HKDF_ADVANCE)
304 .context("In BootLevelKeyCache::get_hkdf_key: Advancing key one step")?;
305 self.cache.push_back(next_key);
306 }
307
308 // If we reach this point, we should have a key at index boot_level - current.
309 Ok(Some(self.cache.get(boot_level - self.current).unwrap()))
310 }
311
312 /// Drop keys prior to the given boot level, while retaining the ability to generate keys for
313 /// that level and later.
314 pub fn advance_boot_level(&mut self, new_boot_level: usize) -> Result<()> {
315 if !self.level_accessible(new_boot_level) {
316 log::error!(
317 concat!(
318 "In BootLevelKeyCache::advance_boot_level: ",
319 "Failed to advance boot level to {}, current is {}, cache size {}"
320 ),
321 new_boot_level,
322 self.current,
323 self.cache.len()
324 );
325 return Ok(());
326 }
327
328 // We `get` the new boot level for the side effect of advancing the cache to a point
329 // where the new boot level is present.
330 self.get_hkdf_key(new_boot_level)
331 .context("In BootLevelKeyCache::advance_boot_level: Advancing cache")?;
332
333 // Then we split the queue at the index of the new boot level and discard the front,
334 // keeping only the keys with the current boot level or higher.
335 self.cache = self.cache.split_off(new_boot_level - self.current);
336
337 // The new cache has the new boot level at index 0, so we set `current` to
338 // `new_boot_level`.
339 self.current = new_boot_level;
340
341 Ok(())
342 }
343
344 /// Drop all keys, effectively raising the current boot level to infinity; no keys can
345 /// be inferred from this point on.
346 pub fn finish(&mut self) {
347 self.cache.clear();
348 }
349
350 fn expand_key(
351 &mut self,
352 boot_level: usize,
353 out_len: usize,
354 info: &[u8],
355 ) -> Result<Option<ZVec>> {
356 self.get_hkdf_key(boot_level)
357 .context("In BootLevelKeyCache::expand_key: Looking up HKDF key")?
358 .map(|k| hkdf_expand(out_len, k, info))
359 .transpose()
360 .context("In BootLevelKeyCache::expand_key: Calling hkdf_expand")
361 }
362
363 /// Return the AES-256-GCM key for the current boot level.
364 pub fn aes_key(&mut self, boot_level: usize) -> Result<Option<ZVec>> {
365 self.expand_key(boot_level, AES_256_KEY_LENGTH, BootLevelKeyCache::HKDF_AES)
366 .context("In BootLevelKeyCache::aes_key: expand_key failed")
367 }
368}
369
370#[cfg(test)]
371mod test {
372 use super::*;
373
374 #[test]
375 fn test_output_is_consistent() -> Result<()> {
376 let initial_key = b"initial key";
377 let mut blkc = BootLevelKeyCache::new(ZVec::try_from(initial_key as &[u8])?);
378 assert_eq!(true, blkc.level_accessible(0));
379 assert_eq!(true, blkc.level_accessible(9));
380 assert_eq!(true, blkc.level_accessible(10));
381 assert_eq!(true, blkc.level_accessible(100));
382 let v0 = blkc.aes_key(0).unwrap().unwrap();
383 let v10 = blkc.aes_key(10).unwrap().unwrap();
384 assert_eq!(Some(&v0), blkc.aes_key(0)?.as_ref());
385 assert_eq!(Some(&v10), blkc.aes_key(10)?.as_ref());
386 blkc.advance_boot_level(5)?;
387 assert_eq!(false, blkc.level_accessible(0));
388 assert_eq!(true, blkc.level_accessible(9));
389 assert_eq!(true, blkc.level_accessible(10));
390 assert_eq!(true, blkc.level_accessible(100));
391 assert_eq!(None, blkc.aes_key(0)?);
392 assert_eq!(Some(&v10), blkc.aes_key(10)?.as_ref());
393 blkc.advance_boot_level(10)?;
394 assert_eq!(false, blkc.level_accessible(0));
395 assert_eq!(false, blkc.level_accessible(9));
396 assert_eq!(true, blkc.level_accessible(10));
397 assert_eq!(true, blkc.level_accessible(100));
398 assert_eq!(None, blkc.aes_key(0)?);
399 assert_eq!(Some(&v10), blkc.aes_key(10)?.as_ref());
400 blkc.advance_boot_level(0)?;
401 assert_eq!(false, blkc.level_accessible(0));
402 assert_eq!(false, blkc.level_accessible(9));
403 assert_eq!(true, blkc.level_accessible(10));
404 assert_eq!(true, blkc.level_accessible(100));
405 assert_eq!(None, blkc.aes_key(0)?);
406 assert_eq!(Some(v10), blkc.aes_key(10)?);
407 blkc.finish();
408 assert_eq!(false, blkc.level_accessible(0));
409 assert_eq!(false, blkc.level_accessible(9));
410 assert_eq!(false, blkc.level_accessible(10));
411 assert_eq!(false, blkc.level_accessible(100));
412 assert_eq!(None, blkc.aes_key(0)?);
413 assert_eq!(None, blkc.aes_key(10)?);
414 Ok(())
415 }
416}