blob: 79944ebeb038028a39c7bc868976712ac232f4f4 [file] [log] [blame]
Joel Galenson26f4d012020-07-17 14:57:21 -07001// Copyright 2020, The Android Open Source Project
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7// http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070015//! This is the Keystore 2.0 database module.
16//! The database module provides a connection to the backing SQLite store.
17//! We have two databases one for persistent key blob storage and one for
18//! items that have a per boot life cycle.
19//!
20//! ## Persistent database
21//! The persistent database has tables for key blobs. They are organized
22//! as follows:
23//! The `keyentry` table is the primary table for key entries. It is
24//! accompanied by two tables for blobs and parameters.
25//! Each key entry occupies exactly one row in the `keyentry` table and
26//! zero or more rows in the tables `blobentry` and `keyparameter`.
27//!
28//! ## Per boot database
29//! The per boot database stores items with a per boot lifecycle.
30//! Currently, there is only the `grant` table in this database.
31//! Grants are references to a key that can be used to access a key by
32//! clients that don't own that key. Grants can only be created by the
33//! owner of a key. And only certain components can create grants.
34//! This is governed by SEPolicy.
35//!
36//! ## Access control
37//! Some database functions that load keys or create grants perform
38//! access control. This is because in some cases access control
39//! can only be performed after some information about the designated
40//! key was loaded from the database. To decouple the permission checks
41//! from the database module these functions take permission check
42//! callbacks.
Joel Galenson26f4d012020-07-17 14:57:21 -070043
Janis Danisevskis4522c2b2020-11-27 18:04:58 -080044use crate::db_utils::{self, SqlField};
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070045use crate::error::{Error as KsError, ResponseCode};
Janis Danisevskis4522c2b2020-11-27 18:04:58 -080046use crate::key_parameter::{KeyParameter, Tag};
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070047use crate::permission::KeyPermSet;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070048use anyhow::{anyhow, Context, Result};
Janis Danisevskis60400fe2020-08-26 15:24:42 -070049
Shawn Willden708744a2020-12-11 13:05:27 +000050use android_hardware_security_keymint::aidl::android::hardware::security::keymint::SecurityLevel::SecurityLevel;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -070051use android_system_keystore2::aidl::android::system::keystore2::{
Janis Danisevskis04b02832020-10-26 09:21:40 -070052 Domain::Domain, KeyDescriptor::KeyDescriptor,
Janis Danisevskis60400fe2020-08-26 15:24:42 -070053};
54
Janis Danisevskisaec14592020-11-12 09:41:49 -080055use lazy_static::lazy_static;
Joel Galenson0891bc12020-07-20 10:37:03 -070056#[cfg(not(test))]
57use rand::prelude::random;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070058use rusqlite::{
59 params, types::FromSql, types::FromSqlResult, types::ToSqlOutput, types::ValueRef, Connection,
Janis Danisevskisbf15d732020-12-08 10:35:26 -080060 OptionalExtension, ToSql, Transaction, TransactionBehavior, NO_PARAMS,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070061};
Janis Danisevskisaec14592020-11-12 09:41:49 -080062use std::{
63 collections::HashSet,
Janis Danisevskisbf15d732020-12-08 10:35:26 -080064 path::Path,
65 sync::{Condvar, Mutex},
Janis Danisevskisaec14592020-11-12 09:41:49 -080066};
Joel Galenson0891bc12020-07-20 10:37:03 -070067#[cfg(test)]
68use tests::random;
Joel Galenson26f4d012020-07-17 14:57:21 -070069
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070070/// Keys have a KeyMint blob component and optional public certificate and
71/// certificate chain components.
72/// KeyEntryLoadBits is a bitmap that indicates to `KeystoreDB::load_key_entry`
73/// which components shall be loaded from the database if present.
74#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
75pub struct KeyEntryLoadBits(u32);
76
77impl KeyEntryLoadBits {
78 /// Indicate to `KeystoreDB::load_key_entry` that no component shall be loaded.
79 pub const NONE: KeyEntryLoadBits = Self(0);
80 /// Indicate to `KeystoreDB::load_key_entry` that the KeyMint component shall be loaded.
81 pub const KM: KeyEntryLoadBits = Self(1);
82 /// Indicate to `KeystoreDB::load_key_entry` that the Public components shall be loaded.
83 pub const PUBLIC: KeyEntryLoadBits = Self(2);
84 /// Indicate to `KeystoreDB::load_key_entry` that both components shall be loaded.
85 pub const BOTH: KeyEntryLoadBits = Self(3);
86
87 /// Returns true if this object indicates that the public components shall be loaded.
88 pub const fn load_public(&self) -> bool {
89 self.0 & Self::PUBLIC.0 != 0
90 }
91
92 /// Returns true if the object indicates that the KeyMint component shall be loaded.
93 pub const fn load_km(&self) -> bool {
94 self.0 & Self::KM.0 != 0
95 }
96}
97
Janis Danisevskisaec14592020-11-12 09:41:49 -080098lazy_static! {
99 static ref KEY_ID_LOCK: KeyIdLockDb = KeyIdLockDb::new();
100}
101
102struct KeyIdLockDb {
103 locked_keys: Mutex<HashSet<i64>>,
104 cond_var: Condvar,
105}
106
107/// A locked key. While a guard exists for a given key id, the same key cannot be loaded
108/// from the database a second time. Most functions manipulating the key blob database
109/// require a KeyIdGuard.
110#[derive(Debug)]
111pub struct KeyIdGuard(i64);
112
113impl KeyIdLockDb {
114 fn new() -> Self {
115 Self { locked_keys: Mutex::new(HashSet::new()), cond_var: Condvar::new() }
116 }
117
118 /// This function blocks until an exclusive lock for the given key entry id can
119 /// be acquired. It returns a guard object, that represents the lifecycle of the
120 /// acquired lock.
121 pub fn get(&self, key_id: i64) -> KeyIdGuard {
122 let mut locked_keys = self.locked_keys.lock().unwrap();
123 while locked_keys.contains(&key_id) {
124 locked_keys = self.cond_var.wait(locked_keys).unwrap();
125 }
126 locked_keys.insert(key_id);
127 KeyIdGuard(key_id)
128 }
129
130 /// This function attempts to acquire an exclusive lock on a given key id. If the
131 /// given key id is already taken the function returns None immediately. If a lock
132 /// can be acquired this function returns a guard object, that represents the
133 /// lifecycle of the acquired lock.
134 pub fn try_get(&self, key_id: i64) -> Option<KeyIdGuard> {
135 let mut locked_keys = self.locked_keys.lock().unwrap();
136 if locked_keys.insert(key_id) {
137 Some(KeyIdGuard(key_id))
138 } else {
139 None
140 }
141 }
142}
143
144impl KeyIdGuard {
145 /// Get the numeric key id of the locked key.
146 pub fn id(&self) -> i64 {
147 self.0
148 }
149}
150
151impl Drop for KeyIdGuard {
152 fn drop(&mut self) {
153 let mut locked_keys = KEY_ID_LOCK.locked_keys.lock().unwrap();
154 locked_keys.remove(&self.0);
Janis Danisevskis7fd53582020-11-23 13:40:34 -0800155 drop(locked_keys);
Janis Danisevskisaec14592020-11-12 09:41:49 -0800156 KEY_ID_LOCK.cond_var.notify_all();
157 }
158}
159
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700160/// This type represents a Keystore 2.0 key entry.
161/// An entry has a unique `id` by which it can be found in the database.
162/// It has a security level field, key parameters, and three optional fields
163/// for the KeyMint blob, public certificate and a public certificate chain.
Janis Danisevskisaec14592020-11-12 09:41:49 -0800164#[derive(Debug, Default, Eq, PartialEq, Ord, PartialOrd)]
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700165pub struct KeyEntry {
166 id: i64,
167 km_blob: Option<Vec<u8>>,
168 cert: Option<Vec<u8>>,
169 cert_chain: Option<Vec<u8>>,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700170 sec_level: SecurityLevel,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700171 parameters: Vec<KeyParameter>,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700172}
173
174impl KeyEntry {
175 /// Returns the unique id of the Key entry.
176 pub fn id(&self) -> i64 {
177 self.id
178 }
179 /// Exposes the optional KeyMint blob.
180 pub fn km_blob(&self) -> &Option<Vec<u8>> {
181 &self.km_blob
182 }
183 /// Extracts the Optional KeyMint blob.
184 pub fn take_km_blob(&mut self) -> Option<Vec<u8>> {
185 self.km_blob.take()
186 }
187 /// Exposes the optional public certificate.
188 pub fn cert(&self) -> &Option<Vec<u8>> {
189 &self.cert
190 }
191 /// Extracts the optional public certificate.
192 pub fn take_cert(&mut self) -> Option<Vec<u8>> {
193 self.cert.take()
194 }
195 /// Exposes the optional public certificate chain.
196 pub fn cert_chain(&self) -> &Option<Vec<u8>> {
197 &self.cert_chain
198 }
199 /// Extracts the optional public certificate_chain.
200 pub fn take_cert_chain(&mut self) -> Option<Vec<u8>> {
201 self.cert_chain.take()
202 }
203 /// Returns the security level of the key entry.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700204 pub fn sec_level(&self) -> SecurityLevel {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700205 self.sec_level
206 }
Janis Danisevskis04b02832020-10-26 09:21:40 -0700207 /// Exposes the key parameters of this key entry.
208 pub fn key_parameters(&self) -> &Vec<KeyParameter> {
209 &self.parameters
210 }
211 /// Consumes this key entry and extracts the keyparameters from it.
212 pub fn into_key_parameters(self) -> Vec<KeyParameter> {
213 self.parameters
214 }
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700215}
216
217/// Indicates the sub component of a key entry for persistent storage.
218#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
219pub struct SubComponentType(u32);
220impl SubComponentType {
221 /// Persistent identifier for a KeyMint blob.
222 pub const KM_BLOB: SubComponentType = Self(0);
223 /// Persistent identifier for a certificate blob.
224 pub const CERT: SubComponentType = Self(1);
225 /// Persistent identifier for a certificate chain blob.
226 pub const CERT_CHAIN: SubComponentType = Self(2);
227}
228
229impl ToSql for SubComponentType {
230 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
231 self.0.to_sql()
232 }
233}
234
235impl FromSql for SubComponentType {
236 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
237 Ok(Self(u32::column_result(value)?))
238 }
239}
240
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700241/// KeystoreDB wraps a connection to an SQLite database and tracks its
242/// ownership. It also implements all of Keystore 2.0's database functionality.
Joel Galenson26f4d012020-07-17 14:57:21 -0700243pub struct KeystoreDB {
Joel Galenson26f4d012020-07-17 14:57:21 -0700244 conn: Connection,
245}
246
247impl KeystoreDB {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700248 /// This will create a new database connection connecting the two
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800249 /// files persistent.sqlite and perboot.sqlite in the given directory.
250 /// It also attempts to initialize all of the tables.
251 /// KeystoreDB cannot be used by multiple threads.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700252 /// Each thread should open their own connection using `thread_local!`.
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800253 pub fn new(db_root: &Path) -> Result<Self> {
254 // Build the path to the sqlite files.
255 let mut persistent_path = db_root.to_path_buf();
256 persistent_path.push("persistent.sqlite");
257 let mut perboot_path = db_root.to_path_buf();
258 perboot_path.push("perboot.sqlite");
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700259
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800260 // Now convert them to strings prefixed with "file:"
261 let mut persistent_path_str = "file:".to_owned();
262 persistent_path_str.push_str(&persistent_path.to_string_lossy());
263 let mut perboot_path_str = "file:".to_owned();
264 perboot_path_str.push_str(&perboot_path.to_string_lossy());
265
266 let conn = Self::make_connection(&persistent_path_str, &perboot_path_str)?;
267
268 Self::init_tables(&conn)?;
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700269 Ok(Self { conn })
Joel Galenson2aab4432020-07-22 15:27:57 -0700270 }
271
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700272 fn init_tables(conn: &Connection) -> Result<()> {
273 conn.execute(
274 "CREATE TABLE IF NOT EXISTS persistent.keyentry (
Joel Galenson0891bc12020-07-20 10:37:03 -0700275 id INTEGER UNIQUE,
276 creation_date DATETIME,
277 domain INTEGER,
278 namespace INTEGER,
Joel Galenson319bb652020-12-01 13:24:08 -0800279 alias BLOB);",
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700280 NO_PARAMS,
281 )
282 .context("Failed to initialize \"keyentry\" table.")?;
283
284 conn.execute(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700285 "CREATE VIEW IF NOT EXISTS persistent.orphaned AS
286 SELECT id FROM persistent.keyentry WHERE domain IS NULL;",
287 NO_PARAMS,
288 )
289 .context("Failed to initialize \"orphaned\" view")?;
290
291 conn.execute(
292 "CREATE TABLE IF NOT EXISTS persistent.blobentry (
293 id INTEGER PRIMARY KEY,
294 subcomponent_type INTEGER,
295 keyentryid INTEGER,
296 blob BLOB,
297 sec_level INTEGER);",
298 NO_PARAMS,
299 )
300 .context("Failed to initialize \"blobentry\" table.")?;
301
302 conn.execute(
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700303 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000304 keyentryid INTEGER,
305 tag INTEGER,
306 data ANY,
307 security_level INTEGER);",
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700308 NO_PARAMS,
309 )
310 .context("Failed to initialize \"keyparameter\" table.")?;
311
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700312 conn.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800313 "CREATE TABLE IF NOT EXISTS persistent.grant (
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700314 id INTEGER UNIQUE,
315 grantee INTEGER,
316 keyentryid INTEGER,
317 access_vector INTEGER);",
318 NO_PARAMS,
319 )
320 .context("Failed to initialize \"grant\" table.")?;
321
Joel Galenson0891bc12020-07-20 10:37:03 -0700322 Ok(())
323 }
324
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700325 fn make_connection(persistent_file: &str, perboot_file: &str) -> Result<Connection> {
326 let conn =
327 Connection::open_in_memory().context("Failed to initialize SQLite connection.")?;
328
329 conn.execute("ATTACH DATABASE ? as persistent;", params![persistent_file])
330 .context("Failed to attach database persistent.")?;
331 conn.execute("ATTACH DATABASE ? as perboot;", params![perboot_file])
332 .context("Failed to attach database perboot.")?;
333
334 Ok(conn)
335 }
336
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700337 /// Creates a new key entry and allocates a new randomized id for the new key.
338 /// The key id gets associated with a domain and namespace but not with an alias.
339 /// To complete key generation `rebind_alias` should be called after all of the
340 /// key artifacts, i.e., blobs and parameters have been associated with the new
341 /// key id. Finalizing with `rebind_alias` makes the creation of a new key entry
342 /// atomic even if key generation is not.
Janis Danisevskisaec14592020-11-12 09:41:49 -0800343 pub fn create_key_entry(&self, domain: Domain, namespace: i64) -> Result<KeyIdGuard> {
Joel Galenson0891bc12020-07-20 10:37:03 -0700344 match domain {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700345 Domain::APP | Domain::SELINUX => {}
Joel Galenson0891bc12020-07-20 10:37:03 -0700346 _ => {
347 return Err(KsError::sys())
348 .context(format!("Domain {:?} must be either App or SELinux.", domain));
349 }
350 }
Janis Danisevskisaec14592020-11-12 09:41:49 -0800351 Ok(KEY_ID_LOCK.get(
352 Self::insert_with_retry(|id| {
353 self.conn.execute(
354 "INSERT into persistent.keyentry (id, creation_date, domain, namespace, alias)
Joel Galenson0891bc12020-07-20 10:37:03 -0700355 VALUES(?, datetime('now'), ?, ?, NULL);",
Janis Danisevskisaec14592020-11-12 09:41:49 -0800356 params![id, domain.0 as u32, namespace],
357 )
358 })
359 .context("In create_key_entry")?,
360 ))
Joel Galenson26f4d012020-07-17 14:57:21 -0700361 }
Joel Galenson33c04ad2020-08-03 11:04:38 -0700362
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700363 /// Inserts a new blob and associates it with the given key id. Each blob
364 /// has a sub component type and a security level.
365 /// Each key can have one of each sub component type associated. If more
366 /// are added only the most recent can be retrieved, and superseded blobs
367 /// will get garbage collected. The security level field of components
368 /// other than `SubComponentType::KM_BLOB` are ignored.
369 pub fn insert_blob(
370 &mut self,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800371 key_id: &KeyIdGuard,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700372 sc_type: SubComponentType,
373 blob: &[u8],
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700374 sec_level: SecurityLevel,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700375 ) -> Result<()> {
376 self.conn
377 .execute(
378 "INSERT into persistent.blobentry (subcomponent_type, keyentryid, blob, sec_level)
379 VALUES (?, ?, ?, ?);",
Janis Danisevskisaec14592020-11-12 09:41:49 -0800380 params![sc_type, key_id.0, blob, sec_level.0],
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700381 )
382 .context("Failed to insert blob.")?;
383 Ok(())
384 }
385
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700386 /// Inserts a collection of key parameters into the `persistent.keyparameter` table
387 /// and associates them with the given `key_id`.
388 pub fn insert_keyparameter<'a>(
389 &mut self,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800390 key_id: &KeyIdGuard,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700391 params: impl IntoIterator<Item = &'a KeyParameter>,
392 ) -> Result<()> {
Janis Danisevskise92a5e62020-12-02 12:57:41 -0800393 let tx = self
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700394 .conn
Janis Danisevskise92a5e62020-12-02 12:57:41 -0800395 .transaction_with_behavior(TransactionBehavior::Immediate)
396 .context("In insert_keyparameter: Failed to start transaction.")?;
397 {
398 let mut stmt = tx
399 .prepare(
400 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700401 VALUES (?, ?, ?, ?);",
Janis Danisevskise92a5e62020-12-02 12:57:41 -0800402 )
403 .context("In insert_keyparameter: Failed to prepare statement.")?;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700404
Janis Danisevskise92a5e62020-12-02 12:57:41 -0800405 let iter = params.into_iter();
406 for p in iter {
407 stmt.insert(params![
408 key_id.0,
409 p.get_tag().0,
410 p.key_parameter_value(),
411 p.security_level().0
412 ])
413 .with_context(|| format!("In insert_keyparameter: Failed to insert {:?}", p))?;
414 }
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700415 }
Janis Danisevskise92a5e62020-12-02 12:57:41 -0800416 tx.commit().context("In insert_keyparameter: Failed to commit transaction.")?;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700417 Ok(())
418 }
419
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700420 /// Updates the alias column of the given key id `newid` with the given alias,
421 /// and atomically, removes the alias, domain, and namespace from another row
422 /// with the same alias-domain-namespace tuple if such row exits.
Joel Galenson33c04ad2020-08-03 11:04:38 -0700423 pub fn rebind_alias(
424 &mut self,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800425 newid: &KeyIdGuard,
Joel Galenson33c04ad2020-08-03 11:04:38 -0700426 alias: &str,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700427 domain: Domain,
Joel Galenson33c04ad2020-08-03 11:04:38 -0700428 namespace: i64,
429 ) -> Result<()> {
430 match domain {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700431 Domain::APP | Domain::SELINUX => {}
Joel Galenson33c04ad2020-08-03 11:04:38 -0700432 _ => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700433 return Err(KsError::sys()).context(format!(
434 "In rebind_alias: Domain {:?} must be either App or SELinux.",
435 domain
436 ));
Joel Galenson33c04ad2020-08-03 11:04:38 -0700437 }
438 }
439 let tx = self
440 .conn
441 .transaction_with_behavior(TransactionBehavior::Immediate)
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700442 .context("In rebind_alias: Failed to initialize transaction.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -0700443 tx.execute(
444 "UPDATE persistent.keyentry
445 SET alias = NULL, domain = NULL, namespace = NULL
446 WHERE alias = ? AND domain = ? AND namespace = ?;",
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700447 params![alias, domain.0 as u32, namespace],
Joel Galenson33c04ad2020-08-03 11:04:38 -0700448 )
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700449 .context("In rebind_alias: Failed to rebind existing entry.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -0700450 let result = tx
451 .execute(
452 "UPDATE persistent.keyentry
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700453 SET alias = ?
454 WHERE id = ? AND domain = ? AND namespace = ?;",
Janis Danisevskisaec14592020-11-12 09:41:49 -0800455 params![alias, newid.0, domain.0 as u32, namespace],
Joel Galenson33c04ad2020-08-03 11:04:38 -0700456 )
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700457 .context("In rebind_alias: Failed to set alias.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -0700458 if result != 1 {
459 // Note that this explicit rollback is not required, as
460 // the transaction should rollback if we do not commit it.
461 // We leave it here for readability.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700462 tx.rollback().context("In rebind_alias: Failed to rollback a failed transaction.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -0700463 return Err(KsError::sys()).context(format!(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700464 "In rebind_alias: Expected to update a single entry but instead updated {}.",
Joel Galenson33c04ad2020-08-03 11:04:38 -0700465 result
466 ));
467 }
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700468 tx.commit().context("In rebind_alias: Failed to commit transaction.")
469 }
470
471 // Helper function loading the key_id given the key descriptor
472 // tuple comprising domain, namespace, and alias.
473 // Requires a valid transaction.
474 fn load_key_entry_id(key: &KeyDescriptor, tx: &Transaction) -> Result<i64> {
475 let alias = key
476 .alias
477 .as_ref()
478 .map_or_else(|| Err(KsError::sys()), Ok)
479 .context("In load_key_entry_id: Alias must be specified.")?;
480 let mut stmt = tx
481 .prepare(
482 "SELECT id FROM persistent.keyentry
483 WHERE
484 domain = ?
485 AND namespace = ?
486 AND alias = ?;",
487 )
488 .context("In load_key_entry_id: Failed to select from keyentry table.")?;
489 let mut rows = stmt
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700490 .query(params![key.domain.0 as u32, key.nspace, alias])
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700491 .context("In load_key_entry_id: Failed to read from keyentry table.")?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800492 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700493 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700494 .get(0)
495 .context("Failed to unpack id.")
496 })
497 .context("In load_key_entry_id.")
498 }
499
500 /// This helper function completes the access tuple of a key, which is required
501 /// to perform access control. The strategy depends on the `domain` field in the
502 /// key descriptor.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700503 /// * Domain::SELINUX: The access tuple is complete and this function only loads
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700504 /// the key_id for further processing.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700505 /// * Domain::APP: Like Domain::SELINUX, but the tuple is completed by `caller_uid`
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700506 /// which serves as the namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700507 /// * Domain::GRANT: The grant table is queried for the `key_id` and the
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700508 /// `access_vector`.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700509 /// * Domain::KEY_ID: The keyentry table is queried for the owning `domain` and
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700510 /// `namespace`.
511 /// In each case the information returned is sufficient to perform the access
512 /// check and the key id can be used to load further key artifacts.
513 fn load_access_tuple(
514 tx: &Transaction,
515 key: KeyDescriptor,
516 caller_uid: u32,
517 ) -> Result<(i64, KeyDescriptor, Option<KeyPermSet>)> {
518 match key.domain {
519 // Domain App or SELinux. In this case we load the key_id from
520 // the keyentry database for further loading of key components.
521 // We already have the full access tuple to perform access control.
522 // The only distinction is that we use the caller_uid instead
523 // of the caller supplied namespace if the domain field is
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700524 // Domain::APP.
525 Domain::APP | Domain::SELINUX => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700526 let mut access_key = key;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700527 if access_key.domain == Domain::APP {
528 access_key.nspace = caller_uid as i64;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700529 }
530 let key_id = Self::load_key_entry_id(&access_key, &tx)
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700531 .with_context(|| format!("With key.domain = {:?}.", access_key.domain))?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700532
533 Ok((key_id, access_key, None))
534 }
535
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700536 // Domain::GRANT. In this case we load the key_id and the access_vector
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700537 // from the grant table.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700538 Domain::GRANT => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700539 let mut stmt = tx
540 .prepare(
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800541 "SELECT keyentryid, access_vector FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700542 WHERE grantee = ? AND id = ?;",
543 )
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700544 .context("Domain::GRANT prepare statement failed")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700545 let mut rows = stmt
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700546 .query(params![caller_uid as i64, key.nspace])
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700547 .context("Domain:Grant: query failed.")?;
548 let (key_id, access_vector): (i64, i32) =
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800549 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700550 let r =
551 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700552 Ok((
553 r.get(0).context("Failed to unpack key_id.")?,
554 r.get(1).context("Failed to unpack access_vector.")?,
555 ))
556 })
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700557 .context("Domain::GRANT.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700558 Ok((key_id, key, Some(access_vector.into())))
559 }
560
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700561 // Domain::KEY_ID. In this case we load the domain and namespace from the
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700562 // keyentry database because we need them for access control.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700563 Domain::KEY_ID => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700564 let mut stmt = tx
565 .prepare(
566 "SELECT domain, namespace FROM persistent.keyentry
567 WHERE
568 id = ?;",
569 )
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700570 .context("Domain::KEY_ID: prepare statement failed")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700571 let mut rows =
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700572 stmt.query(params![key.nspace]).context("Domain::KEY_ID: query failed.")?;
573 let (domain, namespace): (Domain, i64) =
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800574 db_utils::with_rows_extract_one(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700575 let r =
576 row.map_or_else(|| Err(KsError::Rc(ResponseCode::KEY_NOT_FOUND)), Ok)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700577 Ok((
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700578 Domain(r.get(0).context("Failed to unpack domain.")?),
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700579 r.get(1).context("Failed to unpack namespace.")?,
580 ))
581 })
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700582 .context("Domain::KEY_ID.")?;
583 let key_id = key.nspace;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700584 let mut access_key = key;
585 access_key.domain = domain;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700586 access_key.nspace = namespace;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700587
588 Ok((key_id, access_key, None))
589 }
590 _ => Err(anyhow!(KsError::sys())),
591 }
592 }
593
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700594 fn load_blob_components(
595 key_id: i64,
596 load_bits: KeyEntryLoadBits,
597 tx: &Transaction,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700598 ) -> Result<(SecurityLevel, Option<Vec<u8>>, Option<Vec<u8>>, Option<Vec<u8>>)> {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700599 let mut stmt = tx
600 .prepare(
601 "SELECT MAX(id), sec_level, subcomponent_type, blob FROM persistent.blobentry
602 WHERE keyentryid = ? GROUP BY subcomponent_type;",
603 )
604 .context("In load_blob_components: prepare statement failed.")?;
605
606 let mut rows =
607 stmt.query(params![key_id]).context("In load_blob_components: query failed.")?;
608
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700609 let mut sec_level: SecurityLevel = Default::default();
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700610 let mut km_blob: Option<Vec<u8>> = None;
611 let mut cert_blob: Option<Vec<u8>> = None;
612 let mut cert_chain_blob: Option<Vec<u8>> = None;
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800613 db_utils::with_rows_extract_all(&mut rows, |row| {
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700614 let sub_type: SubComponentType =
615 row.get(2).context("Failed to extract subcomponent_type.")?;
616 match (sub_type, load_bits.load_public()) {
617 (SubComponentType::KM_BLOB, _) => {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700618 sec_level =
619 SecurityLevel(row.get(1).context("Failed to extract security level.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700620 if load_bits.load_km() {
621 km_blob = Some(row.get(3).context("Failed to extract KM blob.")?);
622 }
623 }
624 (SubComponentType::CERT, true) => {
625 cert_blob =
626 Some(row.get(3).context("Failed to extract public certificate blob.")?);
627 }
628 (SubComponentType::CERT_CHAIN, true) => {
629 cert_chain_blob =
630 Some(row.get(3).context("Failed to extract certificate chain blob.")?);
631 }
632 (SubComponentType::CERT, _) | (SubComponentType::CERT_CHAIN, _) => {}
633 _ => Err(KsError::sys()).context("Unknown subcomponent type.")?,
634 }
635 Ok(())
636 })
637 .context("In load_blob_components.")?;
638
639 Ok((sec_level, km_blob, cert_blob, cert_chain_blob))
640 }
641
642 fn load_key_parameters(key_id: i64, tx: &Transaction) -> Result<Vec<KeyParameter>> {
643 let mut stmt = tx
644 .prepare(
645 "SELECT tag, data, security_level from persistent.keyparameter
646 WHERE keyentryid = ?;",
647 )
648 .context("In load_key_parameters: prepare statement failed.")?;
649
650 let mut parameters: Vec<KeyParameter> = Vec::new();
651
652 let mut rows =
653 stmt.query(params![key_id]).context("In load_key_parameters: query failed.")?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800654 db_utils::with_rows_extract_all(&mut rows, |row| {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700655 let tag = Tag(row.get(0).context("Failed to read tag.")?);
656 let sec_level = SecurityLevel(row.get(2).context("Failed to read sec_level.")?);
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700657 parameters.push(
658 KeyParameter::new_from_sql(tag, &SqlField::new(1, &row), sec_level)
659 .context("Failed to read KeyParameter.")?,
660 );
661 Ok(())
662 })
663 .context("In load_key_parameters.")?;
664
665 Ok(parameters)
666 }
667
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700668 /// Load a key entry by the given key descriptor.
669 /// It uses the `check_permission` callback to verify if the access is allowed
670 /// given the key access tuple read from the database using `load_access_tuple`.
671 /// With `load_bits` the caller may specify which blobs shall be loaded from
672 /// the blob database.
673 pub fn load_key_entry(
674 &mut self,
675 key: KeyDescriptor,
676 load_bits: KeyEntryLoadBits,
677 caller_uid: u32,
678 check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
Janis Danisevskisaec14592020-11-12 09:41:49 -0800679 ) -> Result<(KeyIdGuard, KeyEntry)> {
680 // KEY ID LOCK 1/2
681 // If we got a key descriptor with a key id we can get the lock right away.
682 // Otherwise we have to defer it until we know the key id.
683 let key_id_guard = match key.domain {
684 Domain::KEY_ID => Some(KEY_ID_LOCK.get(key.nspace)),
685 _ => None,
686 };
687
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700688 let tx = self
689 .conn
Janis Danisevskisaec14592020-11-12 09:41:49 -0800690 .unchecked_transaction()
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700691 .context("In load_key_entry: Failed to initialize transaction.")?;
692
693 // Load the key_id and complete the access control tuple.
694 let (key_id, access_key_descriptor, access_vector) =
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700695 Self::load_access_tuple(&tx, key, caller_uid).context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700696
697 // Perform access control. It is vital that we return here if the permission is denied.
698 // So do not touch that '?' at the end.
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700699 check_permission(&access_key_descriptor, access_vector).context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700700
Janis Danisevskisaec14592020-11-12 09:41:49 -0800701 // KEY ID LOCK 2/2
702 // If we did not get a key id lock by now, it was because we got a key descriptor
703 // without a key id. At this point we got the key id, so we can try and get a lock.
704 // However, we cannot block here, because we are in the middle of the transaction.
705 // So first we try to get the lock non blocking. If that fails, we roll back the
706 // transaction and block until we get the lock. After we successfully got the lock,
707 // we start a new transaction and load the access tuple again.
708 //
709 // We don't need to perform access control again, because we already established
710 // that the caller had access to the given key. But we need to make sure that the
711 // key id still exists. So we have to load the key entry by key id this time.
712 let (key_id_guard, tx) = match key_id_guard {
713 None => match KEY_ID_LOCK.try_get(key_id) {
714 None => {
715 // Roll back the transaction.
716 tx.rollback().context("In load_key_entry: Failed to roll back transaction.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700717
Janis Danisevskisaec14592020-11-12 09:41:49 -0800718 // Block until we have a key id lock.
719 let key_id_guard = KEY_ID_LOCK.get(key_id);
720
721 // Create a new transaction.
722 let tx = self.conn.unchecked_transaction().context(
723 "In load_key_entry: Failed to initialize transaction. (deferred key lock)",
724 )?;
725
726 Self::load_access_tuple(
727 &tx,
728 // This time we have to load the key by the retrieved key id, because the
729 // alias may have been rebound after we rolled back the transaction.
730 KeyDescriptor {
731 domain: Domain::KEY_ID,
732 nspace: key_id,
733 ..Default::default()
734 },
735 caller_uid,
736 )
737 .context("In load_key_entry. (deferred key lock)")?;
738 (key_id_guard, tx)
739 }
740 Some(l) => (l, tx),
741 },
742 Some(key_id_guard) => (key_id_guard, tx),
743 };
744
745 let (sec_level, km_blob, cert_blob, cert_chain_blob) =
746 Self::load_blob_components(key_id_guard.id(), load_bits, &tx)
747 .context("In load_key_entry.")?;
748
749 let parameters =
750 Self::load_key_parameters(key_id_guard.id(), &tx).context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700751
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700752 tx.commit().context("In load_key_entry: Failed to commit transaction.")?;
753
Janis Danisevskisaec14592020-11-12 09:41:49 -0800754 let key_id = key_id_guard.id();
755 Ok((
756 key_id_guard,
757 KeyEntry {
758 id: key_id,
759 km_blob,
760 cert: cert_blob,
761 cert_chain: cert_chain_blob,
762 sec_level,
763 parameters,
764 },
765 ))
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700766 }
767
Janis Danisevskise92a5e62020-12-02 12:57:41 -0800768 /// Returns a list of KeyDescriptors in the selected domain/namespace.
769 /// The key descriptors will have the domain, nspace, and alias field set.
770 /// Domain must be APP or SELINUX, the caller must make sure of that.
771 pub fn list(&mut self, domain: Domain, namespace: i64) -> Result<Vec<KeyDescriptor>> {
772 let mut stmt = self
773 .conn
774 .prepare(
775 "SELECT alias FROM persistent.keyentry
776 WHERE domain = ? AND namespace = ? AND alias IS NOT NULL;",
777 )
778 .context("In list: Failed to prepare.")?;
779
780 let mut rows =
781 stmt.query(params![domain.0 as u32, namespace]).context("In list: Failed to query.")?;
782
783 let mut descriptors: Vec<KeyDescriptor> = Vec::new();
784 db_utils::with_rows_extract_all(&mut rows, |row| {
785 descriptors.push(KeyDescriptor {
786 domain,
787 nspace: namespace,
788 alias: Some(row.get(0).context("Trying to extract alias.")?),
789 blob: None,
790 });
791 Ok(())
792 })
793 .context("In list.")?;
794 Ok(descriptors)
795 }
796
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700797 /// Adds a grant to the grant table.
798 /// Like `load_key_entry` this function loads the access tuple before
799 /// it uses the callback for a permission check. Upon success,
800 /// it inserts the `grantee_uid`, `key_id`, and `access_vector` into the
801 /// grant table. The new row will have a randomized id, which is used as
802 /// grant id in the namespace field of the resulting KeyDescriptor.
803 pub fn grant(
804 &mut self,
805 key: KeyDescriptor,
806 caller_uid: u32,
807 grantee_uid: u32,
808 access_vector: KeyPermSet,
809 check_permission: impl FnOnce(&KeyDescriptor, &KeyPermSet) -> Result<()>,
810 ) -> Result<KeyDescriptor> {
811 let tx = self
812 .conn
813 .transaction_with_behavior(TransactionBehavior::Immediate)
814 .context("In grant: Failed to initialize transaction.")?;
815
816 // Load the key_id and complete the access control tuple.
817 // We ignore the access vector here because grants cannot be granted.
818 // The access vector returned here expresses the permissions the
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700819 // grantee has if key.domain == Domain::GRANT. But this vector
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700820 // cannot include the grant permission by design, so there is no way the
821 // subsequent permission check can pass.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700822 // We could check key.domain == Domain::GRANT and fail early.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700823 // But even if we load the access tuple by grant here, the permission
824 // check denies the attempt to create a grant by grant descriptor.
825 let (key_id, access_key_descriptor, _) =
826 Self::load_access_tuple(&tx, key, caller_uid).context("In grant")?;
827
828 // Perform access control. It is vital that we return here if the permission
829 // was denied. So do not touch that '?' at the end of the line.
830 // This permission check checks if the caller has the grant permission
831 // for the given key and in addition to all of the permissions
832 // expressed in `access_vector`.
833 check_permission(&access_key_descriptor, &access_vector)
834 .context("In grant: check_permission failed.")?;
835
836 let grant_id = if let Some(grant_id) = tx
837 .query_row(
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800838 "SELECT id FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700839 WHERE keyentryid = ? AND grantee = ?;",
840 params![key_id, grantee_uid],
841 |row| row.get(0),
842 )
843 .optional()
844 .context("In grant: Failed get optional existing grant id.")?
845 {
846 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800847 "UPDATE persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700848 SET access_vector = ?
849 WHERE id = ?;",
850 params![i32::from(access_vector), grant_id],
851 )
852 .context("In grant: Failed to update existing grant.")?;
853 grant_id
854 } else {
Joel Galenson845f74b2020-09-09 14:11:55 -0700855 Self::insert_with_retry(|id| {
856 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800857 "INSERT INTO persistent.grant (id, grantee, keyentryid, access_vector)
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700858 VALUES (?, ?, ?, ?);",
Joel Galenson845f74b2020-09-09 14:11:55 -0700859 params![id, grantee_uid, key_id, i32::from(access_vector)],
860 )
861 })
862 .context("In grant")?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700863 };
864 tx.commit().context("In grant: failed to commit transaction.")?;
865
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700866 Ok(KeyDescriptor { domain: Domain::GRANT, nspace: grant_id, alias: None, blob: None })
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700867 }
868
869 /// This function checks permissions like `grant` and `load_key_entry`
870 /// before removing a grant from the grant table.
871 pub fn ungrant(
872 &mut self,
873 key: KeyDescriptor,
874 caller_uid: u32,
875 grantee_uid: u32,
876 check_permission: impl FnOnce(&KeyDescriptor) -> Result<()>,
877 ) -> Result<()> {
878 let tx = self
879 .conn
880 .transaction_with_behavior(TransactionBehavior::Immediate)
881 .context("In ungrant: Failed to initialize transaction.")?;
882
883 // Load the key_id and complete the access control tuple.
884 // We ignore the access vector here because grants cannot be granted.
885 let (key_id, access_key_descriptor, _) =
886 Self::load_access_tuple(&tx, key, caller_uid).context("In ungrant.")?;
887
888 // Perform access control. We must return here if the permission
889 // was denied. So do not touch the '?' at the end of this line.
890 check_permission(&access_key_descriptor).context("In grant: check_permission failed.")?;
891
892 tx.execute(
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800893 "DELETE FROM persistent.grant
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700894 WHERE keyentryid = ? AND grantee = ?;",
895 params![key_id, grantee_uid],
896 )
897 .context("Failed to delete grant.")?;
898
899 tx.commit().context("In ungrant: failed to commit transaction.")?;
900
901 Ok(())
902 }
903
Joel Galenson845f74b2020-09-09 14:11:55 -0700904 // Generates a random id and passes it to the given function, which will
905 // try to insert it into a database. If that insertion fails, retry;
906 // otherwise return the id.
907 fn insert_with_retry(inserter: impl Fn(i64) -> rusqlite::Result<usize>) -> Result<i64> {
908 loop {
909 let newid: i64 = random();
910 match inserter(newid) {
911 // If the id already existed, try again.
912 Err(rusqlite::Error::SqliteFailure(
913 libsqlite3_sys::Error {
914 code: libsqlite3_sys::ErrorCode::ConstraintViolation,
915 extended_code: libsqlite3_sys::SQLITE_CONSTRAINT_UNIQUE,
916 },
917 _,
918 )) => (),
919 Err(e) => {
920 return Err(e).context("In insert_with_retry: failed to insert into database.")
921 }
922 _ => return Ok(newid),
923 }
924 }
925 }
Joel Galenson26f4d012020-07-17 14:57:21 -0700926}
927
928#[cfg(test)]
929mod tests {
930
931 use super::*;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700932 use crate::key_parameter::{
933 Algorithm, BlockMode, Digest, EcCurve, HardwareAuthenticatorType, KeyOrigin, KeyParameter,
934 KeyParameterValue, KeyPurpose, PaddingMode, SecurityLevel,
935 };
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700936 use crate::key_perm_set;
937 use crate::permission::{KeyPerm, KeyPermSet};
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800938 use crate::test::utils::TempDir;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700939 use rusqlite::NO_PARAMS;
Joel Galenson0891bc12020-07-20 10:37:03 -0700940 use std::cell::RefCell;
Janis Danisevskisaec14592020-11-12 09:41:49 -0800941 use std::sync::atomic::{AtomicU8, Ordering};
942 use std::sync::Arc;
943 use std::thread;
Joel Galenson0891bc12020-07-20 10:37:03 -0700944
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700945 fn new_test_db() -> Result<KeystoreDB> {
946 let conn = KeystoreDB::make_connection("file::memory:", "file::memory:")?;
947
948 KeystoreDB::init_tables(&conn).context("Failed to initialize tables.")?;
949 Ok(KeystoreDB { conn })
950 }
951
Joel Galenson0891bc12020-07-20 10:37:03 -0700952 // Ensure that we're using the "injected" random function, not the real one.
953 #[test]
954 fn test_mocked_random() {
955 let rand1 = random();
956 let rand2 = random();
957 let rand3 = random();
958 if rand1 == rand2 {
959 assert_eq!(rand2 + 1, rand3);
960 } else {
961 assert_eq!(rand1 + 1, rand2);
962 assert_eq!(rand2, rand3);
963 }
964 }
Joel Galenson26f4d012020-07-17 14:57:21 -0700965
Joel Galenson26f4d012020-07-17 14:57:21 -0700966 // Test that we have the correct tables.
967 #[test]
968 fn test_tables() -> Result<()> {
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700969 let db = new_test_db()?;
Joel Galenson26f4d012020-07-17 14:57:21 -0700970 let tables = db
971 .conn
Joel Galenson2aab4432020-07-22 15:27:57 -0700972 .prepare("SELECT name from persistent.sqlite_master WHERE type='table' ORDER BY name;")?
Joel Galenson26f4d012020-07-17 14:57:21 -0700973 .query_map(params![], |row| row.get(0))?
974 .collect::<rusqlite::Result<Vec<String>>>()?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800975 assert_eq!(tables.len(), 4);
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700976 assert_eq!(tables[0], "blobentry");
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800977 assert_eq!(tables[1], "grant");
978 assert_eq!(tables[2], "keyentry");
979 assert_eq!(tables[3], "keyparameter");
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700980 let tables = db
981 .conn
982 .prepare("SELECT name from perboot.sqlite_master WHERE type='table' ORDER BY name;")?
983 .query_map(params![], |row| row.get(0))?
984 .collect::<rusqlite::Result<Vec<String>>>()?;
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800985 assert_eq!(tables.len(), 0);
Joel Galenson2aab4432020-07-22 15:27:57 -0700986 Ok(())
987 }
988
989 #[test]
990 fn test_persistence_for_files() -> Result<()> {
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800991 let temp_dir = TempDir::new("persistent_db_test")?;
992 let db = KeystoreDB::new(temp_dir.path())?;
Joel Galenson2aab4432020-07-22 15:27:57 -0700993
Janis Danisevskisc5b210b2020-09-11 13:27:37 -0700994 db.create_key_entry(Domain::APP, 100)?;
Joel Galenson2aab4432020-07-22 15:27:57 -0700995 let entries = get_keyentry(&db)?;
996 assert_eq!(entries.len(), 1);
Janis Danisevskisbf15d732020-12-08 10:35:26 -0800997
998 let db = KeystoreDB::new(temp_dir.path())?;
Joel Galenson2aab4432020-07-22 15:27:57 -0700999
1000 let entries_new = get_keyentry(&db)?;
1001 assert_eq!(entries, entries_new);
1002 Ok(())
1003 }
1004
1005 #[test]
Joel Galenson0891bc12020-07-20 10:37:03 -07001006 fn test_create_key_entry() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001007 fn extractor(ke: &KeyEntryRow) -> (Domain, i64, Option<&str>) {
Joel Galenson0891bc12020-07-20 10:37:03 -07001008 (ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref())
1009 }
1010
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001011 let db = new_test_db()?;
Joel Galenson0891bc12020-07-20 10:37:03 -07001012
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001013 db.create_key_entry(Domain::APP, 100)?;
1014 db.create_key_entry(Domain::SELINUX, 101)?;
Joel Galenson0891bc12020-07-20 10:37:03 -07001015
1016 let entries = get_keyentry(&db)?;
1017 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001018 assert_eq!(extractor(&entries[0]), (Domain::APP, 100, None));
1019 assert_eq!(extractor(&entries[1]), (Domain::SELINUX, 101, None));
Joel Galenson0891bc12020-07-20 10:37:03 -07001020
1021 // Test that we must pass in a valid Domain.
1022 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001023 db.create_key_entry(Domain::GRANT, 102),
1024 "Domain Domain(1) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07001025 );
1026 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001027 db.create_key_entry(Domain::BLOB, 103),
1028 "Domain Domain(3) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07001029 );
1030 check_result_is_error_containing_string(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001031 db.create_key_entry(Domain::KEY_ID, 104),
1032 "Domain Domain(4) must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -07001033 );
1034
1035 Ok(())
1036 }
1037
Joel Galenson33c04ad2020-08-03 11:04:38 -07001038 #[test]
1039 fn test_rebind_alias() -> Result<()> {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001040 fn extractor(ke: &KeyEntryRow) -> (Option<Domain>, Option<i64>, Option<&str>) {
Joel Galenson33c04ad2020-08-03 11:04:38 -07001041 (ke.domain, ke.namespace, ke.alias.as_deref())
1042 }
1043
Janis Danisevskis4df44f42020-08-26 14:40:03 -07001044 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001045 db.create_key_entry(Domain::APP, 42)?;
1046 db.create_key_entry(Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07001047 let entries = get_keyentry(&db)?;
1048 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001049 assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), None));
1050 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
Joel Galenson33c04ad2020-08-03 11:04:38 -07001051
1052 // Test that the first call to rebind_alias sets the alias.
Janis Danisevskisaec14592020-11-12 09:41:49 -08001053 db.rebind_alias(&KEY_ID_LOCK.get(entries[0].id), "foo", Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07001054 let entries = get_keyentry(&db)?;
1055 assert_eq!(entries.len(), 2);
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001056 assert_eq!(extractor(&entries[0]), (Some(Domain::APP), Some(42), Some("foo")));
1057 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), None));
Joel Galenson33c04ad2020-08-03 11:04:38 -07001058
1059 // Test that the second call to rebind_alias also empties the old one.
Janis Danisevskisaec14592020-11-12 09:41:49 -08001060 db.rebind_alias(&KEY_ID_LOCK.get(entries[1].id), "foo", Domain::APP, 42)?;
Joel Galenson33c04ad2020-08-03 11:04:38 -07001061 let entries = get_keyentry(&db)?;
1062 assert_eq!(entries.len(), 2);
Joel Galenson7fa5c412020-11-19 10:56:54 -08001063 assert_eq!(extractor(&entries[0]), (None, None, None));
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001064 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
Joel Galenson33c04ad2020-08-03 11:04:38 -07001065
1066 // Test that we must pass in a valid Domain.
1067 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001068 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::GRANT, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001069 "Domain Domain(1) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07001070 );
1071 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001072 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::BLOB, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001073 "Domain Domain(3) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07001074 );
1075 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001076 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::KEY_ID, 42),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001077 "Domain Domain(4) must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -07001078 );
1079
1080 // Test that we correctly handle setting an alias for something that does not exist.
1081 check_result_is_error_containing_string(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001082 db.rebind_alias(&KEY_ID_LOCK.get(0), "foo", Domain::SELINUX, 42),
Joel Galenson33c04ad2020-08-03 11:04:38 -07001083 "Expected to update a single entry but instead updated 0",
1084 );
1085 // Test that we correctly abort the transaction in this case.
1086 let entries = get_keyentry(&db)?;
1087 assert_eq!(entries.len(), 2);
Joel Galenson7fa5c412020-11-19 10:56:54 -08001088 assert_eq!(extractor(&entries[0]), (None, None, None));
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001089 assert_eq!(extractor(&entries[1]), (Some(Domain::APP), Some(42), Some("foo")));
Joel Galenson33c04ad2020-08-03 11:04:38 -07001090
1091 Ok(())
1092 }
1093
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001094 #[test]
1095 fn test_grant_ungrant() -> Result<()> {
1096 const CALLER_UID: u32 = 15;
1097 const GRANTEE_UID: u32 = 12;
1098 const SELINUX_NAMESPACE: i64 = 7;
1099
1100 let mut db = new_test_db()?;
1101 db.conn.execute(
1102 "INSERT INTO persistent.keyentry (id, creation_date, domain, namespace, alias)
1103 VALUES (1, '1980', 0, 15, 'key'), (2, '1980', 2, 7, 'yek');",
1104 NO_PARAMS,
1105 )?;
1106 let app_key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001107 domain: super::Domain::APP,
1108 nspace: 0,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001109 alias: Some("key".to_string()),
1110 blob: None,
1111 };
1112 const PVEC1: KeyPermSet = key_perm_set![KeyPerm::use_(), KeyPerm::get_info()];
1113 const PVEC2: KeyPermSet = key_perm_set![KeyPerm::use_()];
1114
1115 // Reset totally predictable random number generator in case we
1116 // are not the first test running on this thread.
1117 reset_random();
1118 let next_random = 0i64;
1119
1120 let app_granted_key =
1121 db.grant(app_key.clone(), CALLER_UID, GRANTEE_UID, PVEC1, |k, a| {
1122 assert_eq!(*a, PVEC1);
1123 assert_eq!(
1124 *k,
1125 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001126 domain: super::Domain::APP,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001127 // namespace must be set to the caller_uid.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001128 nspace: CALLER_UID as i64,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001129 alias: Some("key".to_string()),
1130 blob: None,
1131 }
1132 );
1133 Ok(())
1134 })?;
1135
1136 assert_eq!(
1137 app_granted_key,
1138 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001139 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001140 // The grantid is next_random due to the mock random number generator.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001141 nspace: next_random,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001142 alias: None,
1143 blob: None,
1144 }
1145 );
1146
1147 let selinux_key = KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001148 domain: super::Domain::SELINUX,
1149 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001150 alias: Some("yek".to_string()),
1151 blob: None,
1152 };
1153
1154 let selinux_granted_key =
1155 db.grant(selinux_key.clone(), CALLER_UID, 12, PVEC1, |k, a| {
1156 assert_eq!(*a, PVEC1);
1157 assert_eq!(
1158 *k,
1159 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001160 domain: super::Domain::SELINUX,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001161 // namespace must be the supplied SELinux
1162 // namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001163 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001164 alias: Some("yek".to_string()),
1165 blob: None,
1166 }
1167 );
1168 Ok(())
1169 })?;
1170
1171 assert_eq!(
1172 selinux_granted_key,
1173 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001174 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001175 // The grantid is next_random + 1 due to the mock random number generator.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001176 nspace: next_random + 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001177 alias: None,
1178 blob: None,
1179 }
1180 );
1181
1182 // This should update the existing grant with PVEC2.
1183 let selinux_granted_key =
1184 db.grant(selinux_key.clone(), CALLER_UID, 12, PVEC2, |k, a| {
1185 assert_eq!(*a, PVEC2);
1186 assert_eq!(
1187 *k,
1188 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001189 domain: super::Domain::SELINUX,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001190 // namespace must be the supplied SELinux
1191 // namespace.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001192 nspace: SELINUX_NAMESPACE,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001193 alias: Some("yek".to_string()),
1194 blob: None,
1195 }
1196 );
1197 Ok(())
1198 })?;
1199
1200 assert_eq!(
1201 selinux_granted_key,
1202 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001203 domain: super::Domain::GRANT,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001204 // Same grant id as before. The entry was only updated.
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001205 nspace: next_random + 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001206 alias: None,
1207 blob: None,
1208 }
1209 );
1210
1211 {
1212 // Limiting scope of stmt, because it borrows db.
1213 let mut stmt = db
1214 .conn
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001215 .prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?;
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07001216 let mut rows =
1217 stmt.query_map::<(i64, u32, i64, KeyPermSet), _, _>(NO_PARAMS, |row| {
1218 Ok((
1219 row.get(0)?,
1220 row.get(1)?,
1221 row.get(2)?,
1222 KeyPermSet::from(row.get::<_, i32>(3)?),
1223 ))
1224 })?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001225
1226 let r = rows.next().unwrap().unwrap();
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07001227 assert_eq!(r, (next_random, GRANTEE_UID, 1, PVEC1));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001228 let r = rows.next().unwrap().unwrap();
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07001229 assert_eq!(r, (next_random + 1, GRANTEE_UID, 2, PVEC2));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001230 assert!(rows.next().is_none());
1231 }
1232
1233 debug_dump_keyentry_table(&mut db)?;
1234 println!("app_key {:?}", app_key);
1235 println!("selinux_key {:?}", selinux_key);
1236
1237 db.ungrant(app_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
1238 db.ungrant(selinux_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
1239
1240 Ok(())
1241 }
1242
1243 static TEST_KM_BLOB: &[u8] = b"my test blob";
1244 static TEST_CERT_BLOB: &[u8] = b"my test cert";
1245 static TEST_CERT_CHAIN_BLOB: &[u8] = b"my test cert_chain";
1246
1247 #[test]
1248 fn test_insert_blob() -> Result<()> {
1249 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001250 db.insert_blob(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001251 &KEY_ID_LOCK.get(1),
1252 SubComponentType::KM_BLOB,
1253 TEST_KM_BLOB,
1254 SecurityLevel::SOFTWARE,
1255 )?;
1256 db.insert_blob(
1257 &KEY_ID_LOCK.get(1),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001258 SubComponentType::CERT,
1259 TEST_CERT_BLOB,
1260 SecurityLevel::TRUSTED_ENVIRONMENT,
1261 )?;
1262 db.insert_blob(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001263 &KEY_ID_LOCK.get(1),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001264 SubComponentType::CERT_CHAIN,
1265 TEST_CERT_CHAIN_BLOB,
1266 SecurityLevel::STRONGBOX,
1267 )?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001268
1269 let mut stmt = db.conn.prepare(
1270 "SELECT subcomponent_type, keyentryid, blob, sec_level FROM persistent.blobentry
1271 ORDER BY sec_level ASC;",
1272 )?;
1273 let mut rows = stmt
1274 .query_map::<(SubComponentType, i64, Vec<u8>, i64), _, _>(NO_PARAMS, |row| {
1275 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?))
1276 })?;
1277 let r = rows.next().unwrap().unwrap();
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001278 assert_eq!(r, (SubComponentType::KM_BLOB, 1, TEST_KM_BLOB.to_vec(), 0));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001279 let r = rows.next().unwrap().unwrap();
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001280 assert_eq!(r, (SubComponentType::CERT, 1, TEST_CERT_BLOB.to_vec(), 1));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001281 let r = rows.next().unwrap().unwrap();
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001282 assert_eq!(r, (SubComponentType::CERT_CHAIN, 1, TEST_CERT_CHAIN_BLOB.to_vec(), 2));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001283
1284 Ok(())
1285 }
1286
1287 static TEST_ALIAS: &str = "my super duper key";
1288
1289 #[test]
1290 fn test_insert_and_load_full_keyentry_domain_app() -> Result<()> {
1291 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001292 let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08001293 .context("test_insert_and_load_full_keyentry_domain_app")?
1294 .0;
1295 let (_key_guard, key_entry) = db.load_key_entry(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001296 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001297 domain: Domain::APP,
1298 nspace: 0,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001299 alias: Some(TEST_ALIAS.to_string()),
1300 blob: None,
1301 },
1302 KeyEntryLoadBits::BOTH,
1303 1,
1304 |_k, _av| Ok(()),
1305 )?;
1306 assert_eq!(
1307 key_entry,
1308 KeyEntry {
1309 id: key_id,
1310 km_blob: Some(TEST_KM_BLOB.to_vec()),
1311 cert: Some(TEST_CERT_BLOB.to_vec()),
1312 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001313 sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001314 parameters: make_test_params(),
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001315 }
1316 );
1317 Ok(())
1318 }
1319
1320 #[test]
1321 fn test_insert_and_load_full_keyentry_domain_selinux() -> Result<()> {
1322 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001323 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08001324 .context("test_insert_and_load_full_keyentry_domain_selinux")?
1325 .0;
1326 let (_key_guard, key_entry) = db.load_key_entry(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001327 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001328 domain: Domain::SELINUX,
1329 nspace: 1,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001330 alias: Some(TEST_ALIAS.to_string()),
1331 blob: None,
1332 },
1333 KeyEntryLoadBits::BOTH,
1334 1,
1335 |_k, _av| Ok(()),
1336 )?;
1337 assert_eq!(
1338 key_entry,
1339 KeyEntry {
1340 id: key_id,
1341 km_blob: Some(TEST_KM_BLOB.to_vec()),
1342 cert: Some(TEST_CERT_BLOB.to_vec()),
1343 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001344 sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001345 parameters: make_test_params(),
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001346 }
1347 );
1348 Ok(())
1349 }
1350
1351 #[test]
1352 fn test_insert_and_load_full_keyentry_domain_key_id() -> Result<()> {
1353 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001354 let key_id = make_test_key_entry(&mut db, Domain::SELINUX, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08001355 .context("test_insert_and_load_full_keyentry_domain_key_id")?
1356 .0;
1357 let (_key_guard, key_entry) = db.load_key_entry(
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001358 KeyDescriptor { domain: Domain::KEY_ID, nspace: key_id, alias: None, blob: None },
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001359 KeyEntryLoadBits::BOTH,
1360 1,
1361 |_k, _av| Ok(()),
1362 )?;
1363 assert_eq!(
1364 key_entry,
1365 KeyEntry {
1366 id: key_id,
1367 km_blob: Some(TEST_KM_BLOB.to_vec()),
1368 cert: Some(TEST_CERT_BLOB.to_vec()),
1369 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001370 sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001371 parameters: make_test_params(),
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001372 }
1373 );
1374
1375 Ok(())
1376 }
1377
1378 #[test]
1379 fn test_insert_and_load_full_keyentry_from_grant() -> Result<()> {
1380 let mut db = new_test_db()?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001381 let key_id = make_test_key_entry(&mut db, Domain::APP, 1, TEST_ALIAS)
Janis Danisevskisaec14592020-11-12 09:41:49 -08001382 .context("test_insert_and_load_full_keyentry_from_grant")?
1383 .0;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001384
1385 let granted_key = db.grant(
1386 KeyDescriptor {
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001387 domain: Domain::APP,
1388 nspace: 0,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001389 alias: Some(TEST_ALIAS.to_string()),
1390 blob: None,
1391 },
1392 1,
1393 2,
1394 key_perm_set![KeyPerm::use_()],
1395 |_k, _av| Ok(()),
1396 )?;
1397
1398 debug_dump_grant_table(&mut db)?;
1399
Janis Danisevskisaec14592020-11-12 09:41:49 -08001400 let (_key_guard, key_entry) =
1401 db.load_key_entry(granted_key, KeyEntryLoadBits::BOTH, 2, |k, av| {
1402 assert_eq!(Domain::GRANT, k.domain);
1403 assert!(av.unwrap().includes(KeyPerm::use_()));
1404 Ok(())
1405 })?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001406
1407 assert_eq!(
1408 key_entry,
1409 KeyEntry {
1410 id: key_id,
1411 km_blob: Some(TEST_KM_BLOB.to_vec()),
1412 cert: Some(TEST_CERT_BLOB.to_vec()),
1413 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001414 sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001415 parameters: make_test_params(),
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001416 }
1417 );
1418 Ok(())
1419 }
1420
Janis Danisevskisaec14592020-11-12 09:41:49 -08001421 static KEY_LOCK_TEST_ALIAS: &str = "my super duper locked key";
1422
Janis Danisevskisaec14592020-11-12 09:41:49 -08001423 #[test]
1424 fn test_insert_and_load_full_keyentry_domain_app_concurrently() -> Result<()> {
1425 let handle = {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001426 let temp_dir = Arc::new(TempDir::new("id_lock_test")?);
1427 let temp_dir_clone = temp_dir.clone();
1428 let mut db = KeystoreDB::new(temp_dir.path())?;
Janis Danisevskisaec14592020-11-12 09:41:49 -08001429 let key_id = make_test_key_entry(&mut db, Domain::APP, 33, KEY_LOCK_TEST_ALIAS)
1430 .context("test_insert_and_load_full_keyentry_domain_app")?
1431 .0;
1432 let (_key_guard, key_entry) = db.load_key_entry(
1433 KeyDescriptor {
1434 domain: Domain::APP,
1435 nspace: 0,
1436 alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
1437 blob: None,
1438 },
1439 KeyEntryLoadBits::BOTH,
1440 33,
1441 |_k, _av| Ok(()),
1442 )?;
1443 assert_eq!(
1444 key_entry,
1445 KeyEntry {
1446 id: key_id,
1447 km_blob: Some(TEST_KM_BLOB.to_vec()),
1448 cert: Some(TEST_CERT_BLOB.to_vec()),
1449 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
1450 sec_level: SecurityLevel::TRUSTED_ENVIRONMENT,
1451 parameters: make_test_params(),
1452 }
1453 );
1454 let state = Arc::new(AtomicU8::new(1));
1455 let state2 = state.clone();
1456
1457 // Spawning a second thread that attempts to acquire the key id lock
1458 // for the same key as the primary thread. The primary thread then
1459 // waits, thereby forcing the secondary thread into the second stage
1460 // of acquiring the lock (see KEY ID LOCK 2/2 above).
1461 // The test succeeds if the secondary thread observes the transition
1462 // of `state` from 1 to 2, despite having a whole second to overtake
1463 // the primary thread.
1464 let handle = thread::spawn(move || {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001465 let temp_dir = temp_dir_clone;
1466 let mut db = KeystoreDB::new(temp_dir.path()).unwrap();
Janis Danisevskisaec14592020-11-12 09:41:49 -08001467 assert!(db
1468 .load_key_entry(
1469 KeyDescriptor {
1470 domain: Domain::APP,
1471 nspace: 0,
1472 alias: Some(KEY_LOCK_TEST_ALIAS.to_string()),
1473 blob: None,
1474 },
1475 KeyEntryLoadBits::BOTH,
1476 33,
1477 |_k, _av| Ok(()),
1478 )
1479 .is_ok());
1480 // We should only see a 2 here because we can only return
1481 // from load_key_entry when the `_key_guard` expires,
1482 // which happens at the end of the scope.
1483 assert_eq!(2, state2.load(Ordering::Relaxed));
1484 });
1485
1486 thread::sleep(std::time::Duration::from_millis(1000));
1487
1488 assert_eq!(Ok(1), state.compare_exchange(1, 2, Ordering::Relaxed, Ordering::Relaxed));
1489
1490 // Return the handle from this scope so we can join with the
1491 // secondary thread after the key id lock has expired.
1492 handle
1493 // This is where the `_key_guard` goes out of scope,
1494 // which is the reason for concurrent load_key_entry on the same key
1495 // to unblock.
1496 };
1497 // Join with the secondary thread and unwrap, to propagate failing asserts to the
1498 // main test thread. We will not see failing asserts in secondary threads otherwise.
1499 handle.join().unwrap();
1500 Ok(())
1501 }
1502
Janis Danisevskise92a5e62020-12-02 12:57:41 -08001503 #[test]
1504 fn list() -> Result<()> {
1505 let temp_dir = TempDir::new("list_test")?;
1506 let mut db = KeystoreDB::new(temp_dir.path())?;
1507 static LIST_O_ENTRIES: &[(Domain, i64, &str)] = &[
1508 (Domain::APP, 1, "test1"),
1509 (Domain::APP, 1, "test2"),
1510 (Domain::APP, 1, "test3"),
1511 (Domain::APP, 1, "test4"),
1512 (Domain::APP, 1, "test5"),
1513 (Domain::APP, 1, "test6"),
1514 (Domain::APP, 1, "test7"),
1515 (Domain::APP, 2, "test1"),
1516 (Domain::APP, 2, "test2"),
1517 (Domain::APP, 2, "test3"),
1518 (Domain::APP, 2, "test4"),
1519 (Domain::APP, 2, "test5"),
1520 (Domain::APP, 2, "test6"),
1521 (Domain::APP, 2, "test8"),
1522 (Domain::SELINUX, 100, "test1"),
1523 (Domain::SELINUX, 100, "test2"),
1524 (Domain::SELINUX, 100, "test3"),
1525 (Domain::SELINUX, 100, "test4"),
1526 (Domain::SELINUX, 100, "test5"),
1527 (Domain::SELINUX, 100, "test6"),
1528 (Domain::SELINUX, 100, "test9"),
1529 ];
1530
1531 let list_o_keys: Vec<(i64, i64)> = LIST_O_ENTRIES
1532 .iter()
1533 .map(|(domain, ns, alias)| {
1534 let entry =
1535 make_test_key_entry(&mut db, *domain, *ns, *alias).unwrap_or_else(|e| {
1536 panic!("Failed to insert {:?} {} {}. Error {:?}", domain, ns, alias, e)
1537 });
1538 (entry.id(), *ns)
1539 })
1540 .collect();
1541
1542 for (domain, namespace) in
1543 &[(Domain::APP, 1i64), (Domain::APP, 2i64), (Domain::SELINUX, 100i64)]
1544 {
1545 let mut list_o_descriptors: Vec<KeyDescriptor> = LIST_O_ENTRIES
1546 .iter()
1547 .filter_map(|(domain, ns, alias)| match ns {
1548 ns if *ns == *namespace => Some(KeyDescriptor {
1549 domain: *domain,
1550 nspace: *ns,
1551 alias: Some(alias.to_string()),
1552 blob: None,
1553 }),
1554 _ => None,
1555 })
1556 .collect();
1557 list_o_descriptors.sort();
1558 let mut list_result = db.list(*domain, *namespace)?;
1559 list_result.sort();
1560 assert_eq!(list_o_descriptors, list_result);
1561
1562 let mut list_o_ids: Vec<i64> = list_o_descriptors
1563 .into_iter()
1564 .map(|d| {
1565 let (_, entry) = db
1566 .load_key_entry(d, KeyEntryLoadBits::NONE, *namespace as u32, |_, _| Ok(()))
1567 .unwrap();
1568 entry.id()
1569 })
1570 .collect();
1571 list_o_ids.sort_unstable();
1572 let mut loaded_entries: Vec<i64> = list_o_keys
1573 .iter()
1574 .filter_map(|(id, ns)| match ns {
1575 ns if *ns == *namespace => Some(*id),
1576 _ => None,
1577 })
1578 .collect();
1579 loaded_entries.sort_unstable();
1580 assert_eq!(list_o_ids, loaded_entries);
1581 }
1582 assert_eq!(Vec::<KeyDescriptor>::new(), db.list(Domain::SELINUX, 101)?);
1583
1584 Ok(())
1585 }
1586
Joel Galenson0891bc12020-07-20 10:37:03 -07001587 // Helpers
1588
1589 // Checks that the given result is an error containing the given string.
1590 fn check_result_is_error_containing_string<T>(result: Result<T>, target: &str) {
1591 let error_str = format!(
1592 "{:#?}",
1593 result.err().unwrap_or_else(|| panic!("Expected the error: {}", target))
1594 );
1595 assert!(
1596 error_str.contains(target),
1597 "The string \"{}\" should contain \"{}\"",
1598 error_str,
1599 target
1600 );
1601 }
1602
Joel Galenson2aab4432020-07-22 15:27:57 -07001603 #[derive(Debug, PartialEq)]
Joel Galenson0891bc12020-07-20 10:37:03 -07001604 #[allow(dead_code)]
1605 struct KeyEntryRow {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001606 id: i64,
Joel Galenson0891bc12020-07-20 10:37:03 -07001607 creation_date: String,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001608 domain: Option<Domain>,
Joel Galenson0891bc12020-07-20 10:37:03 -07001609 namespace: Option<i64>,
1610 alias: Option<String>,
1611 }
1612
1613 fn get_keyentry(db: &KeystoreDB) -> Result<Vec<KeyEntryRow>> {
1614 db.conn
Joel Galenson2aab4432020-07-22 15:27:57 -07001615 .prepare("SELECT * FROM persistent.keyentry;")?
Joel Galenson0891bc12020-07-20 10:37:03 -07001616 .query_map(NO_PARAMS, |row| {
Joel Galenson0891bc12020-07-20 10:37:03 -07001617 Ok(KeyEntryRow {
1618 id: row.get(0)?,
1619 creation_date: row.get(1)?,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001620 domain: match row.get(2)? {
1621 Some(i) => Some(Domain(i)),
1622 None => None,
1623 },
Joel Galenson0891bc12020-07-20 10:37:03 -07001624 namespace: row.get(3)?,
1625 alias: row.get(4)?,
1626 })
1627 })?
1628 .map(|r| r.context("Could not read keyentry row."))
1629 .collect::<Result<Vec<_>>>()
1630 }
1631
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001632 // Note: The parameters and SecurityLevel associations are nonsensical. This
1633 // collection is only used to check if the parameters are preserved as expected by the
1634 // database.
1635 fn make_test_params() -> Vec<KeyParameter> {
1636 vec![
1637 KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::TRUSTED_ENVIRONMENT),
1638 KeyParameter::new(
1639 KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
1640 SecurityLevel::TRUSTED_ENVIRONMENT,
1641 ),
1642 KeyParameter::new(
1643 KeyParameterValue::KeyPurpose(KeyPurpose::DECRYPT),
1644 SecurityLevel::TRUSTED_ENVIRONMENT,
1645 ),
1646 KeyParameter::new(
1647 KeyParameterValue::Algorithm(Algorithm::RSA),
1648 SecurityLevel::TRUSTED_ENVIRONMENT,
1649 ),
1650 KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::TRUSTED_ENVIRONMENT),
1651 KeyParameter::new(
1652 KeyParameterValue::BlockMode(BlockMode::ECB),
1653 SecurityLevel::TRUSTED_ENVIRONMENT,
1654 ),
1655 KeyParameter::new(
1656 KeyParameterValue::BlockMode(BlockMode::GCM),
1657 SecurityLevel::TRUSTED_ENVIRONMENT,
1658 ),
1659 KeyParameter::new(KeyParameterValue::Digest(Digest::NONE), SecurityLevel::STRONGBOX),
1660 KeyParameter::new(
1661 KeyParameterValue::Digest(Digest::MD5),
1662 SecurityLevel::TRUSTED_ENVIRONMENT,
1663 ),
1664 KeyParameter::new(
1665 KeyParameterValue::Digest(Digest::SHA_2_224),
1666 SecurityLevel::TRUSTED_ENVIRONMENT,
1667 ),
1668 KeyParameter::new(
1669 KeyParameterValue::Digest(Digest::SHA_2_256),
1670 SecurityLevel::STRONGBOX,
1671 ),
1672 KeyParameter::new(
1673 KeyParameterValue::PaddingMode(PaddingMode::NONE),
1674 SecurityLevel::TRUSTED_ENVIRONMENT,
1675 ),
1676 KeyParameter::new(
1677 KeyParameterValue::PaddingMode(PaddingMode::RSA_OAEP),
1678 SecurityLevel::TRUSTED_ENVIRONMENT,
1679 ),
1680 KeyParameter::new(
1681 KeyParameterValue::PaddingMode(PaddingMode::RSA_PSS),
1682 SecurityLevel::STRONGBOX,
1683 ),
1684 KeyParameter::new(
1685 KeyParameterValue::PaddingMode(PaddingMode::RSA_PKCS1_1_5_SIGN),
1686 SecurityLevel::TRUSTED_ENVIRONMENT,
1687 ),
1688 KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::TRUSTED_ENVIRONMENT),
1689 KeyParameter::new(KeyParameterValue::MinMacLength(256), SecurityLevel::STRONGBOX),
1690 KeyParameter::new(
1691 KeyParameterValue::EcCurve(EcCurve::P_224),
1692 SecurityLevel::TRUSTED_ENVIRONMENT,
1693 ),
1694 KeyParameter::new(KeyParameterValue::EcCurve(EcCurve::P_256), SecurityLevel::STRONGBOX),
1695 KeyParameter::new(
1696 KeyParameterValue::EcCurve(EcCurve::P_384),
1697 SecurityLevel::TRUSTED_ENVIRONMENT,
1698 ),
1699 KeyParameter::new(
1700 KeyParameterValue::EcCurve(EcCurve::P_521),
1701 SecurityLevel::TRUSTED_ENVIRONMENT,
1702 ),
1703 KeyParameter::new(
1704 KeyParameterValue::RSAPublicExponent(3),
1705 SecurityLevel::TRUSTED_ENVIRONMENT,
1706 ),
1707 KeyParameter::new(
1708 KeyParameterValue::IncludeUniqueID,
1709 SecurityLevel::TRUSTED_ENVIRONMENT,
1710 ),
1711 KeyParameter::new(KeyParameterValue::BootLoaderOnly, SecurityLevel::STRONGBOX),
1712 KeyParameter::new(KeyParameterValue::RollbackResistance, SecurityLevel::STRONGBOX),
1713 KeyParameter::new(
1714 KeyParameterValue::ActiveDateTime(1234567890),
1715 SecurityLevel::STRONGBOX,
1716 ),
1717 KeyParameter::new(
1718 KeyParameterValue::OriginationExpireDateTime(1234567890),
1719 SecurityLevel::TRUSTED_ENVIRONMENT,
1720 ),
1721 KeyParameter::new(
1722 KeyParameterValue::UsageExpireDateTime(1234567890),
1723 SecurityLevel::TRUSTED_ENVIRONMENT,
1724 ),
1725 KeyParameter::new(
1726 KeyParameterValue::MinSecondsBetweenOps(1234567890),
1727 SecurityLevel::TRUSTED_ENVIRONMENT,
1728 ),
1729 KeyParameter::new(
1730 KeyParameterValue::MaxUsesPerBoot(1234567890),
1731 SecurityLevel::TRUSTED_ENVIRONMENT,
1732 ),
1733 KeyParameter::new(KeyParameterValue::UserID(1), SecurityLevel::STRONGBOX),
1734 KeyParameter::new(KeyParameterValue::UserSecureID(42), SecurityLevel::STRONGBOX),
1735 KeyParameter::new(
1736 KeyParameterValue::NoAuthRequired,
1737 SecurityLevel::TRUSTED_ENVIRONMENT,
1738 ),
1739 KeyParameter::new(
1740 KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType::PASSWORD),
1741 SecurityLevel::TRUSTED_ENVIRONMENT,
1742 ),
1743 KeyParameter::new(KeyParameterValue::AuthTimeout(1234567890), SecurityLevel::SOFTWARE),
1744 KeyParameter::new(KeyParameterValue::AllowWhileOnBody, SecurityLevel::SOFTWARE),
1745 KeyParameter::new(
1746 KeyParameterValue::TrustedUserPresenceRequired,
1747 SecurityLevel::TRUSTED_ENVIRONMENT,
1748 ),
1749 KeyParameter::new(
1750 KeyParameterValue::TrustedConfirmationRequired,
1751 SecurityLevel::TRUSTED_ENVIRONMENT,
1752 ),
1753 KeyParameter::new(
1754 KeyParameterValue::UnlockedDeviceRequired,
1755 SecurityLevel::TRUSTED_ENVIRONMENT,
1756 ),
1757 KeyParameter::new(
1758 KeyParameterValue::ApplicationID(vec![1u8, 2u8, 3u8, 4u8]),
1759 SecurityLevel::SOFTWARE,
1760 ),
1761 KeyParameter::new(
1762 KeyParameterValue::ApplicationData(vec![4u8, 3u8, 2u8, 1u8]),
1763 SecurityLevel::SOFTWARE,
1764 ),
1765 KeyParameter::new(
1766 KeyParameterValue::CreationDateTime(12345677890),
1767 SecurityLevel::SOFTWARE,
1768 ),
1769 KeyParameter::new(
1770 KeyParameterValue::KeyOrigin(KeyOrigin::GENERATED),
1771 SecurityLevel::TRUSTED_ENVIRONMENT,
1772 ),
1773 KeyParameter::new(
1774 KeyParameterValue::RootOfTrust(vec![3u8, 2u8, 1u8, 4u8]),
1775 SecurityLevel::TRUSTED_ENVIRONMENT,
1776 ),
1777 KeyParameter::new(KeyParameterValue::OSVersion(1), SecurityLevel::TRUSTED_ENVIRONMENT),
1778 KeyParameter::new(KeyParameterValue::OSPatchLevel(2), SecurityLevel::SOFTWARE),
1779 KeyParameter::new(
1780 KeyParameterValue::UniqueID(vec![4u8, 3u8, 1u8, 2u8]),
1781 SecurityLevel::SOFTWARE,
1782 ),
1783 KeyParameter::new(
1784 KeyParameterValue::AttestationChallenge(vec![4u8, 3u8, 1u8, 2u8]),
1785 SecurityLevel::TRUSTED_ENVIRONMENT,
1786 ),
1787 KeyParameter::new(
1788 KeyParameterValue::AttestationApplicationID(vec![4u8, 3u8, 1u8, 2u8]),
1789 SecurityLevel::TRUSTED_ENVIRONMENT,
1790 ),
1791 KeyParameter::new(
1792 KeyParameterValue::AttestationIdBrand(vec![4u8, 3u8, 1u8, 2u8]),
1793 SecurityLevel::TRUSTED_ENVIRONMENT,
1794 ),
1795 KeyParameter::new(
1796 KeyParameterValue::AttestationIdDevice(vec![4u8, 3u8, 1u8, 2u8]),
1797 SecurityLevel::TRUSTED_ENVIRONMENT,
1798 ),
1799 KeyParameter::new(
1800 KeyParameterValue::AttestationIdProduct(vec![4u8, 3u8, 1u8, 2u8]),
1801 SecurityLevel::TRUSTED_ENVIRONMENT,
1802 ),
1803 KeyParameter::new(
1804 KeyParameterValue::AttestationIdSerial(vec![4u8, 3u8, 1u8, 2u8]),
1805 SecurityLevel::TRUSTED_ENVIRONMENT,
1806 ),
1807 KeyParameter::new(
1808 KeyParameterValue::AttestationIdIMEI(vec![4u8, 3u8, 1u8, 2u8]),
1809 SecurityLevel::TRUSTED_ENVIRONMENT,
1810 ),
1811 KeyParameter::new(
1812 KeyParameterValue::AttestationIdMEID(vec![4u8, 3u8, 1u8, 2u8]),
1813 SecurityLevel::TRUSTED_ENVIRONMENT,
1814 ),
1815 KeyParameter::new(
1816 KeyParameterValue::AttestationIdManufacturer(vec![4u8, 3u8, 1u8, 2u8]),
1817 SecurityLevel::TRUSTED_ENVIRONMENT,
1818 ),
1819 KeyParameter::new(
1820 KeyParameterValue::AttestationIdModel(vec![4u8, 3u8, 1u8, 2u8]),
1821 SecurityLevel::TRUSTED_ENVIRONMENT,
1822 ),
1823 KeyParameter::new(
1824 KeyParameterValue::VendorPatchLevel(3),
1825 SecurityLevel::TRUSTED_ENVIRONMENT,
1826 ),
1827 KeyParameter::new(
1828 KeyParameterValue::BootPatchLevel(4),
1829 SecurityLevel::TRUSTED_ENVIRONMENT,
1830 ),
1831 KeyParameter::new(
1832 KeyParameterValue::AssociatedData(vec![4u8, 3u8, 1u8, 2u8]),
1833 SecurityLevel::TRUSTED_ENVIRONMENT,
1834 ),
1835 KeyParameter::new(
1836 KeyParameterValue::Nonce(vec![4u8, 3u8, 1u8, 2u8]),
1837 SecurityLevel::TRUSTED_ENVIRONMENT,
1838 ),
1839 KeyParameter::new(
1840 KeyParameterValue::MacLength(256),
1841 SecurityLevel::TRUSTED_ENVIRONMENT,
1842 ),
1843 KeyParameter::new(
1844 KeyParameterValue::ResetSinceIdRotation,
1845 SecurityLevel::TRUSTED_ENVIRONMENT,
1846 ),
1847 KeyParameter::new(
1848 KeyParameterValue::ConfirmationToken(vec![5u8, 5u8, 5u8, 5u8]),
1849 SecurityLevel::TRUSTED_ENVIRONMENT,
1850 ),
1851 ]
1852 }
1853
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001854 fn make_test_key_entry(
1855 db: &mut KeystoreDB,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001856 domain: Domain,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001857 namespace: i64,
1858 alias: &str,
Janis Danisevskisaec14592020-11-12 09:41:49 -08001859 ) -> Result<KeyIdGuard> {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001860 let key_id = db.create_key_entry(domain, namespace)?;
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001861 db.insert_blob(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001862 &key_id,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001863 SubComponentType::KM_BLOB,
1864 TEST_KM_BLOB,
1865 SecurityLevel::TRUSTED_ENVIRONMENT,
1866 )?;
1867 db.insert_blob(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001868 &key_id,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001869 SubComponentType::CERT,
1870 TEST_CERT_BLOB,
1871 SecurityLevel::TRUSTED_ENVIRONMENT,
1872 )?;
1873 db.insert_blob(
Janis Danisevskisaec14592020-11-12 09:41:49 -08001874 &key_id,
Janis Danisevskisc5b210b2020-09-11 13:27:37 -07001875 SubComponentType::CERT_CHAIN,
1876 TEST_CERT_CHAIN_BLOB,
1877 SecurityLevel::TRUSTED_ENVIRONMENT,
1878 )?;
Janis Danisevskisaec14592020-11-12 09:41:49 -08001879 db.insert_keyparameter(&key_id, &make_test_params())?;
1880 db.rebind_alias(&key_id, alias, domain, namespace)?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001881 Ok(key_id)
1882 }
1883
1884 fn debug_dump_keyentry_table(db: &mut KeystoreDB) -> Result<()> {
1885 let mut stmt = db.conn.prepare(
1886 "SELECT id, creation_date, domain, namespace, alias FROM persistent.keyentry;",
1887 )?;
1888 let rows = stmt.query_map::<(i64, i64, i32, i64, String), _, _>(NO_PARAMS, |row| {
1889 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?, row.get(4)?))
1890 })?;
1891
1892 println!("Key entry table rows:");
1893 for r in rows {
1894 let (id, cdate, domain, namespace, alias) = r.unwrap();
1895 println!(
1896 " id: {} Creation date: {} Domain: {} Namespace: {} Alias: {}",
1897 id, cdate, domain, namespace, alias
1898 );
1899 }
1900 Ok(())
1901 }
1902
1903 fn debug_dump_grant_table(db: &mut KeystoreDB) -> Result<()> {
Janis Danisevskisbf15d732020-12-08 10:35:26 -08001904 let mut stmt = db
1905 .conn
1906 .prepare("SELECT id, grantee, keyentryid, access_vector FROM persistent.grant;")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001907 let rows = stmt.query_map::<(i64, i64, i64, i64), _, _>(NO_PARAMS, |row| {
1908 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?))
1909 })?;
1910
1911 println!("Grant table rows:");
1912 for r in rows {
1913 let (id, gt, ki, av) = r.unwrap();
1914 println!(" id: {} grantee: {} key_id: {} access_vector: {}", id, gt, ki, av);
1915 }
1916 Ok(())
1917 }
1918
Joel Galenson0891bc12020-07-20 10:37:03 -07001919 // Use a custom random number generator that repeats each number once.
1920 // This allows us to test repeated elements.
1921
1922 thread_local! {
1923 static RANDOM_COUNTER: RefCell<i64> = RefCell::new(0);
1924 }
1925
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001926 fn reset_random() {
1927 RANDOM_COUNTER.with(|counter| {
1928 *counter.borrow_mut() = 0;
1929 })
1930 }
1931
Joel Galenson0891bc12020-07-20 10:37:03 -07001932 pub fn random() -> i64 {
1933 RANDOM_COUNTER.with(|counter| {
1934 let result = *counter.borrow() / 2;
1935 *counter.borrow_mut() += 1;
1936 result
1937 })
1938 }
Joel Galenson26f4d012020-07-17 14:57:21 -07001939}