blob: dd29d7e55460196d93fccab74aa5785d21f06825 [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 Gunasingheda895552021-01-27 19:34:37 +000018 database::BlobMetaData, database::BlobMetaEntry, database::EncryptedBy, database::KeyEntry,
Hasini Gunasinghedeab85d2021-02-01 21:10:02 +000019 database::KeyType, database::KeystoreDB, enforcements::Enforcements, error::Error,
20 error::ResponseCode, key_parameter::KeyParameter, legacy_blob::LegacyBlobLoader,
Janis Danisevskisb42fc182020-12-15 08:41:27 -080021};
22use android_system_keystore2::aidl::android::system::keystore2::Domain::Domain;
23use anyhow::{Context, Result};
24use keystore2_crypto::{
Hasini Gunasingheda895552021-01-27 19:34:37 +000025 aes_gcm_decrypt, aes_gcm_encrypt, derive_key_from_password, generate_aes256_key, generate_salt,
26 ZVec, AES_256_KEY_LENGTH,
Janis Danisevskisb42fc182020-12-15 08:41:27 -080027};
Hasini Gunasinghedeab85d2021-02-01 21:10:02 +000028use std::ops::Deref;
Janis Danisevskisb42fc182020-12-15 08:41:27 -080029use std::{
30 collections::HashMap,
31 sync::Arc,
32 sync::{Mutex, Weak},
33};
34
35type UserId = u32;
36
37#[derive(Default)]
38struct UserSuperKeys {
39 /// The per boot key is used for LSKF binding of authentication bound keys. There is one
40 /// key per android user. The key is stored on flash encrypted with a key derived from a
41 /// secret, that is itself derived from the user's lock screen knowledge factor (LSKF).
42 /// When the user unlocks the device for the first time, this key is unlocked, i.e., decrypted,
43 /// and stays memory resident until the device reboots.
Hasini Gunasinghe0e161452021-01-27 19:34:37 +000044 per_boot: Option<SuperKey>,
Janis Danisevskisb42fc182020-12-15 08:41:27 -080045 /// The screen lock key works like the per boot key with the distinction that it is cleared
46 /// from memory when the screen lock is engaged.
47 /// TODO the life cycle is not fully implemented at this time.
48 screen_lock: Option<Arc<ZVec>>,
49}
50
Hasini Gunasinghe0e161452021-01-27 19:34:37 +000051#[derive(Default, Clone)]
52pub struct SuperKey {
53 key: Arc<ZVec>,
54 // id of the super key in the database.
55 id: i64,
56}
57
58impl SuperKey {
59 pub fn get_key(&self) -> &Arc<ZVec> {
60 &self.key
61 }
62
63 pub fn get_id(&self) -> i64 {
64 self.id
65 }
66}
67
Janis Danisevskisb42fc182020-12-15 08:41:27 -080068#[derive(Default)]
69struct SkmState {
70 user_keys: HashMap<UserId, UserSuperKeys>,
71 key_index: HashMap<i64, Weak<ZVec>>,
72}
73
74#[derive(Default)]
75pub struct SuperKeyManager {
76 data: Mutex<SkmState>,
77}
78
79impl SuperKeyManager {
80 pub fn new() -> Self {
81 Self { data: Mutex::new(Default::default()) }
82 }
83
84 pub fn forget_screen_lock_key_for_user(&self, user: UserId) {
85 let mut data = self.data.lock().unwrap();
86 if let Some(usk) = data.user_keys.get_mut(&user) {
87 usk.screen_lock = None;
88 }
89 }
90
91 pub fn forget_screen_lock_keys(&self) {
92 let mut data = self.data.lock().unwrap();
93 for (_, usk) in data.user_keys.iter_mut() {
94 usk.screen_lock = None;
95 }
96 }
97
98 pub fn forget_all_keys_for_user(&self, user: UserId) {
99 let mut data = self.data.lock().unwrap();
100 data.user_keys.remove(&user);
101 }
102
103 pub fn forget_all_keys(&self) {
104 let mut data = self.data.lock().unwrap();
105 data.user_keys.clear();
106 data.key_index.clear();
107 }
108
Hasini Gunasingheda895552021-01-27 19:34:37 +0000109 fn install_per_boot_key_for_user(&self, user: UserId, super_key: SuperKey) {
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800110 let mut data = self.data.lock().unwrap();
Hasini Gunasingheda895552021-01-27 19:34:37 +0000111 data.key_index.insert(super_key.id, Arc::downgrade(&(super_key.key)));
112 data.user_keys.entry(user).or_default().per_boot = Some(super_key);
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800113 }
114
115 fn get_key(&self, key_id: &i64) -> Option<Arc<ZVec>> {
116 self.data.lock().unwrap().key_index.get(key_id).and_then(|k| k.upgrade())
117 }
118
Hasini Gunasinghe0e161452021-01-27 19:34:37 +0000119 pub fn get_per_boot_key_by_user_id(&self, user_id: u32) -> Option<SuperKey> {
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800120 let data = self.data.lock().unwrap();
121 data.user_keys.get(&user_id).map(|e| e.per_boot.clone()).flatten()
122 }
123
124 /// This function unlocks the super keys for a given user.
125 /// This means the key is loaded from the database, decrypted and placed in the
126 /// super key cache. If there is no such key a new key is created, encrypted with
127 /// a key derived from the given password and stored in the database.
Janis Danisevskisa51ccbc2020-11-25 21:04:24 -0800128 pub fn unlock_user_key(
129 &self,
Hasini Gunasingheda895552021-01-27 19:34:37 +0000130 db: &mut KeystoreDB,
Janis Danisevskisa51ccbc2020-11-25 21:04:24 -0800131 user: UserId,
132 pw: &[u8],
Janis Danisevskisa51ccbc2020-11-25 21:04:24 -0800133 legacy_blob_loader: &LegacyBlobLoader,
134 ) -> Result<()> {
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800135 let (_, entry) = db
Max Bires8e93d2b2021-01-14 13:17:59 -0800136 .get_or_create_key_with(
137 Domain::APP,
138 user as u64 as i64,
Hasini Gunasinghe0e161452021-01-27 19:34:37 +0000139 KeystoreDB::USER_SUPER_KEY_ALIAS,
Max Bires8e93d2b2021-01-14 13:17:59 -0800140 crate::database::KEYSTORE_UUID,
141 || {
142 // For backward compatibility we need to check if there is a super key present.
143 let super_key = legacy_blob_loader
144 .load_super_key(user, pw)
145 .context("In create_new_key: Failed to load legacy key blob.")?;
146 let super_key = match super_key {
147 None => {
148 // No legacy file was found. So we generate a new key.
Hasini Gunasingheda895552021-01-27 19:34:37 +0000149 generate_aes256_key()
Max Bires8e93d2b2021-01-14 13:17:59 -0800150 .context("In create_new_key: Failed to generate AES 256 key.")?
151 }
152 Some(key) => key,
153 };
Hasini Gunasingheda895552021-01-27 19:34:37 +0000154 // Regardless of whether we loaded an old AES128 key or generated a new AES256
155 // key as the super key, we derive a AES256 key from the password and re-encrypt
156 // the super key before we insert it in the database. The length of the key is
157 // preserved by the encryption so we don't need any extra flags to inform us
158 // which algorithm to use it with.
159 Self::encrypt_with_password(&super_key, pw).context("In create_new_key.")
Max Bires8e93d2b2021-01-14 13:17:59 -0800160 },
161 )
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800162 .context("In unlock_user_key: Failed to get key id.")?;
163
Hasini Gunasingheda895552021-01-27 19:34:37 +0000164 self.populate_cache_from_super_key_blob(user, entry, pw).context("In unlock_user_key.")?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800165 Ok(())
166 }
167
168 /// Unwraps an encrypted key blob given metadata identifying the encryption key.
169 /// The function queries `metadata.encrypted_by()` to determine the encryption key.
170 /// It then check if the required key is memory resident, and if so decrypts the
171 /// blob.
Hasini Gunasinghedeab85d2021-02-01 21:10:02 +0000172 pub fn unwrap_key<'a>(&self, blob: &'a [u8], metadata: &BlobMetaData) -> Result<KeyBlob<'a>> {
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800173 match metadata.encrypted_by() {
174 Some(EncryptedBy::KeyId(key_id)) => match self.get_key(key_id) {
Hasini Gunasinghedeab85d2021-02-01 21:10:02 +0000175 Some(key) => Ok(KeyBlob::Sensitive(
176 Self::unwrap_key_with_key(blob, metadata, &key).context("In unwrap_key.")?,
177 SuperKey { key: key.clone(), id: *key_id },
178 )),
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800179 None => Err(Error::Rc(ResponseCode::LOCKED))
180 .context("In unwrap_key: Key is not usable until the user entered their LSKF."),
181 },
182 _ => Err(Error::Rc(ResponseCode::VALUE_CORRUPTED))
183 .context("In unwrap_key: Cannot determined wrapping key."),
184 }
185 }
186
187 /// Unwraps an encrypted key blob given an encryption key.
Janis Danisevskis7e8b4622021-02-13 10:01:59 -0800188 fn unwrap_key_with_key(blob: &[u8], metadata: &BlobMetaData, key: &[u8]) -> Result<ZVec> {
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800189 match (metadata.iv(), metadata.aead_tag()) {
190 (Some(iv), Some(tag)) => aes_gcm_decrypt(blob, iv, tag, key)
191 .context("In unwrap_key_with_key: Failed to decrypt the key blob."),
192 (iv, tag) => Err(Error::Rc(ResponseCode::VALUE_CORRUPTED)).context(format!(
193 concat!(
194 "In unwrap_key_with_key: Key has incomplete metadata.",
195 "Present: iv: {}, aead_tag: {}."
196 ),
197 iv.is_some(),
198 tag.is_some(),
199 )),
200 }
201 }
Hasini Gunasinghe0e161452021-01-27 19:34:37 +0000202
203 /// Checks if user has setup LSKF, even when super key cache is empty for the user.
204 pub fn super_key_exists_in_db_for_user(db: &mut KeystoreDB, user_id: u32) -> Result<bool> {
205 let key_in_db = db
206 .key_exists(
207 Domain::APP,
208 user_id as u64 as i64,
209 KeystoreDB::USER_SUPER_KEY_ALIAS,
210 KeyType::Super,
211 )
212 .context("In super_key_exists_in_db_for_user.")?;
213
214 if key_in_db {
215 Ok(key_in_db)
216 } else {
217 //TODO (b/159371296): add a function to legacy blob loader to check if super key exists
218 //given user id
219 Ok(false)
220 }
221 }
Hasini Gunasingheda895552021-01-27 19:34:37 +0000222
223 /// Checks if user has already setup LSKF (i.e. a super key is persisted in the database or the
Hasini Gunasinghe731e3c82021-02-06 00:56:28 +0000224 /// legacy database). If not, return Uninitialized state.
225 /// Otherwise, decrypt the super key from the password and return LskfUnlocked state.
226 pub fn check_and_unlock_super_key(
227 &self,
228 db: &mut KeystoreDB,
229 user_id: u32,
230 pw: &[u8],
231 ) -> Result<UserState> {
232 let result = db
233 .load_super_key(user_id)
234 .context("In check_and_unlock_super_key. Failed to load super key")?;
235
236 match result {
237 Some((_, entry)) => {
238 let super_key = self
239 .populate_cache_from_super_key_blob(user_id, entry, pw)
240 .context("In check_and_unlock_super_key.")?;
241 Ok(UserState::LskfUnlocked(super_key))
242 }
243 None =>
244 //TODO: 159371296. Try to load and populate super key from legacy key database.
245 {
246 Ok(UserState::Uninitialized)
247 }
248 }
249 }
250
251 /// Checks if user has already setup LSKF (i.e. a super key is persisted in the database or the
Hasini Gunasingheda895552021-01-27 19:34:37 +0000252 /// legacy database). If so, return LskfLocked state.
253 /// If the password is provided, generate a new super key, encrypt with the password,
254 /// store in the database and populate the super key cache for the new user
255 /// and return LskfUnlocked state.
256 /// If the password is not provided, return Uninitialized state.
257 pub fn check_and_initialize_super_key(
258 &self,
259 db: &mut KeystoreDB,
260 user_id: u32,
261 pw: Option<&[u8]>,
262 ) -> Result<UserState> {
263 let super_key_exists_in_db = Self::super_key_exists_in_db_for_user(db, user_id)
264 .context("In check_and_initialize_super_key. Failed to check if super key exists.")?;
Hasini Gunasingheda895552021-01-27 19:34:37 +0000265 if super_key_exists_in_db {
266 Ok(UserState::LskfLocked)
267 } else {
268 //TODO: 159371296. check if super key exists in legacy key database. If so, return
269 //LskfLocked. Otherwise, if pw is provided, initialize the super key.
270 if let Some(pw) = pw {
271 //generate a new super key.
272 let super_key = generate_aes256_key().context(
273 "In check_and_initialize_super_key: Failed to generate AES 256 key.",
274 )?;
275 //derive an AES256 key from the password and re-encrypt the super key
276 //before we insert it in the database.
277 let (encrypted_super_key, blob_metadata) =
278 Self::encrypt_with_password(&super_key, pw)
279 .context("In check_and_initialize_super_key.")?;
280
281 let key_entry = db
282 .store_super_key(user_id as u64 as i64, &(&encrypted_super_key, &blob_metadata))
283 .context("In check_and_initialize_super_key. Failed to store super key.")?;
284
285 let super_key = self
286 .populate_cache_from_super_key_blob(user_id, key_entry, pw)
287 .context("In check_and_initialize_super_key.")?;
288 Ok(UserState::LskfUnlocked(super_key))
289 } else {
290 Ok(UserState::Uninitialized)
291 }
292 }
293 }
294
295 //helper function to populate super key cache from the super key blob loaded from the database
296 fn populate_cache_from_super_key_blob(
297 &self,
298 user_id: u32,
299 entry: KeyEntry,
300 pw: &[u8],
301 ) -> Result<SuperKey> {
302 let super_key = Self::extract_super_key_from_key_entry(entry, pw).context(
303 "In populate_cache_from_super_key_blob. Failed to extract super key from key entry",
304 )?;
305 self.install_per_boot_key_for_user(user_id, super_key.clone());
306 Ok(super_key)
307 }
308
309 /// Extracts super key from the entry loaded from the database
310 pub fn extract_super_key_from_key_entry(entry: KeyEntry, pw: &[u8]) -> Result<SuperKey> {
311 if let Some((blob, metadata)) = entry.key_blob_info() {
312 let key = match (
313 metadata.encrypted_by(),
314 metadata.salt(),
315 metadata.iv(),
316 metadata.aead_tag(),
317 ) {
318 (Some(&EncryptedBy::Password), Some(salt), Some(iv), Some(tag)) => {
319 let key = derive_key_from_password(pw, Some(salt), AES_256_KEY_LENGTH).context(
320 "In extract_super_key_from_key_entry: Failed to generate key from password.",
321 )?;
322
323 aes_gcm_decrypt(blob, iv, tag, &key).context(
324 "In extract_super_key_from_key_entry: Failed to decrypt key blob.",
325 )?
326 }
327 (enc_by, salt, iv, tag) => {
328 return Err(Error::Rc(ResponseCode::VALUE_CORRUPTED)).context(format!(
329 concat!(
330 "In extract_super_key_from_key_entry: Super key has incomplete metadata.",
331 "Present: encrypted_by: {}, salt: {}, iv: {}, aead_tag: {}."
332 ),
333 enc_by.is_some(),
334 salt.is_some(),
335 iv.is_some(),
336 tag.is_some()
337 ));
338 }
339 };
340 Ok(SuperKey { key: Arc::new(key), id: entry.id() })
341 } else {
342 Err(Error::Rc(ResponseCode::VALUE_CORRUPTED))
343 .context("In extract_super_key_from_key_entry: No key blob info.")
344 }
345 }
346
347 /// Encrypts the super key from a key derived from the password, before storing in the database.
348 pub fn encrypt_with_password(super_key: &[u8], pw: &[u8]) -> Result<(Vec<u8>, BlobMetaData)> {
349 let salt = generate_salt().context("In encrypt_with_password: Failed to generate salt.")?;
350 let derived_key = derive_key_from_password(pw, Some(&salt), AES_256_KEY_LENGTH)
351 .context("In encrypt_with_password: Failed to derive password.")?;
352 let mut metadata = BlobMetaData::new();
353 metadata.add(BlobMetaEntry::EncryptedBy(EncryptedBy::Password));
354 metadata.add(BlobMetaEntry::Salt(salt));
355 let (encrypted_key, iv, tag) = aes_gcm_encrypt(super_key, &derived_key)
356 .context("In encrypt_with_password: Failed to encrypt new super key.")?;
357 metadata.add(BlobMetaEntry::Iv(iv));
358 metadata.add(BlobMetaEntry::AeadTag(tag));
359 Ok((encrypted_key, metadata))
360 }
Hasini Gunasinghedeab85d2021-02-01 21:10:02 +0000361
362 // Encrypt the given key blob with the user's super key, if the super key exists and the device
363 // is unlocked. If the super key exists and the device is locked, or LSKF is not setup,
364 // return error. Note that it is out of the scope of this function to check if super encryption
365 // is required. Such check should be performed before calling this function.
366 fn super_encrypt_on_key_init(
367 db: &mut KeystoreDB,
368 skm: &SuperKeyManager,
369 user_id: u32,
370 key_blob: &[u8],
371 ) -> Result<(Vec<u8>, BlobMetaData)> {
372 match UserState::get(db, skm, user_id)
373 .context("In super_encrypt. Failed to get user state.")?
374 {
375 UserState::LskfUnlocked(super_key) => {
376 Self::encrypt_with_super_key(key_blob, &super_key)
377 .context("In super_encrypt_on_key_init. Failed to encrypt the key.")
378 }
379 UserState::LskfLocked => {
380 Err(Error::Rc(ResponseCode::LOCKED)).context("In super_encrypt. Device is locked.")
381 }
382 UserState::Uninitialized => Err(Error::Rc(ResponseCode::UNINITIALIZED))
383 .context("In super_encrypt. LSKF is not setup for the user."),
384 }
385 }
386
387 //Helper function to encrypt a key with the given super key. Callers should select which super
388 //key to be used. This is called when a key is super encrypted at its creation as well as at its
389 //upgrade.
390 fn encrypt_with_super_key(
391 key_blob: &[u8],
392 super_key: &SuperKey,
393 ) -> Result<(Vec<u8>, BlobMetaData)> {
394 let mut metadata = BlobMetaData::new();
395 let (encrypted_key, iv, tag) = aes_gcm_encrypt(key_blob, &(super_key.key))
396 .context("In encrypt_with_super_key: Failed to encrypt new super key.")?;
397 metadata.add(BlobMetaEntry::Iv(iv));
398 metadata.add(BlobMetaEntry::AeadTag(tag));
399 metadata.add(BlobMetaEntry::EncryptedBy(EncryptedBy::KeyId(super_key.id)));
400 Ok((encrypted_key, metadata))
401 }
402
403 /// Check if super encryption is required and if so, super-encrypt the key to be stored in
404 /// the database.
405 pub fn handle_super_encryption_on_key_init(
406 db: &mut KeystoreDB,
407 skm: &SuperKeyManager,
408 domain: &Domain,
409 key_parameters: &[KeyParameter],
410 flags: Option<i32>,
411 user_id: u32,
412 key_blob: &[u8],
413 ) -> Result<(Vec<u8>, BlobMetaData)> {
414 match (*domain, Enforcements::super_encryption_required(key_parameters, flags)) {
415 (Domain::APP, true) => Self::super_encrypt_on_key_init(db, skm, user_id, &key_blob)
416 .context(
417 "In handle_super_encryption_on_key_init.
418 Failed to super encrypt the key.",
419 ),
420 _ => Ok((key_blob.to_vec(), BlobMetaData::new())),
421 }
422 }
423
424 /// Check if a given key is super-encrypted, from its metadata. If so, unwrap the key using
425 /// the relevant super key.
426 pub fn unwrap_key_if_required<'a>(
427 &self,
428 metadata: &BlobMetaData,
429 key_blob: &'a [u8],
430 ) -> Result<KeyBlob<'a>> {
431 if Self::key_super_encrypted(&metadata) {
432 let unwrapped_key = self
433 .unwrap_key(key_blob, metadata)
434 .context("In unwrap_key_if_required. Error in unwrapping the key.")?;
435 Ok(unwrapped_key)
436 } else {
437 Ok(KeyBlob::Ref(key_blob))
438 }
439 }
440
441 /// Check if a given key needs re-super-encryption, from its KeyBlob type.
442 /// If so, re-super-encrypt the key and return a new set of metadata,
443 /// containing the new super encryption information.
444 pub fn reencrypt_on_upgrade_if_required<'a>(
445 key_blob_before_upgrade: &KeyBlob,
446 key_after_upgrade: &'a [u8],
447 ) -> Result<(KeyBlob<'a>, Option<BlobMetaData>)> {
448 match key_blob_before_upgrade {
449 KeyBlob::Sensitive(_, super_key) => {
450 let (key, metadata) = Self::encrypt_with_super_key(key_after_upgrade, super_key)
451 .context(
452 "In reencrypt_on_upgrade_if_required. Failed to re-super-encrypt key on key upgrade.",
453 )?;
454 Ok((KeyBlob::NonSensitive(key), Some(metadata)))
455 }
456 _ => Ok((KeyBlob::Ref(key_after_upgrade), None)),
457 }
458 }
459
460 // Helper function to decide if a key is super encrypted, given metadata.
461 fn key_super_encrypted(metadata: &BlobMetaData) -> bool {
462 if let Some(&EncryptedBy::KeyId(_)) = metadata.encrypted_by() {
463 return true;
464 }
465 false
466 }
Hasini Gunasinghe0e161452021-01-27 19:34:37 +0000467}
468
469/// This enum represents different states of the user's life cycle in the device.
470/// For now, only three states are defined. More states may be added later.
471pub enum UserState {
472 // The user has registered LSKF and has unlocked the device by entering PIN/Password,
473 // and hence the per-boot super key is available in the cache.
474 LskfUnlocked(SuperKey),
475 // The user has registered LSKF, but has not unlocked the device using password, after reboot.
476 // Hence the per-boot super-key(s) is not available in the cache.
477 // However, the encrypted super key is available in the database.
478 LskfLocked,
479 // There's no user in the device for the given user id, or the user with the user id has not
480 // setup LSKF.
481 Uninitialized,
482}
483
484impl UserState {
Hasini Gunasingheda895552021-01-27 19:34:37 +0000485 pub fn get(db: &mut KeystoreDB, skm: &SuperKeyManager, user_id: u32) -> Result<UserState> {
Hasini Gunasinghe0e161452021-01-27 19:34:37 +0000486 match skm.get_per_boot_key_by_user_id(user_id) {
487 Some(super_key) => Ok(UserState::LskfUnlocked(super_key)),
488 None => {
489 //Check if a super key exists in the database or legacy database.
490 //If so, return locked user state.
491 if SuperKeyManager::super_key_exists_in_db_for_user(db, user_id)
Hasini Gunasingheda895552021-01-27 19:34:37 +0000492 .context("In get.")?
Hasini Gunasinghe0e161452021-01-27 19:34:37 +0000493 {
494 Ok(UserState::LskfLocked)
495 } else {
496 Ok(UserState::Uninitialized)
497 }
498 }
499 }
500 }
Hasini Gunasingheda895552021-01-27 19:34:37 +0000501
502 /// Queries user state when serving password change requests.
503 pub fn get_with_password_changed(
504 db: &mut KeystoreDB,
505 skm: &SuperKeyManager,
506 user_id: u32,
507 password: Option<&[u8]>,
508 ) -> Result<UserState> {
509 match skm.get_per_boot_key_by_user_id(user_id) {
510 Some(super_key) => {
511 if password.is_none() {
512 //transitioning to swiping, delete only the super key in database and cache, and
513 //super-encrypted keys in database (and in KM)
514 Self::reset_user(db, skm, user_id, true)
515 .context("In get_with_password_changed.")?;
516 //Lskf is now removed in Keystore
517 Ok(UserState::Uninitialized)
518 } else {
519 //Keystore won't be notified when changing to a new password when LSKF is
520 //already setup. Therefore, ideally this path wouldn't be reached.
521 Ok(UserState::LskfUnlocked(super_key))
522 }
523 }
524 None => {
525 //Check if a super key exists in the database or legacy database.
526 //If so, return LskfLocked state.
527 //Otherwise, i) if the password is provided, initialize the super key and return
528 //LskfUnlocked state ii) if password is not provided, return Uninitialized state.
529 skm.check_and_initialize_super_key(db, user_id, password)
530 }
531 }
532 }
533
Hasini Gunasinghe731e3c82021-02-06 00:56:28 +0000534 /// Queries user state when serving password unlock requests.
535 pub fn get_with_password_unlock(
536 db: &mut KeystoreDB,
537 skm: &SuperKeyManager,
538 user_id: u32,
539 password: &[u8],
540 ) -> Result<UserState> {
541 match skm.get_per_boot_key_by_user_id(user_id) {
542 Some(super_key) => {
543 log::info!("In get_with_password_unlock. Trying to unlock when already unlocked.");
544 Ok(UserState::LskfUnlocked(super_key))
545 }
546 None => {
547 //Check if a super key exists in the database or legacy database.
548 //If not, return Uninitialized state.
549 //Otherwise, try to unlock the super key and if successful,
550 //return LskfUnlocked state
551 skm.check_and_unlock_super_key(db, user_id, password)
552 .context("In get_with_password_unlock. Failed to unlock super key.")
553 }
554 }
555 }
556
Hasini Gunasingheda895552021-01-27 19:34:37 +0000557 /// Delete all the keys created on behalf of the user.
558 /// If 'keep_non_super_encrypted_keys' is set to true, delete only the super key and super
559 /// encrypted keys.
560 pub fn reset_user(
561 db: &mut KeystoreDB,
562 skm: &SuperKeyManager,
563 user_id: u32,
564 keep_non_super_encrypted_keys: bool,
565 ) -> Result<()> {
566 // mark keys created on behalf of the user as unreferenced.
567 db.unbind_keys_for_user(user_id as u32, keep_non_super_encrypted_keys)
568 .context("In reset user. Error in unbinding keys.")?;
569
570 //delete super key in cache, if exists
571 skm.forget_all_keys_for_user(user_id as u32);
572 Ok(())
573 }
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800574}
Hasini Gunasinghedeab85d2021-02-01 21:10:02 +0000575
576/// This enum represents two states a Keymint Blob can be in, w.r.t super encryption.
577/// Sensitive variant represents a Keymint blob that is supposed to be super encrypted,
578/// but unwrapped during usage. Therefore, it has the super key along with the unwrapped key.
579/// Ref variant represents a Keymint blob that is not required to super encrypt or that is
580/// already super encrypted.
581pub enum KeyBlob<'a> {
582 Sensitive(ZVec, SuperKey),
583 NonSensitive(Vec<u8>),
584 Ref(&'a [u8]),
585}
586
587/// Deref returns a reference to the key material in both variants.
588impl<'a> Deref for KeyBlob<'a> {
589 type Target = [u8];
590
591 fn deref(&self) -> &Self::Target {
592 match self {
593 Self::Sensitive(key, _) => &key,
594 Self::NonSensitive(key) => &key,
595 Self::Ref(key) => key,
596 }
597 }
598}