blob: e25fea219dfdb472e874c10b776bc2af4583de95 [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 Danisevskisb42fc182020-12-15 08:41:27 -080044#![allow(dead_code)]
45
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070046use crate::error::{Error as KsError, ResponseCode};
Janis Danisevskisb42fc182020-12-15 08:41:27 -080047use crate::impl_metadata; // This is in db_utils.rs
Janis Danisevskis4522c2b2020-11-27 18:04:58 -080048use crate::key_parameter::{KeyParameter, Tag};
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070049use crate::permission::KeyPermSet;
Hasini Gunasinghe557b1032020-11-10 01:35:30 +000050use crate::utils::get_current_time_in_seconds;
Janis Danisevskis93927dd2020-12-23 12:23:08 -080051use crate::{
52 db_utils::{self, SqlField},
53 gc::Gc,
54};
Janis Danisevskisb42fc182020-12-15 08:41:27 -080055use anyhow::{anyhow, Context, Result};
56use std::{convert::TryFrom, convert::TryInto, time::SystemTimeError};
Janis Danisevskis60400fe2020-08-26 15:24:42 -070057
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +000058use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +000059 ErrorCode::ErrorCode as Ec, HardwareAuthToken::HardwareAuthToken,
60 HardwareAuthenticatorType::HardwareAuthenticatorType, SecurityLevel::SecurityLevel,
Janis Danisevskisc3a496b2021-01-05 10:37:22 -080061};
62use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +000063 Timestamp::Timestamp,
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +000064};
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070065use android_system_keystore2::aidl::android::system::keystore2::{
Janis Danisevskis04b02832020-10-26 09:21:40 -070066 Domain::Domain, KeyDescriptor::KeyDescriptor,
Janis Danisevskis60400fe2020-08-26 15:24:42 -070067};
Janis Danisevskisaec14592020-11-12 09:41:49 -080068use lazy_static::lazy_static;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +000069use log::error;
Joel Galenson0891bc12020-07-20 10:37:03 -070070#[cfg(not(test))]
71use rand::prelude::random;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070072use rusqlite::{
Janis Danisevskisb42fc182020-12-15 08:41:27 -080073 params,
74 types::FromSql,
75 types::FromSqlResult,
76 types::ToSqlOutput,
77 types::{FromSqlError, Value, ValueRef},
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +000078 Connection, Error, OptionalExtension, ToSql, Transaction, TransactionBehavior, NO_PARAMS,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070079};
Janis Danisevskisaec14592020-11-12 09:41:49 -080080use std::{
Janis Danisevskisb42fc182020-12-15 08:41:27 -080081 collections::{HashMap, HashSet},
Janis Danisevskisbf15d732020-12-08 10:35:26 -080082 path::Path,
83 sync::{Condvar, Mutex},
Janis Danisevskisb42fc182020-12-15 08:41:27 -080084 time::{Duration, SystemTime},
Janis Danisevskisaec14592020-11-12 09:41:49 -080085};
Joel Galenson0891bc12020-07-20 10:37:03 -070086#[cfg(test)]
87use tests::random;
Joel Galenson26f4d012020-07-17 14:57:21 -070088
Janis Danisevskisb42fc182020-12-15 08:41:27 -080089impl_metadata!(
90 /// A set of metadata for key entries.
91 #[derive(Debug, Default, Eq, PartialEq)]
92 pub struct KeyMetaData;
93 /// A metadata entry for key entries.
94 #[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
95 pub enum KeyMetaEntry {
96 /// If present, indicates that the sensitive part of key
97 /// is encrypted with another key or a key derived from a password.
98 EncryptedBy(EncryptedBy) with accessor encrypted_by,
99 /// If the blob is password encrypted this field is set to the
100 /// salt used for the key derivation.
101 Salt(Vec<u8>) with accessor salt,
102 /// If the blob is encrypted, this field is set to the initialization vector.
103 Iv(Vec<u8>) with accessor iv,
104 /// If the blob is encrypted, this field holds the AEAD TAG.
105 AeadTag(Vec<u8>) with accessor aead_tag,
106 /// Creation date of a the key entry.
107 CreationDate(DateTime) with accessor creation_date,
108 /// Expiration date for attestation keys.
109 AttestationExpirationDate(DateTime) with accessor attestation_expiration_date,
110 // --- ADD NEW META DATA FIELDS HERE ---
111 // For backwards compatibility add new entries only to
112 // end of this list and above this comment.
113 };
114);
115
116impl KeyMetaData {
117 fn load_from_db(key_id: i64, tx: &Transaction) -> Result<Self> {
118 let mut stmt = tx
119 .prepare(
120 "SELECT tag, data from persistent.keymetadata
121 WHERE keyentryid = ?;",
122 )
123 .context("In KeyMetaData::load_from_db: prepare statement failed.")?;
124
125 let mut metadata: HashMap<i64, KeyMetaEntry> = Default::default();
126
127 let mut rows =
128 stmt.query(params![key_id]).context("In KeyMetaData::load_from_db: query failed.")?;
129 db_utils::with_rows_extract_all(&mut rows, |row| {
130 let db_tag: i64 = row.get(0).context("Failed to read tag.")?;
131 metadata.insert(
132 db_tag,
133 KeyMetaEntry::new_from_sql(db_tag, &SqlField::new(1, &row))
134 .context("Failed to read KeyMetaEntry.")?,
135 );
136 Ok(())
137 })
138 .context("In KeyMetaData::load_from_db.")?;
139
140 Ok(Self { data: metadata })
141 }
142
143 fn store_in_db(&self, key_id: i64, tx: &Transaction) -> Result<()> {
144 let mut stmt = tx
145 .prepare(
146 "INSERT into persistent.keymetadata (keyentryid, tag, data)
147 VALUES (?, ?, ?);",
148 )
149 .context("In KeyMetaData::store_in_db: Failed to prepare statement.")?;
150
151 let iter = self.data.iter();
152 for (tag, entry) in iter {
153 stmt.insert(params![key_id, tag, entry,]).with_context(|| {
154 format!("In KeyMetaData::store_in_db: Failed to insert {:?}", entry)
155 })?;
156 }
157 Ok(())
158 }
159}
160
161/// Indicates the type of the keyentry.
162#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
163pub enum KeyType {
164 /// This is a client key type. These keys are created or imported through the Keystore 2.0
165 /// AIDL interface android.system.keystore2.
166 Client,
167 /// This is a super key type. These keys are created by keystore itself and used to encrypt
168 /// other key blobs to provide LSKF binding.
169 Super,
170 /// This is an attestation key. These keys are created by the remote provisioning mechanism.
171 Attestation,
172}
173
174impl ToSql for KeyType {
175 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
176 Ok(ToSqlOutput::Owned(Value::Integer(match self {
177 KeyType::Client => 0,
178 KeyType::Super => 1,
179 KeyType::Attestation => 2,
180 })))
181 }
182}
183
184impl FromSql for KeyType {
185 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
186 match i64::column_result(value)? {
187 0 => Ok(KeyType::Client),
188 1 => Ok(KeyType::Super),
189 2 => Ok(KeyType::Attestation),
190 v => Err(FromSqlError::OutOfRange(v)),
191 }
192 }
193}
194
195/// Indicates how the sensitive part of this key blob is encrypted.
196#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
197pub enum EncryptedBy {
198 /// The keyblob is encrypted by a user password.
199 /// In the database this variant is represented as NULL.
200 Password,
201 /// The keyblob is encrypted by another key with wrapped key id.
202 /// In the database this variant is represented as non NULL value
203 /// that is convertible to i64, typically NUMERIC.
204 KeyId(i64),
205}
206
207impl ToSql for EncryptedBy {
208 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
209 match self {
210 Self::Password => Ok(ToSqlOutput::Owned(Value::Null)),
211 Self::KeyId(id) => id.to_sql(),
212 }
213 }
214}
215
216impl FromSql for EncryptedBy {
217 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
218 match value {
219 ValueRef::Null => Ok(Self::Password),
220 _ => Ok(Self::KeyId(i64::column_result(value)?)),
221 }
222 }
223}
224
225/// A database representation of wall clock time. DateTime stores unix epoch time as
226/// i64 in milliseconds.
227#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)]
228pub struct DateTime(i64);
229
230/// Error type returned when creating DateTime or converting it from and to
231/// SystemTime.
232#[derive(thiserror::Error, Debug)]
233pub enum DateTimeError {
234 /// This is returned when SystemTime and Duration computations fail.
235 #[error(transparent)]
236 SystemTimeError(#[from] SystemTimeError),
237
238 /// This is returned when type conversions fail.
239 #[error(transparent)]
240 TypeConversion(#[from] std::num::TryFromIntError),
241
242 /// This is returned when checked time arithmetic failed.
243 #[error("Time arithmetic failed.")]
244 TimeArithmetic,
245}
246
247impl DateTime {
248 /// Constructs a new DateTime object denoting the current time. This may fail during
249 /// conversion to unix epoch time and during conversion to the internal i64 representation.
250 pub fn now() -> Result<Self, DateTimeError> {
251 Ok(Self(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_millis().try_into()?))
252 }
253
254 /// Constructs a new DateTime object from milliseconds.
255 pub fn from_millis_epoch(millis: i64) -> Self {
256 Self(millis)
257 }
258
259 /// Returns unix epoch time in milliseconds.
260 pub fn to_millis_epoch(&self) -> i64 {
261 self.0
262 }
263
264 /// Returns unix epoch time in seconds.
265 pub fn to_secs_epoch(&self) -> i64 {
266 self.0 / 1000
267 }
268}
269
270impl ToSql for DateTime {
271 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
272 Ok(ToSqlOutput::Owned(Value::Integer(self.0)))
273 }
274}
275
276impl FromSql for DateTime {
277 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
278 Ok(Self(i64::column_result(value)?))
279 }
280}
281
282impl TryInto<SystemTime> for DateTime {
283 type Error = DateTimeError;
284
285 fn try_into(self) -> Result<SystemTime, Self::Error> {
286 // We want to construct a SystemTime representation equivalent to self, denoting
287 // a point in time THEN, but we cannot set the time directly. We can only construct
288 // a SystemTime denoting NOW, and we can get the duration between EPOCH and NOW,
289 // and between EPOCH and THEN. With this common reference we can construct the
290 // duration between NOW and THEN which we can add to our SystemTime representation
291 // of NOW to get a SystemTime representation of THEN.
292 // Durations can only be positive, thus the if statement below.
293 let now = SystemTime::now();
294 let now_epoch = now.duration_since(SystemTime::UNIX_EPOCH)?;
295 let then_epoch = Duration::from_millis(self.0.try_into()?);
296 Ok(if now_epoch > then_epoch {
297 // then = now - (now_epoch - then_epoch)
298 now_epoch
299 .checked_sub(then_epoch)
300 .and_then(|d| now.checked_sub(d))
301 .ok_or(DateTimeError::TimeArithmetic)?
302 } else {
303 // then = now + (then_epoch - now_epoch)
304 then_epoch
305 .checked_sub(now_epoch)
306 .and_then(|d| now.checked_add(d))
307 .ok_or(DateTimeError::TimeArithmetic)?
308 })
309 }
310}
311
312impl TryFrom<SystemTime> for DateTime {
313 type Error = DateTimeError;
314
315 fn try_from(t: SystemTime) -> Result<Self, Self::Error> {
316 Ok(Self(t.duration_since(SystemTime::UNIX_EPOCH)?.as_millis().try_into()?))
317 }
318}
319
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800320#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
321enum KeyLifeCycle {
322 /// Existing keys have a key ID but are not fully populated yet.
323 /// This is a transient state. If Keystore finds any such keys when it starts up, it must move
324 /// them to Unreferenced for garbage collection.
325 Existing,
326 /// A live key is fully populated and usable by clients.
327 Live,
328 /// An unreferenced key is scheduled for garbage collection.
329 Unreferenced,
330}
331
332impl ToSql for KeyLifeCycle {
333 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
334 match self {
335 Self::Existing => Ok(ToSqlOutput::Owned(Value::Integer(0))),
336 Self::Live => Ok(ToSqlOutput::Owned(Value::Integer(1))),
337 Self::Unreferenced => Ok(ToSqlOutput::Owned(Value::Integer(2))),
338 }
339 }
340}
341
342impl FromSql for KeyLifeCycle {
343 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
344 match i64::column_result(value)? {
345 0 => Ok(KeyLifeCycle::Existing),
346 1 => Ok(KeyLifeCycle::Live),
347 2 => Ok(KeyLifeCycle::Unreferenced),
348 v => Err(FromSqlError::OutOfRange(v)),
349 }
350 }
351}
352
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700353/// Keys have a KeyMint blob component and optional public certificate and
354/// certificate chain components.
355/// KeyEntryLoadBits is a bitmap that indicates to `KeystoreDB::load_key_entry`
356/// which components shall be loaded from the database if present.
357#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
358pub struct KeyEntryLoadBits(u32);
359
360impl KeyEntryLoadBits {
361 /// Indicate to `KeystoreDB::load_key_entry` that no component shall be loaded.
362 pub const NONE: KeyEntryLoadBits = Self(0);
363 /// Indicate to `KeystoreDB::load_key_entry` that the KeyMint component shall be loaded.
364 pub const KM: KeyEntryLoadBits = Self(1);
365 /// Indicate to `KeystoreDB::load_key_entry` that the Public components shall be loaded.
366 pub const PUBLIC: KeyEntryLoadBits = Self(2);
367 /// Indicate to `KeystoreDB::load_key_entry` that both components shall be loaded.
368 pub const BOTH: KeyEntryLoadBits = Self(3);
369
370 /// Returns true if this object indicates that the public components shall be loaded.
371 pub const fn load_public(&self) -> bool {
372 self.0 & Self::PUBLIC.0 != 0
373 }
374
375 /// Returns true if the object indicates that the KeyMint component shall be loaded.
376 pub const fn load_km(&self) -> bool {
377 self.0 & Self::KM.0 != 0
378 }
379}
380
Janis Danisevskisaec14592020-11-12 09:41:49 -0800381lazy_static! {
382 static ref KEY_ID_LOCK: KeyIdLockDb = KeyIdLockDb::new();
383}
384
385struct KeyIdLockDb {
386 locked_keys: Mutex<HashSet<i64>>,
387 cond_var: Condvar,
388}
389
390/// A locked key. While a guard exists for a given key id, the same key cannot be loaded
391/// from the database a second time. Most functions manipulating the key blob database
392/// require a KeyIdGuard.
393#[derive(Debug)]
394pub struct KeyIdGuard(i64);
395
396impl KeyIdLockDb {
397 fn new() -> Self {
398 Self { locked_keys: Mutex::new(HashSet::new()), cond_var: Condvar::new() }
399 }
400
401 /// This function blocks until an exclusive lock for the given key entry id can
402 /// be acquired. It returns a guard object, that represents the lifecycle of the
403 /// acquired lock.
404 pub fn get(&self, key_id: i64) -> KeyIdGuard {
405 let mut locked_keys = self.locked_keys.lock().unwrap();
406 while locked_keys.contains(&key_id) {
407 locked_keys = self.cond_var.wait(locked_keys).unwrap();
408 }
409 locked_keys.insert(key_id);
410 KeyIdGuard(key_id)
411 }
412
413 /// This function attempts to acquire an exclusive lock on a given key id. If the
414 /// given key id is already taken the function returns None immediately. If a lock
415 /// can be acquired this function returns a guard object, that represents the
416 /// lifecycle of the acquired lock.
417 pub fn try_get(&self, key_id: i64) -> Option<KeyIdGuard> {
418 let mut locked_keys = self.locked_keys.lock().unwrap();
419 if locked_keys.insert(key_id) {
420 Some(KeyIdGuard(key_id))
421 } else {
422 None
423 }
424 }
425}
426
427impl KeyIdGuard {
428 /// Get the numeric key id of the locked key.
429 pub fn id(&self) -> i64 {
430 self.0
431 }
432}
433
434impl Drop for KeyIdGuard {
435 fn drop(&mut self) {
436 let mut locked_keys = KEY_ID_LOCK.locked_keys.lock().unwrap();
437 locked_keys.remove(&self.0);
Janis Danisevskis7fd53582020-11-23 13:40:34 -0800438 drop(locked_keys);
Janis Danisevskisaec14592020-11-12 09:41:49 -0800439 KEY_ID_LOCK.cond_var.notify_all();
440 }
441}
442
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700443/// This type represents a Keystore 2.0 key entry.
444/// An entry has a unique `id` by which it can be found in the database.
445/// It has a security level field, key parameters, and three optional fields
446/// for the KeyMint blob, public certificate and a public certificate chain.
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800447#[derive(Debug, Default, Eq, PartialEq)]
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700448pub struct KeyEntry {
449 id: i64,
450 km_blob: Option<Vec<u8>>,
451 cert: Option<Vec<u8>>,
452 cert_chain: Option<Vec<u8>>,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700453 sec_level: SecurityLevel,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700454 parameters: Vec<KeyParameter>,
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800455 metadata: KeyMetaData,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700456}
457
458impl KeyEntry {
459 /// Returns the unique id of the Key entry.
460 pub fn id(&self) -> i64 {
461 self.id
462 }
463 /// Exposes the optional KeyMint blob.
464 pub fn km_blob(&self) -> &Option<Vec<u8>> {
465 &self.km_blob
466 }
467 /// Extracts the Optional KeyMint blob.
468 pub fn take_km_blob(&mut self) -> Option<Vec<u8>> {
469 self.km_blob.take()
470 }
471 /// Exposes the optional public certificate.
472 pub fn cert(&self) -> &Option<Vec<u8>> {
473 &self.cert
474 }
475 /// Extracts the optional public certificate.
476 pub fn take_cert(&mut self) -> Option<Vec<u8>> {
477 self.cert.take()
478 }
479 /// Exposes the optional public certificate chain.
480 pub fn cert_chain(&self) -> &Option<Vec<u8>> {
481 &self.cert_chain
482 }
483 /// Extracts the optional public certificate_chain.
484 pub fn take_cert_chain(&mut self) -> Option<Vec<u8>> {
485 self.cert_chain.take()
486 }
487 /// Returns the security level of the key entry.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700488 pub fn sec_level(&self) -> SecurityLevel {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700489 self.sec_level
490 }
Janis Danisevskis04b02832020-10-26 09:21:40 -0700491 /// Exposes the key parameters of this key entry.
492 pub fn key_parameters(&self) -> &Vec<KeyParameter> {
493 &self.parameters
494 }
495 /// Consumes this key entry and extracts the keyparameters from it.
496 pub fn into_key_parameters(self) -> Vec<KeyParameter> {
497 self.parameters
498 }
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800499 /// Exposes the key metadata of this key entry.
500 pub fn metadata(&self) -> &KeyMetaData {
501 &self.metadata
502 }
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700503}
504
505/// Indicates the sub component of a key entry for persistent storage.
506#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
507pub struct SubComponentType(u32);
508impl SubComponentType {
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800509 /// Persistent identifier for a key blob.
510 pub const KEY_BLOB: SubComponentType = Self(0);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700511 /// Persistent identifier for a certificate blob.
512 pub const CERT: SubComponentType = Self(1);
513 /// Persistent identifier for a certificate chain blob.
514 pub const CERT_CHAIN: SubComponentType = Self(2);
515}
516
517impl ToSql for SubComponentType {
518 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
519 self.0.to_sql()
520 }
521}
522
523impl FromSql for SubComponentType {
524 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
525 Ok(Self(u32::column_result(value)?))
526 }
527}
528
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700529/// KeystoreDB wraps a connection to an SQLite database and tracks its
530/// ownership. It also implements all of Keystore 2.0's database functionality.
Joel Galenson26f4d012020-07-17 14:57:21 -0700531pub struct KeystoreDB {
Joel Galenson26f4d012020-07-17 14:57:21 -0700532 conn: Connection,
533}
534
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000535/// Database representation of the monotonic time retrieved from the system call clock_gettime with
536/// CLOCK_MONOTONIC_RAW. Stores monotonic time as i64 in seconds.
537#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)]
538pub struct MonotonicRawTime(i64);
539
540impl MonotonicRawTime {
541 /// Constructs a new MonotonicRawTime
542 pub fn now() -> Self {
543 Self(get_current_time_in_seconds())
544 }
545
546 /// Returns the integer value of MonotonicRawTime as i64
547 pub fn seconds(&self) -> i64 {
548 self.0
549 }
550}
551
552impl ToSql for MonotonicRawTime {
553 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
554 Ok(ToSqlOutput::Owned(Value::Integer(self.0)))
555 }
556}
557
558impl FromSql for MonotonicRawTime {
559 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
560 Ok(Self(i64::column_result(value)?))
561 }
562}
563
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000564/// This struct encapsulates the information to be stored in the database about the auth tokens
565/// received by keystore.
566pub struct AuthTokenEntry {
567 auth_token: HardwareAuthToken,
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000568 time_received: MonotonicRawTime,
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000569}
570
571impl AuthTokenEntry {
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000572 fn new(auth_token: HardwareAuthToken, time_received: MonotonicRawTime) -> Self {
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000573 AuthTokenEntry { auth_token, time_received }
574 }
575
576 /// Checks if this auth token satisfies the given authentication information.
577 pub fn satisfies_auth(
578 auth_token: &HardwareAuthToken,
579 user_secure_ids: &[i64],
580 auth_type: HardwareAuthenticatorType,
581 ) -> bool {
582 user_secure_ids.iter().any(|&sid| {
583 (sid == auth_token.userId || sid == auth_token.authenticatorId)
584 && (((auth_type.0 as i32) & (auth_token.authenticatorType.0 as i32)) != 0)
585 })
586 }
587
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000588 /// Returns the auth token wrapped by the AuthTokenEntry
589 pub fn get_auth_token(self) -> HardwareAuthToken {
590 self.auth_token
591 }
592}
593
Joel Galenson26f4d012020-07-17 14:57:21 -0700594impl KeystoreDB {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700595 /// This will create a new database connection connecting the two
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800596 /// files persistent.sqlite and perboot.sqlite in the given directory.
597 /// It also attempts to initialize all of the tables.
598 /// KeystoreDB cannot be used by multiple threads.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700599 /// Each thread should open their own connection using `thread_local!`.
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800600 pub fn new(db_root: &Path) -> Result<Self> {
601 // Build the path to the sqlite files.
602 let mut persistent_path = db_root.to_path_buf();
603 persistent_path.push("persistent.sqlite");
604 let mut perboot_path = db_root.to_path_buf();
605 perboot_path.push("perboot.sqlite");
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700606
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800607 // Now convert them to strings prefixed with "file:"
608 let mut persistent_path_str = "file:".to_owned();
609 persistent_path_str.push_str(&persistent_path.to_string_lossy());
610 let mut perboot_path_str = "file:".to_owned();
611 perboot_path_str.push_str(&perboot_path.to_string_lossy());
612
613 let conn = Self::make_connection(&persistent_path_str, &perboot_path_str)?;
614
615 Self::init_tables(&conn)?;
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700616 Ok(Self { conn })
Joel Galenson2aab4432020-07-22 15:27:57 -0700617 }
618
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700619 fn init_tables(conn: &Connection) -> Result<()> {
620 conn.execute(
621 "CREATE TABLE IF NOT EXISTS persistent.keyentry (
Joel Galenson0891bc12020-07-20 10:37:03 -0700622 id INTEGER UNIQUE,
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800623 key_type INTEGER,
Joel Galenson0891bc12020-07-20 10:37:03 -0700624 domain INTEGER,
625 namespace INTEGER,
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800626 alias BLOB,
627 state INTEGER);",
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700628 NO_PARAMS,
629 )
630 .context("Failed to initialize \"keyentry\" table.")?;
631
632 conn.execute(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700633 "CREATE TABLE IF NOT EXISTS persistent.blobentry (
634 id INTEGER PRIMARY KEY,
635 subcomponent_type INTEGER,
636 keyentryid INTEGER,
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800637 blob BLOB);",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700638 NO_PARAMS,
639 )
640 .context("Failed to initialize \"blobentry\" table.")?;
641
642 conn.execute(
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700643 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000644 keyentryid INTEGER,
645 tag INTEGER,
646 data ANY,
647 security_level INTEGER);",
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700648 NO_PARAMS,
649 )
650 .context("Failed to initialize \"keyparameter\" table.")?;
651
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700652 conn.execute(
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800653 "CREATE TABLE IF NOT EXISTS persistent.keymetadata (
654 keyentryid INTEGER,
655 tag INTEGER,
656 data ANY);",
657 NO_PARAMS,
658 )
659 .context("Failed to initialize \"keymetadata\" table.")?;
660
661 conn.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800662 "CREATE TABLE IF NOT EXISTS persistent.grant (
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700663 id INTEGER UNIQUE,
664 grantee INTEGER,
665 keyentryid INTEGER,
666 access_vector INTEGER);",
667 NO_PARAMS,
668 )
669 .context("Failed to initialize \"grant\" table.")?;
670
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000671 //TODO: only drop the following two perboot tables if this is the first start up
672 //during the boot (b/175716626).
673 // conn.execute("DROP TABLE IF EXISTS perboot.authtoken;", NO_PARAMS)
674 // .context("Failed to drop perboot.authtoken table")?;
675 conn.execute(
676 "CREATE TABLE IF NOT EXISTS perboot.authtoken (
677 id INTEGER PRIMARY KEY,
678 challenge INTEGER,
679 user_id INTEGER,
680 auth_id INTEGER,
681 authenticator_type INTEGER,
682 timestamp INTEGER,
683 mac BLOB,
684 time_received INTEGER,
685 UNIQUE(user_id, auth_id, authenticator_type));",
686 NO_PARAMS,
687 )
688 .context("Failed to initialize \"authtoken\" table.")?;
689
690 // conn.execute("DROP TABLE IF EXISTS perboot.metadata;", NO_PARAMS)
691 // .context("Failed to drop perboot.metadata table")?;
692 // metadata table stores certain miscellaneous information required for keystore functioning
693 // during a boot cycle, as key-value pairs.
694 conn.execute(
695 "CREATE TABLE IF NOT EXISTS perboot.metadata (
696 key TEXT,
697 value BLOB,
698 UNIQUE(key));",
699 NO_PARAMS,
700 )
701 .context("Failed to initialize \"metadata\" table.")?;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +0000702 // TODO: Add the initial entry on last_off_body to the metadata table during the boot of the
703 // device (i.e. during the first startup of the keystore during a boot cycle).
704 Self::insert_last_off_body(conn, MonotonicRawTime::now()).context("In init-tables.")?;
Joel Galenson0891bc12020-07-20 10:37:03 -0700705 Ok(())
706 }
707
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700708 fn make_connection(persistent_file: &str, perboot_file: &str) -> Result<Connection> {
709 let conn =
710 Connection::open_in_memory().context("Failed to initialize SQLite connection.")?;
711
712 conn.execute("ATTACH DATABASE ? as persistent;", params![persistent_file])
713 .context("Failed to attach database persistent.")?;
714 conn.execute("ATTACH DATABASE ? as perboot;", params![perboot_file])
715 .context("Failed to attach database perboot.")?;
716
717 Ok(conn)
718 }
719
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800720 /// Get one unreferenced key. There is no particular order in which the keys are returned.
721 fn get_unreferenced_key_id(tx: &Transaction) -> Result<Option<i64>> {
722 tx.query_row(
723 "SELECT id FROM persistent.keyentry WHERE state = ?",
724 params![KeyLifeCycle::Unreferenced],
725 |row| row.get(0),
726 )
727 .optional()
728 .context("In get_unreferenced_key_id: Trying to get unreferenced key id.")
729 }
730
731 /// Returns a key id guard and key entry for one unreferenced key entry. Of the optional
732 /// fields of the key entry only the km_blob field will be populated. This is required
733 /// to subject the blob to its KeyMint instance for deletion.
734 pub fn get_unreferenced_key(&mut self) -> Result<Option<(KeyIdGuard, KeyEntry)>> {
735 self.with_transaction(TransactionBehavior::Deferred, |tx| {
736 let key_id = match Self::get_unreferenced_key_id(tx)
737 .context("Trying to get unreferenced key id")?
738 {
739 None => return Ok(None),
740 Some(id) => KEY_ID_LOCK.try_get(id).ok_or_else(KsError::sys).context(concat!(
741 "A key id lock was held for an unreferenced key. ",
742 "This should never happen."
743 ))?,
744 };
745 let key_entry = Self::load_key_components(tx, KeyEntryLoadBits::KM, key_id.id())
746 .context("Trying to get key components.")?;
747 Ok(Some((key_id, key_entry)))
748 })
749 .context("In get_unreferenced_key.")
750 }
751
752 /// This function purges all remnants of a key entry from the database.
753 /// Important: This does not check if the key was unreferenced, nor does it
754 /// subject the key to its KeyMint instance for permanent invalidation.
755 /// This function should only be called by the garbage collector.
756 /// To delete a key call `mark_unreferenced`, which transitions the key to the unreferenced
757 /// state, deletes all grants to the key, and notifies the garbage collector.
758 /// The garbage collector will:
759 /// 1. Call get_unreferenced_key.
760 /// 2. Determine the proper way to dispose of sensitive key material, e.g., call
761 /// `KeyMintDevice::delete()`.
762 /// 3. Call `purge_key_entry`.
763 pub fn purge_key_entry(&mut self, key_id: KeyIdGuard) -> Result<()> {
764 self.with_transaction(TransactionBehavior::Immediate, |tx| {
765 tx.execute("DELETE FROM persistent.keyentry WHERE id = ?;", params![key_id.id()])
766 .context("Trying to delete keyentry.")?;
767 tx.execute(
768 "DELETE FROM persistent.blobentry WHERE keyentryid = ?;",
769 params![key_id.id()],
770 )
771 .context("Trying to delete blobentries.")?;
772 tx.execute(
773 "DELETE FROM persistent.keymetadata WHERE keyentryid = ?;",
774 params![key_id.id()],
775 )
776 .context("Trying to delete keymetadata.")?;
777 tx.execute(
778 "DELETE FROM persistent.keyparameter WHERE keyentryid = ?;",
779 params![key_id.id()],
780 )
781 .context("Trying to delete keyparameters.")?;
782 let grants_deleted = tx
783 .execute("DELETE FROM persistent.grant WHERE keyentryid = ?;", params![key_id.id()])
784 .context("Trying to delete grants.")?;
785 if grants_deleted != 0 {
786 log::error!("Purged key that still had grants. This should not happen.");
787 }
788 Ok(())
789 })
790 .context("In purge_key_entry.")
791 }
792
793 /// This maintenance function should be called only once before the database is used for the
794 /// first time. It restores the invariant that `KeyLifeCycle::Existing` is a transient state.
795 /// The function transitions all key entries from Existing to Unreferenced unconditionally and
796 /// returns the number of rows affected. If this returns a value greater than 0, it means that
797 /// Keystore crashed at some point during key generation. Callers may want to log such
798 /// occurrences.
799 /// Unlike with `mark_unreferenced`, we don't need to purge grants, because only keys that made
800 /// it to `KeyLifeCycle::Live` may have grants.
801 pub fn cleanup_leftovers(&mut self) -> Result<usize> {
802 self.conn
803 .execute(
804 "UPDATE persistent.keyentry SET state = ? WHERE state = ?;",
805 params![KeyLifeCycle::Unreferenced, KeyLifeCycle::Existing],
806 )
807 .context("In cleanup_leftovers.")
808 }
809
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800810 /// Atomically loads a key entry and associated metadata or creates it using the
811 /// callback create_new_key callback. The callback is called during a database
812 /// transaction. This means that implementers should be mindful about using
813 /// blocking operations such as IPC or grabbing mutexes.
814 pub fn get_or_create_key_with<F>(
815 &mut self,
816 domain: Domain,
817 namespace: i64,
818 alias: &str,
819 create_new_key: F,
820 ) -> Result<(KeyIdGuard, KeyEntry)>
821 where
822 F: FnOnce() -> Result<(Vec<u8>, KeyMetaData)>,
823 {
824 let tx = self
825 .conn
826 .transaction_with_behavior(TransactionBehavior::Immediate)
827 .context("In get_or_create_key_with: Failed to initialize transaction.")?;
828
829 let id = {
830 let mut stmt = tx
831 .prepare(
832 "SELECT id FROM persistent.keyentry
833 WHERE
834 key_type = ?
835 AND domain = ?
836 AND namespace = ?
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800837 AND alias = ?
838 AND state = ?;",
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800839 )
840 .context("In get_or_create_key_with: Failed to select from keyentry table.")?;
841 let mut rows = stmt
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800842 .query(params![KeyType::Super, domain.0, namespace, alias, KeyLifeCycle::Live])
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800843 .context("In get_or_create_key_with: Failed to query from keyentry table.")?;
844
845 db_utils::with_rows_extract_one(&mut rows, |row| {
846 Ok(match row {
847 Some(r) => r.get(0).context("Failed to unpack id.")?,
848 None => None,
849 })
850 })
851 .context("In get_or_create_key_with.")?
852 };
853
854 let (id, entry) = match id {
855 Some(id) => (
856 id,
857 Self::load_key_components(&tx, KeyEntryLoadBits::KM, id)
858 .context("In get_or_create_key_with.")?,
859 ),
860
861 None => {
862 let id = Self::insert_with_retry(|id| {
863 tx.execute(
864 "INSERT into persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800865 (id, key_type, domain, namespace, alias, state)
866 VALUES(?, ?, ?, ?, ?, ?);",
867 params![id, KeyType::Super, domain.0, namespace, alias, KeyLifeCycle::Live],
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800868 )
869 })
870 .context("In get_or_create_key_with.")?;
871
872 let (blob, metadata) = create_new_key().context("In get_or_create_key_with.")?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800873 Self::insert_blob_internal(&tx, id, SubComponentType::KEY_BLOB, &blob)
874 .context("In get_of_create_key_with.")?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800875 metadata.store_in_db(id, &tx).context("In get_or_create_key_with.")?;
876 (id, KeyEntry { id, km_blob: Some(blob), metadata, ..Default::default() })
877 }
878 };
879 tx.commit().context("In get_or_create_key_with: Failed to commit transaction.")?;
880 Ok((KEY_ID_LOCK.get(id), entry))
881 }
882
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800883 /// Creates a transaction with the given behavior and executes f with the new transaction.
884 /// The transaction is committed only if f returns Ok.
885 fn with_transaction<T, F>(&mut self, behavior: TransactionBehavior, f: F) -> Result<T>
886 where
887 F: FnOnce(&Transaction) -> Result<T>,
888 {
889 let tx = self
890 .conn
891 .transaction_with_behavior(behavior)
892 .context("In with_transaction: Failed to initialize transaction.")?;
893 f(&tx).and_then(|result| {
894 tx.commit().context("In with_transaction: Failed to commit transaction.")?;
895 Ok(result)
896 })
897 }
898
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700899 /// Creates a new key entry and allocates a new randomized id for the new key.
900 /// The key id gets associated with a domain and namespace but not with an alias.
901 /// To complete key generation `rebind_alias` should be called after all of the
902 /// key artifacts, i.e., blobs and parameters have been associated with the new
903 /// key id. Finalizing with `rebind_alias` makes the creation of a new key entry
904 /// atomic even if key generation is not.
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800905 pub fn create_key_entry(&mut self, domain: Domain, namespace: i64) -> Result<KeyIdGuard> {
906 self.with_transaction(TransactionBehavior::Immediate, |tx| {
907 Self::create_key_entry_internal(tx, domain, namespace)
908 })
909 .context("In create_key_entry.")
910 }
911
912 fn create_key_entry_internal(
913 tx: &Transaction,
914 domain: Domain,
915 namespace: i64,
916 ) -> Result<KeyIdGuard> {
Joel Galenson0891bc12020-07-20 10:37:03 -0700917 match domain {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700918 Domain::APP | Domain::SELINUX => {}
Joel Galenson0891bc12020-07-20 10:37:03 -0700919 _ => {
920 return Err(KsError::sys())
921 .context(format!("Domain {:?} must be either App or SELinux.", domain));
922 }
923 }
Janis Danisevskisaec14592020-11-12 09:41:49 -0800924 Ok(KEY_ID_LOCK.get(
925 Self::insert_with_retry(|id| {
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800926 tx.execute(
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800927 "INSERT into persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800928 (id, key_type, domain, namespace, alias, state)
929 VALUES(?, ?, ?, ?, NULL, ?);",
930 params![
931 id,
932 KeyType::Client,
933 domain.0 as u32,
934 namespace,
935 KeyLifeCycle::Existing
936 ],
Janis Danisevskisaec14592020-11-12 09:41:49 -0800937 )
938 })
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800939 .context("In create_key_entry_internal")?,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800940 ))
Joel Galenson26f4d012020-07-17 14:57:21 -0700941 }
Joel Galenson33c04ad2020-08-03 11:04:38 -0700942
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700943 /// Inserts a new blob and associates it with the given key id. Each blob
944 /// has a sub component type and a security level.
945 /// Each key can have one of each sub component type associated. If more
946 /// are added only the most recent can be retrieved, and superseded blobs
947 /// will get garbage collected. The security level field of components
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800948 /// other than `SubComponentType::KEY_BLOB` are ignored.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700949 pub fn insert_blob(
950 &mut self,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800951 key_id: &KeyIdGuard,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700952 sc_type: SubComponentType,
953 blob: &[u8],
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700954 ) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800955 self.with_transaction(TransactionBehavior::Immediate, |tx| {
956 Self::insert_blob_internal(&tx, key_id.0, sc_type, blob)
957 })
958 .context("In insert_blob.")
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800959 }
960
961 fn insert_blob_internal(
962 tx: &Transaction,
963 key_id: i64,
964 sc_type: SubComponentType,
965 blob: &[u8],
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800966 ) -> Result<()> {
967 tx.execute(
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800968 "INSERT into persistent.blobentry (subcomponent_type, keyentryid, blob)
969 VALUES (?, ?, ?);",
970 params![sc_type, key_id, blob],
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800971 )
972 .context("In insert_blob_internal: Failed to insert blob.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700973 Ok(())
974 }
975
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700976 /// Inserts a collection of key parameters into the `persistent.keyparameter` table
977 /// and associates them with the given `key_id`.
978 pub fn insert_keyparameter<'a>(
979 &mut self,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800980 key_id: &KeyIdGuard,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700981 params: impl IntoIterator<Item = &'a KeyParameter>,
982 ) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800983 self.with_transaction(TransactionBehavior::Immediate, |tx| {
984 Self::insert_keyparameter_internal(tx, key_id, params)
985 })
986 .context("In insert_keyparameter.")
987 }
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700988
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800989 fn insert_keyparameter_internal<'a>(
990 tx: &Transaction,
991 key_id: &KeyIdGuard,
992 params: impl IntoIterator<Item = &'a KeyParameter>,
993 ) -> Result<()> {
994 let mut stmt = tx
995 .prepare(
996 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
997 VALUES (?, ?, ?, ?);",
998 )
999 .context("In insert_keyparameter_internal: Failed to prepare statement.")?;
1000
1001 let iter = params.into_iter();
1002 for p in iter {
1003 stmt.insert(params![
1004 key_id.0,
1005 p.get_tag().0,
1006 p.key_parameter_value(),
1007 p.security_level().0
1008 ])
1009 .with_context(|| {
1010 format!("In insert_keyparameter_internal: Failed to insert {:?}", p)
1011 })?;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001012 }
1013 Ok(())
1014 }
1015
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001016 /// Insert a set of key entry specific metadata into the database.
1017 pub fn insert_key_metadata(
1018 &mut self,
1019 key_id: &KeyIdGuard,
1020 metadata: &KeyMetaData,
1021 ) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001022 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1023 metadata.store_in_db(key_id.0, &tx)
1024 })
1025 .context("In insert_key_metadata.")
1026 }
1027
1028 fn rebind_alias(
1029 &mut self,
1030 newid: &KeyIdGuard,
1031 alias: &str,
1032 domain: Domain,
1033 namespace: i64,
1034 ) -> Result<()> {
1035 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1036 Self::rebind_alias_internal(tx, newid, alias, domain, namespace)
1037 })
1038 .context("In rebind_alias.")
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001039 }
1040
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001041 /// Updates the alias column of the given key id `newid` with the given alias,
1042 /// and atomically, removes the alias, domain, and namespace from another row
1043 /// with the same alias-domain-namespace tuple if such row exits.
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001044 fn rebind_alias_internal(
1045 tx: &Transaction,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001046 newid: &KeyIdGuard,
Joel Galenson33c04ad2020-08-03 11:04:38 -07001047 alias: &str,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001048 domain: Domain,
Joel Galenson33c04ad2020-08-03 11:04:38 -07001049 namespace: i64,
1050 ) -> Result<()> {
1051 match domain {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001052 Domain::APP | Domain::SELINUX => {}
Joel Galenson33c04ad2020-08-03 11:04:38 -07001053 _ => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001054 return Err(KsError::sys()).context(format!(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001055 "In rebind_alias_internal: Domain {:?} must be either App or SELinux.",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001056 domain
1057 ));
Joel Galenson33c04ad2020-08-03 11:04:38 -07001058 }
1059 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001060 let updated = tx
1061 .execute(
1062 "UPDATE persistent.keyentry
1063 SET alias = NULL, domain = NULL, namespace = NULL, state = ?
Joel Galenson33c04ad2020-08-03 11:04:38 -07001064 WHERE alias = ? AND domain = ? AND namespace = ?;",
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001065 params![KeyLifeCycle::Unreferenced, alias, domain.0 as u32, namespace],
1066 )
1067 .context("In rebind_alias_internal: Failed to rebind existing entry.")?;
1068 if updated != 0 {
1069 Gc::notify_gc();
1070 }
Joel Galenson33c04ad2020-08-03 11:04:38 -07001071 let result = tx
1072 .execute(
1073 "UPDATE persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001074 SET alias = ?, state = ?
1075 WHERE id = ? AND domain = ? AND namespace = ? AND state = ?;",
1076 params![
1077 alias,
1078 KeyLifeCycle::Live,
1079 newid.0,
1080 domain.0 as u32,
1081 namespace,
1082 KeyLifeCycle::Existing
1083 ],
Joel Galenson33c04ad2020-08-03 11:04:38 -07001084 )
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001085 .context("In rebind_alias_internal: Failed to set alias.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07001086 if result != 1 {
Joel Galenson33c04ad2020-08-03 11:04:38 -07001087 return Err(KsError::sys()).context(format!(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001088 "In rebind_alias_internal: Expected to update a single entry but instead updated {}.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07001089 result
1090 ));
1091 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001092 Ok(())
1093 }
1094
1095 /// Store a new key in a single transaction.
1096 /// The function creates a new key entry, populates the blob, key parameter, and metadata
1097 /// fields, and rebinds the given alias to the new key.
1098 pub fn store_new_key<'a>(
1099 &mut self,
1100 key: KeyDescriptor,
1101 params: impl IntoIterator<Item = &'a KeyParameter>,
1102 blob: &[u8],
1103 cert: Option<&[u8]>,
1104 cert_chain: Option<&[u8]>,
1105 metadata: &KeyMetaData,
1106 ) -> Result<KeyIdGuard> {
1107 let (alias, domain, namespace) = match key {
1108 KeyDescriptor { alias: Some(alias), domain: Domain::APP, nspace, blob: None }
1109 | KeyDescriptor { alias: Some(alias), domain: Domain::SELINUX, nspace, blob: None } => {
1110 (alias, key.domain, nspace)
1111 }
1112 _ => {
1113 return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT))
1114 .context("In store_new_key: Need alias and domain must be APP or SELINUX.")
1115 }
1116 };
1117 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1118 let key_id = Self::create_key_entry_internal(tx, domain, namespace)
1119 .context("Trying to create new key entry.")?;
1120 Self::insert_blob_internal(tx, key_id.id(), SubComponentType::KEY_BLOB, blob)
1121 .context("Trying to insert the key blob.")?;
1122 if let Some(cert) = cert {
1123 Self::insert_blob_internal(tx, key_id.id(), SubComponentType::CERT, cert)
1124 .context("Trying to insert the certificate.")?;
1125 }
1126 if let Some(cert_chain) = cert_chain {
1127 Self::insert_blob_internal(
1128 tx,
1129 key_id.id(),
1130 SubComponentType::CERT_CHAIN,
1131 cert_chain,
1132 )
1133 .context("Trying to insert the certificate chain.")?;
1134 }
1135 Self::insert_keyparameter_internal(tx, &key_id, params)
1136 .context("Trying to insert key parameters.")?;
1137 metadata.store_in_db(key_id.id(), tx).context("Tryin to insert key metadata.")?;
1138 Self::rebind_alias_internal(tx, &key_id, &alias, domain, namespace)
1139 .context("Trying to rebind alias.")?;
1140 Ok(key_id)
1141 })
1142 .context("In store_new_key.")
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001143 }
1144
1145 // Helper function loading the key_id given the key descriptor
1146 // tuple comprising domain, namespace, and alias.
1147 // Requires a valid transaction.
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001148 fn load_key_entry_id(tx: &Transaction, key: &KeyDescriptor, key_type: KeyType) -> Result<i64> {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001149 let alias = key
1150 .alias
1151 .as_ref()
1152 .map_or_else(|| Err(KsError::sys()), Ok)
1153 .context("In load_key_entry_id: Alias must be specified.")?;
1154 let mut stmt = tx
1155 .prepare(
1156 "SELECT id FROM persistent.keyentry
1157 WHERE
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001158 key_type = ?
1159 AND domain = ?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001160 AND namespace = ?
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001161 AND alias = ?
1162 AND state = ?;",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001163 )
1164 .context("In load_key_entry_id: Failed to select from keyentry table.")?;
1165 let mut rows = stmt
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001166 .query(params![key_type, key.domain.0 as u32, key.nspace, alias, KeyLifeCycle::Live])
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001167 .context("In load_key_entry_id: Failed to read from keyentry table.")?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001168 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001169 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001170 .get(0)
1171 .context("Failed to unpack id.")
1172 })
1173 .context("In load_key_entry_id.")
1174 }
1175
1176 /// This helper function completes the access tuple of a key, which is required
1177 /// to perform access control. The strategy depends on the `domain` field in the
1178 /// key descriptor.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001179 /// * Domain::SELINUX: The access tuple is complete and this function only loads
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001180 /// the key_id for further processing.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001181 /// * Domain::APP: Like Domain::SELINUX, but the tuple is completed by `caller_uid`
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001182 /// which serves as the namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001183 /// * Domain::GRANT: The grant table is queried for the `key_id` and the
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001184 /// `access_vector`.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001185 /// * Domain::KEY_ID: The keyentry table is queried for the owning `domain` and
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001186 /// `namespace`.
1187 /// In each case the information returned is sufficient to perform the access
1188 /// check and the key id can be used to load further key artifacts.
1189 fn load_access_tuple(
1190 tx: &Transaction,
1191 key: KeyDescriptor,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001192 key_type: KeyType,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001193 caller_uid: u32,
1194 ) -> Result<(i64, KeyDescriptor, Option<KeyPermSet>)> {
1195 match key.domain {
1196 // Domain App or SELinux. In this case we load the key_id from
1197 // the keyentry database for further loading of key components.
1198 // We already have the full access tuple to perform access control.
1199 // The only distinction is that we use the caller_uid instead
1200 // of the caller supplied namespace if the domain field is
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001201 // Domain::APP.
1202 Domain::APP | Domain::SELINUX => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001203 let mut access_key = key;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001204 if access_key.domain == Domain::APP {
1205 access_key.nspace = caller_uid as i64;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001206 }
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001207 let key_id = Self::load_key_entry_id(&tx, &access_key, key_type)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001208 .with_context(|| format!("With key.domain = {:?}.", access_key.domain))?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001209
1210 Ok((key_id, access_key, None))
1211 }
1212
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001213 // Domain::GRANT. In this case we load the key_id and the access_vector
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001214 // from the grant table.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001215 Domain::GRANT => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001216 let mut stmt = tx
1217 .prepare(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001218 "SELECT keyentryid, access_vector FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001219 WHERE grantee = ? AND id = ?;",
1220 )
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001221 .context("Domain::GRANT prepare statement failed")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001222 let mut rows = stmt
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001223 .query(params![caller_uid as i64, key.nspace])
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001224 .context("Domain:Grant: query failed.")?;
1225 let (key_id, access_vector): (i64, i32) =
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001226 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001227 let r =
1228 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001229 Ok((
1230 r.get(0).context("Failed to unpack key_id.")?,
1231 r.get(1).context("Failed to unpack access_vector.")?,
1232 ))
1233 })
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001234 .context("Domain::GRANT.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001235 Ok((key_id, key, Some(access_vector.into())))
1236 }
1237
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001238 // Domain::KEY_ID. In this case we load the domain and namespace from the
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001239 // keyentry database because we need them for access control.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001240 Domain::KEY_ID => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001241 let mut stmt = tx
1242 .prepare(
1243 "SELECT domain, namespace FROM persistent.keyentry
1244 WHERE
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001245 id = ?
1246 AND state = ?;",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001247 )
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001248 .context("Domain::KEY_ID: prepare statement failed")?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001249 let mut rows = stmt
1250 .query(params![key.nspace, KeyLifeCycle::Live])
1251 .context("Domain::KEY_ID: query failed.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001252 let (domain, namespace): (Domain, i64) =
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001253 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001254 let r =
1255 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001256 Ok((
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001257 Domain(r.get(0).context("Failed to unpack domain.")?),
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001258 r.get(1).context("Failed to unpack namespace.")?,
1259 ))
1260 })
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001261 .context("Domain::KEY_ID.")?;
1262 let key_id = key.nspace;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001263 let mut access_key = key;
1264 access_key.domain = domain;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001265 access_key.nspace = namespace;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001266
1267 Ok((key_id, access_key, None))
1268 }
1269 _ => Err(anyhow!(KsError::sys())),
1270 }
1271 }
1272
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001273 fn load_blob_components(
1274 key_id: i64,
1275 load_bits: KeyEntryLoadBits,
1276 tx: &Transaction,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001277 ) -> Result<(Option<Vec<u8>>, Option<Vec<u8>>, Option<Vec<u8>>)> {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001278 let mut stmt = tx
1279 .prepare(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001280 "SELECT MAX(id), subcomponent_type, blob FROM persistent.blobentry
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001281 WHERE keyentryid = ? GROUP BY subcomponent_type;",
1282 )
1283 .context("In load_blob_components: prepare statement failed.")?;
1284
1285 let mut rows =
1286 stmt.query(params![key_id]).context("In load_blob_components: query failed.")?;
1287
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001288 let mut km_blob: Option<Vec<u8>> = None;
1289 let mut cert_blob: Option<Vec<u8>> = None;
1290 let mut cert_chain_blob: Option<Vec<u8>> = None;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001291 db_utils::with_rows_extract_all(&mut rows, |row| {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001292 let sub_type: SubComponentType =
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001293 row.get(1).context("Failed to extract subcomponent_type.")?;
1294 match (sub_type, load_bits.load_public(), load_bits.load_km()) {
1295 (SubComponentType::KEY_BLOB, _, true) => {
1296 km_blob = Some(row.get(2).context("Failed to extract KM blob.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001297 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001298 (SubComponentType::CERT, true, _) => {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001299 cert_blob =
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001300 Some(row.get(2).context("Failed to extract public certificate blob.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001301 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001302 (SubComponentType::CERT_CHAIN, true, _) => {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001303 cert_chain_blob =
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001304 Some(row.get(2).context("Failed to extract certificate chain blob.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001305 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001306 (SubComponentType::CERT, _, _)
1307 | (SubComponentType::CERT_CHAIN, _, _)
1308 | (SubComponentType::KEY_BLOB, _, _) => {}
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001309 _ => Err(KsError::sys()).context("Unknown subcomponent type.")?,
1310 }
1311 Ok(())
1312 })
1313 .context("In load_blob_components.")?;
1314
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001315 Ok((km_blob, cert_blob, cert_chain_blob))
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001316 }
1317
1318 fn load_key_parameters(key_id: i64, tx: &Transaction) -> Result<Vec<KeyParameter>> {
1319 let mut stmt = tx
1320 .prepare(
1321 "SELECT tag, data, security_level from persistent.keyparameter
1322 WHERE keyentryid = ?;",
1323 )
1324 .context("In load_key_parameters: prepare statement failed.")?;
1325
1326 let mut parameters: Vec<KeyParameter> = Vec::new();
1327
1328 let mut rows =
1329 stmt.query(params![key_id]).context("In load_key_parameters: query failed.")?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001330 db_utils::with_rows_extract_all(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001331 let tag = Tag(row.get(0).context("Failed to read tag.")?);
1332 let sec_level = SecurityLevel(row.get(2).context("Failed to read sec_level.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001333 parameters.push(
1334 KeyParameter::new_from_sql(tag, &SqlField::new(1, &row), sec_level)
1335 .context("Failed to read KeyParameter.")?,
1336 );
1337 Ok(())
1338 })
1339 .context("In load_key_parameters.")?;
1340
1341 Ok(parameters)
1342 }
1343
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001344 /// Load a key entry by the given key descriptor.
1345 /// It uses the `check_permission` callback to verify if the access is allowed
1346 /// given the key access tuple read from the database using `load_access_tuple`.
1347 /// With `load_bits` the caller may specify which blobs shall be loaded from
1348 /// the blob database.
1349 pub fn load_key_entry(
1350 &mut self,
1351 key: KeyDescriptor,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001352 key_type: KeyType,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001353 load_bits: KeyEntryLoadBits,
1354 caller_uid: u32,
1355 check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001356 ) -> Result<(KeyIdGuard, KeyEntry)> {
1357 // KEY ID LOCK 1/2
1358 // If we got a key descriptor with a key id we can get the lock right away.
1359 // Otherwise we have to defer it until we know the key id.
1360 let key_id_guard = match key.domain {
1361 Domain::KEY_ID => Some(KEY_ID_LOCK.get(key.nspace)),
1362 _ => None,
1363 };
1364
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001365 let tx = self
1366 .conn
Janis Danisevskisaec14592020-11-12 09:41:49 -08001367 .unchecked_transaction()
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001368 .context("In load_key_entry: Failed to initialize transaction.")?;
1369
1370 // Load the key_id and complete the access control tuple.
1371 let (key_id, access_key_descriptor, access_vector) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001372 Self::load_access_tuple(&tx, key, key_type, caller_uid)
1373 .context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001374
1375 // Perform access control. It is vital that we return here if the permission is denied.
1376 // So do not touch that '?' at the end.
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001377 check_permission(&access_key_descriptor, access_vector).context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001378
Janis Danisevskisaec14592020-11-12 09:41:49 -08001379 // KEY ID LOCK 2/2
1380 // If we did not get a key id lock by now, it was because we got a key descriptor
1381 // without a key id. At this point we got the key id, so we can try and get a lock.
1382 // However, we cannot block here, because we are in the middle of the transaction.
1383 // So first we try to get the lock non blocking. If that fails, we roll back the
1384 // transaction and block until we get the lock. After we successfully got the lock,
1385 // we start a new transaction and load the access tuple again.
1386 //
1387 // We don't need to perform access control again, because we already established
1388 // that the caller had access to the given key. But we need to make sure that the
1389 // key id still exists. So we have to load the key entry by key id this time.
1390 let (key_id_guard, tx) = match key_id_guard {
1391 None => match KEY_ID_LOCK.try_get(key_id) {
1392 None => {
1393 // Roll back the transaction.
1394 tx.rollback().context("In load_key_entry: Failed to roll back transaction.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001395
Janis Danisevskisaec14592020-11-12 09:41:49 -08001396 // Block until we have a key id lock.
1397 let key_id_guard = KEY_ID_LOCK.get(key_id);
1398
1399 // Create a new transaction.
1400 let tx = self.conn.unchecked_transaction().context(
1401 "In load_key_entry: Failed to initialize transaction. (deferred key lock)",
1402 )?;
1403
1404 Self::load_access_tuple(
1405 &tx,
1406 // This time we have to load the key by the retrieved key id, because the
1407 // alias may have been rebound after we rolled back the transaction.
1408 KeyDescriptor {
1409 domain: Domain::KEY_ID,
1410 nspace: key_id,
1411 ..Default::default()
1412 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001413 key_type,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001414 caller_uid,
1415 )
1416 .context("In load_key_entry. (deferred key lock)")?;
1417 (key_id_guard, tx)
1418 }
1419 Some(l) => (l, tx),
1420 },
1421 Some(key_id_guard) => (key_id_guard, tx),
1422 };
1423
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001424 let key_entry = Self::load_key_components(&tx, load_bits, key_id_guard.id())
1425 .context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001426
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001427 tx.commit().context("In load_key_entry: Failed to commit transaction.")?;
1428
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001429 Ok((key_id_guard, key_entry))
1430 }
1431
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001432 fn mark_unreferenced(tx: &Transaction, key_id: i64) -> Result<()> {
1433 let updated = tx
1434 .execute(
1435 "UPDATE persistent.keyentry SET state = ? WHERE id = ?;",
1436 params![KeyLifeCycle::Unreferenced, key_id],
1437 )
1438 .context("In mark_unreferenced: Failed to update state of key entry.")?;
1439 if updated != 0 {
1440 Gc::notify_gc();
1441 }
1442 tx.execute("DELETE from persistent.grant WHERE keyentryid = ?;", params![key_id])
1443 .context("In mark_unreferenced: Failed to drop grants.")?;
1444 Ok(())
1445 }
1446
1447 /// Marks the given key as unreferenced and removes all of the grants to this key.
1448 pub fn unbind_key(
1449 &mut self,
1450 key: KeyDescriptor,
1451 key_type: KeyType,
1452 caller_uid: u32,
1453 check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
1454 ) -> Result<()> {
1455 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1456 let (key_id, access_key_descriptor, access_vector) =
1457 Self::load_access_tuple(tx, key, key_type, caller_uid)
1458 .context("Trying to get access tuple.")?;
1459
1460 // Perform access control. It is vital that we return here if the permission is denied.
1461 // So do not touch that '?' at the end.
1462 check_permission(&access_key_descriptor, access_vector)
1463 .context("While checking permission.")?;
1464
1465 Self::mark_unreferenced(tx, key_id).context("Trying to mark the key unreferenced.")
1466 })
1467 .context("In unbind_key.")
1468 }
1469
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001470 fn load_key_components(
1471 tx: &Transaction,
1472 load_bits: KeyEntryLoadBits,
1473 key_id: i64,
1474 ) -> Result<KeyEntry> {
1475 let metadata = KeyMetaData::load_from_db(key_id, &tx).context("In load_key_components.")?;
1476
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001477 let (km_blob, cert_blob, cert_chain_blob) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001478 Self::load_blob_components(key_id, load_bits, &tx)
1479 .context("In load_key_components.")?;
1480
1481 let parameters =
1482 Self::load_key_parameters(key_id, &tx).context("In load_key_components.")?;
1483
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001484 // Extract the security level by checking the security level of the origin tag.
1485 // Super keys don't have key parameters so we use security_level software by default.
1486 let sec_level = parameters
1487 .iter()
1488 .find_map(|k| match k.get_tag() {
1489 Tag::ORIGIN => Some(*k.security_level()),
1490 _ => None,
1491 })
1492 .unwrap_or(SecurityLevel::SOFTWARE);
1493
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001494 Ok(KeyEntry {
1495 id: key_id,
1496 km_blob,
1497 cert: cert_blob,
1498 cert_chain: cert_chain_blob,
1499 sec_level,
1500 parameters,
1501 metadata,
1502 })
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001503 }
1504
Janis Danisevskise92a5e62020-12-02 12:57:41 -08001505 /// Returns a list of KeyDescriptors in the selected domain/namespace.
1506 /// The key descriptors will have the domain, nspace, and alias field set.
1507 /// Domain must be APP or SELINUX, the caller must make sure of that.
1508 pub fn list(&mut self, domain: Domain, namespace: i64) -> Result<Vec<KeyDescriptor>> {
1509 let mut stmt = self
1510 .conn
1511 .prepare(
1512 "SELECT alias FROM persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001513 WHERE domain = ? AND namespace = ? AND alias IS NOT NULL AND state = ?;",
Janis Danisevskise92a5e62020-12-02 12:57:41 -08001514 )
1515 .context("In list: Failed to prepare.")?;
1516
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001517 let mut rows = stmt
1518 .query(params![domain.0 as u32, namespace, KeyLifeCycle::Live])
1519 .context("In list: Failed to query.")?;
Janis Danisevskise92a5e62020-12-02 12:57:41 -08001520
1521 let mut descriptors: Vec<KeyDescriptor> = Vec::new();
1522 db_utils::with_rows_extract_all(&mut rows, |row| {
1523 descriptors.push(KeyDescriptor {
1524 domain,
1525 nspace: namespace,
1526 alias: Some(row.get(0).context("Trying to extract alias.")?),
1527 blob: None,
1528 });
1529 Ok(())
1530 })
1531 .context("In list.")?;
1532 Ok(descriptors)
1533 }
1534
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001535 /// Adds a grant to the grant table.
1536 /// Like `load_key_entry` this function loads the access tuple before
1537 /// it uses the callback for a permission check. Upon success,
1538 /// it inserts the `grantee_uid`, `key_id`, and `access_vector` into the
1539 /// grant table. The new row will have a randomized id, which is used as
1540 /// grant id in the namespace field of the resulting KeyDescriptor.
1541 pub fn grant(
1542 &mut self,
1543 key: KeyDescriptor,
1544 caller_uid: u32,
1545 grantee_uid: u32,
1546 access_vector: KeyPermSet,
1547 check_permission: impl FnOnce(&KeyDescriptor, &KeyPermSet) -> Result<()>,
1548 ) -> Result<KeyDescriptor> {
1549 let tx = self
1550 .conn
1551 .transaction_with_behavior(TransactionBehavior::Immediate)
1552 .context("In grant: Failed to initialize transaction.")?;
1553
1554 // Load the key_id and complete the access control tuple.
1555 // We ignore the access vector here because grants cannot be granted.
1556 // The access vector returned here expresses the permissions the
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001557 // grantee has if key.domain == Domain::GRANT. But this vector
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001558 // cannot include the grant permission by design, so there is no way the
1559 // subsequent permission check can pass.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001560 // We could check key.domain == Domain::GRANT and fail early.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001561 // But even if we load the access tuple by grant here, the permission
1562 // check denies the attempt to create a grant by grant descriptor.
1563 let (key_id, access_key_descriptor, _) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001564 Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid).context("In grant")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001565
1566 // Perform access control. It is vital that we return here if the permission
1567 // was denied. So do not touch that '?' at the end of the line.
1568 // This permission check checks if the caller has the grant permission
1569 // for the given key and in addition to all of the permissions
1570 // expressed in `access_vector`.
1571 check_permission(&access_key_descriptor, &access_vector)
1572 .context("In grant: check_permission failed.")?;
1573
1574 let grant_id = if let Some(grant_id) = tx
1575 .query_row(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001576 "SELECT id FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001577 WHERE keyentryid = ? AND grantee = ?;",
1578 params![key_id, grantee_uid],
1579 |row| row.get(0),
1580 )
1581 .optional()
1582 .context("In grant: Failed get optional existing grant id.")?
1583 {
1584 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001585 "UPDATE persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001586 SET access_vector = ?
1587 WHERE id = ?;",
1588 params![i32::from(access_vector), grant_id],
1589 )
1590 .context("In grant: Failed to update existing grant.")?;
1591 grant_id
1592 } else {
Joel Galenson845f74b2020-09-09 14:11:55 -07001593 Self::insert_with_retry(|id| {
1594 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001595 "INSERT INTO persistent.grant (id, grantee, keyentryid, access_vector)
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001596 VALUES (?, ?, ?, ?);",
Joel Galenson845f74b2020-09-09 14:11:55 -07001597 params![id, grantee_uid, key_id, i32::from(access_vector)],
1598 )
1599 })
1600 .context("In grant")?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001601 };
1602 tx.commit().context("In grant: failed to commit transaction.")?;
1603
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001604 Ok(KeyDescriptor { domain: Domain::GRANT, nspace: grant_id, alias: None, blob: None })
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001605 }
1606
1607 /// This function checks permissions like `grant` and `load_key_entry`
1608 /// before removing a grant from the grant table.
1609 pub fn ungrant(
1610 &mut self,
1611 key: KeyDescriptor,
1612 caller_uid: u32,
1613 grantee_uid: u32,
1614 check_permission: impl FnOnce(&KeyDescriptor) -> Result<()>,
1615 ) -> Result<()> {
1616 let tx = self
1617 .conn
1618 .transaction_with_behavior(TransactionBehavior::Immediate)
1619 .context("In ungrant: Failed to initialize transaction.")?;
1620
1621 // Load the key_id and complete the access control tuple.
1622 // We ignore the access vector here because grants cannot be granted.
1623 let (key_id, access_key_descriptor, _) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001624 Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid)
1625 .context("In ungrant.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001626
1627 // Perform access control. We must return here if the permission
1628 // was denied. So do not touch the '?' at the end of this line.
1629 check_permission(&access_key_descriptor).context("In grant: check_permission failed.")?;
1630
1631 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001632 "DELETE FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001633 WHERE keyentryid = ? AND grantee = ?;",
1634 params![key_id, grantee_uid],
1635 )
1636 .context("Failed to delete grant.")?;
1637
1638 tx.commit().context("In ungrant: failed to commit transaction.")?;
1639
1640 Ok(())
1641 }
1642
Joel Galenson845f74b2020-09-09 14:11:55 -07001643 // Generates a random id and passes it to the given function, which will
1644 // try to insert it into a database. If that insertion fails, retry;
1645 // otherwise return the id.
1646 fn insert_with_retry(inserter: impl Fn(i64) -> rusqlite::Result<usize>) -> Result<i64> {
1647 loop {
1648 let newid: i64 = random();
1649 match inserter(newid) {
1650 // If the id already existed, try again.
1651 Err(rusqlite::Error::SqliteFailure(
1652 libsqlite3_sys::Error {
1653 code: libsqlite3_sys::ErrorCode::ConstraintViolation,
1654 extended_code: libsqlite3_sys::SQLITE_CONSTRAINT_UNIQUE,
1655 },
1656 _,
1657 )) => (),
1658 Err(e) => {
1659 return Err(e).context("In insert_with_retry: failed to insert into database.")
1660 }
1661 _ => return Ok(newid),
1662 }
1663 }
1664 }
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001665
1666 /// Insert or replace the auth token based on the UNIQUE constraint of the auth token table
1667 pub fn insert_auth_token(&mut self, auth_token: &HardwareAuthToken) -> Result<()> {
1668 self.conn
1669 .execute(
1670 "INSERT OR REPLACE INTO perboot.authtoken (challenge, user_id, auth_id,
1671 authenticator_type, timestamp, mac, time_received) VALUES(?, ?, ?, ?, ?, ?, ?);",
1672 params![
1673 auth_token.challenge,
1674 auth_token.userId,
1675 auth_token.authenticatorId,
1676 auth_token.authenticatorType.0 as i32,
1677 auth_token.timestamp.milliSeconds as i64,
1678 auth_token.mac,
1679 MonotonicRawTime::now(),
1680 ],
1681 )
1682 .context("In insert_auth_token: failed to insert auth token into the database")?;
1683 Ok(())
1684 }
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001685
1686 /// find the auth token entry issued for a time-out token
1687 pub fn find_timed_auth_token_entry(
1688 &mut self,
1689 user_secure_ids: &[i64],
1690 auth_type: HardwareAuthenticatorType,
1691 key_time_out: i64,
1692 allow_while_on_body: bool,
1693 ) -> Result<AuthTokenEntry> {
1694 let tx = self
1695 .conn
1696 .transaction_with_behavior(TransactionBehavior::Immediate)
1697 .context("In find_timed_auth_token_entry: failed to initialize transaction.")?;
1698 let auth_token_entries =
1699 Self::load_auth_token_entries(&tx).context("In find_timed_auth_token_entry.")?;
1700 // NOTE: Although in legacy keystore both timestamp and time_received are used when finding
1701 // the newest match, we decided to only consider time_received in keystore2 code.
1702 // TODO: verify that the iter().find() preserves the order.
1703 let newest_match: Option<AuthTokenEntry> = auth_token_entries.into_iter().find(|entry| {
1704 AuthTokenEntry::satisfies_auth(&entry.auth_token, user_secure_ids, auth_type)
1705 });
1706
1707 // Tag::ALLOW_WHILE_ON_BODY specifies that the key may be used after authentication
1708 // timeout if device is still on-body. So we return error only if both checks fail.
1709 if let Some(newest_match_entry) = newest_match {
1710 let current_time = MonotonicRawTime::now();
1711 let time_since_received_plus_time_out =
1712 match newest_match_entry.time_received.seconds().checked_add(key_time_out) {
1713 Some(t) => t,
1714 None => {
1715 // we do not expect this behavior, so we need to log this error if it ever
1716 // happens.
1717 error!("In find_timed_auth_token_entry: overflow occurred.");
1718 return Err(KsError::Km(Ec::KEY_USER_NOT_AUTHENTICATED)).context(
1719 "In find_timed_auth_token_entry: matching auth token is expired.",
1720 );
1721 }
1722 };
1723 if (time_since_received_plus_time_out < current_time.seconds())
1724 && (!allow_while_on_body
1725 || (newest_match_entry.time_received.seconds()
1726 < Self::get_last_off_body(&tx)?.seconds()))
1727 {
1728 return Err(KsError::Km(Ec::KEY_USER_NOT_AUTHENTICATED))
1729 .context("In find_timed_auth_token_entry: matching auth token is expired.");
1730 }
1731 tx.commit().context("In find_timed_auth_token_entry, failed to commit transaction.")?;
1732 Ok(newest_match_entry)
1733 } else {
1734 Err(KsError::Km(Ec::KEY_USER_NOT_AUTHENTICATED))
1735 .context("In find_timed_auth_token_entry: no matching auth token found.")
1736 }
1737 }
1738
1739 /// load the existing auth token entries in perboot.authtoken table into a vector.
1740 /// return None if the table is empty.
1741 fn load_auth_token_entries(tx: &Transaction) -> Result<Vec<AuthTokenEntry>> {
1742 let mut stmt = tx
1743 .prepare("SELECT * from perboot.authtoken ORDER BY time_received DESC;")
1744 .context("In load_auth_token_entries: select prepare statement failed.")?;
1745
1746 let auth_token_entries: Vec<AuthTokenEntry> = stmt
1747 .query_map(NO_PARAMS, |row| {
1748 Ok(AuthTokenEntry::new(
1749 HardwareAuthToken {
1750 challenge: row.get(1)?,
1751 userId: row.get(2)?,
1752 authenticatorId: row.get(3)?,
1753 authenticatorType: HardwareAuthenticatorType(row.get(4)?),
1754 timestamp: Timestamp { milliSeconds: row.get(5)? },
1755 mac: row.get(6)?,
1756 },
1757 row.get(7)?,
1758 ))
1759 })
1760 .context("In load_auth_token_entries: query_map failed.")?
1761 .collect::<Result<Vec<AuthTokenEntry>, Error>>()
1762 .context(
1763 "In load_auth_token_entries: failed to create a vector of auth token entries
1764 from mapped rows.",
1765 )?;
1766 Ok(auth_token_entries)
1767 }
1768
1769 /// insert last_off_body into the metadata table at the initialization of auth token table
1770 pub fn insert_last_off_body(conn: &Connection, last_off_body: MonotonicRawTime) -> Result<()> {
1771 conn.execute(
1772 "INSERT OR REPLACE INTO perboot.metadata (key, value) VALUES (?, ?);",
1773 params!["last_off_body", last_off_body],
1774 )
1775 .context("In insert_last_off_body: failed to insert.")?;
1776 Ok(())
1777 }
1778
1779 /// update last_off_body when on_device_off_body is called
1780 pub fn update_last_off_body(&self, last_off_body: MonotonicRawTime) -> Result<()> {
1781 self.conn
1782 .execute(
1783 "UPDATE perboot.metadata SET value = ? WHERE key = ?;",
1784 params![last_off_body, "last_off_body"],
1785 )
1786 .context("In update_last_off_body: failed to update.")?;
1787 Ok(())
1788 }
1789
1790 /// get last_off_body time when finding auth tokens
1791 fn get_last_off_body(tx: &Transaction) -> Result<MonotonicRawTime> {
1792 let mut stmt = tx
1793 .prepare("SELECT value from perboot.metadata WHERE key = ?;")
1794 .context("In get_last_off_body: select prepare statement failed.")?;
1795 let last_off_body: Result<MonotonicRawTime> = stmt
1796 .query_row(params!["last_off_body"], |row| Ok(row.get(0)?))
1797 .context("In get_last_off_body: query_row failed.");
1798 last_off_body
1799 }
Joel Galenson26f4d012020-07-17 14:57:21 -07001800}
1801
1802#[cfg(test)]
1803mod tests {
1804
1805 use super::*;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001806 use crate::key_parameter::{
1807 Algorithm, BlockMode, Digest, EcCurve, HardwareAuthenticatorType, KeyOrigin, KeyParameter,
1808 KeyParameterValue, KeyPurpose, PaddingMode, SecurityLevel,
1809 };
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001810 use crate::key_perm_set;
1811 use crate::permission::{KeyPerm, KeyPermSet};
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001812 use crate::test::utils::TempDir;
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001813 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
1814 HardwareAuthToken::HardwareAuthToken,
1815 HardwareAuthenticatorType::HardwareAuthenticatorType as kmhw_authenticator_type,
Janis Danisevskisc3a496b2021-01-05 10:37:22 -08001816 };
1817 use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001818 Timestamp::Timestamp,
1819 };
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001820 use rusqlite::NO_PARAMS;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001821 use rusqlite::{Error, TransactionBehavior};
Joel Galenson0891bc12020-07-20 10:37:03 -07001822 use std::cell::RefCell;
Janis Danisevskisaec14592020-11-12 09:41:49 -08001823 use std::sync::atomic::{AtomicU8, Ordering};
1824 use std::sync::Arc;
1825 use std::thread;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001826 use std::time::{Duration, SystemTime};
Joel Galenson0891bc12020-07-20 10:37:03 -07001827
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001828 fn new_test_db() -> Result<KeystoreDB> {
1829 let conn = KeystoreDB::make_connection("file::memory:", "file::memory:")?;
1830
1831 KeystoreDB::init_tables(&conn).context("Failed to initialize tables.")?;
1832 Ok(KeystoreDB { conn })
1833 }
1834
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001835 #[test]
1836 fn datetime() -> Result<()> {
1837 let conn = Connection::open_in_memory()?;
1838 conn.execute("CREATE TABLE test (ts DATETIME);", NO_PARAMS)?;
1839 let now = SystemTime::now();
1840 let duration = Duration::from_secs(1000);
1841 let then = now.checked_sub(duration).unwrap();
1842 let soon = now.checked_add(duration).unwrap();
1843 conn.execute(
1844 "INSERT INTO test (ts) VALUES (?), (?), (?);",
1845 params![DateTime::try_from(now)?, DateTime::try_from(then)?, DateTime::try_from(soon)?],
1846 )?;
1847 let mut stmt = conn.prepare("SELECT ts FROM test ORDER BY ts ASC;")?;
1848 let mut rows = stmt.query(NO_PARAMS)?;
1849 assert_eq!(DateTime::try_from(then)?, rows.next()?.unwrap().get(0)?);
1850 assert_eq!(DateTime::try_from(now)?, rows.next()?.unwrap().get(0)?);
1851 assert_eq!(DateTime::try_from(soon)?, rows.next()?.unwrap().get(0)?);
1852 assert!(rows.next()?.is_none());
1853 assert!(DateTime::try_from(then)? < DateTime::try_from(now)?);
1854 assert!(DateTime::try_from(then)? < DateTime::try_from(soon)?);
1855 assert!(DateTime::try_from(now)? < DateTime::try_from(soon)?);
1856 Ok(())
1857 }
1858
Joel Galenson0891bc12020-07-20 10:37:03 -07001859 // Ensure that we're using the "injected" random function, not the real one.
1860 #[test]
1861 fn test_mocked_random() {
1862 let rand1 = random();
1863 let rand2 = random();
1864 let rand3 = random();
1865 if rand1 == rand2 {
1866 assert_eq!(rand2 + 1, rand3);
1867 } else {
1868 assert_eq!(rand1 + 1, rand2);
1869 assert_eq!(rand2, rand3);
1870 }
1871 }
Joel Galenson26f4d012020-07-17 14:57:21 -07001872
Joel Galenson26f4d012020-07-17 14:57:21 -07001873 // Test that we have the correct tables.
1874 #[test]
1875 fn test_tables() -> Result<()> {
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001876 let db = new_test_db()?;
Joel Galenson26f4d012020-07-17 14:57:21 -07001877 let tables = db
1878 .conn
Joel Galenson2aab4432020-07-22 15:27:57 -07001879 .prepare("SELECT name from persistent.sqlite_master WHERE type='table' ORDER BY name;")?
Joel Galenson26f4d012020-07-17 14:57:21 -07001880 .query_map(params![], |row| row.get(0))?
1881 .collect::<rusqlite::Result<Vec<String>>>()?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001882 assert_eq!(tables.len(), 5);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001883 assert_eq!(tables[0], "blobentry");
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001884 assert_eq!(tables[1], "grant");
1885 assert_eq!(tables[2], "keyentry");
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001886 assert_eq!(tables[3], "keymetadata");
1887 assert_eq!(tables[4], "keyparameter");
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001888 let tables = db
1889 .conn
1890 .prepare("SELECT name from perboot.sqlite_master WHERE type='table' ORDER BY name;")?
1891 .query_map(params![], |row| row.get(0))?
1892 .collect::<rusqlite::Result<Vec<String>>>()?;
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001893
1894 assert_eq!(tables.len(), 2);
1895 assert_eq!(tables[0], "authtoken");
1896 assert_eq!(tables[1], "metadata");
Joel Galenson2aab4432020-07-22 15:27:57 -07001897 Ok(())
1898 }
1899
1900 #[test]
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001901 fn test_auth_token_table_invariant() -> Result<()> {
1902 let mut db = new_test_db()?;
1903 let auth_token1 = HardwareAuthToken {
1904 challenge: i64::MAX,
1905 userId: 200,
1906 authenticatorId: 200,
1907 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
1908 timestamp: Timestamp { milliSeconds: 500 },
1909 mac: String::from("mac").into_bytes(),
1910 };
1911 db.insert_auth_token(&auth_token1)?;
1912 let auth_tokens_returned = get_auth_tokens(&mut db)?;
1913 assert_eq!(auth_tokens_returned.len(), 1);
1914
1915 // insert another auth token with the same values for the columns in the UNIQUE constraint
1916 // of the auth token table and different value for timestamp
1917 let auth_token2 = HardwareAuthToken {
1918 challenge: i64::MAX,
1919 userId: 200,
1920 authenticatorId: 200,
1921 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
1922 timestamp: Timestamp { milliSeconds: 600 },
1923 mac: String::from("mac").into_bytes(),
1924 };
1925
1926 db.insert_auth_token(&auth_token2)?;
1927 let mut auth_tokens_returned = get_auth_tokens(&mut db)?;
1928 assert_eq!(auth_tokens_returned.len(), 1);
1929
1930 if let Some(auth_token) = auth_tokens_returned.pop() {
1931 assert_eq!(auth_token.auth_token.timestamp.milliSeconds, 600);
1932 }
1933
1934 // insert another auth token with the different values for the columns in the UNIQUE
1935 // constraint of the auth token table
1936 let auth_token3 = HardwareAuthToken {
1937 challenge: i64::MAX,
1938 userId: 201,
1939 authenticatorId: 200,
1940 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
1941 timestamp: Timestamp { milliSeconds: 600 },
1942 mac: String::from("mac").into_bytes(),
1943 };
1944
1945 db.insert_auth_token(&auth_token3)?;
1946 let auth_tokens_returned = get_auth_tokens(&mut db)?;
1947 assert_eq!(auth_tokens_returned.len(), 2);
1948
1949 Ok(())
1950 }
1951
1952 // utility function for test_auth_token_table_invariant()
1953 fn get_auth_tokens(db: &mut KeystoreDB) -> Result<Vec<AuthTokenEntry>> {
1954 let mut stmt = db.conn.prepare("SELECT * from perboot.authtoken;")?;
1955
1956 let auth_token_entries: Vec<AuthTokenEntry> = stmt
1957 .query_map(NO_PARAMS, |row| {
1958 Ok(AuthTokenEntry::new(
1959 HardwareAuthToken {
1960 challenge: row.get(1)?,
1961 userId: row.get(2)?,
1962 authenticatorId: row.get(3)?,
1963 authenticatorType: HardwareAuthenticatorType(row.get(4)?),
1964 timestamp: Timestamp { milliSeconds: row.get(5)? },
1965 mac: row.get(6)?,
1966 },
1967 row.get(7)?,
1968 ))
1969 })?
1970 .collect::<Result<Vec<AuthTokenEntry>, Error>>()?;
1971 Ok(auth_token_entries)
1972 }
1973
1974 #[test]
Joel Galenson2aab4432020-07-22 15:27:57 -07001975 fn test_persistence_for_files() -> Result<()> {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001976 let temp_dir = TempDir::new("persistent_db_test")?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001977 let mut db = KeystoreDB::new(temp_dir.path())?;
Joel Galenson2aab4432020-07-22 15:27:57 -07001978
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001979 db.create_key_entry(Domain::APP, 100)?;
Joel Galenson2aab4432020-07-22 15:27:57 -07001980 let entries = get_keyentry(&db)?;
1981 assert_eq!(entries.len(), 1);
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001982
1983 let db = KeystoreDB::new(temp_dir.path())?;
Joel Galenson2aab4432020-07-22 15:27:57 -07001984
1985 let entries_new = get_keyentry(&db)?;
1986 assert_eq!(entries, entries_new);
1987 Ok(())
1988 }
1989
1990 #[test]
Joel Galenson0891bc12020-07-20 10:37:03 -07001991 fn test_create_key_entry() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001992 fn extractor(ke: &KeyEntryRow) -> (Domain, i64, Option<&str>) {
Joel Galenson0891bc12020-07-20 10:37:03 -07001993 (ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref())
1994 }
1995
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001996 let mut db = new_test_db()?;
Joel Galenson0891bc12020-07-20 10:37:03 -07001997
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001998 db.create_key_entry(Domain::APP, 100)?;
1999 db.create_key_entry(Domain::SELINUX, 101)?;
Joel Galenson0891bc12020-07-20 10:37:03 -07002000
2001 let entries = get_keyentry(&db)?;
2002 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002003 assert_eq!(extractor(&entries[0]), (Domain::APP, 100, None));
2004 assert_eq!(extractor(&entries[1]), (Domain::SELINUX, 101, None));
Joel Galenson0891bc12020-07-20 10:37:03 -07002005
2006 // Test that we must pass in a valid Domain.
2007 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002008 db.create_key_entry(Domain::GRANT, 102),
2009 "Domain Domain(1) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07002010 );
2011 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002012 db.create_key_entry(Domain::BLOB, 103),
2013 "Domain Domain(3) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07002014 );
2015 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002016 db.create_key_entry(Domain::KEY_ID, 104),
2017 "Domain Domain(4) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07002018 );
2019
2020 Ok(())
2021 }
2022
Joel Galenson33c04ad2020-08-03 11:04:38 -07002023 #[test]
2024 fn test_rebind_alias() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002025 fn extractor(ke: &KeyEntryRow) -> (Option<Domain>, Option<i64>, Option<&str>) {
Joel Galenson33c04ad2020-08-03 11:04:38 -07002026 (ke.domain, ke.namespace, ke.alias.as_deref())
2027 }
2028
Janis Danisevskis4df44f42020-08-26 14:40:03 -07002029 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002030 db.create_key_entry(Domain::APP, 42)?;
2031 db.create_key_entry(Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07002032 let entries = get_keyentry(&db)?;
2033 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002034 assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), None));
2035 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
Joel Galenson33c04ad2020-08-03 11:04:38 -07002036
2037 // Test that the first call to rebind_alias sets the alias.
Janis Danisevskisaec14592020-11-12 09:41:49 -08002038 db.rebind_alias(&KEY_ID_LOCK.get(entries[0].id), "foo", Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07002039 let entries = get_keyentry(&db)?;
2040 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002041 assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), Some("foo")));
2042 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
Joel Galenson33c04ad2020-08-03 11:04:38 -07002043
2044 // Test that the second call to rebind_alias also empties the old one.
Janis Danisevskisaec14592020-11-12 09:41:49 -08002045 db.rebind_alias(&KEY_ID_LOCK.get(entries[1].id), "foo", Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07002046 let entries = get_keyentry(&db)?;
2047 assert_eq!(entries.len(), 2);
Joel Galenson7fa5c412020-11-19 10:56:54 -08002048 assert_eq!(extractor(&entries[0]), (None, None, None));
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002049 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
Joel Galenson33c04ad2020-08-03 11:04:38 -07002050
2051 // Test that we must pass in a valid Domain.
2052 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08002053 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::GRANT, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002054 "Domain Domain(1) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07002055 );
2056 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08002057 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::BLOB, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002058 "Domain Domain(3) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07002059 );
2060 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08002061 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::KEY_ID, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002062 "Domain Domain(4) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07002063 );
2064
2065 // Test that we correctly handle setting an alias for something that does not exist.
2066 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08002067 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::SELINUX, 42),
Joel Galenson33c04ad2020-08-03 11:04:38 -07002068 "Expected to update a single entry but instead updated 0",
2069 );
2070 // Test that we correctly abort the transaction in this case.
2071 let entries = get_keyentry(&db)?;
2072 assert_eq!(entries.len(), 2);
Joel Galenson7fa5c412020-11-19 10:56:54 -08002073 assert_eq!(extractor(&entries[0]), (None, None, None));
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002074 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
Joel Galenson33c04ad2020-08-03 11:04:38 -07002075
2076 Ok(())
2077 }
2078
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002079 #[test]
2080 fn test_grant_ungrant() -> Result<()> {
2081 const CALLER_UID: u32 = 15;
2082 const GRANTEE_UID: u32 = 12;
2083 const SELINUX_NAMESPACE: i64 = 7;
2084
2085 let mut db = new_test_db()?;
2086 db.conn.execute(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002087 "INSERT INTO persistent.keyentry (id, key_type, domain, namespace, alias, state)
2088 VALUES (1, 0, 0, 15, 'key', 1), (2, 0, 2, 7, 'yek', 1);",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002089 NO_PARAMS,
2090 )?;
2091 let app_key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002092 domain: super::Domain::APP,
2093 nspace: 0,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002094 alias: Some("key".to_string()),
2095 blob: None,
2096 };
2097 const PVEC1: KeyPermSet = key_perm_set![KeyPerm::use_(), KeyPerm::get_info()];
2098 const PVEC2: KeyPermSet = key_perm_set![KeyPerm::use_()];
2099
2100 // Reset totally predictable random number generator in case we
2101 // are not the first test running on this thread.
2102 reset_random();
2103 let next_random = 0i64;
2104
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002105 let app_granted_key = db
2106 .grant(app_key.clone(), CALLER_UID, GRANTEE_UID, PVEC1, |k, a| {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002107 assert_eq!(*a, PVEC1);
2108 assert_eq!(
2109 *k,
2110 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002111 domain: super::Domain::APP,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002112 // namespace must be set to the caller_uid.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002113 nspace: CALLER_UID as i64,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002114 alias: Some("key".to_string()),
2115 blob: None,
2116 }
2117 );
2118 Ok(())
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002119 })
2120 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002121
2122 assert_eq!(
2123 app_granted_key,
2124 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002125 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002126 // The grantid is next_random due to the mock random number generator.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002127 nspace: next_random,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002128 alias: None,
2129 blob: None,
2130 }
2131 );
2132
2133 let selinux_key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002134 domain: super::Domain::SELINUX,
2135 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002136 alias: Some("yek".to_string()),
2137 blob: None,
2138 };
2139
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002140 let selinux_granted_key = db
2141 .grant(selinux_key.clone(), CALLER_UID, 12, PVEC1, |k, a| {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002142 assert_eq!(*a, PVEC1);
2143 assert_eq!(
2144 *k,
2145 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002146 domain: super::Domain::SELINUX,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002147 // namespace must be the supplied SELinux
2148 // namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002149 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002150 alias: Some("yek".to_string()),
2151 blob: None,
2152 }
2153 );
2154 Ok(())
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002155 })
2156 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002157
2158 assert_eq!(
2159 selinux_granted_key,
2160 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002161 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002162 // The grantid is next_random + 1 due to the mock random number generator.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002163 nspace: next_random + 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002164 alias: None,
2165 blob: None,
2166 }
2167 );
2168
2169 // This should update the existing grant with PVEC2.
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002170 let selinux_granted_key = db
2171 .grant(selinux_key.clone(), CALLER_UID, 12, PVEC2, |k, a| {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002172 assert_eq!(*a, PVEC2);
2173 assert_eq!(
2174 *k,
2175 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002176 domain: super::Domain::SELINUX,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002177 // namespace must be the supplied SELinux
2178 // namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002179 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002180 alias: Some("yek".to_string()),
2181 blob: None,
2182 }
2183 );
2184 Ok(())
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002185 })
2186 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002187
2188 assert_eq!(
2189 selinux_granted_key,
2190 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002191 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002192 // Same grant id as before. The entry was only updated.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002193 nspace: next_random + 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002194 alias: None,
2195 blob: None,
2196 }
2197 );
2198
2199 {
2200 // Limiting scope of stmt, because it borrows db.
2201 let mut stmt = db
2202 .conn
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002203 .prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?;
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07002204 let mut rows =
2205 stmt.query_map::<(i64, u32, i64, KeyPermSet), _, _>(NO_PARAMS, |row| {
2206 Ok((
2207 row.get(0)?,
2208 row.get(1)?,
2209 row.get(2)?,
2210 KeyPermSet::from(row.get::<_, i32>(3)?),
2211 ))
2212 })?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002213
2214 let r = rows.next().unwrap().unwrap();
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07002215 assert_eq!(r, (next_random, GRANTEE_UID, 1, PVEC1));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002216 let r = rows.next().unwrap().unwrap();
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07002217 assert_eq!(r, (next_random + 1, GRANTEE_UID, 2, PVEC2));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002218 assert!(rows.next().is_none());
2219 }
2220
2221 debug_dump_keyentry_table(&mut db)?;
2222 println!("app_key {:?}", app_key);
2223 println!("selinux_key {:?}", selinux_key);
2224
2225 db.ungrant(app_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
2226 db.ungrant(selinux_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
2227
2228 Ok(())
2229 }
2230
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002231 static TEST_KEY_BLOB: &[u8] = b"my test blob";
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002232 static TEST_CERT_BLOB: &[u8] = b"my test cert";
2233 static TEST_CERT_CHAIN_BLOB: &[u8] = b"my test cert_chain";
2234
2235 #[test]
2236 fn test_insert_blob() -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002237 let key_id = KEY_ID_LOCK.get(3000);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002238 let mut db = new_test_db()?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002239 db.insert_blob(&key_id, SubComponentType::KEY_BLOB, TEST_KEY_BLOB)?;
2240 db.insert_blob(&key_id, SubComponentType::CERT, TEST_CERT_BLOB)?;
2241 db.insert_blob(&key_id, SubComponentType::CERT_CHAIN, TEST_CERT_CHAIN_BLOB)?;
2242 drop(key_id);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002243
2244 let mut stmt = db.conn.prepare(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002245 "SELECT subcomponent_type, keyentryid, blob FROM persistent.blobentry
2246 ORDER BY subcomponent_type ASC;",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002247 )?;
2248 let mut rows = stmt
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002249 .query_map::<(SubComponentType, i64, Vec<u8>), _, _>(NO_PARAMS, |row| {
2250 Ok((row.get(0)?, row.get(1)?, row.get(2)?))
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002251 })?;
2252 let r = rows.next().unwrap().unwrap();
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002253 assert_eq!(r, (SubComponentType::KEY_BLOB, 3000, TEST_KEY_BLOB.to_vec()));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002254 let r = rows.next().unwrap().unwrap();
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002255 assert_eq!(r, (SubComponentType::CERT, 3000, TEST_CERT_BLOB.to_vec()));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002256 let r = rows.next().unwrap().unwrap();
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002257 assert_eq!(r, (SubComponentType::CERT_CHAIN, 3000, TEST_CERT_CHAIN_BLOB.to_vec()));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002258
2259 Ok(())
2260 }
2261
2262 static TEST_ALIAS: &str = "my super duper key";
2263
2264 #[test]
2265 fn test_insert_and_load_full_keyentry_domain_app() -> Result<()> {
2266 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002267 let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002268 .context("test_insert_and_load_full_keyentry_domain_app")?
2269 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002270 let (_key_guard, key_entry) = db
2271 .load_key_entry(
2272 KeyDescriptor {
2273 domain: Domain::APP,
2274 nspace: 0,
2275 alias: Some(TEST_ALIAS.to_string()),
2276 blob: None,
2277 },
2278 KeyType::Client,
2279 KeyEntryLoadBits::BOTH,
2280 1,
2281 |_k, _av| Ok(()),
2282 )
2283 .unwrap();
2284 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
2285
2286 db.unbind_key(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002287 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002288 domain: Domain::APP,
2289 nspace: 0,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002290 alias: Some(TEST_ALIAS.to_string()),
2291 blob: None,
2292 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002293 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002294 1,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002295 |_, _| Ok(()),
2296 )
2297 .unwrap();
2298
2299 assert_eq!(
2300 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2301 db.load_key_entry(
2302 KeyDescriptor {
2303 domain: Domain::APP,
2304 nspace: 0,
2305 alias: Some(TEST_ALIAS.to_string()),
2306 blob: None,
2307 },
2308 KeyType::Client,
2309 KeyEntryLoadBits::NONE,
2310 1,
2311 |_k, _av| Ok(()),
2312 )
2313 .unwrap_err()
2314 .root_cause()
2315 .downcast_ref::<KsError>()
2316 );
2317
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002318 Ok(())
2319 }
2320
2321 #[test]
2322 fn test_insert_and_load_full_keyentry_domain_selinux() -> Result<()> {
2323 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002324 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002325 .context("test_insert_and_load_full_keyentry_domain_selinux")?
2326 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002327 let (_key_guard, key_entry) = db
2328 .load_key_entry(
2329 KeyDescriptor {
2330 domain: Domain::SELINUX,
2331 nspace: 1,
2332 alias: Some(TEST_ALIAS.to_string()),
2333 blob: None,
2334 },
2335 KeyType::Client,
2336 KeyEntryLoadBits::BOTH,
2337 1,
2338 |_k, _av| Ok(()),
2339 )
2340 .unwrap();
2341 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
2342
2343 db.unbind_key(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002344 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002345 domain: Domain::SELINUX,
2346 nspace: 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002347 alias: Some(TEST_ALIAS.to_string()),
2348 blob: None,
2349 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002350 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002351 1,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002352 |_, _| Ok(()),
2353 )
2354 .unwrap();
2355
2356 assert_eq!(
2357 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2358 db.load_key_entry(
2359 KeyDescriptor {
2360 domain: Domain::SELINUX,
2361 nspace: 1,
2362 alias: Some(TEST_ALIAS.to_string()),
2363 blob: None,
2364 },
2365 KeyType::Client,
2366 KeyEntryLoadBits::NONE,
2367 1,
2368 |_k, _av| Ok(()),
2369 )
2370 .unwrap_err()
2371 .root_cause()
2372 .downcast_ref::<KsError>()
2373 );
2374
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002375 Ok(())
2376 }
2377
2378 #[test]
2379 fn test_insert_and_load_full_keyentry_domain_key_id() -> Result<()> {
2380 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002381 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002382 .context("test_insert_and_load_full_keyentry_domain_key_id")?
2383 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002384 let (_, key_entry) = db
2385 .load_key_entry(
2386 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
2387 KeyType::Client,
2388 KeyEntryLoadBits::BOTH,
2389 1,
2390 |_k, _av| Ok(()),
2391 )
2392 .unwrap();
2393
2394 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
2395
2396 db.unbind_key(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002397 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002398 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002399 1,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002400 |_, _| Ok(()),
2401 )
2402 .unwrap();
2403
2404 assert_eq!(
2405 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2406 db.load_key_entry(
2407 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
2408 KeyType::Client,
2409 KeyEntryLoadBits::NONE,
2410 1,
2411 |_k, _av| Ok(()),
2412 )
2413 .unwrap_err()
2414 .root_cause()
2415 .downcast_ref::<KsError>()
2416 );
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002417
2418 Ok(())
2419 }
2420
2421 #[test]
2422 fn test_insert_and_load_full_keyentry_from_grant() -> Result<()> {
2423 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002424 let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002425 .context("test_insert_and_load_full_keyentry_from_grant")?
2426 .0;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002427
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002428 let granted_key = db
2429 .grant(
2430 KeyDescriptor {
2431 domain: Domain::APP,
2432 nspace: 0,
2433 alias: Some(TEST_ALIAS.to_string()),
2434 blob: None,
2435 },
2436 1,
2437 2,
2438 key_perm_set![KeyPerm::use_()],
2439 |_k, _av| Ok(()),
2440 )
2441 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002442
2443 debug_dump_grant_table(&mut db)?;
2444
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002445 let (_key_guard, key_entry) = db
2446 .load_key_entry(
2447 granted_key.clone(),
2448 KeyType::Client,
2449 KeyEntryLoadBits::BOTH,
2450 2,
2451 |k, av| {
2452 assert_eq!(Domain::GRANT, k.domain);
2453 assert!(av.unwrap().includes(KeyPerm::use_()));
2454 Ok(())
2455 },
2456 )
2457 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002458
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002459 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002460
2461 db.unbind_key(granted_key.clone(), KeyType::Client, 2, |_, _| Ok(())).unwrap();
2462
2463 assert_eq!(
2464 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2465 db.load_key_entry(
2466 granted_key,
2467 KeyType::Client,
2468 KeyEntryLoadBits::NONE,
2469 2,
2470 |_k, _av| Ok(()),
2471 )
2472 .unwrap_err()
2473 .root_cause()
2474 .downcast_ref::<KsError>()
2475 );
2476
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002477 Ok(())
2478 }
2479
Janis Danisevskisaec14592020-11-12 09:41:49 -08002480 static KEY_LOCK_TEST_ALIAS: &str = "my super duper locked key";
2481
Janis Danisevskisaec14592020-11-12 09:41:49 -08002482 #[test]
2483 fn test_insert_and_load_full_keyentry_domain_app_concurrently() -> Result<()> {
2484 let handle = {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002485 let temp_dir = Arc::new(TempDir::new("id_lock_test")?);
2486 let temp_dir_clone = temp_dir.clone();
2487 let mut db = KeystoreDB::new(temp_dir.path())?;
Janis Danisevskisaec14592020-11-12 09:41:49 -08002488 let key_id = make_test_key_entry(&mut db, Domain::APP, 33, KEY_LOCK_TEST_ALIAS)
2489 .context("test_insert_and_load_full_keyentry_domain_app")?
2490 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002491 let (_key_guard, key_entry) = db
2492 .load_key_entry(
2493 KeyDescriptor {
2494 domain: Domain::APP,
2495 nspace: 0,
2496 alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
2497 blob: None,
2498 },
2499 KeyType::Client,
2500 KeyEntryLoadBits::BOTH,
2501 33,
2502 |_k, _av| Ok(()),
2503 )
2504 .unwrap();
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002505 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
Janis Danisevskisaec14592020-11-12 09:41:49 -08002506 let state = Arc::new(AtomicU8::new(1));
2507 let state2 = state.clone();
2508
2509 // Spawning a second thread that attempts to acquire the key id lock
2510 // for the same key as the primary thread. The primary thread then
2511 // waits, thereby forcing the secondary thread into the second stage
2512 // of acquiring the lock (see KEY ID LOCK 2/2 above).
2513 // The test succeeds if the secondary thread observes the transition
2514 // of `state` from 1 to 2, despite having a whole second to overtake
2515 // the primary thread.
2516 let handle = thread::spawn(move || {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002517 let temp_dir = temp_dir_clone;
2518 let mut db = KeystoreDB::new(temp_dir.path()).unwrap();
Janis Danisevskisaec14592020-11-12 09:41:49 -08002519 assert!(db
2520 .load_key_entry(
2521 KeyDescriptor {
2522 domain: Domain::APP,
2523 nspace: 0,
2524 alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
2525 blob: None,
2526 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002527 KeyType::Client,
Janis Danisevskisaec14592020-11-12 09:41:49 -08002528 KeyEntryLoadBits::BOTH,
2529 33,
2530 |_k, _av| Ok(()),
2531 )
2532 .is_ok());
2533 // We should only see a 2 here because we can only return
2534 // from load_key_entry when the `_key_guard` expires,
2535 // which happens at the end of the scope.
2536 assert_eq!(2, state2.load(Ordering::Relaxed));
2537 });
2538
2539 thread::sleep(std::time::Duration::from_millis(1000));
2540
2541 assert_eq!(Ok(1), state.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed));
2542
2543 // Return the handle from this scope so we can join with the
2544 // secondary thread after the key id lock has expired.
2545 handle
2546 // This is where the `_key_guard` goes out of scope,
2547 // which is the reason for concurrent load_key_entry on the same key
2548 // to unblock.
2549 };
2550 // Join with the secondary thread and unwrap, to propagate failing asserts to the
2551 // main test thread. We will not see failing asserts in secondary threads otherwise.
2552 handle.join().unwrap();
2553 Ok(())
2554 }
2555
Janis Danisevskise92a5e62020-12-02 12:57:41 -08002556 #[test]
2557 fn list() -> Result<()> {
2558 let temp_dir = TempDir::new("list_test")?;
2559 let mut db = KeystoreDB::new(temp_dir.path())?;
2560 static LIST_O_ENTRIES: &[(Domain, i64, &str)] = &[
2561 (Domain::APP, 1, "test1"),
2562 (Domain::APP, 1, "test2"),
2563 (Domain::APP, 1, "test3"),
2564 (Domain::APP, 1, "test4"),
2565 (Domain::APP, 1, "test5"),
2566 (Domain::APP, 1, "test6"),
2567 (Domain::APP, 1, "test7"),
2568 (Domain::APP, 2, "test1"),
2569 (Domain::APP, 2, "test2"),
2570 (Domain::APP, 2, "test3"),
2571 (Domain::APP, 2, "test4"),
2572 (Domain::APP, 2, "test5"),
2573 (Domain::APP, 2, "test6"),
2574 (Domain::APP, 2, "test8"),
2575 (Domain::SELINUX, 100, "test1"),
2576 (Domain::SELINUX, 100, "test2"),
2577 (Domain::SELINUX, 100, "test3"),
2578 (Domain::SELINUX, 100, "test4"),
2579 (Domain::SELINUX, 100, "test5"),
2580 (Domain::SELINUX, 100, "test6"),
2581 (Domain::SELINUX, 100, "test9"),
2582 ];
2583
2584 let list_o_keys: Vec<(i64, i64)> = LIST_O_ENTRIES
2585 .iter()
2586 .map(|(domain, ns, alias)| {
2587 let entry =
2588 make_test_key_entry(&mut db, *domain, *ns, *alias).unwrap_or_else(|e| {
2589 panic!("Failed to insert {:?} {} {}. Error {:?}", domain, ns, alias, e)
2590 });
2591 (entry.id(), *ns)
2592 })
2593 .collect();
2594
2595 for (domain, namespace) in
2596 &[(Domain::APP, 1i64), (Domain::APP, 2i64), (Domain::SELINUX, 100i64)]
2597 {
2598 let mut list_o_descriptors: Vec<KeyDescriptor> = LIST_O_ENTRIES
2599 .iter()
2600 .filter_map(|(domain, ns, alias)| match ns {
2601 ns if *ns == *namespace => Some(KeyDescriptor {
2602 domain: *domain,
2603 nspace: *ns,
2604 alias: Some(alias.to_string()),
2605 blob: None,
2606 }),
2607 _ => None,
2608 })
2609 .collect();
2610 list_o_descriptors.sort();
2611 let mut list_result = db.list(*domain, *namespace)?;
2612 list_result.sort();
2613 assert_eq!(list_o_descriptors, list_result);
2614
2615 let mut list_o_ids: Vec<i64> = list_o_descriptors
2616 .into_iter()
2617 .map(|d| {
2618 let (_, entry) = db
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002619 .load_key_entry(
2620 d,
2621 KeyType::Client,
2622 KeyEntryLoadBits::NONE,
2623 *namespace as u32,
2624 |_, _| Ok(()),
2625 )
Janis Danisevskise92a5e62020-12-02 12:57:41 -08002626 .unwrap();
2627 entry.id()
2628 })
2629 .collect();
2630 list_o_ids.sort_unstable();
2631 let mut loaded_entries: Vec<i64> = list_o_keys
2632 .iter()
2633 .filter_map(|(id, ns)| match ns {
2634 ns if *ns == *namespace => Some(*id),
2635 _ => None,
2636 })
2637 .collect();
2638 loaded_entries.sort_unstable();
2639 assert_eq!(list_o_ids, loaded_entries);
2640 }
2641 assert_eq!(Vec::<KeyDescriptor>::new(), db.list(Domain::SELINUX, 101)?);
2642
2643 Ok(())
2644 }
2645
Joel Galenson0891bc12020-07-20 10:37:03 -07002646 // Helpers
2647
2648 // Checks that the given result is an error containing the given string.
2649 fn check_result_is_error_containing_string<T>(result: Result<T>, target: &str) {
2650 let error_str = format!(
2651 "{:#?}",
2652 result.err().unwrap_or_else(|| panic!("Expected the error: {}", target))
2653 );
2654 assert!(
2655 error_str.contains(target),
2656 "The string \"{}\" should contain \"{}\"",
2657 error_str,
2658 target
2659 );
2660 }
2661
Joel Galenson2aab4432020-07-22 15:27:57 -07002662 #[derive(Debug, PartialEq)]
Joel Galenson0891bc12020-07-20 10:37:03 -07002663 #[allow(dead_code)]
2664 struct KeyEntryRow {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002665 id: i64,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002666 key_type: KeyType,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002667 domain: Option<Domain>,
Joel Galenson0891bc12020-07-20 10:37:03 -07002668 namespace: Option<i64>,
2669 alias: Option<String>,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002670 state: KeyLifeCycle,
Joel Galenson0891bc12020-07-20 10:37:03 -07002671 }
2672
2673 fn get_keyentry(db: &KeystoreDB) -> Result<Vec<KeyEntryRow>> {
2674 db.conn
Joel Galenson2aab4432020-07-22 15:27:57 -07002675 .prepare("SELECT * FROM persistent.keyentry;")?
Joel Galenson0891bc12020-07-20 10:37:03 -07002676 .query_map(NO_PARAMS, |row| {
Joel Galenson0891bc12020-07-20 10:37:03 -07002677 Ok(KeyEntryRow {
2678 id: row.get(0)?,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002679 key_type: row.get(1)?,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002680 domain: match row.get(2)? {
2681 Some(i) => Some(Domain(i)),
2682 None => None,
2683 },
Joel Galenson0891bc12020-07-20 10:37:03 -07002684 namespace: row.get(3)?,
2685 alias: row.get(4)?,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002686 state: row.get(5)?,
Joel Galenson0891bc12020-07-20 10:37:03 -07002687 })
2688 })?
2689 .map(|r| r.context("Could not read keyentry row."))
2690 .collect::<Result<Vec<_>>>()
2691 }
2692
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07002693 // Note: The parameters and SecurityLevel associations are nonsensical. This
2694 // collection is only used to check if the parameters are preserved as expected by the
2695 // database.
2696 fn make_test_params() -> Vec<KeyParameter> {
2697 vec![
2698 KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::TRUSTED_ENVIRONMENT),
2699 KeyParameter::new(
2700 KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
2701 SecurityLevel::TRUSTED_ENVIRONMENT,
2702 ),
2703 KeyParameter::new(
2704 KeyParameterValue::KeyPurpose(KeyPurpose::DECRYPT),
2705 SecurityLevel::TRUSTED_ENVIRONMENT,
2706 ),
2707 KeyParameter::new(
2708 KeyParameterValue::Algorithm(Algorithm::RSA),
2709 SecurityLevel::TRUSTED_ENVIRONMENT,
2710 ),
2711 KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::TRUSTED_ENVIRONMENT),
2712 KeyParameter::new(
2713 KeyParameterValue::BlockMode(BlockMode::ECB),
2714 SecurityLevel::TRUSTED_ENVIRONMENT,
2715 ),
2716 KeyParameter::new(
2717 KeyParameterValue::BlockMode(BlockMode::GCM),
2718 SecurityLevel::TRUSTED_ENVIRONMENT,
2719 ),
2720 KeyParameter::new(KeyParameterValue::Digest(Digest::NONE), SecurityLevel::STRONGBOX),
2721 KeyParameter::new(
2722 KeyParameterValue::Digest(Digest::MD5),
2723 SecurityLevel::TRUSTED_ENVIRONMENT,
2724 ),
2725 KeyParameter::new(
2726 KeyParameterValue::Digest(Digest::SHA_2_224),
2727 SecurityLevel::TRUSTED_ENVIRONMENT,
2728 ),
2729 KeyParameter::new(
2730 KeyParameterValue::Digest(Digest::SHA_2_256),
2731 SecurityLevel::STRONGBOX,
2732 ),
2733 KeyParameter::new(
2734 KeyParameterValue::PaddingMode(PaddingMode::NONE),
2735 SecurityLevel::TRUSTED_ENVIRONMENT,
2736 ),
2737 KeyParameter::new(
2738 KeyParameterValue::PaddingMode(PaddingMode::RSA_OAEP),
2739 SecurityLevel::TRUSTED_ENVIRONMENT,
2740 ),
2741 KeyParameter::new(
2742 KeyParameterValue::PaddingMode(PaddingMode::RSA_PSS),
2743 SecurityLevel::STRONGBOX,
2744 ),
2745 KeyParameter::new(
2746 KeyParameterValue::PaddingMode(PaddingMode::RSA_PKCS1_1_5_SIGN),
2747 SecurityLevel::TRUSTED_ENVIRONMENT,
2748 ),
2749 KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::TRUSTED_ENVIRONMENT),
2750 KeyParameter::new(KeyParameterValue::MinMacLength(256), SecurityLevel::STRONGBOX),
2751 KeyParameter::new(
2752 KeyParameterValue::EcCurve(EcCurve::P_224),
2753 SecurityLevel::TRUSTED_ENVIRONMENT,
2754 ),
2755 KeyParameter::new(KeyParameterValue::EcCurve(EcCurve::P_256), SecurityLevel::STRONGBOX),
2756 KeyParameter::new(
2757 KeyParameterValue::EcCurve(EcCurve::P_384),
2758 SecurityLevel::TRUSTED_ENVIRONMENT,
2759 ),
2760 KeyParameter::new(
2761 KeyParameterValue::EcCurve(EcCurve::P_521),
2762 SecurityLevel::TRUSTED_ENVIRONMENT,
2763 ),
2764 KeyParameter::new(
2765 KeyParameterValue::RSAPublicExponent(3),
2766 SecurityLevel::TRUSTED_ENVIRONMENT,
2767 ),
2768 KeyParameter::new(
2769 KeyParameterValue::IncludeUniqueID,
2770 SecurityLevel::TRUSTED_ENVIRONMENT,
2771 ),
2772 KeyParameter::new(KeyParameterValue::BootLoaderOnly, SecurityLevel::STRONGBOX),
2773 KeyParameter::new(KeyParameterValue::RollbackResistance, SecurityLevel::STRONGBOX),
2774 KeyParameter::new(
2775 KeyParameterValue::ActiveDateTime(1234567890),
2776 SecurityLevel::STRONGBOX,
2777 ),
2778 KeyParameter::new(
2779 KeyParameterValue::OriginationExpireDateTime(1234567890),
2780 SecurityLevel::TRUSTED_ENVIRONMENT,
2781 ),
2782 KeyParameter::new(
2783 KeyParameterValue::UsageExpireDateTime(1234567890),
2784 SecurityLevel::TRUSTED_ENVIRONMENT,
2785 ),
2786 KeyParameter::new(
2787 KeyParameterValue::MinSecondsBetweenOps(1234567890),
2788 SecurityLevel::TRUSTED_ENVIRONMENT,
2789 ),
2790 KeyParameter::new(
2791 KeyParameterValue::MaxUsesPerBoot(1234567890),
2792 SecurityLevel::TRUSTED_ENVIRONMENT,
2793 ),
2794 KeyParameter::new(KeyParameterValue::UserID(1), SecurityLevel::STRONGBOX),
2795 KeyParameter::new(KeyParameterValue::UserSecureID(42), SecurityLevel::STRONGBOX),
2796 KeyParameter::new(
2797 KeyParameterValue::NoAuthRequired,
2798 SecurityLevel::TRUSTED_ENVIRONMENT,
2799 ),
2800 KeyParameter::new(
2801 KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType::PASSWORD),
2802 SecurityLevel::TRUSTED_ENVIRONMENT,
2803 ),
2804 KeyParameter::new(KeyParameterValue::AuthTimeout(1234567890), SecurityLevel::SOFTWARE),
2805 KeyParameter::new(KeyParameterValue::AllowWhileOnBody, SecurityLevel::SOFTWARE),
2806 KeyParameter::new(
2807 KeyParameterValue::TrustedUserPresenceRequired,
2808 SecurityLevel::TRUSTED_ENVIRONMENT,
2809 ),
2810 KeyParameter::new(
2811 KeyParameterValue::TrustedConfirmationRequired,
2812 SecurityLevel::TRUSTED_ENVIRONMENT,
2813 ),
2814 KeyParameter::new(
2815 KeyParameterValue::UnlockedDeviceRequired,
2816 SecurityLevel::TRUSTED_ENVIRONMENT,
2817 ),
2818 KeyParameter::new(
2819 KeyParameterValue::ApplicationID(vec![1u8, 2u8, 3u8, 4u8]),
2820 SecurityLevel::SOFTWARE,
2821 ),
2822 KeyParameter::new(
2823 KeyParameterValue::ApplicationData(vec![4u8, 3u8, 2u8, 1u8]),
2824 SecurityLevel::SOFTWARE,
2825 ),
2826 KeyParameter::new(
2827 KeyParameterValue::CreationDateTime(12345677890),
2828 SecurityLevel::SOFTWARE,
2829 ),
2830 KeyParameter::new(
2831 KeyParameterValue::KeyOrigin(KeyOrigin::GENERATED),
2832 SecurityLevel::TRUSTED_ENVIRONMENT,
2833 ),
2834 KeyParameter::new(
2835 KeyParameterValue::RootOfTrust(vec![3u8, 2u8, 1u8, 4u8]),
2836 SecurityLevel::TRUSTED_ENVIRONMENT,
2837 ),
2838 KeyParameter::new(KeyParameterValue::OSVersion(1), SecurityLevel::TRUSTED_ENVIRONMENT),
2839 KeyParameter::new(KeyParameterValue::OSPatchLevel(2), SecurityLevel::SOFTWARE),
2840 KeyParameter::new(
2841 KeyParameterValue::UniqueID(vec![4u8, 3u8, 1u8, 2u8]),
2842 SecurityLevel::SOFTWARE,
2843 ),
2844 KeyParameter::new(
2845 KeyParameterValue::AttestationChallenge(vec![4u8, 3u8, 1u8, 2u8]),
2846 SecurityLevel::TRUSTED_ENVIRONMENT,
2847 ),
2848 KeyParameter::new(
2849 KeyParameterValue::AttestationApplicationID(vec![4u8, 3u8, 1u8, 2u8]),
2850 SecurityLevel::TRUSTED_ENVIRONMENT,
2851 ),
2852 KeyParameter::new(
2853 KeyParameterValue::AttestationIdBrand(vec![4u8, 3u8, 1u8, 2u8]),
2854 SecurityLevel::TRUSTED_ENVIRONMENT,
2855 ),
2856 KeyParameter::new(
2857 KeyParameterValue::AttestationIdDevice(vec![4u8, 3u8, 1u8, 2u8]),
2858 SecurityLevel::TRUSTED_ENVIRONMENT,
2859 ),
2860 KeyParameter::new(
2861 KeyParameterValue::AttestationIdProduct(vec![4u8, 3u8, 1u8, 2u8]),
2862 SecurityLevel::TRUSTED_ENVIRONMENT,
2863 ),
2864 KeyParameter::new(
2865 KeyParameterValue::AttestationIdSerial(vec![4u8, 3u8, 1u8, 2u8]),
2866 SecurityLevel::TRUSTED_ENVIRONMENT,
2867 ),
2868 KeyParameter::new(
2869 KeyParameterValue::AttestationIdIMEI(vec![4u8, 3u8, 1u8, 2u8]),
2870 SecurityLevel::TRUSTED_ENVIRONMENT,
2871 ),
2872 KeyParameter::new(
2873 KeyParameterValue::AttestationIdMEID(vec![4u8, 3u8, 1u8, 2u8]),
2874 SecurityLevel::TRUSTED_ENVIRONMENT,
2875 ),
2876 KeyParameter::new(
2877 KeyParameterValue::AttestationIdManufacturer(vec![4u8, 3u8, 1u8, 2u8]),
2878 SecurityLevel::TRUSTED_ENVIRONMENT,
2879 ),
2880 KeyParameter::new(
2881 KeyParameterValue::AttestationIdModel(vec![4u8, 3u8, 1u8, 2u8]),
2882 SecurityLevel::TRUSTED_ENVIRONMENT,
2883 ),
2884 KeyParameter::new(
2885 KeyParameterValue::VendorPatchLevel(3),
2886 SecurityLevel::TRUSTED_ENVIRONMENT,
2887 ),
2888 KeyParameter::new(
2889 KeyParameterValue::BootPatchLevel(4),
2890 SecurityLevel::TRUSTED_ENVIRONMENT,
2891 ),
2892 KeyParameter::new(
2893 KeyParameterValue::AssociatedData(vec![4u8, 3u8, 1u8, 2u8]),
2894 SecurityLevel::TRUSTED_ENVIRONMENT,
2895 ),
2896 KeyParameter::new(
2897 KeyParameterValue::Nonce(vec![4u8, 3u8, 1u8, 2u8]),
2898 SecurityLevel::TRUSTED_ENVIRONMENT,
2899 ),
2900 KeyParameter::new(
2901 KeyParameterValue::MacLength(256),
2902 SecurityLevel::TRUSTED_ENVIRONMENT,
2903 ),
2904 KeyParameter::new(
2905 KeyParameterValue::ResetSinceIdRotation,
2906 SecurityLevel::TRUSTED_ENVIRONMENT,
2907 ),
2908 KeyParameter::new(
2909 KeyParameterValue::ConfirmationToken(vec![5u8, 5u8, 5u8, 5u8]),
2910 SecurityLevel::TRUSTED_ENVIRONMENT,
2911 ),
2912 ]
2913 }
2914
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002915 fn make_test_key_entry(
2916 db: &mut KeystoreDB,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002917 domain: Domain,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002918 namespace: i64,
2919 alias: &str,
Janis Danisevskisaec14592020-11-12 09:41:49 -08002920 ) -> Result<KeyIdGuard> {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002921 let key_id = db.create_key_entry(domain, namespace)?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002922 db.insert_blob(&key_id, SubComponentType::KEY_BLOB, TEST_KEY_BLOB)?;
2923 db.insert_blob(&key_id, SubComponentType::CERT, TEST_CERT_BLOB)?;
2924 db.insert_blob(&key_id, SubComponentType::CERT_CHAIN, TEST_CERT_CHAIN_BLOB)?;
Janis Danisevskisaec14592020-11-12 09:41:49 -08002925 db.insert_keyparameter(&key_id, &make_test_params())?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002926 let mut metadata = KeyMetaData::new();
2927 metadata.add(KeyMetaEntry::EncryptedBy(EncryptedBy::Password));
2928 metadata.add(KeyMetaEntry::Salt(vec![1, 2, 3]));
2929 metadata.add(KeyMetaEntry::Iv(vec![2, 3, 1]));
2930 metadata.add(KeyMetaEntry::AeadTag(vec![3, 1, 2]));
2931 db.insert_key_metadata(&key_id, &metadata)?;
Janis Danisevskisaec14592020-11-12 09:41:49 -08002932 db.rebind_alias(&key_id, alias, domain, namespace)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002933 Ok(key_id)
2934 }
2935
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002936 fn make_test_key_entry_test_vector(key_id: i64) -> KeyEntry {
2937 let mut metadata = KeyMetaData::new();
2938 metadata.add(KeyMetaEntry::EncryptedBy(EncryptedBy::Password));
2939 metadata.add(KeyMetaEntry::Salt(vec![1, 2, 3]));
2940 metadata.add(KeyMetaEntry::Iv(vec![2, 3, 1]));
2941 metadata.add(KeyMetaEntry::AeadTag(vec![3, 1, 2]));
2942
2943 KeyEntry {
2944 id: key_id,
2945 km_blob: Some(TEST_KEY_BLOB.to_vec()),
2946 cert: Some(TEST_CERT_BLOB.to_vec()),
2947 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
2948 sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
2949 parameters: make_test_params(),
2950 metadata,
2951 }
2952 }
2953
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002954 fn debug_dump_keyentry_table(db: &mut KeystoreDB) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002955 let mut stmt = db.conn.prepare(
2956 "SELECT id, key_type, domain, namespace, alias, state FROM persistent.keyentry;",
2957 )?;
2958 let rows = stmt.query_map::<(i64, KeyType, i32, i64, String, KeyLifeCycle), _, _>(
2959 NO_PARAMS,
2960 |row| {
2961 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?, row.get(4)?, row.get(5)?))
2962 },
2963 )?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002964
2965 println!("Key entry table rows:");
2966 for r in rows {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002967 let (id, key_type, domain, namespace, alias, state) = r.unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002968 println!(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002969 " id: {} KeyType: {:?} Domain: {} Namespace: {} Alias: {} State: {:?}",
2970 id, key_type, domain, namespace, alias, state
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002971 );
2972 }
2973 Ok(())
2974 }
2975
2976 fn debug_dump_grant_table(db: &mut KeystoreDB) -> Result<()> {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002977 let mut stmt = db
2978 .conn
2979 .prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002980 let rows = stmt.query_map::<(i64, i64, i64, i64), _, _>(NO_PARAMS, |row| {
2981 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?))
2982 })?;
2983
2984 println!("Grant table rows:");
2985 for r in rows {
2986 let (id, gt, ki, av) = r.unwrap();
2987 println!(" id: {} grantee: {} key_id: {} access_vector: {}", id, gt, ki, av);
2988 }
2989 Ok(())
2990 }
2991
Joel Galenson0891bc12020-07-20 10:37:03 -07002992 // Use a custom random number generator that repeats each number once.
2993 // This allows us to test repeated elements.
2994
2995 thread_local! {
2996 static RANDOM_COUNTER: RefCell<i64> = RefCell::new(0);
2997 }
2998
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002999 fn reset_random() {
3000 RANDOM_COUNTER.with(|counter| {
3001 *counter.borrow_mut() = 0;
3002 })
3003 }
3004
Joel Galenson0891bc12020-07-20 10:37:03 -07003005 pub fn random() -> i64 {
3006 RANDOM_COUNTER.with(|counter| {
3007 let result = *counter.borrow() / 2;
3008 *counter.borrow_mut() += 1;
3009 result
3010 })
3011 }
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00003012
3013 #[test]
3014 fn test_last_off_body() -> Result<()> {
3015 let mut db = new_test_db()?;
3016 KeystoreDB::insert_last_off_body(&db.conn, MonotonicRawTime::now())?;
3017 let tx = db.conn.transaction_with_behavior(TransactionBehavior::Immediate)?;
3018 let last_off_body_1 = KeystoreDB::get_last_off_body(&tx)?;
3019 tx.commit()?;
3020 let one_second = Duration::from_secs(1);
3021 thread::sleep(one_second);
3022 db.update_last_off_body(MonotonicRawTime::now())?;
3023 let tx2 = db.conn.transaction_with_behavior(TransactionBehavior::Immediate)?;
3024 let last_off_body_2 = KeystoreDB::get_last_off_body(&tx2)?;
3025 tx2.commit()?;
3026 assert!(last_off_body_1.seconds() < last_off_body_2.seconds());
3027 Ok(())
3028 }
Joel Galenson26f4d012020-07-17 14:57:21 -07003029}