blob: ab8b05f82a4ccbd08175ffd8c6117df33c712014 [file] [log] [blame]
Joel Galenson26f4d012020-07-17 14:57:21 -07001// Copyright 2020, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070015//! This is the Keystore 2.0 database module.
16//! The database module provides a connection to the backing SQLite store.
17//! We have two databases one for persistent key blob storage and one for
18//! items that have a per boot life cycle.
19//!
20//! ## Persistent database
21//! The persistent database has tables for key blobs. They are organized
22//! as follows:
23//! The `keyentry` table is the primary table for key entries. It is
24//! accompanied by two tables for blobs and parameters.
25//! Each key entry occupies exactly one row in the `keyentry` table and
26//! zero or more rows in the tables `blobentry` and `keyparameter`.
27//!
28//! ## Per boot database
29//! The per boot database stores items with a per boot lifecycle.
30//! Currently, there is only the `grant` table in this database.
31//! Grants are references to a key that can be used to access a key by
32//! clients that don't own that key. Grants can only be created by the
33//! owner of a key. And only certain components can create grants.
34//! This is governed by SEPolicy.
35//!
36//! ## Access control
37//! Some database functions that load keys or create grants perform
38//! access control. This is because in some cases access control
39//! can only be performed after some information about the designated
40//! key was loaded from the database. To decouple the permission checks
41//! from the database module these functions take permission check
42//! callbacks.
Joel Galenson26f4d012020-07-17 14:57:21 -070043
Janis Danisevskisb42fc182020-12-15 08:41:27 -080044#![allow(dead_code)]
45
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070046use crate::error::{Error as KsError, ResponseCode};
Janis Danisevskisb42fc182020-12-15 08:41:27 -080047use crate::impl_metadata; // This is in db_utils.rs
Janis Danisevskis4522c2b2020-11-27 18:04:58 -080048use crate::key_parameter::{KeyParameter, Tag};
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070049use crate::permission::KeyPermSet;
Hasini Gunasinghe557b1032020-11-10 01:35:30 +000050use crate::utils::get_current_time_in_seconds;
Janis Danisevskis93927dd2020-12-23 12:23:08 -080051use crate::{
52 db_utils::{self, SqlField},
53 gc::Gc,
54};
Janis Danisevskisb42fc182020-12-15 08:41:27 -080055use anyhow::{anyhow, Context, Result};
56use std::{convert::TryFrom, convert::TryInto, time::SystemTimeError};
Janis Danisevskis60400fe2020-08-26 15:24:42 -070057
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +000058use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +000059 ErrorCode::ErrorCode as Ec, HardwareAuthToken::HardwareAuthToken,
60 HardwareAuthenticatorType::HardwareAuthenticatorType, SecurityLevel::SecurityLevel,
61 Timestamp::Timestamp,
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +000062};
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070063use android_system_keystore2::aidl::android::system::keystore2::{
Janis Danisevskis04b02832020-10-26 09:21:40 -070064 Domain::Domain, KeyDescriptor::KeyDescriptor,
Janis Danisevskis60400fe2020-08-26 15:24:42 -070065};
Janis Danisevskisaec14592020-11-12 09:41:49 -080066use lazy_static::lazy_static;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +000067use log::error;
Joel Galenson0891bc12020-07-20 10:37:03 -070068#[cfg(not(test))]
69use rand::prelude::random;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070070use rusqlite::{
Janis Danisevskisb42fc182020-12-15 08:41:27 -080071 params,
72 types::FromSql,
73 types::FromSqlResult,
74 types::ToSqlOutput,
75 types::{FromSqlError, Value, ValueRef},
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +000076 Connection, Error, OptionalExtension, ToSql, Transaction, TransactionBehavior, NO_PARAMS,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070077};
Janis Danisevskisaec14592020-11-12 09:41:49 -080078use std::{
Janis Danisevskisb42fc182020-12-15 08:41:27 -080079 collections::{HashMap, HashSet},
Janis Danisevskisbf15d732020-12-08 10:35:26 -080080 path::Path,
81 sync::{Condvar, Mutex},
Janis Danisevskisb42fc182020-12-15 08:41:27 -080082 time::{Duration, SystemTime},
Janis Danisevskisaec14592020-11-12 09:41:49 -080083};
Joel Galenson0891bc12020-07-20 10:37:03 -070084#[cfg(test)]
85use tests::random;
Joel Galenson26f4d012020-07-17 14:57:21 -070086
Janis Danisevskisb42fc182020-12-15 08:41:27 -080087impl_metadata!(
88 /// A set of metadata for key entries.
89 #[derive(Debug, Default, Eq, PartialEq)]
90 pub struct KeyMetaData;
91 /// A metadata entry for key entries.
92 #[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
93 pub enum KeyMetaEntry {
94 /// If present, indicates that the sensitive part of key
95 /// is encrypted with another key or a key derived from a password.
96 EncryptedBy(EncryptedBy) with accessor encrypted_by,
97 /// If the blob is password encrypted this field is set to the
98 /// salt used for the key derivation.
99 Salt(Vec<u8>) with accessor salt,
100 /// If the blob is encrypted, this field is set to the initialization vector.
101 Iv(Vec<u8>) with accessor iv,
102 /// If the blob is encrypted, this field holds the AEAD TAG.
103 AeadTag(Vec<u8>) with accessor aead_tag,
104 /// Creation date of a the key entry.
105 CreationDate(DateTime) with accessor creation_date,
106 /// Expiration date for attestation keys.
107 AttestationExpirationDate(DateTime) with accessor attestation_expiration_date,
108 // --- ADD NEW META DATA FIELDS HERE ---
109 // For backwards compatibility add new entries only to
110 // end of this list and above this comment.
111 };
112);
113
114impl KeyMetaData {
115 fn load_from_db(key_id: i64, tx: &Transaction) -> Result<Self> {
116 let mut stmt = tx
117 .prepare(
118 "SELECT tag, data from persistent.keymetadata
119 WHERE keyentryid = ?;",
120 )
121 .context("In KeyMetaData::load_from_db: prepare statement failed.")?;
122
123 let mut metadata: HashMap<i64, KeyMetaEntry> = Default::default();
124
125 let mut rows =
126 stmt.query(params![key_id]).context("In KeyMetaData::load_from_db: query failed.")?;
127 db_utils::with_rows_extract_all(&mut rows, |row| {
128 let db_tag: i64 = row.get(0).context("Failed to read tag.")?;
129 metadata.insert(
130 db_tag,
131 KeyMetaEntry::new_from_sql(db_tag, &SqlField::new(1, &row))
132 .context("Failed to read KeyMetaEntry.")?,
133 );
134 Ok(())
135 })
136 .context("In KeyMetaData::load_from_db.")?;
137
138 Ok(Self { data: metadata })
139 }
140
141 fn store_in_db(&self, key_id: i64, tx: &Transaction) -> Result<()> {
142 let mut stmt = tx
143 .prepare(
144 "INSERT into persistent.keymetadata (keyentryid, tag, data)
145 VALUES (?, ?, ?);",
146 )
147 .context("In KeyMetaData::store_in_db: Failed to prepare statement.")?;
148
149 let iter = self.data.iter();
150 for (tag, entry) in iter {
151 stmt.insert(params![key_id, tag, entry,]).with_context(|| {
152 format!("In KeyMetaData::store_in_db: Failed to insert {:?}", entry)
153 })?;
154 }
155 Ok(())
156 }
157}
158
159/// Indicates the type of the keyentry.
160#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
161pub enum KeyType {
162 /// This is a client key type. These keys are created or imported through the Keystore 2.0
163 /// AIDL interface android.system.keystore2.
164 Client,
165 /// This is a super key type. These keys are created by keystore itself and used to encrypt
166 /// other key blobs to provide LSKF binding.
167 Super,
168 /// This is an attestation key. These keys are created by the remote provisioning mechanism.
169 Attestation,
170}
171
172impl ToSql for KeyType {
173 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
174 Ok(ToSqlOutput::Owned(Value::Integer(match self {
175 KeyType::Client => 0,
176 KeyType::Super => 1,
177 KeyType::Attestation => 2,
178 })))
179 }
180}
181
182impl FromSql for KeyType {
183 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
184 match i64::column_result(value)? {
185 0 => Ok(KeyType::Client),
186 1 => Ok(KeyType::Super),
187 2 => Ok(KeyType::Attestation),
188 v => Err(FromSqlError::OutOfRange(v)),
189 }
190 }
191}
192
193/// Indicates how the sensitive part of this key blob is encrypted.
194#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
195pub enum EncryptedBy {
196 /// The keyblob is encrypted by a user password.
197 /// In the database this variant is represented as NULL.
198 Password,
199 /// The keyblob is encrypted by another key with wrapped key id.
200 /// In the database this variant is represented as non NULL value
201 /// that is convertible to i64, typically NUMERIC.
202 KeyId(i64),
203}
204
205impl ToSql for EncryptedBy {
206 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
207 match self {
208 Self::Password => Ok(ToSqlOutput::Owned(Value::Null)),
209 Self::KeyId(id) => id.to_sql(),
210 }
211 }
212}
213
214impl FromSql for EncryptedBy {
215 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
216 match value {
217 ValueRef::Null => Ok(Self::Password),
218 _ => Ok(Self::KeyId(i64::column_result(value)?)),
219 }
220 }
221}
222
223/// A database representation of wall clock time. DateTime stores unix epoch time as
224/// i64 in milliseconds.
225#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)]
226pub struct DateTime(i64);
227
228/// Error type returned when creating DateTime or converting it from and to
229/// SystemTime.
230#[derive(thiserror::Error, Debug)]
231pub enum DateTimeError {
232 /// This is returned when SystemTime and Duration computations fail.
233 #[error(transparent)]
234 SystemTimeError(#[from] SystemTimeError),
235
236 /// This is returned when type conversions fail.
237 #[error(transparent)]
238 TypeConversion(#[from] std::num::TryFromIntError),
239
240 /// This is returned when checked time arithmetic failed.
241 #[error("Time arithmetic failed.")]
242 TimeArithmetic,
243}
244
245impl DateTime {
246 /// Constructs a new DateTime object denoting the current time. This may fail during
247 /// conversion to unix epoch time and during conversion to the internal i64 representation.
248 pub fn now() -> Result<Self, DateTimeError> {
249 Ok(Self(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_millis().try_into()?))
250 }
251
252 /// Constructs a new DateTime object from milliseconds.
253 pub fn from_millis_epoch(millis: i64) -> Self {
254 Self(millis)
255 }
256
257 /// Returns unix epoch time in milliseconds.
258 pub fn to_millis_epoch(&self) -> i64 {
259 self.0
260 }
261
262 /// Returns unix epoch time in seconds.
263 pub fn to_secs_epoch(&self) -> i64 {
264 self.0 / 1000
265 }
266}
267
268impl ToSql for DateTime {
269 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
270 Ok(ToSqlOutput::Owned(Value::Integer(self.0)))
271 }
272}
273
274impl FromSql for DateTime {
275 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
276 Ok(Self(i64::column_result(value)?))
277 }
278}
279
280impl TryInto<SystemTime> for DateTime {
281 type Error = DateTimeError;
282
283 fn try_into(self) -> Result<SystemTime, Self::Error> {
284 // We want to construct a SystemTime representation equivalent to self, denoting
285 // a point in time THEN, but we cannot set the time directly. We can only construct
286 // a SystemTime denoting NOW, and we can get the duration between EPOCH and NOW,
287 // and between EPOCH and THEN. With this common reference we can construct the
288 // duration between NOW and THEN which we can add to our SystemTime representation
289 // of NOW to get a SystemTime representation of THEN.
290 // Durations can only be positive, thus the if statement below.
291 let now = SystemTime::now();
292 let now_epoch = now.duration_since(SystemTime::UNIX_EPOCH)?;
293 let then_epoch = Duration::from_millis(self.0.try_into()?);
294 Ok(if now_epoch > then_epoch {
295 // then = now - (now_epoch - then_epoch)
296 now_epoch
297 .checked_sub(then_epoch)
298 .and_then(|d| now.checked_sub(d))
299 .ok_or(DateTimeError::TimeArithmetic)?
300 } else {
301 // then = now + (then_epoch - now_epoch)
302 then_epoch
303 .checked_sub(now_epoch)
304 .and_then(|d| now.checked_add(d))
305 .ok_or(DateTimeError::TimeArithmetic)?
306 })
307 }
308}
309
310impl TryFrom<SystemTime> for DateTime {
311 type Error = DateTimeError;
312
313 fn try_from(t: SystemTime) -> Result<Self, Self::Error> {
314 Ok(Self(t.duration_since(SystemTime::UNIX_EPOCH)?.as_millis().try_into()?))
315 }
316}
317
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800318#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
319enum KeyLifeCycle {
320 /// Existing keys have a key ID but are not fully populated yet.
321 /// This is a transient state. If Keystore finds any such keys when it starts up, it must move
322 /// them to Unreferenced for garbage collection.
323 Existing,
324 /// A live key is fully populated and usable by clients.
325 Live,
326 /// An unreferenced key is scheduled for garbage collection.
327 Unreferenced,
328}
329
330impl ToSql for KeyLifeCycle {
331 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
332 match self {
333 Self::Existing => Ok(ToSqlOutput::Owned(Value::Integer(0))),
334 Self::Live => Ok(ToSqlOutput::Owned(Value::Integer(1))),
335 Self::Unreferenced => Ok(ToSqlOutput::Owned(Value::Integer(2))),
336 }
337 }
338}
339
340impl FromSql for KeyLifeCycle {
341 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
342 match i64::column_result(value)? {
343 0 => Ok(KeyLifeCycle::Existing),
344 1 => Ok(KeyLifeCycle::Live),
345 2 => Ok(KeyLifeCycle::Unreferenced),
346 v => Err(FromSqlError::OutOfRange(v)),
347 }
348 }
349}
350
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700351/// Keys have a KeyMint blob component and optional public certificate and
352/// certificate chain components.
353/// KeyEntryLoadBits is a bitmap that indicates to `KeystoreDB::load_key_entry`
354/// which components shall be loaded from the database if present.
355#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
356pub struct KeyEntryLoadBits(u32);
357
358impl KeyEntryLoadBits {
359 /// Indicate to `KeystoreDB::load_key_entry` that no component shall be loaded.
360 pub const NONE: KeyEntryLoadBits = Self(0);
361 /// Indicate to `KeystoreDB::load_key_entry` that the KeyMint component shall be loaded.
362 pub const KM: KeyEntryLoadBits = Self(1);
363 /// Indicate to `KeystoreDB::load_key_entry` that the Public components shall be loaded.
364 pub const PUBLIC: KeyEntryLoadBits = Self(2);
365 /// Indicate to `KeystoreDB::load_key_entry` that both components shall be loaded.
366 pub const BOTH: KeyEntryLoadBits = Self(3);
367
368 /// Returns true if this object indicates that the public components shall be loaded.
369 pub const fn load_public(&self) -> bool {
370 self.0 & Self::PUBLIC.0 != 0
371 }
372
373 /// Returns true if the object indicates that the KeyMint component shall be loaded.
374 pub const fn load_km(&self) -> bool {
375 self.0 & Self::KM.0 != 0
376 }
377}
378
Janis Danisevskisaec14592020-11-12 09:41:49 -0800379lazy_static! {
380 static ref KEY_ID_LOCK: KeyIdLockDb = KeyIdLockDb::new();
381}
382
383struct KeyIdLockDb {
384 locked_keys: Mutex<HashSet<i64>>,
385 cond_var: Condvar,
386}
387
388/// A locked key. While a guard exists for a given key id, the same key cannot be loaded
389/// from the database a second time. Most functions manipulating the key blob database
390/// require a KeyIdGuard.
391#[derive(Debug)]
392pub struct KeyIdGuard(i64);
393
394impl KeyIdLockDb {
395 fn new() -> Self {
396 Self { locked_keys: Mutex::new(HashSet::new()), cond_var: Condvar::new() }
397 }
398
399 /// This function blocks until an exclusive lock for the given key entry id can
400 /// be acquired. It returns a guard object, that represents the lifecycle of the
401 /// acquired lock.
402 pub fn get(&self, key_id: i64) -> KeyIdGuard {
403 let mut locked_keys = self.locked_keys.lock().unwrap();
404 while locked_keys.contains(&key_id) {
405 locked_keys = self.cond_var.wait(locked_keys).unwrap();
406 }
407 locked_keys.insert(key_id);
408 KeyIdGuard(key_id)
409 }
410
411 /// This function attempts to acquire an exclusive lock on a given key id. If the
412 /// given key id is already taken the function returns None immediately. If a lock
413 /// can be acquired this function returns a guard object, that represents the
414 /// lifecycle of the acquired lock.
415 pub fn try_get(&self, key_id: i64) -> Option<KeyIdGuard> {
416 let mut locked_keys = self.locked_keys.lock().unwrap();
417 if locked_keys.insert(key_id) {
418 Some(KeyIdGuard(key_id))
419 } else {
420 None
421 }
422 }
423}
424
425impl KeyIdGuard {
426 /// Get the numeric key id of the locked key.
427 pub fn id(&self) -> i64 {
428 self.0
429 }
430}
431
432impl Drop for KeyIdGuard {
433 fn drop(&mut self) {
434 let mut locked_keys = KEY_ID_LOCK.locked_keys.lock().unwrap();
435 locked_keys.remove(&self.0);
Janis Danisevskis7fd53582020-11-23 13:40:34 -0800436 drop(locked_keys);
Janis Danisevskisaec14592020-11-12 09:41:49 -0800437 KEY_ID_LOCK.cond_var.notify_all();
438 }
439}
440
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700441/// This type represents a Keystore 2.0 key entry.
442/// An entry has a unique `id` by which it can be found in the database.
443/// It has a security level field, key parameters, and three optional fields
444/// for the KeyMint blob, public certificate and a public certificate chain.
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800445#[derive(Debug, Default, Eq, PartialEq)]
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700446pub struct KeyEntry {
447 id: i64,
448 km_blob: Option<Vec<u8>>,
449 cert: Option<Vec<u8>>,
450 cert_chain: Option<Vec<u8>>,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700451 sec_level: SecurityLevel,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700452 parameters: Vec<KeyParameter>,
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800453 metadata: KeyMetaData,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700454}
455
456impl KeyEntry {
457 /// Returns the unique id of the Key entry.
458 pub fn id(&self) -> i64 {
459 self.id
460 }
461 /// Exposes the optional KeyMint blob.
462 pub fn km_blob(&self) -> &Option<Vec<u8>> {
463 &self.km_blob
464 }
465 /// Extracts the Optional KeyMint blob.
466 pub fn take_km_blob(&mut self) -> Option<Vec<u8>> {
467 self.km_blob.take()
468 }
469 /// Exposes the optional public certificate.
470 pub fn cert(&self) -> &Option<Vec<u8>> {
471 &self.cert
472 }
473 /// Extracts the optional public certificate.
474 pub fn take_cert(&mut self) -> Option<Vec<u8>> {
475 self.cert.take()
476 }
477 /// Exposes the optional public certificate chain.
478 pub fn cert_chain(&self) -> &Option<Vec<u8>> {
479 &self.cert_chain
480 }
481 /// Extracts the optional public certificate_chain.
482 pub fn take_cert_chain(&mut self) -> Option<Vec<u8>> {
483 self.cert_chain.take()
484 }
485 /// Returns the security level of the key entry.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700486 pub fn sec_level(&self) -> SecurityLevel {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700487 self.sec_level
488 }
Janis Danisevskis04b02832020-10-26 09:21:40 -0700489 /// Exposes the key parameters of this key entry.
490 pub fn key_parameters(&self) -> &Vec<KeyParameter> {
491 &self.parameters
492 }
493 /// Consumes this key entry and extracts the keyparameters from it.
494 pub fn into_key_parameters(self) -> Vec<KeyParameter> {
495 self.parameters
496 }
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800497 /// Exposes the key metadata of this key entry.
498 pub fn metadata(&self) -> &KeyMetaData {
499 &self.metadata
500 }
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700501}
502
503/// Indicates the sub component of a key entry for persistent storage.
504#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
505pub struct SubComponentType(u32);
506impl SubComponentType {
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800507 /// Persistent identifier for a key blob.
508 pub const KEY_BLOB: SubComponentType = Self(0);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700509 /// Persistent identifier for a certificate blob.
510 pub const CERT: SubComponentType = Self(1);
511 /// Persistent identifier for a certificate chain blob.
512 pub const CERT_CHAIN: SubComponentType = Self(2);
513}
514
515impl ToSql for SubComponentType {
516 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
517 self.0.to_sql()
518 }
519}
520
521impl FromSql for SubComponentType {
522 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
523 Ok(Self(u32::column_result(value)?))
524 }
525}
526
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700527/// KeystoreDB wraps a connection to an SQLite database and tracks its
528/// ownership. It also implements all of Keystore 2.0's database functionality.
Joel Galenson26f4d012020-07-17 14:57:21 -0700529pub struct KeystoreDB {
Joel Galenson26f4d012020-07-17 14:57:21 -0700530 conn: Connection,
531}
532
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000533/// Database representation of the monotonic time retrieved from the system call clock_gettime with
534/// CLOCK_MONOTONIC_RAW. Stores monotonic time as i64 in seconds.
535#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)]
536pub struct MonotonicRawTime(i64);
537
538impl MonotonicRawTime {
539 /// Constructs a new MonotonicRawTime
540 pub fn now() -> Self {
541 Self(get_current_time_in_seconds())
542 }
543
544 /// Returns the integer value of MonotonicRawTime as i64
545 pub fn seconds(&self) -> i64 {
546 self.0
547 }
548}
549
550impl ToSql for MonotonicRawTime {
551 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
552 Ok(ToSqlOutput::Owned(Value::Integer(self.0)))
553 }
554}
555
556impl FromSql for MonotonicRawTime {
557 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
558 Ok(Self(i64::column_result(value)?))
559 }
560}
561
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000562/// This struct encapsulates the information to be stored in the database about the auth tokens
563/// received by keystore.
564pub struct AuthTokenEntry {
565 auth_token: HardwareAuthToken,
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000566 time_received: MonotonicRawTime,
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000567}
568
569impl AuthTokenEntry {
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000570 fn new(auth_token: HardwareAuthToken, time_received: MonotonicRawTime) -> Self {
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000571 AuthTokenEntry { auth_token, time_received }
572 }
573
574 /// Checks if this auth token satisfies the given authentication information.
575 pub fn satisfies_auth(
576 auth_token: &HardwareAuthToken,
577 user_secure_ids: &[i64],
578 auth_type: HardwareAuthenticatorType,
579 ) -> bool {
580 user_secure_ids.iter().any(|&sid| {
581 (sid == auth_token.userId || sid == auth_token.authenticatorId)
582 && (((auth_type.0 as i32) & (auth_token.authenticatorType.0 as i32)) != 0)
583 })
584 }
585
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000586 /// Returns the auth token wrapped by the AuthTokenEntry
587 pub fn get_auth_token(self) -> HardwareAuthToken {
588 self.auth_token
589 }
590}
591
Joel Galenson26f4d012020-07-17 14:57:21 -0700592impl KeystoreDB {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700593 /// This will create a new database connection connecting the two
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800594 /// files persistent.sqlite and perboot.sqlite in the given directory.
595 /// It also attempts to initialize all of the tables.
596 /// KeystoreDB cannot be used by multiple threads.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700597 /// Each thread should open their own connection using `thread_local!`.
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800598 pub fn new(db_root: &Path) -> Result<Self> {
599 // Build the path to the sqlite files.
600 let mut persistent_path = db_root.to_path_buf();
601 persistent_path.push("persistent.sqlite");
602 let mut perboot_path = db_root.to_path_buf();
603 perboot_path.push("perboot.sqlite");
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700604
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800605 // Now convert them to strings prefixed with "file:"
606 let mut persistent_path_str = "file:".to_owned();
607 persistent_path_str.push_str(&persistent_path.to_string_lossy());
608 let mut perboot_path_str = "file:".to_owned();
609 perboot_path_str.push_str(&perboot_path.to_string_lossy());
610
611 let conn = Self::make_connection(&persistent_path_str, &perboot_path_str)?;
612
613 Self::init_tables(&conn)?;
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700614 Ok(Self { conn })
Joel Galenson2aab4432020-07-22 15:27:57 -0700615 }
616
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700617 fn init_tables(conn: &Connection) -> Result<()> {
618 conn.execute(
619 "CREATE TABLE IF NOT EXISTS persistent.keyentry (
Joel Galenson0891bc12020-07-20 10:37:03 -0700620 id INTEGER UNIQUE,
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800621 key_type INTEGER,
Joel Galenson0891bc12020-07-20 10:37:03 -0700622 domain INTEGER,
623 namespace INTEGER,
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800624 alias BLOB,
625 state INTEGER);",
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700626 NO_PARAMS,
627 )
628 .context("Failed to initialize \"keyentry\" table.")?;
629
630 conn.execute(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700631 "CREATE TABLE IF NOT EXISTS persistent.blobentry (
632 id INTEGER PRIMARY KEY,
633 subcomponent_type INTEGER,
634 keyentryid INTEGER,
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800635 blob BLOB);",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700636 NO_PARAMS,
637 )
638 .context("Failed to initialize \"blobentry\" table.")?;
639
640 conn.execute(
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700641 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000642 keyentryid INTEGER,
643 tag INTEGER,
644 data ANY,
645 security_level INTEGER);",
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700646 NO_PARAMS,
647 )
648 .context("Failed to initialize \"keyparameter\" table.")?;
649
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700650 conn.execute(
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800651 "CREATE TABLE IF NOT EXISTS persistent.keymetadata (
652 keyentryid INTEGER,
653 tag INTEGER,
654 data ANY);",
655 NO_PARAMS,
656 )
657 .context("Failed to initialize \"keymetadata\" table.")?;
658
659 conn.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800660 "CREATE TABLE IF NOT EXISTS persistent.grant (
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700661 id INTEGER UNIQUE,
662 grantee INTEGER,
663 keyentryid INTEGER,
664 access_vector INTEGER);",
665 NO_PARAMS,
666 )
667 .context("Failed to initialize \"grant\" table.")?;
668
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000669 //TODO: only drop the following two perboot tables if this is the first start up
670 //during the boot (b/175716626).
671 // conn.execute("DROP TABLE IF EXISTS perboot.authtoken;", NO_PARAMS)
672 // .context("Failed to drop perboot.authtoken table")?;
673 conn.execute(
674 "CREATE TABLE IF NOT EXISTS perboot.authtoken (
675 id INTEGER PRIMARY KEY,
676 challenge INTEGER,
677 user_id INTEGER,
678 auth_id INTEGER,
679 authenticator_type INTEGER,
680 timestamp INTEGER,
681 mac BLOB,
682 time_received INTEGER,
683 UNIQUE(user_id, auth_id, authenticator_type));",
684 NO_PARAMS,
685 )
686 .context("Failed to initialize \"authtoken\" table.")?;
687
688 // conn.execute("DROP TABLE IF EXISTS perboot.metadata;", NO_PARAMS)
689 // .context("Failed to drop perboot.metadata table")?;
690 // metadata table stores certain miscellaneous information required for keystore functioning
691 // during a boot cycle, as key-value pairs.
692 conn.execute(
693 "CREATE TABLE IF NOT EXISTS perboot.metadata (
694 key TEXT,
695 value BLOB,
696 UNIQUE(key));",
697 NO_PARAMS,
698 )
699 .context("Failed to initialize \"metadata\" table.")?;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +0000700 // TODO: Add the initial entry on last_off_body to the metadata table during the boot of the
701 // device (i.e. during the first startup of the keystore during a boot cycle).
702 Self::insert_last_off_body(conn, MonotonicRawTime::now()).context("In init-tables.")?;
Joel Galenson0891bc12020-07-20 10:37:03 -0700703 Ok(())
704 }
705
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700706 fn make_connection(persistent_file: &str, perboot_file: &str) -> Result<Connection> {
707 let conn =
708 Connection::open_in_memory().context("Failed to initialize SQLite connection.")?;
709
710 conn.execute("ATTACH DATABASE ? as persistent;", params![persistent_file])
711 .context("Failed to attach database persistent.")?;
712 conn.execute("ATTACH DATABASE ? as perboot;", params![perboot_file])
713 .context("Failed to attach database perboot.")?;
714
715 Ok(conn)
716 }
717
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800718 /// Get one unreferenced key. There is no particular order in which the keys are returned.
719 fn get_unreferenced_key_id(tx: &Transaction) -> Result<Option<i64>> {
720 tx.query_row(
721 "SELECT id FROM persistent.keyentry WHERE state = ?",
722 params![KeyLifeCycle::Unreferenced],
723 |row| row.get(0),
724 )
725 .optional()
726 .context("In get_unreferenced_key_id: Trying to get unreferenced key id.")
727 }
728
729 /// Returns a key id guard and key entry for one unreferenced key entry. Of the optional
730 /// fields of the key entry only the km_blob field will be populated. This is required
731 /// to subject the blob to its KeyMint instance for deletion.
732 pub fn get_unreferenced_key(&mut self) -> Result<Option<(KeyIdGuard, KeyEntry)>> {
733 self.with_transaction(TransactionBehavior::Deferred, |tx| {
734 let key_id = match Self::get_unreferenced_key_id(tx)
735 .context("Trying to get unreferenced key id")?
736 {
737 None => return Ok(None),
738 Some(id) => KEY_ID_LOCK.try_get(id).ok_or_else(KsError::sys).context(concat!(
739 "A key id lock was held for an unreferenced key. ",
740 "This should never happen."
741 ))?,
742 };
743 let key_entry = Self::load_key_components(tx, KeyEntryLoadBits::KM, key_id.id())
744 .context("Trying to get key components.")?;
745 Ok(Some((key_id, key_entry)))
746 })
747 .context("In get_unreferenced_key.")
748 }
749
750 /// This function purges all remnants of a key entry from the database.
751 /// Important: This does not check if the key was unreferenced, nor does it
752 /// subject the key to its KeyMint instance for permanent invalidation.
753 /// This function should only be called by the garbage collector.
754 /// To delete a key call `mark_unreferenced`, which transitions the key to the unreferenced
755 /// state, deletes all grants to the key, and notifies the garbage collector.
756 /// The garbage collector will:
757 /// 1. Call get_unreferenced_key.
758 /// 2. Determine the proper way to dispose of sensitive key material, e.g., call
759 /// `KeyMintDevice::delete()`.
760 /// 3. Call `purge_key_entry`.
761 pub fn purge_key_entry(&mut self, key_id: KeyIdGuard) -> Result<()> {
762 self.with_transaction(TransactionBehavior::Immediate, |tx| {
763 tx.execute("DELETE FROM persistent.keyentry WHERE id = ?;", params![key_id.id()])
764 .context("Trying to delete keyentry.")?;
765 tx.execute(
766 "DELETE FROM persistent.blobentry WHERE keyentryid = ?;",
767 params![key_id.id()],
768 )
769 .context("Trying to delete blobentries.")?;
770 tx.execute(
771 "DELETE FROM persistent.keymetadata WHERE keyentryid = ?;",
772 params![key_id.id()],
773 )
774 .context("Trying to delete keymetadata.")?;
775 tx.execute(
776 "DELETE FROM persistent.keyparameter WHERE keyentryid = ?;",
777 params![key_id.id()],
778 )
779 .context("Trying to delete keyparameters.")?;
780 let grants_deleted = tx
781 .execute("DELETE FROM persistent.grant WHERE keyentryid = ?;", params![key_id.id()])
782 .context("Trying to delete grants.")?;
783 if grants_deleted != 0 {
784 log::error!("Purged key that still had grants. This should not happen.");
785 }
786 Ok(())
787 })
788 .context("In purge_key_entry.")
789 }
790
791 /// This maintenance function should be called only once before the database is used for the
792 /// first time. It restores the invariant that `KeyLifeCycle::Existing` is a transient state.
793 /// The function transitions all key entries from Existing to Unreferenced unconditionally and
794 /// returns the number of rows affected. If this returns a value greater than 0, it means that
795 /// Keystore crashed at some point during key generation. Callers may want to log such
796 /// occurrences.
797 /// Unlike with `mark_unreferenced`, we don't need to purge grants, because only keys that made
798 /// it to `KeyLifeCycle::Live` may have grants.
799 pub fn cleanup_leftovers(&mut self) -> Result<usize> {
800 self.conn
801 .execute(
802 "UPDATE persistent.keyentry SET state = ? WHERE state = ?;",
803 params![KeyLifeCycle::Unreferenced, KeyLifeCycle::Existing],
804 )
805 .context("In cleanup_leftovers.")
806 }
807
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800808 /// Atomically loads a key entry and associated metadata or creates it using the
809 /// callback create_new_key callback. The callback is called during a database
810 /// transaction. This means that implementers should be mindful about using
811 /// blocking operations such as IPC or grabbing mutexes.
812 pub fn get_or_create_key_with<F>(
813 &mut self,
814 domain: Domain,
815 namespace: i64,
816 alias: &str,
817 create_new_key: F,
818 ) -> Result<(KeyIdGuard, KeyEntry)>
819 where
820 F: FnOnce() -> Result<(Vec<u8>, KeyMetaData)>,
821 {
822 let tx = self
823 .conn
824 .transaction_with_behavior(TransactionBehavior::Immediate)
825 .context("In get_or_create_key_with: Failed to initialize transaction.")?;
826
827 let id = {
828 let mut stmt = tx
829 .prepare(
830 "SELECT id FROM persistent.keyentry
831 WHERE
832 key_type = ?
833 AND domain = ?
834 AND namespace = ?
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800835 AND alias = ?
836 AND state = ?;",
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800837 )
838 .context("In get_or_create_key_with: Failed to select from keyentry table.")?;
839 let mut rows = stmt
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800840 .query(params![KeyType::Super, domain.0, namespace, alias, KeyLifeCycle::Live])
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800841 .context("In get_or_create_key_with: Failed to query from keyentry table.")?;
842
843 db_utils::with_rows_extract_one(&mut rows, |row| {
844 Ok(match row {
845 Some(r) => r.get(0).context("Failed to unpack id.")?,
846 None => None,
847 })
848 })
849 .context("In get_or_create_key_with.")?
850 };
851
852 let (id, entry) = match id {
853 Some(id) => (
854 id,
855 Self::load_key_components(&tx, KeyEntryLoadBits::KM, id)
856 .context("In get_or_create_key_with.")?,
857 ),
858
859 None => {
860 let id = Self::insert_with_retry(|id| {
861 tx.execute(
862 "INSERT into persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800863 (id, key_type, domain, namespace, alias, state)
864 VALUES(?, ?, ?, ?, ?, ?);",
865 params![id, KeyType::Super, domain.0, namespace, alias, KeyLifeCycle::Live],
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800866 )
867 })
868 .context("In get_or_create_key_with.")?;
869
870 let (blob, metadata) = create_new_key().context("In get_or_create_key_with.")?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800871 Self::insert_blob_internal(&tx, id, SubComponentType::KEY_BLOB, &blob)
872 .context("In get_of_create_key_with.")?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800873 metadata.store_in_db(id, &tx).context("In get_or_create_key_with.")?;
874 (id, KeyEntry { id, km_blob: Some(blob), metadata, ..Default::default() })
875 }
876 };
877 tx.commit().context("In get_or_create_key_with: Failed to commit transaction.")?;
878 Ok((KEY_ID_LOCK.get(id), entry))
879 }
880
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800881 /// Creates a transaction with the given behavior and executes f with the new transaction.
882 /// The transaction is committed only if f returns Ok.
883 fn with_transaction<T, F>(&mut self, behavior: TransactionBehavior, f: F) -> Result<T>
884 where
885 F: FnOnce(&Transaction) -> Result<T>,
886 {
887 let tx = self
888 .conn
889 .transaction_with_behavior(behavior)
890 .context("In with_transaction: Failed to initialize transaction.")?;
891 f(&tx).and_then(|result| {
892 tx.commit().context("In with_transaction: Failed to commit transaction.")?;
893 Ok(result)
894 })
895 }
896
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700897 /// Creates a new key entry and allocates a new randomized id for the new key.
898 /// The key id gets associated with a domain and namespace but not with an alias.
899 /// To complete key generation `rebind_alias` should be called after all of the
900 /// key artifacts, i.e., blobs and parameters have been associated with the new
901 /// key id. Finalizing with `rebind_alias` makes the creation of a new key entry
902 /// atomic even if key generation is not.
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800903 pub fn create_key_entry(&mut self, domain: Domain, namespace: i64) -> Result<KeyIdGuard> {
904 self.with_transaction(TransactionBehavior::Immediate, |tx| {
905 Self::create_key_entry_internal(tx, domain, namespace)
906 })
907 .context("In create_key_entry.")
908 }
909
910 fn create_key_entry_internal(
911 tx: &Transaction,
912 domain: Domain,
913 namespace: i64,
914 ) -> Result<KeyIdGuard> {
Joel Galenson0891bc12020-07-20 10:37:03 -0700915 match domain {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700916 Domain::APP | Domain::SELINUX => {}
Joel Galenson0891bc12020-07-20 10:37:03 -0700917 _ => {
918 return Err(KsError::sys())
919 .context(format!("Domain {:?} must be either App or SELinux.", domain));
920 }
921 }
Janis Danisevskisaec14592020-11-12 09:41:49 -0800922 Ok(KEY_ID_LOCK.get(
923 Self::insert_with_retry(|id| {
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800924 tx.execute(
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800925 "INSERT into persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800926 (id, key_type, domain, namespace, alias, state)
927 VALUES(?, ?, ?, ?, NULL, ?);",
928 params![
929 id,
930 KeyType::Client,
931 domain.0 as u32,
932 namespace,
933 KeyLifeCycle::Existing
934 ],
Janis Danisevskisaec14592020-11-12 09:41:49 -0800935 )
936 })
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800937 .context("In create_key_entry_internal")?,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800938 ))
Joel Galenson26f4d012020-07-17 14:57:21 -0700939 }
Joel Galenson33c04ad2020-08-03 11:04:38 -0700940
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700941 /// Inserts a new blob and associates it with the given key id. Each blob
942 /// has a sub component type and a security level.
943 /// Each key can have one of each sub component type associated. If more
944 /// are added only the most recent can be retrieved, and superseded blobs
945 /// will get garbage collected. The security level field of components
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800946 /// other than `SubComponentType::KEY_BLOB` are ignored.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700947 pub fn insert_blob(
948 &mut self,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800949 key_id: &KeyIdGuard,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700950 sc_type: SubComponentType,
951 blob: &[u8],
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700952 ) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800953 self.with_transaction(TransactionBehavior::Immediate, |tx| {
954 Self::insert_blob_internal(&tx, key_id.0, sc_type, blob)
955 })
956 .context("In insert_blob.")
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800957 }
958
959 fn insert_blob_internal(
960 tx: &Transaction,
961 key_id: i64,
962 sc_type: SubComponentType,
963 blob: &[u8],
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800964 ) -> Result<()> {
965 tx.execute(
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800966 "INSERT into persistent.blobentry (subcomponent_type, keyentryid, blob)
967 VALUES (?, ?, ?);",
968 params![sc_type, key_id, blob],
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800969 )
970 .context("In insert_blob_internal: Failed to insert blob.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700971 Ok(())
972 }
973
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700974 /// Inserts a collection of key parameters into the `persistent.keyparameter` table
975 /// and associates them with the given `key_id`.
976 pub fn insert_keyparameter<'a>(
977 &mut self,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800978 key_id: &KeyIdGuard,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700979 params: impl IntoIterator<Item = &'a KeyParameter>,
980 ) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800981 self.with_transaction(TransactionBehavior::Immediate, |tx| {
982 Self::insert_keyparameter_internal(tx, key_id, params)
983 })
984 .context("In insert_keyparameter.")
985 }
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700986
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800987 fn insert_keyparameter_internal<'a>(
988 tx: &Transaction,
989 key_id: &KeyIdGuard,
990 params: impl IntoIterator<Item = &'a KeyParameter>,
991 ) -> Result<()> {
992 let mut stmt = tx
993 .prepare(
994 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
995 VALUES (?, ?, ?, ?);",
996 )
997 .context("In insert_keyparameter_internal: Failed to prepare statement.")?;
998
999 let iter = params.into_iter();
1000 for p in iter {
1001 stmt.insert(params![
1002 key_id.0,
1003 p.get_tag().0,
1004 p.key_parameter_value(),
1005 p.security_level().0
1006 ])
1007 .with_context(|| {
1008 format!("In insert_keyparameter_internal: Failed to insert {:?}", p)
1009 })?;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001010 }
1011 Ok(())
1012 }
1013
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001014 /// Insert a set of key entry specific metadata into the database.
1015 pub fn insert_key_metadata(
1016 &mut self,
1017 key_id: &KeyIdGuard,
1018 metadata: &KeyMetaData,
1019 ) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001020 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1021 metadata.store_in_db(key_id.0, &tx)
1022 })
1023 .context("In insert_key_metadata.")
1024 }
1025
1026 fn rebind_alias(
1027 &mut self,
1028 newid: &KeyIdGuard,
1029 alias: &str,
1030 domain: Domain,
1031 namespace: i64,
1032 ) -> Result<()> {
1033 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1034 Self::rebind_alias_internal(tx, newid, alias, domain, namespace)
1035 })
1036 .context("In rebind_alias.")
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001037 }
1038
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001039 /// Updates the alias column of the given key id `newid` with the given alias,
1040 /// and atomically, removes the alias, domain, and namespace from another row
1041 /// with the same alias-domain-namespace tuple if such row exits.
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001042 fn rebind_alias_internal(
1043 tx: &Transaction,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001044 newid: &KeyIdGuard,
Joel Galenson33c04ad2020-08-03 11:04:38 -07001045 alias: &str,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001046 domain: Domain,
Joel Galenson33c04ad2020-08-03 11:04:38 -07001047 namespace: i64,
1048 ) -> Result<()> {
1049 match domain {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001050 Domain::APP | Domain::SELINUX => {}
Joel Galenson33c04ad2020-08-03 11:04:38 -07001051 _ => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001052 return Err(KsError::sys()).context(format!(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001053 "In rebind_alias_internal: Domain {:?} must be either App or SELinux.",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001054 domain
1055 ));
Joel Galenson33c04ad2020-08-03 11:04:38 -07001056 }
1057 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001058 let updated = tx
1059 .execute(
1060 "UPDATE persistent.keyentry
1061 SET alias = NULL, domain = NULL, namespace = NULL, state = ?
Joel Galenson33c04ad2020-08-03 11:04:38 -07001062 WHERE alias = ? AND domain = ? AND namespace = ?;",
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001063 params![KeyLifeCycle::Unreferenced, alias, domain.0 as u32, namespace],
1064 )
1065 .context("In rebind_alias_internal: Failed to rebind existing entry.")?;
1066 if updated != 0 {
1067 Gc::notify_gc();
1068 }
Joel Galenson33c04ad2020-08-03 11:04:38 -07001069 let result = tx
1070 .execute(
1071 "UPDATE persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001072 SET alias = ?, state = ?
1073 WHERE id = ? AND domain = ? AND namespace = ? AND state = ?;",
1074 params![
1075 alias,
1076 KeyLifeCycle::Live,
1077 newid.0,
1078 domain.0 as u32,
1079 namespace,
1080 KeyLifeCycle::Existing
1081 ],
Joel Galenson33c04ad2020-08-03 11:04:38 -07001082 )
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001083 .context("In rebind_alias_internal: Failed to set alias.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07001084 if result != 1 {
Joel Galenson33c04ad2020-08-03 11:04:38 -07001085 return Err(KsError::sys()).context(format!(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001086 "In rebind_alias_internal: Expected to update a single entry but instead updated {}.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07001087 result
1088 ));
1089 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001090 Ok(())
1091 }
1092
1093 /// Store a new key in a single transaction.
1094 /// The function creates a new key entry, populates the blob, key parameter, and metadata
1095 /// fields, and rebinds the given alias to the new key.
1096 pub fn store_new_key<'a>(
1097 &mut self,
1098 key: KeyDescriptor,
1099 params: impl IntoIterator<Item = &'a KeyParameter>,
1100 blob: &[u8],
1101 cert: Option<&[u8]>,
1102 cert_chain: Option<&[u8]>,
1103 metadata: &KeyMetaData,
1104 ) -> Result<KeyIdGuard> {
1105 let (alias, domain, namespace) = match key {
1106 KeyDescriptor { alias: Some(alias), domain: Domain::APP, nspace, blob: None }
1107 | KeyDescriptor { alias: Some(alias), domain: Domain::SELINUX, nspace, blob: None } => {
1108 (alias, key.domain, nspace)
1109 }
1110 _ => {
1111 return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT))
1112 .context("In store_new_key: Need alias and domain must be APP or SELINUX.")
1113 }
1114 };
1115 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1116 let key_id = Self::create_key_entry_internal(tx, domain, namespace)
1117 .context("Trying to create new key entry.")?;
1118 Self::insert_blob_internal(tx, key_id.id(), SubComponentType::KEY_BLOB, blob)
1119 .context("Trying to insert the key blob.")?;
1120 if let Some(cert) = cert {
1121 Self::insert_blob_internal(tx, key_id.id(), SubComponentType::CERT, cert)
1122 .context("Trying to insert the certificate.")?;
1123 }
1124 if let Some(cert_chain) = cert_chain {
1125 Self::insert_blob_internal(
1126 tx,
1127 key_id.id(),
1128 SubComponentType::CERT_CHAIN,
1129 cert_chain,
1130 )
1131 .context("Trying to insert the certificate chain.")?;
1132 }
1133 Self::insert_keyparameter_internal(tx, &key_id, params)
1134 .context("Trying to insert key parameters.")?;
1135 metadata.store_in_db(key_id.id(), tx).context("Tryin to insert key metadata.")?;
1136 Self::rebind_alias_internal(tx, &key_id, &alias, domain, namespace)
1137 .context("Trying to rebind alias.")?;
1138 Ok(key_id)
1139 })
1140 .context("In store_new_key.")
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001141 }
1142
1143 // Helper function loading the key_id given the key descriptor
1144 // tuple comprising domain, namespace, and alias.
1145 // Requires a valid transaction.
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001146 fn load_key_entry_id(tx: &Transaction, key: &KeyDescriptor, key_type: KeyType) -> Result<i64> {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001147 let alias = key
1148 .alias
1149 .as_ref()
1150 .map_or_else(|| Err(KsError::sys()), Ok)
1151 .context("In load_key_entry_id: Alias must be specified.")?;
1152 let mut stmt = tx
1153 .prepare(
1154 "SELECT id FROM persistent.keyentry
1155 WHERE
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001156 key_type = ?
1157 AND domain = ?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001158 AND namespace = ?
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001159 AND alias = ?
1160 AND state = ?;",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001161 )
1162 .context("In load_key_entry_id: Failed to select from keyentry table.")?;
1163 let mut rows = stmt
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001164 .query(params![key_type, key.domain.0 as u32, key.nspace, alias, KeyLifeCycle::Live])
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001165 .context("In load_key_entry_id: Failed to read from keyentry table.")?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001166 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001167 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001168 .get(0)
1169 .context("Failed to unpack id.")
1170 })
1171 .context("In load_key_entry_id.")
1172 }
1173
1174 /// This helper function completes the access tuple of a key, which is required
1175 /// to perform access control. The strategy depends on the `domain` field in the
1176 /// key descriptor.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001177 /// * Domain::SELINUX: The access tuple is complete and this function only loads
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001178 /// the key_id for further processing.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001179 /// * Domain::APP: Like Domain::SELINUX, but the tuple is completed by `caller_uid`
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001180 /// which serves as the namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001181 /// * Domain::GRANT: The grant table is queried for the `key_id` and the
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001182 /// `access_vector`.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001183 /// * Domain::KEY_ID: The keyentry table is queried for the owning `domain` and
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001184 /// `namespace`.
1185 /// In each case the information returned is sufficient to perform the access
1186 /// check and the key id can be used to load further key artifacts.
1187 fn load_access_tuple(
1188 tx: &Transaction,
1189 key: KeyDescriptor,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001190 key_type: KeyType,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001191 caller_uid: u32,
1192 ) -> Result<(i64, KeyDescriptor, Option<KeyPermSet>)> {
1193 match key.domain {
1194 // Domain App or SELinux. In this case we load the key_id from
1195 // the keyentry database for further loading of key components.
1196 // We already have the full access tuple to perform access control.
1197 // The only distinction is that we use the caller_uid instead
1198 // of the caller supplied namespace if the domain field is
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001199 // Domain::APP.
1200 Domain::APP | Domain::SELINUX => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001201 let mut access_key = key;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001202 if access_key.domain == Domain::APP {
1203 access_key.nspace = caller_uid as i64;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001204 }
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001205 let key_id = Self::load_key_entry_id(&tx, &access_key, key_type)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001206 .with_context(|| format!("With key.domain = {:?}.", access_key.domain))?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001207
1208 Ok((key_id, access_key, None))
1209 }
1210
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001211 // Domain::GRANT. In this case we load the key_id and the access_vector
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001212 // from the grant table.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001213 Domain::GRANT => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001214 let mut stmt = tx
1215 .prepare(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001216 "SELECT keyentryid, access_vector FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001217 WHERE grantee = ? AND id = ?;",
1218 )
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001219 .context("Domain::GRANT prepare statement failed")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001220 let mut rows = stmt
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001221 .query(params![caller_uid as i64, key.nspace])
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001222 .context("Domain:Grant: query failed.")?;
1223 let (key_id, access_vector): (i64, i32) =
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001224 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001225 let r =
1226 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001227 Ok((
1228 r.get(0).context("Failed to unpack key_id.")?,
1229 r.get(1).context("Failed to unpack access_vector.")?,
1230 ))
1231 })
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001232 .context("Domain::GRANT.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001233 Ok((key_id, key, Some(access_vector.into())))
1234 }
1235
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001236 // Domain::KEY_ID. In this case we load the domain and namespace from the
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001237 // keyentry database because we need them for access control.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001238 Domain::KEY_ID => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001239 let mut stmt = tx
1240 .prepare(
1241 "SELECT domain, namespace FROM persistent.keyentry
1242 WHERE
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001243 id = ?
1244 AND state = ?;",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001245 )
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001246 .context("Domain::KEY_ID: prepare statement failed")?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001247 let mut rows = stmt
1248 .query(params![key.nspace, KeyLifeCycle::Live])
1249 .context("Domain::KEY_ID: query failed.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001250 let (domain, namespace): (Domain, i64) =
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001251 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001252 let r =
1253 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001254 Ok((
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001255 Domain(r.get(0).context("Failed to unpack domain.")?),
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001256 r.get(1).context("Failed to unpack namespace.")?,
1257 ))
1258 })
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001259 .context("Domain::KEY_ID.")?;
1260 let key_id = key.nspace;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001261 let mut access_key = key;
1262 access_key.domain = domain;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001263 access_key.nspace = namespace;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001264
1265 Ok((key_id, access_key, None))
1266 }
1267 _ => Err(anyhow!(KsError::sys())),
1268 }
1269 }
1270
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001271 fn load_blob_components(
1272 key_id: i64,
1273 load_bits: KeyEntryLoadBits,
1274 tx: &Transaction,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001275 ) -> Result<(Option<Vec<u8>>, Option<Vec<u8>>, Option<Vec<u8>>)> {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001276 let mut stmt = tx
1277 .prepare(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001278 "SELECT MAX(id), subcomponent_type, blob FROM persistent.blobentry
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001279 WHERE keyentryid = ? GROUP BY subcomponent_type;",
1280 )
1281 .context("In load_blob_components: prepare statement failed.")?;
1282
1283 let mut rows =
1284 stmt.query(params![key_id]).context("In load_blob_components: query failed.")?;
1285
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001286 let mut km_blob: Option<Vec<u8>> = None;
1287 let mut cert_blob: Option<Vec<u8>> = None;
1288 let mut cert_chain_blob: Option<Vec<u8>> = None;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001289 db_utils::with_rows_extract_all(&mut rows, |row| {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001290 let sub_type: SubComponentType =
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001291 row.get(1).context("Failed to extract subcomponent_type.")?;
1292 match (sub_type, load_bits.load_public(), load_bits.load_km()) {
1293 (SubComponentType::KEY_BLOB, _, true) => {
1294 km_blob = Some(row.get(2).context("Failed to extract KM blob.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001295 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001296 (SubComponentType::CERT, true, _) => {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001297 cert_blob =
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001298 Some(row.get(2).context("Failed to extract public certificate blob.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001299 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001300 (SubComponentType::CERT_CHAIN, true, _) => {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001301 cert_chain_blob =
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001302 Some(row.get(2).context("Failed to extract certificate chain blob.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001303 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001304 (SubComponentType::CERT, _, _)
1305 | (SubComponentType::CERT_CHAIN, _, _)
1306 | (SubComponentType::KEY_BLOB, _, _) => {}
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001307 _ => Err(KsError::sys()).context("Unknown subcomponent type.")?,
1308 }
1309 Ok(())
1310 })
1311 .context("In load_blob_components.")?;
1312
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001313 Ok((km_blob, cert_blob, cert_chain_blob))
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001314 }
1315
1316 fn load_key_parameters(key_id: i64, tx: &Transaction) -> Result<Vec<KeyParameter>> {
1317 let mut stmt = tx
1318 .prepare(
1319 "SELECT tag, data, security_level from persistent.keyparameter
1320 WHERE keyentryid = ?;",
1321 )
1322 .context("In load_key_parameters: prepare statement failed.")?;
1323
1324 let mut parameters: Vec<KeyParameter> = Vec::new();
1325
1326 let mut rows =
1327 stmt.query(params![key_id]).context("In load_key_parameters: query failed.")?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001328 db_utils::with_rows_extract_all(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001329 let tag = Tag(row.get(0).context("Failed to read tag.")?);
1330 let sec_level = SecurityLevel(row.get(2).context("Failed to read sec_level.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001331 parameters.push(
1332 KeyParameter::new_from_sql(tag, &SqlField::new(1, &row), sec_level)
1333 .context("Failed to read KeyParameter.")?,
1334 );
1335 Ok(())
1336 })
1337 .context("In load_key_parameters.")?;
1338
1339 Ok(parameters)
1340 }
1341
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001342 /// Load a key entry by the given key descriptor.
1343 /// It uses the `check_permission` callback to verify if the access is allowed
1344 /// given the key access tuple read from the database using `load_access_tuple`.
1345 /// With `load_bits` the caller may specify which blobs shall be loaded from
1346 /// the blob database.
1347 pub fn load_key_entry(
1348 &mut self,
1349 key: KeyDescriptor,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001350 key_type: KeyType,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001351 load_bits: KeyEntryLoadBits,
1352 caller_uid: u32,
1353 check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001354 ) -> Result<(KeyIdGuard, KeyEntry)> {
1355 // KEY ID LOCK 1/2
1356 // If we got a key descriptor with a key id we can get the lock right away.
1357 // Otherwise we have to defer it until we know the key id.
1358 let key_id_guard = match key.domain {
1359 Domain::KEY_ID => Some(KEY_ID_LOCK.get(key.nspace)),
1360 _ => None,
1361 };
1362
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001363 let tx = self
1364 .conn
Janis Danisevskisaec14592020-11-12 09:41:49 -08001365 .unchecked_transaction()
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001366 .context("In load_key_entry: Failed to initialize transaction.")?;
1367
1368 // Load the key_id and complete the access control tuple.
1369 let (key_id, access_key_descriptor, access_vector) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001370 Self::load_access_tuple(&tx, key, key_type, caller_uid)
1371 .context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001372
1373 // Perform access control. It is vital that we return here if the permission is denied.
1374 // So do not touch that '?' at the end.
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001375 check_permission(&access_key_descriptor, access_vector).context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001376
Janis Danisevskisaec14592020-11-12 09:41:49 -08001377 // KEY ID LOCK 2/2
1378 // If we did not get a key id lock by now, it was because we got a key descriptor
1379 // without a key id. At this point we got the key id, so we can try and get a lock.
1380 // However, we cannot block here, because we are in the middle of the transaction.
1381 // So first we try to get the lock non blocking. If that fails, we roll back the
1382 // transaction and block until we get the lock. After we successfully got the lock,
1383 // we start a new transaction and load the access tuple again.
1384 //
1385 // We don't need to perform access control again, because we already established
1386 // that the caller had access to the given key. But we need to make sure that the
1387 // key id still exists. So we have to load the key entry by key id this time.
1388 let (key_id_guard, tx) = match key_id_guard {
1389 None => match KEY_ID_LOCK.try_get(key_id) {
1390 None => {
1391 // Roll back the transaction.
1392 tx.rollback().context("In load_key_entry: Failed to roll back transaction.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001393
Janis Danisevskisaec14592020-11-12 09:41:49 -08001394 // Block until we have a key id lock.
1395 let key_id_guard = KEY_ID_LOCK.get(key_id);
1396
1397 // Create a new transaction.
1398 let tx = self.conn.unchecked_transaction().context(
1399 "In load_key_entry: Failed to initialize transaction. (deferred key lock)",
1400 )?;
1401
1402 Self::load_access_tuple(
1403 &tx,
1404 // This time we have to load the key by the retrieved key id, because the
1405 // alias may have been rebound after we rolled back the transaction.
1406 KeyDescriptor {
1407 domain: Domain::KEY_ID,
1408 nspace: key_id,
1409 ..Default::default()
1410 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001411 key_type,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001412 caller_uid,
1413 )
1414 .context("In load_key_entry. (deferred key lock)")?;
1415 (key_id_guard, tx)
1416 }
1417 Some(l) => (l, tx),
1418 },
1419 Some(key_id_guard) => (key_id_guard, tx),
1420 };
1421
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001422 let key_entry = Self::load_key_components(&tx, load_bits, key_id_guard.id())
1423 .context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001424
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001425 tx.commit().context("In load_key_entry: Failed to commit transaction.")?;
1426
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001427 Ok((key_id_guard, key_entry))
1428 }
1429
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001430 fn mark_unreferenced(tx: &Transaction, key_id: i64) -> Result<()> {
1431 let updated = tx
1432 .execute(
1433 "UPDATE persistent.keyentry SET state = ? WHERE id = ?;",
1434 params![KeyLifeCycle::Unreferenced, key_id],
1435 )
1436 .context("In mark_unreferenced: Failed to update state of key entry.")?;
1437 if updated != 0 {
1438 Gc::notify_gc();
1439 }
1440 tx.execute("DELETE from persistent.grant WHERE keyentryid = ?;", params![key_id])
1441 .context("In mark_unreferenced: Failed to drop grants.")?;
1442 Ok(())
1443 }
1444
1445 /// Marks the given key as unreferenced and removes all of the grants to this key.
1446 pub fn unbind_key(
1447 &mut self,
1448 key: KeyDescriptor,
1449 key_type: KeyType,
1450 caller_uid: u32,
1451 check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
1452 ) -> Result<()> {
1453 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1454 let (key_id, access_key_descriptor, access_vector) =
1455 Self::load_access_tuple(tx, key, key_type, caller_uid)
1456 .context("Trying to get access tuple.")?;
1457
1458 // Perform access control. It is vital that we return here if the permission is denied.
1459 // So do not touch that '?' at the end.
1460 check_permission(&access_key_descriptor, access_vector)
1461 .context("While checking permission.")?;
1462
1463 Self::mark_unreferenced(tx, key_id).context("Trying to mark the key unreferenced.")
1464 })
1465 .context("In unbind_key.")
1466 }
1467
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001468 fn load_key_components(
1469 tx: &Transaction,
1470 load_bits: KeyEntryLoadBits,
1471 key_id: i64,
1472 ) -> Result<KeyEntry> {
1473 let metadata = KeyMetaData::load_from_db(key_id, &tx).context("In load_key_components.")?;
1474
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001475 let (km_blob, cert_blob, cert_chain_blob) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001476 Self::load_blob_components(key_id, load_bits, &tx)
1477 .context("In load_key_components.")?;
1478
1479 let parameters =
1480 Self::load_key_parameters(key_id, &tx).context("In load_key_components.")?;
1481
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001482 // Extract the security level by checking the security level of the origin tag.
1483 // Super keys don't have key parameters so we use security_level software by default.
1484 let sec_level = parameters
1485 .iter()
1486 .find_map(|k| match k.get_tag() {
1487 Tag::ORIGIN => Some(*k.security_level()),
1488 _ => None,
1489 })
1490 .unwrap_or(SecurityLevel::SOFTWARE);
1491
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001492 Ok(KeyEntry {
1493 id: key_id,
1494 km_blob,
1495 cert: cert_blob,
1496 cert_chain: cert_chain_blob,
1497 sec_level,
1498 parameters,
1499 metadata,
1500 })
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001501 }
1502
Janis Danisevskise92a5e62020-12-02 12:57:41 -08001503 /// Returns a list of KeyDescriptors in the selected domain/namespace.
1504 /// The key descriptors will have the domain, nspace, and alias field set.
1505 /// Domain must be APP or SELINUX, the caller must make sure of that.
1506 pub fn list(&mut self, domain: Domain, namespace: i64) -> Result<Vec<KeyDescriptor>> {
1507 let mut stmt = self
1508 .conn
1509 .prepare(
1510 "SELECT alias FROM persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001511 WHERE domain = ? AND namespace = ? AND alias IS NOT NULL AND state = ?;",
Janis Danisevskise92a5e62020-12-02 12:57:41 -08001512 )
1513 .context("In list: Failed to prepare.")?;
1514
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001515 let mut rows = stmt
1516 .query(params![domain.0 as u32, namespace, KeyLifeCycle::Live])
1517 .context("In list: Failed to query.")?;
Janis Danisevskise92a5e62020-12-02 12:57:41 -08001518
1519 let mut descriptors: Vec<KeyDescriptor> = Vec::new();
1520 db_utils::with_rows_extract_all(&mut rows, |row| {
1521 descriptors.push(KeyDescriptor {
1522 domain,
1523 nspace: namespace,
1524 alias: Some(row.get(0).context("Trying to extract alias.")?),
1525 blob: None,
1526 });
1527 Ok(())
1528 })
1529 .context("In list.")?;
1530 Ok(descriptors)
1531 }
1532
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001533 /// Adds a grant to the grant table.
1534 /// Like `load_key_entry` this function loads the access tuple before
1535 /// it uses the callback for a permission check. Upon success,
1536 /// it inserts the `grantee_uid`, `key_id`, and `access_vector` into the
1537 /// grant table. The new row will have a randomized id, which is used as
1538 /// grant id in the namespace field of the resulting KeyDescriptor.
1539 pub fn grant(
1540 &mut self,
1541 key: KeyDescriptor,
1542 caller_uid: u32,
1543 grantee_uid: u32,
1544 access_vector: KeyPermSet,
1545 check_permission: impl FnOnce(&KeyDescriptor, &KeyPermSet) -> Result<()>,
1546 ) -> Result<KeyDescriptor> {
1547 let tx = self
1548 .conn
1549 .transaction_with_behavior(TransactionBehavior::Immediate)
1550 .context("In grant: Failed to initialize transaction.")?;
1551
1552 // Load the key_id and complete the access control tuple.
1553 // We ignore the access vector here because grants cannot be granted.
1554 // The access vector returned here expresses the permissions the
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001555 // grantee has if key.domain == Domain::GRANT. But this vector
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001556 // cannot include the grant permission by design, so there is no way the
1557 // subsequent permission check can pass.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001558 // We could check key.domain == Domain::GRANT and fail early.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001559 // But even if we load the access tuple by grant here, the permission
1560 // check denies the attempt to create a grant by grant descriptor.
1561 let (key_id, access_key_descriptor, _) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001562 Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid).context("In grant")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001563
1564 // Perform access control. It is vital that we return here if the permission
1565 // was denied. So do not touch that '?' at the end of the line.
1566 // This permission check checks if the caller has the grant permission
1567 // for the given key and in addition to all of the permissions
1568 // expressed in `access_vector`.
1569 check_permission(&access_key_descriptor, &access_vector)
1570 .context("In grant: check_permission failed.")?;
1571
1572 let grant_id = if let Some(grant_id) = tx
1573 .query_row(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001574 "SELECT id FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001575 WHERE keyentryid = ? AND grantee = ?;",
1576 params![key_id, grantee_uid],
1577 |row| row.get(0),
1578 )
1579 .optional()
1580 .context("In grant: Failed get optional existing grant id.")?
1581 {
1582 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001583 "UPDATE persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001584 SET access_vector = ?
1585 WHERE id = ?;",
1586 params![i32::from(access_vector), grant_id],
1587 )
1588 .context("In grant: Failed to update existing grant.")?;
1589 grant_id
1590 } else {
Joel Galenson845f74b2020-09-09 14:11:55 -07001591 Self::insert_with_retry(|id| {
1592 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001593 "INSERT INTO persistent.grant (id, grantee, keyentryid, access_vector)
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001594 VALUES (?, ?, ?, ?);",
Joel Galenson845f74b2020-09-09 14:11:55 -07001595 params![id, grantee_uid, key_id, i32::from(access_vector)],
1596 )
1597 })
1598 .context("In grant")?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001599 };
1600 tx.commit().context("In grant: failed to commit transaction.")?;
1601
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001602 Ok(KeyDescriptor { domain: Domain::GRANT, nspace: grant_id, alias: None, blob: None })
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001603 }
1604
1605 /// This function checks permissions like `grant` and `load_key_entry`
1606 /// before removing a grant from the grant table.
1607 pub fn ungrant(
1608 &mut self,
1609 key: KeyDescriptor,
1610 caller_uid: u32,
1611 grantee_uid: u32,
1612 check_permission: impl FnOnce(&KeyDescriptor) -> Result<()>,
1613 ) -> Result<()> {
1614 let tx = self
1615 .conn
1616 .transaction_with_behavior(TransactionBehavior::Immediate)
1617 .context("In ungrant: Failed to initialize transaction.")?;
1618
1619 // Load the key_id and complete the access control tuple.
1620 // We ignore the access vector here because grants cannot be granted.
1621 let (key_id, access_key_descriptor, _) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001622 Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid)
1623 .context("In ungrant.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001624
1625 // Perform access control. We must return here if the permission
1626 // was denied. So do not touch the '?' at the end of this line.
1627 check_permission(&access_key_descriptor).context("In grant: check_permission failed.")?;
1628
1629 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001630 "DELETE FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001631 WHERE keyentryid = ? AND grantee = ?;",
1632 params![key_id, grantee_uid],
1633 )
1634 .context("Failed to delete grant.")?;
1635
1636 tx.commit().context("In ungrant: failed to commit transaction.")?;
1637
1638 Ok(())
1639 }
1640
Joel Galenson845f74b2020-09-09 14:11:55 -07001641 // Generates a random id and passes it to the given function, which will
1642 // try to insert it into a database. If that insertion fails, retry;
1643 // otherwise return the id.
1644 fn insert_with_retry(inserter: impl Fn(i64) -> rusqlite::Result<usize>) -> Result<i64> {
1645 loop {
1646 let newid: i64 = random();
1647 match inserter(newid) {
1648 // If the id already existed, try again.
1649 Err(rusqlite::Error::SqliteFailure(
1650 libsqlite3_sys::Error {
1651 code: libsqlite3_sys::ErrorCode::ConstraintViolation,
1652 extended_code: libsqlite3_sys::SQLITE_CONSTRAINT_UNIQUE,
1653 },
1654 _,
1655 )) => (),
1656 Err(e) => {
1657 return Err(e).context("In insert_with_retry: failed to insert into database.")
1658 }
1659 _ => return Ok(newid),
1660 }
1661 }
1662 }
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001663
1664 /// Insert or replace the auth token based on the UNIQUE constraint of the auth token table
1665 pub fn insert_auth_token(&mut self, auth_token: &HardwareAuthToken) -> Result<()> {
1666 self.conn
1667 .execute(
1668 "INSERT OR REPLACE INTO perboot.authtoken (challenge, user_id, auth_id,
1669 authenticator_type, timestamp, mac, time_received) VALUES(?, ?, ?, ?, ?, ?, ?);",
1670 params![
1671 auth_token.challenge,
1672 auth_token.userId,
1673 auth_token.authenticatorId,
1674 auth_token.authenticatorType.0 as i32,
1675 auth_token.timestamp.milliSeconds as i64,
1676 auth_token.mac,
1677 MonotonicRawTime::now(),
1678 ],
1679 )
1680 .context("In insert_auth_token: failed to insert auth token into the database")?;
1681 Ok(())
1682 }
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001683
1684 /// find the auth token entry issued for a time-out token
1685 pub fn find_timed_auth_token_entry(
1686 &mut self,
1687 user_secure_ids: &[i64],
1688 auth_type: HardwareAuthenticatorType,
1689 key_time_out: i64,
1690 allow_while_on_body: bool,
1691 ) -> Result<AuthTokenEntry> {
1692 let tx = self
1693 .conn
1694 .transaction_with_behavior(TransactionBehavior::Immediate)
1695 .context("In find_timed_auth_token_entry: failed to initialize transaction.")?;
1696 let auth_token_entries =
1697 Self::load_auth_token_entries(&tx).context("In find_timed_auth_token_entry.")?;
1698 // NOTE: Although in legacy keystore both timestamp and time_received are used when finding
1699 // the newest match, we decided to only consider time_received in keystore2 code.
1700 // TODO: verify that the iter().find() preserves the order.
1701 let newest_match: Option<AuthTokenEntry> = auth_token_entries.into_iter().find(|entry| {
1702 AuthTokenEntry::satisfies_auth(&entry.auth_token, user_secure_ids, auth_type)
1703 });
1704
1705 // Tag::ALLOW_WHILE_ON_BODY specifies that the key may be used after authentication
1706 // timeout if device is still on-body. So we return error only if both checks fail.
1707 if let Some(newest_match_entry) = newest_match {
1708 let current_time = MonotonicRawTime::now();
1709 let time_since_received_plus_time_out =
1710 match newest_match_entry.time_received.seconds().checked_add(key_time_out) {
1711 Some(t) => t,
1712 None => {
1713 // we do not expect this behavior, so we need to log this error if it ever
1714 // happens.
1715 error!("In find_timed_auth_token_entry: overflow occurred.");
1716 return Err(KsError::Km(Ec::KEY_USER_NOT_AUTHENTICATED)).context(
1717 "In find_timed_auth_token_entry: matching auth token is expired.",
1718 );
1719 }
1720 };
1721 if (time_since_received_plus_time_out < current_time.seconds())
1722 && (!allow_while_on_body
1723 || (newest_match_entry.time_received.seconds()
1724 < Self::get_last_off_body(&tx)?.seconds()))
1725 {
1726 return Err(KsError::Km(Ec::KEY_USER_NOT_AUTHENTICATED))
1727 .context("In find_timed_auth_token_entry: matching auth token is expired.");
1728 }
1729 tx.commit().context("In find_timed_auth_token_entry, failed to commit transaction.")?;
1730 Ok(newest_match_entry)
1731 } else {
1732 Err(KsError::Km(Ec::KEY_USER_NOT_AUTHENTICATED))
1733 .context("In find_timed_auth_token_entry: no matching auth token found.")
1734 }
1735 }
1736
1737 /// load the existing auth token entries in perboot.authtoken table into a vector.
1738 /// return None if the table is empty.
1739 fn load_auth_token_entries(tx: &Transaction) -> Result<Vec<AuthTokenEntry>> {
1740 let mut stmt = tx
1741 .prepare("SELECT * from perboot.authtoken ORDER BY time_received DESC;")
1742 .context("In load_auth_token_entries: select prepare statement failed.")?;
1743
1744 let auth_token_entries: Vec<AuthTokenEntry> = stmt
1745 .query_map(NO_PARAMS, |row| {
1746 Ok(AuthTokenEntry::new(
1747 HardwareAuthToken {
1748 challenge: row.get(1)?,
1749 userId: row.get(2)?,
1750 authenticatorId: row.get(3)?,
1751 authenticatorType: HardwareAuthenticatorType(row.get(4)?),
1752 timestamp: Timestamp { milliSeconds: row.get(5)? },
1753 mac: row.get(6)?,
1754 },
1755 row.get(7)?,
1756 ))
1757 })
1758 .context("In load_auth_token_entries: query_map failed.")?
1759 .collect::<Result<Vec<AuthTokenEntry>, Error>>()
1760 .context(
1761 "In load_auth_token_entries: failed to create a vector of auth token entries
1762 from mapped rows.",
1763 )?;
1764 Ok(auth_token_entries)
1765 }
1766
1767 /// insert last_off_body into the metadata table at the initialization of auth token table
1768 pub fn insert_last_off_body(conn: &Connection, last_off_body: MonotonicRawTime) -> Result<()> {
1769 conn.execute(
1770 "INSERT OR REPLACE INTO perboot.metadata (key, value) VALUES (?, ?);",
1771 params!["last_off_body", last_off_body],
1772 )
1773 .context("In insert_last_off_body: failed to insert.")?;
1774 Ok(())
1775 }
1776
1777 /// update last_off_body when on_device_off_body is called
1778 pub fn update_last_off_body(&self, last_off_body: MonotonicRawTime) -> Result<()> {
1779 self.conn
1780 .execute(
1781 "UPDATE perboot.metadata SET value = ? WHERE key = ?;",
1782 params![last_off_body, "last_off_body"],
1783 )
1784 .context("In update_last_off_body: failed to update.")?;
1785 Ok(())
1786 }
1787
1788 /// get last_off_body time when finding auth tokens
1789 fn get_last_off_body(tx: &Transaction) -> Result<MonotonicRawTime> {
1790 let mut stmt = tx
1791 .prepare("SELECT value from perboot.metadata WHERE key = ?;")
1792 .context("In get_last_off_body: select prepare statement failed.")?;
1793 let last_off_body: Result<MonotonicRawTime> = stmt
1794 .query_row(params!["last_off_body"], |row| Ok(row.get(0)?))
1795 .context("In get_last_off_body: query_row failed.");
1796 last_off_body
1797 }
Joel Galenson26f4d012020-07-17 14:57:21 -07001798}
1799
1800#[cfg(test)]
1801mod tests {
1802
1803 use super::*;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001804 use crate::key_parameter::{
1805 Algorithm, BlockMode, Digest, EcCurve, HardwareAuthenticatorType, KeyOrigin, KeyParameter,
1806 KeyParameterValue, KeyPurpose, PaddingMode, SecurityLevel,
1807 };
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001808 use crate::key_perm_set;
1809 use crate::permission::{KeyPerm, KeyPermSet};
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001810 use crate::test::utils::TempDir;
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001811 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
1812 HardwareAuthToken::HardwareAuthToken,
1813 HardwareAuthenticatorType::HardwareAuthenticatorType as kmhw_authenticator_type,
1814 Timestamp::Timestamp,
1815 };
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001816 use rusqlite::NO_PARAMS;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001817 use rusqlite::{Error, TransactionBehavior};
Joel Galenson0891bc12020-07-20 10:37:03 -07001818 use std::cell::RefCell;
Janis Danisevskisaec14592020-11-12 09:41:49 -08001819 use std::sync::atomic::{AtomicU8, Ordering};
1820 use std::sync::Arc;
1821 use std::thread;
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00001822 use std::time::{Duration, SystemTime};
Joel Galenson0891bc12020-07-20 10:37:03 -07001823
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001824 fn new_test_db() -> Result<KeystoreDB> {
1825 let conn = KeystoreDB::make_connection("file::memory:", "file::memory:")?;
1826
1827 KeystoreDB::init_tables(&conn).context("Failed to initialize tables.")?;
1828 Ok(KeystoreDB { conn })
1829 }
1830
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001831 #[test]
1832 fn datetime() -> Result<()> {
1833 let conn = Connection::open_in_memory()?;
1834 conn.execute("CREATE TABLE test (ts DATETIME);", NO_PARAMS)?;
1835 let now = SystemTime::now();
1836 let duration = Duration::from_secs(1000);
1837 let then = now.checked_sub(duration).unwrap();
1838 let soon = now.checked_add(duration).unwrap();
1839 conn.execute(
1840 "INSERT INTO test (ts) VALUES (?), (?), (?);",
1841 params![DateTime::try_from(now)?, DateTime::try_from(then)?, DateTime::try_from(soon)?],
1842 )?;
1843 let mut stmt = conn.prepare("SELECT ts FROM test ORDER BY ts ASC;")?;
1844 let mut rows = stmt.query(NO_PARAMS)?;
1845 assert_eq!(DateTime::try_from(then)?, rows.next()?.unwrap().get(0)?);
1846 assert_eq!(DateTime::try_from(now)?, rows.next()?.unwrap().get(0)?);
1847 assert_eq!(DateTime::try_from(soon)?, rows.next()?.unwrap().get(0)?);
1848 assert!(rows.next()?.is_none());
1849 assert!(DateTime::try_from(then)? < DateTime::try_from(now)?);
1850 assert!(DateTime::try_from(then)? < DateTime::try_from(soon)?);
1851 assert!(DateTime::try_from(now)? < DateTime::try_from(soon)?);
1852 Ok(())
1853 }
1854
Joel Galenson0891bc12020-07-20 10:37:03 -07001855 // Ensure that we're using the "injected" random function, not the real one.
1856 #[test]
1857 fn test_mocked_random() {
1858 let rand1 = random();
1859 let rand2 = random();
1860 let rand3 = random();
1861 if rand1 == rand2 {
1862 assert_eq!(rand2 + 1, rand3);
1863 } else {
1864 assert_eq!(rand1 + 1, rand2);
1865 assert_eq!(rand2, rand3);
1866 }
1867 }
Joel Galenson26f4d012020-07-17 14:57:21 -07001868
Joel Galenson26f4d012020-07-17 14:57:21 -07001869 // Test that we have the correct tables.
1870 #[test]
1871 fn test_tables() -> Result<()> {
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001872 let db = new_test_db()?;
Joel Galenson26f4d012020-07-17 14:57:21 -07001873 let tables = db
1874 .conn
Joel Galenson2aab4432020-07-22 15:27:57 -07001875 .prepare("SELECT name from persistent.sqlite_master WHERE type='table' ORDER BY name;")?
Joel Galenson26f4d012020-07-17 14:57:21 -07001876 .query_map(params![], |row| row.get(0))?
1877 .collect::<rusqlite::Result<Vec<String>>>()?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001878 assert_eq!(tables.len(), 5);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001879 assert_eq!(tables[0], "blobentry");
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001880 assert_eq!(tables[1], "grant");
1881 assert_eq!(tables[2], "keyentry");
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001882 assert_eq!(tables[3], "keymetadata");
1883 assert_eq!(tables[4], "keyparameter");
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001884 let tables = db
1885 .conn
1886 .prepare("SELECT name from perboot.sqlite_master WHERE type='table' ORDER BY name;")?
1887 .query_map(params![], |row| row.get(0))?
1888 .collect::<rusqlite::Result<Vec<String>>>()?;
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001889
1890 assert_eq!(tables.len(), 2);
1891 assert_eq!(tables[0], "authtoken");
1892 assert_eq!(tables[1], "metadata");
Joel Galenson2aab4432020-07-22 15:27:57 -07001893 Ok(())
1894 }
1895
1896 #[test]
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001897 fn test_auth_token_table_invariant() -> Result<()> {
1898 let mut db = new_test_db()?;
1899 let auth_token1 = HardwareAuthToken {
1900 challenge: i64::MAX,
1901 userId: 200,
1902 authenticatorId: 200,
1903 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
1904 timestamp: Timestamp { milliSeconds: 500 },
1905 mac: String::from("mac").into_bytes(),
1906 };
1907 db.insert_auth_token(&auth_token1)?;
1908 let auth_tokens_returned = get_auth_tokens(&mut db)?;
1909 assert_eq!(auth_tokens_returned.len(), 1);
1910
1911 // insert another auth token with the same values for the columns in the UNIQUE constraint
1912 // of the auth token table and different value for timestamp
1913 let auth_token2 = HardwareAuthToken {
1914 challenge: i64::MAX,
1915 userId: 200,
1916 authenticatorId: 200,
1917 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
1918 timestamp: Timestamp { milliSeconds: 600 },
1919 mac: String::from("mac").into_bytes(),
1920 };
1921
1922 db.insert_auth_token(&auth_token2)?;
1923 let mut auth_tokens_returned = get_auth_tokens(&mut db)?;
1924 assert_eq!(auth_tokens_returned.len(), 1);
1925
1926 if let Some(auth_token) = auth_tokens_returned.pop() {
1927 assert_eq!(auth_token.auth_token.timestamp.milliSeconds, 600);
1928 }
1929
1930 // insert another auth token with the different values for the columns in the UNIQUE
1931 // constraint of the auth token table
1932 let auth_token3 = HardwareAuthToken {
1933 challenge: i64::MAX,
1934 userId: 201,
1935 authenticatorId: 200,
1936 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
1937 timestamp: Timestamp { milliSeconds: 600 },
1938 mac: String::from("mac").into_bytes(),
1939 };
1940
1941 db.insert_auth_token(&auth_token3)?;
1942 let auth_tokens_returned = get_auth_tokens(&mut db)?;
1943 assert_eq!(auth_tokens_returned.len(), 2);
1944
1945 Ok(())
1946 }
1947
1948 // utility function for test_auth_token_table_invariant()
1949 fn get_auth_tokens(db: &mut KeystoreDB) -> Result<Vec<AuthTokenEntry>> {
1950 let mut stmt = db.conn.prepare("SELECT * from perboot.authtoken;")?;
1951
1952 let auth_token_entries: Vec<AuthTokenEntry> = stmt
1953 .query_map(NO_PARAMS, |row| {
1954 Ok(AuthTokenEntry::new(
1955 HardwareAuthToken {
1956 challenge: row.get(1)?,
1957 userId: row.get(2)?,
1958 authenticatorId: row.get(3)?,
1959 authenticatorType: HardwareAuthenticatorType(row.get(4)?),
1960 timestamp: Timestamp { milliSeconds: row.get(5)? },
1961 mac: row.get(6)?,
1962 },
1963 row.get(7)?,
1964 ))
1965 })?
1966 .collect::<Result<Vec<AuthTokenEntry>, Error>>()?;
1967 Ok(auth_token_entries)
1968 }
1969
1970 #[test]
Joel Galenson2aab4432020-07-22 15:27:57 -07001971 fn test_persistence_for_files() -> Result<()> {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001972 let temp_dir = TempDir::new("persistent_db_test")?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001973 let mut db = KeystoreDB::new(temp_dir.path())?;
Joel Galenson2aab4432020-07-22 15:27:57 -07001974
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001975 db.create_key_entry(Domain::APP, 100)?;
Joel Galenson2aab4432020-07-22 15:27:57 -07001976 let entries = get_keyentry(&db)?;
1977 assert_eq!(entries.len(), 1);
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001978
1979 let db = KeystoreDB::new(temp_dir.path())?;
Joel Galenson2aab4432020-07-22 15:27:57 -07001980
1981 let entries_new = get_keyentry(&db)?;
1982 assert_eq!(entries, entries_new);
1983 Ok(())
1984 }
1985
1986 #[test]
Joel Galenson0891bc12020-07-20 10:37:03 -07001987 fn test_create_key_entry() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001988 fn extractor(ke: &KeyEntryRow) -> (Domain, i64, Option<&str>) {
Joel Galenson0891bc12020-07-20 10:37:03 -07001989 (ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref())
1990 }
1991
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001992 let mut db = new_test_db()?;
Joel Galenson0891bc12020-07-20 10:37:03 -07001993
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001994 db.create_key_entry(Domain::APP, 100)?;
1995 db.create_key_entry(Domain::SELINUX, 101)?;
Joel Galenson0891bc12020-07-20 10:37:03 -07001996
1997 let entries = get_keyentry(&db)?;
1998 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001999 assert_eq!(extractor(&entries[0]), (Domain::APP, 100, None));
2000 assert_eq!(extractor(&entries[1]), (Domain::SELINUX, 101, None));
Joel Galenson0891bc12020-07-20 10:37:03 -07002001
2002 // Test that we must pass in a valid Domain.
2003 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002004 db.create_key_entry(Domain::GRANT, 102),
2005 "Domain Domain(1) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07002006 );
2007 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002008 db.create_key_entry(Domain::BLOB, 103),
2009 "Domain Domain(3) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07002010 );
2011 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002012 db.create_key_entry(Domain::KEY_ID, 104),
2013 "Domain Domain(4) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07002014 );
2015
2016 Ok(())
2017 }
2018
Joel Galenson33c04ad2020-08-03 11:04:38 -07002019 #[test]
2020 fn test_rebind_alias() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002021 fn extractor(ke: &KeyEntryRow) -> (Option<Domain>, Option<i64>, Option<&str>) {
Joel Galenson33c04ad2020-08-03 11:04:38 -07002022 (ke.domain, ke.namespace, ke.alias.as_deref())
2023 }
2024
Janis Danisevskis4df44f42020-08-26 14:40:03 -07002025 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002026 db.create_key_entry(Domain::APP, 42)?;
2027 db.create_key_entry(Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07002028 let entries = get_keyentry(&db)?;
2029 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002030 assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), None));
2031 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
Joel Galenson33c04ad2020-08-03 11:04:38 -07002032
2033 // Test that the first call to rebind_alias sets the alias.
Janis Danisevskisaec14592020-11-12 09:41:49 -08002034 db.rebind_alias(&KEY_ID_LOCK.get(entries[0].id), "foo", Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07002035 let entries = get_keyentry(&db)?;
2036 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002037 assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), Some("foo")));
2038 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
Joel Galenson33c04ad2020-08-03 11:04:38 -07002039
2040 // Test that the second call to rebind_alias also empties the old one.
Janis Danisevskisaec14592020-11-12 09:41:49 -08002041 db.rebind_alias(&KEY_ID_LOCK.get(entries[1].id), "foo", Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07002042 let entries = get_keyentry(&db)?;
2043 assert_eq!(entries.len(), 2);
Joel Galenson7fa5c412020-11-19 10:56:54 -08002044 assert_eq!(extractor(&entries[0]), (None, None, None));
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002045 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
Joel Galenson33c04ad2020-08-03 11:04:38 -07002046
2047 // Test that we must pass in a valid Domain.
2048 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08002049 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::GRANT, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002050 "Domain Domain(1) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07002051 );
2052 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08002053 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::BLOB, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002054 "Domain Domain(3) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07002055 );
2056 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08002057 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::KEY_ID, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002058 "Domain Domain(4) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07002059 );
2060
2061 // Test that we correctly handle setting an alias for something that does not exist.
2062 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08002063 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::SELINUX, 42),
Joel Galenson33c04ad2020-08-03 11:04:38 -07002064 "Expected to update a single entry but instead updated 0",
2065 );
2066 // Test that we correctly abort the transaction in this case.
2067 let entries = get_keyentry(&db)?;
2068 assert_eq!(entries.len(), 2);
Joel Galenson7fa5c412020-11-19 10:56:54 -08002069 assert_eq!(extractor(&entries[0]), (None, None, None));
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002070 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
Joel Galenson33c04ad2020-08-03 11:04:38 -07002071
2072 Ok(())
2073 }
2074
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002075 #[test]
2076 fn test_grant_ungrant() -> Result<()> {
2077 const CALLER_UID: u32 = 15;
2078 const GRANTEE_UID: u32 = 12;
2079 const SELINUX_NAMESPACE: i64 = 7;
2080
2081 let mut db = new_test_db()?;
2082 db.conn.execute(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002083 "INSERT INTO persistent.keyentry (id, key_type, domain, namespace, alias, state)
2084 VALUES (1, 0, 0, 15, 'key', 1), (2, 0, 2, 7, 'yek', 1);",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002085 NO_PARAMS,
2086 )?;
2087 let app_key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002088 domain: super::Domain::APP,
2089 nspace: 0,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002090 alias: Some("key".to_string()),
2091 blob: None,
2092 };
2093 const PVEC1: KeyPermSet = key_perm_set![KeyPerm::use_(), KeyPerm::get_info()];
2094 const PVEC2: KeyPermSet = key_perm_set![KeyPerm::use_()];
2095
2096 // Reset totally predictable random number generator in case we
2097 // are not the first test running on this thread.
2098 reset_random();
2099 let next_random = 0i64;
2100
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002101 let app_granted_key = db
2102 .grant(app_key.clone(), CALLER_UID, GRANTEE_UID, PVEC1, |k, a| {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002103 assert_eq!(*a, PVEC1);
2104 assert_eq!(
2105 *k,
2106 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002107 domain: super::Domain::APP,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002108 // namespace must be set to the caller_uid.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002109 nspace: CALLER_UID as i64,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002110 alias: Some("key".to_string()),
2111 blob: None,
2112 }
2113 );
2114 Ok(())
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002115 })
2116 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002117
2118 assert_eq!(
2119 app_granted_key,
2120 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002121 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002122 // The grantid is next_random due to the mock random number generator.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002123 nspace: next_random,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002124 alias: None,
2125 blob: None,
2126 }
2127 );
2128
2129 let selinux_key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002130 domain: super::Domain::SELINUX,
2131 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002132 alias: Some("yek".to_string()),
2133 blob: None,
2134 };
2135
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002136 let selinux_granted_key = db
2137 .grant(selinux_key.clone(), CALLER_UID, 12, PVEC1, |k, a| {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002138 assert_eq!(*a, PVEC1);
2139 assert_eq!(
2140 *k,
2141 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002142 domain: super::Domain::SELINUX,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002143 // namespace must be the supplied SELinux
2144 // namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002145 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002146 alias: Some("yek".to_string()),
2147 blob: None,
2148 }
2149 );
2150 Ok(())
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002151 })
2152 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002153
2154 assert_eq!(
2155 selinux_granted_key,
2156 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002157 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002158 // The grantid is next_random + 1 due to the mock random number generator.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002159 nspace: next_random + 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002160 alias: None,
2161 blob: None,
2162 }
2163 );
2164
2165 // This should update the existing grant with PVEC2.
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002166 let selinux_granted_key = db
2167 .grant(selinux_key.clone(), CALLER_UID, 12, PVEC2, |k, a| {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002168 assert_eq!(*a, PVEC2);
2169 assert_eq!(
2170 *k,
2171 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002172 domain: super::Domain::SELINUX,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002173 // namespace must be the supplied SELinux
2174 // namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002175 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002176 alias: Some("yek".to_string()),
2177 blob: None,
2178 }
2179 );
2180 Ok(())
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002181 })
2182 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002183
2184 assert_eq!(
2185 selinux_granted_key,
2186 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002187 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002188 // Same grant id as before. The entry was only updated.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002189 nspace: next_random + 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002190 alias: None,
2191 blob: None,
2192 }
2193 );
2194
2195 {
2196 // Limiting scope of stmt, because it borrows db.
2197 let mut stmt = db
2198 .conn
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002199 .prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?;
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07002200 let mut rows =
2201 stmt.query_map::<(i64, u32, i64, KeyPermSet), _, _>(NO_PARAMS, |row| {
2202 Ok((
2203 row.get(0)?,
2204 row.get(1)?,
2205 row.get(2)?,
2206 KeyPermSet::from(row.get::<_, i32>(3)?),
2207 ))
2208 })?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002209
2210 let r = rows.next().unwrap().unwrap();
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07002211 assert_eq!(r, (next_random, GRANTEE_UID, 1, PVEC1));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002212 let r = rows.next().unwrap().unwrap();
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07002213 assert_eq!(r, (next_random + 1, GRANTEE_UID, 2, PVEC2));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002214 assert!(rows.next().is_none());
2215 }
2216
2217 debug_dump_keyentry_table(&mut db)?;
2218 println!("app_key {:?}", app_key);
2219 println!("selinux_key {:?}", selinux_key);
2220
2221 db.ungrant(app_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
2222 db.ungrant(selinux_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
2223
2224 Ok(())
2225 }
2226
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002227 static TEST_KEY_BLOB: &[u8] = b"my test blob";
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002228 static TEST_CERT_BLOB: &[u8] = b"my test cert";
2229 static TEST_CERT_CHAIN_BLOB: &[u8] = b"my test cert_chain";
2230
2231 #[test]
2232 fn test_insert_blob() -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002233 let key_id = KEY_ID_LOCK.get(3000);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002234 let mut db = new_test_db()?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002235 db.insert_blob(&key_id, SubComponentType::KEY_BLOB, TEST_KEY_BLOB)?;
2236 db.insert_blob(&key_id, SubComponentType::CERT, TEST_CERT_BLOB)?;
2237 db.insert_blob(&key_id, SubComponentType::CERT_CHAIN, TEST_CERT_CHAIN_BLOB)?;
2238 drop(key_id);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002239
2240 let mut stmt = db.conn.prepare(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002241 "SELECT subcomponent_type, keyentryid, blob FROM persistent.blobentry
2242 ORDER BY subcomponent_type ASC;",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002243 )?;
2244 let mut rows = stmt
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002245 .query_map::<(SubComponentType, i64, Vec<u8>), _, _>(NO_PARAMS, |row| {
2246 Ok((row.get(0)?, row.get(1)?, row.get(2)?))
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002247 })?;
2248 let r = rows.next().unwrap().unwrap();
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002249 assert_eq!(r, (SubComponentType::KEY_BLOB, 3000, TEST_KEY_BLOB.to_vec()));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002250 let r = rows.next().unwrap().unwrap();
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002251 assert_eq!(r, (SubComponentType::CERT, 3000, TEST_CERT_BLOB.to_vec()));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002252 let r = rows.next().unwrap().unwrap();
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002253 assert_eq!(r, (SubComponentType::CERT_CHAIN, 3000, TEST_CERT_CHAIN_BLOB.to_vec()));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002254
2255 Ok(())
2256 }
2257
2258 static TEST_ALIAS: &str = "my super duper key";
2259
2260 #[test]
2261 fn test_insert_and_load_full_keyentry_domain_app() -> Result<()> {
2262 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002263 let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002264 .context("test_insert_and_load_full_keyentry_domain_app")?
2265 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002266 let (_key_guard, key_entry) = db
2267 .load_key_entry(
2268 KeyDescriptor {
2269 domain: Domain::APP,
2270 nspace: 0,
2271 alias: Some(TEST_ALIAS.to_string()),
2272 blob: None,
2273 },
2274 KeyType::Client,
2275 KeyEntryLoadBits::BOTH,
2276 1,
2277 |_k, _av| Ok(()),
2278 )
2279 .unwrap();
2280 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
2281
2282 db.unbind_key(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002283 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002284 domain: Domain::APP,
2285 nspace: 0,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002286 alias: Some(TEST_ALIAS.to_string()),
2287 blob: None,
2288 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002289 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002290 1,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002291 |_, _| Ok(()),
2292 )
2293 .unwrap();
2294
2295 assert_eq!(
2296 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2297 db.load_key_entry(
2298 KeyDescriptor {
2299 domain: Domain::APP,
2300 nspace: 0,
2301 alias: Some(TEST_ALIAS.to_string()),
2302 blob: None,
2303 },
2304 KeyType::Client,
2305 KeyEntryLoadBits::NONE,
2306 1,
2307 |_k, _av| Ok(()),
2308 )
2309 .unwrap_err()
2310 .root_cause()
2311 .downcast_ref::<KsError>()
2312 );
2313
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002314 Ok(())
2315 }
2316
2317 #[test]
2318 fn test_insert_and_load_full_keyentry_domain_selinux() -> Result<()> {
2319 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002320 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002321 .context("test_insert_and_load_full_keyentry_domain_selinux")?
2322 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002323 let (_key_guard, key_entry) = db
2324 .load_key_entry(
2325 KeyDescriptor {
2326 domain: Domain::SELINUX,
2327 nspace: 1,
2328 alias: Some(TEST_ALIAS.to_string()),
2329 blob: None,
2330 },
2331 KeyType::Client,
2332 KeyEntryLoadBits::BOTH,
2333 1,
2334 |_k, _av| Ok(()),
2335 )
2336 .unwrap();
2337 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
2338
2339 db.unbind_key(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002340 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002341 domain: Domain::SELINUX,
2342 nspace: 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002343 alias: Some(TEST_ALIAS.to_string()),
2344 blob: None,
2345 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002346 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002347 1,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002348 |_, _| Ok(()),
2349 )
2350 .unwrap();
2351
2352 assert_eq!(
2353 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2354 db.load_key_entry(
2355 KeyDescriptor {
2356 domain: Domain::SELINUX,
2357 nspace: 1,
2358 alias: Some(TEST_ALIAS.to_string()),
2359 blob: None,
2360 },
2361 KeyType::Client,
2362 KeyEntryLoadBits::NONE,
2363 1,
2364 |_k, _av| Ok(()),
2365 )
2366 .unwrap_err()
2367 .root_cause()
2368 .downcast_ref::<KsError>()
2369 );
2370
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002371 Ok(())
2372 }
2373
2374 #[test]
2375 fn test_insert_and_load_full_keyentry_domain_key_id() -> Result<()> {
2376 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002377 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002378 .context("test_insert_and_load_full_keyentry_domain_key_id")?
2379 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002380 let (_, key_entry) = db
2381 .load_key_entry(
2382 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
2383 KeyType::Client,
2384 KeyEntryLoadBits::BOTH,
2385 1,
2386 |_k, _av| Ok(()),
2387 )
2388 .unwrap();
2389
2390 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
2391
2392 db.unbind_key(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002393 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002394 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002395 1,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002396 |_, _| Ok(()),
2397 )
2398 .unwrap();
2399
2400 assert_eq!(
2401 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2402 db.load_key_entry(
2403 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
2404 KeyType::Client,
2405 KeyEntryLoadBits::NONE,
2406 1,
2407 |_k, _av| Ok(()),
2408 )
2409 .unwrap_err()
2410 .root_cause()
2411 .downcast_ref::<KsError>()
2412 );
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002413
2414 Ok(())
2415 }
2416
2417 #[test]
2418 fn test_insert_and_load_full_keyentry_from_grant() -> Result<()> {
2419 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002420 let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002421 .context("test_insert_and_load_full_keyentry_from_grant")?
2422 .0;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002423
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002424 let granted_key = db
2425 .grant(
2426 KeyDescriptor {
2427 domain: Domain::APP,
2428 nspace: 0,
2429 alias: Some(TEST_ALIAS.to_string()),
2430 blob: None,
2431 },
2432 1,
2433 2,
2434 key_perm_set![KeyPerm::use_()],
2435 |_k, _av| Ok(()),
2436 )
2437 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002438
2439 debug_dump_grant_table(&mut db)?;
2440
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002441 let (_key_guard, key_entry) = db
2442 .load_key_entry(
2443 granted_key.clone(),
2444 KeyType::Client,
2445 KeyEntryLoadBits::BOTH,
2446 2,
2447 |k, av| {
2448 assert_eq!(Domain::GRANT, k.domain);
2449 assert!(av.unwrap().includes(KeyPerm::use_()));
2450 Ok(())
2451 },
2452 )
2453 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002454
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002455 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002456
2457 db.unbind_key(granted_key.clone(), KeyType::Client, 2, |_, _| Ok(())).unwrap();
2458
2459 assert_eq!(
2460 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2461 db.load_key_entry(
2462 granted_key,
2463 KeyType::Client,
2464 KeyEntryLoadBits::NONE,
2465 2,
2466 |_k, _av| Ok(()),
2467 )
2468 .unwrap_err()
2469 .root_cause()
2470 .downcast_ref::<KsError>()
2471 );
2472
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002473 Ok(())
2474 }
2475
Janis Danisevskisaec14592020-11-12 09:41:49 -08002476 static KEY_LOCK_TEST_ALIAS: &str = "my super duper locked key";
2477
Janis Danisevskisaec14592020-11-12 09:41:49 -08002478 #[test]
2479 fn test_insert_and_load_full_keyentry_domain_app_concurrently() -> Result<()> {
2480 let handle = {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002481 let temp_dir = Arc::new(TempDir::new("id_lock_test")?);
2482 let temp_dir_clone = temp_dir.clone();
2483 let mut db = KeystoreDB::new(temp_dir.path())?;
Janis Danisevskisaec14592020-11-12 09:41:49 -08002484 let key_id = make_test_key_entry(&mut db, Domain::APP, 33, KEY_LOCK_TEST_ALIAS)
2485 .context("test_insert_and_load_full_keyentry_domain_app")?
2486 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002487 let (_key_guard, key_entry) = db
2488 .load_key_entry(
2489 KeyDescriptor {
2490 domain: Domain::APP,
2491 nspace: 0,
2492 alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
2493 blob: None,
2494 },
2495 KeyType::Client,
2496 KeyEntryLoadBits::BOTH,
2497 33,
2498 |_k, _av| Ok(()),
2499 )
2500 .unwrap();
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002501 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
Janis Danisevskisaec14592020-11-12 09:41:49 -08002502 let state = Arc::new(AtomicU8::new(1));
2503 let state2 = state.clone();
2504
2505 // Spawning a second thread that attempts to acquire the key id lock
2506 // for the same key as the primary thread. The primary thread then
2507 // waits, thereby forcing the secondary thread into the second stage
2508 // of acquiring the lock (see KEY ID LOCK 2/2 above).
2509 // The test succeeds if the secondary thread observes the transition
2510 // of `state` from 1 to 2, despite having a whole second to overtake
2511 // the primary thread.
2512 let handle = thread::spawn(move || {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002513 let temp_dir = temp_dir_clone;
2514 let mut db = KeystoreDB::new(temp_dir.path()).unwrap();
Janis Danisevskisaec14592020-11-12 09:41:49 -08002515 assert!(db
2516 .load_key_entry(
2517 KeyDescriptor {
2518 domain: Domain::APP,
2519 nspace: 0,
2520 alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
2521 blob: None,
2522 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002523 KeyType::Client,
Janis Danisevskisaec14592020-11-12 09:41:49 -08002524 KeyEntryLoadBits::BOTH,
2525 33,
2526 |_k, _av| Ok(()),
2527 )
2528 .is_ok());
2529 // We should only see a 2 here because we can only return
2530 // from load_key_entry when the `_key_guard` expires,
2531 // which happens at the end of the scope.
2532 assert_eq!(2, state2.load(Ordering::Relaxed));
2533 });
2534
2535 thread::sleep(std::time::Duration::from_millis(1000));
2536
2537 assert_eq!(Ok(1), state.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed));
2538
2539 // Return the handle from this scope so we can join with the
2540 // secondary thread after the key id lock has expired.
2541 handle
2542 // This is where the `_key_guard` goes out of scope,
2543 // which is the reason for concurrent load_key_entry on the same key
2544 // to unblock.
2545 };
2546 // Join with the secondary thread and unwrap, to propagate failing asserts to the
2547 // main test thread. We will not see failing asserts in secondary threads otherwise.
2548 handle.join().unwrap();
2549 Ok(())
2550 }
2551
Janis Danisevskise92a5e62020-12-02 12:57:41 -08002552 #[test]
2553 fn list() -> Result<()> {
2554 let temp_dir = TempDir::new("list_test")?;
2555 let mut db = KeystoreDB::new(temp_dir.path())?;
2556 static LIST_O_ENTRIES: &[(Domain, i64, &str)] = &[
2557 (Domain::APP, 1, "test1"),
2558 (Domain::APP, 1, "test2"),
2559 (Domain::APP, 1, "test3"),
2560 (Domain::APP, 1, "test4"),
2561 (Domain::APP, 1, "test5"),
2562 (Domain::APP, 1, "test6"),
2563 (Domain::APP, 1, "test7"),
2564 (Domain::APP, 2, "test1"),
2565 (Domain::APP, 2, "test2"),
2566 (Domain::APP, 2, "test3"),
2567 (Domain::APP, 2, "test4"),
2568 (Domain::APP, 2, "test5"),
2569 (Domain::APP, 2, "test6"),
2570 (Domain::APP, 2, "test8"),
2571 (Domain::SELINUX, 100, "test1"),
2572 (Domain::SELINUX, 100, "test2"),
2573 (Domain::SELINUX, 100, "test3"),
2574 (Domain::SELINUX, 100, "test4"),
2575 (Domain::SELINUX, 100, "test5"),
2576 (Domain::SELINUX, 100, "test6"),
2577 (Domain::SELINUX, 100, "test9"),
2578 ];
2579
2580 let list_o_keys: Vec<(i64, i64)> = LIST_O_ENTRIES
2581 .iter()
2582 .map(|(domain, ns, alias)| {
2583 let entry =
2584 make_test_key_entry(&mut db, *domain, *ns, *alias).unwrap_or_else(|e| {
2585 panic!("Failed to insert {:?} {} {}. Error {:?}", domain, ns, alias, e)
2586 });
2587 (entry.id(), *ns)
2588 })
2589 .collect();
2590
2591 for (domain, namespace) in
2592 &[(Domain::APP, 1i64), (Domain::APP, 2i64), (Domain::SELINUX, 100i64)]
2593 {
2594 let mut list_o_descriptors: Vec<KeyDescriptor> = LIST_O_ENTRIES
2595 .iter()
2596 .filter_map(|(domain, ns, alias)| match ns {
2597 ns if *ns == *namespace => Some(KeyDescriptor {
2598 domain: *domain,
2599 nspace: *ns,
2600 alias: Some(alias.to_string()),
2601 blob: None,
2602 }),
2603 _ => None,
2604 })
2605 .collect();
2606 list_o_descriptors.sort();
2607 let mut list_result = db.list(*domain, *namespace)?;
2608 list_result.sort();
2609 assert_eq!(list_o_descriptors, list_result);
2610
2611 let mut list_o_ids: Vec<i64> = list_o_descriptors
2612 .into_iter()
2613 .map(|d| {
2614 let (_, entry) = db
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002615 .load_key_entry(
2616 d,
2617 KeyType::Client,
2618 KeyEntryLoadBits::NONE,
2619 *namespace as u32,
2620 |_, _| Ok(()),
2621 )
Janis Danisevskise92a5e62020-12-02 12:57:41 -08002622 .unwrap();
2623 entry.id()
2624 })
2625 .collect();
2626 list_o_ids.sort_unstable();
2627 let mut loaded_entries: Vec<i64> = list_o_keys
2628 .iter()
2629 .filter_map(|(id, ns)| match ns {
2630 ns if *ns == *namespace => Some(*id),
2631 _ => None,
2632 })
2633 .collect();
2634 loaded_entries.sort_unstable();
2635 assert_eq!(list_o_ids, loaded_entries);
2636 }
2637 assert_eq!(Vec::<KeyDescriptor>::new(), db.list(Domain::SELINUX, 101)?);
2638
2639 Ok(())
2640 }
2641
Joel Galenson0891bc12020-07-20 10:37:03 -07002642 // Helpers
2643
2644 // Checks that the given result is an error containing the given string.
2645 fn check_result_is_error_containing_string<T>(result: Result<T>, target: &str) {
2646 let error_str = format!(
2647 "{:#?}",
2648 result.err().unwrap_or_else(|| panic!("Expected the error: {}", target))
2649 );
2650 assert!(
2651 error_str.contains(target),
2652 "The string \"{}\" should contain \"{}\"",
2653 error_str,
2654 target
2655 );
2656 }
2657
Joel Galenson2aab4432020-07-22 15:27:57 -07002658 #[derive(Debug, PartialEq)]
Joel Galenson0891bc12020-07-20 10:37:03 -07002659 #[allow(dead_code)]
2660 struct KeyEntryRow {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002661 id: i64,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002662 key_type: KeyType,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002663 domain: Option<Domain>,
Joel Galenson0891bc12020-07-20 10:37:03 -07002664 namespace: Option<i64>,
2665 alias: Option<String>,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002666 state: KeyLifeCycle,
Joel Galenson0891bc12020-07-20 10:37:03 -07002667 }
2668
2669 fn get_keyentry(db: &KeystoreDB) -> Result<Vec<KeyEntryRow>> {
2670 db.conn
Joel Galenson2aab4432020-07-22 15:27:57 -07002671 .prepare("SELECT * FROM persistent.keyentry;")?
Joel Galenson0891bc12020-07-20 10:37:03 -07002672 .query_map(NO_PARAMS, |row| {
Joel Galenson0891bc12020-07-20 10:37:03 -07002673 Ok(KeyEntryRow {
2674 id: row.get(0)?,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002675 key_type: row.get(1)?,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002676 domain: match row.get(2)? {
2677 Some(i) => Some(Domain(i)),
2678 None => None,
2679 },
Joel Galenson0891bc12020-07-20 10:37:03 -07002680 namespace: row.get(3)?,
2681 alias: row.get(4)?,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002682 state: row.get(5)?,
Joel Galenson0891bc12020-07-20 10:37:03 -07002683 })
2684 })?
2685 .map(|r| r.context("Could not read keyentry row."))
2686 .collect::<Result<Vec<_>>>()
2687 }
2688
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07002689 // Note: The parameters and SecurityLevel associations are nonsensical. This
2690 // collection is only used to check if the parameters are preserved as expected by the
2691 // database.
2692 fn make_test_params() -> Vec<KeyParameter> {
2693 vec![
2694 KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::TRUSTED_ENVIRONMENT),
2695 KeyParameter::new(
2696 KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
2697 SecurityLevel::TRUSTED_ENVIRONMENT,
2698 ),
2699 KeyParameter::new(
2700 KeyParameterValue::KeyPurpose(KeyPurpose::DECRYPT),
2701 SecurityLevel::TRUSTED_ENVIRONMENT,
2702 ),
2703 KeyParameter::new(
2704 KeyParameterValue::Algorithm(Algorithm::RSA),
2705 SecurityLevel::TRUSTED_ENVIRONMENT,
2706 ),
2707 KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::TRUSTED_ENVIRONMENT),
2708 KeyParameter::new(
2709 KeyParameterValue::BlockMode(BlockMode::ECB),
2710 SecurityLevel::TRUSTED_ENVIRONMENT,
2711 ),
2712 KeyParameter::new(
2713 KeyParameterValue::BlockMode(BlockMode::GCM),
2714 SecurityLevel::TRUSTED_ENVIRONMENT,
2715 ),
2716 KeyParameter::new(KeyParameterValue::Digest(Digest::NONE), SecurityLevel::STRONGBOX),
2717 KeyParameter::new(
2718 KeyParameterValue::Digest(Digest::MD5),
2719 SecurityLevel::TRUSTED_ENVIRONMENT,
2720 ),
2721 KeyParameter::new(
2722 KeyParameterValue::Digest(Digest::SHA_2_224),
2723 SecurityLevel::TRUSTED_ENVIRONMENT,
2724 ),
2725 KeyParameter::new(
2726 KeyParameterValue::Digest(Digest::SHA_2_256),
2727 SecurityLevel::STRONGBOX,
2728 ),
2729 KeyParameter::new(
2730 KeyParameterValue::PaddingMode(PaddingMode::NONE),
2731 SecurityLevel::TRUSTED_ENVIRONMENT,
2732 ),
2733 KeyParameter::new(
2734 KeyParameterValue::PaddingMode(PaddingMode::RSA_OAEP),
2735 SecurityLevel::TRUSTED_ENVIRONMENT,
2736 ),
2737 KeyParameter::new(
2738 KeyParameterValue::PaddingMode(PaddingMode::RSA_PSS),
2739 SecurityLevel::STRONGBOX,
2740 ),
2741 KeyParameter::new(
2742 KeyParameterValue::PaddingMode(PaddingMode::RSA_PKCS1_1_5_SIGN),
2743 SecurityLevel::TRUSTED_ENVIRONMENT,
2744 ),
2745 KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::TRUSTED_ENVIRONMENT),
2746 KeyParameter::new(KeyParameterValue::MinMacLength(256), SecurityLevel::STRONGBOX),
2747 KeyParameter::new(
2748 KeyParameterValue::EcCurve(EcCurve::P_224),
2749 SecurityLevel::TRUSTED_ENVIRONMENT,
2750 ),
2751 KeyParameter::new(KeyParameterValue::EcCurve(EcCurve::P_256), SecurityLevel::STRONGBOX),
2752 KeyParameter::new(
2753 KeyParameterValue::EcCurve(EcCurve::P_384),
2754 SecurityLevel::TRUSTED_ENVIRONMENT,
2755 ),
2756 KeyParameter::new(
2757 KeyParameterValue::EcCurve(EcCurve::P_521),
2758 SecurityLevel::TRUSTED_ENVIRONMENT,
2759 ),
2760 KeyParameter::new(
2761 KeyParameterValue::RSAPublicExponent(3),
2762 SecurityLevel::TRUSTED_ENVIRONMENT,
2763 ),
2764 KeyParameter::new(
2765 KeyParameterValue::IncludeUniqueID,
2766 SecurityLevel::TRUSTED_ENVIRONMENT,
2767 ),
2768 KeyParameter::new(KeyParameterValue::BootLoaderOnly, SecurityLevel::STRONGBOX),
2769 KeyParameter::new(KeyParameterValue::RollbackResistance, SecurityLevel::STRONGBOX),
2770 KeyParameter::new(
2771 KeyParameterValue::ActiveDateTime(1234567890),
2772 SecurityLevel::STRONGBOX,
2773 ),
2774 KeyParameter::new(
2775 KeyParameterValue::OriginationExpireDateTime(1234567890),
2776 SecurityLevel::TRUSTED_ENVIRONMENT,
2777 ),
2778 KeyParameter::new(
2779 KeyParameterValue::UsageExpireDateTime(1234567890),
2780 SecurityLevel::TRUSTED_ENVIRONMENT,
2781 ),
2782 KeyParameter::new(
2783 KeyParameterValue::MinSecondsBetweenOps(1234567890),
2784 SecurityLevel::TRUSTED_ENVIRONMENT,
2785 ),
2786 KeyParameter::new(
2787 KeyParameterValue::MaxUsesPerBoot(1234567890),
2788 SecurityLevel::TRUSTED_ENVIRONMENT,
2789 ),
2790 KeyParameter::new(KeyParameterValue::UserID(1), SecurityLevel::STRONGBOX),
2791 KeyParameter::new(KeyParameterValue::UserSecureID(42), SecurityLevel::STRONGBOX),
2792 KeyParameter::new(
2793 KeyParameterValue::NoAuthRequired,
2794 SecurityLevel::TRUSTED_ENVIRONMENT,
2795 ),
2796 KeyParameter::new(
2797 KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType::PASSWORD),
2798 SecurityLevel::TRUSTED_ENVIRONMENT,
2799 ),
2800 KeyParameter::new(KeyParameterValue::AuthTimeout(1234567890), SecurityLevel::SOFTWARE),
2801 KeyParameter::new(KeyParameterValue::AllowWhileOnBody, SecurityLevel::SOFTWARE),
2802 KeyParameter::new(
2803 KeyParameterValue::TrustedUserPresenceRequired,
2804 SecurityLevel::TRUSTED_ENVIRONMENT,
2805 ),
2806 KeyParameter::new(
2807 KeyParameterValue::TrustedConfirmationRequired,
2808 SecurityLevel::TRUSTED_ENVIRONMENT,
2809 ),
2810 KeyParameter::new(
2811 KeyParameterValue::UnlockedDeviceRequired,
2812 SecurityLevel::TRUSTED_ENVIRONMENT,
2813 ),
2814 KeyParameter::new(
2815 KeyParameterValue::ApplicationID(vec![1u8, 2u8, 3u8, 4u8]),
2816 SecurityLevel::SOFTWARE,
2817 ),
2818 KeyParameter::new(
2819 KeyParameterValue::ApplicationData(vec![4u8, 3u8, 2u8, 1u8]),
2820 SecurityLevel::SOFTWARE,
2821 ),
2822 KeyParameter::new(
2823 KeyParameterValue::CreationDateTime(12345677890),
2824 SecurityLevel::SOFTWARE,
2825 ),
2826 KeyParameter::new(
2827 KeyParameterValue::KeyOrigin(KeyOrigin::GENERATED),
2828 SecurityLevel::TRUSTED_ENVIRONMENT,
2829 ),
2830 KeyParameter::new(
2831 KeyParameterValue::RootOfTrust(vec![3u8, 2u8, 1u8, 4u8]),
2832 SecurityLevel::TRUSTED_ENVIRONMENT,
2833 ),
2834 KeyParameter::new(KeyParameterValue::OSVersion(1), SecurityLevel::TRUSTED_ENVIRONMENT),
2835 KeyParameter::new(KeyParameterValue::OSPatchLevel(2), SecurityLevel::SOFTWARE),
2836 KeyParameter::new(
2837 KeyParameterValue::UniqueID(vec![4u8, 3u8, 1u8, 2u8]),
2838 SecurityLevel::SOFTWARE,
2839 ),
2840 KeyParameter::new(
2841 KeyParameterValue::AttestationChallenge(vec![4u8, 3u8, 1u8, 2u8]),
2842 SecurityLevel::TRUSTED_ENVIRONMENT,
2843 ),
2844 KeyParameter::new(
2845 KeyParameterValue::AttestationApplicationID(vec![4u8, 3u8, 1u8, 2u8]),
2846 SecurityLevel::TRUSTED_ENVIRONMENT,
2847 ),
2848 KeyParameter::new(
2849 KeyParameterValue::AttestationIdBrand(vec![4u8, 3u8, 1u8, 2u8]),
2850 SecurityLevel::TRUSTED_ENVIRONMENT,
2851 ),
2852 KeyParameter::new(
2853 KeyParameterValue::AttestationIdDevice(vec![4u8, 3u8, 1u8, 2u8]),
2854 SecurityLevel::TRUSTED_ENVIRONMENT,
2855 ),
2856 KeyParameter::new(
2857 KeyParameterValue::AttestationIdProduct(vec![4u8, 3u8, 1u8, 2u8]),
2858 SecurityLevel::TRUSTED_ENVIRONMENT,
2859 ),
2860 KeyParameter::new(
2861 KeyParameterValue::AttestationIdSerial(vec![4u8, 3u8, 1u8, 2u8]),
2862 SecurityLevel::TRUSTED_ENVIRONMENT,
2863 ),
2864 KeyParameter::new(
2865 KeyParameterValue::AttestationIdIMEI(vec![4u8, 3u8, 1u8, 2u8]),
2866 SecurityLevel::TRUSTED_ENVIRONMENT,
2867 ),
2868 KeyParameter::new(
2869 KeyParameterValue::AttestationIdMEID(vec![4u8, 3u8, 1u8, 2u8]),
2870 SecurityLevel::TRUSTED_ENVIRONMENT,
2871 ),
2872 KeyParameter::new(
2873 KeyParameterValue::AttestationIdManufacturer(vec![4u8, 3u8, 1u8, 2u8]),
2874 SecurityLevel::TRUSTED_ENVIRONMENT,
2875 ),
2876 KeyParameter::new(
2877 KeyParameterValue::AttestationIdModel(vec![4u8, 3u8, 1u8, 2u8]),
2878 SecurityLevel::TRUSTED_ENVIRONMENT,
2879 ),
2880 KeyParameter::new(
2881 KeyParameterValue::VendorPatchLevel(3),
2882 SecurityLevel::TRUSTED_ENVIRONMENT,
2883 ),
2884 KeyParameter::new(
2885 KeyParameterValue::BootPatchLevel(4),
2886 SecurityLevel::TRUSTED_ENVIRONMENT,
2887 ),
2888 KeyParameter::new(
2889 KeyParameterValue::AssociatedData(vec![4u8, 3u8, 1u8, 2u8]),
2890 SecurityLevel::TRUSTED_ENVIRONMENT,
2891 ),
2892 KeyParameter::new(
2893 KeyParameterValue::Nonce(vec![4u8, 3u8, 1u8, 2u8]),
2894 SecurityLevel::TRUSTED_ENVIRONMENT,
2895 ),
2896 KeyParameter::new(
2897 KeyParameterValue::MacLength(256),
2898 SecurityLevel::TRUSTED_ENVIRONMENT,
2899 ),
2900 KeyParameter::new(
2901 KeyParameterValue::ResetSinceIdRotation,
2902 SecurityLevel::TRUSTED_ENVIRONMENT,
2903 ),
2904 KeyParameter::new(
2905 KeyParameterValue::ConfirmationToken(vec![5u8, 5u8, 5u8, 5u8]),
2906 SecurityLevel::TRUSTED_ENVIRONMENT,
2907 ),
2908 ]
2909 }
2910
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002911 fn make_test_key_entry(
2912 db: &mut KeystoreDB,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002913 domain: Domain,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002914 namespace: i64,
2915 alias: &str,
Janis Danisevskisaec14592020-11-12 09:41:49 -08002916 ) -> Result<KeyIdGuard> {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002917 let key_id = db.create_key_entry(domain, namespace)?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002918 db.insert_blob(&key_id, SubComponentType::KEY_BLOB, TEST_KEY_BLOB)?;
2919 db.insert_blob(&key_id, SubComponentType::CERT, TEST_CERT_BLOB)?;
2920 db.insert_blob(&key_id, SubComponentType::CERT_CHAIN, TEST_CERT_CHAIN_BLOB)?;
Janis Danisevskisaec14592020-11-12 09:41:49 -08002921 db.insert_keyparameter(&key_id, &make_test_params())?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002922 let mut metadata = KeyMetaData::new();
2923 metadata.add(KeyMetaEntry::EncryptedBy(EncryptedBy::Password));
2924 metadata.add(KeyMetaEntry::Salt(vec![1, 2, 3]));
2925 metadata.add(KeyMetaEntry::Iv(vec![2, 3, 1]));
2926 metadata.add(KeyMetaEntry::AeadTag(vec![3, 1, 2]));
2927 db.insert_key_metadata(&key_id, &metadata)?;
Janis Danisevskisaec14592020-11-12 09:41:49 -08002928 db.rebind_alias(&key_id, alias, domain, namespace)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002929 Ok(key_id)
2930 }
2931
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002932 fn make_test_key_entry_test_vector(key_id: i64) -> KeyEntry {
2933 let mut metadata = KeyMetaData::new();
2934 metadata.add(KeyMetaEntry::EncryptedBy(EncryptedBy::Password));
2935 metadata.add(KeyMetaEntry::Salt(vec![1, 2, 3]));
2936 metadata.add(KeyMetaEntry::Iv(vec![2, 3, 1]));
2937 metadata.add(KeyMetaEntry::AeadTag(vec![3, 1, 2]));
2938
2939 KeyEntry {
2940 id: key_id,
2941 km_blob: Some(TEST_KEY_BLOB.to_vec()),
2942 cert: Some(TEST_CERT_BLOB.to_vec()),
2943 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
2944 sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
2945 parameters: make_test_params(),
2946 metadata,
2947 }
2948 }
2949
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002950 fn debug_dump_keyentry_table(db: &mut KeystoreDB) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002951 let mut stmt = db.conn.prepare(
2952 "SELECT id, key_type, domain, namespace, alias, state FROM persistent.keyentry;",
2953 )?;
2954 let rows = stmt.query_map::<(i64, KeyType, i32, i64, String, KeyLifeCycle), _, _>(
2955 NO_PARAMS,
2956 |row| {
2957 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?, row.get(4)?, row.get(5)?))
2958 },
2959 )?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002960
2961 println!("Key entry table rows:");
2962 for r in rows {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002963 let (id, key_type, domain, namespace, alias, state) = r.unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002964 println!(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002965 " id: {} KeyType: {:?} Domain: {} Namespace: {} Alias: {} State: {:?}",
2966 id, key_type, domain, namespace, alias, state
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002967 );
2968 }
2969 Ok(())
2970 }
2971
2972 fn debug_dump_grant_table(db: &mut KeystoreDB) -> Result<()> {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002973 let mut stmt = db
2974 .conn
2975 .prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002976 let rows = stmt.query_map::<(i64, i64, i64, i64), _, _>(NO_PARAMS, |row| {
2977 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?))
2978 })?;
2979
2980 println!("Grant table rows:");
2981 for r in rows {
2982 let (id, gt, ki, av) = r.unwrap();
2983 println!(" id: {} grantee: {} key_id: {} access_vector: {}", id, gt, ki, av);
2984 }
2985 Ok(())
2986 }
2987
Joel Galenson0891bc12020-07-20 10:37:03 -07002988 // Use a custom random number generator that repeats each number once.
2989 // This allows us to test repeated elements.
2990
2991 thread_local! {
2992 static RANDOM_COUNTER: RefCell<i64> = RefCell::new(0);
2993 }
2994
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002995 fn reset_random() {
2996 RANDOM_COUNTER.with(|counter| {
2997 *counter.borrow_mut() = 0;
2998 })
2999 }
3000
Joel Galenson0891bc12020-07-20 10:37:03 -07003001 pub fn random() -> i64 {
3002 RANDOM_COUNTER.with(|counter| {
3003 let result = *counter.borrow() / 2;
3004 *counter.borrow_mut() += 1;
3005 result
3006 })
3007 }
Hasini Gunasinghef70cf8e2020-11-11 01:02:41 +00003008
3009 #[test]
3010 fn test_last_off_body() -> Result<()> {
3011 let mut db = new_test_db()?;
3012 KeystoreDB::insert_last_off_body(&db.conn, MonotonicRawTime::now())?;
3013 let tx = db.conn.transaction_with_behavior(TransactionBehavior::Immediate)?;
3014 let last_off_body_1 = KeystoreDB::get_last_off_body(&tx)?;
3015 tx.commit()?;
3016 let one_second = Duration::from_secs(1);
3017 thread::sleep(one_second);
3018 db.update_last_off_body(MonotonicRawTime::now())?;
3019 let tx2 = db.conn.transaction_with_behavior(TransactionBehavior::Immediate)?;
3020 let last_off_body_2 = KeystoreDB::get_last_off_body(&tx2)?;
3021 tx2.commit()?;
3022 assert!(last_off_body_1.seconds() < last_off_body_2.seconds());
3023 Ok(())
3024 }
Joel Galenson26f4d012020-07-17 14:57:21 -07003025}