blob: 0c49340558406a0217c391edde2f0c09e6eddd67 [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
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +000015//TODO: remove this in the future CLs in the stack.
16#![allow(dead_code)]
17
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070018//! This is the Keystore 2.0 database module.
19//! The database module provides a connection to the backing SQLite store.
20//! We have two databases one for persistent key blob storage and one for
21//! items that have a per boot life cycle.
22//!
23//! ## Persistent database
24//! The persistent database has tables for key blobs. They are organized
25//! as follows:
26//! The `keyentry` table is the primary table for key entries. It is
27//! accompanied by two tables for blobs and parameters.
28//! Each key entry occupies exactly one row in the `keyentry` table and
29//! zero or more rows in the tables `blobentry` and `keyparameter`.
30//!
31//! ## Per boot database
32//! The per boot database stores items with a per boot lifecycle.
33//! Currently, there is only the `grant` table in this database.
34//! Grants are references to a key that can be used to access a key by
35//! clients that don't own that key. Grants can only be created by the
36//! owner of a key. And only certain components can create grants.
37//! This is governed by SEPolicy.
38//!
39//! ## Access control
40//! Some database functions that load keys or create grants perform
41//! access control. This is because in some cases access control
42//! can only be performed after some information about the designated
43//! key was loaded from the database. To decouple the permission checks
44//! from the database module these functions take permission check
45//! callbacks.
Joel Galenson26f4d012020-07-17 14:57:21 -070046
Janis Danisevskisb42fc182020-12-15 08:41:27 -080047#![allow(dead_code)]
48
Janis Danisevskis4522c2b2020-11-27 18:04:58 -080049use crate::db_utils::{self, SqlField};
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070050use crate::error::{Error as KsError, ResponseCode};
Janis Danisevskisb42fc182020-12-15 08:41:27 -080051use crate::impl_metadata; // This is in db_utils.rs
Janis Danisevskis4522c2b2020-11-27 18:04:58 -080052use crate::key_parameter::{KeyParameter, Tag};
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070053use crate::permission::KeyPermSet;
Hasini Gunasinghe557b1032020-11-10 01:35:30 +000054use crate::utils::get_current_time_in_seconds;
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::{
59 HardwareAuthToken::HardwareAuthToken, HardwareAuthenticatorType::HardwareAuthenticatorType,
60 SecurityLevel::SecurityLevel,
61};
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070062use android_system_keystore2::aidl::android::system::keystore2::{
Janis Danisevskis04b02832020-10-26 09:21:40 -070063 Domain::Domain, KeyDescriptor::KeyDescriptor,
Janis Danisevskis60400fe2020-08-26 15:24:42 -070064};
65
Janis Danisevskisaec14592020-11-12 09:41:49 -080066use lazy_static::lazy_static;
Joel Galenson0891bc12020-07-20 10:37:03 -070067#[cfg(not(test))]
68use rand::prelude::random;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070069use rusqlite::{
Janis Danisevskisb42fc182020-12-15 08:41:27 -080070 params,
71 types::FromSql,
72 types::FromSqlResult,
73 types::ToSqlOutput,
74 types::{FromSqlError, Value, ValueRef},
75 Connection, OptionalExtension, ToSql, Transaction, TransactionBehavior, NO_PARAMS,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070076};
Janis Danisevskisaec14592020-11-12 09:41:49 -080077use std::{
Janis Danisevskisb42fc182020-12-15 08:41:27 -080078 collections::{HashMap, HashSet},
Janis Danisevskisbf15d732020-12-08 10:35:26 -080079 path::Path,
80 sync::{Condvar, Mutex},
Janis Danisevskisb42fc182020-12-15 08:41:27 -080081 time::{Duration, SystemTime},
Janis Danisevskisaec14592020-11-12 09:41:49 -080082};
Joel Galenson0891bc12020-07-20 10:37:03 -070083#[cfg(test)]
84use tests::random;
Joel Galenson26f4d012020-07-17 14:57:21 -070085
Janis Danisevskisb42fc182020-12-15 08:41:27 -080086impl_metadata!(
87 /// A set of metadata for key entries.
88 #[derive(Debug, Default, Eq, PartialEq)]
89 pub struct KeyMetaData;
90 /// A metadata entry for key entries.
91 #[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
92 pub enum KeyMetaEntry {
93 /// If present, indicates that the sensitive part of key
94 /// is encrypted with another key or a key derived from a password.
95 EncryptedBy(EncryptedBy) with accessor encrypted_by,
96 /// If the blob is password encrypted this field is set to the
97 /// salt used for the key derivation.
98 Salt(Vec<u8>) with accessor salt,
99 /// If the blob is encrypted, this field is set to the initialization vector.
100 Iv(Vec<u8>) with accessor iv,
101 /// If the blob is encrypted, this field holds the AEAD TAG.
102 AeadTag(Vec<u8>) with accessor aead_tag,
103 /// Creation date of a the key entry.
104 CreationDate(DateTime) with accessor creation_date,
105 /// Expiration date for attestation keys.
106 AttestationExpirationDate(DateTime) with accessor attestation_expiration_date,
107 // --- ADD NEW META DATA FIELDS HERE ---
108 // For backwards compatibility add new entries only to
109 // end of this list and above this comment.
110 };
111);
112
113impl KeyMetaData {
114 fn load_from_db(key_id: i64, tx: &Transaction) -> Result<Self> {
115 let mut stmt = tx
116 .prepare(
117 "SELECT tag, data from persistent.keymetadata
118 WHERE keyentryid = ?;",
119 )
120 .context("In KeyMetaData::load_from_db: prepare statement failed.")?;
121
122 let mut metadata: HashMap<i64, KeyMetaEntry> = Default::default();
123
124 let mut rows =
125 stmt.query(params![key_id]).context("In KeyMetaData::load_from_db: query failed.")?;
126 db_utils::with_rows_extract_all(&mut rows, |row| {
127 let db_tag: i64 = row.get(0).context("Failed to read tag.")?;
128 metadata.insert(
129 db_tag,
130 KeyMetaEntry::new_from_sql(db_tag, &SqlField::new(1, &row))
131 .context("Failed to read KeyMetaEntry.")?,
132 );
133 Ok(())
134 })
135 .context("In KeyMetaData::load_from_db.")?;
136
137 Ok(Self { data: metadata })
138 }
139
140 fn store_in_db(&self, key_id: i64, tx: &Transaction) -> Result<()> {
141 let mut stmt = tx
142 .prepare(
143 "INSERT into persistent.keymetadata (keyentryid, tag, data)
144 VALUES (?, ?, ?);",
145 )
146 .context("In KeyMetaData::store_in_db: Failed to prepare statement.")?;
147
148 let iter = self.data.iter();
149 for (tag, entry) in iter {
150 stmt.insert(params![key_id, tag, entry,]).with_context(|| {
151 format!("In KeyMetaData::store_in_db: Failed to insert {:?}", entry)
152 })?;
153 }
154 Ok(())
155 }
156}
157
158/// Indicates the type of the keyentry.
159#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
160pub enum KeyType {
161 /// This is a client key type. These keys are created or imported through the Keystore 2.0
162 /// AIDL interface android.system.keystore2.
163 Client,
164 /// This is a super key type. These keys are created by keystore itself and used to encrypt
165 /// other key blobs to provide LSKF binding.
166 Super,
167 /// This is an attestation key. These keys are created by the remote provisioning mechanism.
168 Attestation,
169}
170
171impl ToSql for KeyType {
172 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
173 Ok(ToSqlOutput::Owned(Value::Integer(match self {
174 KeyType::Client => 0,
175 KeyType::Super => 1,
176 KeyType::Attestation => 2,
177 })))
178 }
179}
180
181impl FromSql for KeyType {
182 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
183 match i64::column_result(value)? {
184 0 => Ok(KeyType::Client),
185 1 => Ok(KeyType::Super),
186 2 => Ok(KeyType::Attestation),
187 v => Err(FromSqlError::OutOfRange(v)),
188 }
189 }
190}
191
192/// Indicates how the sensitive part of this key blob is encrypted.
193#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
194pub enum EncryptedBy {
195 /// The keyblob is encrypted by a user password.
196 /// In the database this variant is represented as NULL.
197 Password,
198 /// The keyblob is encrypted by another key with wrapped key id.
199 /// In the database this variant is represented as non NULL value
200 /// that is convertible to i64, typically NUMERIC.
201 KeyId(i64),
202}
203
204impl ToSql for EncryptedBy {
205 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
206 match self {
207 Self::Password => Ok(ToSqlOutput::Owned(Value::Null)),
208 Self::KeyId(id) => id.to_sql(),
209 }
210 }
211}
212
213impl FromSql for EncryptedBy {
214 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
215 match value {
216 ValueRef::Null => Ok(Self::Password),
217 _ => Ok(Self::KeyId(i64::column_result(value)?)),
218 }
219 }
220}
221
222/// A database representation of wall clock time. DateTime stores unix epoch time as
223/// i64 in milliseconds.
224#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)]
225pub struct DateTime(i64);
226
227/// Error type returned when creating DateTime or converting it from and to
228/// SystemTime.
229#[derive(thiserror::Error, Debug)]
230pub enum DateTimeError {
231 /// This is returned when SystemTime and Duration computations fail.
232 #[error(transparent)]
233 SystemTimeError(#[from] SystemTimeError),
234
235 /// This is returned when type conversions fail.
236 #[error(transparent)]
237 TypeConversion(#[from] std::num::TryFromIntError),
238
239 /// This is returned when checked time arithmetic failed.
240 #[error("Time arithmetic failed.")]
241 TimeArithmetic,
242}
243
244impl DateTime {
245 /// Constructs a new DateTime object denoting the current time. This may fail during
246 /// conversion to unix epoch time and during conversion to the internal i64 representation.
247 pub fn now() -> Result<Self, DateTimeError> {
248 Ok(Self(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_millis().try_into()?))
249 }
250
251 /// Constructs a new DateTime object from milliseconds.
252 pub fn from_millis_epoch(millis: i64) -> Self {
253 Self(millis)
254 }
255
256 /// Returns unix epoch time in milliseconds.
257 pub fn to_millis_epoch(&self) -> i64 {
258 self.0
259 }
260
261 /// Returns unix epoch time in seconds.
262 pub fn to_secs_epoch(&self) -> i64 {
263 self.0 / 1000
264 }
265}
266
267impl ToSql for DateTime {
268 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
269 Ok(ToSqlOutput::Owned(Value::Integer(self.0)))
270 }
271}
272
273impl FromSql for DateTime {
274 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
275 Ok(Self(i64::column_result(value)?))
276 }
277}
278
279impl TryInto<SystemTime> for DateTime {
280 type Error = DateTimeError;
281
282 fn try_into(self) -> Result<SystemTime, Self::Error> {
283 // We want to construct a SystemTime representation equivalent to self, denoting
284 // a point in time THEN, but we cannot set the time directly. We can only construct
285 // a SystemTime denoting NOW, and we can get the duration between EPOCH and NOW,
286 // and between EPOCH and THEN. With this common reference we can construct the
287 // duration between NOW and THEN which we can add to our SystemTime representation
288 // of NOW to get a SystemTime representation of THEN.
289 // Durations can only be positive, thus the if statement below.
290 let now = SystemTime::now();
291 let now_epoch = now.duration_since(SystemTime::UNIX_EPOCH)?;
292 let then_epoch = Duration::from_millis(self.0.try_into()?);
293 Ok(if now_epoch > then_epoch {
294 // then = now - (now_epoch - then_epoch)
295 now_epoch
296 .checked_sub(then_epoch)
297 .and_then(|d| now.checked_sub(d))
298 .ok_or(DateTimeError::TimeArithmetic)?
299 } else {
300 // then = now + (then_epoch - now_epoch)
301 then_epoch
302 .checked_sub(now_epoch)
303 .and_then(|d| now.checked_add(d))
304 .ok_or(DateTimeError::TimeArithmetic)?
305 })
306 }
307}
308
309impl TryFrom<SystemTime> for DateTime {
310 type Error = DateTimeError;
311
312 fn try_from(t: SystemTime) -> Result<Self, Self::Error> {
313 Ok(Self(t.duration_since(SystemTime::UNIX_EPOCH)?.as_millis().try_into()?))
314 }
315}
316
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700317/// Keys have a KeyMint blob component and optional public certificate and
318/// certificate chain components.
319/// KeyEntryLoadBits is a bitmap that indicates to `KeystoreDB::load_key_entry`
320/// which components shall be loaded from the database if present.
321#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
322pub struct KeyEntryLoadBits(u32);
323
324impl KeyEntryLoadBits {
325 /// Indicate to `KeystoreDB::load_key_entry` that no component shall be loaded.
326 pub const NONE: KeyEntryLoadBits = Self(0);
327 /// Indicate to `KeystoreDB::load_key_entry` that the KeyMint component shall be loaded.
328 pub const KM: KeyEntryLoadBits = Self(1);
329 /// Indicate to `KeystoreDB::load_key_entry` that the Public components shall be loaded.
330 pub const PUBLIC: KeyEntryLoadBits = Self(2);
331 /// Indicate to `KeystoreDB::load_key_entry` that both components shall be loaded.
332 pub const BOTH: KeyEntryLoadBits = Self(3);
333
334 /// Returns true if this object indicates that the public components shall be loaded.
335 pub const fn load_public(&self) -> bool {
336 self.0 & Self::PUBLIC.0 != 0
337 }
338
339 /// Returns true if the object indicates that the KeyMint component shall be loaded.
340 pub const fn load_km(&self) -> bool {
341 self.0 & Self::KM.0 != 0
342 }
343}
344
Janis Danisevskisaec14592020-11-12 09:41:49 -0800345lazy_static! {
346 static ref KEY_ID_LOCK: KeyIdLockDb = KeyIdLockDb::new();
347}
348
349struct KeyIdLockDb {
350 locked_keys: Mutex<HashSet<i64>>,
351 cond_var: Condvar,
352}
353
354/// A locked key. While a guard exists for a given key id, the same key cannot be loaded
355/// from the database a second time. Most functions manipulating the key blob database
356/// require a KeyIdGuard.
357#[derive(Debug)]
358pub struct KeyIdGuard(i64);
359
360impl KeyIdLockDb {
361 fn new() -> Self {
362 Self { locked_keys: Mutex::new(HashSet::new()), cond_var: Condvar::new() }
363 }
364
365 /// This function blocks until an exclusive lock for the given key entry id can
366 /// be acquired. It returns a guard object, that represents the lifecycle of the
367 /// acquired lock.
368 pub fn get(&self, key_id: i64) -> KeyIdGuard {
369 let mut locked_keys = self.locked_keys.lock().unwrap();
370 while locked_keys.contains(&key_id) {
371 locked_keys = self.cond_var.wait(locked_keys).unwrap();
372 }
373 locked_keys.insert(key_id);
374 KeyIdGuard(key_id)
375 }
376
377 /// This function attempts to acquire an exclusive lock on a given key id. If the
378 /// given key id is already taken the function returns None immediately. If a lock
379 /// can be acquired this function returns a guard object, that represents the
380 /// lifecycle of the acquired lock.
381 pub fn try_get(&self, key_id: i64) -> Option<KeyIdGuard> {
382 let mut locked_keys = self.locked_keys.lock().unwrap();
383 if locked_keys.insert(key_id) {
384 Some(KeyIdGuard(key_id))
385 } else {
386 None
387 }
388 }
389}
390
391impl KeyIdGuard {
392 /// Get the numeric key id of the locked key.
393 pub fn id(&self) -> i64 {
394 self.0
395 }
396}
397
398impl Drop for KeyIdGuard {
399 fn drop(&mut self) {
400 let mut locked_keys = KEY_ID_LOCK.locked_keys.lock().unwrap();
401 locked_keys.remove(&self.0);
Janis Danisevskis7fd53582020-11-23 13:40:34 -0800402 drop(locked_keys);
Janis Danisevskisaec14592020-11-12 09:41:49 -0800403 KEY_ID_LOCK.cond_var.notify_all();
404 }
405}
406
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700407/// This type represents a Keystore 2.0 key entry.
408/// An entry has a unique `id` by which it can be found in the database.
409/// It has a security level field, key parameters, and three optional fields
410/// for the KeyMint blob, public certificate and a public certificate chain.
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800411#[derive(Debug, Default, Eq, PartialEq)]
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700412pub struct KeyEntry {
413 id: i64,
414 km_blob: Option<Vec<u8>>,
415 cert: Option<Vec<u8>>,
416 cert_chain: Option<Vec<u8>>,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700417 sec_level: SecurityLevel,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700418 parameters: Vec<KeyParameter>,
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800419 metadata: KeyMetaData,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700420}
421
422impl KeyEntry {
423 /// Returns the unique id of the Key entry.
424 pub fn id(&self) -> i64 {
425 self.id
426 }
427 /// Exposes the optional KeyMint blob.
428 pub fn km_blob(&self) -> &Option<Vec<u8>> {
429 &self.km_blob
430 }
431 /// Extracts the Optional KeyMint blob.
432 pub fn take_km_blob(&mut self) -> Option<Vec<u8>> {
433 self.km_blob.take()
434 }
435 /// Exposes the optional public certificate.
436 pub fn cert(&self) -> &Option<Vec<u8>> {
437 &self.cert
438 }
439 /// Extracts the optional public certificate.
440 pub fn take_cert(&mut self) -> Option<Vec<u8>> {
441 self.cert.take()
442 }
443 /// Exposes the optional public certificate chain.
444 pub fn cert_chain(&self) -> &Option<Vec<u8>> {
445 &self.cert_chain
446 }
447 /// Extracts the optional public certificate_chain.
448 pub fn take_cert_chain(&mut self) -> Option<Vec<u8>> {
449 self.cert_chain.take()
450 }
451 /// Returns the security level of the key entry.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700452 pub fn sec_level(&self) -> SecurityLevel {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700453 self.sec_level
454 }
Janis Danisevskis04b02832020-10-26 09:21:40 -0700455 /// Exposes the key parameters of this key entry.
456 pub fn key_parameters(&self) -> &Vec<KeyParameter> {
457 &self.parameters
458 }
459 /// Consumes this key entry and extracts the keyparameters from it.
460 pub fn into_key_parameters(self) -> Vec<KeyParameter> {
461 self.parameters
462 }
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800463 /// Exposes the key metadata of this key entry.
464 pub fn metadata(&self) -> &KeyMetaData {
465 &self.metadata
466 }
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700467}
468
469/// Indicates the sub component of a key entry for persistent storage.
470#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
471pub struct SubComponentType(u32);
472impl SubComponentType {
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800473 /// Persistent identifier for a key blob.
474 pub const KEY_BLOB: SubComponentType = Self(0);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700475 /// Persistent identifier for a certificate blob.
476 pub const CERT: SubComponentType = Self(1);
477 /// Persistent identifier for a certificate chain blob.
478 pub const CERT_CHAIN: SubComponentType = Self(2);
479}
480
481impl ToSql for SubComponentType {
482 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
483 self.0.to_sql()
484 }
485}
486
487impl FromSql for SubComponentType {
488 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
489 Ok(Self(u32::column_result(value)?))
490 }
491}
492
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700493/// KeystoreDB wraps a connection to an SQLite database and tracks its
494/// ownership. It also implements all of Keystore 2.0's database functionality.
Joel Galenson26f4d012020-07-17 14:57:21 -0700495pub struct KeystoreDB {
Joel Galenson26f4d012020-07-17 14:57:21 -0700496 conn: Connection,
497}
498
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000499/// Database representation of the monotonic time retrieved from the system call clock_gettime with
500/// CLOCK_MONOTONIC_RAW. Stores monotonic time as i64 in seconds.
501#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)]
502pub struct MonotonicRawTime(i64);
503
504impl MonotonicRawTime {
505 /// Constructs a new MonotonicRawTime
506 pub fn now() -> Self {
507 Self(get_current_time_in_seconds())
508 }
509
510 /// Returns the integer value of MonotonicRawTime as i64
511 pub fn seconds(&self) -> i64 {
512 self.0
513 }
514}
515
516impl ToSql for MonotonicRawTime {
517 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
518 Ok(ToSqlOutput::Owned(Value::Integer(self.0)))
519 }
520}
521
522impl FromSql for MonotonicRawTime {
523 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
524 Ok(Self(i64::column_result(value)?))
525 }
526}
527
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000528/// This struct encapsulates the information to be stored in the database about the auth tokens
529/// received by keystore.
530pub struct AuthTokenEntry {
531 auth_token: HardwareAuthToken,
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000532 time_received: MonotonicRawTime,
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000533}
534
535impl AuthTokenEntry {
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000536 fn new(auth_token: HardwareAuthToken, time_received: MonotonicRawTime) -> Self {
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000537 AuthTokenEntry { auth_token, time_received }
538 }
539
540 /// Checks if this auth token satisfies the given authentication information.
541 pub fn satisfies_auth(
542 auth_token: &HardwareAuthToken,
543 user_secure_ids: &[i64],
544 auth_type: HardwareAuthenticatorType,
545 ) -> bool {
546 user_secure_ids.iter().any(|&sid| {
547 (sid == auth_token.userId || sid == auth_token.authenticatorId)
548 && (((auth_type.0 as i32) & (auth_token.authenticatorType.0 as i32)) != 0)
549 })
550 }
551
552 fn is_newer_than(&self, other: &AuthTokenEntry) -> bool {
553 // NOTE: Although in legacy keystore both timestamp and time_received are involved in this
554 // check, we decided to only consider time_received in keystore2 code.
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000555 self.time_received.seconds() > other.time_received.seconds()
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000556 }
557
558 /// Returns the auth token wrapped by the AuthTokenEntry
559 pub fn get_auth_token(self) -> HardwareAuthToken {
560 self.auth_token
561 }
562}
563
Joel Galenson26f4d012020-07-17 14:57:21 -0700564impl KeystoreDB {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700565 /// This will create a new database connection connecting the two
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800566 /// files persistent.sqlite and perboot.sqlite in the given directory.
567 /// It also attempts to initialize all of the tables.
568 /// KeystoreDB cannot be used by multiple threads.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700569 /// Each thread should open their own connection using `thread_local!`.
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800570 pub fn new(db_root: &Path) -> Result<Self> {
571 // Build the path to the sqlite files.
572 let mut persistent_path = db_root.to_path_buf();
573 persistent_path.push("persistent.sqlite");
574 let mut perboot_path = db_root.to_path_buf();
575 perboot_path.push("perboot.sqlite");
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700576
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800577 // Now convert them to strings prefixed with "file:"
578 let mut persistent_path_str = "file:".to_owned();
579 persistent_path_str.push_str(&persistent_path.to_string_lossy());
580 let mut perboot_path_str = "file:".to_owned();
581 perboot_path_str.push_str(&perboot_path.to_string_lossy());
582
583 let conn = Self::make_connection(&persistent_path_str, &perboot_path_str)?;
584
585 Self::init_tables(&conn)?;
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700586 Ok(Self { conn })
Joel Galenson2aab4432020-07-22 15:27:57 -0700587 }
588
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700589 fn init_tables(conn: &Connection) -> Result<()> {
590 conn.execute(
591 "CREATE TABLE IF NOT EXISTS persistent.keyentry (
Joel Galenson0891bc12020-07-20 10:37:03 -0700592 id INTEGER UNIQUE,
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800593 key_type INTEGER,
Joel Galenson0891bc12020-07-20 10:37:03 -0700594 domain INTEGER,
595 namespace INTEGER,
Joel Galenson319bb652020-12-01 13:24:08 -0800596 alias BLOB);",
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700597 NO_PARAMS,
598 )
599 .context("Failed to initialize \"keyentry\" table.")?;
600
601 conn.execute(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700602 "CREATE VIEW IF NOT EXISTS persistent.orphaned AS
603 SELECT id FROM persistent.keyentry WHERE domain IS NULL;",
604 NO_PARAMS,
605 )
606 .context("Failed to initialize \"orphaned\" view")?;
607
608 conn.execute(
609 "CREATE TABLE IF NOT EXISTS persistent.blobentry (
610 id INTEGER PRIMARY KEY,
611 subcomponent_type INTEGER,
612 keyentryid INTEGER,
613 blob BLOB,
614 sec_level INTEGER);",
615 NO_PARAMS,
616 )
617 .context("Failed to initialize \"blobentry\" table.")?;
618
619 conn.execute(
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700620 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000621 keyentryid INTEGER,
622 tag INTEGER,
623 data ANY,
624 security_level INTEGER);",
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700625 NO_PARAMS,
626 )
627 .context("Failed to initialize \"keyparameter\" table.")?;
628
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700629 conn.execute(
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800630 "CREATE TABLE IF NOT EXISTS persistent.keymetadata (
631 keyentryid INTEGER,
632 tag INTEGER,
633 data ANY);",
634 NO_PARAMS,
635 )
636 .context("Failed to initialize \"keymetadata\" table.")?;
637
638 conn.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800639 "CREATE TABLE IF NOT EXISTS persistent.grant (
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700640 id INTEGER UNIQUE,
641 grantee INTEGER,
642 keyentryid INTEGER,
643 access_vector INTEGER);",
644 NO_PARAMS,
645 )
646 .context("Failed to initialize \"grant\" table.")?;
647
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000648 //TODO: only drop the following two perboot tables if this is the first start up
649 //during the boot (b/175716626).
650 // conn.execute("DROP TABLE IF EXISTS perboot.authtoken;", NO_PARAMS)
651 // .context("Failed to drop perboot.authtoken table")?;
652 conn.execute(
653 "CREATE TABLE IF NOT EXISTS perboot.authtoken (
654 id INTEGER PRIMARY KEY,
655 challenge INTEGER,
656 user_id INTEGER,
657 auth_id INTEGER,
658 authenticator_type INTEGER,
659 timestamp INTEGER,
660 mac BLOB,
661 time_received INTEGER,
662 UNIQUE(user_id, auth_id, authenticator_type));",
663 NO_PARAMS,
664 )
665 .context("Failed to initialize \"authtoken\" table.")?;
666
667 // conn.execute("DROP TABLE IF EXISTS perboot.metadata;", NO_PARAMS)
668 // .context("Failed to drop perboot.metadata table")?;
669 // metadata table stores certain miscellaneous information required for keystore functioning
670 // during a boot cycle, as key-value pairs.
671 conn.execute(
672 "CREATE TABLE IF NOT EXISTS perboot.metadata (
673 key TEXT,
674 value BLOB,
675 UNIQUE(key));",
676 NO_PARAMS,
677 )
678 .context("Failed to initialize \"metadata\" table.")?;
679
Joel Galenson0891bc12020-07-20 10:37:03 -0700680 Ok(())
681 }
682
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700683 fn make_connection(persistent_file: &str, perboot_file: &str) -> Result<Connection> {
684 let conn =
685 Connection::open_in_memory().context("Failed to initialize SQLite connection.")?;
686
687 conn.execute("ATTACH DATABASE ? as persistent;", params![persistent_file])
688 .context("Failed to attach database persistent.")?;
689 conn.execute("ATTACH DATABASE ? as perboot;", params![perboot_file])
690 .context("Failed to attach database perboot.")?;
691
692 Ok(conn)
693 }
694
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800695 /// Atomically loads a key entry and associated metadata or creates it using the
696 /// callback create_new_key callback. The callback is called during a database
697 /// transaction. This means that implementers should be mindful about using
698 /// blocking operations such as IPC or grabbing mutexes.
699 pub fn get_or_create_key_with<F>(
700 &mut self,
701 domain: Domain,
702 namespace: i64,
703 alias: &str,
704 create_new_key: F,
705 ) -> Result<(KeyIdGuard, KeyEntry)>
706 where
707 F: FnOnce() -> Result<(Vec<u8>, KeyMetaData)>,
708 {
709 let tx = self
710 .conn
711 .transaction_with_behavior(TransactionBehavior::Immediate)
712 .context("In get_or_create_key_with: Failed to initialize transaction.")?;
713
714 let id = {
715 let mut stmt = tx
716 .prepare(
717 "SELECT id FROM persistent.keyentry
718 WHERE
719 key_type = ?
720 AND domain = ?
721 AND namespace = ?
722 AND alias = ?;",
723 )
724 .context("In get_or_create_key_with: Failed to select from keyentry table.")?;
725 let mut rows = stmt
726 .query(params![KeyType::Super, domain.0, namespace, alias])
727 .context("In get_or_create_key_with: Failed to query from keyentry table.")?;
728
729 db_utils::with_rows_extract_one(&mut rows, |row| {
730 Ok(match row {
731 Some(r) => r.get(0).context("Failed to unpack id.")?,
732 None => None,
733 })
734 })
735 .context("In get_or_create_key_with.")?
736 };
737
738 let (id, entry) = match id {
739 Some(id) => (
740 id,
741 Self::load_key_components(&tx, KeyEntryLoadBits::KM, id)
742 .context("In get_or_create_key_with.")?,
743 ),
744
745 None => {
746 let id = Self::insert_with_retry(|id| {
747 tx.execute(
748 "INSERT into persistent.keyentry
749 (id, key_type, domain, namespace, alias)
750 VALUES(?, ?, ?, ?, ?);",
751 params![id, KeyType::Super, domain.0, namespace, alias],
752 )
753 })
754 .context("In get_or_create_key_with.")?;
755
756 let (blob, metadata) = create_new_key().context("In get_or_create_key_with.")?;
757 Self::insert_blob_internal(
758 &tx,
759 id,
760 SubComponentType::KEY_BLOB,
761 &blob,
762 SecurityLevel::SOFTWARE,
763 )
764 .context("In get_of_create_key_with.")?;
765 metadata.store_in_db(id, &tx).context("In get_or_create_key_with.")?;
766 (id, KeyEntry { id, km_blob: Some(blob), metadata, ..Default::default() })
767 }
768 };
769 tx.commit().context("In get_or_create_key_with: Failed to commit transaction.")?;
770 Ok((KEY_ID_LOCK.get(id), entry))
771 }
772
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700773 /// Creates a new key entry and allocates a new randomized id for the new key.
774 /// The key id gets associated with a domain and namespace but not with an alias.
775 /// To complete key generation `rebind_alias` should be called after all of the
776 /// key artifacts, i.e., blobs and parameters have been associated with the new
777 /// key id. Finalizing with `rebind_alias` makes the creation of a new key entry
778 /// atomic even if key generation is not.
Janis Danisevskisaec14592020-11-12 09:41:49 -0800779 pub fn create_key_entry(&self, domain: Domain, namespace: i64) -> Result<KeyIdGuard> {
Joel Galenson0891bc12020-07-20 10:37:03 -0700780 match domain {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700781 Domain::APP | Domain::SELINUX => {}
Joel Galenson0891bc12020-07-20 10:37:03 -0700782 _ => {
783 return Err(KsError::sys())
784 .context(format!("Domain {:?} must be either App or SELinux.", domain));
785 }
786 }
Janis Danisevskisaec14592020-11-12 09:41:49 -0800787 Ok(KEY_ID_LOCK.get(
788 Self::insert_with_retry(|id| {
789 self.conn.execute(
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800790 "INSERT into persistent.keyentry
791 (id, key_type, domain, namespace, alias)
792 VALUES(?, ?, ?, ?, NULL);",
793 params![id, KeyType::Client, domain.0 as u32, namespace],
Janis Danisevskisaec14592020-11-12 09:41:49 -0800794 )
795 })
796 .context("In create_key_entry")?,
797 ))
Joel Galenson26f4d012020-07-17 14:57:21 -0700798 }
Joel Galenson33c04ad2020-08-03 11:04:38 -0700799
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700800 /// Inserts a new blob and associates it with the given key id. Each blob
801 /// has a sub component type and a security level.
802 /// Each key can have one of each sub component type associated. If more
803 /// are added only the most recent can be retrieved, and superseded blobs
804 /// will get garbage collected. The security level field of components
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800805 /// other than `SubComponentType::KEY_BLOB` are ignored.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700806 pub fn insert_blob(
807 &mut self,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800808 key_id: &KeyIdGuard,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700809 sc_type: SubComponentType,
810 blob: &[u8],
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700811 sec_level: SecurityLevel,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700812 ) -> Result<()> {
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800813 let tx = self
814 .conn
815 .transaction_with_behavior(TransactionBehavior::Immediate)
816 .context("In insert_blob: Failed to initialize transaction.")?;
817
818 Self::insert_blob_internal(&tx, key_id.0, sc_type, blob, sec_level)
819 .context("In insert_blob.")?;
820
821 tx.commit().context("In insert_blob: Failed to commit transaction.")
822 }
823
824 fn insert_blob_internal(
825 tx: &Transaction,
826 key_id: i64,
827 sc_type: SubComponentType,
828 blob: &[u8],
829 sec_level: SecurityLevel,
830 ) -> Result<()> {
831 tx.execute(
832 "INSERT into persistent.blobentry (subcomponent_type, keyentryid, blob, sec_level)
833 VALUES (?, ?, ?, ?);",
834 params![sc_type, key_id, blob, sec_level.0],
835 )
836 .context("In insert_blob_internal: Failed to insert blob.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700837 Ok(())
838 }
839
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700840 /// Inserts a collection of key parameters into the `persistent.keyparameter` table
841 /// and associates them with the given `key_id`.
842 pub fn insert_keyparameter<'a>(
843 &mut self,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800844 key_id: &KeyIdGuard,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700845 params: impl IntoIterator<Item = &'a KeyParameter>,
846 ) -> Result<()> {
Janis Danisevskise92a5e62020-12-02 12:57:41 -0800847 let tx = self
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700848 .conn
Janis Danisevskise92a5e62020-12-02 12:57:41 -0800849 .transaction_with_behavior(TransactionBehavior::Immediate)
850 .context("In insert_keyparameter: Failed to start transaction.")?;
851 {
852 let mut stmt = tx
853 .prepare(
854 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700855 VALUES (?, ?, ?, ?);",
Janis Danisevskise92a5e62020-12-02 12:57:41 -0800856 )
857 .context("In insert_keyparameter: Failed to prepare statement.")?;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700858
Janis Danisevskise92a5e62020-12-02 12:57:41 -0800859 let iter = params.into_iter();
860 for p in iter {
861 stmt.insert(params![
862 key_id.0,
863 p.get_tag().0,
864 p.key_parameter_value(),
865 p.security_level().0
866 ])
867 .with_context(|| format!("In insert_keyparameter: Failed to insert {:?}", p))?;
868 }
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700869 }
Janis Danisevskise92a5e62020-12-02 12:57:41 -0800870 tx.commit().context("In insert_keyparameter: Failed to commit transaction.")?;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700871 Ok(())
872 }
873
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800874 /// Insert a set of key entry specific metadata into the database.
875 pub fn insert_key_metadata(
876 &mut self,
877 key_id: &KeyIdGuard,
878 metadata: &KeyMetaData,
879 ) -> Result<()> {
880 let tx = self
881 .conn
882 .transaction_with_behavior(TransactionBehavior::Immediate)
883 .context("In insert_key_metadata: Failed to initialize transaction.")?;
884 metadata.store_in_db(key_id.0, &tx).context("In insert_key_metadata")?;
885 tx.commit().context("In insert_key_metadata: Failed to commit transaction")
886 }
887
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700888 /// Updates the alias column of the given key id `newid` with the given alias,
889 /// and atomically, removes the alias, domain, and namespace from another row
890 /// with the same alias-domain-namespace tuple if such row exits.
Joel Galenson33c04ad2020-08-03 11:04:38 -0700891 pub fn rebind_alias(
892 &mut self,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800893 newid: &KeyIdGuard,
Joel Galenson33c04ad2020-08-03 11:04:38 -0700894 alias: &str,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700895 domain: Domain,
Joel Galenson33c04ad2020-08-03 11:04:38 -0700896 namespace: i64,
897 ) -> Result<()> {
898 match domain {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700899 Domain::APP | Domain::SELINUX => {}
Joel Galenson33c04ad2020-08-03 11:04:38 -0700900 _ => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700901 return Err(KsError::sys()).context(format!(
902 "In rebind_alias: Domain {:?} must be either App or SELinux.",
903 domain
904 ));
Joel Galenson33c04ad2020-08-03 11:04:38 -0700905 }
906 }
907 let tx = self
908 .conn
909 .transaction_with_behavior(TransactionBehavior::Immediate)
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700910 .context("In rebind_alias: Failed to initialize transaction.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -0700911 tx.execute(
912 "UPDATE persistent.keyentry
913 SET alias = NULL, domain = NULL, namespace = NULL
914 WHERE alias = ? AND domain = ? AND namespace = ?;",
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700915 params![alias, domain.0 as u32, namespace],
Joel Galenson33c04ad2020-08-03 11:04:38 -0700916 )
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700917 .context("In rebind_alias: Failed to rebind existing entry.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -0700918 let result = tx
919 .execute(
920 "UPDATE persistent.keyentry
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700921 SET alias = ?
922 WHERE id = ? AND domain = ? AND namespace = ?;",
Janis Danisevskisaec14592020-11-12 09:41:49 -0800923 params![alias, newid.0, domain.0 as u32, namespace],
Joel Galenson33c04ad2020-08-03 11:04:38 -0700924 )
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700925 .context("In rebind_alias: Failed to set alias.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -0700926 if result != 1 {
927 // Note that this explicit rollback is not required, as
928 // the transaction should rollback if we do not commit it.
929 // We leave it here for readability.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700930 tx.rollback().context("In rebind_alias: Failed to rollback a failed transaction.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -0700931 return Err(KsError::sys()).context(format!(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700932 "In rebind_alias: Expected to update a single entry but instead updated {}.",
Joel Galenson33c04ad2020-08-03 11:04:38 -0700933 result
934 ));
935 }
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700936 tx.commit().context("In rebind_alias: Failed to commit transaction.")
937 }
938
939 // Helper function loading the key_id given the key descriptor
940 // tuple comprising domain, namespace, and alias.
941 // Requires a valid transaction.
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800942 fn load_key_entry_id(tx: &Transaction, key: &KeyDescriptor, key_type: KeyType) -> Result<i64> {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700943 let alias = key
944 .alias
945 .as_ref()
946 .map_or_else(|| Err(KsError::sys()), Ok)
947 .context("In load_key_entry_id: Alias must be specified.")?;
948 let mut stmt = tx
949 .prepare(
950 "SELECT id FROM persistent.keyentry
951 WHERE
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800952 key_type = ?
953 AND domain = ?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700954 AND namespace = ?
955 AND alias = ?;",
956 )
957 .context("In load_key_entry_id: Failed to select from keyentry table.")?;
958 let mut rows = stmt
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800959 .query(params![key_type, key.domain.0 as u32, key.nspace, alias])
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700960 .context("In load_key_entry_id: Failed to read from keyentry table.")?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800961 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700962 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700963 .get(0)
964 .context("Failed to unpack id.")
965 })
966 .context("In load_key_entry_id.")
967 }
968
969 /// This helper function completes the access tuple of a key, which is required
970 /// to perform access control. The strategy depends on the `domain` field in the
971 /// key descriptor.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700972 /// * Domain::SELINUX: The access tuple is complete and this function only loads
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700973 /// the key_id for further processing.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700974 /// * Domain::APP: Like Domain::SELINUX, but the tuple is completed by `caller_uid`
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700975 /// which serves as the namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700976 /// * Domain::GRANT: The grant table is queried for the `key_id` and the
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700977 /// `access_vector`.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700978 /// * Domain::KEY_ID: The keyentry table is queried for the owning `domain` and
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700979 /// `namespace`.
980 /// In each case the information returned is sufficient to perform the access
981 /// check and the key id can be used to load further key artifacts.
982 fn load_access_tuple(
983 tx: &Transaction,
984 key: KeyDescriptor,
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800985 key_type: KeyType,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700986 caller_uid: u32,
987 ) -> Result<(i64, KeyDescriptor, Option<KeyPermSet>)> {
988 match key.domain {
989 // Domain App or SELinux. In this case we load the key_id from
990 // the keyentry database for further loading of key components.
991 // We already have the full access tuple to perform access control.
992 // The only distinction is that we use the caller_uid instead
993 // of the caller supplied namespace if the domain field is
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700994 // Domain::APP.
995 Domain::APP | Domain::SELINUX => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700996 let mut access_key = key;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700997 if access_key.domain == Domain::APP {
998 access_key.nspace = caller_uid as i64;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700999 }
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001000 let key_id = Self::load_key_entry_id(&tx, &access_key, key_type)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001001 .with_context(|| format!("With key.domain = {:?}.", access_key.domain))?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001002
1003 Ok((key_id, access_key, None))
1004 }
1005
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001006 // Domain::GRANT. In this case we load the key_id and the access_vector
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001007 // from the grant table.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001008 Domain::GRANT => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001009 let mut stmt = tx
1010 .prepare(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001011 "SELECT keyentryid, access_vector FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001012 WHERE grantee = ? AND id = ?;",
1013 )
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001014 .context("Domain::GRANT prepare statement failed")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001015 let mut rows = stmt
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001016 .query(params![caller_uid as i64, key.nspace])
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001017 .context("Domain:Grant: query failed.")?;
1018 let (key_id, access_vector): (i64, i32) =
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001019 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001020 let r =
1021 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001022 Ok((
1023 r.get(0).context("Failed to unpack key_id.")?,
1024 r.get(1).context("Failed to unpack access_vector.")?,
1025 ))
1026 })
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001027 .context("Domain::GRANT.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001028 Ok((key_id, key, Some(access_vector.into())))
1029 }
1030
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001031 // Domain::KEY_ID. In this case we load the domain and namespace from the
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001032 // keyentry database because we need them for access control.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001033 Domain::KEY_ID => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001034 let mut stmt = tx
1035 .prepare(
1036 "SELECT domain, namespace FROM persistent.keyentry
1037 WHERE
1038 id = ?;",
1039 )
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001040 .context("Domain::KEY_ID: prepare statement failed")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001041 let mut rows =
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001042 stmt.query(params![key.nspace]).context("Domain::KEY_ID: query failed.")?;
1043 let (domain, namespace): (Domain, i64) =
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001044 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001045 let r =
1046 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001047 Ok((
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001048 Domain(r.get(0).context("Failed to unpack domain.")?),
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001049 r.get(1).context("Failed to unpack namespace.")?,
1050 ))
1051 })
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001052 .context("Domain::KEY_ID.")?;
1053 let key_id = key.nspace;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001054 let mut access_key = key;
1055 access_key.domain = domain;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001056 access_key.nspace = namespace;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001057
1058 Ok((key_id, access_key, None))
1059 }
1060 _ => Err(anyhow!(KsError::sys())),
1061 }
1062 }
1063
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001064 fn load_blob_components(
1065 key_id: i64,
1066 load_bits: KeyEntryLoadBits,
1067 tx: &Transaction,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001068 ) -> Result<(SecurityLevel, Option<Vec<u8>>, Option<Vec<u8>>, Option<Vec<u8>>)> {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001069 let mut stmt = tx
1070 .prepare(
1071 "SELECT MAX(id), sec_level, subcomponent_type, blob FROM persistent.blobentry
1072 WHERE keyentryid = ? GROUP BY subcomponent_type;",
1073 )
1074 .context("In load_blob_components: prepare statement failed.")?;
1075
1076 let mut rows =
1077 stmt.query(params![key_id]).context("In load_blob_components: query failed.")?;
1078
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001079 let mut sec_level: SecurityLevel = Default::default();
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001080 let mut km_blob: Option<Vec<u8>> = None;
1081 let mut cert_blob: Option<Vec<u8>> = None;
1082 let mut cert_chain_blob: Option<Vec<u8>> = None;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001083 db_utils::with_rows_extract_all(&mut rows, |row| {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001084 let sub_type: SubComponentType =
1085 row.get(2).context("Failed to extract subcomponent_type.")?;
1086 match (sub_type, load_bits.load_public()) {
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001087 (SubComponentType::KEY_BLOB, _) => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001088 sec_level =
1089 SecurityLevel(row.get(1).context("Failed to extract security level.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001090 if load_bits.load_km() {
1091 km_blob = Some(row.get(3).context("Failed to extract KM blob.")?);
1092 }
1093 }
1094 (SubComponentType::CERT, true) => {
1095 cert_blob =
1096 Some(row.get(3).context("Failed to extract public certificate blob.")?);
1097 }
1098 (SubComponentType::CERT_CHAIN, true) => {
1099 cert_chain_blob =
1100 Some(row.get(3).context("Failed to extract certificate chain blob.")?);
1101 }
1102 (SubComponentType::CERT, _) | (SubComponentType::CERT_CHAIN, _) => {}
1103 _ => Err(KsError::sys()).context("Unknown subcomponent type.")?,
1104 }
1105 Ok(())
1106 })
1107 .context("In load_blob_components.")?;
1108
1109 Ok((sec_level, km_blob, cert_blob, cert_chain_blob))
1110 }
1111
1112 fn load_key_parameters(key_id: i64, tx: &Transaction) -> Result<Vec<KeyParameter>> {
1113 let mut stmt = tx
1114 .prepare(
1115 "SELECT tag, data, security_level from persistent.keyparameter
1116 WHERE keyentryid = ?;",
1117 )
1118 .context("In load_key_parameters: prepare statement failed.")?;
1119
1120 let mut parameters: Vec<KeyParameter> = Vec::new();
1121
1122 let mut rows =
1123 stmt.query(params![key_id]).context("In load_key_parameters: query failed.")?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001124 db_utils::with_rows_extract_all(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001125 let tag = Tag(row.get(0).context("Failed to read tag.")?);
1126 let sec_level = SecurityLevel(row.get(2).context("Failed to read sec_level.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001127 parameters.push(
1128 KeyParameter::new_from_sql(tag, &SqlField::new(1, &row), sec_level)
1129 .context("Failed to read KeyParameter.")?,
1130 );
1131 Ok(())
1132 })
1133 .context("In load_key_parameters.")?;
1134
1135 Ok(parameters)
1136 }
1137
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001138 /// Load a key entry by the given key descriptor.
1139 /// It uses the `check_permission` callback to verify if the access is allowed
1140 /// given the key access tuple read from the database using `load_access_tuple`.
1141 /// With `load_bits` the caller may specify which blobs shall be loaded from
1142 /// the blob database.
1143 pub fn load_key_entry(
1144 &mut self,
1145 key: KeyDescriptor,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001146 key_type: KeyType,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001147 load_bits: KeyEntryLoadBits,
1148 caller_uid: u32,
1149 check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001150 ) -> Result<(KeyIdGuard, KeyEntry)> {
1151 // KEY ID LOCK 1/2
1152 // If we got a key descriptor with a key id we can get the lock right away.
1153 // Otherwise we have to defer it until we know the key id.
1154 let key_id_guard = match key.domain {
1155 Domain::KEY_ID => Some(KEY_ID_LOCK.get(key.nspace)),
1156 _ => None,
1157 };
1158
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001159 let tx = self
1160 .conn
Janis Danisevskisaec14592020-11-12 09:41:49 -08001161 .unchecked_transaction()
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001162 .context("In load_key_entry: Failed to initialize transaction.")?;
1163
1164 // Load the key_id and complete the access control tuple.
1165 let (key_id, access_key_descriptor, access_vector) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001166 Self::load_access_tuple(&tx, key, key_type, caller_uid)
1167 .context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001168
1169 // Perform access control. It is vital that we return here if the permission is denied.
1170 // So do not touch that '?' at the end.
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001171 check_permission(&access_key_descriptor, access_vector).context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001172
Janis Danisevskisaec14592020-11-12 09:41:49 -08001173 // KEY ID LOCK 2/2
1174 // If we did not get a key id lock by now, it was because we got a key descriptor
1175 // without a key id. At this point we got the key id, so we can try and get a lock.
1176 // However, we cannot block here, because we are in the middle of the transaction.
1177 // So first we try to get the lock non blocking. If that fails, we roll back the
1178 // transaction and block until we get the lock. After we successfully got the lock,
1179 // we start a new transaction and load the access tuple again.
1180 //
1181 // We don't need to perform access control again, because we already established
1182 // that the caller had access to the given key. But we need to make sure that the
1183 // key id still exists. So we have to load the key entry by key id this time.
1184 let (key_id_guard, tx) = match key_id_guard {
1185 None => match KEY_ID_LOCK.try_get(key_id) {
1186 None => {
1187 // Roll back the transaction.
1188 tx.rollback().context("In load_key_entry: Failed to roll back transaction.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001189
Janis Danisevskisaec14592020-11-12 09:41:49 -08001190 // Block until we have a key id lock.
1191 let key_id_guard = KEY_ID_LOCK.get(key_id);
1192
1193 // Create a new transaction.
1194 let tx = self.conn.unchecked_transaction().context(
1195 "In load_key_entry: Failed to initialize transaction. (deferred key lock)",
1196 )?;
1197
1198 Self::load_access_tuple(
1199 &tx,
1200 // This time we have to load the key by the retrieved key id, because the
1201 // alias may have been rebound after we rolled back the transaction.
1202 KeyDescriptor {
1203 domain: Domain::KEY_ID,
1204 nspace: key_id,
1205 ..Default::default()
1206 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001207 key_type,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001208 caller_uid,
1209 )
1210 .context("In load_key_entry. (deferred key lock)")?;
1211 (key_id_guard, tx)
1212 }
1213 Some(l) => (l, tx),
1214 },
1215 Some(key_id_guard) => (key_id_guard, tx),
1216 };
1217
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001218 let key_entry = Self::load_key_components(&tx, load_bits, key_id_guard.id())
1219 .context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001220
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001221 tx.commit().context("In load_key_entry: Failed to commit transaction.")?;
1222
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001223 Ok((key_id_guard, key_entry))
1224 }
1225
1226 fn load_key_components(
1227 tx: &Transaction,
1228 load_bits: KeyEntryLoadBits,
1229 key_id: i64,
1230 ) -> Result<KeyEntry> {
1231 let metadata = KeyMetaData::load_from_db(key_id, &tx).context("In load_key_components.")?;
1232
1233 let (sec_level, km_blob, cert_blob, cert_chain_blob) =
1234 Self::load_blob_components(key_id, load_bits, &tx)
1235 .context("In load_key_components.")?;
1236
1237 let parameters =
1238 Self::load_key_parameters(key_id, &tx).context("In load_key_components.")?;
1239
1240 Ok(KeyEntry {
1241 id: key_id,
1242 km_blob,
1243 cert: cert_blob,
1244 cert_chain: cert_chain_blob,
1245 sec_level,
1246 parameters,
1247 metadata,
1248 })
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001249 }
1250
Janis Danisevskise92a5e62020-12-02 12:57:41 -08001251 /// Returns a list of KeyDescriptors in the selected domain/namespace.
1252 /// The key descriptors will have the domain, nspace, and alias field set.
1253 /// Domain must be APP or SELINUX, the caller must make sure of that.
1254 pub fn list(&mut self, domain: Domain, namespace: i64) -> Result<Vec<KeyDescriptor>> {
1255 let mut stmt = self
1256 .conn
1257 .prepare(
1258 "SELECT alias FROM persistent.keyentry
1259 WHERE domain = ? AND namespace = ? AND alias IS NOT NULL;",
1260 )
1261 .context("In list: Failed to prepare.")?;
1262
1263 let mut rows =
1264 stmt.query(params![domain.0 as u32, namespace]).context("In list: Failed to query.")?;
1265
1266 let mut descriptors: Vec<KeyDescriptor> = Vec::new();
1267 db_utils::with_rows_extract_all(&mut rows, |row| {
1268 descriptors.push(KeyDescriptor {
1269 domain,
1270 nspace: namespace,
1271 alias: Some(row.get(0).context("Trying to extract alias.")?),
1272 blob: None,
1273 });
1274 Ok(())
1275 })
1276 .context("In list.")?;
1277 Ok(descriptors)
1278 }
1279
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001280 /// Adds a grant to the grant table.
1281 /// Like `load_key_entry` this function loads the access tuple before
1282 /// it uses the callback for a permission check. Upon success,
1283 /// it inserts the `grantee_uid`, `key_id`, and `access_vector` into the
1284 /// grant table. The new row will have a randomized id, which is used as
1285 /// grant id in the namespace field of the resulting KeyDescriptor.
1286 pub fn grant(
1287 &mut self,
1288 key: KeyDescriptor,
1289 caller_uid: u32,
1290 grantee_uid: u32,
1291 access_vector: KeyPermSet,
1292 check_permission: impl FnOnce(&KeyDescriptor, &KeyPermSet) -> Result<()>,
1293 ) -> Result<KeyDescriptor> {
1294 let tx = self
1295 .conn
1296 .transaction_with_behavior(TransactionBehavior::Immediate)
1297 .context("In grant: Failed to initialize transaction.")?;
1298
1299 // Load the key_id and complete the access control tuple.
1300 // We ignore the access vector here because grants cannot be granted.
1301 // The access vector returned here expresses the permissions the
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001302 // grantee has if key.domain == Domain::GRANT. But this vector
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001303 // cannot include the grant permission by design, so there is no way the
1304 // subsequent permission check can pass.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001305 // We could check key.domain == Domain::GRANT and fail early.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001306 // But even if we load the access tuple by grant here, the permission
1307 // check denies the attempt to create a grant by grant descriptor.
1308 let (key_id, access_key_descriptor, _) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001309 Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid).context("In grant")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001310
1311 // Perform access control. It is vital that we return here if the permission
1312 // was denied. So do not touch that '?' at the end of the line.
1313 // This permission check checks if the caller has the grant permission
1314 // for the given key and in addition to all of the permissions
1315 // expressed in `access_vector`.
1316 check_permission(&access_key_descriptor, &access_vector)
1317 .context("In grant: check_permission failed.")?;
1318
1319 let grant_id = if let Some(grant_id) = tx
1320 .query_row(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001321 "SELECT id FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001322 WHERE keyentryid = ? AND grantee = ?;",
1323 params![key_id, grantee_uid],
1324 |row| row.get(0),
1325 )
1326 .optional()
1327 .context("In grant: Failed get optional existing grant id.")?
1328 {
1329 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001330 "UPDATE persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001331 SET access_vector = ?
1332 WHERE id = ?;",
1333 params![i32::from(access_vector), grant_id],
1334 )
1335 .context("In grant: Failed to update existing grant.")?;
1336 grant_id
1337 } else {
Joel Galenson845f74b2020-09-09 14:11:55 -07001338 Self::insert_with_retry(|id| {
1339 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001340 "INSERT INTO persistent.grant (id, grantee, keyentryid, access_vector)
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001341 VALUES (?, ?, ?, ?);",
Joel Galenson845f74b2020-09-09 14:11:55 -07001342 params![id, grantee_uid, key_id, i32::from(access_vector)],
1343 )
1344 })
1345 .context("In grant")?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001346 };
1347 tx.commit().context("In grant: failed to commit transaction.")?;
1348
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001349 Ok(KeyDescriptor { domain: Domain::GRANT, nspace: grant_id, alias: None, blob: None })
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001350 }
1351
1352 /// This function checks permissions like `grant` and `load_key_entry`
1353 /// before removing a grant from the grant table.
1354 pub fn ungrant(
1355 &mut self,
1356 key: KeyDescriptor,
1357 caller_uid: u32,
1358 grantee_uid: u32,
1359 check_permission: impl FnOnce(&KeyDescriptor) -> Result<()>,
1360 ) -> Result<()> {
1361 let tx = self
1362 .conn
1363 .transaction_with_behavior(TransactionBehavior::Immediate)
1364 .context("In ungrant: Failed to initialize transaction.")?;
1365
1366 // Load the key_id and complete the access control tuple.
1367 // We ignore the access vector here because grants cannot be granted.
1368 let (key_id, access_key_descriptor, _) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001369 Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid)
1370 .context("In ungrant.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001371
1372 // Perform access control. We must return here if the permission
1373 // was denied. So do not touch the '?' at the end of this line.
1374 check_permission(&access_key_descriptor).context("In grant: check_permission failed.")?;
1375
1376 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001377 "DELETE FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001378 WHERE keyentryid = ? AND grantee = ?;",
1379 params![key_id, grantee_uid],
1380 )
1381 .context("Failed to delete grant.")?;
1382
1383 tx.commit().context("In ungrant: failed to commit transaction.")?;
1384
1385 Ok(())
1386 }
1387
Joel Galenson845f74b2020-09-09 14:11:55 -07001388 // Generates a random id and passes it to the given function, which will
1389 // try to insert it into a database. If that insertion fails, retry;
1390 // otherwise return the id.
1391 fn insert_with_retry(inserter: impl Fn(i64) -> rusqlite::Result<usize>) -> Result<i64> {
1392 loop {
1393 let newid: i64 = random();
1394 match inserter(newid) {
1395 // If the id already existed, try again.
1396 Err(rusqlite::Error::SqliteFailure(
1397 libsqlite3_sys::Error {
1398 code: libsqlite3_sys::ErrorCode::ConstraintViolation,
1399 extended_code: libsqlite3_sys::SQLITE_CONSTRAINT_UNIQUE,
1400 },
1401 _,
1402 )) => (),
1403 Err(e) => {
1404 return Err(e).context("In insert_with_retry: failed to insert into database.")
1405 }
1406 _ => return Ok(newid),
1407 }
1408 }
1409 }
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001410
1411 /// Insert or replace the auth token based on the UNIQUE constraint of the auth token table
1412 pub fn insert_auth_token(&mut self, auth_token: &HardwareAuthToken) -> Result<()> {
1413 self.conn
1414 .execute(
1415 "INSERT OR REPLACE INTO perboot.authtoken (challenge, user_id, auth_id,
1416 authenticator_type, timestamp, mac, time_received) VALUES(?, ?, ?, ?, ?, ?, ?);",
1417 params![
1418 auth_token.challenge,
1419 auth_token.userId,
1420 auth_token.authenticatorId,
1421 auth_token.authenticatorType.0 as i32,
1422 auth_token.timestamp.milliSeconds as i64,
1423 auth_token.mac,
1424 MonotonicRawTime::now(),
1425 ],
1426 )
1427 .context("In insert_auth_token: failed to insert auth token into the database")?;
1428 Ok(())
1429 }
Joel Galenson26f4d012020-07-17 14:57:21 -07001430}
1431
1432#[cfg(test)]
1433mod tests {
1434
1435 use super::*;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001436 use crate::key_parameter::{
1437 Algorithm, BlockMode, Digest, EcCurve, HardwareAuthenticatorType, KeyOrigin, KeyParameter,
1438 KeyParameterValue, KeyPurpose, PaddingMode, SecurityLevel,
1439 };
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001440 use crate::key_perm_set;
1441 use crate::permission::{KeyPerm, KeyPermSet};
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001442 use crate::test::utils::TempDir;
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001443 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
1444 HardwareAuthToken::HardwareAuthToken,
1445 HardwareAuthenticatorType::HardwareAuthenticatorType as kmhw_authenticator_type,
1446 Timestamp::Timestamp,
1447 };
1448 use rusqlite::Error;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001449 use rusqlite::NO_PARAMS;
Joel Galenson0891bc12020-07-20 10:37:03 -07001450 use std::cell::RefCell;
Janis Danisevskisaec14592020-11-12 09:41:49 -08001451 use std::sync::atomic::{AtomicU8, Ordering};
1452 use std::sync::Arc;
1453 use std::thread;
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001454 use std::time::SystemTime;
Joel Galenson0891bc12020-07-20 10:37:03 -07001455
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001456 fn new_test_db() -> Result<KeystoreDB> {
1457 let conn = KeystoreDB::make_connection("file::memory:", "file::memory:")?;
1458
1459 KeystoreDB::init_tables(&conn).context("Failed to initialize tables.")?;
1460 Ok(KeystoreDB { conn })
1461 }
1462
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001463 #[test]
1464 fn datetime() -> Result<()> {
1465 let conn = Connection::open_in_memory()?;
1466 conn.execute("CREATE TABLE test (ts DATETIME);", NO_PARAMS)?;
1467 let now = SystemTime::now();
1468 let duration = Duration::from_secs(1000);
1469 let then = now.checked_sub(duration).unwrap();
1470 let soon = now.checked_add(duration).unwrap();
1471 conn.execute(
1472 "INSERT INTO test (ts) VALUES (?), (?), (?);",
1473 params![DateTime::try_from(now)?, DateTime::try_from(then)?, DateTime::try_from(soon)?],
1474 )?;
1475 let mut stmt = conn.prepare("SELECT ts FROM test ORDER BY ts ASC;")?;
1476 let mut rows = stmt.query(NO_PARAMS)?;
1477 assert_eq!(DateTime::try_from(then)?, rows.next()?.unwrap().get(0)?);
1478 assert_eq!(DateTime::try_from(now)?, rows.next()?.unwrap().get(0)?);
1479 assert_eq!(DateTime::try_from(soon)?, rows.next()?.unwrap().get(0)?);
1480 assert!(rows.next()?.is_none());
1481 assert!(DateTime::try_from(then)? < DateTime::try_from(now)?);
1482 assert!(DateTime::try_from(then)? < DateTime::try_from(soon)?);
1483 assert!(DateTime::try_from(now)? < DateTime::try_from(soon)?);
1484 Ok(())
1485 }
1486
Joel Galenson0891bc12020-07-20 10:37:03 -07001487 // Ensure that we're using the "injected" random function, not the real one.
1488 #[test]
1489 fn test_mocked_random() {
1490 let rand1 = random();
1491 let rand2 = random();
1492 let rand3 = random();
1493 if rand1 == rand2 {
1494 assert_eq!(rand2 + 1, rand3);
1495 } else {
1496 assert_eq!(rand1 + 1, rand2);
1497 assert_eq!(rand2, rand3);
1498 }
1499 }
Joel Galenson26f4d012020-07-17 14:57:21 -07001500
Joel Galenson26f4d012020-07-17 14:57:21 -07001501 // Test that we have the correct tables.
1502 #[test]
1503 fn test_tables() -> Result<()> {
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001504 let db = new_test_db()?;
Joel Galenson26f4d012020-07-17 14:57:21 -07001505 let tables = db
1506 .conn
Joel Galenson2aab4432020-07-22 15:27:57 -07001507 .prepare("SELECT name from persistent.sqlite_master WHERE type='table' ORDER BY name;")?
Joel Galenson26f4d012020-07-17 14:57:21 -07001508 .query_map(params![], |row| row.get(0))?
1509 .collect::<rusqlite::Result<Vec<String>>>()?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001510 assert_eq!(tables.len(), 5);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001511 assert_eq!(tables[0], "blobentry");
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001512 assert_eq!(tables[1], "grant");
1513 assert_eq!(tables[2], "keyentry");
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001514 assert_eq!(tables[3], "keymetadata");
1515 assert_eq!(tables[4], "keyparameter");
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001516 let tables = db
1517 .conn
1518 .prepare("SELECT name from perboot.sqlite_master WHERE type='table' ORDER BY name;")?
1519 .query_map(params![], |row| row.get(0))?
1520 .collect::<rusqlite::Result<Vec<String>>>()?;
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001521
1522 assert_eq!(tables.len(), 2);
1523 assert_eq!(tables[0], "authtoken");
1524 assert_eq!(tables[1], "metadata");
Joel Galenson2aab4432020-07-22 15:27:57 -07001525 Ok(())
1526 }
1527
1528 #[test]
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001529 fn test_auth_token_table_invariant() -> Result<()> {
1530 let mut db = new_test_db()?;
1531 let auth_token1 = HardwareAuthToken {
1532 challenge: i64::MAX,
1533 userId: 200,
1534 authenticatorId: 200,
1535 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
1536 timestamp: Timestamp { milliSeconds: 500 },
1537 mac: String::from("mac").into_bytes(),
1538 };
1539 db.insert_auth_token(&auth_token1)?;
1540 let auth_tokens_returned = get_auth_tokens(&mut db)?;
1541 assert_eq!(auth_tokens_returned.len(), 1);
1542
1543 // insert another auth token with the same values for the columns in the UNIQUE constraint
1544 // of the auth token table and different value for timestamp
1545 let auth_token2 = HardwareAuthToken {
1546 challenge: i64::MAX,
1547 userId: 200,
1548 authenticatorId: 200,
1549 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
1550 timestamp: Timestamp { milliSeconds: 600 },
1551 mac: String::from("mac").into_bytes(),
1552 };
1553
1554 db.insert_auth_token(&auth_token2)?;
1555 let mut auth_tokens_returned = get_auth_tokens(&mut db)?;
1556 assert_eq!(auth_tokens_returned.len(), 1);
1557
1558 if let Some(auth_token) = auth_tokens_returned.pop() {
1559 assert_eq!(auth_token.auth_token.timestamp.milliSeconds, 600);
1560 }
1561
1562 // insert another auth token with the different values for the columns in the UNIQUE
1563 // constraint of the auth token table
1564 let auth_token3 = HardwareAuthToken {
1565 challenge: i64::MAX,
1566 userId: 201,
1567 authenticatorId: 200,
1568 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
1569 timestamp: Timestamp { milliSeconds: 600 },
1570 mac: String::from("mac").into_bytes(),
1571 };
1572
1573 db.insert_auth_token(&auth_token3)?;
1574 let auth_tokens_returned = get_auth_tokens(&mut db)?;
1575 assert_eq!(auth_tokens_returned.len(), 2);
1576
1577 Ok(())
1578 }
1579
1580 // utility function for test_auth_token_table_invariant()
1581 fn get_auth_tokens(db: &mut KeystoreDB) -> Result<Vec<AuthTokenEntry>> {
1582 let mut stmt = db.conn.prepare("SELECT * from perboot.authtoken;")?;
1583
1584 let auth_token_entries: Vec<AuthTokenEntry> = stmt
1585 .query_map(NO_PARAMS, |row| {
1586 Ok(AuthTokenEntry::new(
1587 HardwareAuthToken {
1588 challenge: row.get(1)?,
1589 userId: row.get(2)?,
1590 authenticatorId: row.get(3)?,
1591 authenticatorType: HardwareAuthenticatorType(row.get(4)?),
1592 timestamp: Timestamp { milliSeconds: row.get(5)? },
1593 mac: row.get(6)?,
1594 },
1595 row.get(7)?,
1596 ))
1597 })?
1598 .collect::<Result<Vec<AuthTokenEntry>, Error>>()?;
1599 Ok(auth_token_entries)
1600 }
1601
1602 #[test]
Joel Galenson2aab4432020-07-22 15:27:57 -07001603 fn test_persistence_for_files() -> Result<()> {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001604 let temp_dir = TempDir::new("persistent_db_test")?;
1605 let db = KeystoreDB::new(temp_dir.path())?;
Joel Galenson2aab4432020-07-22 15:27:57 -07001606
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001607 db.create_key_entry(Domain::APP, 100)?;
Joel Galenson2aab4432020-07-22 15:27:57 -07001608 let entries = get_keyentry(&db)?;
1609 assert_eq!(entries.len(), 1);
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001610
1611 let db = KeystoreDB::new(temp_dir.path())?;
Joel Galenson2aab4432020-07-22 15:27:57 -07001612
1613 let entries_new = get_keyentry(&db)?;
1614 assert_eq!(entries, entries_new);
1615 Ok(())
1616 }
1617
1618 #[test]
Joel Galenson0891bc12020-07-20 10:37:03 -07001619 fn test_create_key_entry() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001620 fn extractor(ke: &KeyEntryRow) -> (Domain, i64, Option<&str>) {
Joel Galenson0891bc12020-07-20 10:37:03 -07001621 (ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref())
1622 }
1623
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001624 let db = new_test_db()?;
Joel Galenson0891bc12020-07-20 10:37:03 -07001625
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001626 db.create_key_entry(Domain::APP, 100)?;
1627 db.create_key_entry(Domain::SELINUX, 101)?;
Joel Galenson0891bc12020-07-20 10:37:03 -07001628
1629 let entries = get_keyentry(&db)?;
1630 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001631 assert_eq!(extractor(&entries[0]), (Domain::APP, 100, None));
1632 assert_eq!(extractor(&entries[1]), (Domain::SELINUX, 101, None));
Joel Galenson0891bc12020-07-20 10:37:03 -07001633
1634 // Test that we must pass in a valid Domain.
1635 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001636 db.create_key_entry(Domain::GRANT, 102),
1637 "Domain Domain(1) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07001638 );
1639 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001640 db.create_key_entry(Domain::BLOB, 103),
1641 "Domain Domain(3) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07001642 );
1643 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001644 db.create_key_entry(Domain::KEY_ID, 104),
1645 "Domain Domain(4) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07001646 );
1647
1648 Ok(())
1649 }
1650
Joel Galenson33c04ad2020-08-03 11:04:38 -07001651 #[test]
1652 fn test_rebind_alias() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001653 fn extractor(ke: &KeyEntryRow) -> (Option<Domain>, Option<i64>, Option<&str>) {
Joel Galenson33c04ad2020-08-03 11:04:38 -07001654 (ke.domain, ke.namespace, ke.alias.as_deref())
1655 }
1656
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001657 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001658 db.create_key_entry(Domain::APP, 42)?;
1659 db.create_key_entry(Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07001660 let entries = get_keyentry(&db)?;
1661 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001662 assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), None));
1663 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
Joel Galenson33c04ad2020-08-03 11:04:38 -07001664
1665 // Test that the first call to rebind_alias sets the alias.
Janis Danisevskisaec14592020-11-12 09:41:49 -08001666 db.rebind_alias(&KEY_ID_LOCK.get(entries[0].id), "foo", Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07001667 let entries = get_keyentry(&db)?;
1668 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001669 assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), Some("foo")));
1670 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
Joel Galenson33c04ad2020-08-03 11:04:38 -07001671
1672 // Test that the second call to rebind_alias also empties the old one.
Janis Danisevskisaec14592020-11-12 09:41:49 -08001673 db.rebind_alias(&KEY_ID_LOCK.get(entries[1].id), "foo", Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07001674 let entries = get_keyentry(&db)?;
1675 assert_eq!(entries.len(), 2);
Joel Galenson7fa5c412020-11-19 10:56:54 -08001676 assert_eq!(extractor(&entries[0]), (None, None, None));
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001677 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
Joel Galenson33c04ad2020-08-03 11:04:38 -07001678
1679 // Test that we must pass in a valid Domain.
1680 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001681 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::GRANT, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001682 "Domain Domain(1) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07001683 );
1684 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001685 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::BLOB, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001686 "Domain Domain(3) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07001687 );
1688 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001689 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::KEY_ID, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001690 "Domain Domain(4) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07001691 );
1692
1693 // Test that we correctly handle setting an alias for something that does not exist.
1694 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001695 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::SELINUX, 42),
Joel Galenson33c04ad2020-08-03 11:04:38 -07001696 "Expected to update a single entry but instead updated 0",
1697 );
1698 // Test that we correctly abort the transaction in this case.
1699 let entries = get_keyentry(&db)?;
1700 assert_eq!(entries.len(), 2);
Joel Galenson7fa5c412020-11-19 10:56:54 -08001701 assert_eq!(extractor(&entries[0]), (None, None, None));
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001702 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
Joel Galenson33c04ad2020-08-03 11:04:38 -07001703
1704 Ok(())
1705 }
1706
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001707 #[test]
1708 fn test_grant_ungrant() -> Result<()> {
1709 const CALLER_UID: u32 = 15;
1710 const GRANTEE_UID: u32 = 12;
1711 const SELINUX_NAMESPACE: i64 = 7;
1712
1713 let mut db = new_test_db()?;
1714 db.conn.execute(
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001715 "INSERT INTO persistent.keyentry (id, key_type, domain, namespace, alias)
1716 VALUES (1, 0, 0, 15, 'key'), (2, 0, 2, 7, 'yek');",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001717 NO_PARAMS,
1718 )?;
1719 let app_key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001720 domain: super::Domain::APP,
1721 nspace: 0,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001722 alias: Some("key".to_string()),
1723 blob: None,
1724 };
1725 const PVEC1: KeyPermSet = key_perm_set![KeyPerm::use_(), KeyPerm::get_info()];
1726 const PVEC2: KeyPermSet = key_perm_set![KeyPerm::use_()];
1727
1728 // Reset totally predictable random number generator in case we
1729 // are not the first test running on this thread.
1730 reset_random();
1731 let next_random = 0i64;
1732
1733 let app_granted_key =
1734 db.grant(app_key.clone(), CALLER_UID, GRANTEE_UID, PVEC1, |k, a| {
1735 assert_eq!(*a, PVEC1);
1736 assert_eq!(
1737 *k,
1738 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001739 domain: super::Domain::APP,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001740 // namespace must be set to the caller_uid.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001741 nspace: CALLER_UID as i64,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001742 alias: Some("key".to_string()),
1743 blob: None,
1744 }
1745 );
1746 Ok(())
1747 })?;
1748
1749 assert_eq!(
1750 app_granted_key,
1751 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001752 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001753 // The grantid is next_random due to the mock random number generator.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001754 nspace: next_random,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001755 alias: None,
1756 blob: None,
1757 }
1758 );
1759
1760 let selinux_key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001761 domain: super::Domain::SELINUX,
1762 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001763 alias: Some("yek".to_string()),
1764 blob: None,
1765 };
1766
1767 let selinux_granted_key =
1768 db.grant(selinux_key.clone(), CALLER_UID, 12, PVEC1, |k, a| {
1769 assert_eq!(*a, PVEC1);
1770 assert_eq!(
1771 *k,
1772 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001773 domain: super::Domain::SELINUX,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001774 // namespace must be the supplied SELinux
1775 // namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001776 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001777 alias: Some("yek".to_string()),
1778 blob: None,
1779 }
1780 );
1781 Ok(())
1782 })?;
1783
1784 assert_eq!(
1785 selinux_granted_key,
1786 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001787 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001788 // The grantid is next_random + 1 due to the mock random number generator.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001789 nspace: next_random + 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001790 alias: None,
1791 blob: None,
1792 }
1793 );
1794
1795 // This should update the existing grant with PVEC2.
1796 let selinux_granted_key =
1797 db.grant(selinux_key.clone(), CALLER_UID, 12, PVEC2, |k, a| {
1798 assert_eq!(*a, PVEC2);
1799 assert_eq!(
1800 *k,
1801 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001802 domain: super::Domain::SELINUX,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001803 // namespace must be the supplied SELinux
1804 // namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001805 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001806 alias: Some("yek".to_string()),
1807 blob: None,
1808 }
1809 );
1810 Ok(())
1811 })?;
1812
1813 assert_eq!(
1814 selinux_granted_key,
1815 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001816 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001817 // Same grant id as before. The entry was only updated.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001818 nspace: next_random + 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001819 alias: None,
1820 blob: None,
1821 }
1822 );
1823
1824 {
1825 // Limiting scope of stmt, because it borrows db.
1826 let mut stmt = db
1827 .conn
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001828 .prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?;
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07001829 let mut rows =
1830 stmt.query_map::<(i64, u32, i64, KeyPermSet), _, _>(NO_PARAMS, |row| {
1831 Ok((
1832 row.get(0)?,
1833 row.get(1)?,
1834 row.get(2)?,
1835 KeyPermSet::from(row.get::<_, i32>(3)?),
1836 ))
1837 })?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001838
1839 let r = rows.next().unwrap().unwrap();
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07001840 assert_eq!(r, (next_random, GRANTEE_UID, 1, PVEC1));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001841 let r = rows.next().unwrap().unwrap();
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07001842 assert_eq!(r, (next_random + 1, GRANTEE_UID, 2, PVEC2));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001843 assert!(rows.next().is_none());
1844 }
1845
1846 debug_dump_keyentry_table(&mut db)?;
1847 println!("app_key {:?}", app_key);
1848 println!("selinux_key {:?}", selinux_key);
1849
1850 db.ungrant(app_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
1851 db.ungrant(selinux_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
1852
1853 Ok(())
1854 }
1855
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001856 static TEST_KEY_BLOB: &[u8] = b"my test blob";
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001857 static TEST_CERT_BLOB: &[u8] = b"my test cert";
1858 static TEST_CERT_CHAIN_BLOB: &[u8] = b"my test cert_chain";
1859
1860 #[test]
1861 fn test_insert_blob() -> Result<()> {
1862 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001863 db.insert_blob(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001864 &KEY_ID_LOCK.get(1),
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001865 SubComponentType::KEY_BLOB,
1866 TEST_KEY_BLOB,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001867 SecurityLevel::SOFTWARE,
1868 )?;
1869 db.insert_blob(
1870 &KEY_ID_LOCK.get(1),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001871 SubComponentType::CERT,
1872 TEST_CERT_BLOB,
1873 SecurityLevel::TRUSTED_ENVIRONMENT,
1874 )?;
1875 db.insert_blob(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001876 &KEY_ID_LOCK.get(1),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001877 SubComponentType::CERT_CHAIN,
1878 TEST_CERT_CHAIN_BLOB,
1879 SecurityLevel::STRONGBOX,
1880 )?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001881
1882 let mut stmt = db.conn.prepare(
1883 "SELECT subcomponent_type, keyentryid, blob, sec_level FROM persistent.blobentry
1884 ORDER BY sec_level ASC;",
1885 )?;
1886 let mut rows = stmt
1887 .query_map::<(SubComponentType, i64, Vec<u8>, i64), _, _>(NO_PARAMS, |row| {
1888 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?))
1889 })?;
1890 let r = rows.next().unwrap().unwrap();
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001891 assert_eq!(r, (SubComponentType::KEY_BLOB, 1, TEST_KEY_BLOB.to_vec(), 0));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001892 let r = rows.next().unwrap().unwrap();
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001893 assert_eq!(r, (SubComponentType::CERT, 1, TEST_CERT_BLOB.to_vec(), 1));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001894 let r = rows.next().unwrap().unwrap();
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001895 assert_eq!(r, (SubComponentType::CERT_CHAIN, 1, TEST_CERT_CHAIN_BLOB.to_vec(), 2));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001896
1897 Ok(())
1898 }
1899
1900 static TEST_ALIAS: &str = "my super duper key";
1901
1902 #[test]
1903 fn test_insert_and_load_full_keyentry_domain_app() -> Result<()> {
1904 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001905 let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08001906 .context("test_insert_and_load_full_keyentry_domain_app")?
1907 .0;
1908 let (_key_guard, key_entry) = db.load_key_entry(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001909 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001910 domain: Domain::APP,
1911 nspace: 0,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001912 alias: Some(TEST_ALIAS.to_string()),
1913 blob: None,
1914 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001915 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001916 KeyEntryLoadBits::BOTH,
1917 1,
1918 |_k, _av| Ok(()),
1919 )?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001920 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001921 Ok(())
1922 }
1923
1924 #[test]
1925 fn test_insert_and_load_full_keyentry_domain_selinux() -> Result<()> {
1926 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001927 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08001928 .context("test_insert_and_load_full_keyentry_domain_selinux")?
1929 .0;
1930 let (_key_guard, key_entry) = db.load_key_entry(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001931 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001932 domain: Domain::SELINUX,
1933 nspace: 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001934 alias: Some(TEST_ALIAS.to_string()),
1935 blob: None,
1936 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001937 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001938 KeyEntryLoadBits::BOTH,
1939 1,
1940 |_k, _av| Ok(()),
1941 )?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001942 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001943 Ok(())
1944 }
1945
1946 #[test]
1947 fn test_insert_and_load_full_keyentry_domain_key_id() -> Result<()> {
1948 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001949 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08001950 .context("test_insert_and_load_full_keyentry_domain_key_id")?
1951 .0;
1952 let (_key_guard, key_entry) = db.load_key_entry(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001953 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001954 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001955 KeyEntryLoadBits::BOTH,
1956 1,
1957 |_k, _av| Ok(()),
1958 )?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001959 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001960
1961 Ok(())
1962 }
1963
1964 #[test]
1965 fn test_insert_and_load_full_keyentry_from_grant() -> Result<()> {
1966 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001967 let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08001968 .context("test_insert_and_load_full_keyentry_from_grant")?
1969 .0;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001970
1971 let granted_key = db.grant(
1972 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001973 domain: Domain::APP,
1974 nspace: 0,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001975 alias: Some(TEST_ALIAS.to_string()),
1976 blob: None,
1977 },
1978 1,
1979 2,
1980 key_perm_set![KeyPerm::use_()],
1981 |_k, _av| Ok(()),
1982 )?;
1983
1984 debug_dump_grant_table(&mut db)?;
1985
Janis Danisevskisaec14592020-11-12 09:41:49 -08001986 let (_key_guard, key_entry) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001987 db.load_key_entry(granted_key, KeyType::Client, KeyEntryLoadBits::BOTH, 2, |k, av| {
Janis Danisevskisaec14592020-11-12 09:41:49 -08001988 assert_eq!(Domain::GRANT, k.domain);
1989 assert!(av.unwrap().includes(KeyPerm::use_()));
1990 Ok(())
1991 })?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001992
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001993 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001994 Ok(())
1995 }
1996
Janis Danisevskisaec14592020-11-12 09:41:49 -08001997 static KEY_LOCK_TEST_ALIAS: &str = "my super duper locked key";
1998
Janis Danisevskisaec14592020-11-12 09:41:49 -08001999 #[test]
2000 fn test_insert_and_load_full_keyentry_domain_app_concurrently() -> Result<()> {
2001 let handle = {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002002 let temp_dir = Arc::new(TempDir::new("id_lock_test")?);
2003 let temp_dir_clone = temp_dir.clone();
2004 let mut db = KeystoreDB::new(temp_dir.path())?;
Janis Danisevskisaec14592020-11-12 09:41:49 -08002005 let key_id = make_test_key_entry(&mut db, Domain::APP, 33, KEY_LOCK_TEST_ALIAS)
2006 .context("test_insert_and_load_full_keyentry_domain_app")?
2007 .0;
2008 let (_key_guard, key_entry) = db.load_key_entry(
2009 KeyDescriptor {
2010 domain: Domain::APP,
2011 nspace: 0,
2012 alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
2013 blob: None,
2014 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002015 KeyType::Client,
Janis Danisevskisaec14592020-11-12 09:41:49 -08002016 KeyEntryLoadBits::BOTH,
2017 33,
2018 |_k, _av| Ok(()),
2019 )?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002020 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
Janis Danisevskisaec14592020-11-12 09:41:49 -08002021 let state = Arc::new(AtomicU8::new(1));
2022 let state2 = state.clone();
2023
2024 // Spawning a second thread that attempts to acquire the key id lock
2025 // for the same key as the primary thread. The primary thread then
2026 // waits, thereby forcing the secondary thread into the second stage
2027 // of acquiring the lock (see KEY ID LOCK 2/2 above).
2028 // The test succeeds if the secondary thread observes the transition
2029 // of `state` from 1 to 2, despite having a whole second to overtake
2030 // the primary thread.
2031 let handle = thread::spawn(move || {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002032 let temp_dir = temp_dir_clone;
2033 let mut db = KeystoreDB::new(temp_dir.path()).unwrap();
Janis Danisevskisaec14592020-11-12 09:41:49 -08002034 assert!(db
2035 .load_key_entry(
2036 KeyDescriptor {
2037 domain: Domain::APP,
2038 nspace: 0,
2039 alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
2040 blob: None,
2041 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002042 KeyType::Client,
Janis Danisevskisaec14592020-11-12 09:41:49 -08002043 KeyEntryLoadBits::BOTH,
2044 33,
2045 |_k, _av| Ok(()),
2046 )
2047 .is_ok());
2048 // We should only see a 2 here because we can only return
2049 // from load_key_entry when the `_key_guard` expires,
2050 // which happens at the end of the scope.
2051 assert_eq!(2, state2.load(Ordering::Relaxed));
2052 });
2053
2054 thread::sleep(std::time::Duration::from_millis(1000));
2055
2056 assert_eq!(Ok(1), state.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed));
2057
2058 // Return the handle from this scope so we can join with the
2059 // secondary thread after the key id lock has expired.
2060 handle
2061 // This is where the `_key_guard` goes out of scope,
2062 // which is the reason for concurrent load_key_entry on the same key
2063 // to unblock.
2064 };
2065 // Join with the secondary thread and unwrap, to propagate failing asserts to the
2066 // main test thread. We will not see failing asserts in secondary threads otherwise.
2067 handle.join().unwrap();
2068 Ok(())
2069 }
2070
Janis Danisevskise92a5e62020-12-02 12:57:41 -08002071 #[test]
2072 fn list() -> Result<()> {
2073 let temp_dir = TempDir::new("list_test")?;
2074 let mut db = KeystoreDB::new(temp_dir.path())?;
2075 static LIST_O_ENTRIES: &[(Domain, i64, &str)] = &[
2076 (Domain::APP, 1, "test1"),
2077 (Domain::APP, 1, "test2"),
2078 (Domain::APP, 1, "test3"),
2079 (Domain::APP, 1, "test4"),
2080 (Domain::APP, 1, "test5"),
2081 (Domain::APP, 1, "test6"),
2082 (Domain::APP, 1, "test7"),
2083 (Domain::APP, 2, "test1"),
2084 (Domain::APP, 2, "test2"),
2085 (Domain::APP, 2, "test3"),
2086 (Domain::APP, 2, "test4"),
2087 (Domain::APP, 2, "test5"),
2088 (Domain::APP, 2, "test6"),
2089 (Domain::APP, 2, "test8"),
2090 (Domain::SELINUX, 100, "test1"),
2091 (Domain::SELINUX, 100, "test2"),
2092 (Domain::SELINUX, 100, "test3"),
2093 (Domain::SELINUX, 100, "test4"),
2094 (Domain::SELINUX, 100, "test5"),
2095 (Domain::SELINUX, 100, "test6"),
2096 (Domain::SELINUX, 100, "test9"),
2097 ];
2098
2099 let list_o_keys: Vec<(i64, i64)> = LIST_O_ENTRIES
2100 .iter()
2101 .map(|(domain, ns, alias)| {
2102 let entry =
2103 make_test_key_entry(&mut db, *domain, *ns, *alias).unwrap_or_else(|e| {
2104 panic!("Failed to insert {:?} {} {}. Error {:?}", domain, ns, alias, e)
2105 });
2106 (entry.id(), *ns)
2107 })
2108 .collect();
2109
2110 for (domain, namespace) in
2111 &[(Domain::APP, 1i64), (Domain::APP, 2i64), (Domain::SELINUX, 100i64)]
2112 {
2113 let mut list_o_descriptors: Vec<KeyDescriptor> = LIST_O_ENTRIES
2114 .iter()
2115 .filter_map(|(domain, ns, alias)| match ns {
2116 ns if *ns == *namespace => Some(KeyDescriptor {
2117 domain: *domain,
2118 nspace: *ns,
2119 alias: Some(alias.to_string()),
2120 blob: None,
2121 }),
2122 _ => None,
2123 })
2124 .collect();
2125 list_o_descriptors.sort();
2126 let mut list_result = db.list(*domain, *namespace)?;
2127 list_result.sort();
2128 assert_eq!(list_o_descriptors, list_result);
2129
2130 let mut list_o_ids: Vec<i64> = list_o_descriptors
2131 .into_iter()
2132 .map(|d| {
2133 let (_, entry) = db
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002134 .load_key_entry(
2135 d,
2136 KeyType::Client,
2137 KeyEntryLoadBits::NONE,
2138 *namespace as u32,
2139 |_, _| Ok(()),
2140 )
Janis Danisevskise92a5e62020-12-02 12:57:41 -08002141 .unwrap();
2142 entry.id()
2143 })
2144 .collect();
2145 list_o_ids.sort_unstable();
2146 let mut loaded_entries: Vec<i64> = list_o_keys
2147 .iter()
2148 .filter_map(|(id, ns)| match ns {
2149 ns if *ns == *namespace => Some(*id),
2150 _ => None,
2151 })
2152 .collect();
2153 loaded_entries.sort_unstable();
2154 assert_eq!(list_o_ids, loaded_entries);
2155 }
2156 assert_eq!(Vec::<KeyDescriptor>::new(), db.list(Domain::SELINUX, 101)?);
2157
2158 Ok(())
2159 }
2160
Joel Galenson0891bc12020-07-20 10:37:03 -07002161 // Helpers
2162
2163 // Checks that the given result is an error containing the given string.
2164 fn check_result_is_error_containing_string<T>(result: Result<T>, target: &str) {
2165 let error_str = format!(
2166 "{:#?}",
2167 result.err().unwrap_or_else(|| panic!("Expected the error: {}", target))
2168 );
2169 assert!(
2170 error_str.contains(target),
2171 "The string \"{}\" should contain \"{}\"",
2172 error_str,
2173 target
2174 );
2175 }
2176
Joel Galenson2aab4432020-07-22 15:27:57 -07002177 #[derive(Debug, PartialEq)]
Joel Galenson0891bc12020-07-20 10:37:03 -07002178 #[allow(dead_code)]
2179 struct KeyEntryRow {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002180 id: i64,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002181 key_type: KeyType,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002182 domain: Option<Domain>,
Joel Galenson0891bc12020-07-20 10:37:03 -07002183 namespace: Option<i64>,
2184 alias: Option<String>,
2185 }
2186
2187 fn get_keyentry(db: &KeystoreDB) -> Result<Vec<KeyEntryRow>> {
2188 db.conn
Joel Galenson2aab4432020-07-22 15:27:57 -07002189 .prepare("SELECT * FROM persistent.keyentry;")?
Joel Galenson0891bc12020-07-20 10:37:03 -07002190 .query_map(NO_PARAMS, |row| {
Joel Galenson0891bc12020-07-20 10:37:03 -07002191 Ok(KeyEntryRow {
2192 id: row.get(0)?,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002193 key_type: row.get(1)?,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002194 domain: match row.get(2)? {
2195 Some(i) => Some(Domain(i)),
2196 None => None,
2197 },
Joel Galenson0891bc12020-07-20 10:37:03 -07002198 namespace: row.get(3)?,
2199 alias: row.get(4)?,
2200 })
2201 })?
2202 .map(|r| r.context("Could not read keyentry row."))
2203 .collect::<Result<Vec<_>>>()
2204 }
2205
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07002206 // Note: The parameters and SecurityLevel associations are nonsensical. This
2207 // collection is only used to check if the parameters are preserved as expected by the
2208 // database.
2209 fn make_test_params() -> Vec<KeyParameter> {
2210 vec![
2211 KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::TRUSTED_ENVIRONMENT),
2212 KeyParameter::new(
2213 KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
2214 SecurityLevel::TRUSTED_ENVIRONMENT,
2215 ),
2216 KeyParameter::new(
2217 KeyParameterValue::KeyPurpose(KeyPurpose::DECRYPT),
2218 SecurityLevel::TRUSTED_ENVIRONMENT,
2219 ),
2220 KeyParameter::new(
2221 KeyParameterValue::Algorithm(Algorithm::RSA),
2222 SecurityLevel::TRUSTED_ENVIRONMENT,
2223 ),
2224 KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::TRUSTED_ENVIRONMENT),
2225 KeyParameter::new(
2226 KeyParameterValue::BlockMode(BlockMode::ECB),
2227 SecurityLevel::TRUSTED_ENVIRONMENT,
2228 ),
2229 KeyParameter::new(
2230 KeyParameterValue::BlockMode(BlockMode::GCM),
2231 SecurityLevel::TRUSTED_ENVIRONMENT,
2232 ),
2233 KeyParameter::new(KeyParameterValue::Digest(Digest::NONE), SecurityLevel::STRONGBOX),
2234 KeyParameter::new(
2235 KeyParameterValue::Digest(Digest::MD5),
2236 SecurityLevel::TRUSTED_ENVIRONMENT,
2237 ),
2238 KeyParameter::new(
2239 KeyParameterValue::Digest(Digest::SHA_2_224),
2240 SecurityLevel::TRUSTED_ENVIRONMENT,
2241 ),
2242 KeyParameter::new(
2243 KeyParameterValue::Digest(Digest::SHA_2_256),
2244 SecurityLevel::STRONGBOX,
2245 ),
2246 KeyParameter::new(
2247 KeyParameterValue::PaddingMode(PaddingMode::NONE),
2248 SecurityLevel::TRUSTED_ENVIRONMENT,
2249 ),
2250 KeyParameter::new(
2251 KeyParameterValue::PaddingMode(PaddingMode::RSA_OAEP),
2252 SecurityLevel::TRUSTED_ENVIRONMENT,
2253 ),
2254 KeyParameter::new(
2255 KeyParameterValue::PaddingMode(PaddingMode::RSA_PSS),
2256 SecurityLevel::STRONGBOX,
2257 ),
2258 KeyParameter::new(
2259 KeyParameterValue::PaddingMode(PaddingMode::RSA_PKCS1_1_5_SIGN),
2260 SecurityLevel::TRUSTED_ENVIRONMENT,
2261 ),
2262 KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::TRUSTED_ENVIRONMENT),
2263 KeyParameter::new(KeyParameterValue::MinMacLength(256), SecurityLevel::STRONGBOX),
2264 KeyParameter::new(
2265 KeyParameterValue::EcCurve(EcCurve::P_224),
2266 SecurityLevel::TRUSTED_ENVIRONMENT,
2267 ),
2268 KeyParameter::new(KeyParameterValue::EcCurve(EcCurve::P_256), SecurityLevel::STRONGBOX),
2269 KeyParameter::new(
2270 KeyParameterValue::EcCurve(EcCurve::P_384),
2271 SecurityLevel::TRUSTED_ENVIRONMENT,
2272 ),
2273 KeyParameter::new(
2274 KeyParameterValue::EcCurve(EcCurve::P_521),
2275 SecurityLevel::TRUSTED_ENVIRONMENT,
2276 ),
2277 KeyParameter::new(
2278 KeyParameterValue::RSAPublicExponent(3),
2279 SecurityLevel::TRUSTED_ENVIRONMENT,
2280 ),
2281 KeyParameter::new(
2282 KeyParameterValue::IncludeUniqueID,
2283 SecurityLevel::TRUSTED_ENVIRONMENT,
2284 ),
2285 KeyParameter::new(KeyParameterValue::BootLoaderOnly, SecurityLevel::STRONGBOX),
2286 KeyParameter::new(KeyParameterValue::RollbackResistance, SecurityLevel::STRONGBOX),
2287 KeyParameter::new(
2288 KeyParameterValue::ActiveDateTime(1234567890),
2289 SecurityLevel::STRONGBOX,
2290 ),
2291 KeyParameter::new(
2292 KeyParameterValue::OriginationExpireDateTime(1234567890),
2293 SecurityLevel::TRUSTED_ENVIRONMENT,
2294 ),
2295 KeyParameter::new(
2296 KeyParameterValue::UsageExpireDateTime(1234567890),
2297 SecurityLevel::TRUSTED_ENVIRONMENT,
2298 ),
2299 KeyParameter::new(
2300 KeyParameterValue::MinSecondsBetweenOps(1234567890),
2301 SecurityLevel::TRUSTED_ENVIRONMENT,
2302 ),
2303 KeyParameter::new(
2304 KeyParameterValue::MaxUsesPerBoot(1234567890),
2305 SecurityLevel::TRUSTED_ENVIRONMENT,
2306 ),
2307 KeyParameter::new(KeyParameterValue::UserID(1), SecurityLevel::STRONGBOX),
2308 KeyParameter::new(KeyParameterValue::UserSecureID(42), SecurityLevel::STRONGBOX),
2309 KeyParameter::new(
2310 KeyParameterValue::NoAuthRequired,
2311 SecurityLevel::TRUSTED_ENVIRONMENT,
2312 ),
2313 KeyParameter::new(
2314 KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType::PASSWORD),
2315 SecurityLevel::TRUSTED_ENVIRONMENT,
2316 ),
2317 KeyParameter::new(KeyParameterValue::AuthTimeout(1234567890), SecurityLevel::SOFTWARE),
2318 KeyParameter::new(KeyParameterValue::AllowWhileOnBody, SecurityLevel::SOFTWARE),
2319 KeyParameter::new(
2320 KeyParameterValue::TrustedUserPresenceRequired,
2321 SecurityLevel::TRUSTED_ENVIRONMENT,
2322 ),
2323 KeyParameter::new(
2324 KeyParameterValue::TrustedConfirmationRequired,
2325 SecurityLevel::TRUSTED_ENVIRONMENT,
2326 ),
2327 KeyParameter::new(
2328 KeyParameterValue::UnlockedDeviceRequired,
2329 SecurityLevel::TRUSTED_ENVIRONMENT,
2330 ),
2331 KeyParameter::new(
2332 KeyParameterValue::ApplicationID(vec![1u8, 2u8, 3u8, 4u8]),
2333 SecurityLevel::SOFTWARE,
2334 ),
2335 KeyParameter::new(
2336 KeyParameterValue::ApplicationData(vec![4u8, 3u8, 2u8, 1u8]),
2337 SecurityLevel::SOFTWARE,
2338 ),
2339 KeyParameter::new(
2340 KeyParameterValue::CreationDateTime(12345677890),
2341 SecurityLevel::SOFTWARE,
2342 ),
2343 KeyParameter::new(
2344 KeyParameterValue::KeyOrigin(KeyOrigin::GENERATED),
2345 SecurityLevel::TRUSTED_ENVIRONMENT,
2346 ),
2347 KeyParameter::new(
2348 KeyParameterValue::RootOfTrust(vec![3u8, 2u8, 1u8, 4u8]),
2349 SecurityLevel::TRUSTED_ENVIRONMENT,
2350 ),
2351 KeyParameter::new(KeyParameterValue::OSVersion(1), SecurityLevel::TRUSTED_ENVIRONMENT),
2352 KeyParameter::new(KeyParameterValue::OSPatchLevel(2), SecurityLevel::SOFTWARE),
2353 KeyParameter::new(
2354 KeyParameterValue::UniqueID(vec![4u8, 3u8, 1u8, 2u8]),
2355 SecurityLevel::SOFTWARE,
2356 ),
2357 KeyParameter::new(
2358 KeyParameterValue::AttestationChallenge(vec![4u8, 3u8, 1u8, 2u8]),
2359 SecurityLevel::TRUSTED_ENVIRONMENT,
2360 ),
2361 KeyParameter::new(
2362 KeyParameterValue::AttestationApplicationID(vec![4u8, 3u8, 1u8, 2u8]),
2363 SecurityLevel::TRUSTED_ENVIRONMENT,
2364 ),
2365 KeyParameter::new(
2366 KeyParameterValue::AttestationIdBrand(vec![4u8, 3u8, 1u8, 2u8]),
2367 SecurityLevel::TRUSTED_ENVIRONMENT,
2368 ),
2369 KeyParameter::new(
2370 KeyParameterValue::AttestationIdDevice(vec![4u8, 3u8, 1u8, 2u8]),
2371 SecurityLevel::TRUSTED_ENVIRONMENT,
2372 ),
2373 KeyParameter::new(
2374 KeyParameterValue::AttestationIdProduct(vec![4u8, 3u8, 1u8, 2u8]),
2375 SecurityLevel::TRUSTED_ENVIRONMENT,
2376 ),
2377 KeyParameter::new(
2378 KeyParameterValue::AttestationIdSerial(vec![4u8, 3u8, 1u8, 2u8]),
2379 SecurityLevel::TRUSTED_ENVIRONMENT,
2380 ),
2381 KeyParameter::new(
2382 KeyParameterValue::AttestationIdIMEI(vec![4u8, 3u8, 1u8, 2u8]),
2383 SecurityLevel::TRUSTED_ENVIRONMENT,
2384 ),
2385 KeyParameter::new(
2386 KeyParameterValue::AttestationIdMEID(vec![4u8, 3u8, 1u8, 2u8]),
2387 SecurityLevel::TRUSTED_ENVIRONMENT,
2388 ),
2389 KeyParameter::new(
2390 KeyParameterValue::AttestationIdManufacturer(vec![4u8, 3u8, 1u8, 2u8]),
2391 SecurityLevel::TRUSTED_ENVIRONMENT,
2392 ),
2393 KeyParameter::new(
2394 KeyParameterValue::AttestationIdModel(vec![4u8, 3u8, 1u8, 2u8]),
2395 SecurityLevel::TRUSTED_ENVIRONMENT,
2396 ),
2397 KeyParameter::new(
2398 KeyParameterValue::VendorPatchLevel(3),
2399 SecurityLevel::TRUSTED_ENVIRONMENT,
2400 ),
2401 KeyParameter::new(
2402 KeyParameterValue::BootPatchLevel(4),
2403 SecurityLevel::TRUSTED_ENVIRONMENT,
2404 ),
2405 KeyParameter::new(
2406 KeyParameterValue::AssociatedData(vec![4u8, 3u8, 1u8, 2u8]),
2407 SecurityLevel::TRUSTED_ENVIRONMENT,
2408 ),
2409 KeyParameter::new(
2410 KeyParameterValue::Nonce(vec![4u8, 3u8, 1u8, 2u8]),
2411 SecurityLevel::TRUSTED_ENVIRONMENT,
2412 ),
2413 KeyParameter::new(
2414 KeyParameterValue::MacLength(256),
2415 SecurityLevel::TRUSTED_ENVIRONMENT,
2416 ),
2417 KeyParameter::new(
2418 KeyParameterValue::ResetSinceIdRotation,
2419 SecurityLevel::TRUSTED_ENVIRONMENT,
2420 ),
2421 KeyParameter::new(
2422 KeyParameterValue::ConfirmationToken(vec![5u8, 5u8, 5u8, 5u8]),
2423 SecurityLevel::TRUSTED_ENVIRONMENT,
2424 ),
2425 ]
2426 }
2427
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002428 fn make_test_key_entry(
2429 db: &mut KeystoreDB,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002430 domain: Domain,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002431 namespace: i64,
2432 alias: &str,
Janis Danisevskisaec14592020-11-12 09:41:49 -08002433 ) -> Result<KeyIdGuard> {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002434 let key_id = db.create_key_entry(domain, namespace)?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002435 db.insert_blob(
Janis Danisevskisaec14592020-11-12 09:41:49 -08002436 &key_id,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002437 SubComponentType::KEY_BLOB,
2438 TEST_KEY_BLOB,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002439 SecurityLevel::TRUSTED_ENVIRONMENT,
2440 )?;
2441 db.insert_blob(
Janis Danisevskisaec14592020-11-12 09:41:49 -08002442 &key_id,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002443 SubComponentType::CERT,
2444 TEST_CERT_BLOB,
2445 SecurityLevel::TRUSTED_ENVIRONMENT,
2446 )?;
2447 db.insert_blob(
Janis Danisevskisaec14592020-11-12 09:41:49 -08002448 &key_id,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002449 SubComponentType::CERT_CHAIN,
2450 TEST_CERT_CHAIN_BLOB,
2451 SecurityLevel::TRUSTED_ENVIRONMENT,
2452 )?;
Janis Danisevskisaec14592020-11-12 09:41:49 -08002453 db.insert_keyparameter(&key_id, &make_test_params())?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002454 let mut metadata = KeyMetaData::new();
2455 metadata.add(KeyMetaEntry::EncryptedBy(EncryptedBy::Password));
2456 metadata.add(KeyMetaEntry::Salt(vec![1, 2, 3]));
2457 metadata.add(KeyMetaEntry::Iv(vec![2, 3, 1]));
2458 metadata.add(KeyMetaEntry::AeadTag(vec![3, 1, 2]));
2459 db.insert_key_metadata(&key_id, &metadata)?;
Janis Danisevskisaec14592020-11-12 09:41:49 -08002460 db.rebind_alias(&key_id, alias, domain, namespace)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002461 Ok(key_id)
2462 }
2463
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002464 fn make_test_key_entry_test_vector(key_id: i64) -> KeyEntry {
2465 let mut metadata = KeyMetaData::new();
2466 metadata.add(KeyMetaEntry::EncryptedBy(EncryptedBy::Password));
2467 metadata.add(KeyMetaEntry::Salt(vec![1, 2, 3]));
2468 metadata.add(KeyMetaEntry::Iv(vec![2, 3, 1]));
2469 metadata.add(KeyMetaEntry::AeadTag(vec![3, 1, 2]));
2470
2471 KeyEntry {
2472 id: key_id,
2473 km_blob: Some(TEST_KEY_BLOB.to_vec()),
2474 cert: Some(TEST_CERT_BLOB.to_vec()),
2475 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
2476 sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
2477 parameters: make_test_params(),
2478 metadata,
2479 }
2480 }
2481
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002482 fn debug_dump_keyentry_table(db: &mut KeystoreDB) -> Result<()> {
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002483 let mut stmt = db
2484 .conn
2485 .prepare("SELECT id, key_type, domain, namespace, alias FROM persistent.keyentry;")?;
2486 let rows = stmt.query_map::<(i64, KeyType, i32, i64, String), _, _>(NO_PARAMS, |row| {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002487 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?, row.get(4)?))
2488 })?;
2489
2490 println!("Key entry table rows:");
2491 for r in rows {
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002492 let (id, key_type, domain, namespace, alias) = r.unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002493 println!(
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002494 " id: {} KeyType: {:?} Domain: {} Namespace: {} Alias: {}",
2495 id, key_type, domain, namespace, alias
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002496 );
2497 }
2498 Ok(())
2499 }
2500
2501 fn debug_dump_grant_table(db: &mut KeystoreDB) -> Result<()> {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002502 let mut stmt = db
2503 .conn
2504 .prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002505 let rows = stmt.query_map::<(i64, i64, i64, i64), _, _>(NO_PARAMS, |row| {
2506 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?))
2507 })?;
2508
2509 println!("Grant table rows:");
2510 for r in rows {
2511 let (id, gt, ki, av) = r.unwrap();
2512 println!(" id: {} grantee: {} key_id: {} access_vector: {}", id, gt, ki, av);
2513 }
2514 Ok(())
2515 }
2516
Joel Galenson0891bc12020-07-20 10:37:03 -07002517 // Use a custom random number generator that repeats each number once.
2518 // This allows us to test repeated elements.
2519
2520 thread_local! {
2521 static RANDOM_COUNTER: RefCell<i64> = RefCell::new(0);
2522 }
2523
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002524 fn reset_random() {
2525 RANDOM_COUNTER.with(|counter| {
2526 *counter.borrow_mut() = 0;
2527 })
2528 }
2529
Joel Galenson0891bc12020-07-20 10:37:03 -07002530 pub fn random() -> i64 {
2531 RANDOM_COUNTER.with(|counter| {
2532 let result = *counter.borrow() / 2;
2533 *counter.borrow_mut() += 1;
2534 result
2535 })
2536 }
Joel Galenson26f4d012020-07-17 14:57:21 -07002537}