blob: ded14a98c8c2858b48ccc169fbd9bcbe02149c04 [file] [log] [blame]
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001// Copyright 2020, 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#![allow(dead_code)]
16
17use crate::{
Hasini Gunasinghe0e161452021-01-27 19:34:37 +000018 database::BlobMetaData, database::BlobMetaEntry, database::EncryptedBy, database::KeyType,
19 database::KeystoreDB, error::Error, error::ResponseCode, legacy_blob::LegacyBlobLoader,
Janis Danisevskisb42fc182020-12-15 08:41:27 -080020};
21use android_system_keystore2::aidl::android::system::keystore2::Domain::Domain;
22use anyhow::{Context, Result};
23use keystore2_crypto::{
24 aes_gcm_decrypt, aes_gcm_encrypt, derive_key_from_password, generate_salt, ZVec,
25 AES_256_KEY_LENGTH,
26};
27use std::{
28 collections::HashMap,
29 sync::Arc,
30 sync::{Mutex, Weak},
31};
32
33type UserId = u32;
34
35#[derive(Default)]
36struct UserSuperKeys {
37 /// The per boot key is used for LSKF binding of authentication bound keys. There is one
38 /// key per android user. The key is stored on flash encrypted with a key derived from a
39 /// secret, that is itself derived from the user's lock screen knowledge factor (LSKF).
40 /// When the user unlocks the device for the first time, this key is unlocked, i.e., decrypted,
41 /// and stays memory resident until the device reboots.
Hasini Gunasinghe0e161452021-01-27 19:34:37 +000042 per_boot: Option<SuperKey>,
Janis Danisevskisb42fc182020-12-15 08:41:27 -080043 /// The screen lock key works like the per boot key with the distinction that it is cleared
44 /// from memory when the screen lock is engaged.
45 /// TODO the life cycle is not fully implemented at this time.
46 screen_lock: Option<Arc<ZVec>>,
47}
48
Hasini Gunasinghe0e161452021-01-27 19:34:37 +000049#[derive(Default, Clone)]
50pub struct SuperKey {
51 key: Arc<ZVec>,
52 // id of the super key in the database.
53 id: i64,
54}
55
56impl SuperKey {
57 pub fn get_key(&self) -> &Arc<ZVec> {
58 &self.key
59 }
60
61 pub fn get_id(&self) -> i64 {
62 self.id
63 }
64}
65
Janis Danisevskisb42fc182020-12-15 08:41:27 -080066#[derive(Default)]
67struct SkmState {
68 user_keys: HashMap<UserId, UserSuperKeys>,
69 key_index: HashMap<i64, Weak<ZVec>>,
70}
71
72#[derive(Default)]
73pub struct SuperKeyManager {
74 data: Mutex<SkmState>,
75}
76
77impl SuperKeyManager {
78 pub fn new() -> Self {
79 Self { data: Mutex::new(Default::default()) }
80 }
81
82 pub fn forget_screen_lock_key_for_user(&self, user: UserId) {
83 let mut data = self.data.lock().unwrap();
84 if let Some(usk) = data.user_keys.get_mut(&user) {
85 usk.screen_lock = None;
86 }
87 }
88
89 pub fn forget_screen_lock_keys(&self) {
90 let mut data = self.data.lock().unwrap();
91 for (_, usk) in data.user_keys.iter_mut() {
92 usk.screen_lock = None;
93 }
94 }
95
96 pub fn forget_all_keys_for_user(&self, user: UserId) {
97 let mut data = self.data.lock().unwrap();
98 data.user_keys.remove(&user);
99 }
100
101 pub fn forget_all_keys(&self) {
102 let mut data = self.data.lock().unwrap();
103 data.user_keys.clear();
104 data.key_index.clear();
105 }
106
Hasini Gunasinghe0e161452021-01-27 19:34:37 +0000107 fn install_per_boot_key_for_user(&self, user: UserId, id: i64, key: ZVec) {
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800108 let mut data = self.data.lock().unwrap();
109 let key = Arc::new(key);
Hasini Gunasinghe0e161452021-01-27 19:34:37 +0000110 data.key_index.insert(id, Arc::downgrade(&key));
111 data.user_keys.entry(user).or_default().per_boot = Some(SuperKey { key, id });
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800112 }
113
114 fn get_key(&self, key_id: &i64) -> Option<Arc<ZVec>> {
115 self.data.lock().unwrap().key_index.get(key_id).and_then(|k| k.upgrade())
116 }
117
Hasini Gunasinghe0e161452021-01-27 19:34:37 +0000118 pub fn get_per_boot_key_by_user_id(&self, user_id: u32) -> Option<SuperKey> {
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800119 let data = self.data.lock().unwrap();
120 data.user_keys.get(&user_id).map(|e| e.per_boot.clone()).flatten()
121 }
122
123 /// This function unlocks the super keys for a given user.
124 /// This means the key is loaded from the database, decrypted and placed in the
125 /// super key cache. If there is no such key a new key is created, encrypted with
126 /// a key derived from the given password and stored in the database.
Janis Danisevskisa51ccbc2020-11-25 21:04:24 -0800127 pub fn unlock_user_key(
128 &self,
129 user: UserId,
130 pw: &[u8],
131 db: &mut KeystoreDB,
132 legacy_blob_loader: &LegacyBlobLoader,
133 ) -> Result<()> {
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800134 let (_, entry) = db
Max Bires8e93d2b2021-01-14 13:17:59 -0800135 .get_or_create_key_with(
136 Domain::APP,
137 user as u64 as i64,
Hasini Gunasinghe0e161452021-01-27 19:34:37 +0000138 KeystoreDB::USER_SUPER_KEY_ALIAS,
Max Bires8e93d2b2021-01-14 13:17:59 -0800139 crate::database::KEYSTORE_UUID,
140 || {
141 // For backward compatibility we need to check if there is a super key present.
142 let super_key = legacy_blob_loader
143 .load_super_key(user, pw)
144 .context("In create_new_key: Failed to load legacy key blob.")?;
145 let super_key = match super_key {
146 None => {
147 // No legacy file was found. So we generate a new key.
148 keystore2_crypto::generate_aes256_key()
149 .context("In create_new_key: Failed to generate AES 256 key.")?
150 }
151 Some(key) => key,
152 };
153 // Regardless of whether we loaded an old AES128 key or a new AES256 key,
154 // we derive a AES256 key and re-encrypt the key before we insert it in the
155 // database. The length of the key is preserved by the encryption so we don't
156 // need any extra flags to inform us which algorithm to use it with.
157 let salt =
158 generate_salt().context("In create_new_key: Failed to generate salt.")?;
159 let derived_key = derive_key_from_password(pw, Some(&salt), AES_256_KEY_LENGTH)
160 .context("In create_new_key: Failed to derive password.")?;
Janis Danisevskis7e8b4622021-02-13 10:01:59 -0800161 let mut metadata = BlobMetaData::new();
162 metadata.add(BlobMetaEntry::EncryptedBy(EncryptedBy::Password));
163 metadata.add(BlobMetaEntry::Salt(salt));
Max Bires8e93d2b2021-01-14 13:17:59 -0800164 let (encrypted_key, iv, tag) = aes_gcm_encrypt(&super_key, &derived_key)
165 .context("In create_new_key: Failed to encrypt new super key.")?;
Janis Danisevskis7e8b4622021-02-13 10:01:59 -0800166 metadata.add(BlobMetaEntry::Iv(iv));
167 metadata.add(BlobMetaEntry::AeadTag(tag));
Max Bires8e93d2b2021-01-14 13:17:59 -0800168 Ok((encrypted_key, metadata))
169 },
170 )
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800171 .context("In unlock_user_key: Failed to get key id.")?;
172
Janis Danisevskis7e8b4622021-02-13 10:01:59 -0800173 if let Some((ref blob, ref metadata)) = entry.key_blob_info() {
174 let super_key = match (
175 metadata.encrypted_by(),
176 metadata.salt(),
177 metadata.iv(),
178 metadata.aead_tag(),
179 ) {
180 (Some(&EncryptedBy::Password), Some(salt), Some(iv), Some(tag)) => {
181 let key = derive_key_from_password(pw, Some(salt), AES_256_KEY_LENGTH)
182 .context("In unlock_user_key: Failed to generate key from password.")?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800183
Janis Danisevskis7e8b4622021-02-13 10:01:59 -0800184 aes_gcm_decrypt(blob, iv, tag, &key)
185 .context("In unlock_user_key: Failed to decrypt key blob.")?
186 }
187 (enc_by, salt, iv, tag) => {
188 return Err(Error::Rc(ResponseCode::VALUE_CORRUPTED)).context(format!(
189 concat!(
190 "In unlock_user_key: Super key has incomplete metadata.",
191 "Present: encrypted_by: {}, salt: {}, iv: {}, aead_tag: {}."
192 ),
193 enc_by.is_some(),
194 salt.is_some(),
195 iv.is_some(),
196 tag.is_some(),
197 ));
198 }
199 };
200 self.install_per_boot_key_for_user(user, entry.id(), super_key);
201 } else {
202 return Err(Error::Rc(ResponseCode::VALUE_CORRUPTED))
203 .context("In unlock_user_key: Key entry has no key blob.");
204 }
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800205
206 Ok(())
207 }
208
209 /// Unwraps an encrypted key blob given metadata identifying the encryption key.
210 /// The function queries `metadata.encrypted_by()` to determine the encryption key.
211 /// It then check if the required key is memory resident, and if so decrypts the
212 /// blob.
Janis Danisevskis7e8b4622021-02-13 10:01:59 -0800213 pub fn unwrap_key(&self, blob: &[u8], metadata: &BlobMetaData) -> Result<ZVec> {
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800214 match metadata.encrypted_by() {
215 Some(EncryptedBy::KeyId(key_id)) => match self.get_key(key_id) {
216 Some(key) => {
217 Self::unwrap_key_with_key(blob, metadata, &key).context("In unwrap_key.")
218 }
219 None => Err(Error::Rc(ResponseCode::LOCKED))
220 .context("In unwrap_key: Key is not usable until the user entered their LSKF."),
221 },
222 _ => Err(Error::Rc(ResponseCode::VALUE_CORRUPTED))
223 .context("In unwrap_key: Cannot determined wrapping key."),
224 }
225 }
226
227 /// Unwraps an encrypted key blob given an encryption key.
Janis Danisevskis7e8b4622021-02-13 10:01:59 -0800228 fn unwrap_key_with_key(blob: &[u8], metadata: &BlobMetaData, key: &[u8]) -> Result<ZVec> {
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800229 match (metadata.iv(), metadata.aead_tag()) {
230 (Some(iv), Some(tag)) => aes_gcm_decrypt(blob, iv, tag, key)
231 .context("In unwrap_key_with_key: Failed to decrypt the key blob."),
232 (iv, tag) => Err(Error::Rc(ResponseCode::VALUE_CORRUPTED)).context(format!(
233 concat!(
234 "In unwrap_key_with_key: Key has incomplete metadata.",
235 "Present: iv: {}, aead_tag: {}."
236 ),
237 iv.is_some(),
238 tag.is_some(),
239 )),
240 }
241 }
Hasini Gunasinghe0e161452021-01-27 19:34:37 +0000242
243 /// Checks if user has setup LSKF, even when super key cache is empty for the user.
244 pub fn super_key_exists_in_db_for_user(db: &mut KeystoreDB, user_id: u32) -> Result<bool> {
245 let key_in_db = db
246 .key_exists(
247 Domain::APP,
248 user_id as u64 as i64,
249 KeystoreDB::USER_SUPER_KEY_ALIAS,
250 KeyType::Super,
251 )
252 .context("In super_key_exists_in_db_for_user.")?;
253
254 if key_in_db {
255 Ok(key_in_db)
256 } else {
257 //TODO (b/159371296): add a function to legacy blob loader to check if super key exists
258 //given user id
259 Ok(false)
260 }
261 }
262}
263
264/// This enum represents different states of the user's life cycle in the device.
265/// For now, only three states are defined. More states may be added later.
266pub enum UserState {
267 // The user has registered LSKF and has unlocked the device by entering PIN/Password,
268 // and hence the per-boot super key is available in the cache.
269 LskfUnlocked(SuperKey),
270 // The user has registered LSKF, but has not unlocked the device using password, after reboot.
271 // Hence the per-boot super-key(s) is not available in the cache.
272 // However, the encrypted super key is available in the database.
273 LskfLocked,
274 // There's no user in the device for the given user id, or the user with the user id has not
275 // setup LSKF.
276 Uninitialized,
277}
278
279impl UserState {
280 pub fn get_user_state(
281 db: &mut KeystoreDB,
282 skm: &SuperKeyManager,
283 user_id: u32,
284 ) -> Result<UserState> {
285 match skm.get_per_boot_key_by_user_id(user_id) {
286 Some(super_key) => Ok(UserState::LskfUnlocked(super_key)),
287 None => {
288 //Check if a super key exists in the database or legacy database.
289 //If so, return locked user state.
290 if SuperKeyManager::super_key_exists_in_db_for_user(db, user_id)
291 .context("In get_user_state.")?
292 {
293 Ok(UserState::LskfLocked)
294 } else {
295 Ok(UserState::Uninitialized)
296 }
297 }
298 }
299 }
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800300}