blob: 840fbc682fe3e66f782fb605642a05a0c26f7c34 [file] [log] [blame]
Joel Galenson26f4d012020-07-17 14:57:21 -07001// 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
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070015//! This is the Keystore 2.0 database module.
16//! The database module provides a connection to the backing SQLite store.
17//! We have two databases one for persistent key blob storage and one for
18//! items that have a per boot life cycle.
19//!
20//! ## Persistent database
21//! The persistent database has tables for key blobs. They are organized
22//! as follows:
23//! The `keyentry` table is the primary table for key entries. It is
24//! accompanied by two tables for blobs and parameters.
25//! Each key entry occupies exactly one row in the `keyentry` table and
26//! zero or more rows in the tables `blobentry` and `keyparameter`.
27//!
28//! ## Per boot database
29//! The per boot database stores items with a per boot lifecycle.
30//! Currently, there is only the `grant` table in this database.
31//! Grants are references to a key that can be used to access a key by
32//! clients that don't own that key. Grants can only be created by the
33//! owner of a key. And only certain components can create grants.
34//! This is governed by SEPolicy.
35//!
36//! ## Access control
37//! Some database functions that load keys or create grants perform
38//! access control. This is because in some cases access control
39//! can only be performed after some information about the designated
40//! key was loaded from the database. To decouple the permission checks
41//! from the database module these functions take permission check
42//! callbacks.
Joel Galenson26f4d012020-07-17 14:57:21 -070043
Janis Danisevskis4507f3b2021-01-13 16:34:39 -080044use crate::db_utils::{self, SqlField};
Qi Wub9433b52020-12-01 14:52:46 +080045use crate::error::{Error as KsError, ErrorCode, ResponseCode};
Janis Danisevskisb42fc182020-12-15 08:41:27 -080046use crate::impl_metadata; // This is in db_utils.rs
Janis Danisevskis4522c2b2020-11-27 18:04:58 -080047use crate::key_parameter::{KeyParameter, Tag};
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070048use crate::permission::KeyPermSet;
Hasini Gunasinghe557b1032020-11-10 01:35:30 +000049use crate::utils::get_current_time_in_seconds;
Janis Danisevskisb42fc182020-12-15 08:41:27 -080050use anyhow::{anyhow, Context, Result};
51use std::{convert::TryFrom, convert::TryInto, time::SystemTimeError};
Janis Danisevskis60400fe2020-08-26 15:24:42 -070052
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +000053use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Janis Danisevskis5ed8c532021-01-11 14:19:42 -080054 HardwareAuthToken::HardwareAuthToken,
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +000055 HardwareAuthenticatorType::HardwareAuthenticatorType, SecurityLevel::SecurityLevel,
Janis Danisevskisc3a496b2021-01-05 10:37:22 -080056};
57use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +000058 Timestamp::Timestamp,
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +000059};
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070060use android_system_keystore2::aidl::android::system::keystore2::{
Janis Danisevskis04b02832020-10-26 09:21:40 -070061 Domain::Domain, KeyDescriptor::KeyDescriptor,
Janis Danisevskis60400fe2020-08-26 15:24:42 -070062};
Janis Danisevskisaec14592020-11-12 09:41:49 -080063use lazy_static::lazy_static;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +000064use log::error;
Joel Galenson0891bc12020-07-20 10:37:03 -070065#[cfg(not(test))]
66use rand::prelude::random;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070067use rusqlite::{
Janis Danisevskisb42fc182020-12-15 08:41:27 -080068 params,
69 types::FromSql,
70 types::FromSqlResult,
71 types::ToSqlOutput,
72 types::{FromSqlError, Value, ValueRef},
Janis Danisevskis5ed8c532021-01-11 14:19:42 -080073 Connection, OptionalExtension, ToSql, Transaction, TransactionBehavior, NO_PARAMS,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070074};
Janis Danisevskisaec14592020-11-12 09:41:49 -080075use std::{
Janis Danisevskisb42fc182020-12-15 08:41:27 -080076 collections::{HashMap, HashSet},
Janis Danisevskisbf15d732020-12-08 10:35:26 -080077 path::Path,
78 sync::{Condvar, Mutex},
Janis Danisevskisb42fc182020-12-15 08:41:27 -080079 time::{Duration, SystemTime},
Janis Danisevskisaec14592020-11-12 09:41:49 -080080};
Joel Galenson0891bc12020-07-20 10:37:03 -070081#[cfg(test)]
82use tests::random;
Joel Galenson26f4d012020-07-17 14:57:21 -070083
Janis Danisevskisb42fc182020-12-15 08:41:27 -080084impl_metadata!(
85 /// A set of metadata for key entries.
86 #[derive(Debug, Default, Eq, PartialEq)]
87 pub struct KeyMetaData;
88 /// A metadata entry for key entries.
89 #[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
90 pub enum KeyMetaEntry {
91 /// If present, indicates that the sensitive part of key
92 /// is encrypted with another key or a key derived from a password.
93 EncryptedBy(EncryptedBy) with accessor encrypted_by,
94 /// If the blob is password encrypted this field is set to the
95 /// salt used for the key derivation.
96 Salt(Vec<u8>) with accessor salt,
97 /// If the blob is encrypted, this field is set to the initialization vector.
98 Iv(Vec<u8>) with accessor iv,
99 /// If the blob is encrypted, this field holds the AEAD TAG.
100 AeadTag(Vec<u8>) with accessor aead_tag,
101 /// Creation date of a the key entry.
102 CreationDate(DateTime) with accessor creation_date,
103 /// Expiration date for attestation keys.
104 AttestationExpirationDate(DateTime) with accessor attestation_expiration_date,
105 // --- ADD NEW META DATA FIELDS HERE ---
106 // For backwards compatibility add new entries only to
107 // end of this list and above this comment.
108 };
109);
110
111impl KeyMetaData {
112 fn load_from_db(key_id: i64, tx: &Transaction) -> Result<Self> {
113 let mut stmt = tx
114 .prepare(
115 "SELECT tag, data from persistent.keymetadata
116 WHERE keyentryid = ?;",
117 )
118 .context("In KeyMetaData::load_from_db: prepare statement failed.")?;
119
120 let mut metadata: HashMap<i64, KeyMetaEntry> = Default::default();
121
122 let mut rows =
123 stmt.query(params![key_id]).context("In KeyMetaData::load_from_db: query failed.")?;
124 db_utils::with_rows_extract_all(&mut rows, |row| {
125 let db_tag: i64 = row.get(0).context("Failed to read tag.")?;
126 metadata.insert(
127 db_tag,
128 KeyMetaEntry::new_from_sql(db_tag, &SqlField::new(1, &row))
129 .context("Failed to read KeyMetaEntry.")?,
130 );
131 Ok(())
132 })
133 .context("In KeyMetaData::load_from_db.")?;
134
135 Ok(Self { data: metadata })
136 }
137
138 fn store_in_db(&self, key_id: i64, tx: &Transaction) -> Result<()> {
139 let mut stmt = tx
140 .prepare(
141 "INSERT into persistent.keymetadata (keyentryid, tag, data)
142 VALUES (?, ?, ?);",
143 )
144 .context("In KeyMetaData::store_in_db: Failed to prepare statement.")?;
145
146 let iter = self.data.iter();
147 for (tag, entry) in iter {
148 stmt.insert(params![key_id, tag, entry,]).with_context(|| {
149 format!("In KeyMetaData::store_in_db: Failed to insert {:?}", entry)
150 })?;
151 }
152 Ok(())
153 }
154}
155
156/// Indicates the type of the keyentry.
157#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
158pub enum KeyType {
159 /// This is a client key type. These keys are created or imported through the Keystore 2.0
160 /// AIDL interface android.system.keystore2.
161 Client,
162 /// This is a super key type. These keys are created by keystore itself and used to encrypt
163 /// other key blobs to provide LSKF binding.
164 Super,
165 /// This is an attestation key. These keys are created by the remote provisioning mechanism.
166 Attestation,
167}
168
169impl ToSql for KeyType {
170 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
171 Ok(ToSqlOutput::Owned(Value::Integer(match self {
172 KeyType::Client => 0,
173 KeyType::Super => 1,
174 KeyType::Attestation => 2,
175 })))
176 }
177}
178
179impl FromSql for KeyType {
180 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
181 match i64::column_result(value)? {
182 0 => Ok(KeyType::Client),
183 1 => Ok(KeyType::Super),
184 2 => Ok(KeyType::Attestation),
185 v => Err(FromSqlError::OutOfRange(v)),
186 }
187 }
188}
189
190/// Indicates how the sensitive part of this key blob is encrypted.
191#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
192pub enum EncryptedBy {
193 /// The keyblob is encrypted by a user password.
194 /// In the database this variant is represented as NULL.
195 Password,
196 /// The keyblob is encrypted by another key with wrapped key id.
197 /// In the database this variant is represented as non NULL value
198 /// that is convertible to i64, typically NUMERIC.
199 KeyId(i64),
200}
201
202impl ToSql for EncryptedBy {
203 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
204 match self {
205 Self::Password => Ok(ToSqlOutput::Owned(Value::Null)),
206 Self::KeyId(id) => id.to_sql(),
207 }
208 }
209}
210
211impl FromSql for EncryptedBy {
212 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
213 match value {
214 ValueRef::Null => Ok(Self::Password),
215 _ => Ok(Self::KeyId(i64::column_result(value)?)),
216 }
217 }
218}
219
220/// A database representation of wall clock time. DateTime stores unix epoch time as
221/// i64 in milliseconds.
222#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)]
223pub struct DateTime(i64);
224
225/// Error type returned when creating DateTime or converting it from and to
226/// SystemTime.
227#[derive(thiserror::Error, Debug)]
228pub enum DateTimeError {
229 /// This is returned when SystemTime and Duration computations fail.
230 #[error(transparent)]
231 SystemTimeError(#[from] SystemTimeError),
232
233 /// This is returned when type conversions fail.
234 #[error(transparent)]
235 TypeConversion(#[from] std::num::TryFromIntError),
236
237 /// This is returned when checked time arithmetic failed.
238 #[error("Time arithmetic failed.")]
239 TimeArithmetic,
240}
241
242impl DateTime {
243 /// Constructs a new DateTime object denoting the current time. This may fail during
244 /// conversion to unix epoch time and during conversion to the internal i64 representation.
245 pub fn now() -> Result<Self, DateTimeError> {
246 Ok(Self(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_millis().try_into()?))
247 }
248
249 /// Constructs a new DateTime object from milliseconds.
250 pub fn from_millis_epoch(millis: i64) -> Self {
251 Self(millis)
252 }
253
254 /// Returns unix epoch time in milliseconds.
255 pub fn to_millis_epoch(&self) -> i64 {
256 self.0
257 }
258
259 /// Returns unix epoch time in seconds.
260 pub fn to_secs_epoch(&self) -> i64 {
261 self.0 / 1000
262 }
263}
264
265impl ToSql for DateTime {
266 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
267 Ok(ToSqlOutput::Owned(Value::Integer(self.0)))
268 }
269}
270
271impl FromSql for DateTime {
272 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
273 Ok(Self(i64::column_result(value)?))
274 }
275}
276
277impl TryInto<SystemTime> for DateTime {
278 type Error = DateTimeError;
279
280 fn try_into(self) -> Result<SystemTime, Self::Error> {
281 // We want to construct a SystemTime representation equivalent to self, denoting
282 // a point in time THEN, but we cannot set the time directly. We can only construct
283 // a SystemTime denoting NOW, and we can get the duration between EPOCH and NOW,
284 // and between EPOCH and THEN. With this common reference we can construct the
285 // duration between NOW and THEN which we can add to our SystemTime representation
286 // of NOW to get a SystemTime representation of THEN.
287 // Durations can only be positive, thus the if statement below.
288 let now = SystemTime::now();
289 let now_epoch = now.duration_since(SystemTime::UNIX_EPOCH)?;
290 let then_epoch = Duration::from_millis(self.0.try_into()?);
291 Ok(if now_epoch > then_epoch {
292 // then = now - (now_epoch - then_epoch)
293 now_epoch
294 .checked_sub(then_epoch)
295 .and_then(|d| now.checked_sub(d))
296 .ok_or(DateTimeError::TimeArithmetic)?
297 } else {
298 // then = now + (then_epoch - now_epoch)
299 then_epoch
300 .checked_sub(now_epoch)
301 .and_then(|d| now.checked_add(d))
302 .ok_or(DateTimeError::TimeArithmetic)?
303 })
304 }
305}
306
307impl TryFrom<SystemTime> for DateTime {
308 type Error = DateTimeError;
309
310 fn try_from(t: SystemTime) -> Result<Self, Self::Error> {
311 Ok(Self(t.duration_since(SystemTime::UNIX_EPOCH)?.as_millis().try_into()?))
312 }
313}
314
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800315#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
316enum KeyLifeCycle {
317 /// Existing keys have a key ID but are not fully populated yet.
318 /// This is a transient state. If Keystore finds any such keys when it starts up, it must move
319 /// them to Unreferenced for garbage collection.
320 Existing,
321 /// A live key is fully populated and usable by clients.
322 Live,
323 /// An unreferenced key is scheduled for garbage collection.
324 Unreferenced,
325}
326
327impl ToSql for KeyLifeCycle {
328 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
329 match self {
330 Self::Existing => Ok(ToSqlOutput::Owned(Value::Integer(0))),
331 Self::Live => Ok(ToSqlOutput::Owned(Value::Integer(1))),
332 Self::Unreferenced => Ok(ToSqlOutput::Owned(Value::Integer(2))),
333 }
334 }
335}
336
337impl FromSql for KeyLifeCycle {
338 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
339 match i64::column_result(value)? {
340 0 => Ok(KeyLifeCycle::Existing),
341 1 => Ok(KeyLifeCycle::Live),
342 2 => Ok(KeyLifeCycle::Unreferenced),
343 v => Err(FromSqlError::OutOfRange(v)),
344 }
345 }
346}
347
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700348/// Keys have a KeyMint blob component and optional public certificate and
349/// certificate chain components.
350/// KeyEntryLoadBits is a bitmap that indicates to `KeystoreDB::load_key_entry`
351/// which components shall be loaded from the database if present.
352#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
353pub struct KeyEntryLoadBits(u32);
354
355impl KeyEntryLoadBits {
356 /// Indicate to `KeystoreDB::load_key_entry` that no component shall be loaded.
357 pub const NONE: KeyEntryLoadBits = Self(0);
358 /// Indicate to `KeystoreDB::load_key_entry` that the KeyMint component shall be loaded.
359 pub const KM: KeyEntryLoadBits = Self(1);
360 /// Indicate to `KeystoreDB::load_key_entry` that the Public components shall be loaded.
361 pub const PUBLIC: KeyEntryLoadBits = Self(2);
362 /// Indicate to `KeystoreDB::load_key_entry` that both components shall be loaded.
363 pub const BOTH: KeyEntryLoadBits = Self(3);
364
365 /// Returns true if this object indicates that the public components shall be loaded.
366 pub const fn load_public(&self) -> bool {
367 self.0 & Self::PUBLIC.0 != 0
368 }
369
370 /// Returns true if the object indicates that the KeyMint component shall be loaded.
371 pub const fn load_km(&self) -> bool {
372 self.0 & Self::KM.0 != 0
373 }
374}
375
Janis Danisevskisaec14592020-11-12 09:41:49 -0800376lazy_static! {
377 static ref KEY_ID_LOCK: KeyIdLockDb = KeyIdLockDb::new();
378}
379
380struct KeyIdLockDb {
381 locked_keys: Mutex<HashSet<i64>>,
382 cond_var: Condvar,
383}
384
385/// A locked key. While a guard exists for a given key id, the same key cannot be loaded
386/// from the database a second time. Most functions manipulating the key blob database
387/// require a KeyIdGuard.
388#[derive(Debug)]
389pub struct KeyIdGuard(i64);
390
391impl KeyIdLockDb {
392 fn new() -> Self {
393 Self { locked_keys: Mutex::new(HashSet::new()), cond_var: Condvar::new() }
394 }
395
396 /// This function blocks until an exclusive lock for the given key entry id can
397 /// be acquired. It returns a guard object, that represents the lifecycle of the
398 /// acquired lock.
399 pub fn get(&self, key_id: i64) -> KeyIdGuard {
400 let mut locked_keys = self.locked_keys.lock().unwrap();
401 while locked_keys.contains(&key_id) {
402 locked_keys = self.cond_var.wait(locked_keys).unwrap();
403 }
404 locked_keys.insert(key_id);
405 KeyIdGuard(key_id)
406 }
407
408 /// This function attempts to acquire an exclusive lock on a given key id. If the
409 /// given key id is already taken the function returns None immediately. If a lock
410 /// can be acquired this function returns a guard object, that represents the
411 /// lifecycle of the acquired lock.
412 pub fn try_get(&self, key_id: i64) -> Option<KeyIdGuard> {
413 let mut locked_keys = self.locked_keys.lock().unwrap();
414 if locked_keys.insert(key_id) {
415 Some(KeyIdGuard(key_id))
416 } else {
417 None
418 }
419 }
420}
421
422impl KeyIdGuard {
423 /// Get the numeric key id of the locked key.
424 pub fn id(&self) -> i64 {
425 self.0
426 }
427}
428
429impl Drop for KeyIdGuard {
430 fn drop(&mut self) {
431 let mut locked_keys = KEY_ID_LOCK.locked_keys.lock().unwrap();
432 locked_keys.remove(&self.0);
Janis Danisevskis7fd53582020-11-23 13:40:34 -0800433 drop(locked_keys);
Janis Danisevskisaec14592020-11-12 09:41:49 -0800434 KEY_ID_LOCK.cond_var.notify_all();
435 }
436}
437
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700438/// This type represents a Keystore 2.0 key entry.
439/// An entry has a unique `id` by which it can be found in the database.
440/// It has a security level field, key parameters, and three optional fields
441/// for the KeyMint blob, public certificate and a public certificate chain.
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800442#[derive(Debug, Default, Eq, PartialEq)]
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700443pub struct KeyEntry {
444 id: i64,
445 km_blob: Option<Vec<u8>>,
446 cert: Option<Vec<u8>>,
447 cert_chain: Option<Vec<u8>>,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700448 sec_level: SecurityLevel,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700449 parameters: Vec<KeyParameter>,
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800450 metadata: KeyMetaData,
Janis Danisevskis377d1002021-01-27 19:07:48 -0800451 pure_cert: bool,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700452}
453
454impl KeyEntry {
455 /// Returns the unique id of the Key entry.
456 pub fn id(&self) -> i64 {
457 self.id
458 }
459 /// Exposes the optional KeyMint blob.
460 pub fn km_blob(&self) -> &Option<Vec<u8>> {
461 &self.km_blob
462 }
463 /// Extracts the Optional KeyMint blob.
464 pub fn take_km_blob(&mut self) -> Option<Vec<u8>> {
465 self.km_blob.take()
466 }
467 /// Exposes the optional public certificate.
468 pub fn cert(&self) -> &Option<Vec<u8>> {
469 &self.cert
470 }
471 /// Extracts the optional public certificate.
472 pub fn take_cert(&mut self) -> Option<Vec<u8>> {
473 self.cert.take()
474 }
475 /// Exposes the optional public certificate chain.
476 pub fn cert_chain(&self) -> &Option<Vec<u8>> {
477 &self.cert_chain
478 }
479 /// Extracts the optional public certificate_chain.
480 pub fn take_cert_chain(&mut self) -> Option<Vec<u8>> {
481 self.cert_chain.take()
482 }
483 /// Returns the security level of the key entry.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700484 pub fn sec_level(&self) -> SecurityLevel {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700485 self.sec_level
486 }
Janis Danisevskis04b02832020-10-26 09:21:40 -0700487 /// Exposes the key parameters of this key entry.
488 pub fn key_parameters(&self) -> &Vec<KeyParameter> {
489 &self.parameters
490 }
491 /// Consumes this key entry and extracts the keyparameters from it.
492 pub fn into_key_parameters(self) -> Vec<KeyParameter> {
493 self.parameters
494 }
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800495 /// Exposes the key metadata of this key entry.
496 pub fn metadata(&self) -> &KeyMetaData {
497 &self.metadata
498 }
Janis Danisevskis377d1002021-01-27 19:07:48 -0800499 /// This returns true if the entry is a pure certificate entry with no
500 /// private key component.
501 pub fn pure_cert(&self) -> bool {
502 self.pure_cert
503 }
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700504}
505
506/// Indicates the sub component of a key entry for persistent storage.
Janis Danisevskis377d1002021-01-27 19:07:48 -0800507#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd)]
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700508pub struct SubComponentType(u32);
509impl SubComponentType {
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800510 /// Persistent identifier for a key blob.
511 pub const KEY_BLOB: SubComponentType = Self(0);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700512 /// Persistent identifier for a certificate blob.
513 pub const CERT: SubComponentType = Self(1);
514 /// Persistent identifier for a certificate chain blob.
515 pub const CERT_CHAIN: SubComponentType = Self(2);
516}
517
518impl ToSql for SubComponentType {
519 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
520 self.0.to_sql()
521 }
522}
523
524impl FromSql for SubComponentType {
525 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
526 Ok(Self(u32::column_result(value)?))
527 }
528}
529
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700530/// KeystoreDB wraps a connection to an SQLite database and tracks its
531/// ownership. It also implements all of Keystore 2.0's database functionality.
Joel Galenson26f4d012020-07-17 14:57:21 -0700532pub struct KeystoreDB {
Joel Galenson26f4d012020-07-17 14:57:21 -0700533 conn: Connection,
534}
535
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000536/// Database representation of the monotonic time retrieved from the system call clock_gettime with
537/// CLOCK_MONOTONIC_RAW. Stores monotonic time as i64 in seconds.
538#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)]
539pub struct MonotonicRawTime(i64);
540
541impl MonotonicRawTime {
542 /// Constructs a new MonotonicRawTime
543 pub fn now() -> Self {
544 Self(get_current_time_in_seconds())
545 }
546
547 /// Returns the integer value of MonotonicRawTime as i64
548 pub fn seconds(&self) -> i64 {
549 self.0
550 }
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800551
552 /// Like i64::checked_sub.
553 pub fn checked_sub(&self, other: &Self) -> Option<Self> {
554 self.0.checked_sub(other.0).map(Self)
555 }
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000556}
557
558impl ToSql for MonotonicRawTime {
559 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
560 Ok(ToSqlOutput::Owned(Value::Integer(self.0)))
561 }
562}
563
564impl FromSql for MonotonicRawTime {
565 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
566 Ok(Self(i64::column_result(value)?))
567 }
568}
569
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000570/// This struct encapsulates the information to be stored in the database about the auth tokens
571/// received by keystore.
572pub struct AuthTokenEntry {
573 auth_token: HardwareAuthToken,
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000574 time_received: MonotonicRawTime,
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000575}
576
577impl AuthTokenEntry {
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000578 fn new(auth_token: HardwareAuthToken, time_received: MonotonicRawTime) -> Self {
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000579 AuthTokenEntry { auth_token, time_received }
580 }
581
582 /// Checks if this auth token satisfies the given authentication information.
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800583 pub fn satisfies(&self, user_secure_ids: &[i64], auth_type: HardwareAuthenticatorType) -> bool {
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000584 user_secure_ids.iter().any(|&sid| {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800585 (sid == self.auth_token.userId || sid == self.auth_token.authenticatorId)
586 && (((auth_type.0 as i32) & (self.auth_token.authenticatorType.0 as i32)) != 0)
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000587 })
588 }
589
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000590 /// Returns the auth token wrapped by the AuthTokenEntry
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800591 pub fn auth_token(&self) -> &HardwareAuthToken {
592 &self.auth_token
593 }
594
595 /// Returns the auth token wrapped by the AuthTokenEntry
596 pub fn take_auth_token(self) -> HardwareAuthToken {
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000597 self.auth_token
598 }
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800599
600 /// Returns the time that this auth token was received.
601 pub fn time_received(&self) -> MonotonicRawTime {
602 self.time_received
603 }
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000604}
605
Joel Galenson26f4d012020-07-17 14:57:21 -0700606impl KeystoreDB {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700607 /// This will create a new database connection connecting the two
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800608 /// files persistent.sqlite and perboot.sqlite in the given directory.
609 /// It also attempts to initialize all of the tables.
610 /// KeystoreDB cannot be used by multiple threads.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700611 /// Each thread should open their own connection using `thread_local!`.
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800612 pub fn new(db_root: &Path) -> Result<Self> {
613 // Build the path to the sqlite files.
614 let mut persistent_path = db_root.to_path_buf();
615 persistent_path.push("persistent.sqlite");
616 let mut perboot_path = db_root.to_path_buf();
617 perboot_path.push("perboot.sqlite");
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700618
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800619 // Now convert them to strings prefixed with "file:"
620 let mut persistent_path_str = "file:".to_owned();
621 persistent_path_str.push_str(&persistent_path.to_string_lossy());
622 let mut perboot_path_str = "file:".to_owned();
623 perboot_path_str.push_str(&perboot_path.to_string_lossy());
624
625 let conn = Self::make_connection(&persistent_path_str, &perboot_path_str)?;
Janis Danisevskisaea27342021-01-29 08:38:11 -0800626 conn.busy_handler(Some(|_| {
627 std::thread::sleep(std::time::Duration::from_micros(50));
628 true
629 }))
630 .context("In KeystoreDB::new: Failed to set busy handler.")?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800631
632 Self::init_tables(&conn)?;
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700633 Ok(Self { conn })
Joel Galenson2aab4432020-07-22 15:27:57 -0700634 }
635
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700636 fn init_tables(conn: &Connection) -> Result<()> {
637 conn.execute(
638 "CREATE TABLE IF NOT EXISTS persistent.keyentry (
Joel Galenson0891bc12020-07-20 10:37:03 -0700639 id INTEGER UNIQUE,
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800640 key_type INTEGER,
Joel Galenson0891bc12020-07-20 10:37:03 -0700641 domain INTEGER,
642 namespace INTEGER,
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800643 alias BLOB,
644 state INTEGER);",
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700645 NO_PARAMS,
646 )
647 .context("Failed to initialize \"keyentry\" table.")?;
648
649 conn.execute(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700650 "CREATE TABLE IF NOT EXISTS persistent.blobentry (
651 id INTEGER PRIMARY KEY,
652 subcomponent_type INTEGER,
653 keyentryid INTEGER,
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800654 blob BLOB);",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700655 NO_PARAMS,
656 )
657 .context("Failed to initialize \"blobentry\" table.")?;
658
659 conn.execute(
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700660 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000661 keyentryid INTEGER,
662 tag INTEGER,
663 data ANY,
664 security_level INTEGER);",
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700665 NO_PARAMS,
666 )
667 .context("Failed to initialize \"keyparameter\" table.")?;
668
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700669 conn.execute(
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800670 "CREATE TABLE IF NOT EXISTS persistent.keymetadata (
671 keyentryid INTEGER,
672 tag INTEGER,
673 data ANY);",
674 NO_PARAMS,
675 )
676 .context("Failed to initialize \"keymetadata\" table.")?;
677
678 conn.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800679 "CREATE TABLE IF NOT EXISTS persistent.grant (
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700680 id INTEGER UNIQUE,
681 grantee INTEGER,
682 keyentryid INTEGER,
683 access_vector INTEGER);",
684 NO_PARAMS,
685 )
686 .context("Failed to initialize \"grant\" table.")?;
687
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000688 //TODO: only drop the following two perboot tables if this is the first start up
689 //during the boot (b/175716626).
690 // conn.execute("DROP TABLE IF EXISTS perboot.authtoken;", NO_PARAMS)
691 // .context("Failed to drop perboot.authtoken table")?;
692 conn.execute(
693 "CREATE TABLE IF NOT EXISTS perboot.authtoken (
694 id INTEGER PRIMARY KEY,
695 challenge INTEGER,
696 user_id INTEGER,
697 auth_id INTEGER,
698 authenticator_type INTEGER,
699 timestamp INTEGER,
700 mac BLOB,
701 time_received INTEGER,
702 UNIQUE(user_id, auth_id, authenticator_type));",
703 NO_PARAMS,
704 )
705 .context("Failed to initialize \"authtoken\" table.")?;
706
707 // conn.execute("DROP TABLE IF EXISTS perboot.metadata;", NO_PARAMS)
708 // .context("Failed to drop perboot.metadata table")?;
709 // metadata table stores certain miscellaneous information required for keystore functioning
710 // during a boot cycle, as key-value pairs.
711 conn.execute(
712 "CREATE TABLE IF NOT EXISTS perboot.metadata (
713 key TEXT,
714 value BLOB,
715 UNIQUE(key));",
716 NO_PARAMS,
717 )
718 .context("Failed to initialize \"metadata\" table.")?;
Joel Galenson0891bc12020-07-20 10:37:03 -0700719 Ok(())
720 }
721
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700722 fn make_connection(persistent_file: &str, perboot_file: &str) -> Result<Connection> {
723 let conn =
724 Connection::open_in_memory().context("Failed to initialize SQLite connection.")?;
725
726 conn.execute("ATTACH DATABASE ? as persistent;", params![persistent_file])
727 .context("Failed to attach database persistent.")?;
728 conn.execute("ATTACH DATABASE ? as perboot;", params![perboot_file])
729 .context("Failed to attach database perboot.")?;
730
731 Ok(conn)
732 }
733
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800734 /// Get one unreferenced key. There is no particular order in which the keys are returned.
735 fn get_unreferenced_key_id(tx: &Transaction) -> Result<Option<i64>> {
736 tx.query_row(
737 "SELECT id FROM persistent.keyentry WHERE state = ?",
738 params![KeyLifeCycle::Unreferenced],
739 |row| row.get(0),
740 )
741 .optional()
742 .context("In get_unreferenced_key_id: Trying to get unreferenced key id.")
743 }
744
745 /// Returns a key id guard and key entry for one unreferenced key entry. Of the optional
746 /// fields of the key entry only the km_blob field will be populated. This is required
747 /// to subject the blob to its KeyMint instance for deletion.
748 pub fn get_unreferenced_key(&mut self) -> Result<Option<(KeyIdGuard, KeyEntry)>> {
749 self.with_transaction(TransactionBehavior::Deferred, |tx| {
750 let key_id = match Self::get_unreferenced_key_id(tx)
751 .context("Trying to get unreferenced key id")?
752 {
753 None => return Ok(None),
754 Some(id) => KEY_ID_LOCK.try_get(id).ok_or_else(KsError::sys).context(concat!(
755 "A key id lock was held for an unreferenced key. ",
756 "This should never happen."
757 ))?,
758 };
759 let key_entry = Self::load_key_components(tx, KeyEntryLoadBits::KM, key_id.id())
760 .context("Trying to get key components.")?;
761 Ok(Some((key_id, key_entry)))
762 })
763 .context("In get_unreferenced_key.")
764 }
765
766 /// This function purges all remnants of a key entry from the database.
767 /// Important: This does not check if the key was unreferenced, nor does it
768 /// subject the key to its KeyMint instance for permanent invalidation.
769 /// This function should only be called by the garbage collector.
770 /// To delete a key call `mark_unreferenced`, which transitions the key to the unreferenced
771 /// state, deletes all grants to the key, and notifies the garbage collector.
772 /// The garbage collector will:
773 /// 1. Call get_unreferenced_key.
774 /// 2. Determine the proper way to dispose of sensitive key material, e.g., call
775 /// `KeyMintDevice::delete()`.
776 /// 3. Call `purge_key_entry`.
777 pub fn purge_key_entry(&mut self, key_id: KeyIdGuard) -> Result<()> {
778 self.with_transaction(TransactionBehavior::Immediate, |tx| {
779 tx.execute("DELETE FROM persistent.keyentry WHERE id = ?;", params![key_id.id()])
780 .context("Trying to delete keyentry.")?;
781 tx.execute(
782 "DELETE FROM persistent.blobentry WHERE keyentryid = ?;",
783 params![key_id.id()],
784 )
785 .context("Trying to delete blobentries.")?;
786 tx.execute(
787 "DELETE FROM persistent.keymetadata WHERE keyentryid = ?;",
788 params![key_id.id()],
789 )
790 .context("Trying to delete keymetadata.")?;
791 tx.execute(
792 "DELETE FROM persistent.keyparameter WHERE keyentryid = ?;",
793 params![key_id.id()],
794 )
795 .context("Trying to delete keyparameters.")?;
796 let grants_deleted = tx
797 .execute("DELETE FROM persistent.grant WHERE keyentryid = ?;", params![key_id.id()])
798 .context("Trying to delete grants.")?;
799 if grants_deleted != 0 {
800 log::error!("Purged key that still had grants. This should not happen.");
801 }
802 Ok(())
803 })
804 .context("In purge_key_entry.")
805 }
806
807 /// This maintenance function should be called only once before the database is used for the
808 /// first time. It restores the invariant that `KeyLifeCycle::Existing` is a transient state.
809 /// The function transitions all key entries from Existing to Unreferenced unconditionally and
810 /// returns the number of rows affected. If this returns a value greater than 0, it means that
811 /// Keystore crashed at some point during key generation. Callers may want to log such
812 /// occurrences.
813 /// Unlike with `mark_unreferenced`, we don't need to purge grants, because only keys that made
814 /// it to `KeyLifeCycle::Live` may have grants.
815 pub fn cleanup_leftovers(&mut self) -> Result<usize> {
816 self.conn
817 .execute(
818 "UPDATE persistent.keyentry SET state = ? WHERE state = ?;",
819 params![KeyLifeCycle::Unreferenced, KeyLifeCycle::Existing],
820 )
821 .context("In cleanup_leftovers.")
822 }
823
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800824 /// Atomically loads a key entry and associated metadata or creates it using the
825 /// callback create_new_key callback. The callback is called during a database
826 /// transaction. This means that implementers should be mindful about using
827 /// blocking operations such as IPC or grabbing mutexes.
828 pub fn get_or_create_key_with<F>(
829 &mut self,
830 domain: Domain,
831 namespace: i64,
832 alias: &str,
833 create_new_key: F,
834 ) -> Result<(KeyIdGuard, KeyEntry)>
835 where
836 F: FnOnce() -> Result<(Vec<u8>, KeyMetaData)>,
837 {
838 let tx = self
839 .conn
840 .transaction_with_behavior(TransactionBehavior::Immediate)
841 .context("In get_or_create_key_with: Failed to initialize transaction.")?;
842
843 let id = {
844 let mut stmt = tx
845 .prepare(
846 "SELECT id FROM persistent.keyentry
847 WHERE
848 key_type = ?
849 AND domain = ?
850 AND namespace = ?
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800851 AND alias = ?
852 AND state = ?;",
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800853 )
854 .context("In get_or_create_key_with: Failed to select from keyentry table.")?;
855 let mut rows = stmt
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800856 .query(params![KeyType::Super, domain.0, namespace, alias, KeyLifeCycle::Live])
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800857 .context("In get_or_create_key_with: Failed to query from keyentry table.")?;
858
859 db_utils::with_rows_extract_one(&mut rows, |row| {
860 Ok(match row {
861 Some(r) => r.get(0).context("Failed to unpack id.")?,
862 None => None,
863 })
864 })
865 .context("In get_or_create_key_with.")?
866 };
867
868 let (id, entry) = match id {
869 Some(id) => (
870 id,
871 Self::load_key_components(&tx, KeyEntryLoadBits::KM, id)
872 .context("In get_or_create_key_with.")?,
873 ),
874
875 None => {
876 let id = Self::insert_with_retry(|id| {
877 tx.execute(
878 "INSERT into persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800879 (id, key_type, domain, namespace, alias, state)
880 VALUES(?, ?, ?, ?, ?, ?);",
881 params![id, KeyType::Super, domain.0, namespace, alias, KeyLifeCycle::Live],
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800882 )
883 })
884 .context("In get_or_create_key_with.")?;
885
886 let (blob, metadata) = create_new_key().context("In get_or_create_key_with.")?;
Janis Danisevskis377d1002021-01-27 19:07:48 -0800887 Self::set_blob_internal(&tx, id, SubComponentType::KEY_BLOB, Some(&blob))
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800888 .context("In get_of_create_key_with.")?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800889 metadata.store_in_db(id, &tx).context("In get_or_create_key_with.")?;
Janis Danisevskis377d1002021-01-27 19:07:48 -0800890 (
891 id,
892 KeyEntry {
893 id,
894 km_blob: Some(blob),
895 metadata,
896 pure_cert: false,
897 ..Default::default()
898 },
899 )
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800900 }
901 };
902 tx.commit().context("In get_or_create_key_with: Failed to commit transaction.")?;
903 Ok((KEY_ID_LOCK.get(id), entry))
904 }
905
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800906 /// Creates a transaction with the given behavior and executes f with the new transaction.
907 /// The transaction is committed only if f returns Ok.
908 fn with_transaction<T, F>(&mut self, behavior: TransactionBehavior, f: F) -> Result<T>
909 where
910 F: FnOnce(&Transaction) -> Result<T>,
911 {
912 let tx = self
913 .conn
914 .transaction_with_behavior(behavior)
915 .context("In with_transaction: Failed to initialize transaction.")?;
916 f(&tx).and_then(|result| {
917 tx.commit().context("In with_transaction: Failed to commit transaction.")?;
918 Ok(result)
919 })
920 }
921
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700922 /// Creates a new key entry and allocates a new randomized id for the new key.
923 /// The key id gets associated with a domain and namespace but not with an alias.
924 /// To complete key generation `rebind_alias` should be called after all of the
925 /// key artifacts, i.e., blobs and parameters have been associated with the new
926 /// key id. Finalizing with `rebind_alias` makes the creation of a new key entry
927 /// atomic even if key generation is not.
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800928 pub fn create_key_entry(&mut self, domain: Domain, namespace: i64) -> Result<KeyIdGuard> {
929 self.with_transaction(TransactionBehavior::Immediate, |tx| {
930 Self::create_key_entry_internal(tx, domain, namespace)
931 })
932 .context("In create_key_entry.")
933 }
934
935 fn create_key_entry_internal(
936 tx: &Transaction,
937 domain: Domain,
938 namespace: i64,
939 ) -> Result<KeyIdGuard> {
Joel Galenson0891bc12020-07-20 10:37:03 -0700940 match domain {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700941 Domain::APP | Domain::SELINUX => {}
Joel Galenson0891bc12020-07-20 10:37:03 -0700942 _ => {
943 return Err(KsError::sys())
944 .context(format!("Domain {:?} must be either App or SELinux.", domain));
945 }
946 }
Janis Danisevskisaec14592020-11-12 09:41:49 -0800947 Ok(KEY_ID_LOCK.get(
948 Self::insert_with_retry(|id| {
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800949 tx.execute(
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800950 "INSERT into persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800951 (id, key_type, domain, namespace, alias, state)
952 VALUES(?, ?, ?, ?, NULL, ?);",
953 params![
954 id,
955 KeyType::Client,
956 domain.0 as u32,
957 namespace,
958 KeyLifeCycle::Existing
959 ],
Janis Danisevskisaec14592020-11-12 09:41:49 -0800960 )
961 })
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800962 .context("In create_key_entry_internal")?,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800963 ))
Joel Galenson26f4d012020-07-17 14:57:21 -0700964 }
Joel Galenson33c04ad2020-08-03 11:04:38 -0700965
Janis Danisevskis377d1002021-01-27 19:07:48 -0800966 /// Set a new blob and associates it with the given key id. Each blob
967 /// has a sub component type.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700968 /// Each key can have one of each sub component type associated. If more
969 /// are added only the most recent can be retrieved, and superseded blobs
Janis Danisevskis377d1002021-01-27 19:07:48 -0800970 /// will get garbage collected.
971 /// Components SubComponentType::CERT and SubComponentType::CERT_CHAIN can be
972 /// removed by setting blob to None.
973 pub fn set_blob(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700974 &mut self,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800975 key_id: &KeyIdGuard,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700976 sc_type: SubComponentType,
Janis Danisevskis377d1002021-01-27 19:07:48 -0800977 blob: Option<&[u8]>,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700978 ) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800979 self.with_transaction(TransactionBehavior::Immediate, |tx| {
Janis Danisevskis377d1002021-01-27 19:07:48 -0800980 Self::set_blob_internal(&tx, key_id.0, sc_type, blob)
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800981 })
Janis Danisevskis377d1002021-01-27 19:07:48 -0800982 .context("In set_blob.")
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800983 }
984
Janis Danisevskis377d1002021-01-27 19:07:48 -0800985 fn set_blob_internal(
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800986 tx: &Transaction,
987 key_id: i64,
988 sc_type: SubComponentType,
Janis Danisevskis377d1002021-01-27 19:07:48 -0800989 blob: Option<&[u8]>,
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800990 ) -> Result<()> {
Janis Danisevskis377d1002021-01-27 19:07:48 -0800991 match (blob, sc_type) {
992 (Some(blob), _) => {
993 tx.execute(
994 "INSERT INTO persistent.blobentry
995 (subcomponent_type, keyentryid, blob) VALUES (?, ?, ?);",
996 params![sc_type, key_id, blob],
997 )
998 .context("In set_blob_internal: Failed to insert blob.")?;
999 }
1000 (None, SubComponentType::CERT) | (None, SubComponentType::CERT_CHAIN) => {
1001 tx.execute(
1002 "DELETE FROM persistent.blobentry
1003 WHERE subcomponent_type = ? AND keyentryid = ?;",
1004 params![sc_type, key_id],
1005 )
1006 .context("In set_blob_internal: Failed to delete blob.")?;
1007 }
1008 (None, _) => {
1009 return Err(KsError::sys())
1010 .context("In set_blob_internal: Other blobs cannot be deleted in this way.");
1011 }
1012 }
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001013 Ok(())
1014 }
1015
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001016 /// Inserts a collection of key parameters into the `persistent.keyparameter` table
1017 /// and associates them with the given `key_id`.
1018 pub fn insert_keyparameter<'a>(
1019 &mut self,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001020 key_id: &KeyIdGuard,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001021 params: impl IntoIterator<Item = &'a KeyParameter>,
1022 ) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001023 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1024 Self::insert_keyparameter_internal(tx, key_id, params)
1025 })
1026 .context("In insert_keyparameter.")
1027 }
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001028
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001029 fn insert_keyparameter_internal<'a>(
1030 tx: &Transaction,
1031 key_id: &KeyIdGuard,
1032 params: impl IntoIterator<Item = &'a KeyParameter>,
1033 ) -> Result<()> {
1034 let mut stmt = tx
1035 .prepare(
1036 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
1037 VALUES (?, ?, ?, ?);",
1038 )
1039 .context("In insert_keyparameter_internal: Failed to prepare statement.")?;
1040
1041 let iter = params.into_iter();
1042 for p in iter {
1043 stmt.insert(params![
1044 key_id.0,
1045 p.get_tag().0,
1046 p.key_parameter_value(),
1047 p.security_level().0
1048 ])
1049 .with_context(|| {
1050 format!("In insert_keyparameter_internal: Failed to insert {:?}", p)
1051 })?;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001052 }
1053 Ok(())
1054 }
1055
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001056 /// Insert a set of key entry specific metadata into the database.
1057 pub fn insert_key_metadata(
1058 &mut self,
1059 key_id: &KeyIdGuard,
1060 metadata: &KeyMetaData,
1061 ) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001062 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1063 metadata.store_in_db(key_id.0, &tx)
1064 })
1065 .context("In insert_key_metadata.")
1066 }
1067
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001068 /// Updates the alias column of the given key id `newid` with the given alias,
1069 /// and atomically, removes the alias, domain, and namespace from another row
1070 /// with the same alias-domain-namespace tuple if such row exits.
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08001071 /// Returns Ok(true) if an old key was marked unreferenced as a hint to the garbage
1072 /// collector.
1073 fn rebind_alias(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001074 tx: &Transaction,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001075 newid: &KeyIdGuard,
Joel Galenson33c04ad2020-08-03 11:04:38 -07001076 alias: &str,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001077 domain: Domain,
Joel Galenson33c04ad2020-08-03 11:04:38 -07001078 namespace: i64,
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08001079 ) -> Result<bool> {
Joel Galenson33c04ad2020-08-03 11:04:38 -07001080 match domain {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001081 Domain::APP | Domain::SELINUX => {}
Joel Galenson33c04ad2020-08-03 11:04:38 -07001082 _ => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001083 return Err(KsError::sys()).context(format!(
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08001084 "In rebind_alias: Domain {:?} must be either App or SELinux.",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001085 domain
1086 ));
Joel Galenson33c04ad2020-08-03 11:04:38 -07001087 }
1088 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001089 let updated = tx
1090 .execute(
1091 "UPDATE persistent.keyentry
1092 SET alias = NULL, domain = NULL, namespace = NULL, state = ?
Joel Galenson33c04ad2020-08-03 11:04:38 -07001093 WHERE alias = ? AND domain = ? AND namespace = ?;",
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001094 params![KeyLifeCycle::Unreferenced, alias, domain.0 as u32, namespace],
1095 )
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08001096 .context("In rebind_alias: Failed to rebind existing entry.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07001097 let result = tx
1098 .execute(
1099 "UPDATE persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001100 SET alias = ?, state = ?
1101 WHERE id = ? AND domain = ? AND namespace = ? AND state = ?;",
1102 params![
1103 alias,
1104 KeyLifeCycle::Live,
1105 newid.0,
1106 domain.0 as u32,
1107 namespace,
1108 KeyLifeCycle::Existing
1109 ],
Joel Galenson33c04ad2020-08-03 11:04:38 -07001110 )
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08001111 .context("In rebind_alias: Failed to set alias.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07001112 if result != 1 {
Joel Galenson33c04ad2020-08-03 11:04:38 -07001113 return Err(KsError::sys()).context(format!(
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08001114 "In rebind_alias: Expected to update a single entry but instead updated {}.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07001115 result
1116 ));
1117 }
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08001118 Ok(updated != 0)
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001119 }
1120
1121 /// Store a new key in a single transaction.
1122 /// The function creates a new key entry, populates the blob, key parameter, and metadata
1123 /// fields, and rebinds the given alias to the new key.
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08001124 /// The boolean returned is a hint for the garbage collector. If true, a key was replaced,
1125 /// is now unreferenced and needs to be collected.
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001126 pub fn store_new_key<'a>(
1127 &mut self,
1128 key: KeyDescriptor,
1129 params: impl IntoIterator<Item = &'a KeyParameter>,
1130 blob: &[u8],
1131 cert: Option<&[u8]>,
1132 cert_chain: Option<&[u8]>,
1133 metadata: &KeyMetaData,
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08001134 ) -> Result<(bool, KeyIdGuard)> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001135 let (alias, domain, namespace) = match key {
1136 KeyDescriptor { alias: Some(alias), domain: Domain::APP, nspace, blob: None }
1137 | KeyDescriptor { alias: Some(alias), domain: Domain::SELINUX, nspace, blob: None } => {
1138 (alias, key.domain, nspace)
1139 }
1140 _ => {
1141 return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT))
1142 .context("In store_new_key: Need alias and domain must be APP or SELINUX.")
1143 }
1144 };
1145 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1146 let key_id = Self::create_key_entry_internal(tx, domain, namespace)
1147 .context("Trying to create new key entry.")?;
Janis Danisevskis377d1002021-01-27 19:07:48 -08001148 Self::set_blob_internal(tx, key_id.id(), SubComponentType::KEY_BLOB, Some(blob))
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001149 .context("Trying to insert the key blob.")?;
1150 if let Some(cert) = cert {
Janis Danisevskis377d1002021-01-27 19:07:48 -08001151 Self::set_blob_internal(tx, key_id.id(), SubComponentType::CERT, Some(&cert))
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001152 .context("Trying to insert the certificate.")?;
1153 }
1154 if let Some(cert_chain) = cert_chain {
Janis Danisevskis377d1002021-01-27 19:07:48 -08001155 Self::set_blob_internal(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001156 tx,
1157 key_id.id(),
1158 SubComponentType::CERT_CHAIN,
Janis Danisevskis377d1002021-01-27 19:07:48 -08001159 Some(&cert_chain),
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001160 )
1161 .context("Trying to insert the certificate chain.")?;
1162 }
1163 Self::insert_keyparameter_internal(tx, &key_id, params)
1164 .context("Trying to insert key parameters.")?;
Janis Danisevskis377d1002021-01-27 19:07:48 -08001165 metadata.store_in_db(key_id.id(), tx).context("Trying to insert key metadata.")?;
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08001166 let need_gc = Self::rebind_alias(tx, &key_id, &alias, domain, namespace)
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001167 .context("Trying to rebind alias.")?;
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08001168 Ok((need_gc, key_id))
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001169 })
1170 .context("In store_new_key.")
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001171 }
1172
Janis Danisevskis377d1002021-01-27 19:07:48 -08001173 /// Store a new certificate
1174 /// The function creates a new key entry, populates the blob field and metadata, and rebinds
1175 /// the given alias to the new cert.
1176 pub fn store_new_certificate(&mut self, key: KeyDescriptor, cert: &[u8]) -> Result<KeyIdGuard> {
1177 let (alias, domain, namespace) = match key {
1178 KeyDescriptor { alias: Some(alias), domain: Domain::APP, nspace, blob: None }
1179 | KeyDescriptor { alias: Some(alias), domain: Domain::SELINUX, nspace, blob: None } => {
1180 (alias, key.domain, nspace)
1181 }
1182 _ => {
1183 return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT)).context(
1184 "In store_new_certificate: Need alias and domain must be APP or SELINUX.",
1185 )
1186 }
1187 };
1188 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1189 let key_id = Self::create_key_entry_internal(tx, domain, namespace)
1190 .context("Trying to create new key entry.")?;
1191
1192 Self::set_blob_internal(tx, key_id.id(), SubComponentType::CERT_CHAIN, Some(cert))
1193 .context("Trying to insert certificate.")?;
1194
1195 let mut metadata = KeyMetaData::new();
1196 metadata.add(KeyMetaEntry::CreationDate(
1197 DateTime::now().context("Trying to make creation time.")?,
1198 ));
1199
1200 metadata.store_in_db(key_id.id(), tx).context("Trying to insert key metadata.")?;
1201
1202 Self::rebind_alias(tx, &key_id, &alias, domain, namespace)
1203 .context("Trying to rebind alias.")?;
1204 Ok(key_id)
1205 })
1206 .context("In store_new_certificate.")
1207 }
1208
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001209 // Helper function loading the key_id given the key descriptor
1210 // tuple comprising domain, namespace, and alias.
1211 // Requires a valid transaction.
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001212 fn load_key_entry_id(tx: &Transaction, key: &KeyDescriptor, key_type: KeyType) -> Result<i64> {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001213 let alias = key
1214 .alias
1215 .as_ref()
1216 .map_or_else(|| Err(KsError::sys()), Ok)
1217 .context("In load_key_entry_id: Alias must be specified.")?;
1218 let mut stmt = tx
1219 .prepare(
1220 "SELECT id FROM persistent.keyentry
1221 WHERE
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001222 key_type = ?
1223 AND domain = ?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001224 AND namespace = ?
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001225 AND alias = ?
1226 AND state = ?;",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001227 )
1228 .context("In load_key_entry_id: Failed to select from keyentry table.")?;
1229 let mut rows = stmt
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001230 .query(params![key_type, key.domain.0 as u32, key.nspace, alias, KeyLifeCycle::Live])
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001231 .context("In load_key_entry_id: Failed to read from keyentry table.")?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001232 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001233 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001234 .get(0)
1235 .context("Failed to unpack id.")
1236 })
1237 .context("In load_key_entry_id.")
1238 }
1239
1240 /// This helper function completes the access tuple of a key, which is required
1241 /// to perform access control. The strategy depends on the `domain` field in the
1242 /// key descriptor.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001243 /// * Domain::SELINUX: The access tuple is complete and this function only loads
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001244 /// the key_id for further processing.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001245 /// * Domain::APP: Like Domain::SELINUX, but the tuple is completed by `caller_uid`
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001246 /// which serves as the namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001247 /// * Domain::GRANT: The grant table is queried for the `key_id` and the
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001248 /// `access_vector`.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001249 /// * Domain::KEY_ID: The keyentry table is queried for the owning `domain` and
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001250 /// `namespace`.
1251 /// In each case the information returned is sufficient to perform the access
1252 /// check and the key id can be used to load further key artifacts.
1253 fn load_access_tuple(
1254 tx: &Transaction,
1255 key: KeyDescriptor,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001256 key_type: KeyType,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001257 caller_uid: u32,
1258 ) -> Result<(i64, KeyDescriptor, Option<KeyPermSet>)> {
1259 match key.domain {
1260 // Domain App or SELinux. In this case we load the key_id from
1261 // the keyentry database for further loading of key components.
1262 // We already have the full access tuple to perform access control.
1263 // The only distinction is that we use the caller_uid instead
1264 // of the caller supplied namespace if the domain field is
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001265 // Domain::APP.
1266 Domain::APP | Domain::SELINUX => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001267 let mut access_key = key;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001268 if access_key.domain == Domain::APP {
1269 access_key.nspace = caller_uid as i64;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001270 }
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001271 let key_id = Self::load_key_entry_id(&tx, &access_key, key_type)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001272 .with_context(|| format!("With key.domain = {:?}.", access_key.domain))?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001273
1274 Ok((key_id, access_key, None))
1275 }
1276
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001277 // Domain::GRANT. In this case we load the key_id and the access_vector
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001278 // from the grant table.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001279 Domain::GRANT => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001280 let mut stmt = tx
1281 .prepare(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001282 "SELECT keyentryid, access_vector FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001283 WHERE grantee = ? AND id = ?;",
1284 )
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001285 .context("Domain::GRANT prepare statement failed")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001286 let mut rows = stmt
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001287 .query(params![caller_uid as i64, key.nspace])
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001288 .context("Domain:Grant: query failed.")?;
1289 let (key_id, access_vector): (i64, i32) =
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001290 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001291 let r =
1292 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001293 Ok((
1294 r.get(0).context("Failed to unpack key_id.")?,
1295 r.get(1).context("Failed to unpack access_vector.")?,
1296 ))
1297 })
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001298 .context("Domain::GRANT.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001299 Ok((key_id, key, Some(access_vector.into())))
1300 }
1301
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001302 // Domain::KEY_ID. In this case we load the domain and namespace from the
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001303 // keyentry database because we need them for access control.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001304 Domain::KEY_ID => {
Janis Danisevskis45760022021-01-19 16:34:10 -08001305 let (domain, namespace): (Domain, i64) = {
1306 let mut stmt = tx
1307 .prepare(
1308 "SELECT domain, namespace FROM persistent.keyentry
1309 WHERE
1310 id = ?
1311 AND state = ?;",
1312 )
1313 .context("Domain::KEY_ID: prepare statement failed")?;
1314 let mut rows = stmt
1315 .query(params![key.nspace, KeyLifeCycle::Live])
1316 .context("Domain::KEY_ID: query failed.")?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001317 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001318 let r =
1319 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001320 Ok((
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001321 Domain(r.get(0).context("Failed to unpack domain.")?),
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001322 r.get(1).context("Failed to unpack namespace.")?,
1323 ))
1324 })
Janis Danisevskis45760022021-01-19 16:34:10 -08001325 .context("Domain::KEY_ID.")?
1326 };
1327
1328 // We may use a key by id after loading it by grant.
1329 // In this case we have to check if the caller has a grant for this particular
1330 // key. We can skip this if we already know that the caller is the owner.
1331 // But we cannot know this if domain is anything but App. E.g. in the case
1332 // of Domain::SELINUX we have to speculatively check for grants because we have to
1333 // consult the SEPolicy before we know if the caller is the owner.
1334 let access_vector: Option<KeyPermSet> =
1335 if domain != Domain::APP || namespace != caller_uid as i64 {
1336 let access_vector: Option<i32> = tx
1337 .query_row(
1338 "SELECT access_vector FROM persistent.grant
1339 WHERE grantee = ? AND keyentryid = ?;",
1340 params![caller_uid as i64, key.nspace],
1341 |row| row.get(0),
1342 )
1343 .optional()
1344 .context("Domain::KEY_ID: query grant failed.")?;
1345 access_vector.map(|p| p.into())
1346 } else {
1347 None
1348 };
1349
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001350 let key_id = key.nspace;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001351 let mut access_key = key;
1352 access_key.domain = domain;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001353 access_key.nspace = namespace;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001354
Janis Danisevskis45760022021-01-19 16:34:10 -08001355 Ok((key_id, access_key, access_vector))
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001356 }
1357 _ => Err(anyhow!(KsError::sys())),
1358 }
1359 }
1360
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001361 fn load_blob_components(
1362 key_id: i64,
1363 load_bits: KeyEntryLoadBits,
1364 tx: &Transaction,
Janis Danisevskis377d1002021-01-27 19:07:48 -08001365 ) -> Result<(bool, Option<Vec<u8>>, Option<Vec<u8>>, Option<Vec<u8>>)> {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001366 let mut stmt = tx
1367 .prepare(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001368 "SELECT MAX(id), subcomponent_type, blob FROM persistent.blobentry
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001369 WHERE keyentryid = ? GROUP BY subcomponent_type;",
1370 )
1371 .context("In load_blob_components: prepare statement failed.")?;
1372
1373 let mut rows =
1374 stmt.query(params![key_id]).context("In load_blob_components: query failed.")?;
1375
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001376 let mut km_blob: Option<Vec<u8>> = None;
1377 let mut cert_blob: Option<Vec<u8>> = None;
1378 let mut cert_chain_blob: Option<Vec<u8>> = None;
Janis Danisevskis377d1002021-01-27 19:07:48 -08001379 let mut has_km_blob: bool = false;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001380 db_utils::with_rows_extract_all(&mut rows, |row| {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001381 let sub_type: SubComponentType =
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001382 row.get(1).context("Failed to extract subcomponent_type.")?;
Janis Danisevskis377d1002021-01-27 19:07:48 -08001383 has_km_blob = has_km_blob || sub_type == SubComponentType::KEY_BLOB;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001384 match (sub_type, load_bits.load_public(), load_bits.load_km()) {
1385 (SubComponentType::KEY_BLOB, _, true) => {
1386 km_blob = Some(row.get(2).context("Failed to extract KM blob.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001387 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001388 (SubComponentType::CERT, true, _) => {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001389 cert_blob =
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001390 Some(row.get(2).context("Failed to extract public certificate blob.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001391 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001392 (SubComponentType::CERT_CHAIN, true, _) => {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001393 cert_chain_blob =
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001394 Some(row.get(2).context("Failed to extract certificate chain blob.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001395 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001396 (SubComponentType::CERT, _, _)
1397 | (SubComponentType::CERT_CHAIN, _, _)
1398 | (SubComponentType::KEY_BLOB, _, _) => {}
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001399 _ => Err(KsError::sys()).context("Unknown subcomponent type.")?,
1400 }
1401 Ok(())
1402 })
1403 .context("In load_blob_components.")?;
1404
Janis Danisevskis377d1002021-01-27 19:07:48 -08001405 Ok((has_km_blob, km_blob, cert_blob, cert_chain_blob))
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001406 }
1407
1408 fn load_key_parameters(key_id: i64, tx: &Transaction) -> Result<Vec<KeyParameter>> {
1409 let mut stmt = tx
1410 .prepare(
1411 "SELECT tag, data, security_level from persistent.keyparameter
1412 WHERE keyentryid = ?;",
1413 )
1414 .context("In load_key_parameters: prepare statement failed.")?;
1415
1416 let mut parameters: Vec<KeyParameter> = Vec::new();
1417
1418 let mut rows =
1419 stmt.query(params![key_id]).context("In load_key_parameters: query failed.")?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001420 db_utils::with_rows_extract_all(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001421 let tag = Tag(row.get(0).context("Failed to read tag.")?);
1422 let sec_level = SecurityLevel(row.get(2).context("Failed to read sec_level.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001423 parameters.push(
1424 KeyParameter::new_from_sql(tag, &SqlField::new(1, &row), sec_level)
1425 .context("Failed to read KeyParameter.")?,
1426 );
1427 Ok(())
1428 })
1429 .context("In load_key_parameters.")?;
1430
1431 Ok(parameters)
1432 }
1433
Qi Wub9433b52020-12-01 14:52:46 +08001434 /// Decrements the usage count of a limited use key. This function first checks whether the
1435 /// usage has been exhausted, if not, decreases the usage count. If the usage count reaches
1436 /// zero, the key also gets marked unreferenced and scheduled for deletion.
1437 /// Returns Ok(true) if the key was marked unreferenced as a hint to the garbage collector.
1438 pub fn check_and_update_key_usage_count(&mut self, key_id: i64) -> Result<bool> {
1439 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1440 let limit: Option<i32> = tx
1441 .query_row(
1442 "SELECT data FROM persistent.keyparameter WHERE keyentryid = ? AND tag = ?;",
1443 params![key_id, Tag::USAGE_COUNT_LIMIT.0],
1444 |row| row.get(0),
1445 )
1446 .optional()
1447 .context("Trying to load usage count")?;
1448
1449 let limit = limit
1450 .ok_or(KsError::Km(ErrorCode::INVALID_KEY_BLOB))
1451 .context("The Key no longer exists. Key is exhausted.")?;
1452
1453 tx.execute(
1454 "UPDATE persistent.keyparameter
1455 SET data = data - 1
1456 WHERE keyentryid = ? AND tag = ? AND data > 0;",
1457 params![key_id, Tag::USAGE_COUNT_LIMIT.0],
1458 )
1459 .context("Failed to update key usage count.")?;
1460
1461 match limit {
1462 1 => Self::mark_unreferenced(tx, key_id)
1463 .context("Trying to mark limited use key for deletion."),
1464 0 => Err(KsError::Km(ErrorCode::INVALID_KEY_BLOB)).context("Key is exhausted."),
1465 _ => Ok(false),
1466 }
1467 })
1468 .context("In check_and_update_key_usage_count.")
1469 }
1470
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001471 /// Load a key entry by the given key descriptor.
1472 /// It uses the `check_permission` callback to verify if the access is allowed
1473 /// given the key access tuple read from the database using `load_access_tuple`.
1474 /// With `load_bits` the caller may specify which blobs shall be loaded from
1475 /// the blob database.
1476 pub fn load_key_entry(
1477 &mut self,
1478 key: KeyDescriptor,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001479 key_type: KeyType,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001480 load_bits: KeyEntryLoadBits,
1481 caller_uid: u32,
1482 check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001483 ) -> Result<(KeyIdGuard, KeyEntry)> {
1484 // KEY ID LOCK 1/2
1485 // If we got a key descriptor with a key id we can get the lock right away.
1486 // Otherwise we have to defer it until we know the key id.
1487 let key_id_guard = match key.domain {
1488 Domain::KEY_ID => Some(KEY_ID_LOCK.get(key.nspace)),
1489 _ => None,
1490 };
1491
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001492 let tx = self
1493 .conn
Janis Danisevskisaec14592020-11-12 09:41:49 -08001494 .unchecked_transaction()
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001495 .context("In load_key_entry: Failed to initialize transaction.")?;
1496
1497 // Load the key_id and complete the access control tuple.
1498 let (key_id, access_key_descriptor, access_vector) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001499 Self::load_access_tuple(&tx, key, key_type, caller_uid)
1500 .context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001501
1502 // Perform access control. It is vital that we return here if the permission is denied.
1503 // So do not touch that '?' at the end.
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001504 check_permission(&access_key_descriptor, access_vector).context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001505
Janis Danisevskisaec14592020-11-12 09:41:49 -08001506 // KEY ID LOCK 2/2
1507 // If we did not get a key id lock by now, it was because we got a key descriptor
1508 // without a key id. At this point we got the key id, so we can try and get a lock.
1509 // However, we cannot block here, because we are in the middle of the transaction.
1510 // So first we try to get the lock non blocking. If that fails, we roll back the
1511 // transaction and block until we get the lock. After we successfully got the lock,
1512 // we start a new transaction and load the access tuple again.
1513 //
1514 // We don't need to perform access control again, because we already established
1515 // that the caller had access to the given key. But we need to make sure that the
1516 // key id still exists. So we have to load the key entry by key id this time.
1517 let (key_id_guard, tx) = match key_id_guard {
1518 None => match KEY_ID_LOCK.try_get(key_id) {
1519 None => {
1520 // Roll back the transaction.
1521 tx.rollback().context("In load_key_entry: Failed to roll back transaction.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001522
Janis Danisevskisaec14592020-11-12 09:41:49 -08001523 // Block until we have a key id lock.
1524 let key_id_guard = KEY_ID_LOCK.get(key_id);
1525
1526 // Create a new transaction.
1527 let tx = self.conn.unchecked_transaction().context(
1528 "In load_key_entry: Failed to initialize transaction. (deferred key lock)",
1529 )?;
1530
1531 Self::load_access_tuple(
1532 &tx,
1533 // This time we have to load the key by the retrieved key id, because the
1534 // alias may have been rebound after we rolled back the transaction.
1535 KeyDescriptor {
1536 domain: Domain::KEY_ID,
1537 nspace: key_id,
1538 ..Default::default()
1539 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001540 key_type,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001541 caller_uid,
1542 )
1543 .context("In load_key_entry. (deferred key lock)")?;
1544 (key_id_guard, tx)
1545 }
1546 Some(l) => (l, tx),
1547 },
1548 Some(key_id_guard) => (key_id_guard, tx),
1549 };
1550
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001551 let key_entry = Self::load_key_components(&tx, load_bits, key_id_guard.id())
1552 .context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001553
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001554 tx.commit().context("In load_key_entry: Failed to commit transaction.")?;
1555
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001556 Ok((key_id_guard, key_entry))
1557 }
1558
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08001559 fn mark_unreferenced(tx: &Transaction, key_id: i64) -> Result<bool> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001560 let updated = tx
1561 .execute(
1562 "UPDATE persistent.keyentry SET state = ? WHERE id = ?;",
1563 params![KeyLifeCycle::Unreferenced, key_id],
1564 )
1565 .context("In mark_unreferenced: Failed to update state of key entry.")?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001566 tx.execute("DELETE from persistent.grant WHERE keyentryid = ?;", params![key_id])
1567 .context("In mark_unreferenced: Failed to drop grants.")?;
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08001568 Ok(updated != 0)
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001569 }
1570
1571 /// Marks the given key as unreferenced and removes all of the grants to this key.
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08001572 /// Returns Ok(true) if a key was marked unreferenced as a hint for the garbage collector.
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001573 pub fn unbind_key(
1574 &mut self,
1575 key: KeyDescriptor,
1576 key_type: KeyType,
1577 caller_uid: u32,
1578 check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08001579 ) -> Result<bool> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001580 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1581 let (key_id, access_key_descriptor, access_vector) =
1582 Self::load_access_tuple(tx, key, key_type, caller_uid)
1583 .context("Trying to get access tuple.")?;
1584
1585 // Perform access control. It is vital that we return here if the permission is denied.
1586 // So do not touch that '?' at the end.
1587 check_permission(&access_key_descriptor, access_vector)
1588 .context("While checking permission.")?;
1589
1590 Self::mark_unreferenced(tx, key_id).context("Trying to mark the key unreferenced.")
1591 })
1592 .context("In unbind_key.")
1593 }
1594
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001595 fn load_key_components(
1596 tx: &Transaction,
1597 load_bits: KeyEntryLoadBits,
1598 key_id: i64,
1599 ) -> Result<KeyEntry> {
1600 let metadata = KeyMetaData::load_from_db(key_id, &tx).context("In load_key_components.")?;
1601
Janis Danisevskis377d1002021-01-27 19:07:48 -08001602 let (has_km_blob, km_blob, cert_blob, cert_chain_blob) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001603 Self::load_blob_components(key_id, load_bits, &tx)
1604 .context("In load_key_components.")?;
1605
1606 let parameters =
1607 Self::load_key_parameters(key_id, &tx).context("In load_key_components.")?;
1608
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001609 // Extract the security level by checking the security level of the origin tag.
1610 // Super keys don't have key parameters so we use security_level software by default.
1611 let sec_level = parameters
1612 .iter()
1613 .find_map(|k| match k.get_tag() {
1614 Tag::ORIGIN => Some(*k.security_level()),
1615 _ => None,
1616 })
1617 .unwrap_or(SecurityLevel::SOFTWARE);
1618
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001619 Ok(KeyEntry {
1620 id: key_id,
1621 km_blob,
1622 cert: cert_blob,
1623 cert_chain: cert_chain_blob,
1624 sec_level,
1625 parameters,
1626 metadata,
Janis Danisevskis377d1002021-01-27 19:07:48 -08001627 pure_cert: !has_km_blob,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001628 })
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001629 }
1630
Janis Danisevskise92a5e62020-12-02 12:57:41 -08001631 /// Returns a list of KeyDescriptors in the selected domain/namespace.
1632 /// The key descriptors will have the domain, nspace, and alias field set.
1633 /// Domain must be APP or SELINUX, the caller must make sure of that.
1634 pub fn list(&mut self, domain: Domain, namespace: i64) -> Result<Vec<KeyDescriptor>> {
1635 let mut stmt = self
1636 .conn
1637 .prepare(
1638 "SELECT alias FROM persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001639 WHERE domain = ? AND namespace = ? AND alias IS NOT NULL AND state = ?;",
Janis Danisevskise92a5e62020-12-02 12:57:41 -08001640 )
1641 .context("In list: Failed to prepare.")?;
1642
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001643 let mut rows = stmt
1644 .query(params![domain.0 as u32, namespace, KeyLifeCycle::Live])
1645 .context("In list: Failed to query.")?;
Janis Danisevskise92a5e62020-12-02 12:57:41 -08001646
1647 let mut descriptors: Vec<KeyDescriptor> = Vec::new();
1648 db_utils::with_rows_extract_all(&mut rows, |row| {
1649 descriptors.push(KeyDescriptor {
1650 domain,
1651 nspace: namespace,
1652 alias: Some(row.get(0).context("Trying to extract alias.")?),
1653 blob: None,
1654 });
1655 Ok(())
1656 })
1657 .context("In list.")?;
1658 Ok(descriptors)
1659 }
1660
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001661 /// Adds a grant to the grant table.
1662 /// Like `load_key_entry` this function loads the access tuple before
1663 /// it uses the callback for a permission check. Upon success,
1664 /// it inserts the `grantee_uid`, `key_id`, and `access_vector` into the
1665 /// grant table. The new row will have a randomized id, which is used as
1666 /// grant id in the namespace field of the resulting KeyDescriptor.
1667 pub fn grant(
1668 &mut self,
1669 key: KeyDescriptor,
1670 caller_uid: u32,
1671 grantee_uid: u32,
1672 access_vector: KeyPermSet,
1673 check_permission: impl FnOnce(&KeyDescriptor, &KeyPermSet) -> Result<()>,
1674 ) -> Result<KeyDescriptor> {
1675 let tx = self
1676 .conn
1677 .transaction_with_behavior(TransactionBehavior::Immediate)
1678 .context("In grant: Failed to initialize transaction.")?;
1679
1680 // Load the key_id and complete the access control tuple.
1681 // We ignore the access vector here because grants cannot be granted.
1682 // The access vector returned here expresses the permissions the
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001683 // grantee has if key.domain == Domain::GRANT. But this vector
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001684 // cannot include the grant permission by design, so there is no way the
1685 // subsequent permission check can pass.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001686 // We could check key.domain == Domain::GRANT and fail early.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001687 // But even if we load the access tuple by grant here, the permission
1688 // check denies the attempt to create a grant by grant descriptor.
1689 let (key_id, access_key_descriptor, _) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001690 Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid).context("In grant")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001691
1692 // Perform access control. It is vital that we return here if the permission
1693 // was denied. So do not touch that '?' at the end of the line.
1694 // This permission check checks if the caller has the grant permission
1695 // for the given key and in addition to all of the permissions
1696 // expressed in `access_vector`.
1697 check_permission(&access_key_descriptor, &access_vector)
1698 .context("In grant: check_permission failed.")?;
1699
1700 let grant_id = if let Some(grant_id) = tx
1701 .query_row(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001702 "SELECT id FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001703 WHERE keyentryid = ? AND grantee = ?;",
1704 params![key_id, grantee_uid],
1705 |row| row.get(0),
1706 )
1707 .optional()
1708 .context("In grant: Failed get optional existing grant id.")?
1709 {
1710 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001711 "UPDATE persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001712 SET access_vector = ?
1713 WHERE id = ?;",
1714 params![i32::from(access_vector), grant_id],
1715 )
1716 .context("In grant: Failed to update existing grant.")?;
1717 grant_id
1718 } else {
Joel Galenson845f74b2020-09-09 14:11:55 -07001719 Self::insert_with_retry(|id| {
1720 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001721 "INSERT INTO persistent.grant (id, grantee, keyentryid, access_vector)
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001722 VALUES (?, ?, ?, ?);",
Joel Galenson845f74b2020-09-09 14:11:55 -07001723 params![id, grantee_uid, key_id, i32::from(access_vector)],
1724 )
1725 })
1726 .context("In grant")?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001727 };
1728 tx.commit().context("In grant: failed to commit transaction.")?;
1729
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001730 Ok(KeyDescriptor { domain: Domain::GRANT, nspace: grant_id, alias: None, blob: None })
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001731 }
1732
1733 /// This function checks permissions like `grant` and `load_key_entry`
1734 /// before removing a grant from the grant table.
1735 pub fn ungrant(
1736 &mut self,
1737 key: KeyDescriptor,
1738 caller_uid: u32,
1739 grantee_uid: u32,
1740 check_permission: impl FnOnce(&KeyDescriptor) -> Result<()>,
1741 ) -> Result<()> {
1742 let tx = self
1743 .conn
1744 .transaction_with_behavior(TransactionBehavior::Immediate)
1745 .context("In ungrant: Failed to initialize transaction.")?;
1746
1747 // Load the key_id and complete the access control tuple.
1748 // We ignore the access vector here because grants cannot be granted.
1749 let (key_id, access_key_descriptor, _) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001750 Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid)
1751 .context("In ungrant.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001752
1753 // Perform access control. We must return here if the permission
1754 // was denied. So do not touch the '?' at the end of this line.
1755 check_permission(&access_key_descriptor).context("In grant: check_permission failed.")?;
1756
1757 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001758 "DELETE FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001759 WHERE keyentryid = ? AND grantee = ?;",
1760 params![key_id, grantee_uid],
1761 )
1762 .context("Failed to delete grant.")?;
1763
1764 tx.commit().context("In ungrant: failed to commit transaction.")?;
1765
1766 Ok(())
1767 }
1768
Joel Galenson845f74b2020-09-09 14:11:55 -07001769 // Generates a random id and passes it to the given function, which will
1770 // try to insert it into a database. If that insertion fails, retry;
1771 // otherwise return the id.
1772 fn insert_with_retry(inserter: impl Fn(i64) -> rusqlite::Result<usize>) -> Result<i64> {
1773 loop {
1774 let newid: i64 = random();
1775 match inserter(newid) {
1776 // If the id already existed, try again.
1777 Err(rusqlite::Error::SqliteFailure(
1778 libsqlite3_sys::Error {
1779 code: libsqlite3_sys::ErrorCode::ConstraintViolation,
1780 extended_code: libsqlite3_sys::SQLITE_CONSTRAINT_UNIQUE,
1781 },
1782 _,
1783 )) => (),
1784 Err(e) => {
1785 return Err(e).context("In insert_with_retry: failed to insert into database.")
1786 }
1787 _ => return Ok(newid),
1788 }
1789 }
1790 }
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001791
1792 /// Insert or replace the auth token based on the UNIQUE constraint of the auth token table
1793 pub fn insert_auth_token(&mut self, auth_token: &HardwareAuthToken) -> Result<()> {
1794 self.conn
1795 .execute(
1796 "INSERT OR REPLACE INTO perboot.authtoken (challenge, user_id, auth_id,
1797 authenticator_type, timestamp, mac, time_received) VALUES(?, ?, ?, ?, ?, ?, ?);",
1798 params![
1799 auth_token.challenge,
1800 auth_token.userId,
1801 auth_token.authenticatorId,
1802 auth_token.authenticatorType.0 as i32,
1803 auth_token.timestamp.milliSeconds as i64,
1804 auth_token.mac,
1805 MonotonicRawTime::now(),
1806 ],
1807 )
1808 .context("In insert_auth_token: failed to insert auth token into the database")?;
1809 Ok(())
1810 }
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001811
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001812 /// Find the newest auth token matching the given predicate.
1813 pub fn find_auth_token_entry<F>(
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001814 &mut self,
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001815 p: F,
1816 ) -> Result<Option<(AuthTokenEntry, MonotonicRawTime)>>
1817 where
1818 F: Fn(&AuthTokenEntry) -> bool,
1819 {
1820 self.with_transaction(TransactionBehavior::Deferred, |tx| {
1821 let mut stmt = tx
1822 .prepare("SELECT * from perboot.authtoken ORDER BY time_received DESC;")
1823 .context("Prepare statement failed.")?;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001824
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001825 let mut rows = stmt.query(NO_PARAMS).context("Failed to query.")?;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001826
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001827 while let Some(row) = rows.next().context("Failed to get next row.")? {
1828 let entry = AuthTokenEntry::new(
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001829 HardwareAuthToken {
1830 challenge: row.get(1)?,
1831 userId: row.get(2)?,
1832 authenticatorId: row.get(3)?,
1833 authenticatorType: HardwareAuthenticatorType(row.get(4)?),
1834 timestamp: Timestamp { milliSeconds: row.get(5)? },
1835 mac: row.get(6)?,
1836 },
1837 row.get(7)?,
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001838 );
1839 if p(&entry) {
1840 return Ok(Some((
1841 entry,
1842 Self::get_last_off_body(tx)
1843 .context("In find_auth_token_entry: Trying to get last off body")?,
1844 )));
1845 }
1846 }
1847 Ok(None)
1848 })
1849 .context("In find_auth_token_entry.")
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001850 }
1851
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001852 /// Insert last_off_body into the metadata table at the initialization of auth token table
1853 pub fn insert_last_off_body(&self, last_off_body: MonotonicRawTime) -> Result<()> {
1854 self.conn
1855 .execute(
1856 "INSERT OR REPLACE INTO perboot.metadata (key, value) VALUES (?, ?);",
1857 params!["last_off_body", last_off_body],
1858 )
1859 .context("In insert_last_off_body: failed to insert.")?;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001860 Ok(())
1861 }
1862
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001863 /// Update last_off_body when on_device_off_body is called
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001864 pub fn update_last_off_body(&self, last_off_body: MonotonicRawTime) -> Result<()> {
1865 self.conn
1866 .execute(
1867 "UPDATE perboot.metadata SET value = ? WHERE key = ?;",
1868 params![last_off_body, "last_off_body"],
1869 )
1870 .context("In update_last_off_body: failed to update.")?;
1871 Ok(())
1872 }
1873
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001874 /// Get last_off_body time when finding auth tokens
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001875 fn get_last_off_body(tx: &Transaction) -> Result<MonotonicRawTime> {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001876 tx.query_row(
1877 "SELECT value from perboot.metadata WHERE key = ?;",
1878 params!["last_off_body"],
1879 |row| Ok(row.get(0)?),
1880 )
1881 .context("In get_last_off_body: query_row failed.")
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001882 }
Joel Galenson26f4d012020-07-17 14:57:21 -07001883}
1884
1885#[cfg(test)]
1886mod tests {
1887
1888 use super::*;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001889 use crate::key_parameter::{
1890 Algorithm, BlockMode, Digest, EcCurve, HardwareAuthenticatorType, KeyOrigin, KeyParameter,
1891 KeyParameterValue, KeyPurpose, PaddingMode, SecurityLevel,
1892 };
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001893 use crate::key_perm_set;
1894 use crate::permission::{KeyPerm, KeyPermSet};
Janis Danisevskis2a8330a2021-01-20 15:34:26 -08001895 use keystore2_test_utils::TempDir;
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001896 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
1897 HardwareAuthToken::HardwareAuthToken,
1898 HardwareAuthenticatorType::HardwareAuthenticatorType as kmhw_authenticator_type,
Janis Danisevskisc3a496b2021-01-05 10:37:22 -08001899 };
1900 use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001901 Timestamp::Timestamp,
1902 };
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001903 use rusqlite::NO_PARAMS;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001904 use rusqlite::{Error, TransactionBehavior};
Joel Galenson0891bc12020-07-20 10:37:03 -07001905 use std::cell::RefCell;
Janis Danisevskisaec14592020-11-12 09:41:49 -08001906 use std::sync::atomic::{AtomicU8, Ordering};
1907 use std::sync::Arc;
1908 use std::thread;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001909 use std::time::{Duration, SystemTime};
Joel Galenson0891bc12020-07-20 10:37:03 -07001910
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001911 fn new_test_db() -> Result<KeystoreDB> {
1912 let conn = KeystoreDB::make_connection("file::memory:", "file::memory:")?;
1913
1914 KeystoreDB::init_tables(&conn).context("Failed to initialize tables.")?;
1915 Ok(KeystoreDB { conn })
1916 }
1917
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08001918 fn rebind_alias(
1919 db: &mut KeystoreDB,
1920 newid: &KeyIdGuard,
1921 alias: &str,
1922 domain: Domain,
1923 namespace: i64,
1924 ) -> Result<bool> {
1925 db.with_transaction(TransactionBehavior::Immediate, |tx| {
1926 KeystoreDB::rebind_alias(tx, newid, alias, domain, namespace)
1927 })
1928 .context("In rebind_alias.")
1929 }
1930
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001931 #[test]
1932 fn datetime() -> Result<()> {
1933 let conn = Connection::open_in_memory()?;
1934 conn.execute("CREATE TABLE test (ts DATETIME);", NO_PARAMS)?;
1935 let now = SystemTime::now();
1936 let duration = Duration::from_secs(1000);
1937 let then = now.checked_sub(duration).unwrap();
1938 let soon = now.checked_add(duration).unwrap();
1939 conn.execute(
1940 "INSERT INTO test (ts) VALUES (?), (?), (?);",
1941 params![DateTime::try_from(now)?, DateTime::try_from(then)?, DateTime::try_from(soon)?],
1942 )?;
1943 let mut stmt = conn.prepare("SELECT ts FROM test ORDER BY ts ASC;")?;
1944 let mut rows = stmt.query(NO_PARAMS)?;
1945 assert_eq!(DateTime::try_from(then)?, rows.next()?.unwrap().get(0)?);
1946 assert_eq!(DateTime::try_from(now)?, rows.next()?.unwrap().get(0)?);
1947 assert_eq!(DateTime::try_from(soon)?, rows.next()?.unwrap().get(0)?);
1948 assert!(rows.next()?.is_none());
1949 assert!(DateTime::try_from(then)? < DateTime::try_from(now)?);
1950 assert!(DateTime::try_from(then)? < DateTime::try_from(soon)?);
1951 assert!(DateTime::try_from(now)? < DateTime::try_from(soon)?);
1952 Ok(())
1953 }
1954
Joel Galenson0891bc12020-07-20 10:37:03 -07001955 // Ensure that we're using the "injected" random function, not the real one.
1956 #[test]
1957 fn test_mocked_random() {
1958 let rand1 = random();
1959 let rand2 = random();
1960 let rand3 = random();
1961 if rand1 == rand2 {
1962 assert_eq!(rand2 + 1, rand3);
1963 } else {
1964 assert_eq!(rand1 + 1, rand2);
1965 assert_eq!(rand2, rand3);
1966 }
1967 }
Joel Galenson26f4d012020-07-17 14:57:21 -07001968
Joel Galenson26f4d012020-07-17 14:57:21 -07001969 // Test that we have the correct tables.
1970 #[test]
1971 fn test_tables() -> Result<()> {
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001972 let db = new_test_db()?;
Joel Galenson26f4d012020-07-17 14:57:21 -07001973 let tables = db
1974 .conn
Joel Galenson2aab4432020-07-22 15:27:57 -07001975 .prepare("SELECT name from persistent.sqlite_master WHERE type='table' ORDER BY name;")?
Joel Galenson26f4d012020-07-17 14:57:21 -07001976 .query_map(params![], |row| row.get(0))?
1977 .collect::<rusqlite::Result<Vec<String>>>()?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001978 assert_eq!(tables.len(), 5);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001979 assert_eq!(tables[0], "blobentry");
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001980 assert_eq!(tables[1], "grant");
1981 assert_eq!(tables[2], "keyentry");
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001982 assert_eq!(tables[3], "keymetadata");
1983 assert_eq!(tables[4], "keyparameter");
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001984 let tables = db
1985 .conn
1986 .prepare("SELECT name from perboot.sqlite_master WHERE type='table' ORDER BY name;")?
1987 .query_map(params![], |row| row.get(0))?
1988 .collect::<rusqlite::Result<Vec<String>>>()?;
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001989
1990 assert_eq!(tables.len(), 2);
1991 assert_eq!(tables[0], "authtoken");
1992 assert_eq!(tables[1], "metadata");
Joel Galenson2aab4432020-07-22 15:27:57 -07001993 Ok(())
1994 }
1995
1996 #[test]
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001997 fn test_auth_token_table_invariant() -> Result<()> {
1998 let mut db = new_test_db()?;
1999 let auth_token1 = HardwareAuthToken {
2000 challenge: i64::MAX,
2001 userId: 200,
2002 authenticatorId: 200,
2003 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
2004 timestamp: Timestamp { milliSeconds: 500 },
2005 mac: String::from("mac").into_bytes(),
2006 };
2007 db.insert_auth_token(&auth_token1)?;
2008 let auth_tokens_returned = get_auth_tokens(&mut db)?;
2009 assert_eq!(auth_tokens_returned.len(), 1);
2010
2011 // insert another auth token with the same values for the columns in the UNIQUE constraint
2012 // of the auth token table and different value for timestamp
2013 let auth_token2 = HardwareAuthToken {
2014 challenge: i64::MAX,
2015 userId: 200,
2016 authenticatorId: 200,
2017 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
2018 timestamp: Timestamp { milliSeconds: 600 },
2019 mac: String::from("mac").into_bytes(),
2020 };
2021
2022 db.insert_auth_token(&auth_token2)?;
2023 let mut auth_tokens_returned = get_auth_tokens(&mut db)?;
2024 assert_eq!(auth_tokens_returned.len(), 1);
2025
2026 if let Some(auth_token) = auth_tokens_returned.pop() {
2027 assert_eq!(auth_token.auth_token.timestamp.milliSeconds, 600);
2028 }
2029
2030 // insert another auth token with the different values for the columns in the UNIQUE
2031 // constraint of the auth token table
2032 let auth_token3 = HardwareAuthToken {
2033 challenge: i64::MAX,
2034 userId: 201,
2035 authenticatorId: 200,
2036 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
2037 timestamp: Timestamp { milliSeconds: 600 },
2038 mac: String::from("mac").into_bytes(),
2039 };
2040
2041 db.insert_auth_token(&auth_token3)?;
2042 let auth_tokens_returned = get_auth_tokens(&mut db)?;
2043 assert_eq!(auth_tokens_returned.len(), 2);
2044
2045 Ok(())
2046 }
2047
2048 // utility function for test_auth_token_table_invariant()
2049 fn get_auth_tokens(db: &mut KeystoreDB) -> Result<Vec<AuthTokenEntry>> {
2050 let mut stmt = db.conn.prepare("SELECT * from perboot.authtoken;")?;
2051
2052 let auth_token_entries: Vec<AuthTokenEntry> = stmt
2053 .query_map(NO_PARAMS, |row| {
2054 Ok(AuthTokenEntry::new(
2055 HardwareAuthToken {
2056 challenge: row.get(1)?,
2057 userId: row.get(2)?,
2058 authenticatorId: row.get(3)?,
2059 authenticatorType: HardwareAuthenticatorType(row.get(4)?),
2060 timestamp: Timestamp { milliSeconds: row.get(5)? },
2061 mac: row.get(6)?,
2062 },
2063 row.get(7)?,
2064 ))
2065 })?
2066 .collect::<Result<Vec<AuthTokenEntry>, Error>>()?;
2067 Ok(auth_token_entries)
2068 }
2069
2070 #[test]
Joel Galenson2aab4432020-07-22 15:27:57 -07002071 fn test_persistence_for_files() -> Result<()> {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002072 let temp_dir = TempDir::new("persistent_db_test")?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002073 let mut db = KeystoreDB::new(temp_dir.path())?;
Joel Galenson2aab4432020-07-22 15:27:57 -07002074
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002075 db.create_key_entry(Domain::APP, 100)?;
Joel Galenson2aab4432020-07-22 15:27:57 -07002076 let entries = get_keyentry(&db)?;
2077 assert_eq!(entries.len(), 1);
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002078
2079 let db = KeystoreDB::new(temp_dir.path())?;
Joel Galenson2aab4432020-07-22 15:27:57 -07002080
2081 let entries_new = get_keyentry(&db)?;
2082 assert_eq!(entries, entries_new);
2083 Ok(())
2084 }
2085
2086 #[test]
Joel Galenson0891bc12020-07-20 10:37:03 -07002087 fn test_create_key_entry() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002088 fn extractor(ke: &KeyEntryRow) -> (Domain, i64, Option<&str>) {
Joel Galenson0891bc12020-07-20 10:37:03 -07002089 (ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref())
2090 }
2091
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002092 let mut db = new_test_db()?;
Joel Galenson0891bc12020-07-20 10:37:03 -07002093
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002094 db.create_key_entry(Domain::APP, 100)?;
2095 db.create_key_entry(Domain::SELINUX, 101)?;
Joel Galenson0891bc12020-07-20 10:37:03 -07002096
2097 let entries = get_keyentry(&db)?;
2098 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002099 assert_eq!(extractor(&entries[0]), (Domain::APP, 100, None));
2100 assert_eq!(extractor(&entries[1]), (Domain::SELINUX, 101, None));
Joel Galenson0891bc12020-07-20 10:37:03 -07002101
2102 // Test that we must pass in a valid Domain.
2103 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002104 db.create_key_entry(Domain::GRANT, 102),
2105 "Domain Domain(1) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07002106 );
2107 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002108 db.create_key_entry(Domain::BLOB, 103),
2109 "Domain Domain(3) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07002110 );
2111 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002112 db.create_key_entry(Domain::KEY_ID, 104),
2113 "Domain Domain(4) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07002114 );
2115
2116 Ok(())
2117 }
2118
Joel Galenson33c04ad2020-08-03 11:04:38 -07002119 #[test]
2120 fn test_rebind_alias() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002121 fn extractor(ke: &KeyEntryRow) -> (Option<Domain>, Option<i64>, Option<&str>) {
Joel Galenson33c04ad2020-08-03 11:04:38 -07002122 (ke.domain, ke.namespace, ke.alias.as_deref())
2123 }
2124
Janis Danisevskis4df44f42020-08-26 14:40:03 -07002125 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002126 db.create_key_entry(Domain::APP, 42)?;
2127 db.create_key_entry(Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07002128 let entries = get_keyentry(&db)?;
2129 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002130 assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), None));
2131 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
Joel Galenson33c04ad2020-08-03 11:04:38 -07002132
2133 // Test that the first call to rebind_alias sets the alias.
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08002134 rebind_alias(&mut db, &KEY_ID_LOCK.get(entries[0].id), "foo", Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07002135 let entries = get_keyentry(&db)?;
2136 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002137 assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), Some("foo")));
2138 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
Joel Galenson33c04ad2020-08-03 11:04:38 -07002139
2140 // Test that the second call to rebind_alias also empties the old one.
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08002141 rebind_alias(&mut db, &KEY_ID_LOCK.get(entries[1].id), "foo", Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07002142 let entries = get_keyentry(&db)?;
2143 assert_eq!(entries.len(), 2);
Joel Galenson7fa5c412020-11-19 10:56:54 -08002144 assert_eq!(extractor(&entries[0]), (None, None, None));
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002145 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
Joel Galenson33c04ad2020-08-03 11:04:38 -07002146
2147 // Test that we must pass in a valid Domain.
2148 check_result_is_error_containing_string(
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08002149 rebind_alias(&mut db, &KEY_ID_LOCK.get(0), "foo", Domain::GRANT, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002150 "Domain Domain(1) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07002151 );
2152 check_result_is_error_containing_string(
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08002153 rebind_alias(&mut db, &KEY_ID_LOCK.get(0), "foo", Domain::BLOB, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002154 "Domain Domain(3) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07002155 );
2156 check_result_is_error_containing_string(
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08002157 rebind_alias(&mut db, &KEY_ID_LOCK.get(0), "foo", Domain::KEY_ID, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002158 "Domain Domain(4) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07002159 );
2160
2161 // Test that we correctly handle setting an alias for something that does not exist.
2162 check_result_is_error_containing_string(
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08002163 rebind_alias(&mut db, &KEY_ID_LOCK.get(0), "foo", Domain::SELINUX, 42),
Joel Galenson33c04ad2020-08-03 11:04:38 -07002164 "Expected to update a single entry but instead updated 0",
2165 );
2166 // Test that we correctly abort the transaction in this case.
2167 let entries = get_keyentry(&db)?;
2168 assert_eq!(entries.len(), 2);
Joel Galenson7fa5c412020-11-19 10:56:54 -08002169 assert_eq!(extractor(&entries[0]), (None, None, None));
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002170 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
Joel Galenson33c04ad2020-08-03 11:04:38 -07002171
2172 Ok(())
2173 }
2174
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002175 #[test]
2176 fn test_grant_ungrant() -> Result<()> {
2177 const CALLER_UID: u32 = 15;
2178 const GRANTEE_UID: u32 = 12;
2179 const SELINUX_NAMESPACE: i64 = 7;
2180
2181 let mut db = new_test_db()?;
2182 db.conn.execute(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002183 "INSERT INTO persistent.keyentry (id, key_type, domain, namespace, alias, state)
2184 VALUES (1, 0, 0, 15, 'key', 1), (2, 0, 2, 7, 'yek', 1);",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002185 NO_PARAMS,
2186 )?;
2187 let app_key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002188 domain: super::Domain::APP,
2189 nspace: 0,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002190 alias: Some("key".to_string()),
2191 blob: None,
2192 };
2193 const PVEC1: KeyPermSet = key_perm_set![KeyPerm::use_(), KeyPerm::get_info()];
2194 const PVEC2: KeyPermSet = key_perm_set![KeyPerm::use_()];
2195
2196 // Reset totally predictable random number generator in case we
2197 // are not the first test running on this thread.
2198 reset_random();
2199 let next_random = 0i64;
2200
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002201 let app_granted_key = db
2202 .grant(app_key.clone(), CALLER_UID, GRANTEE_UID, PVEC1, |k, a| {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002203 assert_eq!(*a, PVEC1);
2204 assert_eq!(
2205 *k,
2206 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002207 domain: super::Domain::APP,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002208 // namespace must be set to the caller_uid.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002209 nspace: CALLER_UID as i64,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002210 alias: Some("key".to_string()),
2211 blob: None,
2212 }
2213 );
2214 Ok(())
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002215 })
2216 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002217
2218 assert_eq!(
2219 app_granted_key,
2220 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002221 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002222 // The grantid is next_random due to the mock random number generator.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002223 nspace: next_random,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002224 alias: None,
2225 blob: None,
2226 }
2227 );
2228
2229 let selinux_key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002230 domain: super::Domain::SELINUX,
2231 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002232 alias: Some("yek".to_string()),
2233 blob: None,
2234 };
2235
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002236 let selinux_granted_key = db
2237 .grant(selinux_key.clone(), CALLER_UID, 12, PVEC1, |k, a| {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002238 assert_eq!(*a, PVEC1);
2239 assert_eq!(
2240 *k,
2241 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002242 domain: super::Domain::SELINUX,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002243 // namespace must be the supplied SELinux
2244 // namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002245 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002246 alias: Some("yek".to_string()),
2247 blob: None,
2248 }
2249 );
2250 Ok(())
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002251 })
2252 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002253
2254 assert_eq!(
2255 selinux_granted_key,
2256 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002257 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002258 // The grantid is next_random + 1 due to the mock random number generator.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002259 nspace: next_random + 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002260 alias: None,
2261 blob: None,
2262 }
2263 );
2264
2265 // This should update the existing grant with PVEC2.
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002266 let selinux_granted_key = db
2267 .grant(selinux_key.clone(), CALLER_UID, 12, PVEC2, |k, a| {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002268 assert_eq!(*a, PVEC2);
2269 assert_eq!(
2270 *k,
2271 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002272 domain: super::Domain::SELINUX,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002273 // namespace must be the supplied SELinux
2274 // namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002275 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002276 alias: Some("yek".to_string()),
2277 blob: None,
2278 }
2279 );
2280 Ok(())
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002281 })
2282 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002283
2284 assert_eq!(
2285 selinux_granted_key,
2286 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002287 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002288 // Same grant id as before. The entry was only updated.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002289 nspace: next_random + 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002290 alias: None,
2291 blob: None,
2292 }
2293 );
2294
2295 {
2296 // Limiting scope of stmt, because it borrows db.
2297 let mut stmt = db
2298 .conn
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002299 .prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?;
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07002300 let mut rows =
2301 stmt.query_map::<(i64, u32, i64, KeyPermSet), _, _>(NO_PARAMS, |row| {
2302 Ok((
2303 row.get(0)?,
2304 row.get(1)?,
2305 row.get(2)?,
2306 KeyPermSet::from(row.get::<_, i32>(3)?),
2307 ))
2308 })?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002309
2310 let r = rows.next().unwrap().unwrap();
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07002311 assert_eq!(r, (next_random, GRANTEE_UID, 1, PVEC1));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002312 let r = rows.next().unwrap().unwrap();
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07002313 assert_eq!(r, (next_random + 1, GRANTEE_UID, 2, PVEC2));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002314 assert!(rows.next().is_none());
2315 }
2316
2317 debug_dump_keyentry_table(&mut db)?;
2318 println!("app_key {:?}", app_key);
2319 println!("selinux_key {:?}", selinux_key);
2320
2321 db.ungrant(app_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
2322 db.ungrant(selinux_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
2323
2324 Ok(())
2325 }
2326
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002327 static TEST_KEY_BLOB: &[u8] = b"my test blob";
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002328 static TEST_CERT_BLOB: &[u8] = b"my test cert";
2329 static TEST_CERT_CHAIN_BLOB: &[u8] = b"my test cert_chain";
2330
2331 #[test]
Janis Danisevskis377d1002021-01-27 19:07:48 -08002332 fn test_set_blob() -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002333 let key_id = KEY_ID_LOCK.get(3000);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002334 let mut db = new_test_db()?;
Janis Danisevskis377d1002021-01-27 19:07:48 -08002335 db.set_blob(&key_id, SubComponentType::KEY_BLOB, Some(TEST_KEY_BLOB))?;
2336 db.set_blob(&key_id, SubComponentType::CERT, Some(TEST_CERT_BLOB))?;
2337 db.set_blob(&key_id, SubComponentType::CERT_CHAIN, Some(TEST_CERT_CHAIN_BLOB))?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002338 drop(key_id);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002339
2340 let mut stmt = db.conn.prepare(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002341 "SELECT subcomponent_type, keyentryid, blob FROM persistent.blobentry
2342 ORDER BY subcomponent_type ASC;",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002343 )?;
2344 let mut rows = stmt
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002345 .query_map::<(SubComponentType, i64, Vec<u8>), _, _>(NO_PARAMS, |row| {
2346 Ok((row.get(0)?, row.get(1)?, row.get(2)?))
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002347 })?;
2348 let r = rows.next().unwrap().unwrap();
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002349 assert_eq!(r, (SubComponentType::KEY_BLOB, 3000, TEST_KEY_BLOB.to_vec()));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002350 let r = rows.next().unwrap().unwrap();
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002351 assert_eq!(r, (SubComponentType::CERT, 3000, TEST_CERT_BLOB.to_vec()));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002352 let r = rows.next().unwrap().unwrap();
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002353 assert_eq!(r, (SubComponentType::CERT_CHAIN, 3000, TEST_CERT_CHAIN_BLOB.to_vec()));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002354
2355 Ok(())
2356 }
2357
2358 static TEST_ALIAS: &str = "my super duper key";
2359
2360 #[test]
2361 fn test_insert_and_load_full_keyentry_domain_app() -> Result<()> {
2362 let mut db = new_test_db()?;
Qi Wub9433b52020-12-01 14:52:46 +08002363 let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS, None)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002364 .context("test_insert_and_load_full_keyentry_domain_app")?
2365 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002366 let (_key_guard, key_entry) = db
2367 .load_key_entry(
2368 KeyDescriptor {
2369 domain: Domain::APP,
2370 nspace: 0,
2371 alias: Some(TEST_ALIAS.to_string()),
2372 blob: None,
2373 },
2374 KeyType::Client,
2375 KeyEntryLoadBits::BOTH,
2376 1,
2377 |_k, _av| Ok(()),
2378 )
2379 .unwrap();
Qi Wub9433b52020-12-01 14:52:46 +08002380 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002381
2382 db.unbind_key(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002383 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002384 domain: Domain::APP,
2385 nspace: 0,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002386 alias: Some(TEST_ALIAS.to_string()),
2387 blob: None,
2388 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002389 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002390 1,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002391 |_, _| Ok(()),
2392 )
2393 .unwrap();
2394
2395 assert_eq!(
2396 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2397 db.load_key_entry(
2398 KeyDescriptor {
2399 domain: Domain::APP,
2400 nspace: 0,
2401 alias: Some(TEST_ALIAS.to_string()),
2402 blob: None,
2403 },
2404 KeyType::Client,
2405 KeyEntryLoadBits::NONE,
2406 1,
2407 |_k, _av| Ok(()),
2408 )
2409 .unwrap_err()
2410 .root_cause()
2411 .downcast_ref::<KsError>()
2412 );
2413
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002414 Ok(())
2415 }
2416
2417 #[test]
Janis Danisevskis377d1002021-01-27 19:07:48 -08002418 fn test_insert_and_load_certificate_entry_domain_app() -> Result<()> {
2419 let mut db = new_test_db()?;
2420
2421 db.store_new_certificate(
2422 KeyDescriptor {
2423 domain: Domain::APP,
2424 nspace: 1,
2425 alias: Some(TEST_ALIAS.to_string()),
2426 blob: None,
2427 },
2428 TEST_CERT_BLOB,
2429 )
2430 .expect("Trying to insert cert.");
2431
2432 let (_key_guard, mut key_entry) = db
2433 .load_key_entry(
2434 KeyDescriptor {
2435 domain: Domain::APP,
2436 nspace: 1,
2437 alias: Some(TEST_ALIAS.to_string()),
2438 blob: None,
2439 },
2440 KeyType::Client,
2441 KeyEntryLoadBits::PUBLIC,
2442 1,
2443 |_k, _av| Ok(()),
2444 )
2445 .expect("Trying to read certificate entry.");
2446
2447 assert!(key_entry.pure_cert());
2448 assert!(key_entry.cert().is_none());
2449 assert_eq!(key_entry.take_cert_chain(), Some(TEST_CERT_BLOB.to_vec()));
2450
2451 db.unbind_key(
2452 KeyDescriptor {
2453 domain: Domain::APP,
2454 nspace: 1,
2455 alias: Some(TEST_ALIAS.to_string()),
2456 blob: None,
2457 },
2458 KeyType::Client,
2459 1,
2460 |_, _| Ok(()),
2461 )
2462 .unwrap();
2463
2464 assert_eq!(
2465 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2466 db.load_key_entry(
2467 KeyDescriptor {
2468 domain: Domain::APP,
2469 nspace: 1,
2470 alias: Some(TEST_ALIAS.to_string()),
2471 blob: None,
2472 },
2473 KeyType::Client,
2474 KeyEntryLoadBits::NONE,
2475 1,
2476 |_k, _av| Ok(()),
2477 )
2478 .unwrap_err()
2479 .root_cause()
2480 .downcast_ref::<KsError>()
2481 );
2482
2483 Ok(())
2484 }
2485
2486 #[test]
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002487 fn test_insert_and_load_full_keyentry_domain_selinux() -> Result<()> {
2488 let mut db = new_test_db()?;
Qi Wub9433b52020-12-01 14:52:46 +08002489 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS, None)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002490 .context("test_insert_and_load_full_keyentry_domain_selinux")?
2491 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002492 let (_key_guard, key_entry) = db
2493 .load_key_entry(
2494 KeyDescriptor {
2495 domain: Domain::SELINUX,
2496 nspace: 1,
2497 alias: Some(TEST_ALIAS.to_string()),
2498 blob: None,
2499 },
2500 KeyType::Client,
2501 KeyEntryLoadBits::BOTH,
2502 1,
2503 |_k, _av| Ok(()),
2504 )
2505 .unwrap();
Qi Wub9433b52020-12-01 14:52:46 +08002506 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002507
2508 db.unbind_key(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002509 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002510 domain: Domain::SELINUX,
2511 nspace: 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002512 alias: Some(TEST_ALIAS.to_string()),
2513 blob: None,
2514 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002515 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002516 1,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002517 |_, _| Ok(()),
2518 )
2519 .unwrap();
2520
2521 assert_eq!(
2522 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2523 db.load_key_entry(
2524 KeyDescriptor {
2525 domain: Domain::SELINUX,
2526 nspace: 1,
2527 alias: Some(TEST_ALIAS.to_string()),
2528 blob: None,
2529 },
2530 KeyType::Client,
2531 KeyEntryLoadBits::NONE,
2532 1,
2533 |_k, _av| Ok(()),
2534 )
2535 .unwrap_err()
2536 .root_cause()
2537 .downcast_ref::<KsError>()
2538 );
2539
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002540 Ok(())
2541 }
2542
2543 #[test]
2544 fn test_insert_and_load_full_keyentry_domain_key_id() -> Result<()> {
2545 let mut db = new_test_db()?;
Qi Wub9433b52020-12-01 14:52:46 +08002546 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS, None)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002547 .context("test_insert_and_load_full_keyentry_domain_key_id")?
2548 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002549 let (_, key_entry) = db
2550 .load_key_entry(
2551 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
2552 KeyType::Client,
2553 KeyEntryLoadBits::BOTH,
2554 1,
2555 |_k, _av| Ok(()),
2556 )
2557 .unwrap();
2558
Qi Wub9433b52020-12-01 14:52:46 +08002559 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002560
2561 db.unbind_key(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002562 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002563 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002564 1,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002565 |_, _| Ok(()),
2566 )
2567 .unwrap();
2568
2569 assert_eq!(
2570 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2571 db.load_key_entry(
2572 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
2573 KeyType::Client,
2574 KeyEntryLoadBits::NONE,
2575 1,
2576 |_k, _av| Ok(()),
2577 )
2578 .unwrap_err()
2579 .root_cause()
2580 .downcast_ref::<KsError>()
2581 );
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002582
2583 Ok(())
2584 }
2585
2586 #[test]
Qi Wub9433b52020-12-01 14:52:46 +08002587 fn test_check_and_update_key_usage_count_with_limited_use_key() -> Result<()> {
2588 let mut db = new_test_db()?;
2589 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS, Some(123))
2590 .context("test_check_and_update_key_usage_count_with_limited_use_key")?
2591 .0;
2592 // Update the usage count of the limited use key.
2593 db.check_and_update_key_usage_count(key_id)?;
2594
2595 let (_key_guard, key_entry) = db.load_key_entry(
2596 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
2597 KeyType::Client,
2598 KeyEntryLoadBits::BOTH,
2599 1,
2600 |_k, _av| Ok(()),
2601 )?;
2602
2603 // The usage count is decremented now.
2604 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, Some(122)));
2605
2606 Ok(())
2607 }
2608
2609 #[test]
2610 fn test_check_and_update_key_usage_count_with_exhausted_limited_use_key() -> Result<()> {
2611 let mut db = new_test_db()?;
2612 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS, Some(1))
2613 .context("test_check_and_update_key_usage_count_with_exhausted_limited_use_key")?
2614 .0;
2615 // Update the usage count of the limited use key.
2616 db.check_and_update_key_usage_count(key_id).expect(concat!(
2617 "In test_check_and_update_key_usage_count_with_exhausted_limited_use_key: ",
2618 "This should succeed."
2619 ));
2620
2621 // Try to update the exhausted limited use key.
2622 let e = db.check_and_update_key_usage_count(key_id).expect_err(concat!(
2623 "In test_check_and_update_key_usage_count_with_exhausted_limited_use_key: ",
2624 "This should fail."
2625 ));
2626 assert_eq!(
2627 &KsError::Km(ErrorCode::INVALID_KEY_BLOB),
2628 e.root_cause().downcast_ref::<KsError>().unwrap()
2629 );
2630
2631 Ok(())
2632 }
2633
2634 #[test]
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002635 fn test_insert_and_load_full_keyentry_from_grant() -> Result<()> {
2636 let mut db = new_test_db()?;
Qi Wub9433b52020-12-01 14:52:46 +08002637 let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS, None)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002638 .context("test_insert_and_load_full_keyentry_from_grant")?
2639 .0;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002640
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002641 let granted_key = db
2642 .grant(
2643 KeyDescriptor {
2644 domain: Domain::APP,
2645 nspace: 0,
2646 alias: Some(TEST_ALIAS.to_string()),
2647 blob: None,
2648 },
2649 1,
2650 2,
2651 key_perm_set![KeyPerm::use_()],
2652 |_k, _av| Ok(()),
2653 )
2654 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002655
2656 debug_dump_grant_table(&mut db)?;
2657
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002658 let (_key_guard, key_entry) = db
2659 .load_key_entry(
2660 granted_key.clone(),
2661 KeyType::Client,
2662 KeyEntryLoadBits::BOTH,
2663 2,
2664 |k, av| {
2665 assert_eq!(Domain::GRANT, k.domain);
2666 assert!(av.unwrap().includes(KeyPerm::use_()));
2667 Ok(())
2668 },
2669 )
2670 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002671
Qi Wub9433b52020-12-01 14:52:46 +08002672 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002673
2674 db.unbind_key(granted_key.clone(), KeyType::Client, 2, |_, _| Ok(())).unwrap();
2675
2676 assert_eq!(
2677 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2678 db.load_key_entry(
2679 granted_key,
2680 KeyType::Client,
2681 KeyEntryLoadBits::NONE,
2682 2,
2683 |_k, _av| Ok(()),
2684 )
2685 .unwrap_err()
2686 .root_cause()
2687 .downcast_ref::<KsError>()
2688 );
2689
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002690 Ok(())
2691 }
2692
Janis Danisevskis45760022021-01-19 16:34:10 -08002693 // This test attempts to load a key by key id while the caller is not the owner
2694 // but a grant exists for the given key and the caller.
2695 #[test]
2696 fn test_insert_and_load_full_keyentry_from_grant_by_key_id() -> Result<()> {
2697 let mut db = new_test_db()?;
2698 const OWNER_UID: u32 = 1u32;
2699 const GRANTEE_UID: u32 = 2u32;
2700 const SOMEONE_ELSE_UID: u32 = 3u32;
2701 let key_id = make_test_key_entry(&mut db, Domain::APP, OWNER_UID as i64, TEST_ALIAS, None)
2702 .context("test_insert_and_load_full_keyentry_from_grant_by_key_id")?
2703 .0;
2704
2705 db.grant(
2706 KeyDescriptor {
2707 domain: Domain::APP,
2708 nspace: 0,
2709 alias: Some(TEST_ALIAS.to_string()),
2710 blob: None,
2711 },
2712 OWNER_UID,
2713 GRANTEE_UID,
2714 key_perm_set![KeyPerm::use_()],
2715 |_k, _av| Ok(()),
2716 )
2717 .unwrap();
2718
2719 debug_dump_grant_table(&mut db)?;
2720
2721 let id_descriptor =
2722 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, ..Default::default() };
2723
2724 let (_, key_entry) = db
2725 .load_key_entry(
2726 id_descriptor.clone(),
2727 KeyType::Client,
2728 KeyEntryLoadBits::BOTH,
2729 GRANTEE_UID,
2730 |k, av| {
2731 assert_eq!(Domain::APP, k.domain);
2732 assert_eq!(OWNER_UID as i64, k.nspace);
2733 assert!(av.unwrap().includes(KeyPerm::use_()));
2734 Ok(())
2735 },
2736 )
2737 .unwrap();
2738
2739 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
2740
2741 let (_, key_entry) = db
2742 .load_key_entry(
2743 id_descriptor.clone(),
2744 KeyType::Client,
2745 KeyEntryLoadBits::BOTH,
2746 SOMEONE_ELSE_UID,
2747 |k, av| {
2748 assert_eq!(Domain::APP, k.domain);
2749 assert_eq!(OWNER_UID as i64, k.nspace);
2750 assert!(av.is_none());
2751 Ok(())
2752 },
2753 )
2754 .unwrap();
2755
2756 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
2757
2758 db.unbind_key(id_descriptor.clone(), KeyType::Client, OWNER_UID, |_, _| Ok(())).unwrap();
2759
2760 assert_eq!(
2761 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2762 db.load_key_entry(
2763 id_descriptor,
2764 KeyType::Client,
2765 KeyEntryLoadBits::NONE,
2766 GRANTEE_UID,
2767 |_k, _av| Ok(()),
2768 )
2769 .unwrap_err()
2770 .root_cause()
2771 .downcast_ref::<KsError>()
2772 );
2773
2774 Ok(())
2775 }
2776
Janis Danisevskisaec14592020-11-12 09:41:49 -08002777 static KEY_LOCK_TEST_ALIAS: &str = "my super duper locked key";
2778
Janis Danisevskisaec14592020-11-12 09:41:49 -08002779 #[test]
2780 fn test_insert_and_load_full_keyentry_domain_app_concurrently() -> Result<()> {
2781 let handle = {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002782 let temp_dir = Arc::new(TempDir::new("id_lock_test")?);
2783 let temp_dir_clone = temp_dir.clone();
2784 let mut db = KeystoreDB::new(temp_dir.path())?;
Qi Wub9433b52020-12-01 14:52:46 +08002785 let key_id = make_test_key_entry(&mut db, Domain::APP, 33, KEY_LOCK_TEST_ALIAS, None)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002786 .context("test_insert_and_load_full_keyentry_domain_app")?
2787 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002788 let (_key_guard, key_entry) = db
2789 .load_key_entry(
2790 KeyDescriptor {
2791 domain: Domain::APP,
2792 nspace: 0,
2793 alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
2794 blob: None,
2795 },
2796 KeyType::Client,
2797 KeyEntryLoadBits::BOTH,
2798 33,
2799 |_k, _av| Ok(()),
2800 )
2801 .unwrap();
Qi Wub9433b52020-12-01 14:52:46 +08002802 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id, None));
Janis Danisevskisaec14592020-11-12 09:41:49 -08002803 let state = Arc::new(AtomicU8::new(1));
2804 let state2 = state.clone();
2805
2806 // Spawning a second thread that attempts to acquire the key id lock
2807 // for the same key as the primary thread. The primary thread then
2808 // waits, thereby forcing the secondary thread into the second stage
2809 // of acquiring the lock (see KEY ID LOCK 2/2 above).
2810 // The test succeeds if the secondary thread observes the transition
2811 // of `state` from 1 to 2, despite having a whole second to overtake
2812 // the primary thread.
2813 let handle = thread::spawn(move || {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002814 let temp_dir = temp_dir_clone;
2815 let mut db = KeystoreDB::new(temp_dir.path()).unwrap();
Janis Danisevskisaec14592020-11-12 09:41:49 -08002816 assert!(db
2817 .load_key_entry(
2818 KeyDescriptor {
2819 domain: Domain::APP,
2820 nspace: 0,
2821 alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
2822 blob: None,
2823 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002824 KeyType::Client,
Janis Danisevskisaec14592020-11-12 09:41:49 -08002825 KeyEntryLoadBits::BOTH,
2826 33,
2827 |_k, _av| Ok(()),
2828 )
2829 .is_ok());
2830 // We should only see a 2 here because we can only return
2831 // from load_key_entry when the `_key_guard` expires,
2832 // which happens at the end of the scope.
2833 assert_eq!(2, state2.load(Ordering::Relaxed));
2834 });
2835
2836 thread::sleep(std::time::Duration::from_millis(1000));
2837
2838 assert_eq!(Ok(1), state.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed));
2839
2840 // Return the handle from this scope so we can join with the
2841 // secondary thread after the key id lock has expired.
2842 handle
2843 // This is where the `_key_guard` goes out of scope,
2844 // which is the reason for concurrent load_key_entry on the same key
2845 // to unblock.
2846 };
2847 // Join with the secondary thread and unwrap, to propagate failing asserts to the
2848 // main test thread. We will not see failing asserts in secondary threads otherwise.
2849 handle.join().unwrap();
2850 Ok(())
2851 }
2852
Janis Danisevskise92a5e62020-12-02 12:57:41 -08002853 #[test]
2854 fn list() -> Result<()> {
2855 let temp_dir = TempDir::new("list_test")?;
2856 let mut db = KeystoreDB::new(temp_dir.path())?;
2857 static LIST_O_ENTRIES: &[(Domain, i64, &str)] = &[
2858 (Domain::APP, 1, "test1"),
2859 (Domain::APP, 1, "test2"),
2860 (Domain::APP, 1, "test3"),
2861 (Domain::APP, 1, "test4"),
2862 (Domain::APP, 1, "test5"),
2863 (Domain::APP, 1, "test6"),
2864 (Domain::APP, 1, "test7"),
2865 (Domain::APP, 2, "test1"),
2866 (Domain::APP, 2, "test2"),
2867 (Domain::APP, 2, "test3"),
2868 (Domain::APP, 2, "test4"),
2869 (Domain::APP, 2, "test5"),
2870 (Domain::APP, 2, "test6"),
2871 (Domain::APP, 2, "test8"),
2872 (Domain::SELINUX, 100, "test1"),
2873 (Domain::SELINUX, 100, "test2"),
2874 (Domain::SELINUX, 100, "test3"),
2875 (Domain::SELINUX, 100, "test4"),
2876 (Domain::SELINUX, 100, "test5"),
2877 (Domain::SELINUX, 100, "test6"),
2878 (Domain::SELINUX, 100, "test9"),
2879 ];
2880
2881 let list_o_keys: Vec<(i64, i64)> = LIST_O_ENTRIES
2882 .iter()
2883 .map(|(domain, ns, alias)| {
Qi Wub9433b52020-12-01 14:52:46 +08002884 let entry = make_test_key_entry(&mut db, *domain, *ns, *alias, None)
2885 .unwrap_or_else(|e| {
Janis Danisevskise92a5e62020-12-02 12:57:41 -08002886 panic!("Failed to insert {:?} {} {}. Error {:?}", domain, ns, alias, e)
2887 });
2888 (entry.id(), *ns)
2889 })
2890 .collect();
2891
2892 for (domain, namespace) in
2893 &[(Domain::APP, 1i64), (Domain::APP, 2i64), (Domain::SELINUX, 100i64)]
2894 {
2895 let mut list_o_descriptors: Vec<KeyDescriptor> = LIST_O_ENTRIES
2896 .iter()
2897 .filter_map(|(domain, ns, alias)| match ns {
2898 ns if *ns == *namespace => Some(KeyDescriptor {
2899 domain: *domain,
2900 nspace: *ns,
2901 alias: Some(alias.to_string()),
2902 blob: None,
2903 }),
2904 _ => None,
2905 })
2906 .collect();
2907 list_o_descriptors.sort();
2908 let mut list_result = db.list(*domain, *namespace)?;
2909 list_result.sort();
2910 assert_eq!(list_o_descriptors, list_result);
2911
2912 let mut list_o_ids: Vec<i64> = list_o_descriptors
2913 .into_iter()
2914 .map(|d| {
2915 let (_, entry) = db
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002916 .load_key_entry(
2917 d,
2918 KeyType::Client,
2919 KeyEntryLoadBits::NONE,
2920 *namespace as u32,
2921 |_, _| Ok(()),
2922 )
Janis Danisevskise92a5e62020-12-02 12:57:41 -08002923 .unwrap();
2924 entry.id()
2925 })
2926 .collect();
2927 list_o_ids.sort_unstable();
2928 let mut loaded_entries: Vec<i64> = list_o_keys
2929 .iter()
2930 .filter_map(|(id, ns)| match ns {
2931 ns if *ns == *namespace => Some(*id),
2932 _ => None,
2933 })
2934 .collect();
2935 loaded_entries.sort_unstable();
2936 assert_eq!(list_o_ids, loaded_entries);
2937 }
2938 assert_eq!(Vec::<KeyDescriptor>::new(), db.list(Domain::SELINUX, 101)?);
2939
2940 Ok(())
2941 }
2942
Joel Galenson0891bc12020-07-20 10:37:03 -07002943 // Helpers
2944
2945 // Checks that the given result is an error containing the given string.
2946 fn check_result_is_error_containing_string<T>(result: Result<T>, target: &str) {
2947 let error_str = format!(
2948 "{:#?}",
2949 result.err().unwrap_or_else(|| panic!("Expected the error: {}", target))
2950 );
2951 assert!(
2952 error_str.contains(target),
2953 "The string \"{}\" should contain \"{}\"",
2954 error_str,
2955 target
2956 );
2957 }
2958
Joel Galenson2aab4432020-07-22 15:27:57 -07002959 #[derive(Debug, PartialEq)]
Joel Galenson0891bc12020-07-20 10:37:03 -07002960 #[allow(dead_code)]
2961 struct KeyEntryRow {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002962 id: i64,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002963 key_type: KeyType,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002964 domain: Option<Domain>,
Joel Galenson0891bc12020-07-20 10:37:03 -07002965 namespace: Option<i64>,
2966 alias: Option<String>,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002967 state: KeyLifeCycle,
Joel Galenson0891bc12020-07-20 10:37:03 -07002968 }
2969
2970 fn get_keyentry(db: &KeystoreDB) -> Result<Vec<KeyEntryRow>> {
2971 db.conn
Joel Galenson2aab4432020-07-22 15:27:57 -07002972 .prepare("SELECT * FROM persistent.keyentry;")?
Joel Galenson0891bc12020-07-20 10:37:03 -07002973 .query_map(NO_PARAMS, |row| {
Joel Galenson0891bc12020-07-20 10:37:03 -07002974 Ok(KeyEntryRow {
2975 id: row.get(0)?,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002976 key_type: row.get(1)?,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002977 domain: match row.get(2)? {
2978 Some(i) => Some(Domain(i)),
2979 None => None,
2980 },
Joel Galenson0891bc12020-07-20 10:37:03 -07002981 namespace: row.get(3)?,
2982 alias: row.get(4)?,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002983 state: row.get(5)?,
Joel Galenson0891bc12020-07-20 10:37:03 -07002984 })
2985 })?
2986 .map(|r| r.context("Could not read keyentry row."))
2987 .collect::<Result<Vec<_>>>()
2988 }
2989
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07002990 // Note: The parameters and SecurityLevel associations are nonsensical. This
2991 // collection is only used to check if the parameters are preserved as expected by the
2992 // database.
Qi Wub9433b52020-12-01 14:52:46 +08002993 fn make_test_params(max_usage_count: Option<i32>) -> Vec<KeyParameter> {
2994 let mut params = vec![
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07002995 KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::TRUSTED_ENVIRONMENT),
2996 KeyParameter::new(
2997 KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
2998 SecurityLevel::TRUSTED_ENVIRONMENT,
2999 ),
3000 KeyParameter::new(
3001 KeyParameterValue::KeyPurpose(KeyPurpose::DECRYPT),
3002 SecurityLevel::TRUSTED_ENVIRONMENT,
3003 ),
3004 KeyParameter::new(
3005 KeyParameterValue::Algorithm(Algorithm::RSA),
3006 SecurityLevel::TRUSTED_ENVIRONMENT,
3007 ),
3008 KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::TRUSTED_ENVIRONMENT),
3009 KeyParameter::new(
3010 KeyParameterValue::BlockMode(BlockMode::ECB),
3011 SecurityLevel::TRUSTED_ENVIRONMENT,
3012 ),
3013 KeyParameter::new(
3014 KeyParameterValue::BlockMode(BlockMode::GCM),
3015 SecurityLevel::TRUSTED_ENVIRONMENT,
3016 ),
3017 KeyParameter::new(KeyParameterValue::Digest(Digest::NONE), SecurityLevel::STRONGBOX),
3018 KeyParameter::new(
3019 KeyParameterValue::Digest(Digest::MD5),
3020 SecurityLevel::TRUSTED_ENVIRONMENT,
3021 ),
3022 KeyParameter::new(
3023 KeyParameterValue::Digest(Digest::SHA_2_224),
3024 SecurityLevel::TRUSTED_ENVIRONMENT,
3025 ),
3026 KeyParameter::new(
3027 KeyParameterValue::Digest(Digest::SHA_2_256),
3028 SecurityLevel::STRONGBOX,
3029 ),
3030 KeyParameter::new(
3031 KeyParameterValue::PaddingMode(PaddingMode::NONE),
3032 SecurityLevel::TRUSTED_ENVIRONMENT,
3033 ),
3034 KeyParameter::new(
3035 KeyParameterValue::PaddingMode(PaddingMode::RSA_OAEP),
3036 SecurityLevel::TRUSTED_ENVIRONMENT,
3037 ),
3038 KeyParameter::new(
3039 KeyParameterValue::PaddingMode(PaddingMode::RSA_PSS),
3040 SecurityLevel::STRONGBOX,
3041 ),
3042 KeyParameter::new(
3043 KeyParameterValue::PaddingMode(PaddingMode::RSA_PKCS1_1_5_SIGN),
3044 SecurityLevel::TRUSTED_ENVIRONMENT,
3045 ),
3046 KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::TRUSTED_ENVIRONMENT),
3047 KeyParameter::new(KeyParameterValue::MinMacLength(256), SecurityLevel::STRONGBOX),
3048 KeyParameter::new(
3049 KeyParameterValue::EcCurve(EcCurve::P_224),
3050 SecurityLevel::TRUSTED_ENVIRONMENT,
3051 ),
3052 KeyParameter::new(KeyParameterValue::EcCurve(EcCurve::P_256), SecurityLevel::STRONGBOX),
3053 KeyParameter::new(
3054 KeyParameterValue::EcCurve(EcCurve::P_384),
3055 SecurityLevel::TRUSTED_ENVIRONMENT,
3056 ),
3057 KeyParameter::new(
3058 KeyParameterValue::EcCurve(EcCurve::P_521),
3059 SecurityLevel::TRUSTED_ENVIRONMENT,
3060 ),
3061 KeyParameter::new(
3062 KeyParameterValue::RSAPublicExponent(3),
3063 SecurityLevel::TRUSTED_ENVIRONMENT,
3064 ),
3065 KeyParameter::new(
3066 KeyParameterValue::IncludeUniqueID,
3067 SecurityLevel::TRUSTED_ENVIRONMENT,
3068 ),
3069 KeyParameter::new(KeyParameterValue::BootLoaderOnly, SecurityLevel::STRONGBOX),
3070 KeyParameter::new(KeyParameterValue::RollbackResistance, SecurityLevel::STRONGBOX),
3071 KeyParameter::new(
3072 KeyParameterValue::ActiveDateTime(1234567890),
3073 SecurityLevel::STRONGBOX,
3074 ),
3075 KeyParameter::new(
3076 KeyParameterValue::OriginationExpireDateTime(1234567890),
3077 SecurityLevel::TRUSTED_ENVIRONMENT,
3078 ),
3079 KeyParameter::new(
3080 KeyParameterValue::UsageExpireDateTime(1234567890),
3081 SecurityLevel::TRUSTED_ENVIRONMENT,
3082 ),
3083 KeyParameter::new(
3084 KeyParameterValue::MinSecondsBetweenOps(1234567890),
3085 SecurityLevel::TRUSTED_ENVIRONMENT,
3086 ),
3087 KeyParameter::new(
3088 KeyParameterValue::MaxUsesPerBoot(1234567890),
3089 SecurityLevel::TRUSTED_ENVIRONMENT,
3090 ),
3091 KeyParameter::new(KeyParameterValue::UserID(1), SecurityLevel::STRONGBOX),
3092 KeyParameter::new(KeyParameterValue::UserSecureID(42), SecurityLevel::STRONGBOX),
3093 KeyParameter::new(
3094 KeyParameterValue::NoAuthRequired,
3095 SecurityLevel::TRUSTED_ENVIRONMENT,
3096 ),
3097 KeyParameter::new(
3098 KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType::PASSWORD),
3099 SecurityLevel::TRUSTED_ENVIRONMENT,
3100 ),
3101 KeyParameter::new(KeyParameterValue::AuthTimeout(1234567890), SecurityLevel::SOFTWARE),
3102 KeyParameter::new(KeyParameterValue::AllowWhileOnBody, SecurityLevel::SOFTWARE),
3103 KeyParameter::new(
3104 KeyParameterValue::TrustedUserPresenceRequired,
3105 SecurityLevel::TRUSTED_ENVIRONMENT,
3106 ),
3107 KeyParameter::new(
3108 KeyParameterValue::TrustedConfirmationRequired,
3109 SecurityLevel::TRUSTED_ENVIRONMENT,
3110 ),
3111 KeyParameter::new(
3112 KeyParameterValue::UnlockedDeviceRequired,
3113 SecurityLevel::TRUSTED_ENVIRONMENT,
3114 ),
3115 KeyParameter::new(
3116 KeyParameterValue::ApplicationID(vec![1u8, 2u8, 3u8, 4u8]),
3117 SecurityLevel::SOFTWARE,
3118 ),
3119 KeyParameter::new(
3120 KeyParameterValue::ApplicationData(vec![4u8, 3u8, 2u8, 1u8]),
3121 SecurityLevel::SOFTWARE,
3122 ),
3123 KeyParameter::new(
3124 KeyParameterValue::CreationDateTime(12345677890),
3125 SecurityLevel::SOFTWARE,
3126 ),
3127 KeyParameter::new(
3128 KeyParameterValue::KeyOrigin(KeyOrigin::GENERATED),
3129 SecurityLevel::TRUSTED_ENVIRONMENT,
3130 ),
3131 KeyParameter::new(
3132 KeyParameterValue::RootOfTrust(vec![3u8, 2u8, 1u8, 4u8]),
3133 SecurityLevel::TRUSTED_ENVIRONMENT,
3134 ),
3135 KeyParameter::new(KeyParameterValue::OSVersion(1), SecurityLevel::TRUSTED_ENVIRONMENT),
3136 KeyParameter::new(KeyParameterValue::OSPatchLevel(2), SecurityLevel::SOFTWARE),
3137 KeyParameter::new(
3138 KeyParameterValue::UniqueID(vec![4u8, 3u8, 1u8, 2u8]),
3139 SecurityLevel::SOFTWARE,
3140 ),
3141 KeyParameter::new(
3142 KeyParameterValue::AttestationChallenge(vec![4u8, 3u8, 1u8, 2u8]),
3143 SecurityLevel::TRUSTED_ENVIRONMENT,
3144 ),
3145 KeyParameter::new(
3146 KeyParameterValue::AttestationApplicationID(vec![4u8, 3u8, 1u8, 2u8]),
3147 SecurityLevel::TRUSTED_ENVIRONMENT,
3148 ),
3149 KeyParameter::new(
3150 KeyParameterValue::AttestationIdBrand(vec![4u8, 3u8, 1u8, 2u8]),
3151 SecurityLevel::TRUSTED_ENVIRONMENT,
3152 ),
3153 KeyParameter::new(
3154 KeyParameterValue::AttestationIdDevice(vec![4u8, 3u8, 1u8, 2u8]),
3155 SecurityLevel::TRUSTED_ENVIRONMENT,
3156 ),
3157 KeyParameter::new(
3158 KeyParameterValue::AttestationIdProduct(vec![4u8, 3u8, 1u8, 2u8]),
3159 SecurityLevel::TRUSTED_ENVIRONMENT,
3160 ),
3161 KeyParameter::new(
3162 KeyParameterValue::AttestationIdSerial(vec![4u8, 3u8, 1u8, 2u8]),
3163 SecurityLevel::TRUSTED_ENVIRONMENT,
3164 ),
3165 KeyParameter::new(
3166 KeyParameterValue::AttestationIdIMEI(vec![4u8, 3u8, 1u8, 2u8]),
3167 SecurityLevel::TRUSTED_ENVIRONMENT,
3168 ),
3169 KeyParameter::new(
3170 KeyParameterValue::AttestationIdMEID(vec![4u8, 3u8, 1u8, 2u8]),
3171 SecurityLevel::TRUSTED_ENVIRONMENT,
3172 ),
3173 KeyParameter::new(
3174 KeyParameterValue::AttestationIdManufacturer(vec![4u8, 3u8, 1u8, 2u8]),
3175 SecurityLevel::TRUSTED_ENVIRONMENT,
3176 ),
3177 KeyParameter::new(
3178 KeyParameterValue::AttestationIdModel(vec![4u8, 3u8, 1u8, 2u8]),
3179 SecurityLevel::TRUSTED_ENVIRONMENT,
3180 ),
3181 KeyParameter::new(
3182 KeyParameterValue::VendorPatchLevel(3),
3183 SecurityLevel::TRUSTED_ENVIRONMENT,
3184 ),
3185 KeyParameter::new(
3186 KeyParameterValue::BootPatchLevel(4),
3187 SecurityLevel::TRUSTED_ENVIRONMENT,
3188 ),
3189 KeyParameter::new(
3190 KeyParameterValue::AssociatedData(vec![4u8, 3u8, 1u8, 2u8]),
3191 SecurityLevel::TRUSTED_ENVIRONMENT,
3192 ),
3193 KeyParameter::new(
3194 KeyParameterValue::Nonce(vec![4u8, 3u8, 1u8, 2u8]),
3195 SecurityLevel::TRUSTED_ENVIRONMENT,
3196 ),
3197 KeyParameter::new(
3198 KeyParameterValue::MacLength(256),
3199 SecurityLevel::TRUSTED_ENVIRONMENT,
3200 ),
3201 KeyParameter::new(
3202 KeyParameterValue::ResetSinceIdRotation,
3203 SecurityLevel::TRUSTED_ENVIRONMENT,
3204 ),
3205 KeyParameter::new(
3206 KeyParameterValue::ConfirmationToken(vec![5u8, 5u8, 5u8, 5u8]),
3207 SecurityLevel::TRUSTED_ENVIRONMENT,
3208 ),
Qi Wub9433b52020-12-01 14:52:46 +08003209 ];
3210 if let Some(value) = max_usage_count {
3211 params.push(KeyParameter::new(
3212 KeyParameterValue::UsageCountLimit(value),
3213 SecurityLevel::SOFTWARE,
3214 ));
3215 }
3216 params
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07003217 }
3218
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07003219 fn make_test_key_entry(
3220 db: &mut KeystoreDB,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07003221 domain: Domain,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07003222 namespace: i64,
3223 alias: &str,
Qi Wub9433b52020-12-01 14:52:46 +08003224 max_usage_count: Option<i32>,
Janis Danisevskisaec14592020-11-12 09:41:49 -08003225 ) -> Result<KeyIdGuard> {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07003226 let key_id = db.create_key_entry(domain, namespace)?;
Janis Danisevskis377d1002021-01-27 19:07:48 -08003227 db.set_blob(&key_id, SubComponentType::KEY_BLOB, Some(TEST_KEY_BLOB))?;
3228 db.set_blob(&key_id, SubComponentType::CERT, Some(TEST_CERT_BLOB))?;
3229 db.set_blob(&key_id, SubComponentType::CERT_CHAIN, Some(TEST_CERT_CHAIN_BLOB))?;
Qi Wub9433b52020-12-01 14:52:46 +08003230
3231 let params = make_test_params(max_usage_count);
3232 db.insert_keyparameter(&key_id, &params)?;
3233
Janis Danisevskisb42fc182020-12-15 08:41:27 -08003234 let mut metadata = KeyMetaData::new();
3235 metadata.add(KeyMetaEntry::EncryptedBy(EncryptedBy::Password));
3236 metadata.add(KeyMetaEntry::Salt(vec![1, 2, 3]));
3237 metadata.add(KeyMetaEntry::Iv(vec![2, 3, 1]));
3238 metadata.add(KeyMetaEntry::AeadTag(vec![3, 1, 2]));
3239 db.insert_key_metadata(&key_id, &metadata)?;
Janis Danisevskis4507f3b2021-01-13 16:34:39 -08003240 rebind_alias(db, &key_id, alias, domain, namespace)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07003241 Ok(key_id)
3242 }
3243
Qi Wub9433b52020-12-01 14:52:46 +08003244 fn make_test_key_entry_test_vector(key_id: i64, max_usage_count: Option<i32>) -> KeyEntry {
3245 let params = make_test_params(max_usage_count);
3246
Janis Danisevskisb42fc182020-12-15 08:41:27 -08003247 let mut metadata = KeyMetaData::new();
3248 metadata.add(KeyMetaEntry::EncryptedBy(EncryptedBy::Password));
3249 metadata.add(KeyMetaEntry::Salt(vec![1, 2, 3]));
3250 metadata.add(KeyMetaEntry::Iv(vec![2, 3, 1]));
3251 metadata.add(KeyMetaEntry::AeadTag(vec![3, 1, 2]));
3252
3253 KeyEntry {
3254 id: key_id,
3255 km_blob: Some(TEST_KEY_BLOB.to_vec()),
3256 cert: Some(TEST_CERT_BLOB.to_vec()),
3257 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
3258 sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
Qi Wub9433b52020-12-01 14:52:46 +08003259 parameters: params,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08003260 metadata,
Janis Danisevskis377d1002021-01-27 19:07:48 -08003261 pure_cert: false,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08003262 }
3263 }
3264
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07003265 fn debug_dump_keyentry_table(db: &mut KeystoreDB) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08003266 let mut stmt = db.conn.prepare(
3267 "SELECT id, key_type, domain, namespace, alias, state FROM persistent.keyentry;",
3268 )?;
3269 let rows = stmt.query_map::<(i64, KeyType, i32, i64, String, KeyLifeCycle), _, _>(
3270 NO_PARAMS,
3271 |row| {
3272 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?, row.get(4)?, row.get(5)?))
3273 },
3274 )?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07003275
3276 println!("Key entry table rows:");
3277 for r in rows {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08003278 let (id, key_type, domain, namespace, alias, state) = r.unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07003279 println!(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08003280 " id: {} KeyType: {:?} Domain: {} Namespace: {} Alias: {} State: {:?}",
3281 id, key_type, domain, namespace, alias, state
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07003282 );
3283 }
3284 Ok(())
3285 }
3286
3287 fn debug_dump_grant_table(db: &mut KeystoreDB) -> Result<()> {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08003288 let mut stmt = db
3289 .conn
3290 .prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07003291 let rows = stmt.query_map::<(i64, i64, i64, i64), _, _>(NO_PARAMS, |row| {
3292 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?))
3293 })?;
3294
3295 println!("Grant table rows:");
3296 for r in rows {
3297 let (id, gt, ki, av) = r.unwrap();
3298 println!(" id: {} grantee: {} key_id: {} access_vector: {}", id, gt, ki, av);
3299 }
3300 Ok(())
3301 }
3302
Joel Galenson0891bc12020-07-20 10:37:03 -07003303 // Use a custom random number generator that repeats each number once.
3304 // This allows us to test repeated elements.
3305
3306 thread_local! {
3307 static RANDOM_COUNTER: RefCell<i64> = RefCell::new(0);
3308 }
3309
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07003310 fn reset_random() {
3311 RANDOM_COUNTER.with(|counter| {
3312 *counter.borrow_mut() = 0;
3313 })
3314 }
3315
Joel Galenson0891bc12020-07-20 10:37:03 -07003316 pub fn random() -> i64 {
3317 RANDOM_COUNTER.with(|counter| {
3318 let result = *counter.borrow() / 2;
3319 *counter.borrow_mut() += 1;
3320 result
3321 })
3322 }
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00003323
3324 #[test]
3325 fn test_last_off_body() -> Result<()> {
3326 let mut db = new_test_db()?;
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08003327 db.insert_last_off_body(MonotonicRawTime::now())?;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00003328 let tx = db.conn.transaction_with_behavior(TransactionBehavior::Immediate)?;
3329 let last_off_body_1 = KeystoreDB::get_last_off_body(&tx)?;
3330 tx.commit()?;
3331 let one_second = Duration::from_secs(1);
3332 thread::sleep(one_second);
3333 db.update_last_off_body(MonotonicRawTime::now())?;
3334 let tx2 = db.conn.transaction_with_behavior(TransactionBehavior::Immediate)?;
3335 let last_off_body_2 = KeystoreDB::get_last_off_body(&tx2)?;
3336 tx2.commit()?;
3337 assert!(last_off_body_1.seconds() < last_off_body_2.seconds());
3338 Ok(())
3339 }
Joel Galenson26f4d012020-07-17 14:57:21 -07003340}