blob: ea70195b3ca518163884aee51fbef69cb6db15ce [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
Joel Galenson0891bc12020-07-20 10:37:03 -070044use crate::error::Error as KsError;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -070045use crate::key_parameter::{KeyParameter, SqlField, TagType};
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070046use crate::{error, permission::KeyPermSet};
47use anyhow::{anyhow, Context, Result};
Janis Danisevskis60400fe2020-08-26 15:24:42 -070048
Janis Danisevskis3f322cb2020-09-03 14:46:22 -070049use android_hardware_keymint::aidl::android::hardware::keymint::SecurityLevel::SecurityLevel as SecurityLevelType;
Janis Danisevskis60400fe2020-08-26 15:24:42 -070050use android_security_keystore2::aidl::android::security::keystore2::{
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070051 Domain, Domain::Domain as DomainType, KeyDescriptor::KeyDescriptor,
Janis Danisevskis60400fe2020-08-26 15:24:42 -070052};
53
Joel Galenson0891bc12020-07-20 10:37:03 -070054#[cfg(not(test))]
55use rand::prelude::random;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070056use rusqlite::{
57 params, types::FromSql, types::FromSqlResult, types::ToSqlOutput, types::ValueRef, Connection,
58 OptionalExtension, Row, Rows, ToSql, Transaction, TransactionBehavior, NO_PARAMS,
59};
Janis Danisevskis4df44f42020-08-26 14:40:03 -070060use std::sync::Once;
Joel Galenson0891bc12020-07-20 10:37:03 -070061#[cfg(test)]
62use tests::random;
Joel Galenson26f4d012020-07-17 14:57:21 -070063
Janis Danisevskis63f7bc82020-09-03 10:12:56 -070064/// Keys have a KeyMint blob component and optional public certificate and
65/// certificate chain components.
66/// KeyEntryLoadBits is a bitmap that indicates to `KeystoreDB::load_key_entry`
67/// which components shall be loaded from the database if present.
68#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
69pub struct KeyEntryLoadBits(u32);
70
71impl KeyEntryLoadBits {
72 /// Indicate to `KeystoreDB::load_key_entry` that no component shall be loaded.
73 pub const NONE: KeyEntryLoadBits = Self(0);
74 /// Indicate to `KeystoreDB::load_key_entry` that the KeyMint component shall be loaded.
75 pub const KM: KeyEntryLoadBits = Self(1);
76 /// Indicate to `KeystoreDB::load_key_entry` that the Public components shall be loaded.
77 pub const PUBLIC: KeyEntryLoadBits = Self(2);
78 /// Indicate to `KeystoreDB::load_key_entry` that both components shall be loaded.
79 pub const BOTH: KeyEntryLoadBits = Self(3);
80
81 /// Returns true if this object indicates that the public components shall be loaded.
82 pub const fn load_public(&self) -> bool {
83 self.0 & Self::PUBLIC.0 != 0
84 }
85
86 /// Returns true if the object indicates that the KeyMint component shall be loaded.
87 pub const fn load_km(&self) -> bool {
88 self.0 & Self::KM.0 != 0
89 }
90}
91
92/// This type represents a Keystore 2.0 key entry.
93/// An entry has a unique `id` by which it can be found in the database.
94/// It has a security level field, key parameters, and three optional fields
95/// for the KeyMint blob, public certificate and a public certificate chain.
96#[derive(Debug, Default, Clone, Eq, PartialEq, Ord, PartialOrd)]
97pub struct KeyEntry {
98 id: i64,
99 km_blob: Option<Vec<u8>>,
100 cert: Option<Vec<u8>>,
101 cert_chain: Option<Vec<u8>>,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700102 sec_level: SecurityLevelType,
103 parameters: Vec<KeyParameter>,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700104}
105
106impl KeyEntry {
107 /// Returns the unique id of the Key entry.
108 pub fn id(&self) -> i64 {
109 self.id
110 }
111 /// Exposes the optional KeyMint blob.
112 pub fn km_blob(&self) -> &Option<Vec<u8>> {
113 &self.km_blob
114 }
115 /// Extracts the Optional KeyMint blob.
116 pub fn take_km_blob(&mut self) -> Option<Vec<u8>> {
117 self.km_blob.take()
118 }
119 /// Exposes the optional public certificate.
120 pub fn cert(&self) -> &Option<Vec<u8>> {
121 &self.cert
122 }
123 /// Extracts the optional public certificate.
124 pub fn take_cert(&mut self) -> Option<Vec<u8>> {
125 self.cert.take()
126 }
127 /// Exposes the optional public certificate chain.
128 pub fn cert_chain(&self) -> &Option<Vec<u8>> {
129 &self.cert_chain
130 }
131 /// Extracts the optional public certificate_chain.
132 pub fn take_cert_chain(&mut self) -> Option<Vec<u8>> {
133 self.cert_chain.take()
134 }
135 /// Returns the security level of the key entry.
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700136 pub fn sec_level(&self) -> SecurityLevelType {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700137 self.sec_level
138 }
139}
140
141/// Indicates the sub component of a key entry for persistent storage.
142#[derive(Debug, Eq, PartialEq, Ord, PartialOrd)]
143pub struct SubComponentType(u32);
144impl SubComponentType {
145 /// Persistent identifier for a KeyMint blob.
146 pub const KM_BLOB: SubComponentType = Self(0);
147 /// Persistent identifier for a certificate blob.
148 pub const CERT: SubComponentType = Self(1);
149 /// Persistent identifier for a certificate chain blob.
150 pub const CERT_CHAIN: SubComponentType = Self(2);
151}
152
153impl ToSql for SubComponentType {
154 fn to_sql(&self) -> rusqlite::Result<ToSqlOutput> {
155 self.0.to_sql()
156 }
157}
158
159impl FromSql for SubComponentType {
160 fn column_result(value: ValueRef) -> FromSqlResult<Self> {
161 Ok(Self(u32::column_result(value)?))
162 }
163}
164
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700165static INIT_TABLES: Once = Once::new();
166
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700167/// KeystoreDB wraps a connection to an SQLite database and tracks its
168/// ownership. It also implements all of Keystore 2.0's database functionality.
Joel Galenson26f4d012020-07-17 14:57:21 -0700169pub struct KeystoreDB {
Joel Galenson26f4d012020-07-17 14:57:21 -0700170 conn: Connection,
171}
172
173impl KeystoreDB {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700174 /// This will create a new database connection connecting the two
175 /// files persistent.sqlite and perboot.sqlite in the current working
176 /// directory, which is usually `/data/misc/keystore/`.
177 /// It also attempts to initialize all of the tables on the first instantiation
178 /// per service startup. KeystoreDB cannot be used by multiple threads.
179 /// Each thread should open their own connection using `thread_local!`.
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700180 pub fn new() -> Result<Self> {
181 let conn = Self::make_connection("file:persistent.sqlite", "file:perboot.sqlite")?;
182
183 INIT_TABLES.call_once(|| Self::init_tables(&conn).expect("Failed to initialize tables."));
184 Ok(Self { conn })
Joel Galenson2aab4432020-07-22 15:27:57 -0700185 }
186
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700187 fn init_tables(conn: &Connection) -> Result<()> {
188 conn.execute(
189 "CREATE TABLE IF NOT EXISTS persistent.keyentry (
Joel Galenson0891bc12020-07-20 10:37:03 -0700190 id INTEGER UNIQUE,
191 creation_date DATETIME,
192 domain INTEGER,
193 namespace INTEGER,
194 alias TEXT);",
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700195 NO_PARAMS,
196 )
197 .context("Failed to initialize \"keyentry\" table.")?;
198
199 conn.execute(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700200 "CREATE VIEW IF NOT EXISTS persistent.orphaned AS
201 SELECT id FROM persistent.keyentry WHERE domain IS NULL;",
202 NO_PARAMS,
203 )
204 .context("Failed to initialize \"orphaned\" view")?;
205
206 conn.execute(
207 "CREATE TABLE IF NOT EXISTS persistent.blobentry (
208 id INTEGER PRIMARY KEY,
209 subcomponent_type INTEGER,
210 keyentryid INTEGER,
211 blob BLOB,
212 sec_level INTEGER);",
213 NO_PARAMS,
214 )
215 .context("Failed to initialize \"blobentry\" table.")?;
216
217 conn.execute(
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700218 "CREATE TABLE IF NOT EXISTS persistent.keyparameter (
Hasini Gunasingheaf993662020-07-24 18:40:20 +0000219 keyentryid INTEGER,
220 tag INTEGER,
221 data ANY,
222 security_level INTEGER);",
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700223 NO_PARAMS,
224 )
225 .context("Failed to initialize \"keyparameter\" table.")?;
226
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700227 // TODO only drop the perboot table if we start up for the first time per boot.
228 // Right now this is done once per startup which will lose some information
229 // upon a crash.
230 // Note: This is no regression with respect to the legacy Keystore.
231 conn.execute("DROP TABLE IF EXISTS perboot.grant;", NO_PARAMS)
232 .context("Failed to drop perboot.grant table")?;
233 conn.execute(
234 "CREATE TABLE perboot.grant (
235 id INTEGER UNIQUE,
236 grantee INTEGER,
237 keyentryid INTEGER,
238 access_vector INTEGER);",
239 NO_PARAMS,
240 )
241 .context("Failed to initialize \"grant\" table.")?;
242
Joel Galenson0891bc12020-07-20 10:37:03 -0700243 Ok(())
244 }
245
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700246 fn make_connection(persistent_file: &str, perboot_file: &str) -> Result<Connection> {
247 let conn =
248 Connection::open_in_memory().context("Failed to initialize SQLite connection.")?;
249
250 conn.execute("ATTACH DATABASE ? as persistent;", params![persistent_file])
251 .context("Failed to attach database persistent.")?;
252 conn.execute("ATTACH DATABASE ? as perboot;", params![perboot_file])
253 .context("Failed to attach database perboot.")?;
254
255 Ok(conn)
256 }
257
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700258 /// Creates a new key entry and allocates a new randomized id for the new key.
259 /// The key id gets associated with a domain and namespace but not with an alias.
260 /// To complete key generation `rebind_alias` should be called after all of the
261 /// key artifacts, i.e., blobs and parameters have been associated with the new
262 /// key id. Finalizing with `rebind_alias` makes the creation of a new key entry
263 /// atomic even if key generation is not.
Janis Danisevskis60400fe2020-08-26 15:24:42 -0700264 pub fn create_key_entry(&self, domain: DomainType, namespace: i64) -> Result<i64> {
Joel Galenson0891bc12020-07-20 10:37:03 -0700265 match domain {
Janis Danisevskis60400fe2020-08-26 15:24:42 -0700266 Domain::App | Domain::SELinux => {}
Joel Galenson0891bc12020-07-20 10:37:03 -0700267 _ => {
268 return Err(KsError::sys())
269 .context(format!("Domain {:?} must be either App or SELinux.", domain));
270 }
271 }
Joel Galenson845f74b2020-09-09 14:11:55 -0700272 Self::insert_with_retry(|id| {
273 self.conn.execute(
Joel Galenson2aab4432020-07-22 15:27:57 -0700274 "INSERT into persistent.keyentry (id, creation_date, domain, namespace, alias)
Joel Galenson0891bc12020-07-20 10:37:03 -0700275 VALUES(?, datetime('now'), ?, ?, NULL);",
Joel Galenson845f74b2020-09-09 14:11:55 -0700276 params![id, domain as i64, namespace],
277 )
278 })
279 .context("In create_key_entry")
Joel Galenson26f4d012020-07-17 14:57:21 -0700280 }
Joel Galenson33c04ad2020-08-03 11:04:38 -0700281
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700282 /// Inserts a new blob and associates it with the given key id. Each blob
283 /// has a sub component type and a security level.
284 /// Each key can have one of each sub component type associated. If more
285 /// are added only the most recent can be retrieved, and superseded blobs
286 /// will get garbage collected. The security level field of components
287 /// other than `SubComponentType::KM_BLOB` are ignored.
288 pub fn insert_blob(
289 &mut self,
290 key_id: i64,
291 sc_type: SubComponentType,
292 blob: &[u8],
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700293 sec_level: SecurityLevelType,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700294 ) -> Result<()> {
295 self.conn
296 .execute(
297 "INSERT into persistent.blobentry (subcomponent_type, keyentryid, blob, sec_level)
298 VALUES (?, ?, ?, ?);",
299 params![sc_type, key_id, blob, sec_level],
300 )
301 .context("Failed to insert blob.")?;
302 Ok(())
303 }
304
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700305 /// Inserts a collection of key parameters into the `persistent.keyparameter` table
306 /// and associates them with the given `key_id`.
307 pub fn insert_keyparameter<'a>(
308 &mut self,
309 key_id: i64,
310 params: impl IntoIterator<Item = &'a KeyParameter>,
311 ) -> Result<()> {
312 let mut stmt = self
313 .conn
314 .prepare(
315 "INSERT into persistent.keyparameter (keyentryid, tag, data, security_level)
316 VALUES (?, ?, ?, ?);",
317 )
318 .context("In insert_keyparameter: Failed to prepare statement.")?;
319
320 let iter = params.into_iter();
321 for p in iter {
322 stmt.insert(params![key_id, p.get_tag(), p.key_parameter_value(), p.security_level()])
323 .with_context(|| format!("In insert_keyparameter: Failed to insert {:?}", p))?;
324 }
325 Ok(())
326 }
327
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700328 /// Updates the alias column of the given key id `newid` with the given alias,
329 /// and atomically, removes the alias, domain, and namespace from another row
330 /// with the same alias-domain-namespace tuple if such row exits.
Joel Galenson33c04ad2020-08-03 11:04:38 -0700331 pub fn rebind_alias(
332 &mut self,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700333 newid: i64,
Joel Galenson33c04ad2020-08-03 11:04:38 -0700334 alias: &str,
Janis Danisevskis60400fe2020-08-26 15:24:42 -0700335 domain: DomainType,
Joel Galenson33c04ad2020-08-03 11:04:38 -0700336 namespace: i64,
337 ) -> Result<()> {
338 match domain {
Janis Danisevskis60400fe2020-08-26 15:24:42 -0700339 Domain::App | Domain::SELinux => {}
Joel Galenson33c04ad2020-08-03 11:04:38 -0700340 _ => {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700341 return Err(KsError::sys()).context(format!(
342 "In rebind_alias: Domain {:?} must be either App or SELinux.",
343 domain
344 ));
Joel Galenson33c04ad2020-08-03 11:04:38 -0700345 }
346 }
347 let tx = self
348 .conn
349 .transaction_with_behavior(TransactionBehavior::Immediate)
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700350 .context("In rebind_alias: Failed to initialize transaction.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -0700351 tx.execute(
352 "UPDATE persistent.keyentry
353 SET alias = NULL, domain = NULL, namespace = NULL
354 WHERE alias = ? AND domain = ? AND namespace = ?;",
355 params![alias, domain as i64, namespace],
356 )
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700357 .context("In rebind_alias: Failed to rebind existing entry.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -0700358 let result = tx
359 .execute(
360 "UPDATE persistent.keyentry
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700361 SET alias = ?
362 WHERE id = ? AND domain = ? AND namespace = ?;",
Joel Galenson33c04ad2020-08-03 11:04:38 -0700363 params![alias, newid, domain as i64, namespace],
364 )
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700365 .context("In rebind_alias: Failed to set alias.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -0700366 if result != 1 {
367 // Note that this explicit rollback is not required, as
368 // the transaction should rollback if we do not commit it.
369 // We leave it here for readability.
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700370 tx.rollback().context("In rebind_alias: Failed to rollback a failed transaction.")?;
Joel Galenson33c04ad2020-08-03 11:04:38 -0700371 return Err(KsError::sys()).context(format!(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700372 "In rebind_alias: Expected to update a single entry but instead updated {}.",
Joel Galenson33c04ad2020-08-03 11:04:38 -0700373 result
374 ));
375 }
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700376 tx.commit().context("In rebind_alias: Failed to commit transaction.")
377 }
378
379 // Helper function loading the key_id given the key descriptor
380 // tuple comprising domain, namespace, and alias.
381 // Requires a valid transaction.
382 fn load_key_entry_id(key: &KeyDescriptor, tx: &Transaction) -> Result<i64> {
383 let alias = key
384 .alias
385 .as_ref()
386 .map_or_else(|| Err(KsError::sys()), Ok)
387 .context("In load_key_entry_id: Alias must be specified.")?;
388 let mut stmt = tx
389 .prepare(
390 "SELECT id FROM persistent.keyentry
391 WHERE
392 domain = ?
393 AND namespace = ?
394 AND alias = ?;",
395 )
396 .context("In load_key_entry_id: Failed to select from keyentry table.")?;
397 let mut rows = stmt
398 .query(params![key.domain, key.namespace_, alias])
399 .context("In load_key_entry_id: Failed to read from keyentry table.")?;
400 Self::with_rows_extract_one(&mut rows, |row| {
401 row.map_or_else(|| Err(KsError::Rc(error::Rc::KeyNotFound)), Ok)?
402 .get(0)
403 .context("Failed to unpack id.")
404 })
405 .context("In load_key_entry_id.")
406 }
407
408 /// This helper function completes the access tuple of a key, which is required
409 /// to perform access control. The strategy depends on the `domain` field in the
410 /// key descriptor.
411 /// * Domain::SELinux: The access tuple is complete and this function only loads
412 /// the key_id for further processing.
413 /// * Domain::App: Like Domain::SELinux, but the tuple is completed by `caller_uid`
414 /// which serves as the namespace.
415 /// * Domain::Grant: The grant table is queried for the `key_id` and the
416 /// `access_vector`.
417 /// * Domain::KeyId: The keyentry table is queried for the owning `domain` and
418 /// `namespace`.
419 /// In each case the information returned is sufficient to perform the access
420 /// check and the key id can be used to load further key artifacts.
421 fn load_access_tuple(
422 tx: &Transaction,
423 key: KeyDescriptor,
424 caller_uid: u32,
425 ) -> Result<(i64, KeyDescriptor, Option<KeyPermSet>)> {
426 match key.domain {
427 // Domain App or SELinux. In this case we load the key_id from
428 // the keyentry database for further loading of key components.
429 // We already have the full access tuple to perform access control.
430 // The only distinction is that we use the caller_uid instead
431 // of the caller supplied namespace if the domain field is
432 // Domain::App.
433 Domain::App | Domain::SELinux => {
434 let mut access_key = key;
435 if access_key.domain == Domain::App {
436 access_key.namespace_ = caller_uid as i64;
437 }
438 let key_id = Self::load_key_entry_id(&access_key, &tx)
439 .with_context(|| format!("With key.domain = {}.", access_key.domain))?;
440
441 Ok((key_id, access_key, None))
442 }
443
444 // Domain::Grant. In this case we load the key_id and the access_vector
445 // from the grant table.
446 Domain::Grant => {
447 let mut stmt = tx
448 .prepare(
449 "SELECT keyentryid, access_vector FROM perboot.grant
450 WHERE grantee = ? AND id = ?;",
451 )
452 .context("Domain::Grant prepare statement failed")?;
453 let mut rows = stmt
454 .query(params![caller_uid as i64, key.namespace_])
455 .context("Domain:Grant: query failed.")?;
456 let (key_id, access_vector): (i64, i32) =
457 Self::with_rows_extract_one(&mut rows, |row| {
458 let r = row.map_or_else(|| Err(KsError::Rc(error::Rc::KeyNotFound)), Ok)?;
459 Ok((
460 r.get(0).context("Failed to unpack key_id.")?,
461 r.get(1).context("Failed to unpack access_vector.")?,
462 ))
463 })
464 .context("Domain::Grant.")?;
465 Ok((key_id, key, Some(access_vector.into())))
466 }
467
468 // Domain::KeyId. In this case we load the domain and namespace from the
469 // keyentry database because we need them for access control.
470 Domain::KeyId => {
471 let mut stmt = tx
472 .prepare(
473 "SELECT domain, namespace FROM persistent.keyentry
474 WHERE
475 id = ?;",
476 )
477 .context("Domain::KeyId: prepare statement failed")?;
478 let mut rows =
479 stmt.query(params![key.namespace_]).context("Domain::KeyId: query failed.")?;
480 let (domain, namespace): (DomainType, i64) =
481 Self::with_rows_extract_one(&mut rows, |row| {
482 let r = row.map_or_else(|| Err(KsError::Rc(error::Rc::KeyNotFound)), Ok)?;
483 Ok((
484 r.get(0).context("Failed to unpack domain.")?,
485 r.get(1).context("Failed to unpack namespace.")?,
486 ))
487 })
488 .context("Domain::KeyId.")?;
489 let key_id = key.namespace_;
490 let mut access_key = key;
491 access_key.domain = domain;
492 access_key.namespace_ = namespace;
493
494 Ok((key_id, access_key, None))
495 }
496 _ => Err(anyhow!(KsError::sys())),
497 }
498 }
499
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700500 fn load_blob_components(
501 key_id: i64,
502 load_bits: KeyEntryLoadBits,
503 tx: &Transaction,
504 ) -> Result<(SecurityLevelType, Option<Vec<u8>>, Option<Vec<u8>>, Option<Vec<u8>>)> {
505 let mut stmt = tx
506 .prepare(
507 "SELECT MAX(id), sec_level, subcomponent_type, blob FROM persistent.blobentry
508 WHERE keyentryid = ? GROUP BY subcomponent_type;",
509 )
510 .context("In load_blob_components: prepare statement failed.")?;
511
512 let mut rows =
513 stmt.query(params![key_id]).context("In load_blob_components: query failed.")?;
514
515 let mut sec_level: SecurityLevelType = Default::default();
516 let mut km_blob: Option<Vec<u8>> = None;
517 let mut cert_blob: Option<Vec<u8>> = None;
518 let mut cert_chain_blob: Option<Vec<u8>> = None;
519 Self::with_rows_extract_all(&mut rows, |row| {
520 let sub_type: SubComponentType =
521 row.get(2).context("Failed to extract subcomponent_type.")?;
522 match (sub_type, load_bits.load_public()) {
523 (SubComponentType::KM_BLOB, _) => {
524 sec_level = row.get(1).context("Failed to extract security level.")?;
525 if load_bits.load_km() {
526 km_blob = Some(row.get(3).context("Failed to extract KM blob.")?);
527 }
528 }
529 (SubComponentType::CERT, true) => {
530 cert_blob =
531 Some(row.get(3).context("Failed to extract public certificate blob.")?);
532 }
533 (SubComponentType::CERT_CHAIN, true) => {
534 cert_chain_blob =
535 Some(row.get(3).context("Failed to extract certificate chain blob.")?);
536 }
537 (SubComponentType::CERT, _) | (SubComponentType::CERT_CHAIN, _) => {}
538 _ => Err(KsError::sys()).context("Unknown subcomponent type.")?,
539 }
540 Ok(())
541 })
542 .context("In load_blob_components.")?;
543
544 Ok((sec_level, km_blob, cert_blob, cert_chain_blob))
545 }
546
547 fn load_key_parameters(key_id: i64, tx: &Transaction) -> Result<Vec<KeyParameter>> {
548 let mut stmt = tx
549 .prepare(
550 "SELECT tag, data, security_level from persistent.keyparameter
551 WHERE keyentryid = ?;",
552 )
553 .context("In load_key_parameters: prepare statement failed.")?;
554
555 let mut parameters: Vec<KeyParameter> = Vec::new();
556
557 let mut rows =
558 stmt.query(params![key_id]).context("In load_key_parameters: query failed.")?;
559 Self::with_rows_extract_all(&mut rows, |row| {
560 let tag: TagType = row.get(0).context("Failed to read tag.")?;
561 let sec_level: SecurityLevelType = row.get(2).context("Failed to read sec_level.")?;
562 parameters.push(
563 KeyParameter::new_from_sql(tag, &SqlField::new(1, &row), sec_level)
564 .context("Failed to read KeyParameter.")?,
565 );
566 Ok(())
567 })
568 .context("In load_key_parameters.")?;
569
570 Ok(parameters)
571 }
572
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700573 /// Load a key entry by the given key descriptor.
574 /// It uses the `check_permission` callback to verify if the access is allowed
575 /// given the key access tuple read from the database using `load_access_tuple`.
576 /// With `load_bits` the caller may specify which blobs shall be loaded from
577 /// the blob database.
578 pub fn load_key_entry(
579 &mut self,
580 key: KeyDescriptor,
581 load_bits: KeyEntryLoadBits,
582 caller_uid: u32,
583 check_permission: impl FnOnce(&KeyDescriptor, Option<KeyPermSet>) -> Result<()>,
584 ) -> Result<KeyEntry> {
585 let tx = self
586 .conn
587 .transaction_with_behavior(TransactionBehavior::Deferred)
588 .context("In load_key_entry: Failed to initialize transaction.")?;
589
590 // Load the key_id and complete the access control tuple.
591 let (key_id, access_key_descriptor, access_vector) =
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700592 Self::load_access_tuple(&tx, key, caller_uid).context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700593
594 // Perform access control. It is vital that we return here if the permission is denied.
595 // So do not touch that '?' at the end.
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700596 check_permission(&access_key_descriptor, access_vector).context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700597
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700598 let (sec_level, km_blob, cert_blob, cert_chain_blob) =
599 Self::load_blob_components(key_id, load_bits, &tx).context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700600
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700601 let parameters = Self::load_key_parameters(key_id, &tx).context("In load_key_entry.")?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700602
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700603 tx.commit().context("In load_key_entry: Failed to commit transaction.")?;
604
605 Ok(KeyEntry {
606 id: key_id,
607 km_blob,
608 cert: cert_blob,
609 cert_chain: cert_chain_blob,
610 sec_level,
611 parameters,
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700612 })
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700613 }
614
615 /// Adds a grant to the grant table.
616 /// Like `load_key_entry` this function loads the access tuple before
617 /// it uses the callback for a permission check. Upon success,
618 /// it inserts the `grantee_uid`, `key_id`, and `access_vector` into the
619 /// grant table. The new row will have a randomized id, which is used as
620 /// grant id in the namespace field of the resulting KeyDescriptor.
621 pub fn grant(
622 &mut self,
623 key: KeyDescriptor,
624 caller_uid: u32,
625 grantee_uid: u32,
626 access_vector: KeyPermSet,
627 check_permission: impl FnOnce(&KeyDescriptor, &KeyPermSet) -> Result<()>,
628 ) -> Result<KeyDescriptor> {
629 let tx = self
630 .conn
631 .transaction_with_behavior(TransactionBehavior::Immediate)
632 .context("In grant: Failed to initialize transaction.")?;
633
634 // Load the key_id and complete the access control tuple.
635 // We ignore the access vector here because grants cannot be granted.
636 // The access vector returned here expresses the permissions the
637 // grantee has if key.domain == Domain::Grant. But this vector
638 // cannot include the grant permission by design, so there is no way the
639 // subsequent permission check can pass.
640 // We could check key.domain == Domain::Grant and fail early.
641 // But even if we load the access tuple by grant here, the permission
642 // check denies the attempt to create a grant by grant descriptor.
643 let (key_id, access_key_descriptor, _) =
644 Self::load_access_tuple(&tx, key, caller_uid).context("In grant")?;
645
646 // Perform access control. It is vital that we return here if the permission
647 // was denied. So do not touch that '?' at the end of the line.
648 // This permission check checks if the caller has the grant permission
649 // for the given key and in addition to all of the permissions
650 // expressed in `access_vector`.
651 check_permission(&access_key_descriptor, &access_vector)
652 .context("In grant: check_permission failed.")?;
653
654 let grant_id = if let Some(grant_id) = tx
655 .query_row(
656 "SELECT id FROM perboot.grant
657 WHERE keyentryid = ? AND grantee = ?;",
658 params![key_id, grantee_uid],
659 |row| row.get(0),
660 )
661 .optional()
662 .context("In grant: Failed get optional existing grant id.")?
663 {
664 tx.execute(
665 "UPDATE perboot.grant
666 SET access_vector = ?
667 WHERE id = ?;",
668 params![i32::from(access_vector), grant_id],
669 )
670 .context("In grant: Failed to update existing grant.")?;
671 grant_id
672 } else {
Joel Galenson845f74b2020-09-09 14:11:55 -0700673 Self::insert_with_retry(|id| {
674 tx.execute(
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700675 "INSERT INTO perboot.grant (id, grantee, keyentryid, access_vector)
676 VALUES (?, ?, ?, ?);",
Joel Galenson845f74b2020-09-09 14:11:55 -0700677 params![id, grantee_uid, key_id, i32::from(access_vector)],
678 )
679 })
680 .context("In grant")?
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700681 };
682 tx.commit().context("In grant: failed to commit transaction.")?;
683
684 Ok(KeyDescriptor { domain: Domain::Grant, namespace_: grant_id, alias: None, blob: None })
685 }
686
687 /// This function checks permissions like `grant` and `load_key_entry`
688 /// before removing a grant from the grant table.
689 pub fn ungrant(
690 &mut self,
691 key: KeyDescriptor,
692 caller_uid: u32,
693 grantee_uid: u32,
694 check_permission: impl FnOnce(&KeyDescriptor) -> Result<()>,
695 ) -> Result<()> {
696 let tx = self
697 .conn
698 .transaction_with_behavior(TransactionBehavior::Immediate)
699 .context("In ungrant: Failed to initialize transaction.")?;
700
701 // Load the key_id and complete the access control tuple.
702 // We ignore the access vector here because grants cannot be granted.
703 let (key_id, access_key_descriptor, _) =
704 Self::load_access_tuple(&tx, key, caller_uid).context("In ungrant.")?;
705
706 // Perform access control. We must return here if the permission
707 // was denied. So do not touch the '?' at the end of this line.
708 check_permission(&access_key_descriptor).context("In grant: check_permission failed.")?;
709
710 tx.execute(
711 "DELETE FROM perboot.grant
712 WHERE keyentryid = ? AND grantee = ?;",
713 params![key_id, grantee_uid],
714 )
715 .context("Failed to delete grant.")?;
716
717 tx.commit().context("In ungrant: failed to commit transaction.")?;
718
719 Ok(())
720 }
721
Joel Galenson845f74b2020-09-09 14:11:55 -0700722 // Generates a random id and passes it to the given function, which will
723 // try to insert it into a database. If that insertion fails, retry;
724 // otherwise return the id.
725 fn insert_with_retry(inserter: impl Fn(i64) -> rusqlite::Result<usize>) -> Result<i64> {
726 loop {
727 let newid: i64 = random();
728 match inserter(newid) {
729 // If the id already existed, try again.
730 Err(rusqlite::Error::SqliteFailure(
731 libsqlite3_sys::Error {
732 code: libsqlite3_sys::ErrorCode::ConstraintViolation,
733 extended_code: libsqlite3_sys::SQLITE_CONSTRAINT_UNIQUE,
734 },
735 _,
736 )) => (),
737 Err(e) => {
738 return Err(e).context("In insert_with_retry: failed to insert into database.")
739 }
740 _ => return Ok(newid),
741 }
742 }
743 }
744
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700745 // Takes Rows as returned by a query call on prepared statement.
746 // Extracts exactly one row with the `row_extractor` and fails if more
747 // rows are available.
748 // If no row was found, `None` is passed to the `row_extractor`.
749 // This allows the row extractor to decide on an error condition or
750 // a different default behavior.
751 fn with_rows_extract_one<'a, T, F>(rows: &mut Rows<'a>, row_extractor: F) -> Result<T>
752 where
753 F: FnOnce(Option<&Row<'a>>) -> Result<T>,
754 {
755 let result =
756 row_extractor(rows.next().context("with_rows_extract_one: Failed to unpack row.")?);
757
758 rows.next()
759 .context("In with_rows_extract_one: Failed to unpack unexpected row.")?
760 .map_or_else(|| Ok(()), |_| Err(KsError::sys()))
761 .context("In with_rows_extract_one: Unexpected row.")?;
762
763 result
764 }
765
766 fn with_rows_extract_all<'a, F>(rows: &mut Rows<'a>, mut row_extractor: F) -> Result<()>
767 where
768 F: FnMut(&Row<'a>) -> Result<()>,
769 {
770 loop {
771 match rows.next().context("In with_rows_extract_all: Failed to unpack row")? {
772 Some(row) => {
773 row_extractor(&row).context("In with_rows_extract_all.")?;
774 }
775 None => break Ok(()),
776 }
777 }
Joel Galenson33c04ad2020-08-03 11:04:38 -0700778 }
Joel Galenson26f4d012020-07-17 14:57:21 -0700779}
780
781#[cfg(test)]
782mod tests {
783
784 use super::*;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -0700785 use crate::key_parameter::{
786 Algorithm, BlockMode, Digest, EcCurve, HardwareAuthenticatorType, KeyOrigin, KeyParameter,
787 KeyParameterValue, KeyPurpose, PaddingMode, SecurityLevel,
788 };
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700789 use crate::key_perm_set;
790 use crate::permission::{KeyPerm, KeyPermSet};
791 use rusqlite::NO_PARAMS;
Joel Galenson0891bc12020-07-20 10:37:03 -0700792 use std::cell::RefCell;
793
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700794 static PERSISTENT_TEST_SQL: &str = "/data/local/tmp/persistent.sqlite";
795 static PERBOOT_TEST_SQL: &str = "/data/local/tmp/perboot.sqlite";
796
797 fn new_test_db() -> Result<KeystoreDB> {
798 let conn = KeystoreDB::make_connection("file::memory:", "file::memory:")?;
799
800 KeystoreDB::init_tables(&conn).context("Failed to initialize tables.")?;
801 Ok(KeystoreDB { conn })
802 }
803
804 fn new_test_db_with_persistent_file() -> Result<KeystoreDB> {
805 let conn = KeystoreDB::make_connection(PERSISTENT_TEST_SQL, PERBOOT_TEST_SQL)?;
806
807 KeystoreDB::init_tables(&conn).context("Failed to initialize tables.")?;
808 Ok(KeystoreDB { conn })
809 }
810
Joel Galenson0891bc12020-07-20 10:37:03 -0700811 // Ensure that we're using the "injected" random function, not the real one.
812 #[test]
813 fn test_mocked_random() {
814 let rand1 = random();
815 let rand2 = random();
816 let rand3 = random();
817 if rand1 == rand2 {
818 assert_eq!(rand2 + 1, rand3);
819 } else {
820 assert_eq!(rand1 + 1, rand2);
821 assert_eq!(rand2, rand3);
822 }
823 }
Joel Galenson26f4d012020-07-17 14:57:21 -0700824
Joel Galenson26f4d012020-07-17 14:57:21 -0700825 // Test that we have the correct tables.
826 #[test]
827 fn test_tables() -> Result<()> {
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700828 let db = new_test_db()?;
Joel Galenson26f4d012020-07-17 14:57:21 -0700829 let tables = db
830 .conn
Joel Galenson2aab4432020-07-22 15:27:57 -0700831 .prepare("SELECT name from persistent.sqlite_master WHERE type='table' ORDER BY name;")?
Joel Galenson26f4d012020-07-17 14:57:21 -0700832 .query_map(params![], |row| row.get(0))?
833 .collect::<rusqlite::Result<Vec<String>>>()?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700834 assert_eq!(tables.len(), 3);
835 assert_eq!(tables[0], "blobentry");
836 assert_eq!(tables[1], "keyentry");
837 assert_eq!(tables[2], "keyparameter");
838 let tables = db
839 .conn
840 .prepare("SELECT name from perboot.sqlite_master WHERE type='table' ORDER BY name;")?
841 .query_map(params![], |row| row.get(0))?
842 .collect::<rusqlite::Result<Vec<String>>>()?;
843 assert_eq!(tables.len(), 1);
844 assert_eq!(tables[0], "grant");
Joel Galenson26f4d012020-07-17 14:57:21 -0700845 Ok(())
846 }
Joel Galenson0891bc12020-07-20 10:37:03 -0700847
848 #[test]
Joel Galenson2aab4432020-07-22 15:27:57 -0700849 fn test_no_persistence_for_tests() -> Result<()> {
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700850 let db = new_test_db()?;
Joel Galenson2aab4432020-07-22 15:27:57 -0700851
Janis Danisevskis60400fe2020-08-26 15:24:42 -0700852 db.create_key_entry(Domain::App, 100)?;
Joel Galenson2aab4432020-07-22 15:27:57 -0700853 let entries = get_keyentry(&db)?;
854 assert_eq!(entries.len(), 1);
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700855 let db = new_test_db()?;
Joel Galenson2aab4432020-07-22 15:27:57 -0700856
857 let entries = get_keyentry(&db)?;
858 assert_eq!(entries.len(), 0);
859 Ok(())
860 }
861
862 #[test]
863 fn test_persistence_for_files() -> Result<()> {
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700864 let _file_guard_persistent = TempFile { filename: PERSISTENT_TEST_SQL };
865 let _file_guard_perboot = TempFile { filename: PERBOOT_TEST_SQL };
866 let db = new_test_db_with_persistent_file()?;
Joel Galenson2aab4432020-07-22 15:27:57 -0700867
Janis Danisevskis60400fe2020-08-26 15:24:42 -0700868 db.create_key_entry(Domain::App, 100)?;
Joel Galenson2aab4432020-07-22 15:27:57 -0700869 let entries = get_keyentry(&db)?;
870 assert_eq!(entries.len(), 1);
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700871 let db = new_test_db_with_persistent_file()?;
Joel Galenson2aab4432020-07-22 15:27:57 -0700872
873 let entries_new = get_keyentry(&db)?;
874 assert_eq!(entries, entries_new);
875 Ok(())
876 }
877
878 #[test]
Joel Galenson0891bc12020-07-20 10:37:03 -0700879 fn test_create_key_entry() -> Result<()> {
Janis Danisevskis60400fe2020-08-26 15:24:42 -0700880 fn extractor(ke: &KeyEntryRow) -> (DomainType, i64, Option<&str>) {
Joel Galenson0891bc12020-07-20 10:37:03 -0700881 (ke.domain.unwrap(), ke.namespace.unwrap(), ke.alias.as_deref())
882 }
883
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700884 let db = new_test_db()?;
Joel Galenson0891bc12020-07-20 10:37:03 -0700885
886 db.create_key_entry(Domain::App, 100)?;
887 db.create_key_entry(Domain::SELinux, 101)?;
888
889 let entries = get_keyentry(&db)?;
890 assert_eq!(entries.len(), 2);
891 assert_eq!(extractor(&entries[0]), (Domain::App, 100, None));
892 assert_eq!(extractor(&entries[1]), (Domain::SELinux, 101, None));
893
894 // Test that we must pass in a valid Domain.
895 check_result_is_error_containing_string(
896 db.create_key_entry(Domain::Grant, 102),
Janis Danisevskis60400fe2020-08-26 15:24:42 -0700897 "Domain 1 must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -0700898 );
899 check_result_is_error_containing_string(
900 db.create_key_entry(Domain::Blob, 103),
Janis Danisevskis60400fe2020-08-26 15:24:42 -0700901 "Domain 3 must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -0700902 );
903 check_result_is_error_containing_string(
904 db.create_key_entry(Domain::KeyId, 104),
Janis Danisevskis60400fe2020-08-26 15:24:42 -0700905 "Domain 4 must be either App or SELinux.",
Joel Galenson0891bc12020-07-20 10:37:03 -0700906 );
907
908 Ok(())
909 }
910
Joel Galenson33c04ad2020-08-03 11:04:38 -0700911 #[test]
912 fn test_rebind_alias() -> Result<()> {
Janis Danisevskis60400fe2020-08-26 15:24:42 -0700913 fn extractor(ke: &KeyEntryRow) -> (Option<DomainType>, Option<i64>, Option<&str>) {
Joel Galenson33c04ad2020-08-03 11:04:38 -0700914 (ke.domain, ke.namespace, ke.alias.as_deref())
915 }
916
Janis Danisevskis4df44f42020-08-26 14:40:03 -0700917 let mut db = new_test_db()?;
Joel Galenson33c04ad2020-08-03 11:04:38 -0700918 db.create_key_entry(Domain::App, 42)?;
919 db.create_key_entry(Domain::App, 42)?;
920 let entries = get_keyentry(&db)?;
921 assert_eq!(entries.len(), 2);
922 assert_eq!(extractor(&entries[0]), (Some(Domain::App), Some(42), None));
923 assert_eq!(extractor(&entries[1]), (Some(Domain::App), Some(42), None));
924
925 // Test that the first call to rebind_alias sets the alias.
926 db.rebind_alias(entries[0].id, "foo", Domain::App, 42)?;
927 let entries = get_keyentry(&db)?;
928 assert_eq!(entries.len(), 2);
929 assert_eq!(extractor(&entries[0]), (Some(Domain::App), Some(42), Some("foo")));
930 assert_eq!(extractor(&entries[1]), (Some(Domain::App), Some(42), None));
931
932 // Test that the second call to rebind_alias also empties the old one.
933 db.rebind_alias(entries[1].id, "foo", Domain::App, 42)?;
934 let entries = get_keyentry(&db)?;
935 assert_eq!(entries.len(), 2);
936 assert_eq!(extractor(&entries[0]), (None, None, None));
937 assert_eq!(extractor(&entries[1]), (Some(Domain::App), Some(42), Some("foo")));
938
939 // Test that we must pass in a valid Domain.
940 check_result_is_error_containing_string(
941 db.rebind_alias(0, "foo", Domain::Grant, 42),
Janis Danisevskis60400fe2020-08-26 15:24:42 -0700942 "Domain 1 must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -0700943 );
944 check_result_is_error_containing_string(
945 db.rebind_alias(0, "foo", Domain::Blob, 42),
Janis Danisevskis60400fe2020-08-26 15:24:42 -0700946 "Domain 3 must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -0700947 );
948 check_result_is_error_containing_string(
949 db.rebind_alias(0, "foo", Domain::KeyId, 42),
Janis Danisevskis60400fe2020-08-26 15:24:42 -0700950 "Domain 4 must be either App or SELinux.",
Joel Galenson33c04ad2020-08-03 11:04:38 -0700951 );
952
953 // Test that we correctly handle setting an alias for something that does not exist.
954 check_result_is_error_containing_string(
955 db.rebind_alias(0, "foo", Domain::SELinux, 42),
956 "Expected to update a single entry but instead updated 0",
957 );
958 // Test that we correctly abort the transaction in this case.
959 let entries = get_keyentry(&db)?;
960 assert_eq!(entries.len(), 2);
961 assert_eq!(extractor(&entries[0]), (None, None, None));
962 assert_eq!(extractor(&entries[1]), (Some(Domain::App), Some(42), Some("foo")));
963
964 Ok(())
965 }
966
Janis Danisevskis63f7bc82020-09-03 10:12:56 -0700967 #[test]
968 fn test_grant_ungrant() -> Result<()> {
969 const CALLER_UID: u32 = 15;
970 const GRANTEE_UID: u32 = 12;
971 const SELINUX_NAMESPACE: i64 = 7;
972
973 let mut db = new_test_db()?;
974 db.conn.execute(
975 "INSERT INTO persistent.keyentry (id, creation_date, domain, namespace, alias)
976 VALUES (1, '1980', 0, 15, 'key'), (2, '1980', 2, 7, 'yek');",
977 NO_PARAMS,
978 )?;
979 let app_key = KeyDescriptor {
980 domain: super::Domain::App,
981 namespace_: 0,
982 alias: Some("key".to_string()),
983 blob: None,
984 };
985 const PVEC1: KeyPermSet = key_perm_set![KeyPerm::use_(), KeyPerm::get_info()];
986 const PVEC2: KeyPermSet = key_perm_set![KeyPerm::use_()];
987
988 // Reset totally predictable random number generator in case we
989 // are not the first test running on this thread.
990 reset_random();
991 let next_random = 0i64;
992
993 let app_granted_key =
994 db.grant(app_key.clone(), CALLER_UID, GRANTEE_UID, PVEC1, |k, a| {
995 assert_eq!(*a, PVEC1);
996 assert_eq!(
997 *k,
998 KeyDescriptor {
999 domain: super::Domain::App,
1000 // namespace must be set to the caller_uid.
1001 namespace_: CALLER_UID as i64,
1002 alias: Some("key".to_string()),
1003 blob: None,
1004 }
1005 );
1006 Ok(())
1007 })?;
1008
1009 assert_eq!(
1010 app_granted_key,
1011 KeyDescriptor {
1012 domain: super::Domain::Grant,
1013 // The grantid is next_random due to the mock random number generator.
1014 namespace_: next_random,
1015 alias: None,
1016 blob: None,
1017 }
1018 );
1019
1020 let selinux_key = KeyDescriptor {
1021 domain: super::Domain::SELinux,
1022 namespace_: SELINUX_NAMESPACE,
1023 alias: Some("yek".to_string()),
1024 blob: None,
1025 };
1026
1027 let selinux_granted_key =
1028 db.grant(selinux_key.clone(), CALLER_UID, 12, PVEC1, |k, a| {
1029 assert_eq!(*a, PVEC1);
1030 assert_eq!(
1031 *k,
1032 KeyDescriptor {
1033 domain: super::Domain::SELinux,
1034 // namespace must be the supplied SELinux
1035 // namespace.
1036 namespace_: SELINUX_NAMESPACE,
1037 alias: Some("yek".to_string()),
1038 blob: None,
1039 }
1040 );
1041 Ok(())
1042 })?;
1043
1044 assert_eq!(
1045 selinux_granted_key,
1046 KeyDescriptor {
1047 domain: super::Domain::Grant,
1048 // The grantid is next_random + 1 due to the mock random number generator.
1049 namespace_: next_random + 1,
1050 alias: None,
1051 blob: None,
1052 }
1053 );
1054
1055 // This should update the existing grant with PVEC2.
1056 let selinux_granted_key =
1057 db.grant(selinux_key.clone(), CALLER_UID, 12, PVEC2, |k, a| {
1058 assert_eq!(*a, PVEC2);
1059 assert_eq!(
1060 *k,
1061 KeyDescriptor {
1062 domain: super::Domain::SELinux,
1063 // namespace must be the supplied SELinux
1064 // namespace.
1065 namespace_: SELINUX_NAMESPACE,
1066 alias: Some("yek".to_string()),
1067 blob: None,
1068 }
1069 );
1070 Ok(())
1071 })?;
1072
1073 assert_eq!(
1074 selinux_granted_key,
1075 KeyDescriptor {
1076 domain: super::Domain::Grant,
1077 // Same grant id as before. The entry was only updated.
1078 namespace_: next_random + 1,
1079 alias: None,
1080 blob: None,
1081 }
1082 );
1083
1084 {
1085 // Limiting scope of stmt, because it borrows db.
1086 let mut stmt = db
1087 .conn
1088 .prepare("SELECT id, grantee, keyentryid, access_vector FROM perboot.grant;")?;
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07001089 let mut rows =
1090 stmt.query_map::<(i64, u32, i64, KeyPermSet), _, _>(NO_PARAMS, |row| {
1091 Ok((
1092 row.get(0)?,
1093 row.get(1)?,
1094 row.get(2)?,
1095 KeyPermSet::from(row.get::<_, i32>(3)?),
1096 ))
1097 })?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001098
1099 let r = rows.next().unwrap().unwrap();
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07001100 assert_eq!(r, (next_random, GRANTEE_UID, 1, PVEC1));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001101 let r = rows.next().unwrap().unwrap();
Janis Danisevskisee10b5f2020-09-22 16:42:35 -07001102 assert_eq!(r, (next_random + 1, GRANTEE_UID, 2, PVEC2));
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001103 assert!(rows.next().is_none());
1104 }
1105
1106 debug_dump_keyentry_table(&mut db)?;
1107 println!("app_key {:?}", app_key);
1108 println!("selinux_key {:?}", selinux_key);
1109
1110 db.ungrant(app_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
1111 db.ungrant(selinux_key, CALLER_UID, GRANTEE_UID, |_| Ok(()))?;
1112
1113 Ok(())
1114 }
1115
1116 static TEST_KM_BLOB: &[u8] = b"my test blob";
1117 static TEST_CERT_BLOB: &[u8] = b"my test cert";
1118 static TEST_CERT_CHAIN_BLOB: &[u8] = b"my test cert_chain";
1119
1120 #[test]
1121 fn test_insert_blob() -> Result<()> {
1122 let mut db = new_test_db()?;
1123 db.insert_blob(1, SubComponentType::KM_BLOB, TEST_KM_BLOB, 1)?;
1124 db.insert_blob(1, SubComponentType::CERT, TEST_CERT_BLOB, 2)?;
1125 db.insert_blob(1, SubComponentType::CERT_CHAIN, TEST_CERT_CHAIN_BLOB, 3)?;
1126
1127 let mut stmt = db.conn.prepare(
1128 "SELECT subcomponent_type, keyentryid, blob, sec_level FROM persistent.blobentry
1129 ORDER BY sec_level ASC;",
1130 )?;
1131 let mut rows = stmt
1132 .query_map::<(SubComponentType, i64, Vec<u8>, i64), _, _>(NO_PARAMS, |row| {
1133 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?))
1134 })?;
1135 let r = rows.next().unwrap().unwrap();
1136 assert_eq!(r, (SubComponentType::KM_BLOB, 1, TEST_KM_BLOB.to_vec(), 1));
1137 let r = rows.next().unwrap().unwrap();
1138 assert_eq!(r, (SubComponentType::CERT, 1, TEST_CERT_BLOB.to_vec(), 2));
1139 let r = rows.next().unwrap().unwrap();
1140 assert_eq!(r, (SubComponentType::CERT_CHAIN, 1, TEST_CERT_CHAIN_BLOB.to_vec(), 3));
1141
1142 Ok(())
1143 }
1144
1145 static TEST_ALIAS: &str = "my super duper key";
1146
1147 #[test]
1148 fn test_insert_and_load_full_keyentry_domain_app() -> Result<()> {
1149 let mut db = new_test_db()?;
1150 let key_id = make_test_key_entry(&mut db, Domain::App, 1, TEST_ALIAS)
1151 .context("test_insert_and_load_full_keyentry_domain_app")?;
1152 let key_entry = db.load_key_entry(
1153 KeyDescriptor {
1154 domain: Domain::App,
1155 namespace_: 0,
1156 alias: Some(TEST_ALIAS.to_string()),
1157 blob: None,
1158 },
1159 KeyEntryLoadBits::BOTH,
1160 1,
1161 |_k, _av| Ok(()),
1162 )?;
1163 assert_eq!(
1164 key_entry,
1165 KeyEntry {
1166 id: key_id,
1167 km_blob: Some(TEST_KM_BLOB.to_vec()),
1168 cert: Some(TEST_CERT_BLOB.to_vec()),
1169 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
1170 sec_level: 1,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001171 parameters: make_test_params()
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001172 }
1173 );
1174 Ok(())
1175 }
1176
1177 #[test]
1178 fn test_insert_and_load_full_keyentry_domain_selinux() -> Result<()> {
1179 let mut db = new_test_db()?;
1180 let key_id = make_test_key_entry(&mut db, Domain::SELinux, 1, TEST_ALIAS)
1181 .context("test_insert_and_load_full_keyentry_domain_selinux")?;
1182 let key_entry = db.load_key_entry(
1183 KeyDescriptor {
1184 domain: Domain::SELinux,
1185 namespace_: 1,
1186 alias: Some(TEST_ALIAS.to_string()),
1187 blob: None,
1188 },
1189 KeyEntryLoadBits::BOTH,
1190 1,
1191 |_k, _av| Ok(()),
1192 )?;
1193 assert_eq!(
1194 key_entry,
1195 KeyEntry {
1196 id: key_id,
1197 km_blob: Some(TEST_KM_BLOB.to_vec()),
1198 cert: Some(TEST_CERT_BLOB.to_vec()),
1199 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
1200 sec_level: 1,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001201 parameters: make_test_params()
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001202 }
1203 );
1204 Ok(())
1205 }
1206
1207 #[test]
1208 fn test_insert_and_load_full_keyentry_domain_key_id() -> Result<()> {
1209 let mut db = new_test_db()?;
1210 let key_id = make_test_key_entry(&mut db, Domain::SELinux, 1, TEST_ALIAS)
1211 .context("test_insert_and_load_full_keyentry_domain_key_id")?;
1212 let key_entry = db.load_key_entry(
1213 KeyDescriptor { domain: Domain::KeyId, namespace_: key_id, alias: None, blob: None },
1214 KeyEntryLoadBits::BOTH,
1215 1,
1216 |_k, _av| Ok(()),
1217 )?;
1218 assert_eq!(
1219 key_entry,
1220 KeyEntry {
1221 id: key_id,
1222 km_blob: Some(TEST_KM_BLOB.to_vec()),
1223 cert: Some(TEST_CERT_BLOB.to_vec()),
1224 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
1225 sec_level: 1,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001226 parameters: make_test_params()
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001227 }
1228 );
1229
1230 Ok(())
1231 }
1232
1233 #[test]
1234 fn test_insert_and_load_full_keyentry_from_grant() -> Result<()> {
1235 let mut db = new_test_db()?;
1236 let key_id = make_test_key_entry(&mut db, Domain::App, 1, TEST_ALIAS)
1237 .context("test_insert_and_load_full_keyentry_from_grant")?;
1238
1239 let granted_key = db.grant(
1240 KeyDescriptor {
1241 domain: Domain::App,
1242 namespace_: 0,
1243 alias: Some(TEST_ALIAS.to_string()),
1244 blob: None,
1245 },
1246 1,
1247 2,
1248 key_perm_set![KeyPerm::use_()],
1249 |_k, _av| Ok(()),
1250 )?;
1251
1252 debug_dump_grant_table(&mut db)?;
1253
1254 let key_entry = db.load_key_entry(granted_key, KeyEntryLoadBits::BOTH, 2, |k, av| {
1255 assert_eq!(Domain::Grant, k.domain);
1256 assert!(av.unwrap().includes(KeyPerm::use_()));
1257 Ok(())
1258 })?;
1259
1260 assert_eq!(
1261 key_entry,
1262 KeyEntry {
1263 id: key_id,
1264 km_blob: Some(TEST_KM_BLOB.to_vec()),
1265 cert: Some(TEST_CERT_BLOB.to_vec()),
1266 cert_chain: Some(TEST_CERT_CHAIN_BLOB.to_vec()),
1267 sec_level: 1,
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001268 parameters: make_test_params()
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001269 }
1270 );
1271 Ok(())
1272 }
1273
Joel Galenson0891bc12020-07-20 10:37:03 -07001274 // Helpers
1275
1276 // Checks that the given result is an error containing the given string.
1277 fn check_result_is_error_containing_string<T>(result: Result<T>, target: &str) {
1278 let error_str = format!(
1279 "{:#?}",
1280 result.err().unwrap_or_else(|| panic!("Expected the error: {}", target))
1281 );
1282 assert!(
1283 error_str.contains(target),
1284 "The string \"{}\" should contain \"{}\"",
1285 error_str,
1286 target
1287 );
1288 }
1289
Joel Galenson2aab4432020-07-22 15:27:57 -07001290 #[derive(Debug, PartialEq)]
Joel Galenson0891bc12020-07-20 10:37:03 -07001291 #[allow(dead_code)]
1292 struct KeyEntryRow {
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001293 id: i64,
Joel Galenson0891bc12020-07-20 10:37:03 -07001294 creation_date: String,
Janis Danisevskis60400fe2020-08-26 15:24:42 -07001295 domain: Option<DomainType>,
Joel Galenson0891bc12020-07-20 10:37:03 -07001296 namespace: Option<i64>,
1297 alias: Option<String>,
1298 }
1299
1300 fn get_keyentry(db: &KeystoreDB) -> Result<Vec<KeyEntryRow>> {
1301 db.conn
Joel Galenson2aab4432020-07-22 15:27:57 -07001302 .prepare("SELECT * FROM persistent.keyentry;")?
Joel Galenson0891bc12020-07-20 10:37:03 -07001303 .query_map(NO_PARAMS, |row| {
Joel Galenson0891bc12020-07-20 10:37:03 -07001304 Ok(KeyEntryRow {
1305 id: row.get(0)?,
1306 creation_date: row.get(1)?,
Janis Danisevskis60400fe2020-08-26 15:24:42 -07001307 domain: row.get(2)?,
Joel Galenson0891bc12020-07-20 10:37:03 -07001308 namespace: row.get(3)?,
1309 alias: row.get(4)?,
1310 })
1311 })?
1312 .map(|r| r.context("Could not read keyentry row."))
1313 .collect::<Result<Vec<_>>>()
1314 }
1315
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001316 // Note: The parameters and SecurityLevel associations are nonsensical. This
1317 // collection is only used to check if the parameters are preserved as expected by the
1318 // database.
1319 fn make_test_params() -> Vec<KeyParameter> {
1320 vec![
1321 KeyParameter::new(KeyParameterValue::Invalid, SecurityLevel::TRUSTED_ENVIRONMENT),
1322 KeyParameter::new(
1323 KeyParameterValue::KeyPurpose(KeyPurpose::SIGN),
1324 SecurityLevel::TRUSTED_ENVIRONMENT,
1325 ),
1326 KeyParameter::new(
1327 KeyParameterValue::KeyPurpose(KeyPurpose::DECRYPT),
1328 SecurityLevel::TRUSTED_ENVIRONMENT,
1329 ),
1330 KeyParameter::new(
1331 KeyParameterValue::Algorithm(Algorithm::RSA),
1332 SecurityLevel::TRUSTED_ENVIRONMENT,
1333 ),
1334 KeyParameter::new(KeyParameterValue::KeySize(1024), SecurityLevel::TRUSTED_ENVIRONMENT),
1335 KeyParameter::new(
1336 KeyParameterValue::BlockMode(BlockMode::ECB),
1337 SecurityLevel::TRUSTED_ENVIRONMENT,
1338 ),
1339 KeyParameter::new(
1340 KeyParameterValue::BlockMode(BlockMode::GCM),
1341 SecurityLevel::TRUSTED_ENVIRONMENT,
1342 ),
1343 KeyParameter::new(KeyParameterValue::Digest(Digest::NONE), SecurityLevel::STRONGBOX),
1344 KeyParameter::new(
1345 KeyParameterValue::Digest(Digest::MD5),
1346 SecurityLevel::TRUSTED_ENVIRONMENT,
1347 ),
1348 KeyParameter::new(
1349 KeyParameterValue::Digest(Digest::SHA_2_224),
1350 SecurityLevel::TRUSTED_ENVIRONMENT,
1351 ),
1352 KeyParameter::new(
1353 KeyParameterValue::Digest(Digest::SHA_2_256),
1354 SecurityLevel::STRONGBOX,
1355 ),
1356 KeyParameter::new(
1357 KeyParameterValue::PaddingMode(PaddingMode::NONE),
1358 SecurityLevel::TRUSTED_ENVIRONMENT,
1359 ),
1360 KeyParameter::new(
1361 KeyParameterValue::PaddingMode(PaddingMode::RSA_OAEP),
1362 SecurityLevel::TRUSTED_ENVIRONMENT,
1363 ),
1364 KeyParameter::new(
1365 KeyParameterValue::PaddingMode(PaddingMode::RSA_PSS),
1366 SecurityLevel::STRONGBOX,
1367 ),
1368 KeyParameter::new(
1369 KeyParameterValue::PaddingMode(PaddingMode::RSA_PKCS1_1_5_SIGN),
1370 SecurityLevel::TRUSTED_ENVIRONMENT,
1371 ),
1372 KeyParameter::new(KeyParameterValue::CallerNonce, SecurityLevel::TRUSTED_ENVIRONMENT),
1373 KeyParameter::new(KeyParameterValue::MinMacLength(256), SecurityLevel::STRONGBOX),
1374 KeyParameter::new(
1375 KeyParameterValue::EcCurve(EcCurve::P_224),
1376 SecurityLevel::TRUSTED_ENVIRONMENT,
1377 ),
1378 KeyParameter::new(KeyParameterValue::EcCurve(EcCurve::P_256), SecurityLevel::STRONGBOX),
1379 KeyParameter::new(
1380 KeyParameterValue::EcCurve(EcCurve::P_384),
1381 SecurityLevel::TRUSTED_ENVIRONMENT,
1382 ),
1383 KeyParameter::new(
1384 KeyParameterValue::EcCurve(EcCurve::P_521),
1385 SecurityLevel::TRUSTED_ENVIRONMENT,
1386 ),
1387 KeyParameter::new(
1388 KeyParameterValue::RSAPublicExponent(3),
1389 SecurityLevel::TRUSTED_ENVIRONMENT,
1390 ),
1391 KeyParameter::new(
1392 KeyParameterValue::IncludeUniqueID,
1393 SecurityLevel::TRUSTED_ENVIRONMENT,
1394 ),
1395 KeyParameter::new(KeyParameterValue::BootLoaderOnly, SecurityLevel::STRONGBOX),
1396 KeyParameter::new(KeyParameterValue::RollbackResistance, SecurityLevel::STRONGBOX),
1397 KeyParameter::new(
1398 KeyParameterValue::ActiveDateTime(1234567890),
1399 SecurityLevel::STRONGBOX,
1400 ),
1401 KeyParameter::new(
1402 KeyParameterValue::OriginationExpireDateTime(1234567890),
1403 SecurityLevel::TRUSTED_ENVIRONMENT,
1404 ),
1405 KeyParameter::new(
1406 KeyParameterValue::UsageExpireDateTime(1234567890),
1407 SecurityLevel::TRUSTED_ENVIRONMENT,
1408 ),
1409 KeyParameter::new(
1410 KeyParameterValue::MinSecondsBetweenOps(1234567890),
1411 SecurityLevel::TRUSTED_ENVIRONMENT,
1412 ),
1413 KeyParameter::new(
1414 KeyParameterValue::MaxUsesPerBoot(1234567890),
1415 SecurityLevel::TRUSTED_ENVIRONMENT,
1416 ),
1417 KeyParameter::new(KeyParameterValue::UserID(1), SecurityLevel::STRONGBOX),
1418 KeyParameter::new(KeyParameterValue::UserSecureID(42), SecurityLevel::STRONGBOX),
1419 KeyParameter::new(
1420 KeyParameterValue::NoAuthRequired,
1421 SecurityLevel::TRUSTED_ENVIRONMENT,
1422 ),
1423 KeyParameter::new(
1424 KeyParameterValue::HardwareAuthenticatorType(HardwareAuthenticatorType::PASSWORD),
1425 SecurityLevel::TRUSTED_ENVIRONMENT,
1426 ),
1427 KeyParameter::new(KeyParameterValue::AuthTimeout(1234567890), SecurityLevel::SOFTWARE),
1428 KeyParameter::new(KeyParameterValue::AllowWhileOnBody, SecurityLevel::SOFTWARE),
1429 KeyParameter::new(
1430 KeyParameterValue::TrustedUserPresenceRequired,
1431 SecurityLevel::TRUSTED_ENVIRONMENT,
1432 ),
1433 KeyParameter::new(
1434 KeyParameterValue::TrustedConfirmationRequired,
1435 SecurityLevel::TRUSTED_ENVIRONMENT,
1436 ),
1437 KeyParameter::new(
1438 KeyParameterValue::UnlockedDeviceRequired,
1439 SecurityLevel::TRUSTED_ENVIRONMENT,
1440 ),
1441 KeyParameter::new(
1442 KeyParameterValue::ApplicationID(vec![1u8, 2u8, 3u8, 4u8]),
1443 SecurityLevel::SOFTWARE,
1444 ),
1445 KeyParameter::new(
1446 KeyParameterValue::ApplicationData(vec![4u8, 3u8, 2u8, 1u8]),
1447 SecurityLevel::SOFTWARE,
1448 ),
1449 KeyParameter::new(
1450 KeyParameterValue::CreationDateTime(12345677890),
1451 SecurityLevel::SOFTWARE,
1452 ),
1453 KeyParameter::new(
1454 KeyParameterValue::KeyOrigin(KeyOrigin::GENERATED),
1455 SecurityLevel::TRUSTED_ENVIRONMENT,
1456 ),
1457 KeyParameter::new(
1458 KeyParameterValue::RootOfTrust(vec![3u8, 2u8, 1u8, 4u8]),
1459 SecurityLevel::TRUSTED_ENVIRONMENT,
1460 ),
1461 KeyParameter::new(KeyParameterValue::OSVersion(1), SecurityLevel::TRUSTED_ENVIRONMENT),
1462 KeyParameter::new(KeyParameterValue::OSPatchLevel(2), SecurityLevel::SOFTWARE),
1463 KeyParameter::new(
1464 KeyParameterValue::UniqueID(vec![4u8, 3u8, 1u8, 2u8]),
1465 SecurityLevel::SOFTWARE,
1466 ),
1467 KeyParameter::new(
1468 KeyParameterValue::AttestationChallenge(vec![4u8, 3u8, 1u8, 2u8]),
1469 SecurityLevel::TRUSTED_ENVIRONMENT,
1470 ),
1471 KeyParameter::new(
1472 KeyParameterValue::AttestationApplicationID(vec![4u8, 3u8, 1u8, 2u8]),
1473 SecurityLevel::TRUSTED_ENVIRONMENT,
1474 ),
1475 KeyParameter::new(
1476 KeyParameterValue::AttestationIdBrand(vec![4u8, 3u8, 1u8, 2u8]),
1477 SecurityLevel::TRUSTED_ENVIRONMENT,
1478 ),
1479 KeyParameter::new(
1480 KeyParameterValue::AttestationIdDevice(vec![4u8, 3u8, 1u8, 2u8]),
1481 SecurityLevel::TRUSTED_ENVIRONMENT,
1482 ),
1483 KeyParameter::new(
1484 KeyParameterValue::AttestationIdProduct(vec![4u8, 3u8, 1u8, 2u8]),
1485 SecurityLevel::TRUSTED_ENVIRONMENT,
1486 ),
1487 KeyParameter::new(
1488 KeyParameterValue::AttestationIdSerial(vec![4u8, 3u8, 1u8, 2u8]),
1489 SecurityLevel::TRUSTED_ENVIRONMENT,
1490 ),
1491 KeyParameter::new(
1492 KeyParameterValue::AttestationIdIMEI(vec![4u8, 3u8, 1u8, 2u8]),
1493 SecurityLevel::TRUSTED_ENVIRONMENT,
1494 ),
1495 KeyParameter::new(
1496 KeyParameterValue::AttestationIdMEID(vec![4u8, 3u8, 1u8, 2u8]),
1497 SecurityLevel::TRUSTED_ENVIRONMENT,
1498 ),
1499 KeyParameter::new(
1500 KeyParameterValue::AttestationIdManufacturer(vec![4u8, 3u8, 1u8, 2u8]),
1501 SecurityLevel::TRUSTED_ENVIRONMENT,
1502 ),
1503 KeyParameter::new(
1504 KeyParameterValue::AttestationIdModel(vec![4u8, 3u8, 1u8, 2u8]),
1505 SecurityLevel::TRUSTED_ENVIRONMENT,
1506 ),
1507 KeyParameter::new(
1508 KeyParameterValue::VendorPatchLevel(3),
1509 SecurityLevel::TRUSTED_ENVIRONMENT,
1510 ),
1511 KeyParameter::new(
1512 KeyParameterValue::BootPatchLevel(4),
1513 SecurityLevel::TRUSTED_ENVIRONMENT,
1514 ),
1515 KeyParameter::new(
1516 KeyParameterValue::AssociatedData(vec![4u8, 3u8, 1u8, 2u8]),
1517 SecurityLevel::TRUSTED_ENVIRONMENT,
1518 ),
1519 KeyParameter::new(
1520 KeyParameterValue::Nonce(vec![4u8, 3u8, 1u8, 2u8]),
1521 SecurityLevel::TRUSTED_ENVIRONMENT,
1522 ),
1523 KeyParameter::new(
1524 KeyParameterValue::MacLength(256),
1525 SecurityLevel::TRUSTED_ENVIRONMENT,
1526 ),
1527 KeyParameter::new(
1528 KeyParameterValue::ResetSinceIdRotation,
1529 SecurityLevel::TRUSTED_ENVIRONMENT,
1530 ),
1531 KeyParameter::new(
1532 KeyParameterValue::ConfirmationToken(vec![5u8, 5u8, 5u8, 5u8]),
1533 SecurityLevel::TRUSTED_ENVIRONMENT,
1534 ),
1535 ]
1536 }
1537
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001538 fn make_test_key_entry(
1539 db: &mut KeystoreDB,
1540 domain: DomainType,
1541 namespace: i64,
1542 alias: &str,
1543 ) -> Result<i64> {
1544 let key_id = db.create_key_entry(domain, namespace)?;
1545 db.insert_blob(key_id, SubComponentType::KM_BLOB, TEST_KM_BLOB, 1)?;
1546 db.insert_blob(key_id, SubComponentType::CERT, TEST_CERT_BLOB, 1)?;
1547 db.insert_blob(key_id, SubComponentType::CERT_CHAIN, TEST_CERT_CHAIN_BLOB, 1)?;
Janis Danisevskis3f322cb2020-09-03 14:46:22 -07001548 db.insert_keyparameter(key_id, &make_test_params())?;
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001549 db.rebind_alias(key_id, alias, domain, namespace)?;
1550 Ok(key_id)
1551 }
1552
1553 fn debug_dump_keyentry_table(db: &mut KeystoreDB) -> Result<()> {
1554 let mut stmt = db.conn.prepare(
1555 "SELECT id, creation_date, domain, namespace, alias FROM persistent.keyentry;",
1556 )?;
1557 let rows = stmt.query_map::<(i64, i64, i32, i64, String), _, _>(NO_PARAMS, |row| {
1558 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?, row.get(4)?))
1559 })?;
1560
1561 println!("Key entry table rows:");
1562 for r in rows {
1563 let (id, cdate, domain, namespace, alias) = r.unwrap();
1564 println!(
1565 " id: {} Creation date: {} Domain: {} Namespace: {} Alias: {}",
1566 id, cdate, domain, namespace, alias
1567 );
1568 }
1569 Ok(())
1570 }
1571
1572 fn debug_dump_grant_table(db: &mut KeystoreDB) -> Result<()> {
1573 let mut stmt =
1574 db.conn.prepare("SELECT id, grantee, keyentryid, access_vector FROM perboot.grant;")?;
1575 let rows = stmt.query_map::<(i64, i64, i64, i64), _, _>(NO_PARAMS, |row| {
1576 Ok((row.get(0)?, row.get(1)?, row.get(2)?, row.get(3)?))
1577 })?;
1578
1579 println!("Grant table rows:");
1580 for r in rows {
1581 let (id, gt, ki, av) = r.unwrap();
1582 println!(" id: {} grantee: {} key_id: {} access_vector: {}", id, gt, ki, av);
1583 }
1584 Ok(())
1585 }
1586
Joel Galenson2aab4432020-07-22 15:27:57 -07001587 // A class that deletes a file when it is dropped.
1588 // TODO: If we ever add a crate that does this, we can use it instead.
1589 struct TempFile {
1590 filename: &'static str,
1591 }
1592
1593 impl Drop for TempFile {
1594 fn drop(&mut self) {
1595 std::fs::remove_file(self.filename).expect("Cannot delete temporary file");
1596 }
1597 }
1598
Joel Galenson0891bc12020-07-20 10:37:03 -07001599 // Use a custom random number generator that repeats each number once.
1600 // This allows us to test repeated elements.
1601
1602 thread_local! {
1603 static RANDOM_COUNTER: RefCell<i64> = RefCell::new(0);
1604 }
1605
Janis Danisevskis63f7bc82020-09-03 10:12:56 -07001606 fn reset_random() {
1607 RANDOM_COUNTER.with(|counter| {
1608 *counter.borrow_mut() = 0;
1609 })
1610 }
1611
Joel Galenson0891bc12020-07-20 10:37:03 -07001612 pub fn random() -> i64 {
1613 RANDOM_COUNTER.with(|counter| {
1614 let result = *counter.borrow() / 2;
1615 *counter.borrow_mut() += 1;
1616 result
1617 })
1618 }
Joel Galenson26f4d012020-07-17 14:57:21 -07001619}