blob: df1c24c1925b1ba51a4e8d6c356d8d1e635aab3d [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 Danisevskisc5b210b2020-09-11 13:27:37 -070049use crate::error::{Error as KsError, ResponseCode};
Janis Danisevskisb42fc182020-12-15 08:41:27 -080050use crate::impl_metadata; // This is in db_utils.rs
Janis Danisevskis4522c2b2020-11-27 18:04:58 -080051use crate::key_parameter::{KeyParameter, Tag};
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070052use crate::permission::KeyPermSet;
Hasini Gunasinghe557b1032020-11-10 01:35:30 +000053use crate::utils::get_current_time_in_seconds;
Janis Danisevskis93927dd2020-12-23 12:23:08 -080054use crate::{
55 db_utils::{self, SqlField},
56 gc::Gc,
57};
Janis Danisevskisb42fc182020-12-15 08:41:27 -080058use anyhow::{anyhow, Context, Result};
59use std::{convert::TryFrom, convert::TryInto, time::SystemTimeError};
Janis Danisevskis60400fe2020-08-26 15:24:42 -070060
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +000061use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
62 HardwareAuthToken::HardwareAuthToken, HardwareAuthenticatorType::HardwareAuthenticatorType,
63 SecurityLevel::SecurityLevel,
64};
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070065use android_system_keystore2::aidl::android::system::keystore2::{
Janis Danisevskis04b02832020-10-26 09:21:40 -070066 Domain::Domain, KeyDescriptor::KeyDescriptor,
Janis Danisevskis60400fe2020-08-26 15:24:42 -070067};
68
Janis Danisevskisaec14592020-11-12 09:41:49 -080069use lazy_static::lazy_static;
Joel Galenson0891bc12020-07-20 10:37:03 -070070#[cfg(not(test))]
71use rand::prelude::random;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070072use rusqlite::{
Janis Danisevskisb42fc182020-12-15 08:41:27 -080073 params,
74 types::FromSql,
75 types::FromSqlResult,
76 types::ToSqlOutput,
77 types::{FromSqlError, Value, ValueRef},
78 Connection, OptionalExtension, ToSql, Transaction, TransactionBehavior, NO_PARAMS,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070079};
Janis Danisevskisaec14592020-11-12 09:41:49 -080080use std::{
Janis Danisevskisb42fc182020-12-15 08:41:27 -080081 collections::{HashMap, HashSet},
Janis Danisevskisbf15d732020-12-08 10:35:26 -080082 path::Path,
83 sync::{Condvar, Mutex},
Janis Danisevskisb42fc182020-12-15 08:41:27 -080084 time::{Duration, SystemTime},
Janis Danisevskisaec14592020-11-12 09:41:49 -080085};
Joel Galenson0891bc12020-07-20 10:37:03 -070086#[cfg(test)]
87use tests::random;
Joel Galenson26f4d012020-07-17 14:57:21 -070088
Janis Danisevskisb42fc182020-12-15 08:41:27 -080089impl_metadata!(
90 /// A set of metadata for key entries.
91 #[derive(Debug, Default, Eq, PartialEq)]
92 pub struct KeyMetaData;
93 /// A metadata entry for key entries.
94 #[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
95 pub enum KeyMetaEntry {
96 /// If present, indicates that the sensitive part of key
97 /// is encrypted with another key or a key derived from a password.
98 EncryptedBy(EncryptedBy) with accessor encrypted_by,
99 /// If the blob is password encrypted this field is set to the
100 /// salt used for the key derivation.
101 Salt(Vec<u8>) with accessor salt,
102 /// If the blob is encrypted, this field is set to the initialization vector.
103 Iv(Vec<u8>) with accessor iv,
104 /// If the blob is encrypted, this field holds the AEAD TAG.
105 AeadTag(Vec<u8>) with accessor aead_tag,
106 /// Creation date of a the key entry.
107 CreationDate(DateTime) with accessor creation_date,
108 /// Expiration date for attestation keys.
109 AttestationExpirationDate(DateTime) with accessor attestation_expiration_date,
110 // --- ADD NEW META DATA FIELDS HERE ---
111 // For backwards compatibility add new entries only to
112 // end of this list and above this comment.
113 };
114);
115
116impl KeyMetaData {
117 fn load_from_db(key_id: i64, tx: &Transaction) -> Result<Self> {
118 let mut stmt = tx
119 .prepare(
120 "SELECT tag, data from persistent.keymetadata
121 WHERE keyentryid = ?;",
122 )
123 .context("In KeyMetaData::load_from_db: prepare statement failed.")?;
124
125 let mut metadata: HashMap<i64, KeyMetaEntry> = Default::default();
126
127 let mut rows =
128 stmt.query(params![key_id]).context("In KeyMetaData::load_from_db: query failed.")?;
129 db_utils::with_rows_extract_all(&mut rows, |row| {
130 let db_tag: i64 = row.get(0).context("Failed to read tag.")?;
131 metadata.insert(
132 db_tag,
133 KeyMetaEntry::new_from_sql(db_tag, &SqlField::new(1, &row))
134 .context("Failed to read KeyMetaEntry.")?,
135 );
136 Ok(())
137 })
138 .context("In KeyMetaData::load_from_db.")?;
139
140 Ok(Self { data: metadata })
141 }
142
143 fn store_in_db(&self, key_id: i64, tx: &Transaction) -> Result<()> {
144 let mut stmt = tx
145 .prepare(
146 "INSERT into persistent.keymetadata (keyentryid, tag, data)
147 VALUES (?, ?, ?);",
148 )
149 .context("In KeyMetaData::store_in_db: Failed to prepare statement.")?;
150
151 let iter = self.data.iter();
152 for (tag, entry) in iter {
153 stmt.insert(params![key_id, tag, entry,]).with_context(|| {
154 format!("In KeyMetaData::store_in_db: Failed to insert {:?}", entry)
155 })?;
156 }
157 Ok(())
158 }
159}
160
161/// Indicates the type of the keyentry.
162#[derive(Debug, Copy, Clone, Eq, PartialEq, Ord, PartialOrd)]
163pub enum KeyType {
164 /// This is a client key type. These keys are created or imported through the Keystore 2.0
165 /// AIDL interface android.system.keystore2.
166 Client,
167 /// This is a super key type. These keys are created by keystore itself and used to encrypt
168 /// other key blobs to provide LSKF binding.
169 Super,
170 /// This is an attestation key. These keys are created by the remote provisioning mechanism.
171 Attestation,
172}
173
174impl ToSql for KeyType {
175 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
176 Ok(ToSqlOutput::Owned(Value::Integer(match self {
177 KeyType::Client => 0,
178 KeyType::Super => 1,
179 KeyType::Attestation => 2,
180 })))
181 }
182}
183
184impl FromSql for KeyType {
185 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
186 match i64::column_result(value)? {
187 0 => Ok(KeyType::Client),
188 1 => Ok(KeyType::Super),
189 2 => Ok(KeyType::Attestation),
190 v => Err(FromSqlError::OutOfRange(v)),
191 }
192 }
193}
194
195/// Indicates how the sensitive part of this key blob is encrypted.
196#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
197pub enum EncryptedBy {
198 /// The keyblob is encrypted by a user password.
199 /// In the database this variant is represented as NULL.
200 Password,
201 /// The keyblob is encrypted by another key with wrapped key id.
202 /// In the database this variant is represented as non NULL value
203 /// that is convertible to i64, typically NUMERIC.
204 KeyId(i64),
205}
206
207impl ToSql for EncryptedBy {
208 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
209 match self {
210 Self::Password => Ok(ToSqlOutput::Owned(Value::Null)),
211 Self::KeyId(id) => id.to_sql(),
212 }
213 }
214}
215
216impl FromSql for EncryptedBy {
217 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
218 match value {
219 ValueRef::Null => Ok(Self::Password),
220 _ => Ok(Self::KeyId(i64::column_result(value)?)),
221 }
222 }
223}
224
225/// A database representation of wall clock time. DateTime stores unix epoch time as
226/// i64 in milliseconds.
227#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)]
228pub struct DateTime(i64);
229
230/// Error type returned when creating DateTime or converting it from and to
231/// SystemTime.
232#[derive(thiserror::Error, Debug)]
233pub enum DateTimeError {
234 /// This is returned when SystemTime and Duration computations fail.
235 #[error(transparent)]
236 SystemTimeError(#[from] SystemTimeError),
237
238 /// This is returned when type conversions fail.
239 #[error(transparent)]
240 TypeConversion(#[from] std::num::TryFromIntError),
241
242 /// This is returned when checked time arithmetic failed.
243 #[error("Time arithmetic failed.")]
244 TimeArithmetic,
245}
246
247impl DateTime {
248 /// Constructs a new DateTime object denoting the current time. This may fail during
249 /// conversion to unix epoch time and during conversion to the internal i64 representation.
250 pub fn now() -> Result<Self, DateTimeError> {
251 Ok(Self(SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_millis().try_into()?))
252 }
253
254 /// Constructs a new DateTime object from milliseconds.
255 pub fn from_millis_epoch(millis: i64) -> Self {
256 Self(millis)
257 }
258
259 /// Returns unix epoch time in milliseconds.
260 pub fn to_millis_epoch(&self) -> i64 {
261 self.0
262 }
263
264 /// Returns unix epoch time in seconds.
265 pub fn to_secs_epoch(&self) -> i64 {
266 self.0 / 1000
267 }
268}
269
270impl ToSql for DateTime {
271 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
272 Ok(ToSqlOutput::Owned(Value::Integer(self.0)))
273 }
274}
275
276impl FromSql for DateTime {
277 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
278 Ok(Self(i64::column_result(value)?))
279 }
280}
281
282impl TryInto<SystemTime> for DateTime {
283 type Error = DateTimeError;
284
285 fn try_into(self) -> Result<SystemTime, Self::Error> {
286 // We want to construct a SystemTime representation equivalent to self, denoting
287 // a point in time THEN, but we cannot set the time directly. We can only construct
288 // a SystemTime denoting NOW, and we can get the duration between EPOCH and NOW,
289 // and between EPOCH and THEN. With this common reference we can construct the
290 // duration between NOW and THEN which we can add to our SystemTime representation
291 // of NOW to get a SystemTime representation of THEN.
292 // Durations can only be positive, thus the if statement below.
293 let now = SystemTime::now();
294 let now_epoch = now.duration_since(SystemTime::UNIX_EPOCH)?;
295 let then_epoch = Duration::from_millis(self.0.try_into()?);
296 Ok(if now_epoch > then_epoch {
297 // then = now - (now_epoch - then_epoch)
298 now_epoch
299 .checked_sub(then_epoch)
300 .and_then(|d| now.checked_sub(d))
301 .ok_or(DateTimeError::TimeArithmetic)?
302 } else {
303 // then = now + (then_epoch - now_epoch)
304 then_epoch
305 .checked_sub(now_epoch)
306 .and_then(|d| now.checked_add(d))
307 .ok_or(DateTimeError::TimeArithmetic)?
308 })
309 }
310}
311
312impl TryFrom<SystemTime> for DateTime {
313 type Error = DateTimeError;
314
315 fn try_from(t: SystemTime) -> Result<Self, Self::Error> {
316 Ok(Self(t.duration_since(SystemTime::UNIX_EPOCH)?.as_millis().try_into()?))
317 }
318}
319
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800320#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
321enum KeyLifeCycle {
322 /// Existing keys have a key ID but are not fully populated yet.
323 /// This is a transient state. If Keystore finds any such keys when it starts up, it must move
324 /// them to Unreferenced for garbage collection.
325 Existing,
326 /// A live key is fully populated and usable by clients.
327 Live,
328 /// An unreferenced key is scheduled for garbage collection.
329 Unreferenced,
330}
331
332impl ToSql for KeyLifeCycle {
333 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
334 match self {
335 Self::Existing => Ok(ToSqlOutput::Owned(Value::Integer(0))),
336 Self::Live => Ok(ToSqlOutput::Owned(Value::Integer(1))),
337 Self::Unreferenced => Ok(ToSqlOutput::Owned(Value::Integer(2))),
338 }
339 }
340}
341
342impl FromSql for KeyLifeCycle {
343 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
344 match i64::column_result(value)? {
345 0 => Ok(KeyLifeCycle::Existing),
346 1 => Ok(KeyLifeCycle::Live),
347 2 => Ok(KeyLifeCycle::Unreferenced),
348 v => Err(FromSqlError::OutOfRange(v)),
349 }
350 }
351}
352
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700353/// Keys have a KeyMint blob component and optional public certificate and
354/// certificate chain components.
355/// KeyEntryLoadBits is a bitmap that indicates to `KeystoreDB::load_key_entry`
356/// which components shall be loaded from the database if present.
357#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
358pub struct KeyEntryLoadBits(u32);
359
360impl KeyEntryLoadBits {
361 /// Indicate to `KeystoreDB::load_key_entry` that no component shall be loaded.
362 pub const NONE: KeyEntryLoadBits = Self(0);
363 /// Indicate to `KeystoreDB::load_key_entry` that the KeyMint component shall be loaded.
364 pub const KM: KeyEntryLoadBits = Self(1);
365 /// Indicate to `KeystoreDB::load_key_entry` that the Public components shall be loaded.
366 pub const PUBLIC: KeyEntryLoadBits = Self(2);
367 /// Indicate to `KeystoreDB::load_key_entry` that both components shall be loaded.
368 pub const BOTH: KeyEntryLoadBits = Self(3);
369
370 /// Returns true if this object indicates that the public components shall be loaded.
371 pub const fn load_public(&self) -> bool {
372 self.0 & Self::PUBLIC.0 != 0
373 }
374
375 /// Returns true if the object indicates that the KeyMint component shall be loaded.
376 pub const fn load_km(&self) -> bool {
377 self.0 & Self::KM.0 != 0
378 }
379}
380
Janis Danisevskisaec14592020-11-12 09:41:49 -0800381lazy_static! {
382 static ref KEY_ID_LOCK: KeyIdLockDb = KeyIdLockDb::new();
383}
384
385struct KeyIdLockDb {
386 locked_keys: Mutex<HashSet<i64>>,
387 cond_var: Condvar,
388}
389
390/// A locked key. While a guard exists for a given key id, the same key cannot be loaded
391/// from the database a second time. Most functions manipulating the key blob database
392/// require a KeyIdGuard.
393#[derive(Debug)]
394pub struct KeyIdGuard(i64);
395
396impl KeyIdLockDb {
397 fn new() -> Self {
398 Self { locked_keys: Mutex::new(HashSet::new()), cond_var: Condvar::new() }
399 }
400
401 /// This function blocks until an exclusive lock for the given key entry id can
402 /// be acquired. It returns a guard object, that represents the lifecycle of the
403 /// acquired lock.
404 pub fn get(&self, key_id: i64) -> KeyIdGuard {
405 let mut locked_keys = self.locked_keys.lock().unwrap();
406 while locked_keys.contains(&key_id) {
407 locked_keys = self.cond_var.wait(locked_keys).unwrap();
408 }
409 locked_keys.insert(key_id);
410 KeyIdGuard(key_id)
411 }
412
413 /// This function attempts to acquire an exclusive lock on a given key id. If the
414 /// given key id is already taken the function returns None immediately. If a lock
415 /// can be acquired this function returns a guard object, that represents the
416 /// lifecycle of the acquired lock.
417 pub fn try_get(&self, key_id: i64) -> Option<KeyIdGuard> {
418 let mut locked_keys = self.locked_keys.lock().unwrap();
419 if locked_keys.insert(key_id) {
420 Some(KeyIdGuard(key_id))
421 } else {
422 None
423 }
424 }
425}
426
427impl KeyIdGuard {
428 /// Get the numeric key id of the locked key.
429 pub fn id(&self) -> i64 {
430 self.0
431 }
432}
433
434impl Drop for KeyIdGuard {
435 fn drop(&mut self) {
436 let mut locked_keys = KEY_ID_LOCK.locked_keys.lock().unwrap();
437 locked_keys.remove(&self.0);
Janis Danisevskis7fd53582020-11-23 13:40:34 -0800438 drop(locked_keys);
Janis Danisevskisaec14592020-11-12 09:41:49 -0800439 KEY_ID_LOCK.cond_var.notify_all();
440 }
441}
442
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700443/// This type represents a Keystore 2.0 key entry.
444/// An entry has a unique `id` by which it can be found in the database.
445/// It has a security level field, key parameters, and three optional fields
446/// for the KeyMint blob, public certificate and a public certificate chain.
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800447#[derive(Debug, Default, Eq, PartialEq)]
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700448pub struct KeyEntry {
449 id: i64,
450 km_blob: Option<Vec<u8>>,
451 cert: Option<Vec<u8>>,
452 cert_chain: Option<Vec<u8>>,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700453 sec_level: SecurityLevel,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700454 parameters: Vec<KeyParameter>,
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800455 metadata: KeyMetaData,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700456}
457
458impl KeyEntry {
459 /// Returns the unique id of the Key entry.
460 pub fn id(&self) -> i64 {
461 self.id
462 }
463 /// Exposes the optional KeyMint blob.
464 pub fn km_blob(&self) -> &Option<Vec<u8>> {
465 &self.km_blob
466 }
467 /// Extracts the Optional KeyMint blob.
468 pub fn take_km_blob(&mut self) -> Option<Vec<u8>> {
469 self.km_blob.take()
470 }
471 /// Exposes the optional public certificate.
472 pub fn cert(&self) -> &Option<Vec<u8>> {
473 &self.cert
474 }
475 /// Extracts the optional public certificate.
476 pub fn take_cert(&mut self) -> Option<Vec<u8>> {
477 self.cert.take()
478 }
479 /// Exposes the optional public certificate chain.
480 pub fn cert_chain(&self) -> &Option<Vec<u8>> {
481 &self.cert_chain
482 }
483 /// Extracts the optional public certificate_chain.
484 pub fn take_cert_chain(&mut self) -> Option<Vec<u8>> {
485 self.cert_chain.take()
486 }
487 /// Returns the security level of the key entry.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700488 pub fn sec_level(&self) -> SecurityLevel {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700489 self.sec_level
490 }
Janis Danisevskis04b02832020-10-26 09:21:40 -0700491 /// Exposes the key parameters of this key entry.
492 pub fn key_parameters(&self) -> &Vec<KeyParameter> {
493 &self.parameters
494 }
495 /// Consumes this key entry and extracts the keyparameters from it.
496 pub fn into_key_parameters(self) -> Vec<KeyParameter> {
497 self.parameters
498 }
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800499 /// Exposes the key metadata of this key entry.
500 pub fn metadata(&self) -> &KeyMetaData {
501 &self.metadata
502 }
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700503}
504
505/// Indicates the sub component of a key entry for persistent storage.
506#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
507pub struct SubComponentType(u32);
508impl SubComponentType {
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800509 /// Persistent identifier for a key blob.
510 pub const KEY_BLOB: SubComponentType = Self(0);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700511 /// Persistent identifier for a certificate blob.
512 pub const CERT: SubComponentType = Self(1);
513 /// Persistent identifier for a certificate chain blob.
514 pub const CERT_CHAIN: SubComponentType = Self(2);
515}
516
517impl ToSql for SubComponentType {
518 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
519 self.0.to_sql()
520 }
521}
522
523impl FromSql for SubComponentType {
524 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
525 Ok(Self(u32::column_result(value)?))
526 }
527}
528
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700529/// KeystoreDB wraps a connection to an SQLite database and tracks its
530/// ownership. It also implements all of Keystore 2.0's database functionality.
Joel Galenson26f4d012020-07-17 14:57:21 -0700531pub struct KeystoreDB {
Joel Galenson26f4d012020-07-17 14:57:21 -0700532 conn: Connection,
533}
534
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000535/// Database representation of the monotonic time retrieved from the system call clock_gettime with
536/// CLOCK_MONOTONIC_RAW. Stores monotonic time as i64 in seconds.
537#[derive(Debug, Copy, Clone, Default, Eq, PartialEq, Ord, PartialOrd)]
538pub struct MonotonicRawTime(i64);
539
540impl MonotonicRawTime {
541 /// Constructs a new MonotonicRawTime
542 pub fn now() -> Self {
543 Self(get_current_time_in_seconds())
544 }
545
546 /// Returns the integer value of MonotonicRawTime as i64
547 pub fn seconds(&self) -> i64 {
548 self.0
549 }
550}
551
552impl ToSql for MonotonicRawTime {
553 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
554 Ok(ToSqlOutput::Owned(Value::Integer(self.0)))
555 }
556}
557
558impl FromSql for MonotonicRawTime {
559 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
560 Ok(Self(i64::column_result(value)?))
561 }
562}
563
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000564/// This struct encapsulates the information to be stored in the database about the auth tokens
565/// received by keystore.
566pub struct AuthTokenEntry {
567 auth_token: HardwareAuthToken,
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000568 time_received: MonotonicRawTime,
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000569}
570
571impl AuthTokenEntry {
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000572 fn new(auth_token: HardwareAuthToken, time_received: MonotonicRawTime) -> Self {
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000573 AuthTokenEntry { auth_token, time_received }
574 }
575
576 /// Checks if this auth token satisfies the given authentication information.
577 pub fn satisfies_auth(
578 auth_token: &HardwareAuthToken,
579 user_secure_ids: &[i64],
580 auth_type: HardwareAuthenticatorType,
581 ) -> bool {
582 user_secure_ids.iter().any(|&sid| {
583 (sid == auth_token.userId || sid == auth_token.authenticatorId)
584 && (((auth_type.0 as i32) & (auth_token.authenticatorType.0 as i32)) != 0)
585 })
586 }
587
588 fn is_newer_than(&self, other: &AuthTokenEntry) -> bool {
589 // NOTE: Although in legacy keystore both timestamp and time_received are involved in this
590 // check, we decided to only consider time_received in keystore2 code.
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000591 self.time_received.seconds() > other.time_received.seconds()
Hasini Gunasinghe52333ba2020-11-06 01:24:16 +0000592 }
593
594 /// Returns the auth token wrapped by the AuthTokenEntry
595 pub fn get_auth_token(self) -> HardwareAuthToken {
596 self.auth_token
597 }
598}
599
Joel Galenson26f4d012020-07-17 14:57:21 -0700600impl KeystoreDB {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700601 /// This will create a new database connection connecting the two
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800602 /// files persistent.sqlite and perboot.sqlite in the given directory.
603 /// It also attempts to initialize all of the tables.
604 /// KeystoreDB cannot be used by multiple threads.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700605 /// Each thread should open their own connection using `thread_local!`.
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800606 pub fn new(db_root: &Path) -> Result<Self> {
607 // Build the path to the sqlite files.
608 let mut persistent_path = db_root.to_path_buf();
609 persistent_path.push("persistent.sqlite");
610 let mut perboot_path = db_root.to_path_buf();
611 perboot_path.push("perboot.sqlite");
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700612
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800613 // Now convert them to strings prefixed with "file:"
614 let mut persistent_path_str = "file:".to_owned();
615 persistent_path_str.push_str(&persistent_path.to_string_lossy());
616 let mut perboot_path_str = "file:".to_owned();
617 perboot_path_str.push_str(&perboot_path.to_string_lossy());
618
619 let conn = Self::make_connection(&persistent_path_str, &perboot_path_str)?;
620
621 Self::init_tables(&conn)?;
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700622 Ok(Self { conn })
Joel Galenson2aab4432020-07-22 15:27:57 -0700623 }
624
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700625 fn init_tables(conn: &Connection) -> Result<()> {
626 conn.execute(
627 "CREATE TABLE IF NOT EXISTS persistent.keyentry (
Joel Galenson0891bc12020-07-20 10:37:03 -0700628 id INTEGER UNIQUE,
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800629 key_type INTEGER,
Joel Galenson0891bc12020-07-20 10:37:03 -0700630 domain INTEGER,
631 namespace INTEGER,
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800632 alias BLOB,
633 state INTEGER);",
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700634 NO_PARAMS,
635 )
636 .context("Failed to initialize \"keyentry\" table.")?;
637
638 conn.execute(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700639 "CREATE TABLE IF NOT EXISTS persistent.blobentry (
640 id INTEGER PRIMARY KEY,
641 subcomponent_type INTEGER,
642 keyentryid INTEGER,
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800643 blob BLOB);",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700644 NO_PARAMS,
645 )
646 .context("Failed to initialize \"blobentry\" table.")?;
647
648 conn.execute(
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700649 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000650 keyentryid INTEGER,
651 tag INTEGER,
652 data ANY,
653 security_level INTEGER);",
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700654 NO_PARAMS,
655 )
656 .context("Failed to initialize \"keyparameter\" table.")?;
657
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700658 conn.execute(
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800659 "CREATE TABLE IF NOT EXISTS persistent.keymetadata (
660 keyentryid INTEGER,
661 tag INTEGER,
662 data ANY);",
663 NO_PARAMS,
664 )
665 .context("Failed to initialize \"keymetadata\" table.")?;
666
667 conn.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800668 "CREATE TABLE IF NOT EXISTS persistent.grant (
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700669 id INTEGER UNIQUE,
670 grantee INTEGER,
671 keyentryid INTEGER,
672 access_vector INTEGER);",
673 NO_PARAMS,
674 )
675 .context("Failed to initialize \"grant\" table.")?;
676
Hasini Gunasinghe557b1032020-11-10 01:35:30 +0000677 //TODO: only drop the following two perboot tables if this is the first start up
678 //during the boot (b/175716626).
679 // conn.execute("DROP TABLE IF EXISTS perboot.authtoken;", NO_PARAMS)
680 // .context("Failed to drop perboot.authtoken table")?;
681 conn.execute(
682 "CREATE TABLE IF NOT EXISTS perboot.authtoken (
683 id INTEGER PRIMARY KEY,
684 challenge INTEGER,
685 user_id INTEGER,
686 auth_id INTEGER,
687 authenticator_type INTEGER,
688 timestamp INTEGER,
689 mac BLOB,
690 time_received INTEGER,
691 UNIQUE(user_id, auth_id, authenticator_type));",
692 NO_PARAMS,
693 )
694 .context("Failed to initialize \"authtoken\" table.")?;
695
696 // conn.execute("DROP TABLE IF EXISTS perboot.metadata;", NO_PARAMS)
697 // .context("Failed to drop perboot.metadata table")?;
698 // metadata table stores certain miscellaneous information required for keystore functioning
699 // during a boot cycle, as key-value pairs.
700 conn.execute(
701 "CREATE TABLE IF NOT EXISTS perboot.metadata (
702 key TEXT,
703 value BLOB,
704 UNIQUE(key));",
705 NO_PARAMS,
706 )
707 .context("Failed to initialize \"metadata\" table.")?;
708
Joel Galenson0891bc12020-07-20 10:37:03 -0700709 Ok(())
710 }
711
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700712 fn make_connection(persistent_file: &str, perboot_file: &str) -> Result<Connection> {
713 let conn =
714 Connection::open_in_memory().context("Failed to initialize SQLite connection.")?;
715
716 conn.execute("ATTACH DATABASE ? as persistent;", params![persistent_file])
717 .context("Failed to attach database persistent.")?;
718 conn.execute("ATTACH DATABASE ? as perboot;", params![perboot_file])
719 .context("Failed to attach database perboot.")?;
720
721 Ok(conn)
722 }
723
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800724 /// Get one unreferenced key. There is no particular order in which the keys are returned.
725 fn get_unreferenced_key_id(tx: &Transaction) -> Result<Option<i64>> {
726 tx.query_row(
727 "SELECT id FROM persistent.keyentry WHERE state = ?",
728 params![KeyLifeCycle::Unreferenced],
729 |row| row.get(0),
730 )
731 .optional()
732 .context("In get_unreferenced_key_id: Trying to get unreferenced key id.")
733 }
734
735 /// Returns a key id guard and key entry for one unreferenced key entry. Of the optional
736 /// fields of the key entry only the km_blob field will be populated. This is required
737 /// to subject the blob to its KeyMint instance for deletion.
738 pub fn get_unreferenced_key(&mut self) -> Result<Option<(KeyIdGuard, KeyEntry)>> {
739 self.with_transaction(TransactionBehavior::Deferred, |tx| {
740 let key_id = match Self::get_unreferenced_key_id(tx)
741 .context("Trying to get unreferenced key id")?
742 {
743 None => return Ok(None),
744 Some(id) => KEY_ID_LOCK.try_get(id).ok_or_else(KsError::sys).context(concat!(
745 "A key id lock was held for an unreferenced key. ",
746 "This should never happen."
747 ))?,
748 };
749 let key_entry = Self::load_key_components(tx, KeyEntryLoadBits::KM, key_id.id())
750 .context("Trying to get key components.")?;
751 Ok(Some((key_id, key_entry)))
752 })
753 .context("In get_unreferenced_key.")
754 }
755
756 /// This function purges all remnants of a key entry from the database.
757 /// Important: This does not check if the key was unreferenced, nor does it
758 /// subject the key to its KeyMint instance for permanent invalidation.
759 /// This function should only be called by the garbage collector.
760 /// To delete a key call `mark_unreferenced`, which transitions the key to the unreferenced
761 /// state, deletes all grants to the key, and notifies the garbage collector.
762 /// The garbage collector will:
763 /// 1. Call get_unreferenced_key.
764 /// 2. Determine the proper way to dispose of sensitive key material, e.g., call
765 /// `KeyMintDevice::delete()`.
766 /// 3. Call `purge_key_entry`.
767 pub fn purge_key_entry(&mut self, key_id: KeyIdGuard) -> Result<()> {
768 self.with_transaction(TransactionBehavior::Immediate, |tx| {
769 tx.execute("DELETE FROM persistent.keyentry WHERE id = ?;", params![key_id.id()])
770 .context("Trying to delete keyentry.")?;
771 tx.execute(
772 "DELETE FROM persistent.blobentry WHERE keyentryid = ?;",
773 params![key_id.id()],
774 )
775 .context("Trying to delete blobentries.")?;
776 tx.execute(
777 "DELETE FROM persistent.keymetadata WHERE keyentryid = ?;",
778 params![key_id.id()],
779 )
780 .context("Trying to delete keymetadata.")?;
781 tx.execute(
782 "DELETE FROM persistent.keyparameter WHERE keyentryid = ?;",
783 params![key_id.id()],
784 )
785 .context("Trying to delete keyparameters.")?;
786 let grants_deleted = tx
787 .execute("DELETE FROM persistent.grant WHERE keyentryid = ?;", params![key_id.id()])
788 .context("Trying to delete grants.")?;
789 if grants_deleted != 0 {
790 log::error!("Purged key that still had grants. This should not happen.");
791 }
792 Ok(())
793 })
794 .context("In purge_key_entry.")
795 }
796
797 /// This maintenance function should be called only once before the database is used for the
798 /// first time. It restores the invariant that `KeyLifeCycle::Existing` is a transient state.
799 /// The function transitions all key entries from Existing to Unreferenced unconditionally and
800 /// returns the number of rows affected. If this returns a value greater than 0, it means that
801 /// Keystore crashed at some point during key generation. Callers may want to log such
802 /// occurrences.
803 /// Unlike with `mark_unreferenced`, we don't need to purge grants, because only keys that made
804 /// it to `KeyLifeCycle::Live` may have grants.
805 pub fn cleanup_leftovers(&mut self) -> Result<usize> {
806 self.conn
807 .execute(
808 "UPDATE persistent.keyentry SET state = ? WHERE state = ?;",
809 params![KeyLifeCycle::Unreferenced, KeyLifeCycle::Existing],
810 )
811 .context("In cleanup_leftovers.")
812 }
813
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800814 /// Atomically loads a key entry and associated metadata or creates it using the
815 /// callback create_new_key callback. The callback is called during a database
816 /// transaction. This means that implementers should be mindful about using
817 /// blocking operations such as IPC or grabbing mutexes.
818 pub fn get_or_create_key_with<F>(
819 &mut self,
820 domain: Domain,
821 namespace: i64,
822 alias: &str,
823 create_new_key: F,
824 ) -> Result<(KeyIdGuard, KeyEntry)>
825 where
826 F: FnOnce() -> Result<(Vec<u8>, KeyMetaData)>,
827 {
828 let tx = self
829 .conn
830 .transaction_with_behavior(TransactionBehavior::Immediate)
831 .context("In get_or_create_key_with: Failed to initialize transaction.")?;
832
833 let id = {
834 let mut stmt = tx
835 .prepare(
836 "SELECT id FROM persistent.keyentry
837 WHERE
838 key_type = ?
839 AND domain = ?
840 AND namespace = ?
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800841 AND alias = ?
842 AND state = ?;",
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800843 )
844 .context("In get_or_create_key_with: Failed to select from keyentry table.")?;
845 let mut rows = stmt
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800846 .query(params![KeyType::Super, domain.0, namespace, alias, KeyLifeCycle::Live])
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800847 .context("In get_or_create_key_with: Failed to query from keyentry table.")?;
848
849 db_utils::with_rows_extract_one(&mut rows, |row| {
850 Ok(match row {
851 Some(r) => r.get(0).context("Failed to unpack id.")?,
852 None => None,
853 })
854 })
855 .context("In get_or_create_key_with.")?
856 };
857
858 let (id, entry) = match id {
859 Some(id) => (
860 id,
861 Self::load_key_components(&tx, KeyEntryLoadBits::KM, id)
862 .context("In get_or_create_key_with.")?,
863 ),
864
865 None => {
866 let id = Self::insert_with_retry(|id| {
867 tx.execute(
868 "INSERT into persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800869 (id, key_type, domain, namespace, alias, state)
870 VALUES(?, ?, ?, ?, ?, ?);",
871 params![id, KeyType::Super, domain.0, namespace, alias, KeyLifeCycle::Live],
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800872 )
873 })
874 .context("In get_or_create_key_with.")?;
875
876 let (blob, metadata) = create_new_key().context("In get_or_create_key_with.")?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800877 Self::insert_blob_internal(&tx, id, SubComponentType::KEY_BLOB, &blob)
878 .context("In get_of_create_key_with.")?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800879 metadata.store_in_db(id, &tx).context("In get_or_create_key_with.")?;
880 (id, KeyEntry { id, km_blob: Some(blob), metadata, ..Default::default() })
881 }
882 };
883 tx.commit().context("In get_or_create_key_with: Failed to commit transaction.")?;
884 Ok((KEY_ID_LOCK.get(id), entry))
885 }
886
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800887 /// Creates a transaction with the given behavior and executes f with the new transaction.
888 /// The transaction is committed only if f returns Ok.
889 fn with_transaction<T, F>(&mut self, behavior: TransactionBehavior, f: F) -> Result<T>
890 where
891 F: FnOnce(&Transaction) -> Result<T>,
892 {
893 let tx = self
894 .conn
895 .transaction_with_behavior(behavior)
896 .context("In with_transaction: Failed to initialize transaction.")?;
897 f(&tx).and_then(|result| {
898 tx.commit().context("In with_transaction: Failed to commit transaction.")?;
899 Ok(result)
900 })
901 }
902
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700903 /// Creates a new key entry and allocates a new randomized id for the new key.
904 /// The key id gets associated with a domain and namespace but not with an alias.
905 /// To complete key generation `rebind_alias` should be called after all of the
906 /// key artifacts, i.e., blobs and parameters have been associated with the new
907 /// key id. Finalizing with `rebind_alias` makes the creation of a new key entry
908 /// atomic even if key generation is not.
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800909 pub fn create_key_entry(&mut self, domain: Domain, namespace: i64) -> Result<KeyIdGuard> {
910 self.with_transaction(TransactionBehavior::Immediate, |tx| {
911 Self::create_key_entry_internal(tx, domain, namespace)
912 })
913 .context("In create_key_entry.")
914 }
915
916 fn create_key_entry_internal(
917 tx: &Transaction,
918 domain: Domain,
919 namespace: i64,
920 ) -> Result<KeyIdGuard> {
Joel Galenson0891bc12020-07-20 10:37:03 -0700921 match domain {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700922 Domain::APP | Domain::SELINUX => {}
Joel Galenson0891bc12020-07-20 10:37:03 -0700923 _ => {
924 return Err(KsError::sys())
925 .context(format!("Domain {:?} must be either App or SELinux.", domain));
926 }
927 }
Janis Danisevskisaec14592020-11-12 09:41:49 -0800928 Ok(KEY_ID_LOCK.get(
929 Self::insert_with_retry(|id| {
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800930 tx.execute(
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800931 "INSERT into persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800932 (id, key_type, domain, namespace, alias, state)
933 VALUES(?, ?, ?, ?, NULL, ?);",
934 params![
935 id,
936 KeyType::Client,
937 domain.0 as u32,
938 namespace,
939 KeyLifeCycle::Existing
940 ],
Janis Danisevskisaec14592020-11-12 09:41:49 -0800941 )
942 })
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800943 .context("In create_key_entry_internal")?,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800944 ))
Joel Galenson26f4d012020-07-17 14:57:21 -0700945 }
Joel Galenson33c04ad2020-08-03 11:04:38 -0700946
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700947 /// Inserts a new blob and associates it with the given key id. Each blob
948 /// has a sub component type and a security level.
949 /// Each key can have one of each sub component type associated. If more
950 /// are added only the most recent can be retrieved, and superseded blobs
951 /// will get garbage collected. The security level field of components
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800952 /// other than `SubComponentType::KEY_BLOB` are ignored.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700953 pub fn insert_blob(
954 &mut self,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800955 key_id: &KeyIdGuard,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700956 sc_type: SubComponentType,
957 blob: &[u8],
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700958 ) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800959 self.with_transaction(TransactionBehavior::Immediate, |tx| {
960 Self::insert_blob_internal(&tx, key_id.0, sc_type, blob)
961 })
962 .context("In insert_blob.")
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800963 }
964
965 fn insert_blob_internal(
966 tx: &Transaction,
967 key_id: i64,
968 sc_type: SubComponentType,
969 blob: &[u8],
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800970 ) -> Result<()> {
971 tx.execute(
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800972 "INSERT into persistent.blobentry (subcomponent_type, keyentryid, blob)
973 VALUES (?, ?, ?);",
974 params![sc_type, key_id, blob],
Janis Danisevskisb42fc182020-12-15 08:41:27 -0800975 )
976 .context("In insert_blob_internal: Failed to insert blob.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700977 Ok(())
978 }
979
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700980 /// Inserts a collection of key parameters into the `persistent.keyparameter` table
981 /// and associates them with the given `key_id`.
982 pub fn insert_keyparameter<'a>(
983 &mut self,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800984 key_id: &KeyIdGuard,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700985 params: impl IntoIterator<Item = &'a KeyParameter>,
986 ) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800987 self.with_transaction(TransactionBehavior::Immediate, |tx| {
988 Self::insert_keyparameter_internal(tx, key_id, params)
989 })
990 .context("In insert_keyparameter.")
991 }
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700992
Janis Danisevskis93927dd2020-12-23 12:23:08 -0800993 fn insert_keyparameter_internal<'a>(
994 tx: &Transaction,
995 key_id: &KeyIdGuard,
996 params: impl IntoIterator<Item = &'a KeyParameter>,
997 ) -> Result<()> {
998 let mut stmt = tx
999 .prepare(
1000 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
1001 VALUES (?, ?, ?, ?);",
1002 )
1003 .context("In insert_keyparameter_internal: Failed to prepare statement.")?;
1004
1005 let iter = params.into_iter();
1006 for p in iter {
1007 stmt.insert(params![
1008 key_id.0,
1009 p.get_tag().0,
1010 p.key_parameter_value(),
1011 p.security_level().0
1012 ])
1013 .with_context(|| {
1014 format!("In insert_keyparameter_internal: Failed to insert {:?}", p)
1015 })?;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001016 }
1017 Ok(())
1018 }
1019
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001020 /// Insert a set of key entry specific metadata into the database.
1021 pub fn insert_key_metadata(
1022 &mut self,
1023 key_id: &KeyIdGuard,
1024 metadata: &KeyMetaData,
1025 ) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001026 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1027 metadata.store_in_db(key_id.0, &tx)
1028 })
1029 .context("In insert_key_metadata.")
1030 }
1031
1032 fn rebind_alias(
1033 &mut self,
1034 newid: &KeyIdGuard,
1035 alias: &str,
1036 domain: Domain,
1037 namespace: i64,
1038 ) -> Result<()> {
1039 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1040 Self::rebind_alias_internal(tx, newid, alias, domain, namespace)
1041 })
1042 .context("In rebind_alias.")
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001043 }
1044
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001045 /// Updates the alias column of the given key id `newid` with the given alias,
1046 /// and atomically, removes the alias, domain, and namespace from another row
1047 /// with the same alias-domain-namespace tuple if such row exits.
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001048 fn rebind_alias_internal(
1049 tx: &Transaction,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001050 newid: &KeyIdGuard,
Joel Galenson33c04ad2020-08-03 11:04:38 -07001051 alias: &str,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001052 domain: Domain,
Joel Galenson33c04ad2020-08-03 11:04:38 -07001053 namespace: i64,
1054 ) -> Result<()> {
1055 match domain {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001056 Domain::APP | Domain::SELINUX => {}
Joel Galenson33c04ad2020-08-03 11:04:38 -07001057 _ => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001058 return Err(KsError::sys()).context(format!(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001059 "In rebind_alias_internal: Domain {:?} must be either App or SELinux.",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001060 domain
1061 ));
Joel Galenson33c04ad2020-08-03 11:04:38 -07001062 }
1063 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001064 let updated = tx
1065 .execute(
1066 "UPDATE persistent.keyentry
1067 SET alias = NULL, domain = NULL, namespace = NULL, state = ?
Joel Galenson33c04ad2020-08-03 11:04:38 -07001068 WHERE alias = ? AND domain = ? AND namespace = ?;",
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001069 params![KeyLifeCycle::Unreferenced, alias, domain.0 as u32, namespace],
1070 )
1071 .context("In rebind_alias_internal: Failed to rebind existing entry.")?;
1072 if updated != 0 {
1073 Gc::notify_gc();
1074 }
Joel Galenson33c04ad2020-08-03 11:04:38 -07001075 let result = tx
1076 .execute(
1077 "UPDATE persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001078 SET alias = ?, state = ?
1079 WHERE id = ? AND domain = ? AND namespace = ? AND state = ?;",
1080 params![
1081 alias,
1082 KeyLifeCycle::Live,
1083 newid.0,
1084 domain.0 as u32,
1085 namespace,
1086 KeyLifeCycle::Existing
1087 ],
Joel Galenson33c04ad2020-08-03 11:04:38 -07001088 )
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001089 .context("In rebind_alias_internal: Failed to set alias.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07001090 if result != 1 {
Joel Galenson33c04ad2020-08-03 11:04:38 -07001091 return Err(KsError::sys()).context(format!(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001092 "In rebind_alias_internal: Expected to update a single entry but instead updated {}.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07001093 result
1094 ));
1095 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001096 Ok(())
1097 }
1098
1099 /// Store a new key in a single transaction.
1100 /// The function creates a new key entry, populates the blob, key parameter, and metadata
1101 /// fields, and rebinds the given alias to the new key.
1102 pub fn store_new_key<'a>(
1103 &mut self,
1104 key: KeyDescriptor,
1105 params: impl IntoIterator<Item = &'a KeyParameter>,
1106 blob: &[u8],
1107 cert: Option<&[u8]>,
1108 cert_chain: Option<&[u8]>,
1109 metadata: &KeyMetaData,
1110 ) -> Result<KeyIdGuard> {
1111 let (alias, domain, namespace) = match key {
1112 KeyDescriptor { alias: Some(alias), domain: Domain::APP, nspace, blob: None }
1113 | KeyDescriptor { alias: Some(alias), domain: Domain::SELINUX, nspace, blob: None } => {
1114 (alias, key.domain, nspace)
1115 }
1116 _ => {
1117 return Err(KsError::Rc(ResponseCode::INVALID_ARGUMENT))
1118 .context("In store_new_key: Need alias and domain must be APP or SELINUX.")
1119 }
1120 };
1121 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1122 let key_id = Self::create_key_entry_internal(tx, domain, namespace)
1123 .context("Trying to create new key entry.")?;
1124 Self::insert_blob_internal(tx, key_id.id(), SubComponentType::KEY_BLOB, blob)
1125 .context("Trying to insert the key blob.")?;
1126 if let Some(cert) = cert {
1127 Self::insert_blob_internal(tx, key_id.id(), SubComponentType::CERT, cert)
1128 .context("Trying to insert the certificate.")?;
1129 }
1130 if let Some(cert_chain) = cert_chain {
1131 Self::insert_blob_internal(
1132 tx,
1133 key_id.id(),
1134 SubComponentType::CERT_CHAIN,
1135 cert_chain,
1136 )
1137 .context("Trying to insert the certificate chain.")?;
1138 }
1139 Self::insert_keyparameter_internal(tx, &key_id, params)
1140 .context("Trying to insert key parameters.")?;
1141 metadata.store_in_db(key_id.id(), tx).context("Tryin to insert key metadata.")?;
1142 Self::rebind_alias_internal(tx, &key_id, &alias, domain, namespace)
1143 .context("Trying to rebind alias.")?;
1144 Ok(key_id)
1145 })
1146 .context("In store_new_key.")
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001147 }
1148
1149 // Helper function loading the key_id given the key descriptor
1150 // tuple comprising domain, namespace, and alias.
1151 // Requires a valid transaction.
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001152 fn load_key_entry_id(tx: &Transaction, key: &KeyDescriptor, key_type: KeyType) -> Result<i64> {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001153 let alias = key
1154 .alias
1155 .as_ref()
1156 .map_or_else(|| Err(KsError::sys()), Ok)
1157 .context("In load_key_entry_id: Alias must be specified.")?;
1158 let mut stmt = tx
1159 .prepare(
1160 "SELECT id FROM persistent.keyentry
1161 WHERE
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001162 key_type = ?
1163 AND domain = ?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001164 AND namespace = ?
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001165 AND alias = ?
1166 AND state = ?;",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001167 )
1168 .context("In load_key_entry_id: Failed to select from keyentry table.")?;
1169 let mut rows = stmt
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001170 .query(params![key_type, key.domain.0 as u32, key.nspace, alias, KeyLifeCycle::Live])
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001171 .context("In load_key_entry_id: Failed to read from keyentry table.")?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001172 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001173 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001174 .get(0)
1175 .context("Failed to unpack id.")
1176 })
1177 .context("In load_key_entry_id.")
1178 }
1179
1180 /// This helper function completes the access tuple of a key, which is required
1181 /// to perform access control. The strategy depends on the `domain` field in the
1182 /// key descriptor.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001183 /// * Domain::SELINUX: The access tuple is complete and this function only loads
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001184 /// the key_id for further processing.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001185 /// * Domain::APP: Like Domain::SELINUX, but the tuple is completed by `caller_uid`
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001186 /// which serves as the namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001187 /// * Domain::GRANT: The grant table is queried for the `key_id` and the
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001188 /// `access_vector`.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001189 /// * Domain::KEY_ID: The keyentry table is queried for the owning `domain` and
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001190 /// `namespace`.
1191 /// In each case the information returned is sufficient to perform the access
1192 /// check and the key id can be used to load further key artifacts.
1193 fn load_access_tuple(
1194 tx: &Transaction,
1195 key: KeyDescriptor,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001196 key_type: KeyType,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001197 caller_uid: u32,
1198 ) -> Result<(i64, KeyDescriptor, Option<KeyPermSet>)> {
1199 match key.domain {
1200 // Domain App or SELinux. In this case we load the key_id from
1201 // the keyentry database for further loading of key components.
1202 // We already have the full access tuple to perform access control.
1203 // The only distinction is that we use the caller_uid instead
1204 // of the caller supplied namespace if the domain field is
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001205 // Domain::APP.
1206 Domain::APP | Domain::SELINUX => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001207 let mut access_key = key;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001208 if access_key.domain == Domain::APP {
1209 access_key.nspace = caller_uid as i64;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001210 }
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001211 let key_id = Self::load_key_entry_id(&tx, &access_key, key_type)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001212 .with_context(|| format!("With key.domain = {:?}.", access_key.domain))?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001213
1214 Ok((key_id, access_key, None))
1215 }
1216
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001217 // Domain::GRANT. In this case we load the key_id and the access_vector
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001218 // from the grant table.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001219 Domain::GRANT => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001220 let mut stmt = tx
1221 .prepare(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001222 "SELECT keyentryid, access_vector FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001223 WHERE grantee = ? AND id = ?;",
1224 )
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001225 .context("Domain::GRANT prepare statement failed")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001226 let mut rows = stmt
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001227 .query(params![caller_uid as i64, key.nspace])
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001228 .context("Domain:Grant: query failed.")?;
1229 let (key_id, access_vector): (i64, i32) =
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001230 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001231 let r =
1232 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001233 Ok((
1234 r.get(0).context("Failed to unpack key_id.")?,
1235 r.get(1).context("Failed to unpack access_vector.")?,
1236 ))
1237 })
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001238 .context("Domain::GRANT.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001239 Ok((key_id, key, Some(access_vector.into())))
1240 }
1241
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001242 // Domain::KEY_ID. In this case we load the domain and namespace from the
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001243 // keyentry database because we need them for access control.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001244 Domain::KEY_ID => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001245 let mut stmt = tx
1246 .prepare(
1247 "SELECT domain, namespace FROM persistent.keyentry
1248 WHERE
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001249 id = ?
1250 AND state = ?;",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001251 )
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001252 .context("Domain::KEY_ID: prepare statement failed")?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001253 let mut rows = stmt
1254 .query(params![key.nspace, KeyLifeCycle::Live])
1255 .context("Domain::KEY_ID: query failed.")?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001256 let (domain, namespace): (Domain, i64) =
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001257 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001258 let r =
1259 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001260 Ok((
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001261 Domain(r.get(0).context("Failed to unpack domain.")?),
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001262 r.get(1).context("Failed to unpack namespace.")?,
1263 ))
1264 })
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001265 .context("Domain::KEY_ID.")?;
1266 let key_id = key.nspace;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001267 let mut access_key = key;
1268 access_key.domain = domain;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001269 access_key.nspace = namespace;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001270
1271 Ok((key_id, access_key, None))
1272 }
1273 _ => Err(anyhow!(KsError::sys())),
1274 }
1275 }
1276
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001277 fn load_blob_components(
1278 key_id: i64,
1279 load_bits: KeyEntryLoadBits,
1280 tx: &Transaction,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001281 ) -> Result<(Option<Vec<u8>>, Option<Vec<u8>>, Option<Vec<u8>>)> {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001282 let mut stmt = tx
1283 .prepare(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001284 "SELECT MAX(id), subcomponent_type, blob FROM persistent.blobentry
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001285 WHERE keyentryid = ? GROUP BY subcomponent_type;",
1286 )
1287 .context("In load_blob_components: prepare statement failed.")?;
1288
1289 let mut rows =
1290 stmt.query(params![key_id]).context("In load_blob_components: query failed.")?;
1291
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001292 let mut km_blob: Option<Vec<u8>> = None;
1293 let mut cert_blob: Option<Vec<u8>> = None;
1294 let mut cert_chain_blob: Option<Vec<u8>> = None;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001295 db_utils::with_rows_extract_all(&mut rows, |row| {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001296 let sub_type: SubComponentType =
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001297 row.get(1).context("Failed to extract subcomponent_type.")?;
1298 match (sub_type, load_bits.load_public(), load_bits.load_km()) {
1299 (SubComponentType::KEY_BLOB, _, true) => {
1300 km_blob = Some(row.get(2).context("Failed to extract KM blob.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001301 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001302 (SubComponentType::CERT, true, _) => {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001303 cert_blob =
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001304 Some(row.get(2).context("Failed to extract public certificate blob.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001305 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001306 (SubComponentType::CERT_CHAIN, true, _) => {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001307 cert_chain_blob =
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001308 Some(row.get(2).context("Failed to extract certificate chain blob.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001309 }
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001310 (SubComponentType::CERT, _, _)
1311 | (SubComponentType::CERT_CHAIN, _, _)
1312 | (SubComponentType::KEY_BLOB, _, _) => {}
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001313 _ => Err(KsError::sys()).context("Unknown subcomponent type.")?,
1314 }
1315 Ok(())
1316 })
1317 .context("In load_blob_components.")?;
1318
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001319 Ok((km_blob, cert_blob, cert_chain_blob))
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001320 }
1321
1322 fn load_key_parameters(key_id: i64, tx: &Transaction) -> Result<Vec<KeyParameter>> {
1323 let mut stmt = tx
1324 .prepare(
1325 "SELECT tag, data, security_level from persistent.keyparameter
1326 WHERE keyentryid = ?;",
1327 )
1328 .context("In load_key_parameters: prepare statement failed.")?;
1329
1330 let mut parameters: Vec<KeyParameter> = Vec::new();
1331
1332 let mut rows =
1333 stmt.query(params![key_id]).context("In load_key_parameters: query failed.")?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001334 db_utils::with_rows_extract_all(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001335 let tag = Tag(row.get(0).context("Failed to read tag.")?);
1336 let sec_level = SecurityLevel(row.get(2).context("Failed to read sec_level.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001337 parameters.push(
1338 KeyParameter::new_from_sql(tag, &SqlField::new(1, &row), sec_level)
1339 .context("Failed to read KeyParameter.")?,
1340 );
1341 Ok(())
1342 })
1343 .context("In load_key_parameters.")?;
1344
1345 Ok(parameters)
1346 }
1347
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001348 /// Load a key entry by the given key descriptor.
1349 /// It uses the `check_permission` callback to verify if the access is allowed
1350 /// given the key access tuple read from the database using `load_access_tuple`.
1351 /// With `load_bits` the caller may specify which blobs shall be loaded from
1352 /// the blob database.
1353 pub fn load_key_entry(
1354 &mut self,
1355 key: KeyDescriptor,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001356 key_type: KeyType,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001357 load_bits: KeyEntryLoadBits,
1358 caller_uid: u32,
1359 check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001360 ) -> Result<(KeyIdGuard, KeyEntry)> {
1361 // KEY ID LOCK 1/2
1362 // If we got a key descriptor with a key id we can get the lock right away.
1363 // Otherwise we have to defer it until we know the key id.
1364 let key_id_guard = match key.domain {
1365 Domain::KEY_ID => Some(KEY_ID_LOCK.get(key.nspace)),
1366 _ => None,
1367 };
1368
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001369 let tx = self
1370 .conn
Janis Danisevskisaec14592020-11-12 09:41:49 -08001371 .unchecked_transaction()
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001372 .context("In load_key_entry: Failed to initialize transaction.")?;
1373
1374 // Load the key_id and complete the access control tuple.
1375 let (key_id, access_key_descriptor, access_vector) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001376 Self::load_access_tuple(&tx, key, key_type, caller_uid)
1377 .context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001378
1379 // Perform access control. It is vital that we return here if the permission is denied.
1380 // So do not touch that '?' at the end.
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001381 check_permission(&access_key_descriptor, access_vector).context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001382
Janis Danisevskisaec14592020-11-12 09:41:49 -08001383 // KEY ID LOCK 2/2
1384 // If we did not get a key id lock by now, it was because we got a key descriptor
1385 // without a key id. At this point we got the key id, so we can try and get a lock.
1386 // However, we cannot block here, because we are in the middle of the transaction.
1387 // So first we try to get the lock non blocking. If that fails, we roll back the
1388 // transaction and block until we get the lock. After we successfully got the lock,
1389 // we start a new transaction and load the access tuple again.
1390 //
1391 // We don't need to perform access control again, because we already established
1392 // that the caller had access to the given key. But we need to make sure that the
1393 // key id still exists. So we have to load the key entry by key id this time.
1394 let (key_id_guard, tx) = match key_id_guard {
1395 None => match KEY_ID_LOCK.try_get(key_id) {
1396 None => {
1397 // Roll back the transaction.
1398 tx.rollback().context("In load_key_entry: Failed to roll back transaction.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001399
Janis Danisevskisaec14592020-11-12 09:41:49 -08001400 // Block until we have a key id lock.
1401 let key_id_guard = KEY_ID_LOCK.get(key_id);
1402
1403 // Create a new transaction.
1404 let tx = self.conn.unchecked_transaction().context(
1405 "In load_key_entry: Failed to initialize transaction. (deferred key lock)",
1406 )?;
1407
1408 Self::load_access_tuple(
1409 &tx,
1410 // This time we have to load the key by the retrieved key id, because the
1411 // alias may have been rebound after we rolled back the transaction.
1412 KeyDescriptor {
1413 domain: Domain::KEY_ID,
1414 nspace: key_id,
1415 ..Default::default()
1416 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001417 key_type,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001418 caller_uid,
1419 )
1420 .context("In load_key_entry. (deferred key lock)")?;
1421 (key_id_guard, tx)
1422 }
1423 Some(l) => (l, tx),
1424 },
1425 Some(key_id_guard) => (key_id_guard, tx),
1426 };
1427
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001428 let key_entry = Self::load_key_components(&tx, load_bits, key_id_guard.id())
1429 .context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001430
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001431 tx.commit().context("In load_key_entry: Failed to commit transaction.")?;
1432
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001433 Ok((key_id_guard, key_entry))
1434 }
1435
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001436 fn mark_unreferenced(tx: &Transaction, key_id: i64) -> Result<()> {
1437 let updated = tx
1438 .execute(
1439 "UPDATE persistent.keyentry SET state = ? WHERE id = ?;",
1440 params![KeyLifeCycle::Unreferenced, key_id],
1441 )
1442 .context("In mark_unreferenced: Failed to update state of key entry.")?;
1443 if updated != 0 {
1444 Gc::notify_gc();
1445 }
1446 tx.execute("DELETE from persistent.grant WHERE keyentryid = ?;", params![key_id])
1447 .context("In mark_unreferenced: Failed to drop grants.")?;
1448 Ok(())
1449 }
1450
1451 /// Marks the given key as unreferenced and removes all of the grants to this key.
1452 pub fn unbind_key(
1453 &mut self,
1454 key: KeyDescriptor,
1455 key_type: KeyType,
1456 caller_uid: u32,
1457 check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
1458 ) -> Result<()> {
1459 self.with_transaction(TransactionBehavior::Immediate, |tx| {
1460 let (key_id, access_key_descriptor, access_vector) =
1461 Self::load_access_tuple(tx, key, key_type, caller_uid)
1462 .context("Trying to get access tuple.")?;
1463
1464 // Perform access control. It is vital that we return here if the permission is denied.
1465 // So do not touch that '?' at the end.
1466 check_permission(&access_key_descriptor, access_vector)
1467 .context("While checking permission.")?;
1468
1469 Self::mark_unreferenced(tx, key_id).context("Trying to mark the key unreferenced.")
1470 })
1471 .context("In unbind_key.")
1472 }
1473
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001474 fn load_key_components(
1475 tx: &Transaction,
1476 load_bits: KeyEntryLoadBits,
1477 key_id: i64,
1478 ) -> Result<KeyEntry> {
1479 let metadata = KeyMetaData::load_from_db(key_id, &tx).context("In load_key_components.")?;
1480
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001481 let (km_blob, cert_blob, cert_chain_blob) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001482 Self::load_blob_components(key_id, load_bits, &tx)
1483 .context("In load_key_components.")?;
1484
1485 let parameters =
1486 Self::load_key_parameters(key_id, &tx).context("In load_key_components.")?;
1487
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001488 // Extract the security level by checking the security level of the origin tag.
1489 // Super keys don't have key parameters so we use security_level software by default.
1490 let sec_level = parameters
1491 .iter()
1492 .find_map(|k| match k.get_tag() {
1493 Tag::ORIGIN => Some(*k.security_level()),
1494 _ => None,
1495 })
1496 .unwrap_or(SecurityLevel::SOFTWARE);
1497
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001498 Ok(KeyEntry {
1499 id: key_id,
1500 km_blob,
1501 cert: cert_blob,
1502 cert_chain: cert_chain_blob,
1503 sec_level,
1504 parameters,
1505 metadata,
1506 })
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001507 }
1508
Janis Danisevskise92a5e62020-12-02 12:57:41 -08001509 /// Returns a list of KeyDescriptors in the selected domain/namespace.
1510 /// The key descriptors will have the domain, nspace, and alias field set.
1511 /// Domain must be APP or SELINUX, the caller must make sure of that.
1512 pub fn list(&mut self, domain: Domain, namespace: i64) -> Result<Vec<KeyDescriptor>> {
1513 let mut stmt = self
1514 .conn
1515 .prepare(
1516 "SELECT alias FROM persistent.keyentry
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001517 WHERE domain = ? AND namespace = ? AND alias IS NOT NULL AND state = ?;",
Janis Danisevskise92a5e62020-12-02 12:57:41 -08001518 )
1519 .context("In list: Failed to prepare.")?;
1520
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001521 let mut rows = stmt
1522 .query(params![domain.0 as u32, namespace, KeyLifeCycle::Live])
1523 .context("In list: Failed to query.")?;
Janis Danisevskise92a5e62020-12-02 12:57:41 -08001524
1525 let mut descriptors: Vec<KeyDescriptor> = Vec::new();
1526 db_utils::with_rows_extract_all(&mut rows, |row| {
1527 descriptors.push(KeyDescriptor {
1528 domain,
1529 nspace: namespace,
1530 alias: Some(row.get(0).context("Trying to extract alias.")?),
1531 blob: None,
1532 });
1533 Ok(())
1534 })
1535 .context("In list.")?;
1536 Ok(descriptors)
1537 }
1538
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001539 /// Adds a grant to the grant table.
1540 /// Like `load_key_entry` this function loads the access tuple before
1541 /// it uses the callback for a permission check. Upon success,
1542 /// it inserts the `grantee_uid`, `key_id`, and `access_vector` into the
1543 /// grant table. The new row will have a randomized id, which is used as
1544 /// grant id in the namespace field of the resulting KeyDescriptor.
1545 pub fn grant(
1546 &mut self,
1547 key: KeyDescriptor,
1548 caller_uid: u32,
1549 grantee_uid: u32,
1550 access_vector: KeyPermSet,
1551 check_permission: impl FnOnce(&KeyDescriptor, &KeyPermSet) -> Result<()>,
1552 ) -> Result<KeyDescriptor> {
1553 let tx = self
1554 .conn
1555 .transaction_with_behavior(TransactionBehavior::Immediate)
1556 .context("In grant: Failed to initialize transaction.")?;
1557
1558 // Load the key_id and complete the access control tuple.
1559 // We ignore the access vector here because grants cannot be granted.
1560 // The access vector returned here expresses the permissions the
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001561 // grantee has if key.domain == Domain::GRANT. But this vector
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001562 // cannot include the grant permission by design, so there is no way the
1563 // subsequent permission check can pass.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001564 // We could check key.domain == Domain::GRANT and fail early.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001565 // But even if we load the access tuple by grant here, the permission
1566 // check denies the attempt to create a grant by grant descriptor.
1567 let (key_id, access_key_descriptor, _) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001568 Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid).context("In grant")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001569
1570 // Perform access control. It is vital that we return here if the permission
1571 // was denied. So do not touch that '?' at the end of the line.
1572 // This permission check checks if the caller has the grant permission
1573 // for the given key and in addition to all of the permissions
1574 // expressed in `access_vector`.
1575 check_permission(&access_key_descriptor, &access_vector)
1576 .context("In grant: check_permission failed.")?;
1577
1578 let grant_id = if let Some(grant_id) = tx
1579 .query_row(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001580 "SELECT id FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001581 WHERE keyentryid = ? AND grantee = ?;",
1582 params![key_id, grantee_uid],
1583 |row| row.get(0),
1584 )
1585 .optional()
1586 .context("In grant: Failed get optional existing grant id.")?
1587 {
1588 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001589 "UPDATE persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001590 SET access_vector = ?
1591 WHERE id = ?;",
1592 params![i32::from(access_vector), grant_id],
1593 )
1594 .context("In grant: Failed to update existing grant.")?;
1595 grant_id
1596 } else {
Joel Galenson845f74b2020-09-09 14:11:55 -07001597 Self::insert_with_retry(|id| {
1598 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001599 "INSERT INTO persistent.grant (id, grantee, keyentryid, access_vector)
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001600 VALUES (?, ?, ?, ?);",
Joel Galenson845f74b2020-09-09 14:11:55 -07001601 params![id, grantee_uid, key_id, i32::from(access_vector)],
1602 )
1603 })
1604 .context("In grant")?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001605 };
1606 tx.commit().context("In grant: failed to commit transaction.")?;
1607
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001608 Ok(KeyDescriptor { domain: Domain::GRANT, nspace: grant_id, alias: None, blob: None })
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001609 }
1610
1611 /// This function checks permissions like `grant` and `load_key_entry`
1612 /// before removing a grant from the grant table.
1613 pub fn ungrant(
1614 &mut self,
1615 key: KeyDescriptor,
1616 caller_uid: u32,
1617 grantee_uid: u32,
1618 check_permission: impl FnOnce(&KeyDescriptor) -> Result<()>,
1619 ) -> Result<()> {
1620 let tx = self
1621 .conn
1622 .transaction_with_behavior(TransactionBehavior::Immediate)
1623 .context("In ungrant: Failed to initialize transaction.")?;
1624
1625 // Load the key_id and complete the access control tuple.
1626 // We ignore the access vector here because grants cannot be granted.
1627 let (key_id, access_key_descriptor, _) =
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001628 Self::load_access_tuple(&tx, key, KeyType::Client, caller_uid)
1629 .context("In ungrant.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001630
1631 // Perform access control. We must return here if the permission
1632 // was denied. So do not touch the '?' at the end of this line.
1633 check_permission(&access_key_descriptor).context("In grant: check_permission failed.")?;
1634
1635 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001636 "DELETE FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001637 WHERE keyentryid = ? AND grantee = ?;",
1638 params![key_id, grantee_uid],
1639 )
1640 .context("Failed to delete grant.")?;
1641
1642 tx.commit().context("In ungrant: failed to commit transaction.")?;
1643
1644 Ok(())
1645 }
1646
Joel Galenson845f74b2020-09-09 14:11:55 -07001647 // Generates a random id and passes it to the given function, which will
1648 // try to insert it into a database. If that insertion fails, retry;
1649 // otherwise return the id.
1650 fn insert_with_retry(inserter: impl Fn(i64) -> rusqlite::Result<usize>) -> Result<i64> {
1651 loop {
1652 let newid: i64 = random();
1653 match inserter(newid) {
1654 // If the id already existed, try again.
1655 Err(rusqlite::Error::SqliteFailure(
1656 libsqlite3_sys::Error {
1657 code: libsqlite3_sys::ErrorCode::ConstraintViolation,
1658 extended_code: libsqlite3_sys::SQLITE_CONSTRAINT_UNIQUE,
1659 },
1660 _,
1661 )) => (),
1662 Err(e) => {
1663 return Err(e).context("In insert_with_retry: failed to insert into database.")
1664 }
1665 _ => return Ok(newid),
1666 }
1667 }
1668 }
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001669
1670 /// Insert or replace the auth token based on the UNIQUE constraint of the auth token table
1671 pub fn insert_auth_token(&mut self, auth_token: &HardwareAuthToken) -> Result<()> {
1672 self.conn
1673 .execute(
1674 "INSERT OR REPLACE INTO perboot.authtoken (challenge, user_id, auth_id,
1675 authenticator_type, timestamp, mac, time_received) VALUES(?, ?, ?, ?, ?, ?, ?);",
1676 params![
1677 auth_token.challenge,
1678 auth_token.userId,
1679 auth_token.authenticatorId,
1680 auth_token.authenticatorType.0 as i32,
1681 auth_token.timestamp.milliSeconds as i64,
1682 auth_token.mac,
1683 MonotonicRawTime::now(),
1684 ],
1685 )
1686 .context("In insert_auth_token: failed to insert auth token into the database")?;
1687 Ok(())
1688 }
Joel Galenson26f4d012020-07-17 14:57:21 -07001689}
1690
1691#[cfg(test)]
1692mod tests {
1693
1694 use super::*;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001695 use crate::key_parameter::{
1696 Algorithm, BlockMode, Digest, EcCurve, HardwareAuthenticatorType, KeyOrigin, KeyParameter,
1697 KeyParameterValue, KeyPurpose, PaddingMode, SecurityLevel,
1698 };
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001699 use crate::key_perm_set;
1700 use crate::permission::{KeyPerm, KeyPermSet};
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001701 use crate::test::utils::TempDir;
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001702 use android_hardware_security_keymint::aidl::android::hardware::security::keymint::{
1703 HardwareAuthToken::HardwareAuthToken,
1704 HardwareAuthenticatorType::HardwareAuthenticatorType as kmhw_authenticator_type,
1705 Timestamp::Timestamp,
1706 };
1707 use rusqlite::Error;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001708 use rusqlite::NO_PARAMS;
Joel Galenson0891bc12020-07-20 10:37:03 -07001709 use std::cell::RefCell;
Janis Danisevskisaec14592020-11-12 09:41:49 -08001710 use std::sync::atomic::{AtomicU8, Ordering};
1711 use std::sync::Arc;
1712 use std::thread;
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001713 use std::time::SystemTime;
Joel Galenson0891bc12020-07-20 10:37:03 -07001714
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001715 fn new_test_db() -> Result<KeystoreDB> {
1716 let conn = KeystoreDB::make_connection("file::memory:", "file::memory:")?;
1717
1718 KeystoreDB::init_tables(&conn).context("Failed to initialize tables.")?;
1719 Ok(KeystoreDB { conn })
1720 }
1721
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001722 #[test]
1723 fn datetime() -> Result<()> {
1724 let conn = Connection::open_in_memory()?;
1725 conn.execute("CREATE TABLE test (ts DATETIME);", NO_PARAMS)?;
1726 let now = SystemTime::now();
1727 let duration = Duration::from_secs(1000);
1728 let then = now.checked_sub(duration).unwrap();
1729 let soon = now.checked_add(duration).unwrap();
1730 conn.execute(
1731 "INSERT INTO test (ts) VALUES (?), (?), (?);",
1732 params![DateTime::try_from(now)?, DateTime::try_from(then)?, DateTime::try_from(soon)?],
1733 )?;
1734 let mut stmt = conn.prepare("SELECT ts FROM test ORDER BY ts ASC;")?;
1735 let mut rows = stmt.query(NO_PARAMS)?;
1736 assert_eq!(DateTime::try_from(then)?, rows.next()?.unwrap().get(0)?);
1737 assert_eq!(DateTime::try_from(now)?, rows.next()?.unwrap().get(0)?);
1738 assert_eq!(DateTime::try_from(soon)?, rows.next()?.unwrap().get(0)?);
1739 assert!(rows.next()?.is_none());
1740 assert!(DateTime::try_from(then)? < DateTime::try_from(now)?);
1741 assert!(DateTime::try_from(then)? < DateTime::try_from(soon)?);
1742 assert!(DateTime::try_from(now)? < DateTime::try_from(soon)?);
1743 Ok(())
1744 }
1745
Joel Galenson0891bc12020-07-20 10:37:03 -07001746 // Ensure that we're using the "injected" random function, not the real one.
1747 #[test]
1748 fn test_mocked_random() {
1749 let rand1 = random();
1750 let rand2 = random();
1751 let rand3 = random();
1752 if rand1 == rand2 {
1753 assert_eq!(rand2 + 1, rand3);
1754 } else {
1755 assert_eq!(rand1 + 1, rand2);
1756 assert_eq!(rand2, rand3);
1757 }
1758 }
Joel Galenson26f4d012020-07-17 14:57:21 -07001759
Joel Galenson26f4d012020-07-17 14:57:21 -07001760 // Test that we have the correct tables.
1761 #[test]
1762 fn test_tables() -> Result<()> {
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001763 let db = new_test_db()?;
Joel Galenson26f4d012020-07-17 14:57:21 -07001764 let tables = db
1765 .conn
Joel Galenson2aab4432020-07-22 15:27:57 -07001766 .prepare("SELECT name from persistent.sqlite_master WHERE type='table' ORDER BY name;")?
Joel Galenson26f4d012020-07-17 14:57:21 -07001767 .query_map(params![], |row| row.get(0))?
1768 .collect::<rusqlite::Result<Vec<String>>>()?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001769 assert_eq!(tables.len(), 5);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001770 assert_eq!(tables[0], "blobentry");
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001771 assert_eq!(tables[1], "grant");
1772 assert_eq!(tables[2], "keyentry");
Janis Danisevskisb42fc182020-12-15 08:41:27 -08001773 assert_eq!(tables[3], "keymetadata");
1774 assert_eq!(tables[4], "keyparameter");
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001775 let tables = db
1776 .conn
1777 .prepare("SELECT name from perboot.sqlite_master WHERE type='table' ORDER BY name;")?
1778 .query_map(params![], |row| row.get(0))?
1779 .collect::<rusqlite::Result<Vec<String>>>()?;
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001780
1781 assert_eq!(tables.len(), 2);
1782 assert_eq!(tables[0], "authtoken");
1783 assert_eq!(tables[1], "metadata");
Joel Galenson2aab4432020-07-22 15:27:57 -07001784 Ok(())
1785 }
1786
1787 #[test]
Hasini Gunasinghe557b1032020-11-10 01:35:30 +00001788 fn test_auth_token_table_invariant() -> Result<()> {
1789 let mut db = new_test_db()?;
1790 let auth_token1 = HardwareAuthToken {
1791 challenge: i64::MAX,
1792 userId: 200,
1793 authenticatorId: 200,
1794 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
1795 timestamp: Timestamp { milliSeconds: 500 },
1796 mac: String::from("mac").into_bytes(),
1797 };
1798 db.insert_auth_token(&auth_token1)?;
1799 let auth_tokens_returned = get_auth_tokens(&mut db)?;
1800 assert_eq!(auth_tokens_returned.len(), 1);
1801
1802 // insert another auth token with the same values for the columns in the UNIQUE constraint
1803 // of the auth token table and different value for timestamp
1804 let auth_token2 = HardwareAuthToken {
1805 challenge: i64::MAX,
1806 userId: 200,
1807 authenticatorId: 200,
1808 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
1809 timestamp: Timestamp { milliSeconds: 600 },
1810 mac: String::from("mac").into_bytes(),
1811 };
1812
1813 db.insert_auth_token(&auth_token2)?;
1814 let mut auth_tokens_returned = get_auth_tokens(&mut db)?;
1815 assert_eq!(auth_tokens_returned.len(), 1);
1816
1817 if let Some(auth_token) = auth_tokens_returned.pop() {
1818 assert_eq!(auth_token.auth_token.timestamp.milliSeconds, 600);
1819 }
1820
1821 // insert another auth token with the different values for the columns in the UNIQUE
1822 // constraint of the auth token table
1823 let auth_token3 = HardwareAuthToken {
1824 challenge: i64::MAX,
1825 userId: 201,
1826 authenticatorId: 200,
1827 authenticatorType: kmhw_authenticator_type(kmhw_authenticator_type::PASSWORD.0),
1828 timestamp: Timestamp { milliSeconds: 600 },
1829 mac: String::from("mac").into_bytes(),
1830 };
1831
1832 db.insert_auth_token(&auth_token3)?;
1833 let auth_tokens_returned = get_auth_tokens(&mut db)?;
1834 assert_eq!(auth_tokens_returned.len(), 2);
1835
1836 Ok(())
1837 }
1838
1839 // utility function for test_auth_token_table_invariant()
1840 fn get_auth_tokens(db: &mut KeystoreDB) -> Result<Vec<AuthTokenEntry>> {
1841 let mut stmt = db.conn.prepare("SELECT * from perboot.authtoken;")?;
1842
1843 let auth_token_entries: Vec<AuthTokenEntry> = stmt
1844 .query_map(NO_PARAMS, |row| {
1845 Ok(AuthTokenEntry::new(
1846 HardwareAuthToken {
1847 challenge: row.get(1)?,
1848 userId: row.get(2)?,
1849 authenticatorId: row.get(3)?,
1850 authenticatorType: HardwareAuthenticatorType(row.get(4)?),
1851 timestamp: Timestamp { milliSeconds: row.get(5)? },
1852 mac: row.get(6)?,
1853 },
1854 row.get(7)?,
1855 ))
1856 })?
1857 .collect::<Result<Vec<AuthTokenEntry>, Error>>()?;
1858 Ok(auth_token_entries)
1859 }
1860
1861 #[test]
Joel Galenson2aab4432020-07-22 15:27:57 -07001862 fn test_persistence_for_files() -> Result<()> {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001863 let temp_dir = TempDir::new("persistent_db_test")?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001864 let mut db = KeystoreDB::new(temp_dir.path())?;
Joel Galenson2aab4432020-07-22 15:27:57 -07001865
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001866 db.create_key_entry(Domain::APP, 100)?;
Joel Galenson2aab4432020-07-22 15:27:57 -07001867 let entries = get_keyentry(&db)?;
1868 assert_eq!(entries.len(), 1);
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001869
1870 let db = KeystoreDB::new(temp_dir.path())?;
Joel Galenson2aab4432020-07-22 15:27:57 -07001871
1872 let entries_new = get_keyentry(&db)?;
1873 assert_eq!(entries, entries_new);
1874 Ok(())
1875 }
1876
1877 #[test]
Joel Galenson0891bc12020-07-20 10:37:03 -07001878 fn test_create_key_entry() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001879 fn extractor(ke: &KeyEntryRow) -> (Domain, i64, Option<&str>) {
Joel Galenson0891bc12020-07-20 10:37:03 -07001880 (ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref())
1881 }
1882
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001883 let mut db = new_test_db()?;
Joel Galenson0891bc12020-07-20 10:37:03 -07001884
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001885 db.create_key_entry(Domain::APP, 100)?;
1886 db.create_key_entry(Domain::SELINUX, 101)?;
Joel Galenson0891bc12020-07-20 10:37:03 -07001887
1888 let entries = get_keyentry(&db)?;
1889 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001890 assert_eq!(extractor(&entries[0]), (Domain::APP, 100, None));
1891 assert_eq!(extractor(&entries[1]), (Domain::SELINUX, 101, None));
Joel Galenson0891bc12020-07-20 10:37:03 -07001892
1893 // Test that we must pass in a valid Domain.
1894 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001895 db.create_key_entry(Domain::GRANT, 102),
1896 "Domain Domain(1) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07001897 );
1898 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001899 db.create_key_entry(Domain::BLOB, 103),
1900 "Domain Domain(3) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07001901 );
1902 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001903 db.create_key_entry(Domain::KEY_ID, 104),
1904 "Domain Domain(4) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07001905 );
1906
1907 Ok(())
1908 }
1909
Joel Galenson33c04ad2020-08-03 11:04:38 -07001910 #[test]
1911 fn test_rebind_alias() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001912 fn extractor(ke: &KeyEntryRow) -> (Option<Domain>, Option<i64>, Option<&str>) {
Joel Galenson33c04ad2020-08-03 11:04:38 -07001913 (ke.domain, ke.namespace, ke.alias.as_deref())
1914 }
1915
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001916 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001917 db.create_key_entry(Domain::APP, 42)?;
1918 db.create_key_entry(Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07001919 let entries = get_keyentry(&db)?;
1920 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001921 assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), None));
1922 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
Joel Galenson33c04ad2020-08-03 11:04:38 -07001923
1924 // Test that the first call to rebind_alias sets the alias.
Janis Danisevskisaec14592020-11-12 09:41:49 -08001925 db.rebind_alias(&KEY_ID_LOCK.get(entries[0].id), "foo", Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07001926 let entries = get_keyentry(&db)?;
1927 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001928 assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), Some("foo")));
1929 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
Joel Galenson33c04ad2020-08-03 11:04:38 -07001930
1931 // Test that the second call to rebind_alias also empties the old one.
Janis Danisevskisaec14592020-11-12 09:41:49 -08001932 db.rebind_alias(&KEY_ID_LOCK.get(entries[1].id), "foo", Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07001933 let entries = get_keyentry(&db)?;
1934 assert_eq!(entries.len(), 2);
Joel Galenson7fa5c412020-11-19 10:56:54 -08001935 assert_eq!(extractor(&entries[0]), (None, None, None));
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001936 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
Joel Galenson33c04ad2020-08-03 11:04:38 -07001937
1938 // Test that we must pass in a valid Domain.
1939 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001940 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::GRANT, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001941 "Domain Domain(1) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07001942 );
1943 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001944 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::BLOB, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001945 "Domain Domain(3) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07001946 );
1947 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001948 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::KEY_ID, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001949 "Domain Domain(4) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07001950 );
1951
1952 // Test that we correctly handle setting an alias for something that does not exist.
1953 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001954 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::SELINUX, 42),
Joel Galenson33c04ad2020-08-03 11:04:38 -07001955 "Expected to update a single entry but instead updated 0",
1956 );
1957 // Test that we correctly abort the transaction in this case.
1958 let entries = get_keyentry(&db)?;
1959 assert_eq!(entries.len(), 2);
Joel Galenson7fa5c412020-11-19 10:56:54 -08001960 assert_eq!(extractor(&entries[0]), (None, None, None));
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001961 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
Joel Galenson33c04ad2020-08-03 11:04:38 -07001962
1963 Ok(())
1964 }
1965
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001966 #[test]
1967 fn test_grant_ungrant() -> Result<()> {
1968 const CALLER_UID: u32 = 15;
1969 const GRANTEE_UID: u32 = 12;
1970 const SELINUX_NAMESPACE: i64 = 7;
1971
1972 let mut db = new_test_db()?;
1973 db.conn.execute(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001974 "INSERT INTO persistent.keyentry (id, key_type, domain, namespace, alias, state)
1975 VALUES (1, 0, 0, 15, 'key', 1), (2, 0, 2, 7, 'yek', 1);",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001976 NO_PARAMS,
1977 )?;
1978 let app_key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001979 domain: super::Domain::APP,
1980 nspace: 0,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001981 alias: Some("key".to_string()),
1982 blob: None,
1983 };
1984 const PVEC1: KeyPermSet = key_perm_set![KeyPerm::use_(), KeyPerm::get_info()];
1985 const PVEC2: KeyPermSet = key_perm_set![KeyPerm::use_()];
1986
1987 // Reset totally predictable random number generator in case we
1988 // are not the first test running on this thread.
1989 reset_random();
1990 let next_random = 0i64;
1991
Janis Danisevskis93927dd2020-12-23 12:23:08 -08001992 let app_granted_key = db
1993 .grant(app_key.clone(), CALLER_UID, GRANTEE_UID, PVEC1, |k, a| {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001994 assert_eq!(*a, PVEC1);
1995 assert_eq!(
1996 *k,
1997 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001998 domain: super::Domain::APP,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001999 // namespace must be set to the caller_uid.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002000 nspace: CALLER_UID as i64,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002001 alias: Some("key".to_string()),
2002 blob: None,
2003 }
2004 );
2005 Ok(())
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002006 })
2007 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002008
2009 assert_eq!(
2010 app_granted_key,
2011 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002012 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002013 // The grantid is next_random due to the mock random number generator.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002014 nspace: next_random,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002015 alias: None,
2016 blob: None,
2017 }
2018 );
2019
2020 let selinux_key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002021 domain: super::Domain::SELINUX,
2022 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002023 alias: Some("yek".to_string()),
2024 blob: None,
2025 };
2026
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002027 let selinux_granted_key = db
2028 .grant(selinux_key.clone(), CALLER_UID, 12, PVEC1, |k, a| {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002029 assert_eq!(*a, PVEC1);
2030 assert_eq!(
2031 *k,
2032 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002033 domain: super::Domain::SELINUX,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002034 // namespace must be the supplied SELinux
2035 // namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002036 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002037 alias: Some("yek".to_string()),
2038 blob: None,
2039 }
2040 );
2041 Ok(())
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002042 })
2043 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002044
2045 assert_eq!(
2046 selinux_granted_key,
2047 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002048 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002049 // The grantid is next_random + 1 due to the mock random number generator.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002050 nspace: next_random + 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002051 alias: None,
2052 blob: None,
2053 }
2054 );
2055
2056 // This should update the existing grant with PVEC2.
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002057 let selinux_granted_key = db
2058 .grant(selinux_key.clone(), CALLER_UID, 12, PVEC2, |k, a| {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002059 assert_eq!(*a, PVEC2);
2060 assert_eq!(
2061 *k,
2062 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002063 domain: super::Domain::SELINUX,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002064 // namespace must be the supplied SELinux
2065 // namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002066 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002067 alias: Some("yek".to_string()),
2068 blob: None,
2069 }
2070 );
2071 Ok(())
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002072 })
2073 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002074
2075 assert_eq!(
2076 selinux_granted_key,
2077 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002078 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002079 // Same grant id as before. The entry was only updated.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002080 nspace: next_random + 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002081 alias: None,
2082 blob: None,
2083 }
2084 );
2085
2086 {
2087 // Limiting scope of stmt, because it borrows db.
2088 let mut stmt = db
2089 .conn
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002090 .prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?;
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07002091 let mut rows =
2092 stmt.query_map::<(i64, u32, i64, KeyPermSet), _, _>(NO_PARAMS, |row| {
2093 Ok((
2094 row.get(0)?,
2095 row.get(1)?,
2096 row.get(2)?,
2097 KeyPermSet::from(row.get::<_, i32>(3)?),
2098 ))
2099 })?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002100
2101 let r = rows.next().unwrap().unwrap();
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07002102 assert_eq!(r, (next_random, GRANTEE_UID, 1, PVEC1));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002103 let r = rows.next().unwrap().unwrap();
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07002104 assert_eq!(r, (next_random + 1, GRANTEE_UID, 2, PVEC2));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002105 assert!(rows.next().is_none());
2106 }
2107
2108 debug_dump_keyentry_table(&mut db)?;
2109 println!("app_key {:?}", app_key);
2110 println!("selinux_key {:?}", selinux_key);
2111
2112 db.ungrant(app_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
2113 db.ungrant(selinux_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
2114
2115 Ok(())
2116 }
2117
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002118 static TEST_KEY_BLOB: &[u8] = b"my test blob";
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002119 static TEST_CERT_BLOB: &[u8] = b"my test cert";
2120 static TEST_CERT_CHAIN_BLOB: &[u8] = b"my test cert_chain";
2121
2122 #[test]
2123 fn test_insert_blob() -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002124 let key_id = KEY_ID_LOCK.get(3000);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002125 let mut db = new_test_db()?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002126 db.insert_blob(&key_id, SubComponentType::KEY_BLOB, TEST_KEY_BLOB)?;
2127 db.insert_blob(&key_id, SubComponentType::CERT, TEST_CERT_BLOB)?;
2128 db.insert_blob(&key_id, SubComponentType::CERT_CHAIN, TEST_CERT_CHAIN_BLOB)?;
2129 drop(key_id);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002130
2131 let mut stmt = db.conn.prepare(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002132 "SELECT subcomponent_type, keyentryid, blob FROM persistent.blobentry
2133 ORDER BY subcomponent_type ASC;",
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002134 )?;
2135 let mut rows = stmt
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002136 .query_map::<(SubComponentType, i64, Vec<u8>), _, _>(NO_PARAMS, |row| {
2137 Ok((row.get(0)?, row.get(1)?, row.get(2)?))
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002138 })?;
2139 let r = rows.next().unwrap().unwrap();
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002140 assert_eq!(r, (SubComponentType::KEY_BLOB, 3000, TEST_KEY_BLOB.to_vec()));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002141 let r = rows.next().unwrap().unwrap();
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002142 assert_eq!(r, (SubComponentType::CERT, 3000, TEST_CERT_BLOB.to_vec()));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002143 let r = rows.next().unwrap().unwrap();
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002144 assert_eq!(r, (SubComponentType::CERT_CHAIN, 3000, TEST_CERT_CHAIN_BLOB.to_vec()));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002145
2146 Ok(())
2147 }
2148
2149 static TEST_ALIAS: &str = "my super duper key";
2150
2151 #[test]
2152 fn test_insert_and_load_full_keyentry_domain_app() -> Result<()> {
2153 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002154 let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002155 .context("test_insert_and_load_full_keyentry_domain_app")?
2156 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002157 let (_key_guard, key_entry) = db
2158 .load_key_entry(
2159 KeyDescriptor {
2160 domain: Domain::APP,
2161 nspace: 0,
2162 alias: Some(TEST_ALIAS.to_string()),
2163 blob: None,
2164 },
2165 KeyType::Client,
2166 KeyEntryLoadBits::BOTH,
2167 1,
2168 |_k, _av| Ok(()),
2169 )
2170 .unwrap();
2171 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
2172
2173 db.unbind_key(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002174 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002175 domain: Domain::APP,
2176 nspace: 0,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002177 alias: Some(TEST_ALIAS.to_string()),
2178 blob: None,
2179 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002180 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002181 1,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002182 |_, _| Ok(()),
2183 )
2184 .unwrap();
2185
2186 assert_eq!(
2187 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2188 db.load_key_entry(
2189 KeyDescriptor {
2190 domain: Domain::APP,
2191 nspace: 0,
2192 alias: Some(TEST_ALIAS.to_string()),
2193 blob: None,
2194 },
2195 KeyType::Client,
2196 KeyEntryLoadBits::NONE,
2197 1,
2198 |_k, _av| Ok(()),
2199 )
2200 .unwrap_err()
2201 .root_cause()
2202 .downcast_ref::<KsError>()
2203 );
2204
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002205 Ok(())
2206 }
2207
2208 #[test]
2209 fn test_insert_and_load_full_keyentry_domain_selinux() -> Result<()> {
2210 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002211 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002212 .context("test_insert_and_load_full_keyentry_domain_selinux")?
2213 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002214 let (_key_guard, key_entry) = db
2215 .load_key_entry(
2216 KeyDescriptor {
2217 domain: Domain::SELINUX,
2218 nspace: 1,
2219 alias: Some(TEST_ALIAS.to_string()),
2220 blob: None,
2221 },
2222 KeyType::Client,
2223 KeyEntryLoadBits::BOTH,
2224 1,
2225 |_k, _av| Ok(()),
2226 )
2227 .unwrap();
2228 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
2229
2230 db.unbind_key(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002231 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002232 domain: Domain::SELINUX,
2233 nspace: 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002234 alias: Some(TEST_ALIAS.to_string()),
2235 blob: None,
2236 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002237 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002238 1,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002239 |_, _| Ok(()),
2240 )
2241 .unwrap();
2242
2243 assert_eq!(
2244 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2245 db.load_key_entry(
2246 KeyDescriptor {
2247 domain: Domain::SELINUX,
2248 nspace: 1,
2249 alias: Some(TEST_ALIAS.to_string()),
2250 blob: None,
2251 },
2252 KeyType::Client,
2253 KeyEntryLoadBits::NONE,
2254 1,
2255 |_k, _av| Ok(()),
2256 )
2257 .unwrap_err()
2258 .root_cause()
2259 .downcast_ref::<KsError>()
2260 );
2261
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002262 Ok(())
2263 }
2264
2265 #[test]
2266 fn test_insert_and_load_full_keyentry_domain_key_id() -> Result<()> {
2267 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002268 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002269 .context("test_insert_and_load_full_keyentry_domain_key_id")?
2270 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002271 let (_, key_entry) = db
2272 .load_key_entry(
2273 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
2274 KeyType::Client,
2275 KeyEntryLoadBits::BOTH,
2276 1,
2277 |_k, _av| Ok(()),
2278 )
2279 .unwrap();
2280
2281 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
2282
2283 db.unbind_key(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002284 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002285 KeyType::Client,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002286 1,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002287 |_, _| Ok(()),
2288 )
2289 .unwrap();
2290
2291 assert_eq!(
2292 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2293 db.load_key_entry(
2294 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
2295 KeyType::Client,
2296 KeyEntryLoadBits::NONE,
2297 1,
2298 |_k, _av| Ok(()),
2299 )
2300 .unwrap_err()
2301 .root_cause()
2302 .downcast_ref::<KsError>()
2303 );
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002304
2305 Ok(())
2306 }
2307
2308 #[test]
2309 fn test_insert_and_load_full_keyentry_from_grant() -> Result<()> {
2310 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002311 let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08002312 .context("test_insert_and_load_full_keyentry_from_grant")?
2313 .0;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002314
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002315 let granted_key = db
2316 .grant(
2317 KeyDescriptor {
2318 domain: Domain::APP,
2319 nspace: 0,
2320 alias: Some(TEST_ALIAS.to_string()),
2321 blob: None,
2322 },
2323 1,
2324 2,
2325 key_perm_set![KeyPerm::use_()],
2326 |_k, _av| Ok(()),
2327 )
2328 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002329
2330 debug_dump_grant_table(&mut db)?;
2331
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002332 let (_key_guard, key_entry) = db
2333 .load_key_entry(
2334 granted_key.clone(),
2335 KeyType::Client,
2336 KeyEntryLoadBits::BOTH,
2337 2,
2338 |k, av| {
2339 assert_eq!(Domain::GRANT, k.domain);
2340 assert!(av.unwrap().includes(KeyPerm::use_()));
2341 Ok(())
2342 },
2343 )
2344 .unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002345
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002346 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002347
2348 db.unbind_key(granted_key.clone(), KeyType::Client, 2, |_, _| Ok(())).unwrap();
2349
2350 assert_eq!(
2351 Some(&KsError::Rc(ResponseCode::KEY_NOT_FOUND)),
2352 db.load_key_entry(
2353 granted_key,
2354 KeyType::Client,
2355 KeyEntryLoadBits::NONE,
2356 2,
2357 |_k, _av| Ok(()),
2358 )
2359 .unwrap_err()
2360 .root_cause()
2361 .downcast_ref::<KsError>()
2362 );
2363
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002364 Ok(())
2365 }
2366
Janis Danisevskisaec14592020-11-12 09:41:49 -08002367 static KEY_LOCK_TEST_ALIAS: &str = "my super duper locked key";
2368
Janis Danisevskisaec14592020-11-12 09:41:49 -08002369 #[test]
2370 fn test_insert_and_load_full_keyentry_domain_app_concurrently() -> Result<()> {
2371 let handle = {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002372 let temp_dir = Arc::new(TempDir::new("id_lock_test")?);
2373 let temp_dir_clone = temp_dir.clone();
2374 let mut db = KeystoreDB::new(temp_dir.path())?;
Janis Danisevskisaec14592020-11-12 09:41:49 -08002375 let key_id = make_test_key_entry(&mut db, Domain::APP, 33, KEY_LOCK_TEST_ALIAS)
2376 .context("test_insert_and_load_full_keyentry_domain_app")?
2377 .0;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002378 let (_key_guard, key_entry) = db
2379 .load_key_entry(
2380 KeyDescriptor {
2381 domain: Domain::APP,
2382 nspace: 0,
2383 alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
2384 blob: None,
2385 },
2386 KeyType::Client,
2387 KeyEntryLoadBits::BOTH,
2388 33,
2389 |_k, _av| Ok(()),
2390 )
2391 .unwrap();
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002392 assert_eq!(key_entry, make_test_key_entry_test_vector(key_id));
Janis Danisevskisaec14592020-11-12 09:41:49 -08002393 let state = Arc::new(AtomicU8::new(1));
2394 let state2 = state.clone();
2395
2396 // Spawning a second thread that attempts to acquire the key id lock
2397 // for the same key as the primary thread. The primary thread then
2398 // waits, thereby forcing the secondary thread into the second stage
2399 // of acquiring the lock (see KEY ID LOCK 2/2 above).
2400 // The test succeeds if the secondary thread observes the transition
2401 // of `state` from 1 to 2, despite having a whole second to overtake
2402 // the primary thread.
2403 let handle = thread::spawn(move || {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002404 let temp_dir = temp_dir_clone;
2405 let mut db = KeystoreDB::new(temp_dir.path()).unwrap();
Janis Danisevskisaec14592020-11-12 09:41:49 -08002406 assert!(db
2407 .load_key_entry(
2408 KeyDescriptor {
2409 domain: Domain::APP,
2410 nspace: 0,
2411 alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
2412 blob: None,
2413 },
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002414 KeyType::Client,
Janis Danisevskisaec14592020-11-12 09:41:49 -08002415 KeyEntryLoadBits::BOTH,
2416 33,
2417 |_k, _av| Ok(()),
2418 )
2419 .is_ok());
2420 // We should only see a 2 here because we can only return
2421 // from load_key_entry when the `_key_guard` expires,
2422 // which happens at the end of the scope.
2423 assert_eq!(2, state2.load(Ordering::Relaxed));
2424 });
2425
2426 thread::sleep(std::time::Duration::from_millis(1000));
2427
2428 assert_eq!(Ok(1), state.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed));
2429
2430 // Return the handle from this scope so we can join with the
2431 // secondary thread after the key id lock has expired.
2432 handle
2433 // This is where the `_key_guard` goes out of scope,
2434 // which is the reason for concurrent load_key_entry on the same key
2435 // to unblock.
2436 };
2437 // Join with the secondary thread and unwrap, to propagate failing asserts to the
2438 // main test thread. We will not see failing asserts in secondary threads otherwise.
2439 handle.join().unwrap();
2440 Ok(())
2441 }
2442
Janis Danisevskise92a5e62020-12-02 12:57:41 -08002443 #[test]
2444 fn list() -> Result<()> {
2445 let temp_dir = TempDir::new("list_test")?;
2446 let mut db = KeystoreDB::new(temp_dir.path())?;
2447 static LIST_O_ENTRIES: &[(Domain, i64, &str)] = &[
2448 (Domain::APP, 1, "test1"),
2449 (Domain::APP, 1, "test2"),
2450 (Domain::APP, 1, "test3"),
2451 (Domain::APP, 1, "test4"),
2452 (Domain::APP, 1, "test5"),
2453 (Domain::APP, 1, "test6"),
2454 (Domain::APP, 1, "test7"),
2455 (Domain::APP, 2, "test1"),
2456 (Domain::APP, 2, "test2"),
2457 (Domain::APP, 2, "test3"),
2458 (Domain::APP, 2, "test4"),
2459 (Domain::APP, 2, "test5"),
2460 (Domain::APP, 2, "test6"),
2461 (Domain::APP, 2, "test8"),
2462 (Domain::SELINUX, 100, "test1"),
2463 (Domain::SELINUX, 100, "test2"),
2464 (Domain::SELINUX, 100, "test3"),
2465 (Domain::SELINUX, 100, "test4"),
2466 (Domain::SELINUX, 100, "test5"),
2467 (Domain::SELINUX, 100, "test6"),
2468 (Domain::SELINUX, 100, "test9"),
2469 ];
2470
2471 let list_o_keys: Vec<(i64, i64)> = LIST_O_ENTRIES
2472 .iter()
2473 .map(|(domain, ns, alias)| {
2474 let entry =
2475 make_test_key_entry(&mut db, *domain, *ns, *alias).unwrap_or_else(|e| {
2476 panic!("Failed to insert {:?} {} {}. Error {:?}", domain, ns, alias, e)
2477 });
2478 (entry.id(), *ns)
2479 })
2480 .collect();
2481
2482 for (domain, namespace) in
2483 &[(Domain::APP, 1i64), (Domain::APP, 2i64), (Domain::SELINUX, 100i64)]
2484 {
2485 let mut list_o_descriptors: Vec<KeyDescriptor> = LIST_O_ENTRIES
2486 .iter()
2487 .filter_map(|(domain, ns, alias)| match ns {
2488 ns if *ns == *namespace => Some(KeyDescriptor {
2489 domain: *domain,
2490 nspace: *ns,
2491 alias: Some(alias.to_string()),
2492 blob: None,
2493 }),
2494 _ => None,
2495 })
2496 .collect();
2497 list_o_descriptors.sort();
2498 let mut list_result = db.list(*domain, *namespace)?;
2499 list_result.sort();
2500 assert_eq!(list_o_descriptors, list_result);
2501
2502 let mut list_o_ids: Vec<i64> = list_o_descriptors
2503 .into_iter()
2504 .map(|d| {
2505 let (_, entry) = db
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002506 .load_key_entry(
2507 d,
2508 KeyType::Client,
2509 KeyEntryLoadBits::NONE,
2510 *namespace as u32,
2511 |_, _| Ok(()),
2512 )
Janis Danisevskise92a5e62020-12-02 12:57:41 -08002513 .unwrap();
2514 entry.id()
2515 })
2516 .collect();
2517 list_o_ids.sort_unstable();
2518 let mut loaded_entries: Vec<i64> = list_o_keys
2519 .iter()
2520 .filter_map(|(id, ns)| match ns {
2521 ns if *ns == *namespace => Some(*id),
2522 _ => None,
2523 })
2524 .collect();
2525 loaded_entries.sort_unstable();
2526 assert_eq!(list_o_ids, loaded_entries);
2527 }
2528 assert_eq!(Vec::<KeyDescriptor>::new(), db.list(Domain::SELINUX, 101)?);
2529
2530 Ok(())
2531 }
2532
Joel Galenson0891bc12020-07-20 10:37:03 -07002533 // Helpers
2534
2535 // Checks that the given result is an error containing the given string.
2536 fn check_result_is_error_containing_string<T>(result: Result<T>, target: &str) {
2537 let error_str = format!(
2538 "{:#?}",
2539 result.err().unwrap_or_else(|| panic!("Expected the error: {}", target))
2540 );
2541 assert!(
2542 error_str.contains(target),
2543 "The string \"{}\" should contain \"{}\"",
2544 error_str,
2545 target
2546 );
2547 }
2548
Joel Galenson2aab4432020-07-22 15:27:57 -07002549 #[derive(Debug, PartialEq)]
Joel Galenson0891bc12020-07-20 10:37:03 -07002550 #[allow(dead_code)]
2551 struct KeyEntryRow {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002552 id: i64,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002553 key_type: KeyType,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002554 domain: Option<Domain>,
Joel Galenson0891bc12020-07-20 10:37:03 -07002555 namespace: Option<i64>,
2556 alias: Option<String>,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002557 state: KeyLifeCycle,
Joel Galenson0891bc12020-07-20 10:37:03 -07002558 }
2559
2560 fn get_keyentry(db: &KeystoreDB) -> Result<Vec<KeyEntryRow>> {
2561 db.conn
Joel Galenson2aab4432020-07-22 15:27:57 -07002562 .prepare("SELECT * FROM persistent.keyentry;")?
Joel Galenson0891bc12020-07-20 10:37:03 -07002563 .query_map(NO_PARAMS, |row| {
Joel Galenson0891bc12020-07-20 10:37:03 -07002564 Ok(KeyEntryRow {
2565 id: row.get(0)?,
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002566 key_type: row.get(1)?,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002567 domain: match row.get(2)? {
2568 Some(i) => Some(Domain(i)),
2569 None => None,
2570 },
Joel Galenson0891bc12020-07-20 10:37:03 -07002571 namespace: row.get(3)?,
2572 alias: row.get(4)?,
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002573 state: row.get(5)?,
Joel Galenson0891bc12020-07-20 10:37:03 -07002574 })
2575 })?
2576 .map(|r| r.context("Could not read keyentry row."))
2577 .collect::<Result<Vec<_>>>()
2578 }
2579
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07002580 // Note: The parameters and SecurityLevel associations are nonsensical. This
2581 // collection is only used to check if the parameters are preserved as expected by the
2582 // database.
2583 fn make_test_params() -> Vec<KeyParameter> {
2584 vec![
2585 KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::TRUSTED_ENVIRONMENT),
2586 KeyParameter::new(
2587 KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
2588 SecurityLevel::TRUSTED_ENVIRONMENT,
2589 ),
2590 KeyParameter::new(
2591 KeyParameterValue::KeyPurpose(KeyPurpose::DECRYPT),
2592 SecurityLevel::TRUSTED_ENVIRONMENT,
2593 ),
2594 KeyParameter::new(
2595 KeyParameterValue::Algorithm(Algorithm::RSA),
2596 SecurityLevel::TRUSTED_ENVIRONMENT,
2597 ),
2598 KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::TRUSTED_ENVIRONMENT),
2599 KeyParameter::new(
2600 KeyParameterValue::BlockMode(BlockMode::ECB),
2601 SecurityLevel::TRUSTED_ENVIRONMENT,
2602 ),
2603 KeyParameter::new(
2604 KeyParameterValue::BlockMode(BlockMode::GCM),
2605 SecurityLevel::TRUSTED_ENVIRONMENT,
2606 ),
2607 KeyParameter::new(KeyParameterValue::Digest(Digest::NONE), SecurityLevel::STRONGBOX),
2608 KeyParameter::new(
2609 KeyParameterValue::Digest(Digest::MD5),
2610 SecurityLevel::TRUSTED_ENVIRONMENT,
2611 ),
2612 KeyParameter::new(
2613 KeyParameterValue::Digest(Digest::SHA_2_224),
2614 SecurityLevel::TRUSTED_ENVIRONMENT,
2615 ),
2616 KeyParameter::new(
2617 KeyParameterValue::Digest(Digest::SHA_2_256),
2618 SecurityLevel::STRONGBOX,
2619 ),
2620 KeyParameter::new(
2621 KeyParameterValue::PaddingMode(PaddingMode::NONE),
2622 SecurityLevel::TRUSTED_ENVIRONMENT,
2623 ),
2624 KeyParameter::new(
2625 KeyParameterValue::PaddingMode(PaddingMode::RSA_OAEP),
2626 SecurityLevel::TRUSTED_ENVIRONMENT,
2627 ),
2628 KeyParameter::new(
2629 KeyParameterValue::PaddingMode(PaddingMode::RSA_PSS),
2630 SecurityLevel::STRONGBOX,
2631 ),
2632 KeyParameter::new(
2633 KeyParameterValue::PaddingMode(PaddingMode::RSA_PKCS1_1_5_SIGN),
2634 SecurityLevel::TRUSTED_ENVIRONMENT,
2635 ),
2636 KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::TRUSTED_ENVIRONMENT),
2637 KeyParameter::new(KeyParameterValue::MinMacLength(256), SecurityLevel::STRONGBOX),
2638 KeyParameter::new(
2639 KeyParameterValue::EcCurve(EcCurve::P_224),
2640 SecurityLevel::TRUSTED_ENVIRONMENT,
2641 ),
2642 KeyParameter::new(KeyParameterValue::EcCurve(EcCurve::P_256), SecurityLevel::STRONGBOX),
2643 KeyParameter::new(
2644 KeyParameterValue::EcCurve(EcCurve::P_384),
2645 SecurityLevel::TRUSTED_ENVIRONMENT,
2646 ),
2647 KeyParameter::new(
2648 KeyParameterValue::EcCurve(EcCurve::P_521),
2649 SecurityLevel::TRUSTED_ENVIRONMENT,
2650 ),
2651 KeyParameter::new(
2652 KeyParameterValue::RSAPublicExponent(3),
2653 SecurityLevel::TRUSTED_ENVIRONMENT,
2654 ),
2655 KeyParameter::new(
2656 KeyParameterValue::IncludeUniqueID,
2657 SecurityLevel::TRUSTED_ENVIRONMENT,
2658 ),
2659 KeyParameter::new(KeyParameterValue::BootLoaderOnly, SecurityLevel::STRONGBOX),
2660 KeyParameter::new(KeyParameterValue::RollbackResistance, SecurityLevel::STRONGBOX),
2661 KeyParameter::new(
2662 KeyParameterValue::ActiveDateTime(1234567890),
2663 SecurityLevel::STRONGBOX,
2664 ),
2665 KeyParameter::new(
2666 KeyParameterValue::OriginationExpireDateTime(1234567890),
2667 SecurityLevel::TRUSTED_ENVIRONMENT,
2668 ),
2669 KeyParameter::new(
2670 KeyParameterValue::UsageExpireDateTime(1234567890),
2671 SecurityLevel::TRUSTED_ENVIRONMENT,
2672 ),
2673 KeyParameter::new(
2674 KeyParameterValue::MinSecondsBetweenOps(1234567890),
2675 SecurityLevel::TRUSTED_ENVIRONMENT,
2676 ),
2677 KeyParameter::new(
2678 KeyParameterValue::MaxUsesPerBoot(1234567890),
2679 SecurityLevel::TRUSTED_ENVIRONMENT,
2680 ),
2681 KeyParameter::new(KeyParameterValue::UserID(1), SecurityLevel::STRONGBOX),
2682 KeyParameter::new(KeyParameterValue::UserSecureID(42), SecurityLevel::STRONGBOX),
2683 KeyParameter::new(
2684 KeyParameterValue::NoAuthRequired,
2685 SecurityLevel::TRUSTED_ENVIRONMENT,
2686 ),
2687 KeyParameter::new(
2688 KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType::PASSWORD),
2689 SecurityLevel::TRUSTED_ENVIRONMENT,
2690 ),
2691 KeyParameter::new(KeyParameterValue::AuthTimeout(1234567890), SecurityLevel::SOFTWARE),
2692 KeyParameter::new(KeyParameterValue::AllowWhileOnBody, SecurityLevel::SOFTWARE),
2693 KeyParameter::new(
2694 KeyParameterValue::TrustedUserPresenceRequired,
2695 SecurityLevel::TRUSTED_ENVIRONMENT,
2696 ),
2697 KeyParameter::new(
2698 KeyParameterValue::TrustedConfirmationRequired,
2699 SecurityLevel::TRUSTED_ENVIRONMENT,
2700 ),
2701 KeyParameter::new(
2702 KeyParameterValue::UnlockedDeviceRequired,
2703 SecurityLevel::TRUSTED_ENVIRONMENT,
2704 ),
2705 KeyParameter::new(
2706 KeyParameterValue::ApplicationID(vec![1u8, 2u8, 3u8, 4u8]),
2707 SecurityLevel::SOFTWARE,
2708 ),
2709 KeyParameter::new(
2710 KeyParameterValue::ApplicationData(vec![4u8, 3u8, 2u8, 1u8]),
2711 SecurityLevel::SOFTWARE,
2712 ),
2713 KeyParameter::new(
2714 KeyParameterValue::CreationDateTime(12345677890),
2715 SecurityLevel::SOFTWARE,
2716 ),
2717 KeyParameter::new(
2718 KeyParameterValue::KeyOrigin(KeyOrigin::GENERATED),
2719 SecurityLevel::TRUSTED_ENVIRONMENT,
2720 ),
2721 KeyParameter::new(
2722 KeyParameterValue::RootOfTrust(vec![3u8, 2u8, 1u8, 4u8]),
2723 SecurityLevel::TRUSTED_ENVIRONMENT,
2724 ),
2725 KeyParameter::new(KeyParameterValue::OSVersion(1), SecurityLevel::TRUSTED_ENVIRONMENT),
2726 KeyParameter::new(KeyParameterValue::OSPatchLevel(2), SecurityLevel::SOFTWARE),
2727 KeyParameter::new(
2728 KeyParameterValue::UniqueID(vec![4u8, 3u8, 1u8, 2u8]),
2729 SecurityLevel::SOFTWARE,
2730 ),
2731 KeyParameter::new(
2732 KeyParameterValue::AttestationChallenge(vec![4u8, 3u8, 1u8, 2u8]),
2733 SecurityLevel::TRUSTED_ENVIRONMENT,
2734 ),
2735 KeyParameter::new(
2736 KeyParameterValue::AttestationApplicationID(vec![4u8, 3u8, 1u8, 2u8]),
2737 SecurityLevel::TRUSTED_ENVIRONMENT,
2738 ),
2739 KeyParameter::new(
2740 KeyParameterValue::AttestationIdBrand(vec![4u8, 3u8, 1u8, 2u8]),
2741 SecurityLevel::TRUSTED_ENVIRONMENT,
2742 ),
2743 KeyParameter::new(
2744 KeyParameterValue::AttestationIdDevice(vec![4u8, 3u8, 1u8, 2u8]),
2745 SecurityLevel::TRUSTED_ENVIRONMENT,
2746 ),
2747 KeyParameter::new(
2748 KeyParameterValue::AttestationIdProduct(vec![4u8, 3u8, 1u8, 2u8]),
2749 SecurityLevel::TRUSTED_ENVIRONMENT,
2750 ),
2751 KeyParameter::new(
2752 KeyParameterValue::AttestationIdSerial(vec![4u8, 3u8, 1u8, 2u8]),
2753 SecurityLevel::TRUSTED_ENVIRONMENT,
2754 ),
2755 KeyParameter::new(
2756 KeyParameterValue::AttestationIdIMEI(vec![4u8, 3u8, 1u8, 2u8]),
2757 SecurityLevel::TRUSTED_ENVIRONMENT,
2758 ),
2759 KeyParameter::new(
2760 KeyParameterValue::AttestationIdMEID(vec![4u8, 3u8, 1u8, 2u8]),
2761 SecurityLevel::TRUSTED_ENVIRONMENT,
2762 ),
2763 KeyParameter::new(
2764 KeyParameterValue::AttestationIdManufacturer(vec![4u8, 3u8, 1u8, 2u8]),
2765 SecurityLevel::TRUSTED_ENVIRONMENT,
2766 ),
2767 KeyParameter::new(
2768 KeyParameterValue::AttestationIdModel(vec![4u8, 3u8, 1u8, 2u8]),
2769 SecurityLevel::TRUSTED_ENVIRONMENT,
2770 ),
2771 KeyParameter::new(
2772 KeyParameterValue::VendorPatchLevel(3),
2773 SecurityLevel::TRUSTED_ENVIRONMENT,
2774 ),
2775 KeyParameter::new(
2776 KeyParameterValue::BootPatchLevel(4),
2777 SecurityLevel::TRUSTED_ENVIRONMENT,
2778 ),
2779 KeyParameter::new(
2780 KeyParameterValue::AssociatedData(vec![4u8, 3u8, 1u8, 2u8]),
2781 SecurityLevel::TRUSTED_ENVIRONMENT,
2782 ),
2783 KeyParameter::new(
2784 KeyParameterValue::Nonce(vec![4u8, 3u8, 1u8, 2u8]),
2785 SecurityLevel::TRUSTED_ENVIRONMENT,
2786 ),
2787 KeyParameter::new(
2788 KeyParameterValue::MacLength(256),
2789 SecurityLevel::TRUSTED_ENVIRONMENT,
2790 ),
2791 KeyParameter::new(
2792 KeyParameterValue::ResetSinceIdRotation,
2793 SecurityLevel::TRUSTED_ENVIRONMENT,
2794 ),
2795 KeyParameter::new(
2796 KeyParameterValue::ConfirmationToken(vec![5u8, 5u8, 5u8, 5u8]),
2797 SecurityLevel::TRUSTED_ENVIRONMENT,
2798 ),
2799 ]
2800 }
2801
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002802 fn make_test_key_entry(
2803 db: &mut KeystoreDB,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07002804 domain: Domain,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002805 namespace: i64,
2806 alias: &str,
Janis Danisevskisaec14592020-11-12 09:41:49 -08002807 ) -> Result<KeyIdGuard> {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002808 let key_id = db.create_key_entry(domain, namespace)?;
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002809 db.insert_blob(&key_id, SubComponentType::KEY_BLOB, TEST_KEY_BLOB)?;
2810 db.insert_blob(&key_id, SubComponentType::CERT, TEST_CERT_BLOB)?;
2811 db.insert_blob(&key_id, SubComponentType::CERT_CHAIN, TEST_CERT_CHAIN_BLOB)?;
Janis Danisevskisaec14592020-11-12 09:41:49 -08002812 db.insert_keyparameter(&key_id, &make_test_params())?;
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002813 let mut metadata = KeyMetaData::new();
2814 metadata.add(KeyMetaEntry::EncryptedBy(EncryptedBy::Password));
2815 metadata.add(KeyMetaEntry::Salt(vec![1, 2, 3]));
2816 metadata.add(KeyMetaEntry::Iv(vec![2, 3, 1]));
2817 metadata.add(KeyMetaEntry::AeadTag(vec![3, 1, 2]));
2818 db.insert_key_metadata(&key_id, &metadata)?;
Janis Danisevskisaec14592020-11-12 09:41:49 -08002819 db.rebind_alias(&key_id, alias, domain, namespace)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002820 Ok(key_id)
2821 }
2822
Janis Danisevskisb42fc182020-12-15 08:41:27 -08002823 fn make_test_key_entry_test_vector(key_id: i64) -> KeyEntry {
2824 let mut metadata = KeyMetaData::new();
2825 metadata.add(KeyMetaEntry::EncryptedBy(EncryptedBy::Password));
2826 metadata.add(KeyMetaEntry::Salt(vec![1, 2, 3]));
2827 metadata.add(KeyMetaEntry::Iv(vec![2, 3, 1]));
2828 metadata.add(KeyMetaEntry::AeadTag(vec![3, 1, 2]));
2829
2830 KeyEntry {
2831 id: key_id,
2832 km_blob: Some(TEST_KEY_BLOB.to_vec()),
2833 cert: Some(TEST_CERT_BLOB.to_vec()),
2834 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
2835 sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
2836 parameters: make_test_params(),
2837 metadata,
2838 }
2839 }
2840
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002841 fn debug_dump_keyentry_table(db: &mut KeystoreDB) -> Result<()> {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002842 let mut stmt = db.conn.prepare(
2843 "SELECT id, key_type, domain, namespace, alias, state FROM persistent.keyentry;",
2844 )?;
2845 let rows = stmt.query_map::<(i64, KeyType, i32, i64, String, KeyLifeCycle), _, _>(
2846 NO_PARAMS,
2847 |row| {
2848 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?, row.get(4)?, row.get(5)?))
2849 },
2850 )?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002851
2852 println!("Key entry table rows:");
2853 for r in rows {
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002854 let (id, key_type, domain, namespace, alias, state) = r.unwrap();
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002855 println!(
Janis Danisevskis93927dd2020-12-23 12:23:08 -08002856 " id: {} KeyType: {:?} Domain: {} Namespace: {} Alias: {} State: {:?}",
2857 id, key_type, domain, namespace, alias, state
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002858 );
2859 }
2860 Ok(())
2861 }
2862
2863 fn debug_dump_grant_table(db: &mut KeystoreDB) -> Result<()> {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08002864 let mut stmt = db
2865 .conn
2866 .prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002867 let rows = stmt.query_map::<(i64, i64, i64, i64), _, _>(NO_PARAMS, |row| {
2868 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?))
2869 })?;
2870
2871 println!("Grant table rows:");
2872 for r in rows {
2873 let (id, gt, ki, av) = r.unwrap();
2874 println!(" id: {} grantee: {} key_id: {} access_vector: {}", id, gt, ki, av);
2875 }
2876 Ok(())
2877 }
2878
Joel Galenson0891bc12020-07-20 10:37:03 -07002879 // Use a custom random number generator that repeats each number once.
2880 // This allows us to test repeated elements.
2881
2882 thread_local! {
2883 static RANDOM_COUNTER: RefCell<i64> = RefCell::new(0);
2884 }
2885
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07002886 fn reset_random() {
2887 RANDOM_COUNTER.with(|counter| {
2888 *counter.borrow_mut() = 0;
2889 })
2890 }
2891
Joel Galenson0891bc12020-07-20 10:37:03 -07002892 pub fn random() -> i64 {
2893 RANDOM_COUNTER.with(|counter| {
2894 let result = *counter.borrow() / 2;
2895 *counter.borrow_mut() += 1;
2896 result
2897 })
2898 }
Joel Galenson26f4d012020-07-17 14:57:21 -07002899}