blob: f70b0dfa732c8ffd0d707defd16f5b321d944b1c [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::{
Janis Danisevskis5ed8c532021-01-11 14:19:42 -080059 HardwareAuthToken::HardwareAuthToken,
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +000060 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},
Janis Danisevskis5ed8c532021-01-11 14:19:42 -080078 Connection, 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 }
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800550
551 /// Like i64::checked_sub.
552 pub fn checked_sub(&self, other: &Self) -> Option<Self> {
553 self.0.checked_sub(other.0).map(Self)
554 }
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000555}
556
557impl ToSql for MonotonicRawTime {
558 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
559 Ok(ToSqlOutput::Owned(Value::Integer(self.0)))
560 }
561}
562
563impl FromSql for MonotonicRawTime {
564 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
565 Ok(Self(i64::column_result(value)?))
566 }
567}
568
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000569/// This struct encapsulates the information to be stored in the database about the auth tokens
570/// received by keystore.
571pub struct AuthTokenEntry {
572 auth_token: HardwareAuthToken,
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000573 time_received: MonotonicRawTime,
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000574}
575
576impl AuthTokenEntry {
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000577 fn new(auth_token: HardwareAuthToken, time_received: MonotonicRawTime) -> Self {
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000578 AuthTokenEntry { auth_token, time_received }
579 }
580
581 /// Checks if this auth token satisfies the given authentication information.
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800582 pub fn satisfies(&self, user_secure_ids: &[i64], auth_type: HardwareAuthenticatorType) -> bool {
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000583 user_secure_ids.iter().any(|&sid| {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800584 (sid == self.auth_token.userId || sid == self.auth_token.authenticatorId)
585 && (((auth_type.0 as i32) & (self.auth_token.authenticatorType.0 as i32)) != 0)
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000586 })
587 }
588
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000589 /// Returns the auth token wrapped by the AuthTokenEntry
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800590 pub fn auth_token(&self) -> &HardwareAuthToken {
591 &self.auth_token
592 }
593
594 /// Returns the auth token wrapped by the AuthTokenEntry
595 pub fn take_auth_token(self) -> HardwareAuthToken {
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000596 self.auth_token
597 }
Janis Danisevskis5ed8c532021-01-11 14:19:42 -0800598
599 /// Returns the time that this auth token was received.
600 pub fn time_received(&self) -> MonotonicRawTime {
601 self.time_received
602 }
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000603}
604
Joel Galenson26f4d012020-07-17 14:57:21 -0700605impl KeystoreDB {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700606 /// This will create a new database connection connecting the two
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800607 /// files persistent.sqlite and perboot.sqlite in the given directory.
608 /// It also attempts to initialize all of the tables.
609 /// KeystoreDB cannot be used by multiple threads.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700610 /// Each thread should open their own connection using `thread_local!`.
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800611 pub fn new(db_root: &Path) -> Result<Self> {
612 // Build the path to the sqlite files.
613 let mut persistent_path = db_root.to_path_buf();
614 persistent_path.push("persistent.sqlite");
615 let mut perboot_path = db_root.to_path_buf();
616 perboot_path.push("perboot.sqlite");
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700617
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800618 // Now convert them to strings prefixed with "file:"
619 let mut persistent_path_str = "file:".to_owned();
620 persistent_path_str.push_str(&persistent_path.to_string_lossy());
621 let mut perboot_path_str = "file:".to_owned();
622 perboot_path_str.push_str(&perboot_path.to_string_lossy());
623
624 let conn = Self::make_connection(&persistent_path_str, &perboot_path_str)?;
625
626 Self::init_tables(&conn)?;
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700627 Ok(Self { conn })
Joel Galenson2aab4432020-07-22 15:27:57 -0700628 }
629
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700630 fn init_tables(conn: &Connection) -> Result<()> {
631 conn.execute(
632 "CREATE TABLE IF NOT EXISTS persistent.keyentry (
Joel Galenson0891bc12020-07-20 10:37:03 -0700633 id INTEGER UNIQUE,
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800634 key_type INTEGER,
Joel Galenson0891bc12020-07-20 10:37:03 -0700635 domain INTEGER,
636 namespace INTEGER,
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800637 alias BLOB,
638 state INTEGER);",
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700639 NO_PARAMS,
640 )
641 .context("Failed to initialize \"keyentry\" table.")?;
642
643 conn.execute(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700644 "CREATE TABLE IF NOT EXISTS persistent.blobentry (
645 id INTEGER PRIMARY KEY,
646 subcomponent_type INTEGER,
647 keyentryid INTEGER,
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800648 blob BLOB);",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700649 NO_PARAMS,
650 )
651 .context("Failed to initialize \"blobentry\" table.")?;
652
653 conn.execute(
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700654 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000655 keyentryid INTEGER,
656 tag INTEGER,
657 data ANY,
658 security_level INTEGER);",
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700659 NO_PARAMS,
660 )
661 .context("Failed to initialize \"keyparameter\" table.")?;
662
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700663 conn.execute(
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800664 "CREATE TABLE IF NOT EXISTS persistent.keymetadata (
665 keyentryid INTEGER,
666 tag INTEGER,
667 data ANY);",
668 NO_PARAMS,
669 )
670 .context("Failed to initialize \"keymetadata\" table.")?;
671
672 conn.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800673 "CREATE TABLE IF NOT EXISTS persistent.grant (
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700674 id INTEGER UNIQUE,
675 grantee INTEGER,
676 keyentryid INTEGER,
677 access_vector INTEGER);",
678 NO_PARAMS,
679 )
680 .context("Failed to initialize \"grant\" table.")?;
681
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000682 //TODO: only drop the following two perboot tables if this is the first start up
683 //during the boot (b/175716626).
684 // conn.execute("DROP TABLE IF EXISTS perboot.authtoken;", NO_PARAMS)
685 // .context("Failed to drop perboot.authtoken table")?;
686 conn.execute(
687 "CREATE TABLE IF NOT EXISTS perboot.authtoken (
688 id INTEGER PRIMARY KEY,
689 challenge INTEGER,
690 user_id INTEGER,
691 auth_id INTEGER,
692 authenticator_type INTEGER,
693 timestamp INTEGER,
694 mac BLOB,
695 time_received INTEGER,
696 UNIQUE(user_id, auth_id, authenticator_type));",
697 NO_PARAMS,
698 )
699 .context("Failed to initialize \"authtoken\" table.")?;
700
701 // conn.execute("DROP TABLE IF EXISTS perboot.metadata;", NO_PARAMS)
702 // .context("Failed to drop perboot.metadata table")?;
703 // metadata table stores certain miscellaneous information required for keystore functioning
704 // during a boot cycle, as key-value pairs.
705 conn.execute(
706 "CREATE TABLE IF NOT EXISTS perboot.metadata (
707 key TEXT,
708 value BLOB,
709 UNIQUE(key));",
710 NO_PARAMS,
711 )
712 .context("Failed to initialize \"metadata\" table.")?;
Joel Galenson0891bc12020-07-20 10:37:03 -0700713 Ok(())
714 }
715
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700716 fn make_connection(persistent_file: &str, perboot_file: &str) -> Result<Connection> {
717 let conn =
718 Connection::open_in_memory().context("Failed to initialize SQLite connection.")?;
719
720 conn.execute("ATTACH DATABASE ? as persistent;", params![persistent_file])
721 .context("Failed to attach database persistent.")?;
722 conn.execute("ATTACH DATABASE ? as perboot;", params![perboot_file])
723 .context("Failed to attach database perboot.")?;
724
725 Ok(conn)
726 }
727
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800728 /// Get one unreferenced key. There is no particular order in which the keys are returned.
729 fn get_unreferenced_key_id(tx: &Transaction) -> Result<Option<i64>> {
730 tx.query_row(
731 "SELECT id FROM persistent.keyentry WHERE state = ?",
732 params![KeyLifeCycle::Unreferenced],
733 |row| row.get(0),
734 )
735 .optional()
736 .context("In get_unreferenced_key_id: Trying to get unreferenced key id.")
737 }
738
739 /// Returns a key id guard and key entry for one unreferenced key entry. Of the optional
740 /// fields of the key entry only the km_blob field will be populated. This is required
741 /// to subject the blob to its KeyMint instance for deletion.
742 pub fn get_unreferenced_key(&mut self) -> Result<Option<(KeyIdGuard, KeyEntry)>> {
743 self.with_transaction(TransactionBehavior::Deferred, |tx| {
744 let key_id = match Self::get_unreferenced_key_id(tx)
745 .context("Trying to get unreferenced key id")?
746 {
747 None => return Ok(None),
748 Some(id) => KEY_ID_LOCK.try_get(id).ok_or_else(KsError::sys).context(concat!(
749 "A key id lock was held for an unreferenced key. ",
750 "This should never happen."
751 ))?,
752 };
753 let key_entry = Self::load_key_components(tx, KeyEntryLoadBits::KM, key_id.id())
754 .context("Trying to get key components.")?;
755 Ok(Some((key_id, key_entry)))
756 })
757 .context("In get_unreferenced_key.")
758 }
759
760 /// This function purges all remnants of a key entry from the database.
761 /// Important: This does not check if the key was unreferenced, nor does it
762 /// subject the key to its KeyMint instance for permanent invalidation.
763 /// This function should only be called by the garbage collector.
764 /// To delete a key call `mark_unreferenced`, which transitions the key to the unreferenced
765 /// state, deletes all grants to the key, and notifies the garbage collector.
766 /// The garbage collector will:
767 /// 1. Call get_unreferenced_key.
768 /// 2. Determine the proper way to dispose of sensitive key material, e.g., call
769 /// `KeyMintDevice::delete()`.
770 /// 3. Call `purge_key_entry`.
771 pub fn purge_key_entry(&mut self, key_id: KeyIdGuard) -> Result<()> {
772 self.with_transaction(TransactionBehavior::Immediate, |tx| {
773 tx.execute("DELETE FROM persistent.keyentry WHERE id = ?;", params![key_id.id()])
774 .context("Trying to delete keyentry.")?;
775 tx.execute(
776 "DELETE FROM persistent.blobentry WHERE keyentryid = ?;",
777 params![key_id.id()],
778 )
779 .context("Trying to delete blobentries.")?;
780 tx.execute(
781 "DELETE FROM persistent.keymetadata WHERE keyentryid = ?;",
782 params![key_id.id()],
783 )
784 .context("Trying to delete keymetadata.")?;
785 tx.execute(
786 "DELETE FROM persistent.keyparameter WHERE keyentryid = ?;",
787 params![key_id.id()],
788 )
789 .context("Trying to delete keyparameters.")?;
790 let grants_deleted = tx
791 .execute("DELETE FROM persistent.grant WHERE keyentryid = ?;", params![key_id.id()])
792 .context("Trying to delete grants.")?;
793 if grants_deleted != 0 {
794 log::error!("Purged key that still had grants. This should not happen.");
795 }
796 Ok(())
797 })
798 .context("In purge_key_entry.")
799 }
800
801 /// This maintenance function should be called only once before the database is used for the
802 /// first time. It restores the invariant that `KeyLifeCycle::Existing` is a transient state.
803 /// The function transitions all key entries from Existing to Unreferenced unconditionally and
804 /// returns the number of rows affected. If this returns a value greater than 0, it means that
805 /// Keystore crashed at some point during key generation. Callers may want to log such
806 /// occurrences.
807 /// Unlike with `mark_unreferenced`, we don't need to purge grants, because only keys that made
808 /// it to `KeyLifeCycle::Live` may have grants.
809 pub fn cleanup_leftovers(&mut self) -> Result<usize> {
810 self.conn
811 .execute(
812 "UPDATE persistent.keyentry SET state = ? WHERE state = ?;",
813 params![KeyLifeCycle::Unreferenced, KeyLifeCycle::Existing],
814 )
815 .context("In cleanup_leftovers.")
816 }
817
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800818 /// Atomically loads a key entry and associated metadata or creates it using the
819 /// callback create_new_key callback. The callback is called during a database
820 /// transaction. This means that implementers should be mindful about using
821 /// blocking operations such as IPC or grabbing mutexes.
822 pub fn get_or_create_key_with<F>(
823 &mut self,
824 domain: Domain,
825 namespace: i64,
826 alias: &str,
827 create_new_key: F,
828 ) -> Result<(KeyIdGuard, KeyEntry)>
829 where
830 F: FnOnce() -> Result<(Vec<u8>, KeyMetaData)>,
831 {
832 let tx = self
833 .conn
834 .transaction_with_behavior(TransactionBehavior::Immediate)
835 .context("In get_or_create_key_with: Failed to initialize transaction.")?;
836
837 let id = {
838 let mut stmt = tx
839 .prepare(
840 "SELECT id FROM persistent.keyentry
841 WHERE
842 key_type = ?
843 AND domain = ?
844 AND namespace = ?
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800845 AND alias = ?
846 AND state = ?;",
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800847 )
848 .context("In get_or_create_key_with: Failed to select from keyentry table.")?;
849 let mut rows = stmt
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800850 .query(params![KeyType::Super, domain.0, namespace, alias, KeyLifeCycle::Live])
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800851 .context("In get_or_create_key_with: Failed to query from keyentry table.")?;
852
853 db_utils::with_rows_extract_one(&mut rows, |row| {
854 Ok(match row {
855 Some(r) => r.get(0).context("Failed to unpack id.")?,
856 None => None,
857 })
858 })
859 .context("In get_or_create_key_with.")?
860 };
861
862 let (id, entry) = match id {
863 Some(id) => (
864 id,
865 Self::load_key_components(&tx, KeyEntryLoadBits::KM, id)
866 .context("In get_or_create_key_with.")?,
867 ),
868
869 None => {
870 let id = Self::insert_with_retry(|id| {
871 tx.execute(
872 "INSERT into persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800873 (id, key_type, domain, namespace, alias, state)
874 VALUES(?, ?, ?, ?, ?, ?);",
875 params![id, KeyType::Super, domain.0, namespace, alias, KeyLifeCycle::Live],
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800876 )
877 })
878 .context("In get_or_create_key_with.")?;
879
880 let (blob, metadata) = create_new_key().context("In get_or_create_key_with.")?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800881 Self::insert_blob_internal(&tx, id, SubComponentType::KEY_BLOB, &blob)
882 .context("In get_of_create_key_with.")?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800883 metadata.store_in_db(id, &tx).context("In get_or_create_key_with.")?;
884 (id, KeyEntry { id, km_blob: Some(blob), metadata, ..Default::default() })
885 }
886 };
887 tx.commit().context("In get_or_create_key_with: Failed to commit transaction.")?;
888 Ok((KEY_ID_LOCK.get(id), entry))
889 }
890
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800891 /// Creates a transaction with the given behavior and executes f with the new transaction.
892 /// The transaction is committed only if f returns Ok.
893 fn with_transaction<T, F>(&mut self, behavior: TransactionBehavior, f: F) -> Result<T>
894 where
895 F: FnOnce(&Transaction) -> Result<T>,
896 {
897 let tx = self
898 .conn
899 .transaction_with_behavior(behavior)
900 .context("In with_transaction: Failed to initialize transaction.")?;
901 f(&tx).and_then(|result| {
902 tx.commit().context("In with_transaction: Failed to commit transaction.")?;
903 Ok(result)
904 })
905 }
906
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700907 /// Creates a new key entry and allocates a new randomized id for the new key.
908 /// The key id gets associated with a domain and namespace but not with an alias.
909 /// To complete key generation `rebind_alias` should be called after all of the
910 /// key artifacts, i.e., blobs and parameters have been associated with the new
911 /// key id. Finalizing with `rebind_alias` makes the creation of a new key entry
912 /// atomic even if key generation is not.
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800913 pub fn create_key_entry(&mut self, domain: Domain, namespace: i64) -> Result<KeyIdGuard> {
914 self.with_transaction(TransactionBehavior::Immediate, |tx| {
915 Self::create_key_entry_internal(tx, domain, namespace)
916 })
917 .context("In create_key_entry.")
918 }
919
920 fn create_key_entry_internal(
921 tx: &Transaction,
922 domain: Domain,
923 namespace: i64,
924 ) -> Result<KeyIdGuard> {
Joel Galenson0891bc12020-07-20 10:37:03 -0700925 match domain {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700926 Domain::APP | Domain::SELINUX => {}
Joel Galenson0891bc12020-07-20 10:37:03 -0700927 _ => {
928 return Err(KsError::sys())
929 .context(format!("Domain {:?} must be either App or SELinux.", domain));
930 }
931 }
Janis Danisevskisaec14592020-11-12 09:41:49 -0800932 Ok(KEY_ID_LOCK.get(
933 Self::insert_with_retry(|id| {
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800934 tx.execute(
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800935 "INSERT into persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800936 (id, key_type, domain, namespace, alias, state)
937 VALUES(?, ?, ?, ?, NULL, ?);",
938 params![
939 id,
940 KeyType::Client,
941 domain.0 as u32,
942 namespace,
943 KeyLifeCycle::Existing
944 ],
Janis Danisevskisaec14592020-11-12 09:41:49 -0800945 )
946 })
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800947 .context("In create_key_entry_internal")?,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800948 ))
Joel Galenson26f4d012020-07-17 14:57:21 -0700949 }
Joel Galenson33c04ad2020-08-03 11:04:38 -0700950
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700951 /// Inserts a new blob and associates it with the given key id. Each blob
952 /// has a sub component type and a security level.
953 /// Each key can have one of each sub component type associated. If more
954 /// are added only the most recent can be retrieved, and superseded blobs
955 /// will get garbage collected. The security level field of components
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800956 /// other than `SubComponentType::KEY_BLOB` are ignored.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700957 pub fn insert_blob(
958 &mut self,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800959 key_id: &KeyIdGuard,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700960 sc_type: SubComponentType,
961 blob: &[u8],
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700962 ) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800963 self.with_transaction(TransactionBehavior::Immediate, |tx| {
964 Self::insert_blob_internal(&tx, key_id.0, sc_type, blob)
965 })
966 .context("In insert_blob.")
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800967 }
968
969 fn insert_blob_internal(
970 tx: &Transaction,
971 key_id: i64,
972 sc_type: SubComponentType,
973 blob: &[u8],
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800974 ) -> Result<()> {
975 tx.execute(
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800976 "INSERT into persistent.blobentry (subcomponent_type, keyentryid, blob)
977 VALUES (?, ?, ?);",
978 params![sc_type, key_id, blob],
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800979 )
980 .context("In insert_blob_internal: Failed to insert blob.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700981 Ok(())
982 }
983
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700984 /// Inserts a collection of key parameters into the `persistent.keyparameter` table
985 /// and associates them with the given `key_id`.
986 pub fn insert_keyparameter<'a>(
987 &mut self,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800988 key_id: &KeyIdGuard,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700989 params: impl IntoIterator<Item = &'a KeyParameter>,
990 ) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800991 self.with_transaction(TransactionBehavior::Immediate, |tx| {
992 Self::insert_keyparameter_internal(tx, key_id, params)
993 })
994 .context("In insert_keyparameter.")
995 }
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700996
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800997 fn insert_keyparameter_internal<'a>(
998 tx: &Transaction,
999 key_id: &KeyIdGuard,
1000 params: impl IntoIterator<Item = &'a KeyParameter>,
1001 ) -> Result<()> {
1002 let mut stmt = tx
1003 .prepare(
1004 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
1005 VALUES (?, ?, ?, ?);",
1006 )
1007 .context("In insert_keyparameter_internal: Failed to prepare statement.")?;
1008
1009 let iter = params.into_iter();
1010 for p in iter {
1011 stmt.insert(params![
1012 key_id.0,
1013 p.get_tag().0,
1014 p.key_parameter_value(),
1015 p.security_level().0
1016 ])
1017 .with_context(|| {
1018 format!("In insert_keyparameter_internal: Failed to insert {:?}", p)
1019 })?;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001020 }
1021 Ok(())
1022 }
1023
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001024 /// Insert a set of key entry specific metadata into the database.
1025 pub fn insert_key_metadata(
1026 &mut self,
1027 key_id: &KeyIdGuard,
1028 metadata: &KeyMetaData,
1029 ) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001030 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1031 metadata.store_in_db(key_id.0, &tx)
1032 })
1033 .context("In insert_key_metadata.")
1034 }
1035
1036 fn rebind_alias(
1037 &mut self,
1038 newid: &KeyIdGuard,
1039 alias: &str,
1040 domain: Domain,
1041 namespace: i64,
1042 ) -> Result<()> {
1043 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1044 Self::rebind_alias_internal(tx, newid, alias, domain, namespace)
1045 })
1046 .context("In rebind_alias.")
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001047 }
1048
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001049 /// Updates the alias column of the given key id `newid` with the given alias,
1050 /// and atomically, removes the alias, domain, and namespace from another row
1051 /// with the same alias-domain-namespace tuple if such row exits.
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001052 fn rebind_alias_internal(
1053 tx: &Transaction,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001054 newid: &KeyIdGuard,
Joel Galenson33c04ad2020-08-03 11:04:38 -07001055 alias: &str,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001056 domain: Domain,
Joel Galenson33c04ad2020-08-03 11:04:38 -07001057 namespace: i64,
1058 ) -> Result<()> {
1059 match domain {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001060 Domain::APP | Domain::SELINUX => {}
Joel Galenson33c04ad2020-08-03 11:04:38 -07001061 _ => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001062 return Err(KsError::sys()).context(format!(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001063 "In rebind_alias_internal: Domain {:?} must be either App or SELinux.",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001064 domain
1065 ));
Joel Galenson33c04ad2020-08-03 11:04:38 -07001066 }
1067 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001068 let updated = tx
1069 .execute(
1070 "UPDATE persistent.keyentry
1071 SET alias = NULL, domain = NULL, namespace = NULL, state = ?
Joel Galenson33c04ad2020-08-03 11:04:38 -07001072 WHERE alias = ? AND domain = ? AND namespace = ?;",
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001073 params![KeyLifeCycle::Unreferenced, alias, domain.0 as u32, namespace],
1074 )
1075 .context("In rebind_alias_internal: Failed to rebind existing entry.")?;
1076 if updated != 0 {
1077 Gc::notify_gc();
1078 }
Joel Galenson33c04ad2020-08-03 11:04:38 -07001079 let result = tx
1080 .execute(
1081 "UPDATE persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001082 SET alias = ?, state = ?
1083 WHERE id = ? AND domain = ? AND namespace = ? AND state = ?;",
1084 params![
1085 alias,
1086 KeyLifeCycle::Live,
1087 newid.0,
1088 domain.0 as u32,
1089 namespace,
1090 KeyLifeCycle::Existing
1091 ],
Joel Galenson33c04ad2020-08-03 11:04:38 -07001092 )
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001093 .context("In rebind_alias_internal: Failed to set alias.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07001094 if result != 1 {
Joel Galenson33c04ad2020-08-03 11:04:38 -07001095 return Err(KsError::sys()).context(format!(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001096 "In rebind_alias_internal: Expected to update a single entry but instead updated {}.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07001097 result
1098 ));
1099 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001100 Ok(())
1101 }
1102
1103 /// Store a new key in a single transaction.
1104 /// The function creates a new key entry, populates the blob, key parameter, and metadata
1105 /// fields, and rebinds the given alias to the new key.
1106 pub fn store_new_key<'a>(
1107 &mut self,
1108 key: KeyDescriptor,
1109 params: impl IntoIterator<Item = &'a KeyParameter>,
1110 blob: &[u8],
1111 cert: Option<&[u8]>,
1112 cert_chain: Option<&[u8]>,
1113 metadata: &KeyMetaData,
1114 ) -> Result<KeyIdGuard> {
1115 let (alias, domain, namespace) = match key {
1116 KeyDescriptor { alias: Some(alias), domain: Domain::APP, nspace, blob: None }
1117 | KeyDescriptor { alias: Some(alias), domain: Domain::SELINUX, nspace, blob: None } => {
1118 (alias, key.domain, nspace)
1119 }
1120 _ => {
1121 return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT))
1122 .context("In store_new_key: Need alias and domain must be APP or SELINUX.")
1123 }
1124 };
1125 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1126 let key_id = Self::create_key_entry_internal(tx, domain, namespace)
1127 .context("Trying to create new key entry.")?;
1128 Self::insert_blob_internal(tx, key_id.id(), SubComponentType::KEY_BLOB, blob)
1129 .context("Trying to insert the key blob.")?;
1130 if let Some(cert) = cert {
1131 Self::insert_blob_internal(tx, key_id.id(), SubComponentType::CERT, cert)
1132 .context("Trying to insert the certificate.")?;
1133 }
1134 if let Some(cert_chain) = cert_chain {
1135 Self::insert_blob_internal(
1136 tx,
1137 key_id.id(),
1138 SubComponentType::CERT_CHAIN,
1139 cert_chain,
1140 )
1141 .context("Trying to insert the certificate chain.")?;
1142 }
1143 Self::insert_keyparameter_internal(tx, &key_id, params)
1144 .context("Trying to insert key parameters.")?;
1145 metadata.store_in_db(key_id.id(), tx).context("Tryin to insert key metadata.")?;
1146 Self::rebind_alias_internal(tx, &key_id, &alias, domain, namespace)
1147 .context("Trying to rebind alias.")?;
1148 Ok(key_id)
1149 })
1150 .context("In store_new_key.")
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001151 }
1152
1153 // Helper function loading the key_id given the key descriptor
1154 // tuple comprising domain, namespace, and alias.
1155 // Requires a valid transaction.
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001156 fn load_key_entry_id(tx: &Transaction, key: &KeyDescriptor, key_type: KeyType) -> Result<i64> {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001157 let alias = key
1158 .alias
1159 .as_ref()
1160 .map_or_else(|| Err(KsError::sys()), Ok)
1161 .context("In load_key_entry_id: Alias must be specified.")?;
1162 let mut stmt = tx
1163 .prepare(
1164 "SELECT id FROM persistent.keyentry
1165 WHERE
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001166 key_type = ?
1167 AND domain = ?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001168 AND namespace = ?
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001169 AND alias = ?
1170 AND state = ?;",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001171 )
1172 .context("In load_key_entry_id: Failed to select from keyentry table.")?;
1173 let mut rows = stmt
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001174 .query(params![key_type, key.domain.0 as u32, key.nspace, alias, KeyLifeCycle::Live])
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001175 .context("In load_key_entry_id: Failed to read from keyentry table.")?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001176 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001177 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001178 .get(0)
1179 .context("Failed to unpack id.")
1180 })
1181 .context("In load_key_entry_id.")
1182 }
1183
1184 /// This helper function completes the access tuple of a key, which is required
1185 /// to perform access control. The strategy depends on the `domain` field in the
1186 /// key descriptor.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001187 /// * Domain::SELINUX: The access tuple is complete and this function only loads
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001188 /// the key_id for further processing.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001189 /// * Domain::APP: Like Domain::SELINUX, but the tuple is completed by `caller_uid`
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001190 /// which serves as the namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001191 /// * Domain::GRANT: The grant table is queried for the `key_id` and the
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001192 /// `access_vector`.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001193 /// * Domain::KEY_ID: The keyentry table is queried for the owning `domain` and
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001194 /// `namespace`.
1195 /// In each case the information returned is sufficient to perform the access
1196 /// check and the key id can be used to load further key artifacts.
1197 fn load_access_tuple(
1198 tx: &Transaction,
1199 key: KeyDescriptor,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001200 key_type: KeyType,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001201 caller_uid: u32,
1202 ) -> Result<(i64, KeyDescriptor, Option<KeyPermSet>)> {
1203 match key.domain {
1204 // Domain App or SELinux. In this case we load the key_id from
1205 // the keyentry database for further loading of key components.
1206 // We already have the full access tuple to perform access control.
1207 // The only distinction is that we use the caller_uid instead
1208 // of the caller supplied namespace if the domain field is
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001209 // Domain::APP.
1210 Domain::APP | Domain::SELINUX => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001211 let mut access_key = key;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001212 if access_key.domain == Domain::APP {
1213 access_key.nspace = caller_uid as i64;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001214 }
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001215 let key_id = Self::load_key_entry_id(&tx, &access_key, key_type)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001216 .with_context(|| format!("With key.domain = {:?}.", access_key.domain))?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001217
1218 Ok((key_id, access_key, None))
1219 }
1220
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001221 // Domain::GRANT. In this case we load the key_id and the access_vector
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001222 // from the grant table.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001223 Domain::GRANT => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001224 let mut stmt = tx
1225 .prepare(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001226 "SELECT keyentryid, access_vector FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001227 WHERE grantee = ? AND id = ?;",
1228 )
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001229 .context("Domain::GRANT prepare statement failed")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001230 let mut rows = stmt
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001231 .query(params![caller_uid as i64, key.nspace])
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001232 .context("Domain:Grant: query failed.")?;
1233 let (key_id, access_vector): (i64, i32) =
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001234 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001235 let r =
1236 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001237 Ok((
1238 r.get(0).context("Failed to unpack key_id.")?,
1239 r.get(1).context("Failed to unpack access_vector.")?,
1240 ))
1241 })
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001242 .context("Domain::GRANT.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001243 Ok((key_id, key, Some(access_vector.into())))
1244 }
1245
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001246 // Domain::KEY_ID. In this case we load the domain and namespace from the
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001247 // keyentry database because we need them for access control.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001248 Domain::KEY_ID => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001249 let mut stmt = tx
1250 .prepare(
1251 "SELECT domain, namespace FROM persistent.keyentry
1252 WHERE
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001253 id = ?
1254 AND state = ?;",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001255 )
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001256 .context("Domain::KEY_ID: prepare statement failed")?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001257 let mut rows = stmt
1258 .query(params![key.nspace, KeyLifeCycle::Live])
1259 .context("Domain::KEY_ID: query failed.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001260 let (domain, namespace): (Domain, i64) =
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001261 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001262 let r =
1263 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001264 Ok((
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001265 Domain(r.get(0).context("Failed to unpack domain.")?),
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001266 r.get(1).context("Failed to unpack namespace.")?,
1267 ))
1268 })
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001269 .context("Domain::KEY_ID.")?;
1270 let key_id = key.nspace;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001271 let mut access_key = key;
1272 access_key.domain = domain;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001273 access_key.nspace = namespace;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001274
1275 Ok((key_id, access_key, None))
1276 }
1277 _ => Err(anyhow!(KsError::sys())),
1278 }
1279 }
1280
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001281 fn load_blob_components(
1282 key_id: i64,
1283 load_bits: KeyEntryLoadBits,
1284 tx: &Transaction,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001285 ) -> Result<(Option<Vec<u8>>, Option<Vec<u8>>, Option<Vec<u8>>)> {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001286 let mut stmt = tx
1287 .prepare(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001288 "SELECT MAX(id), subcomponent_type, blob FROM persistent.blobentry
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001289 WHERE keyentryid = ? GROUP BY subcomponent_type;",
1290 )
1291 .context("In load_blob_components: prepare statement failed.")?;
1292
1293 let mut rows =
1294 stmt.query(params![key_id]).context("In load_blob_components: query failed.")?;
1295
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001296 let mut km_blob: Option<Vec<u8>> = None;
1297 let mut cert_blob: Option<Vec<u8>> = None;
1298 let mut cert_chain_blob: Option<Vec<u8>> = None;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001299 db_utils::with_rows_extract_all(&mut rows, |row| {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001300 let sub_type: SubComponentType =
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001301 row.get(1).context("Failed to extract subcomponent_type.")?;
1302 match (sub_type, load_bits.load_public(), load_bits.load_km()) {
1303 (SubComponentType::KEY_BLOB, _, true) => {
1304 km_blob = Some(row.get(2).context("Failed to extract KM blob.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001305 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001306 (SubComponentType::CERT, true, _) => {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001307 cert_blob =
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001308 Some(row.get(2).context("Failed to extract public certificate blob.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001309 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001310 (SubComponentType::CERT_CHAIN, true, _) => {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001311 cert_chain_blob =
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001312 Some(row.get(2).context("Failed to extract certificate chain blob.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001313 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001314 (SubComponentType::CERT, _, _)
1315 | (SubComponentType::CERT_CHAIN, _, _)
1316 | (SubComponentType::KEY_BLOB, _, _) => {}
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001317 _ => Err(KsError::sys()).context("Unknown subcomponent type.")?,
1318 }
1319 Ok(())
1320 })
1321 .context("In load_blob_components.")?;
1322
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001323 Ok((km_blob, cert_blob, cert_chain_blob))
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001324 }
1325
1326 fn load_key_parameters(key_id: i64, tx: &Transaction) -> Result<Vec<KeyParameter>> {
1327 let mut stmt = tx
1328 .prepare(
1329 "SELECT tag, data, security_level from persistent.keyparameter
1330 WHERE keyentryid = ?;",
1331 )
1332 .context("In load_key_parameters: prepare statement failed.")?;
1333
1334 let mut parameters: Vec<KeyParameter> = Vec::new();
1335
1336 let mut rows =
1337 stmt.query(params![key_id]).context("In load_key_parameters: query failed.")?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001338 db_utils::with_rows_extract_all(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001339 let tag = Tag(row.get(0).context("Failed to read tag.")?);
1340 let sec_level = SecurityLevel(row.get(2).context("Failed to read sec_level.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001341 parameters.push(
1342 KeyParameter::new_from_sql(tag, &SqlField::new(1, &row), sec_level)
1343 .context("Failed to read KeyParameter.")?,
1344 );
1345 Ok(())
1346 })
1347 .context("In load_key_parameters.")?;
1348
1349 Ok(parameters)
1350 }
1351
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001352 /// Load a key entry by the given key descriptor.
1353 /// It uses the `check_permission` callback to verify if the access is allowed
1354 /// given the key access tuple read from the database using `load_access_tuple`.
1355 /// With `load_bits` the caller may specify which blobs shall be loaded from
1356 /// the blob database.
1357 pub fn load_key_entry(
1358 &mut self,
1359 key: KeyDescriptor,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001360 key_type: KeyType,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001361 load_bits: KeyEntryLoadBits,
1362 caller_uid: u32,
1363 check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001364 ) -> Result<(KeyIdGuard, KeyEntry)> {
1365 // KEY ID LOCK 1/2
1366 // If we got a key descriptor with a key id we can get the lock right away.
1367 // Otherwise we have to defer it until we know the key id.
1368 let key_id_guard = match key.domain {
1369 Domain::KEY_ID => Some(KEY_ID_LOCK.get(key.nspace)),
1370 _ => None,
1371 };
1372
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001373 let tx = self
1374 .conn
Janis Danisevskisaec14592020-11-12 09:41:49 -08001375 .unchecked_transaction()
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001376 .context("In load_key_entry: Failed to initialize transaction.")?;
1377
1378 // Load the key_id and complete the access control tuple.
1379 let (key_id, access_key_descriptor, access_vector) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001380 Self::load_access_tuple(&tx, key, key_type, caller_uid)
1381 .context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001382
1383 // Perform access control. It is vital that we return here if the permission is denied.
1384 // So do not touch that '?' at the end.
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001385 check_permission(&access_key_descriptor, access_vector).context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001386
Janis Danisevskisaec14592020-11-12 09:41:49 -08001387 // KEY ID LOCK 2/2
1388 // If we did not get a key id lock by now, it was because we got a key descriptor
1389 // without a key id. At this point we got the key id, so we can try and get a lock.
1390 // However, we cannot block here, because we are in the middle of the transaction.
1391 // So first we try to get the lock non blocking. If that fails, we roll back the
1392 // transaction and block until we get the lock. After we successfully got the lock,
1393 // we start a new transaction and load the access tuple again.
1394 //
1395 // We don't need to perform access control again, because we already established
1396 // that the caller had access to the given key. But we need to make sure that the
1397 // key id still exists. So we have to load the key entry by key id this time.
1398 let (key_id_guard, tx) = match key_id_guard {
1399 None => match KEY_ID_LOCK.try_get(key_id) {
1400 None => {
1401 // Roll back the transaction.
1402 tx.rollback().context("In load_key_entry: Failed to roll back transaction.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001403
Janis Danisevskisaec14592020-11-12 09:41:49 -08001404 // Block until we have a key id lock.
1405 let key_id_guard = KEY_ID_LOCK.get(key_id);
1406
1407 // Create a new transaction.
1408 let tx = self.conn.unchecked_transaction().context(
1409 "In load_key_entry: Failed to initialize transaction. (deferred key lock)",
1410 )?;
1411
1412 Self::load_access_tuple(
1413 &tx,
1414 // This time we have to load the key by the retrieved key id, because the
1415 // alias may have been rebound after we rolled back the transaction.
1416 KeyDescriptor {
1417 domain: Domain::KEY_ID,
1418 nspace: key_id,
1419 ..Default::default()
1420 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001421 key_type,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001422 caller_uid,
1423 )
1424 .context("In load_key_entry. (deferred key lock)")?;
1425 (key_id_guard, tx)
1426 }
1427 Some(l) => (l, tx),
1428 },
1429 Some(key_id_guard) => (key_id_guard, tx),
1430 };
1431
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001432 let key_entry = Self::load_key_components(&tx, load_bits, key_id_guard.id())
1433 .context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001434
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001435 tx.commit().context("In load_key_entry: Failed to commit transaction.")?;
1436
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001437 Ok((key_id_guard, key_entry))
1438 }
1439
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001440 fn mark_unreferenced(tx: &Transaction, key_id: i64) -> Result<()> {
1441 let updated = tx
1442 .execute(
1443 "UPDATE persistent.keyentry SET state = ? WHERE id = ?;",
1444 params![KeyLifeCycle::Unreferenced, key_id],
1445 )
1446 .context("In mark_unreferenced: Failed to update state of key entry.")?;
1447 if updated != 0 {
1448 Gc::notify_gc();
1449 }
1450 tx.execute("DELETE from persistent.grant WHERE keyentryid = ?;", params![key_id])
1451 .context("In mark_unreferenced: Failed to drop grants.")?;
1452 Ok(())
1453 }
1454
1455 /// Marks the given key as unreferenced and removes all of the grants to this key.
1456 pub fn unbind_key(
1457 &mut self,
1458 key: KeyDescriptor,
1459 key_type: KeyType,
1460 caller_uid: u32,
1461 check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
1462 ) -> Result<()> {
1463 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1464 let (key_id, access_key_descriptor, access_vector) =
1465 Self::load_access_tuple(tx, key, key_type, caller_uid)
1466 .context("Trying to get access tuple.")?;
1467
1468 // Perform access control. It is vital that we return here if the permission is denied.
1469 // So do not touch that '?' at the end.
1470 check_permission(&access_key_descriptor, access_vector)
1471 .context("While checking permission.")?;
1472
1473 Self::mark_unreferenced(tx, key_id).context("Trying to mark the key unreferenced.")
1474 })
1475 .context("In unbind_key.")
1476 }
1477
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001478 fn load_key_components(
1479 tx: &Transaction,
1480 load_bits: KeyEntryLoadBits,
1481 key_id: i64,
1482 ) -> Result<KeyEntry> {
1483 let metadata = KeyMetaData::load_from_db(key_id, &tx).context("In load_key_components.")?;
1484
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001485 let (km_blob, cert_blob, cert_chain_blob) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001486 Self::load_blob_components(key_id, load_bits, &tx)
1487 .context("In load_key_components.")?;
1488
1489 let parameters =
1490 Self::load_key_parameters(key_id, &tx).context("In load_key_components.")?;
1491
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001492 // Extract the security level by checking the security level of the origin tag.
1493 // Super keys don't have key parameters so we use security_level software by default.
1494 let sec_level = parameters
1495 .iter()
1496 .find_map(|k| match k.get_tag() {
1497 Tag::ORIGIN => Some(*k.security_level()),
1498 _ => None,
1499 })
1500 .unwrap_or(SecurityLevel::SOFTWARE);
1501
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001502 Ok(KeyEntry {
1503 id: key_id,
1504 km_blob,
1505 cert: cert_blob,
1506 cert_chain: cert_chain_blob,
1507 sec_level,
1508 parameters,
1509 metadata,
1510 })
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001511 }
1512
Janis Danisevskise92a5e62020-12-02 12:57:41 -08001513 /// Returns a list of KeyDescriptors in the selected domain/namespace.
1514 /// The key descriptors will have the domain, nspace, and alias field set.
1515 /// Domain must be APP or SELINUX, the caller must make sure of that.
1516 pub fn list(&mut self, domain: Domain, namespace: i64) -> Result<Vec<KeyDescriptor>> {
1517 let mut stmt = self
1518 .conn
1519 .prepare(
1520 "SELECT alias FROM persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001521 WHERE domain = ? AND namespace = ? AND alias IS NOT NULL AND state = ?;",
Janis Danisevskise92a5e62020-12-02 12:57:41 -08001522 )
1523 .context("In list: Failed to prepare.")?;
1524
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001525 let mut rows = stmt
1526 .query(params![domain.0 as u32, namespace, KeyLifeCycle::Live])
1527 .context("In list: Failed to query.")?;
Janis Danisevskise92a5e62020-12-02 12:57:41 -08001528
1529 let mut descriptors: Vec<KeyDescriptor> = Vec::new();
1530 db_utils::with_rows_extract_all(&mut rows, |row| {
1531 descriptors.push(KeyDescriptor {
1532 domain,
1533 nspace: namespace,
1534 alias: Some(row.get(0).context("Trying to extract alias.")?),
1535 blob: None,
1536 });
1537 Ok(())
1538 })
1539 .context("In list.")?;
1540 Ok(descriptors)
1541 }
1542
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001543 /// Adds a grant to the grant table.
1544 /// Like `load_key_entry` this function loads the access tuple before
1545 /// it uses the callback for a permission check. Upon success,
1546 /// it inserts the `grantee_uid`, `key_id`, and `access_vector` into the
1547 /// grant table. The new row will have a randomized id, which is used as
1548 /// grant id in the namespace field of the resulting KeyDescriptor.
1549 pub fn grant(
1550 &mut self,
1551 key: KeyDescriptor,
1552 caller_uid: u32,
1553 grantee_uid: u32,
1554 access_vector: KeyPermSet,
1555 check_permission: impl FnOnce(&KeyDescriptor, &KeyPermSet) -> Result<()>,
1556 ) -> Result<KeyDescriptor> {
1557 let tx = self
1558 .conn
1559 .transaction_with_behavior(TransactionBehavior::Immediate)
1560 .context("In grant: Failed to initialize transaction.")?;
1561
1562 // Load the key_id and complete the access control tuple.
1563 // We ignore the access vector here because grants cannot be granted.
1564 // The access vector returned here expresses the permissions the
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001565 // grantee has if key.domain == Domain::GRANT. But this vector
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001566 // cannot include the grant permission by design, so there is no way the
1567 // subsequent permission check can pass.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001568 // We could check key.domain == Domain::GRANT and fail early.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001569 // But even if we load the access tuple by grant here, the permission
1570 // check denies the attempt to create a grant by grant descriptor.
1571 let (key_id, access_key_descriptor, _) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001572 Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid).context("In grant")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001573
1574 // Perform access control. It is vital that we return here if the permission
1575 // was denied. So do not touch that '?' at the end of the line.
1576 // This permission check checks if the caller has the grant permission
1577 // for the given key and in addition to all of the permissions
1578 // expressed in `access_vector`.
1579 check_permission(&access_key_descriptor, &access_vector)
1580 .context("In grant: check_permission failed.")?;
1581
1582 let grant_id = if let Some(grant_id) = tx
1583 .query_row(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001584 "SELECT id FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001585 WHERE keyentryid = ? AND grantee = ?;",
1586 params![key_id, grantee_uid],
1587 |row| row.get(0),
1588 )
1589 .optional()
1590 .context("In grant: Failed get optional existing grant id.")?
1591 {
1592 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001593 "UPDATE persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001594 SET access_vector = ?
1595 WHERE id = ?;",
1596 params![i32::from(access_vector), grant_id],
1597 )
1598 .context("In grant: Failed to update existing grant.")?;
1599 grant_id
1600 } else {
Joel Galenson845f74b2020-09-09 14:11:55 -07001601 Self::insert_with_retry(|id| {
1602 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001603 "INSERT INTO persistent.grant (id, grantee, keyentryid, access_vector)
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001604 VALUES (?, ?, ?, ?);",
Joel Galenson845f74b2020-09-09 14:11:55 -07001605 params![id, grantee_uid, key_id, i32::from(access_vector)],
1606 )
1607 })
1608 .context("In grant")?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001609 };
1610 tx.commit().context("In grant: failed to commit transaction.")?;
1611
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001612 Ok(KeyDescriptor { domain: Domain::GRANT, nspace: grant_id, alias: None, blob: None })
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001613 }
1614
1615 /// This function checks permissions like `grant` and `load_key_entry`
1616 /// before removing a grant from the grant table.
1617 pub fn ungrant(
1618 &mut self,
1619 key: KeyDescriptor,
1620 caller_uid: u32,
1621 grantee_uid: u32,
1622 check_permission: impl FnOnce(&KeyDescriptor) -> Result<()>,
1623 ) -> Result<()> {
1624 let tx = self
1625 .conn
1626 .transaction_with_behavior(TransactionBehavior::Immediate)
1627 .context("In ungrant: Failed to initialize transaction.")?;
1628
1629 // Load the key_id and complete the access control tuple.
1630 // We ignore the access vector here because grants cannot be granted.
1631 let (key_id, access_key_descriptor, _) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001632 Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid)
1633 .context("In ungrant.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001634
1635 // Perform access control. We must return here if the permission
1636 // was denied. So do not touch the '?' at the end of this line.
1637 check_permission(&access_key_descriptor).context("In grant: check_permission failed.")?;
1638
1639 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001640 "DELETE FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001641 WHERE keyentryid = ? AND grantee = ?;",
1642 params![key_id, grantee_uid],
1643 )
1644 .context("Failed to delete grant.")?;
1645
1646 tx.commit().context("In ungrant: failed to commit transaction.")?;
1647
1648 Ok(())
1649 }
1650
Joel Galenson845f74b2020-09-09 14:11:55 -07001651 // Generates a random id and passes it to the given function, which will
1652 // try to insert it into a database. If that insertion fails, retry;
1653 // otherwise return the id.
1654 fn insert_with_retry(inserter: impl Fn(i64) -> rusqlite::Result<usize>) -> Result<i64> {
1655 loop {
1656 let newid: i64 = random();
1657 match inserter(newid) {
1658 // If the id already existed, try again.
1659 Err(rusqlite::Error::SqliteFailure(
1660 libsqlite3_sys::Error {
1661 code: libsqlite3_sys::ErrorCode::ConstraintViolation,
1662 extended_code: libsqlite3_sys::SQLITE_CONSTRAINT_UNIQUE,
1663 },
1664 _,
1665 )) => (),
1666 Err(e) => {
1667 return Err(e).context("In insert_with_retry: failed to insert into database.")
1668 }
1669 _ => return Ok(newid),
1670 }
1671 }
1672 }
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001673
1674 /// Insert or replace the auth token based on the UNIQUE constraint of the auth token table
1675 pub fn insert_auth_token(&mut self, auth_token: &HardwareAuthToken) -> Result<()> {
1676 self.conn
1677 .execute(
1678 "INSERT OR REPLACE INTO perboot.authtoken (challenge, user_id, auth_id,
1679 authenticator_type, timestamp, mac, time_received) VALUES(?, ?, ?, ?, ?, ?, ?);",
1680 params![
1681 auth_token.challenge,
1682 auth_token.userId,
1683 auth_token.authenticatorId,
1684 auth_token.authenticatorType.0 as i32,
1685 auth_token.timestamp.milliSeconds as i64,
1686 auth_token.mac,
1687 MonotonicRawTime::now(),
1688 ],
1689 )
1690 .context("In insert_auth_token: failed to insert auth token into the database")?;
1691 Ok(())
1692 }
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001693
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001694 /// Find the newest auth token matching the given predicate.
1695 pub fn find_auth_token_entry<F>(
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001696 &mut self,
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001697 p: F,
1698 ) -> Result<Option<(AuthTokenEntry, MonotonicRawTime)>>
1699 where
1700 F: Fn(&AuthTokenEntry) -> bool,
1701 {
1702 self.with_transaction(TransactionBehavior::Deferred, |tx| {
1703 let mut stmt = tx
1704 .prepare("SELECT * from perboot.authtoken ORDER BY time_received DESC;")
1705 .context("Prepare statement failed.")?;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001706
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001707 let mut rows = stmt.query(NO_PARAMS).context("Failed to query.")?;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001708
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001709 while let Some(row) = rows.next().context("Failed to get next row.")? {
1710 let entry = AuthTokenEntry::new(
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001711 HardwareAuthToken {
1712 challenge: row.get(1)?,
1713 userId: row.get(2)?,
1714 authenticatorId: row.get(3)?,
1715 authenticatorType: HardwareAuthenticatorType(row.get(4)?),
1716 timestamp: Timestamp { milliSeconds: row.get(5)? },
1717 mac: row.get(6)?,
1718 },
1719 row.get(7)?,
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001720 );
1721 if p(&entry) {
1722 return Ok(Some((
1723 entry,
1724 Self::get_last_off_body(tx)
1725 .context("In find_auth_token_entry: Trying to get last off body")?,
1726 )));
1727 }
1728 }
1729 Ok(None)
1730 })
1731 .context("In find_auth_token_entry.")
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001732 }
1733
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001734 /// Insert last_off_body into the metadata table at the initialization of auth token table
1735 pub fn insert_last_off_body(&self, last_off_body: MonotonicRawTime) -> Result<()> {
1736 self.conn
1737 .execute(
1738 "INSERT OR REPLACE INTO perboot.metadata (key, value) VALUES (?, ?);",
1739 params!["last_off_body", last_off_body],
1740 )
1741 .context("In insert_last_off_body: failed to insert.")?;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001742 Ok(())
1743 }
1744
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001745 /// Update last_off_body when on_device_off_body is called
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001746 pub fn update_last_off_body(&self, last_off_body: MonotonicRawTime) -> Result<()> {
1747 self.conn
1748 .execute(
1749 "UPDATE perboot.metadata SET value = ? WHERE key = ?;",
1750 params![last_off_body, "last_off_body"],
1751 )
1752 .context("In update_last_off_body: failed to update.")?;
1753 Ok(())
1754 }
1755
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001756 /// Get last_off_body time when finding auth tokens
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001757 fn get_last_off_body(tx: &Transaction) -> Result<MonotonicRawTime> {
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08001758 tx.query_row(
1759 "SELECT value from perboot.metadata WHERE key = ?;",
1760 params!["last_off_body"],
1761 |row| Ok(row.get(0)?),
1762 )
1763 .context("In get_last_off_body: query_row failed.")
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001764 }
Joel Galenson26f4d012020-07-17 14:57:21 -07001765}
1766
1767#[cfg(test)]
1768mod tests {
1769
1770 use super::*;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001771 use crate::key_parameter::{
1772 Algorithm, BlockMode, Digest, EcCurve, HardwareAuthenticatorType, KeyOrigin, KeyParameter,
1773 KeyParameterValue, KeyPurpose, PaddingMode, SecurityLevel,
1774 };
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001775 use crate::key_perm_set;
1776 use crate::permission::{KeyPerm, KeyPermSet};
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001777 use crate::test::utils::TempDir;
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001778 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
1779 HardwareAuthToken::HardwareAuthToken,
1780 HardwareAuthenticatorType::HardwareAuthenticatorType as kmhw_authenticator_type,
Janis Danisevskisc3a496b2021-01-05 10:37:22 -08001781 };
1782 use android_hardware_security_secureclock::aidl::android::hardware::security::secureclock::{
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001783 Timestamp::Timestamp,
1784 };
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001785 use rusqlite::NO_PARAMS;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001786 use rusqlite::{Error, TransactionBehavior};
Joel Galenson0891bc12020-07-20 10:37:03 -07001787 use std::cell::RefCell;
Janis Danisevskisaec14592020-11-12 09:41:49 -08001788 use std::sync::atomic::{AtomicU8, Ordering};
1789 use std::sync::Arc;
1790 use std::thread;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001791 use std::time::{Duration, SystemTime};
Joel Galenson0891bc12020-07-20 10:37:03 -07001792
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001793 fn new_test_db() -> Result<KeystoreDB> {
1794 let conn = KeystoreDB::make_connection("file::memory:", "file::memory:")?;
1795
1796 KeystoreDB::init_tables(&conn).context("Failed to initialize tables.")?;
1797 Ok(KeystoreDB { conn })
1798 }
1799
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001800 #[test]
1801 fn datetime() -> Result<()> {
1802 let conn = Connection::open_in_memory()?;
1803 conn.execute("CREATE TABLE test (ts DATETIME);", NO_PARAMS)?;
1804 let now = SystemTime::now();
1805 let duration = Duration::from_secs(1000);
1806 let then = now.checked_sub(duration).unwrap();
1807 let soon = now.checked_add(duration).unwrap();
1808 conn.execute(
1809 "INSERT INTO test (ts) VALUES (?), (?), (?);",
1810 params![DateTime::try_from(now)?, DateTime::try_from(then)?, DateTime::try_from(soon)?],
1811 )?;
1812 let mut stmt = conn.prepare("SELECT ts FROM test ORDER BY ts ASC;")?;
1813 let mut rows = stmt.query(NO_PARAMS)?;
1814 assert_eq!(DateTime::try_from(then)?, rows.next()?.unwrap().get(0)?);
1815 assert_eq!(DateTime::try_from(now)?, rows.next()?.unwrap().get(0)?);
1816 assert_eq!(DateTime::try_from(soon)?, rows.next()?.unwrap().get(0)?);
1817 assert!(rows.next()?.is_none());
1818 assert!(DateTime::try_from(then)? < DateTime::try_from(now)?);
1819 assert!(DateTime::try_from(then)? < DateTime::try_from(soon)?);
1820 assert!(DateTime::try_from(now)? < DateTime::try_from(soon)?);
1821 Ok(())
1822 }
1823
Joel Galenson0891bc12020-07-20 10:37:03 -07001824 // Ensure that we're using the "injected" random function, not the real one.
1825 #[test]
1826 fn test_mocked_random() {
1827 let rand1 = random();
1828 let rand2 = random();
1829 let rand3 = random();
1830 if rand1 == rand2 {
1831 assert_eq!(rand2 + 1, rand3);
1832 } else {
1833 assert_eq!(rand1 + 1, rand2);
1834 assert_eq!(rand2, rand3);
1835 }
1836 }
Joel Galenson26f4d012020-07-17 14:57:21 -07001837
Joel Galenson26f4d012020-07-17 14:57:21 -07001838 // Test that we have the correct tables.
1839 #[test]
1840 fn test_tables() -> Result<()> {
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001841 let db = new_test_db()?;
Joel Galenson26f4d012020-07-17 14:57:21 -07001842 let tables = db
1843 .conn
Joel Galenson2aab4432020-07-22 15:27:57 -07001844 .prepare("SELECT name from persistent.sqlite_master WHERE type='table' ORDER BY name;")?
Joel Galenson26f4d012020-07-17 14:57:21 -07001845 .query_map(params![], |row| row.get(0))?
1846 .collect::<rusqlite::Result<Vec<String>>>()?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001847 assert_eq!(tables.len(), 5);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001848 assert_eq!(tables[0], "blobentry");
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001849 assert_eq!(tables[1], "grant");
1850 assert_eq!(tables[2], "keyentry");
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001851 assert_eq!(tables[3], "keymetadata");
1852 assert_eq!(tables[4], "keyparameter");
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001853 let tables = db
1854 .conn
1855 .prepare("SELECT name from perboot.sqlite_master WHERE type='table' ORDER BY name;")?
1856 .query_map(params![], |row| row.get(0))?
1857 .collect::<rusqlite::Result<Vec<String>>>()?;
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001858
1859 assert_eq!(tables.len(), 2);
1860 assert_eq!(tables[0], "authtoken");
1861 assert_eq!(tables[1], "metadata");
Joel Galenson2aab4432020-07-22 15:27:57 -07001862 Ok(())
1863 }
1864
1865 #[test]
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001866 fn test_auth_token_table_invariant() -> Result<()> {
1867 let mut db = new_test_db()?;
1868 let auth_token1 = HardwareAuthToken {
1869 challenge: i64::MAX,
1870 userId: 200,
1871 authenticatorId: 200,
1872 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
1873 timestamp: Timestamp { milliSeconds: 500 },
1874 mac: String::from("mac").into_bytes(),
1875 };
1876 db.insert_auth_token(&auth_token1)?;
1877 let auth_tokens_returned = get_auth_tokens(&mut db)?;
1878 assert_eq!(auth_tokens_returned.len(), 1);
1879
1880 // insert another auth token with the same values for the columns in the UNIQUE constraint
1881 // of the auth token table and different value for timestamp
1882 let auth_token2 = HardwareAuthToken {
1883 challenge: i64::MAX,
1884 userId: 200,
1885 authenticatorId: 200,
1886 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
1887 timestamp: Timestamp { milliSeconds: 600 },
1888 mac: String::from("mac").into_bytes(),
1889 };
1890
1891 db.insert_auth_token(&auth_token2)?;
1892 let mut auth_tokens_returned = get_auth_tokens(&mut db)?;
1893 assert_eq!(auth_tokens_returned.len(), 1);
1894
1895 if let Some(auth_token) = auth_tokens_returned.pop() {
1896 assert_eq!(auth_token.auth_token.timestamp.milliSeconds, 600);
1897 }
1898
1899 // insert another auth token with the different values for the columns in the UNIQUE
1900 // constraint of the auth token table
1901 let auth_token3 = HardwareAuthToken {
1902 challenge: i64::MAX,
1903 userId: 201,
1904 authenticatorId: 200,
1905 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
1906 timestamp: Timestamp { milliSeconds: 600 },
1907 mac: String::from("mac").into_bytes(),
1908 };
1909
1910 db.insert_auth_token(&auth_token3)?;
1911 let auth_tokens_returned = get_auth_tokens(&mut db)?;
1912 assert_eq!(auth_tokens_returned.len(), 2);
1913
1914 Ok(())
1915 }
1916
1917 // utility function for test_auth_token_table_invariant()
1918 fn get_auth_tokens(db: &mut KeystoreDB) -> Result<Vec<AuthTokenEntry>> {
1919 let mut stmt = db.conn.prepare("SELECT * from perboot.authtoken;")?;
1920
1921 let auth_token_entries: Vec<AuthTokenEntry> = stmt
1922 .query_map(NO_PARAMS, |row| {
1923 Ok(AuthTokenEntry::new(
1924 HardwareAuthToken {
1925 challenge: row.get(1)?,
1926 userId: row.get(2)?,
1927 authenticatorId: row.get(3)?,
1928 authenticatorType: HardwareAuthenticatorType(row.get(4)?),
1929 timestamp: Timestamp { milliSeconds: row.get(5)? },
1930 mac: row.get(6)?,
1931 },
1932 row.get(7)?,
1933 ))
1934 })?
1935 .collect::<Result<Vec<AuthTokenEntry>, Error>>()?;
1936 Ok(auth_token_entries)
1937 }
1938
1939 #[test]
Joel Galenson2aab4432020-07-22 15:27:57 -07001940 fn test_persistence_for_files() -> Result<()> {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001941 let temp_dir = TempDir::new("persistent_db_test")?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001942 let mut db = KeystoreDB::new(temp_dir.path())?;
Joel Galenson2aab4432020-07-22 15:27:57 -07001943
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001944 db.create_key_entry(Domain::APP, 100)?;
Joel Galenson2aab4432020-07-22 15:27:57 -07001945 let entries = get_keyentry(&db)?;
1946 assert_eq!(entries.len(), 1);
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001947
1948 let db = KeystoreDB::new(temp_dir.path())?;
Joel Galenson2aab4432020-07-22 15:27:57 -07001949
1950 let entries_new = get_keyentry(&db)?;
1951 assert_eq!(entries, entries_new);
1952 Ok(())
1953 }
1954
1955 #[test]
Joel Galenson0891bc12020-07-20 10:37:03 -07001956 fn test_create_key_entry() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001957 fn extractor(ke: &KeyEntryRow) -> (Domain, i64, Option<&str>) {
Joel Galenson0891bc12020-07-20 10:37:03 -07001958 (ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref())
1959 }
1960
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001961 let mut db = new_test_db()?;
Joel Galenson0891bc12020-07-20 10:37:03 -07001962
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001963 db.create_key_entry(Domain::APP, 100)?;
1964 db.create_key_entry(Domain::SELINUX, 101)?;
Joel Galenson0891bc12020-07-20 10:37:03 -07001965
1966 let entries = get_keyentry(&db)?;
1967 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001968 assert_eq!(extractor(&entries[0]), (Domain::APP, 100, None));
1969 assert_eq!(extractor(&entries[1]), (Domain::SELINUX, 101, None));
Joel Galenson0891bc12020-07-20 10:37:03 -07001970
1971 // Test that we must pass in a valid Domain.
1972 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001973 db.create_key_entry(Domain::GRANT, 102),
1974 "Domain Domain(1) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07001975 );
1976 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001977 db.create_key_entry(Domain::BLOB, 103),
1978 "Domain Domain(3) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07001979 );
1980 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001981 db.create_key_entry(Domain::KEY_ID, 104),
1982 "Domain Domain(4) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07001983 );
1984
1985 Ok(())
1986 }
1987
Joel Galenson33c04ad2020-08-03 11:04:38 -07001988 #[test]
1989 fn test_rebind_alias() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001990 fn extractor(ke: &KeyEntryRow) -> (Option<Domain>, Option<i64>, Option<&str>) {
Joel Galenson33c04ad2020-08-03 11:04:38 -07001991 (ke.domain, ke.namespace, ke.alias.as_deref())
1992 }
1993
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001994 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001995 db.create_key_entry(Domain::APP, 42)?;
1996 db.create_key_entry(Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07001997 let entries = get_keyentry(&db)?;
1998 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001999 assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), None));
2000 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
Joel Galenson33c04ad2020-08-03 11:04:38 -07002001
2002 // Test that the first call to rebind_alias sets the alias.
Janis Danisevskisaec14592020-11-12 09:41:49 -08002003 db.rebind_alias(&KEY_ID_LOCK.get(entries[0].id), "foo", Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07002004 let entries = get_keyentry(&db)?;
2005 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002006 assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), Some("foo")));
2007 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
Joel Galenson33c04ad2020-08-03 11:04:38 -07002008
2009 // Test that the second call to rebind_alias also empties the old one.
Janis Danisevskisaec14592020-11-12 09:41:49 -08002010 db.rebind_alias(&KEY_ID_LOCK.get(entries[1].id), "foo", Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07002011 let entries = get_keyentry(&db)?;
2012 assert_eq!(entries.len(), 2);
Joel Galenson7fa5c412020-11-19 10:56:54 -08002013 assert_eq!(extractor(&entries[0]), (None, None, None));
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002014 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
Joel Galenson33c04ad2020-08-03 11:04:38 -07002015
2016 // Test that we must pass in a valid Domain.
2017 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08002018 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::GRANT, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002019 "Domain Domain(1) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07002020 );
2021 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08002022 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::BLOB, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002023 "Domain Domain(3) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07002024 );
2025 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08002026 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::KEY_ID, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002027 "Domain Domain(4) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07002028 );
2029
2030 // Test that we correctly handle setting an alias for something that does not exist.
2031 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08002032 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::SELINUX, 42),
Joel Galenson33c04ad2020-08-03 11:04:38 -07002033 "Expected to update a single entry but instead updated 0",
2034 );
2035 // Test that we correctly abort the transaction in this case.
2036 let entries = get_keyentry(&db)?;
2037 assert_eq!(entries.len(), 2);
Joel Galenson7fa5c412020-11-19 10:56:54 -08002038 assert_eq!(extractor(&entries[0]), (None, None, None));
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002039 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
Joel Galenson33c04ad2020-08-03 11:04:38 -07002040
2041 Ok(())
2042 }
2043
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002044 #[test]
2045 fn test_grant_ungrant() -> Result<()> {
2046 const CALLER_UID: u32 = 15;
2047 const GRANTEE_UID: u32 = 12;
2048 const SELINUX_NAMESPACE: i64 = 7;
2049
2050 let mut db = new_test_db()?;
2051 db.conn.execute(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002052 "INSERT INTO persistent.keyentry (id, key_type, domain, namespace, alias, state)
2053 VALUES (1, 0, 0, 15, 'key', 1), (2, 0, 2, 7, 'yek', 1);",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002054 NO_PARAMS,
2055 )?;
2056 let app_key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002057 domain: super::Domain::APP,
2058 nspace: 0,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002059 alias: Some("key".to_string()),
2060 blob: None,
2061 };
2062 const PVEC1: KeyPermSet = key_perm_set![KeyPerm::use_(), KeyPerm::get_info()];
2063 const PVEC2: KeyPermSet = key_perm_set![KeyPerm::use_()];
2064
2065 // Reset totally predictable random number generator in case we
2066 // are not the first test running on this thread.
2067 reset_random();
2068 let next_random = 0i64;
2069
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002070 let app_granted_key = db
2071 .grant(app_key.clone(), CALLER_UID, GRANTEE_UID, PVEC1, |k, a| {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002072 assert_eq!(*a, PVEC1);
2073 assert_eq!(
2074 *k,
2075 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002076 domain: super::Domain::APP,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002077 // namespace must be set to the caller_uid.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002078 nspace: CALLER_UID as i64,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002079 alias: Some("key".to_string()),
2080 blob: None,
2081 }
2082 );
2083 Ok(())
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002084 })
2085 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002086
2087 assert_eq!(
2088 app_granted_key,
2089 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002090 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002091 // The grantid is next_random due to the mock random number generator.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002092 nspace: next_random,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002093 alias: None,
2094 blob: None,
2095 }
2096 );
2097
2098 let selinux_key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002099 domain: super::Domain::SELINUX,
2100 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002101 alias: Some("yek".to_string()),
2102 blob: None,
2103 };
2104
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002105 let selinux_granted_key = db
2106 .grant(selinux_key.clone(), CALLER_UID, 12, 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::SELINUX,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002112 // namespace must be the supplied SELinux
2113 // namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002114 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002115 alias: Some("yek".to_string()),
2116 blob: None,
2117 }
2118 );
2119 Ok(())
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002120 })
2121 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002122
2123 assert_eq!(
2124 selinux_granted_key,
2125 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002126 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002127 // The grantid is next_random + 1 due to the mock random number generator.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002128 nspace: next_random + 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002129 alias: None,
2130 blob: None,
2131 }
2132 );
2133
2134 // This should update the existing grant with PVEC2.
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002135 let selinux_granted_key = db
2136 .grant(selinux_key.clone(), CALLER_UID, 12, PVEC2, |k, a| {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002137 assert_eq!(*a, PVEC2);
2138 assert_eq!(
2139 *k,
2140 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002141 domain: super::Domain::SELINUX,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002142 // namespace must be the supplied SELinux
2143 // namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002144 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002145 alias: Some("yek".to_string()),
2146 blob: None,
2147 }
2148 );
2149 Ok(())
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002150 })
2151 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002152
2153 assert_eq!(
2154 selinux_granted_key,
2155 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002156 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002157 // Same grant id as before. The entry was only updated.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002158 nspace: next_random + 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002159 alias: None,
2160 blob: None,
2161 }
2162 );
2163
2164 {
2165 // Limiting scope of stmt, because it borrows db.
2166 let mut stmt = db
2167 .conn
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002168 .prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?;
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07002169 let mut rows =
2170 stmt.query_map::<(i64, u32, i64, KeyPermSet), _, _>(NO_PARAMS, |row| {
2171 Ok((
2172 row.get(0)?,
2173 row.get(1)?,
2174 row.get(2)?,
2175 KeyPermSet::from(row.get::<_, i32>(3)?),
2176 ))
2177 })?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002178
2179 let r = rows.next().unwrap().unwrap();
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07002180 assert_eq!(r, (next_random, GRANTEE_UID, 1, PVEC1));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002181 let r = rows.next().unwrap().unwrap();
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07002182 assert_eq!(r, (next_random + 1, GRANTEE_UID, 2, PVEC2));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002183 assert!(rows.next().is_none());
2184 }
2185
2186 debug_dump_keyentry_table(&mut db)?;
2187 println!("app_key {:?}", app_key);
2188 println!("selinux_key {:?}", selinux_key);
2189
2190 db.ungrant(app_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
2191 db.ungrant(selinux_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
2192
2193 Ok(())
2194 }
2195
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002196 static TEST_KEY_BLOB: &[u8] = b"my test blob";
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002197 static TEST_CERT_BLOB: &[u8] = b"my test cert";
2198 static TEST_CERT_CHAIN_BLOB: &[u8] = b"my test cert_chain";
2199
2200 #[test]
2201 fn test_insert_blob() -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002202 let key_id = KEY_ID_LOCK.get(3000);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002203 let mut db = new_test_db()?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002204 db.insert_blob(&key_id, SubComponentType::KEY_BLOB, TEST_KEY_BLOB)?;
2205 db.insert_blob(&key_id, SubComponentType::CERT, TEST_CERT_BLOB)?;
2206 db.insert_blob(&key_id, SubComponentType::CERT_CHAIN, TEST_CERT_CHAIN_BLOB)?;
2207 drop(key_id);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002208
2209 let mut stmt = db.conn.prepare(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002210 "SELECT subcomponent_type, keyentryid, blob FROM persistent.blobentry
2211 ORDER BY subcomponent_type ASC;",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002212 )?;
2213 let mut rows = stmt
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002214 .query_map::<(SubComponentType, i64, Vec<u8>), _, _>(NO_PARAMS, |row| {
2215 Ok((row.get(0)?, row.get(1)?, row.get(2)?))
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002216 })?;
2217 let r = rows.next().unwrap().unwrap();
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002218 assert_eq!(r, (SubComponentType::KEY_BLOB, 3000, TEST_KEY_BLOB.to_vec()));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002219 let r = rows.next().unwrap().unwrap();
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002220 assert_eq!(r, (SubComponentType::CERT, 3000, TEST_CERT_BLOB.to_vec()));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002221 let r = rows.next().unwrap().unwrap();
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002222 assert_eq!(r, (SubComponentType::CERT_CHAIN, 3000, TEST_CERT_CHAIN_BLOB.to_vec()));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002223
2224 Ok(())
2225 }
2226
2227 static TEST_ALIAS: &str = "my super duper key";
2228
2229 #[test]
2230 fn test_insert_and_load_full_keyentry_domain_app() -> Result<()> {
2231 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002232 let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002233 .context("test_insert_and_load_full_keyentry_domain_app")?
2234 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002235 let (_key_guard, key_entry) = db
2236 .load_key_entry(
2237 KeyDescriptor {
2238 domain: Domain::APP,
2239 nspace: 0,
2240 alias: Some(TEST_ALIAS.to_string()),
2241 blob: None,
2242 },
2243 KeyType::Client,
2244 KeyEntryLoadBits::BOTH,
2245 1,
2246 |_k, _av| Ok(()),
2247 )
2248 .unwrap();
2249 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
2250
2251 db.unbind_key(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002252 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002253 domain: Domain::APP,
2254 nspace: 0,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002255 alias: Some(TEST_ALIAS.to_string()),
2256 blob: None,
2257 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002258 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002259 1,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002260 |_, _| Ok(()),
2261 )
2262 .unwrap();
2263
2264 assert_eq!(
2265 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2266 db.load_key_entry(
2267 KeyDescriptor {
2268 domain: Domain::APP,
2269 nspace: 0,
2270 alias: Some(TEST_ALIAS.to_string()),
2271 blob: None,
2272 },
2273 KeyType::Client,
2274 KeyEntryLoadBits::NONE,
2275 1,
2276 |_k, _av| Ok(()),
2277 )
2278 .unwrap_err()
2279 .root_cause()
2280 .downcast_ref::<KsError>()
2281 );
2282
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002283 Ok(())
2284 }
2285
2286 #[test]
2287 fn test_insert_and_load_full_keyentry_domain_selinux() -> Result<()> {
2288 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002289 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002290 .context("test_insert_and_load_full_keyentry_domain_selinux")?
2291 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002292 let (_key_guard, key_entry) = db
2293 .load_key_entry(
2294 KeyDescriptor {
2295 domain: Domain::SELINUX,
2296 nspace: 1,
2297 alias: Some(TEST_ALIAS.to_string()),
2298 blob: None,
2299 },
2300 KeyType::Client,
2301 KeyEntryLoadBits::BOTH,
2302 1,
2303 |_k, _av| Ok(()),
2304 )
2305 .unwrap();
2306 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
2307
2308 db.unbind_key(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002309 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002310 domain: Domain::SELINUX,
2311 nspace: 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002312 alias: Some(TEST_ALIAS.to_string()),
2313 blob: None,
2314 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002315 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002316 1,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002317 |_, _| Ok(()),
2318 )
2319 .unwrap();
2320
2321 assert_eq!(
2322 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2323 db.load_key_entry(
2324 KeyDescriptor {
2325 domain: Domain::SELINUX,
2326 nspace: 1,
2327 alias: Some(TEST_ALIAS.to_string()),
2328 blob: None,
2329 },
2330 KeyType::Client,
2331 KeyEntryLoadBits::NONE,
2332 1,
2333 |_k, _av| Ok(()),
2334 )
2335 .unwrap_err()
2336 .root_cause()
2337 .downcast_ref::<KsError>()
2338 );
2339
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002340 Ok(())
2341 }
2342
2343 #[test]
2344 fn test_insert_and_load_full_keyentry_domain_key_id() -> Result<()> {
2345 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002346 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002347 .context("test_insert_and_load_full_keyentry_domain_key_id")?
2348 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002349 let (_, key_entry) = db
2350 .load_key_entry(
2351 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
2352 KeyType::Client,
2353 KeyEntryLoadBits::BOTH,
2354 1,
2355 |_k, _av| Ok(()),
2356 )
2357 .unwrap();
2358
2359 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
2360
2361 db.unbind_key(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002362 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002363 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002364 1,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002365 |_, _| Ok(()),
2366 )
2367 .unwrap();
2368
2369 assert_eq!(
2370 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2371 db.load_key_entry(
2372 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
2373 KeyType::Client,
2374 KeyEntryLoadBits::NONE,
2375 1,
2376 |_k, _av| Ok(()),
2377 )
2378 .unwrap_err()
2379 .root_cause()
2380 .downcast_ref::<KsError>()
2381 );
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002382
2383 Ok(())
2384 }
2385
2386 #[test]
2387 fn test_insert_and_load_full_keyentry_from_grant() -> Result<()> {
2388 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002389 let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002390 .context("test_insert_and_load_full_keyentry_from_grant")?
2391 .0;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002392
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002393 let granted_key = db
2394 .grant(
2395 KeyDescriptor {
2396 domain: Domain::APP,
2397 nspace: 0,
2398 alias: Some(TEST_ALIAS.to_string()),
2399 blob: None,
2400 },
2401 1,
2402 2,
2403 key_perm_set![KeyPerm::use_()],
2404 |_k, _av| Ok(()),
2405 )
2406 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002407
2408 debug_dump_grant_table(&mut db)?;
2409
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002410 let (_key_guard, key_entry) = db
2411 .load_key_entry(
2412 granted_key.clone(),
2413 KeyType::Client,
2414 KeyEntryLoadBits::BOTH,
2415 2,
2416 |k, av| {
2417 assert_eq!(Domain::GRANT, k.domain);
2418 assert!(av.unwrap().includes(KeyPerm::use_()));
2419 Ok(())
2420 },
2421 )
2422 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002423
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002424 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002425
2426 db.unbind_key(granted_key.clone(), KeyType::Client, 2, |_, _| Ok(())).unwrap();
2427
2428 assert_eq!(
2429 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2430 db.load_key_entry(
2431 granted_key,
2432 KeyType::Client,
2433 KeyEntryLoadBits::NONE,
2434 2,
2435 |_k, _av| Ok(()),
2436 )
2437 .unwrap_err()
2438 .root_cause()
2439 .downcast_ref::<KsError>()
2440 );
2441
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002442 Ok(())
2443 }
2444
Janis Danisevskisaec14592020-11-12 09:41:49 -08002445 static KEY_LOCK_TEST_ALIAS: &str = "my super duper locked key";
2446
Janis Danisevskisaec14592020-11-12 09:41:49 -08002447 #[test]
2448 fn test_insert_and_load_full_keyentry_domain_app_concurrently() -> Result<()> {
2449 let handle = {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002450 let temp_dir = Arc::new(TempDir::new("id_lock_test")?);
2451 let temp_dir_clone = temp_dir.clone();
2452 let mut db = KeystoreDB::new(temp_dir.path())?;
Janis Danisevskisaec14592020-11-12 09:41:49 -08002453 let key_id = make_test_key_entry(&mut db, Domain::APP, 33, KEY_LOCK_TEST_ALIAS)
2454 .context("test_insert_and_load_full_keyentry_domain_app")?
2455 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002456 let (_key_guard, key_entry) = db
2457 .load_key_entry(
2458 KeyDescriptor {
2459 domain: Domain::APP,
2460 nspace: 0,
2461 alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
2462 blob: None,
2463 },
2464 KeyType::Client,
2465 KeyEntryLoadBits::BOTH,
2466 33,
2467 |_k, _av| Ok(()),
2468 )
2469 .unwrap();
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002470 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
Janis Danisevskisaec14592020-11-12 09:41:49 -08002471 let state = Arc::new(AtomicU8::new(1));
2472 let state2 = state.clone();
2473
2474 // Spawning a second thread that attempts to acquire the key id lock
2475 // for the same key as the primary thread. The primary thread then
2476 // waits, thereby forcing the secondary thread into the second stage
2477 // of acquiring the lock (see KEY ID LOCK 2/2 above).
2478 // The test succeeds if the secondary thread observes the transition
2479 // of `state` from 1 to 2, despite having a whole second to overtake
2480 // the primary thread.
2481 let handle = thread::spawn(move || {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002482 let temp_dir = temp_dir_clone;
2483 let mut db = KeystoreDB::new(temp_dir.path()).unwrap();
Janis Danisevskisaec14592020-11-12 09:41:49 -08002484 assert!(db
2485 .load_key_entry(
2486 KeyDescriptor {
2487 domain: Domain::APP,
2488 nspace: 0,
2489 alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
2490 blob: None,
2491 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002492 KeyType::Client,
Janis Danisevskisaec14592020-11-12 09:41:49 -08002493 KeyEntryLoadBits::BOTH,
2494 33,
2495 |_k, _av| Ok(()),
2496 )
2497 .is_ok());
2498 // We should only see a 2 here because we can only return
2499 // from load_key_entry when the `_key_guard` expires,
2500 // which happens at the end of the scope.
2501 assert_eq!(2, state2.load(Ordering::Relaxed));
2502 });
2503
2504 thread::sleep(std::time::Duration::from_millis(1000));
2505
2506 assert_eq!(Ok(1), state.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed));
2507
2508 // Return the handle from this scope so we can join with the
2509 // secondary thread after the key id lock has expired.
2510 handle
2511 // This is where the `_key_guard` goes out of scope,
2512 // which is the reason for concurrent load_key_entry on the same key
2513 // to unblock.
2514 };
2515 // Join with the secondary thread and unwrap, to propagate failing asserts to the
2516 // main test thread. We will not see failing asserts in secondary threads otherwise.
2517 handle.join().unwrap();
2518 Ok(())
2519 }
2520
Janis Danisevskise92a5e62020-12-02 12:57:41 -08002521 #[test]
2522 fn list() -> Result<()> {
2523 let temp_dir = TempDir::new("list_test")?;
2524 let mut db = KeystoreDB::new(temp_dir.path())?;
2525 static LIST_O_ENTRIES: &[(Domain, i64, &str)] = &[
2526 (Domain::APP, 1, "test1"),
2527 (Domain::APP, 1, "test2"),
2528 (Domain::APP, 1, "test3"),
2529 (Domain::APP, 1, "test4"),
2530 (Domain::APP, 1, "test5"),
2531 (Domain::APP, 1, "test6"),
2532 (Domain::APP, 1, "test7"),
2533 (Domain::APP, 2, "test1"),
2534 (Domain::APP, 2, "test2"),
2535 (Domain::APP, 2, "test3"),
2536 (Domain::APP, 2, "test4"),
2537 (Domain::APP, 2, "test5"),
2538 (Domain::APP, 2, "test6"),
2539 (Domain::APP, 2, "test8"),
2540 (Domain::SELINUX, 100, "test1"),
2541 (Domain::SELINUX, 100, "test2"),
2542 (Domain::SELINUX, 100, "test3"),
2543 (Domain::SELINUX, 100, "test4"),
2544 (Domain::SELINUX, 100, "test5"),
2545 (Domain::SELINUX, 100, "test6"),
2546 (Domain::SELINUX, 100, "test9"),
2547 ];
2548
2549 let list_o_keys: Vec<(i64, i64)> = LIST_O_ENTRIES
2550 .iter()
2551 .map(|(domain, ns, alias)| {
2552 let entry =
2553 make_test_key_entry(&mut db, *domain, *ns, *alias).unwrap_or_else(|e| {
2554 panic!("Failed to insert {:?} {} {}. Error {:?}", domain, ns, alias, e)
2555 });
2556 (entry.id(), *ns)
2557 })
2558 .collect();
2559
2560 for (domain, namespace) in
2561 &[(Domain::APP, 1i64), (Domain::APP, 2i64), (Domain::SELINUX, 100i64)]
2562 {
2563 let mut list_o_descriptors: Vec<KeyDescriptor> = LIST_O_ENTRIES
2564 .iter()
2565 .filter_map(|(domain, ns, alias)| match ns {
2566 ns if *ns == *namespace => Some(KeyDescriptor {
2567 domain: *domain,
2568 nspace: *ns,
2569 alias: Some(alias.to_string()),
2570 blob: None,
2571 }),
2572 _ => None,
2573 })
2574 .collect();
2575 list_o_descriptors.sort();
2576 let mut list_result = db.list(*domain, *namespace)?;
2577 list_result.sort();
2578 assert_eq!(list_o_descriptors, list_result);
2579
2580 let mut list_o_ids: Vec<i64> = list_o_descriptors
2581 .into_iter()
2582 .map(|d| {
2583 let (_, entry) = db
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002584 .load_key_entry(
2585 d,
2586 KeyType::Client,
2587 KeyEntryLoadBits::NONE,
2588 *namespace as u32,
2589 |_, _| Ok(()),
2590 )
Janis Danisevskise92a5e62020-12-02 12:57:41 -08002591 .unwrap();
2592 entry.id()
2593 })
2594 .collect();
2595 list_o_ids.sort_unstable();
2596 let mut loaded_entries: Vec<i64> = list_o_keys
2597 .iter()
2598 .filter_map(|(id, ns)| match ns {
2599 ns if *ns == *namespace => Some(*id),
2600 _ => None,
2601 })
2602 .collect();
2603 loaded_entries.sort_unstable();
2604 assert_eq!(list_o_ids, loaded_entries);
2605 }
2606 assert_eq!(Vec::<KeyDescriptor>::new(), db.list(Domain::SELINUX, 101)?);
2607
2608 Ok(())
2609 }
2610
Joel Galenson0891bc12020-07-20 10:37:03 -07002611 // Helpers
2612
2613 // Checks that the given result is an error containing the given string.
2614 fn check_result_is_error_containing_string<T>(result: Result<T>, target: &str) {
2615 let error_str = format!(
2616 "{:#?}",
2617 result.err().unwrap_or_else(|| panic!("Expected the error: {}", target))
2618 );
2619 assert!(
2620 error_str.contains(target),
2621 "The string \"{}\" should contain \"{}\"",
2622 error_str,
2623 target
2624 );
2625 }
2626
Joel Galenson2aab4432020-07-22 15:27:57 -07002627 #[derive(Debug, PartialEq)]
Joel Galenson0891bc12020-07-20 10:37:03 -07002628 #[allow(dead_code)]
2629 struct KeyEntryRow {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002630 id: i64,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002631 key_type: KeyType,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002632 domain: Option<Domain>,
Joel Galenson0891bc12020-07-20 10:37:03 -07002633 namespace: Option<i64>,
2634 alias: Option<String>,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002635 state: KeyLifeCycle,
Joel Galenson0891bc12020-07-20 10:37:03 -07002636 }
2637
2638 fn get_keyentry(db: &KeystoreDB) -> Result<Vec<KeyEntryRow>> {
2639 db.conn
Joel Galenson2aab4432020-07-22 15:27:57 -07002640 .prepare("SELECT * FROM persistent.keyentry;")?
Joel Galenson0891bc12020-07-20 10:37:03 -07002641 .query_map(NO_PARAMS, |row| {
Joel Galenson0891bc12020-07-20 10:37:03 -07002642 Ok(KeyEntryRow {
2643 id: row.get(0)?,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002644 key_type: row.get(1)?,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002645 domain: match row.get(2)? {
2646 Some(i) => Some(Domain(i)),
2647 None => None,
2648 },
Joel Galenson0891bc12020-07-20 10:37:03 -07002649 namespace: row.get(3)?,
2650 alias: row.get(4)?,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002651 state: row.get(5)?,
Joel Galenson0891bc12020-07-20 10:37:03 -07002652 })
2653 })?
2654 .map(|r| r.context("Could not read keyentry row."))
2655 .collect::<Result<Vec<_>>>()
2656 }
2657
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07002658 // Note: The parameters and SecurityLevel associations are nonsensical. This
2659 // collection is only used to check if the parameters are preserved as expected by the
2660 // database.
2661 fn make_test_params() -> Vec<KeyParameter> {
2662 vec![
2663 KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::TRUSTED_ENVIRONMENT),
2664 KeyParameter::new(
2665 KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
2666 SecurityLevel::TRUSTED_ENVIRONMENT,
2667 ),
2668 KeyParameter::new(
2669 KeyParameterValue::KeyPurpose(KeyPurpose::DECRYPT),
2670 SecurityLevel::TRUSTED_ENVIRONMENT,
2671 ),
2672 KeyParameter::new(
2673 KeyParameterValue::Algorithm(Algorithm::RSA),
2674 SecurityLevel::TRUSTED_ENVIRONMENT,
2675 ),
2676 KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::TRUSTED_ENVIRONMENT),
2677 KeyParameter::new(
2678 KeyParameterValue::BlockMode(BlockMode::ECB),
2679 SecurityLevel::TRUSTED_ENVIRONMENT,
2680 ),
2681 KeyParameter::new(
2682 KeyParameterValue::BlockMode(BlockMode::GCM),
2683 SecurityLevel::TRUSTED_ENVIRONMENT,
2684 ),
2685 KeyParameter::new(KeyParameterValue::Digest(Digest::NONE), SecurityLevel::STRONGBOX),
2686 KeyParameter::new(
2687 KeyParameterValue::Digest(Digest::MD5),
2688 SecurityLevel::TRUSTED_ENVIRONMENT,
2689 ),
2690 KeyParameter::new(
2691 KeyParameterValue::Digest(Digest::SHA_2_224),
2692 SecurityLevel::TRUSTED_ENVIRONMENT,
2693 ),
2694 KeyParameter::new(
2695 KeyParameterValue::Digest(Digest::SHA_2_256),
2696 SecurityLevel::STRONGBOX,
2697 ),
2698 KeyParameter::new(
2699 KeyParameterValue::PaddingMode(PaddingMode::NONE),
2700 SecurityLevel::TRUSTED_ENVIRONMENT,
2701 ),
2702 KeyParameter::new(
2703 KeyParameterValue::PaddingMode(PaddingMode::RSA_OAEP),
2704 SecurityLevel::TRUSTED_ENVIRONMENT,
2705 ),
2706 KeyParameter::new(
2707 KeyParameterValue::PaddingMode(PaddingMode::RSA_PSS),
2708 SecurityLevel::STRONGBOX,
2709 ),
2710 KeyParameter::new(
2711 KeyParameterValue::PaddingMode(PaddingMode::RSA_PKCS1_1_5_SIGN),
2712 SecurityLevel::TRUSTED_ENVIRONMENT,
2713 ),
2714 KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::TRUSTED_ENVIRONMENT),
2715 KeyParameter::new(KeyParameterValue::MinMacLength(256), SecurityLevel::STRONGBOX),
2716 KeyParameter::new(
2717 KeyParameterValue::EcCurve(EcCurve::P_224),
2718 SecurityLevel::TRUSTED_ENVIRONMENT,
2719 ),
2720 KeyParameter::new(KeyParameterValue::EcCurve(EcCurve::P_256), SecurityLevel::STRONGBOX),
2721 KeyParameter::new(
2722 KeyParameterValue::EcCurve(EcCurve::P_384),
2723 SecurityLevel::TRUSTED_ENVIRONMENT,
2724 ),
2725 KeyParameter::new(
2726 KeyParameterValue::EcCurve(EcCurve::P_521),
2727 SecurityLevel::TRUSTED_ENVIRONMENT,
2728 ),
2729 KeyParameter::new(
2730 KeyParameterValue::RSAPublicExponent(3),
2731 SecurityLevel::TRUSTED_ENVIRONMENT,
2732 ),
2733 KeyParameter::new(
2734 KeyParameterValue::IncludeUniqueID,
2735 SecurityLevel::TRUSTED_ENVIRONMENT,
2736 ),
2737 KeyParameter::new(KeyParameterValue::BootLoaderOnly, SecurityLevel::STRONGBOX),
2738 KeyParameter::new(KeyParameterValue::RollbackResistance, SecurityLevel::STRONGBOX),
2739 KeyParameter::new(
2740 KeyParameterValue::ActiveDateTime(1234567890),
2741 SecurityLevel::STRONGBOX,
2742 ),
2743 KeyParameter::new(
2744 KeyParameterValue::OriginationExpireDateTime(1234567890),
2745 SecurityLevel::TRUSTED_ENVIRONMENT,
2746 ),
2747 KeyParameter::new(
2748 KeyParameterValue::UsageExpireDateTime(1234567890),
2749 SecurityLevel::TRUSTED_ENVIRONMENT,
2750 ),
2751 KeyParameter::new(
2752 KeyParameterValue::MinSecondsBetweenOps(1234567890),
2753 SecurityLevel::TRUSTED_ENVIRONMENT,
2754 ),
2755 KeyParameter::new(
2756 KeyParameterValue::MaxUsesPerBoot(1234567890),
2757 SecurityLevel::TRUSTED_ENVIRONMENT,
2758 ),
2759 KeyParameter::new(KeyParameterValue::UserID(1), SecurityLevel::STRONGBOX),
2760 KeyParameter::new(KeyParameterValue::UserSecureID(42), SecurityLevel::STRONGBOX),
2761 KeyParameter::new(
2762 KeyParameterValue::NoAuthRequired,
2763 SecurityLevel::TRUSTED_ENVIRONMENT,
2764 ),
2765 KeyParameter::new(
2766 KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType::PASSWORD),
2767 SecurityLevel::TRUSTED_ENVIRONMENT,
2768 ),
2769 KeyParameter::new(KeyParameterValue::AuthTimeout(1234567890), SecurityLevel::SOFTWARE),
2770 KeyParameter::new(KeyParameterValue::AllowWhileOnBody, SecurityLevel::SOFTWARE),
2771 KeyParameter::new(
2772 KeyParameterValue::TrustedUserPresenceRequired,
2773 SecurityLevel::TRUSTED_ENVIRONMENT,
2774 ),
2775 KeyParameter::new(
2776 KeyParameterValue::TrustedConfirmationRequired,
2777 SecurityLevel::TRUSTED_ENVIRONMENT,
2778 ),
2779 KeyParameter::new(
2780 KeyParameterValue::UnlockedDeviceRequired,
2781 SecurityLevel::TRUSTED_ENVIRONMENT,
2782 ),
2783 KeyParameter::new(
2784 KeyParameterValue::ApplicationID(vec![1u8, 2u8, 3u8, 4u8]),
2785 SecurityLevel::SOFTWARE,
2786 ),
2787 KeyParameter::new(
2788 KeyParameterValue::ApplicationData(vec![4u8, 3u8, 2u8, 1u8]),
2789 SecurityLevel::SOFTWARE,
2790 ),
2791 KeyParameter::new(
2792 KeyParameterValue::CreationDateTime(12345677890),
2793 SecurityLevel::SOFTWARE,
2794 ),
2795 KeyParameter::new(
2796 KeyParameterValue::KeyOrigin(KeyOrigin::GENERATED),
2797 SecurityLevel::TRUSTED_ENVIRONMENT,
2798 ),
2799 KeyParameter::new(
2800 KeyParameterValue::RootOfTrust(vec![3u8, 2u8, 1u8, 4u8]),
2801 SecurityLevel::TRUSTED_ENVIRONMENT,
2802 ),
2803 KeyParameter::new(KeyParameterValue::OSVersion(1), SecurityLevel::TRUSTED_ENVIRONMENT),
2804 KeyParameter::new(KeyParameterValue::OSPatchLevel(2), SecurityLevel::SOFTWARE),
2805 KeyParameter::new(
2806 KeyParameterValue::UniqueID(vec![4u8, 3u8, 1u8, 2u8]),
2807 SecurityLevel::SOFTWARE,
2808 ),
2809 KeyParameter::new(
2810 KeyParameterValue::AttestationChallenge(vec![4u8, 3u8, 1u8, 2u8]),
2811 SecurityLevel::TRUSTED_ENVIRONMENT,
2812 ),
2813 KeyParameter::new(
2814 KeyParameterValue::AttestationApplicationID(vec![4u8, 3u8, 1u8, 2u8]),
2815 SecurityLevel::TRUSTED_ENVIRONMENT,
2816 ),
2817 KeyParameter::new(
2818 KeyParameterValue::AttestationIdBrand(vec![4u8, 3u8, 1u8, 2u8]),
2819 SecurityLevel::TRUSTED_ENVIRONMENT,
2820 ),
2821 KeyParameter::new(
2822 KeyParameterValue::AttestationIdDevice(vec![4u8, 3u8, 1u8, 2u8]),
2823 SecurityLevel::TRUSTED_ENVIRONMENT,
2824 ),
2825 KeyParameter::new(
2826 KeyParameterValue::AttestationIdProduct(vec![4u8, 3u8, 1u8, 2u8]),
2827 SecurityLevel::TRUSTED_ENVIRONMENT,
2828 ),
2829 KeyParameter::new(
2830 KeyParameterValue::AttestationIdSerial(vec![4u8, 3u8, 1u8, 2u8]),
2831 SecurityLevel::TRUSTED_ENVIRONMENT,
2832 ),
2833 KeyParameter::new(
2834 KeyParameterValue::AttestationIdIMEI(vec![4u8, 3u8, 1u8, 2u8]),
2835 SecurityLevel::TRUSTED_ENVIRONMENT,
2836 ),
2837 KeyParameter::new(
2838 KeyParameterValue::AttestationIdMEID(vec![4u8, 3u8, 1u8, 2u8]),
2839 SecurityLevel::TRUSTED_ENVIRONMENT,
2840 ),
2841 KeyParameter::new(
2842 KeyParameterValue::AttestationIdManufacturer(vec![4u8, 3u8, 1u8, 2u8]),
2843 SecurityLevel::TRUSTED_ENVIRONMENT,
2844 ),
2845 KeyParameter::new(
2846 KeyParameterValue::AttestationIdModel(vec![4u8, 3u8, 1u8, 2u8]),
2847 SecurityLevel::TRUSTED_ENVIRONMENT,
2848 ),
2849 KeyParameter::new(
2850 KeyParameterValue::VendorPatchLevel(3),
2851 SecurityLevel::TRUSTED_ENVIRONMENT,
2852 ),
2853 KeyParameter::new(
2854 KeyParameterValue::BootPatchLevel(4),
2855 SecurityLevel::TRUSTED_ENVIRONMENT,
2856 ),
2857 KeyParameter::new(
2858 KeyParameterValue::AssociatedData(vec![4u8, 3u8, 1u8, 2u8]),
2859 SecurityLevel::TRUSTED_ENVIRONMENT,
2860 ),
2861 KeyParameter::new(
2862 KeyParameterValue::Nonce(vec![4u8, 3u8, 1u8, 2u8]),
2863 SecurityLevel::TRUSTED_ENVIRONMENT,
2864 ),
2865 KeyParameter::new(
2866 KeyParameterValue::MacLength(256),
2867 SecurityLevel::TRUSTED_ENVIRONMENT,
2868 ),
2869 KeyParameter::new(
2870 KeyParameterValue::ResetSinceIdRotation,
2871 SecurityLevel::TRUSTED_ENVIRONMENT,
2872 ),
2873 KeyParameter::new(
2874 KeyParameterValue::ConfirmationToken(vec![5u8, 5u8, 5u8, 5u8]),
2875 SecurityLevel::TRUSTED_ENVIRONMENT,
2876 ),
2877 ]
2878 }
2879
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002880 fn make_test_key_entry(
2881 db: &mut KeystoreDB,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002882 domain: Domain,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002883 namespace: i64,
2884 alias: &str,
Janis Danisevskisaec14592020-11-12 09:41:49 -08002885 ) -> Result<KeyIdGuard> {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002886 let key_id = db.create_key_entry(domain, namespace)?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002887 db.insert_blob(&key_id, SubComponentType::KEY_BLOB, TEST_KEY_BLOB)?;
2888 db.insert_blob(&key_id, SubComponentType::CERT, TEST_CERT_BLOB)?;
2889 db.insert_blob(&key_id, SubComponentType::CERT_CHAIN, TEST_CERT_CHAIN_BLOB)?;
Janis Danisevskisaec14592020-11-12 09:41:49 -08002890 db.insert_keyparameter(&key_id, &make_test_params())?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002891 let mut metadata = KeyMetaData::new();
2892 metadata.add(KeyMetaEntry::EncryptedBy(EncryptedBy::Password));
2893 metadata.add(KeyMetaEntry::Salt(vec![1, 2, 3]));
2894 metadata.add(KeyMetaEntry::Iv(vec![2, 3, 1]));
2895 metadata.add(KeyMetaEntry::AeadTag(vec![3, 1, 2]));
2896 db.insert_key_metadata(&key_id, &metadata)?;
Janis Danisevskisaec14592020-11-12 09:41:49 -08002897 db.rebind_alias(&key_id, alias, domain, namespace)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002898 Ok(key_id)
2899 }
2900
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002901 fn make_test_key_entry_test_vector(key_id: i64) -> KeyEntry {
2902 let mut metadata = KeyMetaData::new();
2903 metadata.add(KeyMetaEntry::EncryptedBy(EncryptedBy::Password));
2904 metadata.add(KeyMetaEntry::Salt(vec![1, 2, 3]));
2905 metadata.add(KeyMetaEntry::Iv(vec![2, 3, 1]));
2906 metadata.add(KeyMetaEntry::AeadTag(vec![3, 1, 2]));
2907
2908 KeyEntry {
2909 id: key_id,
2910 km_blob: Some(TEST_KEY_BLOB.to_vec()),
2911 cert: Some(TEST_CERT_BLOB.to_vec()),
2912 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
2913 sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
2914 parameters: make_test_params(),
2915 metadata,
2916 }
2917 }
2918
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002919 fn debug_dump_keyentry_table(db: &mut KeystoreDB) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002920 let mut stmt = db.conn.prepare(
2921 "SELECT id, key_type, domain, namespace, alias, state FROM persistent.keyentry;",
2922 )?;
2923 let rows = stmt.query_map::<(i64, KeyType, i32, i64, String, KeyLifeCycle), _, _>(
2924 NO_PARAMS,
2925 |row| {
2926 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?, row.get(4)?, row.get(5)?))
2927 },
2928 )?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002929
2930 println!("Key entry table rows:");
2931 for r in rows {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002932 let (id, key_type, domain, namespace, alias, state) = r.unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002933 println!(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002934 " id: {} KeyType: {:?} Domain: {} Namespace: {} Alias: {} State: {:?}",
2935 id, key_type, domain, namespace, alias, state
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002936 );
2937 }
2938 Ok(())
2939 }
2940
2941 fn debug_dump_grant_table(db: &mut KeystoreDB) -> Result<()> {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002942 let mut stmt = db
2943 .conn
2944 .prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002945 let rows = stmt.query_map::<(i64, i64, i64, i64), _, _>(NO_PARAMS, |row| {
2946 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?))
2947 })?;
2948
2949 println!("Grant table rows:");
2950 for r in rows {
2951 let (id, gt, ki, av) = r.unwrap();
2952 println!(" id: {} grantee: {} key_id: {} access_vector: {}", id, gt, ki, av);
2953 }
2954 Ok(())
2955 }
2956
Joel Galenson0891bc12020-07-20 10:37:03 -07002957 // Use a custom random number generator that repeats each number once.
2958 // This allows us to test repeated elements.
2959
2960 thread_local! {
2961 static RANDOM_COUNTER: RefCell<i64> = RefCell::new(0);
2962 }
2963
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002964 fn reset_random() {
2965 RANDOM_COUNTER.with(|counter| {
2966 *counter.borrow_mut() = 0;
2967 })
2968 }
2969
Joel Galenson0891bc12020-07-20 10:37:03 -07002970 pub fn random() -> i64 {
2971 RANDOM_COUNTER.with(|counter| {
2972 let result = *counter.borrow() / 2;
2973 *counter.borrow_mut() += 1;
2974 result
2975 })
2976 }
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00002977
2978 #[test]
2979 fn test_last_off_body() -> Result<()> {
2980 let mut db = new_test_db()?;
Janis Danisevskis5ed8c532021-01-11 14:19:42 -08002981 db.insert_last_off_body(MonotonicRawTime::now())?;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00002982 let tx = db.conn.transaction_with_behavior(TransactionBehavior::Immediate)?;
2983 let last_off_body_1 = KeystoreDB::get_last_off_body(&tx)?;
2984 tx.commit()?;
2985 let one_second = Duration::from_secs(1);
2986 thread::sleep(one_second);
2987 db.update_last_off_body(MonotonicRawTime::now())?;
2988 let tx2 = db.conn.transaction_with_behavior(TransactionBehavior::Immediate)?;
2989 let last_off_body_2 = KeystoreDB::get_last_off_body(&tx2)?;
2990 tx2.commit()?;
2991 assert!(last_off_body_1.seconds() < last_off_body_2.seconds());
2992 Ok(())
2993 }
Joel Galenson26f4d012020-07-17 14:57:21 -07002994}