blob: 0df3a457cc908f362f8a6b0792611b1b8330d896 [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
Janis Danisevskis0cabd712021-05-25 11:07:10 -070017use crate::{
18 database::{KeyType, KeystoreDB},
19 key_parameter::KeyParameterValue,
20 raw_device::KeyMintDevice,
21};
Paul Crowley44c02da2021-04-08 17:04:43 +000022use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Janis Danisevskisacebfa22021-05-25 10:56:10 -070023 Algorithm::Algorithm, Digest::Digest, KeyParameter::KeyParameter as KmKeyParameter,
24 KeyParameterValue::KeyParameterValue as KmKeyParameterValue, KeyPurpose::KeyPurpose,
25 SecurityLevel::SecurityLevel, Tag::Tag,
Paul Crowley44c02da2021-04-08 17:04:43 +000026};
Paul Crowley44c02da2021-04-08 17:04:43 +000027use anyhow::{Context, Result};
Paul Crowley44c02da2021-04-08 17:04:43 +000028use keystore2_crypto::{hkdf_expand, ZVec, AES_256_KEY_LENGTH};
29use std::{collections::VecDeque, convert::TryFrom};
30
Janis Danisevskis5c748212021-05-17 17:13:56 -070031fn 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}
Paul Crowley44c02da2021-04-08 17:04:43 +000047
Paul Crowley44c02da2021-04-08 17:04:43 +000048/// 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.
51pub fn get_level_zero_key(db: &mut KeystoreDB) -> Result<ZVec> {
Janis Danisevskis5c748212021-05-17 17:13:56 -070052 let km_dev = get_preferred_km_instance_for_level_zero_key()
53 .context("In get_level_zero_key: get preferred KM instance failed")?;
54
Paul Crowley618869e2021-04-08 20:30:54 -070055 let key_desc = KeyMintDevice::internal_descriptor("boot_level_key".to_string());
Janis Danisevskis5c748212021-05-17 17:13:56 -070056 let mut params = vec![
Paul Crowley44c02da2021-04-08 17:04:43 +000057 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(),
Paul Crowleyeb964cf2021-04-19 18:14:15 -070062 KeyParameterValue::NoAuthRequired.into(),
Paul Crowley44c02da2021-04-08 17:04:43 +000063 ];
Janis Danisevskis5c748212021-05-17 17:13:56 -070064
Janis Danisevskisacebfa22021-05-25 10:56:10 -070065 let has_early_boot_only = km_dev.version() >= KeyMintDevice::KEY_MASTER_V4_1;
66
67 if has_early_boot_only {
Janis Danisevskis5c748212021-05-17 17:13:56 -070068 params.push(KeyParameterValue::EarlyBootOnly.into());
69 } else {
70 params.push(KeyParameterValue::MaxUsesPerBoot(1).into())
71 }
72
Paul Crowley44c02da2021-04-08 17:04:43 +000073 let (key_id_guard, key_entry) = km_dev
Janis Danisevskis0cabd712021-05-25 11:07:10 -070074 .lookup_or_generate_key(db, &key_desc, KeyType::Client, &params, |key_characteristics| {
Janis Danisevskisacebfa22021-05-25 10:56:10 -070075 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 })
Paul Crowley44c02da2021-04-08 17:04:43 +0000100 .context("In get_level_zero_key: lookup_or_generate_key failed")?;
101
102 let params = [KeyParameterValue::MacLength(256).into()];
103 let level_zero_key = km_dev
104 .use_key_in_one_step(
105 db,
Paul Crowley618869e2021-04-08 20:30:54 -0700106 &key_id_guard,
Paul Crowley44c02da2021-04-08 17:04:43 +0000107 &key_entry,
108 KeyPurpose::SIGN,
109 &params,
Paul Crowley618869e2021-04-08 20:30:54 -0700110 None,
Paul Crowley44c02da2021-04-08 17:04:43 +0000111 b"Create boot level key",
112 )
113 .context("In get_level_zero_key: use_key_in_one_step failed")?;
114 // TODO: this is rather unsatisfactory, we need a better way to handle
115 // sensitive binder returns.
116 let level_zero_key = ZVec::try_from(level_zero_key)
117 .context("In get_level_zero_key: conversion to ZVec failed")?;
118 Ok(level_zero_key)
119}
120
121/// Holds the key for the current boot level, and a cache of future keys generated as required.
122/// When the boot level advances, keys prior to the current boot level are securely dropped.
123pub struct BootLevelKeyCache {
124 /// Least boot level currently accessible, if any is.
125 current: usize,
126 /// Invariant: cache entry *i*, if it exists, holds the HKDF key for boot level
127 /// *i* + `current`. If the cache is non-empty it can be grown forwards, but it cannot be
128 /// grown backwards, so keys below `current` are inaccessible.
129 /// `cache.clear()` makes all keys inaccessible.
130 cache: VecDeque<ZVec>,
131}
132
133impl BootLevelKeyCache {
134 const HKDF_ADVANCE: &'static [u8] = b"Advance KDF one step";
135 const HKDF_AES: &'static [u8] = b"Generate AES-256-GCM key";
136 const HKDF_KEY_SIZE: usize = 32;
137
138 /// Initialize the cache with the level zero key.
139 pub fn new(level_zero_key: ZVec) -> Self {
140 let mut cache: VecDeque<ZVec> = VecDeque::new();
141 cache.push_back(level_zero_key);
142 Self { current: 0, cache }
143 }
144
145 /// Report whether the key for the given level can be inferred.
146 pub fn level_accessible(&self, boot_level: usize) -> bool {
147 // If the requested boot level is lower than the current boot level
148 // or if we have reached the end (`cache.empty()`) we can't retrieve
149 // the boot key.
150 boot_level >= self.current && !self.cache.is_empty()
151 }
152
153 /// Get the HKDF key for boot level `boot_level`. The key for level *i*+1
154 /// is calculated from the level *i* key using `hkdf_expand`.
155 fn get_hkdf_key(&mut self, boot_level: usize) -> Result<Option<&ZVec>> {
156 if !self.level_accessible(boot_level) {
157 return Ok(None);
158 }
159 // `self.cache.len()` represents the first entry not in the cache,
160 // so `self.current + self.cache.len()` is the first boot level not in the cache.
161 let first_not_cached = self.current + self.cache.len();
162
163 // Grow the cache forwards until it contains the desired boot level.
164 for _level in first_not_cached..=boot_level {
165 // We check at the start that cache is non-empty and future iterations only push,
166 // so this must unwrap.
167 let highest_key = self.cache.back().unwrap();
168 let next_key = hkdf_expand(Self::HKDF_KEY_SIZE, highest_key, Self::HKDF_ADVANCE)
169 .context("In BootLevelKeyCache::get_hkdf_key: Advancing key one step")?;
170 self.cache.push_back(next_key);
171 }
172
173 // If we reach this point, we should have a key at index boot_level - current.
174 Ok(Some(self.cache.get(boot_level - self.current).unwrap()))
175 }
176
177 /// Drop keys prior to the given boot level, while retaining the ability to generate keys for
178 /// that level and later.
179 pub fn advance_boot_level(&mut self, new_boot_level: usize) -> Result<()> {
180 if !self.level_accessible(new_boot_level) {
181 log::error!(
182 concat!(
183 "In BootLevelKeyCache::advance_boot_level: ",
184 "Failed to advance boot level to {}, current is {}, cache size {}"
185 ),
186 new_boot_level,
187 self.current,
188 self.cache.len()
189 );
190 return Ok(());
191 }
192
193 // We `get` the new boot level for the side effect of advancing the cache to a point
194 // where the new boot level is present.
195 self.get_hkdf_key(new_boot_level)
196 .context("In BootLevelKeyCache::advance_boot_level: Advancing cache")?;
197
198 // Then we split the queue at the index of the new boot level and discard the front,
199 // keeping only the keys with the current boot level or higher.
200 self.cache = self.cache.split_off(new_boot_level - self.current);
201
202 // The new cache has the new boot level at index 0, so we set `current` to
203 // `new_boot_level`.
204 self.current = new_boot_level;
205
206 Ok(())
207 }
208
209 /// Drop all keys, effectively raising the current boot level to infinity; no keys can
210 /// be inferred from this point on.
211 pub fn finish(&mut self) {
212 self.cache.clear();
213 }
214
215 fn expand_key(
216 &mut self,
217 boot_level: usize,
218 out_len: usize,
219 info: &[u8],
220 ) -> Result<Option<ZVec>> {
221 self.get_hkdf_key(boot_level)
222 .context("In BootLevelKeyCache::expand_key: Looking up HKDF key")?
223 .map(|k| hkdf_expand(out_len, k, info))
224 .transpose()
225 .context("In BootLevelKeyCache::expand_key: Calling hkdf_expand")
226 }
227
228 /// Return the AES-256-GCM key for the current boot level.
229 pub fn aes_key(&mut self, boot_level: usize) -> Result<Option<ZVec>> {
230 self.expand_key(boot_level, AES_256_KEY_LENGTH, BootLevelKeyCache::HKDF_AES)
231 .context("In BootLevelKeyCache::aes_key: expand_key failed")
232 }
233}
234
235#[cfg(test)]
236mod test {
237 use super::*;
238
239 #[test]
240 fn test_output_is_consistent() -> Result<()> {
241 let initial_key = b"initial key";
242 let mut blkc = BootLevelKeyCache::new(ZVec::try_from(initial_key as &[u8])?);
243 assert_eq!(true, blkc.level_accessible(0));
244 assert_eq!(true, blkc.level_accessible(9));
245 assert_eq!(true, blkc.level_accessible(10));
246 assert_eq!(true, blkc.level_accessible(100));
247 let v0 = blkc.aes_key(0).unwrap().unwrap();
248 let v10 = blkc.aes_key(10).unwrap().unwrap();
249 assert_eq!(Some(&v0), blkc.aes_key(0)?.as_ref());
250 assert_eq!(Some(&v10), blkc.aes_key(10)?.as_ref());
251 blkc.advance_boot_level(5)?;
252 assert_eq!(false, blkc.level_accessible(0));
253 assert_eq!(true, blkc.level_accessible(9));
254 assert_eq!(true, blkc.level_accessible(10));
255 assert_eq!(true, blkc.level_accessible(100));
256 assert_eq!(None, blkc.aes_key(0)?);
257 assert_eq!(Some(&v10), blkc.aes_key(10)?.as_ref());
258 blkc.advance_boot_level(10)?;
259 assert_eq!(false, blkc.level_accessible(0));
260 assert_eq!(false, blkc.level_accessible(9));
261 assert_eq!(true, blkc.level_accessible(10));
262 assert_eq!(true, blkc.level_accessible(100));
263 assert_eq!(None, blkc.aes_key(0)?);
264 assert_eq!(Some(&v10), blkc.aes_key(10)?.as_ref());
265 blkc.advance_boot_level(0)?;
266 assert_eq!(false, blkc.level_accessible(0));
267 assert_eq!(false, blkc.level_accessible(9));
268 assert_eq!(true, blkc.level_accessible(10));
269 assert_eq!(true, blkc.level_accessible(100));
270 assert_eq!(None, blkc.aes_key(0)?);
271 assert_eq!(Some(v10), blkc.aes_key(10)?);
272 blkc.finish();
273 assert_eq!(false, blkc.level_accessible(0));
274 assert_eq!(false, blkc.level_accessible(9));
275 assert_eq!(false, blkc.level_accessible(10));
276 assert_eq!(false, blkc.level_accessible(100));
277 assert_eq!(None, blkc.aes_key(0)?);
278 assert_eq!(None, blkc.aes_key(10)?);
279 Ok(())
280 }
281}