Skip to main content

parsec_service/key_info_managers/sqlite_manager/
mod.rs

1// Copyright 2021 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3//! A key info manager storing key identity to key info mappings using a SQLite database.
4//!
5//! For security reasons, only the PARSEC service should have the ability to modify these files.
6use super::{KeyIdentity, KeyInfo, ManageKeyInfo};
7use crate::authenticators::{ApplicationIdentity, Auth, INTERNAL_AUTH_ID};
8use crate::providers::ProviderIdentity;
9use crate::utils::config::KeyInfoManagerType;
10use anyhow::{Context, Result};
11use log::{error, info};
12use num_traits::FromPrimitive;
13use parsec_interface::operations::psa_key_attributes::Attributes;
14use parsec_interface::requests::AuthType;
15use rusqlite::types::Type::{Blob, Integer};
16use rusqlite::{Connection, Error as RusqliteError, params};
17use std::collections::HashMap;
18use std::fs;
19use std::fs::Permissions;
20use std::io::{Error, ErrorKind};
21use std::os::unix::fs::PermissionsExt;
22use std::path::PathBuf;
23
24/// Default path where the database will be stored on disk
25pub const DEFAULT_DB_PATH: &str =
26    "/var/lib/parsec/kim-mappings/sqlite/sqlite-key-info-manager.sqlite3";
27
28///File permissions for sqlite database
29///Should only be visible to parsec user
30pub const FILE_PERMISSION: u32 = 0o600;
31
32/// The current serialization version of the Attributes object.
33pub const CURRENT_KEY_ATTRIBUTES_VERSION: u8 = 1;
34
35/// Placeholder global key_id_version until a new key id version for
36/// one of the providers is needed.
37pub const CURRENT_KEY_ID_VERSION: u8 = 1;
38
39/// The current database schema version of the SQLiteKeyInfoManager.
40pub const CURRENT_SCHEMA_VERSION: u8 = 1;
41
42/// A key info manager storing key identity to key info mapping on files on disk
43#[derive(Debug)]
44pub struct SQLiteKeyInfoManager {
45    /// Internal mapping, used for non-modifying operations.
46    key_store: HashMap<KeyIdentity, KeyInfo>,
47    /// The file path where the SQLite database exists. This database holds
48    /// key identity to key info mappings.
49    database_path: PathBuf,
50}
51
52/// Converts a 64 bit integer to an AuthType
53fn i64_to_auth_type(auth_type: i64) -> Result<AuthType, String> {
54    match FromPrimitive::from_i64(auth_type) {
55        Some(auth_type) => Ok(auth_type),
56        None => Err(format!(
57            "Failed to get AuthType from authenticator_id.\nAuthenticator \"{}\" does not exist.",
58            auth_type
59        )),
60    }
61}
62
63/// SQLite-based `KeyInfoManager`
64///
65/// The `SQLiteKeyInfoManager` relies on access control mechanisms provided by the OS for
66/// the filesystem to ensure security of the database.
67impl SQLiteKeyInfoManager {
68    /// Creates an instance of the sqlite key info manager.
69    /// The SQLiteKeyInfoManager stores key info in the provided database_path file.
70    /// Uses rusqlite.
71    fn new(database_path: PathBuf) -> Result<SQLiteKeyInfoManager> {
72        // Create directory if it does not already exist
73        let mut directory_path = database_path.clone();
74        let _ = directory_path.pop();
75        fs::create_dir_all(&directory_path)
76            .with_context(|| format!("create directory {:?}", directory_path))?;
77        // Connect to or create database at set path
78        let conn = Connection::open(&database_path)?;
79        let mut key_store = HashMap::new();
80
81        // Check if the tables we require exist
82        let mut check_for_tables_stmt = conn.prepare(
83            "
84            SELECT
85                *
86            FROM
87                sqlite_master
88            WHERE
89                type='table'
90                AND (
91                    name='key_mapping'
92                    OR name='kim_metadata'
93                )
94        ",
95        )?;
96        let key_iter = check_for_tables_stmt.query_map([], |_row| Ok(()))?;
97        let num_of_tables = key_iter.count();
98        match num_of_tables {
99            // Create tables as they do not exist.
100            0 => {
101                let _ = conn.execute(
102                    "
103                    CREATE TABLE kim_metadata (
104                        id                    TEXT NOT NULL,
105                        int_value             INTEGER NOT NULL,
106                        PRIMARY KEY (id)
107                    )
108                    ",
109                    [],
110                )?;
111                let _ = conn.execute(
112                    "
113                    INSERT INTO
114                        kim_metadata
115                        (id, int_value)
116                    VALUES
117                        ('schema_version', ?1)
118                    ",
119                    params![CURRENT_SCHEMA_VERSION],
120                )?;
121                let _ = conn.execute(
122                    "
123                    CREATE TABLE IF NOT EXISTS key_mapping (
124                        authenticator_id            INTEGER NOT NULL,
125                        application_name            TEXT NOT NULL,
126                        key_name                    TEXT NOT NULL,
127                        provider_uuid               TEXT NOT NULL,
128                        provider_name               TEXT NOT NULL,
129                        key_id                      BLOB NOT NULL,
130                        key_id_version              INTEGER NOT NULL,
131                        key_attributes              BLOB NOT NULL,
132                        key_attributes_version      INTEGER NOT NULL,
133                        PRIMARY KEY (authenticator_id, application_name, key_name)
134                    )
135                    ",
136                    [],
137                )?;
138            }
139            // The correct number of tables are present, no-op
140            2 => {}
141            // The KIM expects both the kim_metadata and key_mapping table to be present, throw an error
142            _ => {
143                let error_message = format!(
144                    "SQLiteKeyInfoManager database schema is not in a recognised format.
145                    There is an unrecognised number of tables in the database.
146                    Database found at {}",
147                    database_path
148                        .into_os_string()
149                        .into_string()
150                        .unwrap_or_else(|_| "DB_FILE_PATH_UNKNOWN".to_string()),
151                );
152                error!("{}", error_message);
153                return Err(Error::other(error_message).into());
154            }
155        }
156
157        // The tables we require exist, check schema version matches
158        let mut schema_version_stmt = conn.prepare(
159            "
160            SELECT
161                *
162            FROM
163                kim_metadata
164            WHERE
165                id = 'schema_version'
166        ",
167        )?;
168        let mut rows = schema_version_stmt.query(params![])?;
169        while let Some(row) = rows.next()? {
170            let version_number: u8 = row.get("int_value")?;
171            if version_number != CURRENT_SCHEMA_VERSION {
172                let error_message = format!(
173                    "
174                    SQLiteKeyInfoManager database schema version is incompatible.
175                    Parsec Service is using version [{}].
176                    Database at [{}] is using version [{}].
177                    ",
178                    CURRENT_SCHEMA_VERSION,
179                    database_path
180                        .into_os_string()
181                        .into_string()
182                        .unwrap_or_else(|_| "DB_FILE_PATH_UNKNOWN".to_string()),
183                    version_number
184                );
185                error!("{}", error_message);
186                return Err(Error::other(error_message).into());
187            }
188        }
189
190        // The tables we require exist and the schema version is the correct.
191        // Check that the key_info_version for every key is correct.
192        let mut key_info_version_stmt = conn.prepare(
193            "
194            SELECT
195                *
196            FROM
197                key_mapping
198            WHERE
199                key_id_version != ?1
200                OR key_attributes_version != ?2
201            ",
202        )?;
203        let mut rows = key_info_version_stmt.query(params![
204            CURRENT_KEY_ID_VERSION,
205            CURRENT_KEY_ATTRIBUTES_VERSION
206        ])?;
207        // If a mapping exists with the wrong key_id_version or key_attributes_version, throw an error.
208        if let Some(row) = rows.next()? {
209            let key_id_version: u8 = row.get("key_id_version")?;
210            let key_attributes_version: u8 = row.get("key_attributes_version")?;
211            let error_message = format!(
212                "
213                Some records within the SQLiteKeyInfoManager are using an incompatible key_id_version or key_attributes_version.
214                Parsec Service SQLiteKeyInfoManager is using [key_id_version={}, key_attributes_version={}].
215                Database at [{}] contains mapping(s) using [key_id_version={}, key_attributes_version={}].
216                ",
217                CURRENT_KEY_ID_VERSION,
218                CURRENT_KEY_ATTRIBUTES_VERSION,
219                database_path
220                    .into_os_string()
221                    .into_string()
222                    .unwrap_or_else(|_| "DB_FILE_PATH".to_string()),
223                key_id_version,
224                key_attributes_version,
225            );
226            error!("{}", error_message);
227            return Err(Error::other(error_message).into());
228        }
229
230        // All checks have passed, load key mappings
231        let mut key_mapping_stmt = conn.prepare(
232            "
233            SELECT
234                *
235            FROM
236                key_mapping
237            ",
238        )?;
239        // Deserialize key mappings and store within local key_store HashMap.
240        let mut rows = key_mapping_stmt.query(params![])?;
241        while let Some(row) = rows.next()? {
242            let auth = match row.get("authenticator_id")? {
243                INTERNAL_AUTH_ID => Auth::Internal,
244                auth_type => Auth::Client(i64_to_auth_type(auth_type).map_err(|e| {
245                    format_error!("Failed to get AuthType from authenticator_id.", e);
246                    let error = Box::new(Error::new(ErrorKind::InvalidData, e));
247                    RusqliteError::FromSqlConversionFailure(64, Integer, error)
248                })?),
249            };
250            let key_identity = KeyIdentity::new(
251                ApplicationIdentity::new_with_auth(row.get("application_name")?, auth),
252                ProviderIdentity::new(row.get("provider_uuid")?, row.get("provider_name")?),
253                row.get("key_name")?,
254            );
255
256            let key_id: Vec<u8> = row.get("key_id")?;
257            let key_attributes_blob: Vec<u8> = row.get("key_attributes")?;
258            let key_attributes: Attributes = bincode::deserialize(&key_attributes_blob[..])
259                .map_err(|e| {
260                    format_error!("Error deserializing key attributes", e);
261                    RusqliteError::FromSqlConversionFailure(key_attributes_blob.len(), Blob, e)
262                })?;
263
264            let key_info = KeyInfo {
265                id: key_id,
266                attributes: key_attributes,
267            };
268
269            let _ = key_store.insert(key_identity, key_info);
270        }
271
272        if !crate::utils::GlobalConfig::log_error_details() {
273            info!(
274                "SQLiteKeyInfoManager - Found {} key info mapping records",
275                key_store.len()
276            );
277        }
278
279        let permissions = Permissions::from_mode(FILE_PERMISSION);
280        fs::set_permissions(database_path.clone(), permissions)?;
281
282        Ok(SQLiteKeyInfoManager {
283            key_store,
284            database_path,
285        })
286    }
287
288    /// Saves the KeyIdentity and KeyInfo to the database.
289    /// Inserts a new record to the database `key_mapping` table.
290    fn save_mapping(
291        &self,
292        key_identity: &KeyIdentity,
293        key_info: &KeyInfo,
294    ) -> rusqlite::Result<(), RusqliteError> {
295        let conn = Connection::open(&self.database_path)?;
296
297        // The key_info.id should already be serialized using bincode at this stage by the
298        // KIM client insert_key_info() function.
299        let key_id_blob = key_info.id.clone();
300        // TODO: Change this to (protobuf?) version once format has been decided.
301        // https://github.com/parallaxsecond/parsec/issues/424#issuecomment-883608164
302        let key_attributes_blob = bincode::serialize(&key_info.attributes).map_err(|e| {
303            format_error!("Error serializing key info", e);
304            RusqliteError::ToSqlConversionFailure(e)
305        })?;
306
307        // Insert the new key mapping, if a record does not exist.
308        // If one does exist, replace the existing record.
309        let _ = conn.execute(
310            "
311            REPLACE INTO
312                `key_mapping`
313                (`authenticator_id`, `application_name`, `provider_uuid`, `provider_name`, `key_name`, `key_id`, `key_id_version`, `key_attributes`, `key_attributes_version`)
314            VALUES
315                (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9);
316            ",
317            params![
318                key_identity.application().authenticator_id(),
319                key_identity.application().name(),
320                key_identity.provider().uuid(),
321                key_identity.provider().name(),
322                key_identity.key_name(),
323                key_id_blob,
324                // Key ID versioning will eventually need passing down from individual providers
325                // if the serialization structure of one of them changes.
326                CURRENT_KEY_ID_VERSION,
327                key_attributes_blob,
328                CURRENT_KEY_ATTRIBUTES_VERSION,
329            ],
330        )?;
331        Ok(())
332    }
333
334    /// Removes the mapping record.
335    /// Will do nothing if the mapping record does not exist.
336    fn delete_mapping(&self, key_identity: &KeyIdentity) -> rusqlite::Result<(), RusqliteError> {
337        let conn = Connection::open(&self.database_path)?;
338
339        let _ = conn.execute(
340            "
341            DELETE FROM
342                `key_mapping`
343            WHERE
344                `authenticator_id` = ?1
345                AND `application_name` = ?2
346                AND `key_name` = ?3
347            ",
348            params![
349                key_identity.application().authenticator_id(),
350                key_identity.application().name(),
351                key_identity.key_name(),
352            ],
353        )?;
354        Ok(())
355    }
356}
357
358impl ManageKeyInfo for SQLiteKeyInfoManager {
359    fn key_info_manager_type(&self) -> KeyInfoManagerType {
360        KeyInfoManagerType::SQLite
361    }
362
363    fn get(&self, key_identity: &KeyIdentity) -> Result<Option<&KeyInfo>, String> {
364        if let Some(key_info) = self.key_store.get(key_identity) {
365            Ok(Some(key_info))
366        } else {
367            Ok(None)
368        }
369    }
370
371    fn get_all(&self, provider_identity: ProviderIdentity) -> Result<Vec<KeyIdentity>, String> {
372        Ok(self
373            .key_store
374            .keys()
375            .filter(|key_identity| key_identity.belongs_to_provider(&provider_identity))
376            .cloned()
377            .collect())
378    }
379
380    fn insert(
381        &mut self,
382        key_identity: KeyIdentity,
383        key_info: KeyInfo,
384    ) -> Result<Option<KeyInfo>, String> {
385        match self.save_mapping(&key_identity, &key_info) {
386            Err(err) => Err(err.to_string()),
387            _ => Ok(self.key_store.insert(key_identity, key_info)),
388        }
389    }
390
391    fn remove(&mut self, key_identity: &KeyIdentity) -> Result<Option<KeyInfo>, String> {
392        match self.delete_mapping(key_identity) {
393            Err(err) => Err(err.to_string()),
394            _ => match self.key_store.remove(key_identity) {
395                Some(key_info) => Ok(Some(key_info)),
396                _ => Ok(None),
397            },
398        }
399    }
400
401    fn exists(&self, key_identity: &KeyIdentity) -> Result<bool, String> {
402        Ok(self.key_store.contains_key(key_identity))
403    }
404}
405
406/// SQLiteKeyInfoManager builder
407#[derive(Debug, Default)]
408pub struct SQLiteKeyInfoManagerBuilder {
409    database_path: Option<PathBuf>,
410}
411
412impl SQLiteKeyInfoManagerBuilder {
413    /// Create a new SQLiteKeyInfoManagerBuilder
414    pub fn new() -> SQLiteKeyInfoManagerBuilder {
415        SQLiteKeyInfoManagerBuilder {
416            database_path: None,
417        }
418    }
419
420    /// Add a mappings directory path to the builder
421    pub fn with_db_path(mut self, path: PathBuf) -> SQLiteKeyInfoManagerBuilder {
422        self.database_path = Some(path);
423        self
424    }
425
426    /// Build into a SQLiteKeyInfoManager
427    pub fn build(self) -> Result<SQLiteKeyInfoManager> {
428        SQLiteKeyInfoManager::new(
429            self.database_path
430                .unwrap_or_else(|| PathBuf::from(DEFAULT_DB_PATH)),
431        )
432    }
433}
434
435#[cfg(test)]
436mod test {
437    use super::super::{KeyIdentity, KeyInfo, ManageKeyInfo};
438    use super::SQLiteKeyInfoManager;
439    use crate::key_info_managers::sqlite_manager::FILE_PERMISSION;
440    use crate::key_info_managers::{ApplicationIdentity, ProviderIdentity};
441    use crate::providers::core::Provider as CoreProvider;
442    #[cfg(feature = "mbed-crypto-provider")]
443    use crate::providers::mbed_crypto::Provider as MbedCryptoProvider;
444    use parsec_interface::operations::psa_algorithm::{
445        Algorithm, AsymmetricSignature, Hash, SignHash,
446    };
447    use parsec_interface::operations::psa_key_attributes::{
448        Attributes, Lifetime, Policy, Type, UsageFlags,
449    };
450    use parsec_interface::requests::AuthType;
451    use rand::Rng;
452    use std::fs;
453    use std::fs::Permissions;
454    use std::os::unix::fs::PermissionsExt;
455    use std::path::PathBuf;
456
457    fn test_key_attributes() -> Attributes {
458        Attributes {
459            lifetime: Lifetime::Persistent,
460            key_type: Type::Derive,
461            bits: 1024,
462            policy: Policy {
463                usage_flags: {
464                    let mut usage_flags = UsageFlags::default();
465                    let _ = usage_flags.set_sign_hash();
466                    usage_flags
467                },
468                permitted_algorithms: Algorithm::AsymmetricSignature(
469                    AsymmetricSignature::RsaPkcs1v15Sign {
470                        hash_alg: SignHash::Specific(Hash::Sha256),
471                    },
472                ),
473            },
474        }
475    }
476
477    fn test_key_info() -> KeyInfo {
478        KeyInfo {
479            id: vec![0x11, 0x22, 0x33],
480            attributes: test_key_attributes(),
481        }
482    }
483
484    fn test_key_info_with_random_id() -> KeyInfo {
485        let mut rng = rand::thread_rng();
486        KeyInfo {
487            id: vec![rng.r#gen(), rng.r#gen(), rng.r#gen()],
488            attributes: test_key_attributes(),
489        }
490    }
491
492    #[test]
493    fn insert_get_key_info() {
494        let path = PathBuf::from(
495            env!("OUT_DIR").to_owned() + "/kim/sqlite/insert_get_key_info_mappings.sqlite3",
496        );
497        fs::remove_file(&path).unwrap_or_default();
498        let mut manager = SQLiteKeyInfoManager::new(path.clone()).unwrap();
499
500        let key_identity = new_key_identity("insert_get_key_info".to_string());
501        let key_info = test_key_info();
502
503        assert!(manager.get(&key_identity).unwrap().is_none());
504
505        assert!(
506            manager
507                .insert(key_identity.clone(), key_info.clone())
508                .unwrap()
509                .is_none()
510        );
511
512        let stored_key_info = manager
513            .get(&key_identity)
514            .unwrap()
515            .expect("Failed to get key info")
516            .clone();
517
518        assert_eq!(stored_key_info, key_info);
519        assert!(manager.remove(&key_identity).unwrap().is_some());
520        fs::remove_file(&path).unwrap();
521    }
522
523    #[test]
524    fn insert_remove_key() {
525        let path = PathBuf::from(
526            env!("OUT_DIR").to_owned() + "/kim/sqlite/insert_remove_key_mappings.sqlite3",
527        );
528        fs::remove_file(&path).unwrap_or_default();
529        let mut manager = SQLiteKeyInfoManager::new(path.clone()).unwrap();
530
531        let key_identity = new_key_identity("insert_remove_key".to_string());
532        let key_info = test_key_info();
533
534        let _ = manager.insert(key_identity.clone(), key_info).unwrap();
535
536        assert!(manager.remove(&key_identity).unwrap().is_some());
537        fs::remove_file(&path).unwrap();
538    }
539
540    #[test]
541    fn remove_unexisting_key() {
542        let path = PathBuf::from(
543            env!("OUT_DIR").to_owned() + "/kim/sqlite/remove_unexisting_key_mappings.sqlite3",
544        );
545        fs::remove_file(&path).unwrap_or_default();
546        let mut manager = SQLiteKeyInfoManager::new(path.clone()).unwrap();
547
548        let key_identity = new_key_identity("remove_unexisting_key".to_string());
549        assert_eq!(manager.remove(&key_identity).unwrap(), None);
550        fs::remove_file(&path).unwrap();
551    }
552
553    #[test]
554    fn exists() {
555        let path =
556            PathBuf::from(env!("OUT_DIR").to_owned() + "/kim/sqlite/exists_mappings.sqlite3");
557        fs::remove_file(&path).unwrap_or_default();
558        let mut manager = SQLiteKeyInfoManager::new(path.clone()).unwrap();
559
560        let key_identity = new_key_identity("exists".to_string());
561        let key_info = test_key_info();
562
563        assert!(!manager.exists(&key_identity).unwrap());
564
565        let _ = manager.insert(key_identity.clone(), key_info).unwrap();
566        assert!(manager.exists(&key_identity).unwrap());
567
568        let _ = manager.remove(&key_identity).unwrap();
569        assert!(!manager.exists(&key_identity).unwrap());
570        fs::remove_file(&path).unwrap();
571    }
572
573    #[test]
574    fn insert_overwrites() {
575        let path = PathBuf::from(
576            env!("OUT_DIR").to_owned() + "/kim/sqlite/insert_overwrites_mappings.sqlite3",
577        );
578        fs::remove_file(&path).unwrap_or_default();
579        let mut manager = SQLiteKeyInfoManager::new(path.clone()).unwrap();
580
581        let key_identity = new_key_identity("insert_overwrites".to_string());
582        let key_info_1 = test_key_info();
583        let key_info_2 = KeyInfo {
584            id: vec![0xaa, 0xbb, 0xcc],
585            attributes: test_key_attributes(),
586        };
587
588        let _ = manager.insert(key_identity.clone(), key_info_1).unwrap();
589        let _ = manager
590            .insert(key_identity.clone(), key_info_2.clone())
591            .unwrap();
592
593        let stored_key_info = manager
594            .get(&key_identity)
595            .unwrap()
596            .expect("Failed to get key info")
597            .clone();
598
599        assert_eq!(stored_key_info, key_info_2);
600        assert!(manager.remove(&key_identity).unwrap().is_some());
601        fs::remove_file(&path).unwrap();
602    }
603
604    #[test]
605    fn big_names_ascii() {
606        let path = PathBuf::from(
607            env!("OUT_DIR").to_owned() + "/kim/sqlite/big_names_ascii_mappings.sqlite3",
608        );
609        fs::remove_file(&path).unwrap_or_default();
610        let mut manager = SQLiteKeyInfoManager::new(path.clone()).unwrap();
611
612        let big_app_name_ascii = "  Lorem ipsum dolor sit amet, ei suas viris sea, deleniti repudiare te qui. Natum paulo decore ut nec, ne propriae offendit adipisci has. Eius clita legere mel at, ei vis minimum tincidunt.".to_string();
613        let big_key_name_ascii = "  Lorem ipsum dolor sit amet, ei suas viris sea, deleniti repudiare te qui. Natum paulo decore ut nec, ne propriae offendit adipisci has. Eius clita legere mel at, ei vis minimum tincidunt.".to_string();
614
615        let key_identity = KeyIdentity::new(
616            ApplicationIdentity::new(big_app_name_ascii, AuthType::NoAuth),
617            ProviderIdentity::new(
618                CoreProvider::PROVIDER_UUID.to_string(),
619                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
620            ),
621            big_key_name_ascii,
622        );
623        let key_info = test_key_info();
624
625        let _ = manager
626            .insert(key_identity.clone(), key_info.clone())
627            .unwrap();
628        assert_eq!(manager.remove(&key_identity).unwrap().unwrap(), key_info);
629        fs::remove_file(&path).unwrap();
630    }
631
632    #[test]
633    fn big_names_emoticons() {
634        let path = PathBuf::from(
635            env!("OUT_DIR").to_owned() + "/kim/sqlite/big_names_emoticons_mappings.sqlite3",
636        );
637        fs::remove_file(&path).unwrap_or_default();
638        let mut manager = SQLiteKeyInfoManager::new(path.clone()).unwrap();
639
640        let big_app_name_emoticons = "😀😁😂😃😄😅😆😇😈😉😊😋😌😍😎😏😐😑😒😓😔😕😖😗😘😙😚😛😜😝😞😟😠😡😢😣😤😥😦😧😨😩😪😫😬😭😮".to_string();
641        let big_key_name_emoticons = "😀😁😂😃😄😅😆😇😈😉😊😋😌😍😎😏😐😑😒😓😔😕😖😗😘😙😚😛😜😝😞😟😠😡😢😣😤😥😦😧😨😩😪😫😬😭😮".to_string();
642
643        let key_identity = KeyIdentity::new(
644            ApplicationIdentity::new(big_app_name_emoticons, AuthType::NoAuth),
645            ProviderIdentity::new(
646                CoreProvider::PROVIDER_UUID.to_string(),
647                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
648            ),
649            big_key_name_emoticons,
650        );
651        let key_info = test_key_info();
652
653        let _ = manager
654            .insert(key_identity.clone(), key_info.clone())
655            .unwrap();
656        assert_eq!(manager.remove(&key_identity).unwrap().unwrap(), key_info);
657        fs::remove_file(&path).unwrap();
658    }
659
660    /// Test that keys with identical identities (aside from authenticator id)
661    /// produce separate entries.
662    #[test]
663    fn namespace_authenticator_id() {
664        let path = PathBuf::from(
665            env!("OUT_DIR").to_owned() + "/kim/sqlite/namespace_authenticator_id.sqlite3",
666        );
667        fs::remove_file(&path).unwrap_or_default();
668        let mut manager = SQLiteKeyInfoManager::new(path.clone()).unwrap();
669
670        let key_name = "key_name".to_string();
671        let app_name = "the_application".to_string();
672
673        let key_identity_1 = KeyIdentity::new(
674            ApplicationIdentity::new(app_name.clone(), AuthType::NoAuth),
675            ProviderIdentity::new(
676                CoreProvider::PROVIDER_UUID.to_string(),
677                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
678            ),
679            key_name.clone(),
680        );
681        let key_identity_2 = KeyIdentity::new(
682            ApplicationIdentity::new(app_name, AuthType::Direct),
683            ProviderIdentity::new(
684                CoreProvider::PROVIDER_UUID.to_string(),
685                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
686            ),
687            key_name,
688        );
689
690        let key_info_1 = test_key_info_with_random_id();
691        let key_info_2 = test_key_info_with_random_id();
692
693        let _ = manager
694            .insert(key_identity_1.clone(), key_info_1.clone())
695            .unwrap();
696        let _ = manager
697            .insert(key_identity_2.clone(), key_info_2.clone())
698            .unwrap();
699
700        assert_eq!(
701            manager.remove(&key_identity_1).unwrap().unwrap(),
702            key_info_1
703        );
704        assert_eq!(
705            manager.remove(&key_identity_2).unwrap().unwrap(),
706            key_info_2
707        );
708
709        fs::remove_file(&path).unwrap();
710    }
711
712    /// Test that keys with identical identities (aside from application name)
713    /// produce separate entries.
714    #[test]
715    fn namespace_application_name() {
716        let path = PathBuf::from(
717            env!("OUT_DIR").to_owned() + "/kim/sqlite/namespace_application_name.sqlite3",
718        );
719        fs::remove_file(&path).unwrap_or_default();
720        let mut manager = SQLiteKeyInfoManager::new(path.clone()).unwrap();
721
722        let key_name = "key_name".to_string();
723        let app_name_1 = "application_1".to_string();
724        let app_name_2 = "application_2".to_string();
725
726        let key_identity_1 = KeyIdentity::new(
727            ApplicationIdentity::new(app_name_1, AuthType::NoAuth),
728            ProviderIdentity::new(
729                CoreProvider::PROVIDER_UUID.to_string(),
730                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
731            ),
732            key_name.clone(),
733        );
734        let key_identity_2 = KeyIdentity::new(
735            ApplicationIdentity::new(app_name_2, AuthType::NoAuth),
736            ProviderIdentity::new(
737                CoreProvider::PROVIDER_UUID.to_string(),
738                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
739            ),
740            key_name,
741        );
742
743        let key_info_1 = test_key_info_with_random_id();
744        let key_info_2 = test_key_info_with_random_id();
745
746        let _ = manager
747            .insert(key_identity_1.clone(), key_info_1.clone())
748            .unwrap();
749        let _ = manager
750            .insert(key_identity_2.clone(), key_info_2.clone())
751            .unwrap();
752
753        assert_eq!(
754            manager.remove(&key_identity_1).unwrap().unwrap(),
755            key_info_1
756        );
757        assert_eq!(
758            manager.remove(&key_identity_2).unwrap().unwrap(),
759            key_info_2
760        );
761
762        fs::remove_file(&path).unwrap();
763    }
764
765    /// Test that keys with identical identities (aside from key name)
766    /// produce separate entries.
767    #[test]
768    fn namespace_key_name() {
769        let path =
770            PathBuf::from(env!("OUT_DIR").to_owned() + "/kim/sqlite/namespace_key_name.sqlite3");
771        fs::remove_file(&path).unwrap_or_default();
772        let mut manager = SQLiteKeyInfoManager::new(path.clone()).unwrap();
773
774        let key_name_1 = "key_1".to_string();
775        let key_name_2 = "key_2".to_string();
776        let app_name = "the_application".to_string();
777
778        let key_identity_1 = KeyIdentity::new(
779            ApplicationIdentity::new(app_name.clone(), AuthType::NoAuth),
780            ProviderIdentity::new(
781                CoreProvider::PROVIDER_UUID.to_string(),
782                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
783            ),
784            key_name_1,
785        );
786        let key_identity_2 = KeyIdentity::new(
787            ApplicationIdentity::new(app_name, AuthType::NoAuth),
788            ProviderIdentity::new(
789                CoreProvider::PROVIDER_UUID.to_string(),
790                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
791            ),
792            key_name_2,
793        );
794
795        let key_info_1 = test_key_info_with_random_id();
796        let key_info_2 = test_key_info_with_random_id();
797
798        let _ = manager
799            .insert(key_identity_1.clone(), key_info_1.clone())
800            .unwrap();
801        let _ = manager
802            .insert(key_identity_2.clone(), key_info_2.clone())
803            .unwrap();
804
805        assert_eq!(
806            manager.remove(&key_identity_1).unwrap().unwrap(),
807            key_info_1
808        );
809        assert_eq!(
810            manager.remove(&key_identity_2).unwrap().unwrap(),
811            key_info_2
812        );
813
814        fs::remove_file(&path).unwrap();
815    }
816
817    /// Test that keys with identical identities (aside from provider name)
818    /// produce the same entry.
819    #[test]
820    fn namespace_provider_name() {
821        let path = PathBuf::from(
822            env!("OUT_DIR").to_owned() + "/kim/sqlite/namespace_provider_name.sqlite3",
823        );
824        fs::remove_file(&path).unwrap_or_default();
825        let mut manager = SQLiteKeyInfoManager::new(path.clone()).unwrap();
826
827        let key_name = "key_name".to_string();
828        let app_name = "the_application".to_string();
829
830        let key_identity_1 = KeyIdentity::new(
831            ApplicationIdentity::new(app_name.clone(), AuthType::NoAuth),
832            ProviderIdentity::new(
833                CoreProvider::PROVIDER_UUID.to_string(),
834                "One provider name".to_string(),
835            ),
836            key_name.clone(),
837        );
838        let key_identity_2 = KeyIdentity::new(
839            ApplicationIdentity::new(app_name, AuthType::NoAuth),
840            ProviderIdentity::new(
841                CoreProvider::PROVIDER_UUID.to_string(),
842                "Another provider name".to_string(),
843            ),
844            key_name,
845        );
846
847        let key_info = test_key_info_with_random_id();
848
849        let _ = manager.insert(key_identity_1, key_info.clone()).unwrap();
850
851        assert_eq!(manager.remove(&key_identity_2).unwrap().unwrap(), key_info);
852
853        fs::remove_file(&path).unwrap();
854    }
855
856    /// Test that keys with identical identities (aside from provider name)
857    /// produce the same entry.
858    #[test]
859    fn namespace_provider_uuid() {
860        let path = PathBuf::from(
861            env!("OUT_DIR").to_owned() + "/kim/sqlite/namespace_provider_uuid.sqlite3",
862        );
863        fs::remove_file(&path).unwrap_or_default();
864        let mut manager = SQLiteKeyInfoManager::new(path.clone()).unwrap();
865
866        let key_name = "key_name".to_string();
867        let app_name = "the_application".to_string();
868
869        let key_identity_1 = KeyIdentity::new(
870            ApplicationIdentity::new(app_name.clone(), AuthType::NoAuth),
871            ProviderIdentity::new(
872                "some-random-uuid".to_string(),
873                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
874            ),
875            key_name.clone(),
876        );
877        let key_identity_2 = KeyIdentity::new(
878            ApplicationIdentity::new(app_name, AuthType::NoAuth),
879            ProviderIdentity::new(
880                "some-random-uuid-that-isn't-the-same".to_string(),
881                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
882            ),
883            key_name,
884        );
885
886        let key_info = test_key_info_with_random_id();
887
888        let _ = manager.insert(key_identity_1, key_info.clone()).unwrap();
889
890        assert_eq!(manager.remove(&key_identity_2).unwrap().unwrap(), key_info);
891
892        fs::remove_file(&path).unwrap();
893    }
894
895    #[cfg(feature = "mbed-crypto-provider")]
896    #[test]
897    fn create_and_load() {
898        let path = PathBuf::from(
899            env!("OUT_DIR").to_owned() + "/kim/sqlite/create_and_load_mappings.sqlite3",
900        );
901        fs::remove_file(&path).unwrap_or_default();
902
903        let app_name1 = "😀 Application One 😀".to_string();
904        let key_name1 = "😀 Key One 😀".to_string();
905        let key_identity_1 = KeyIdentity::new(
906            ApplicationIdentity::new(app_name1, AuthType::NoAuth),
907            ProviderIdentity::new(
908                CoreProvider::PROVIDER_UUID.to_string(),
909                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
910            ),
911            key_name1,
912        );
913        let key_info1 = test_key_info();
914
915        let app_name2 = "😇 Application Two 😇".to_string();
916        let key_name2 = "😇 Key Two 😇".to_string();
917        let key_identity_2 = KeyIdentity::new(
918            ApplicationIdentity::new(app_name2, AuthType::NoAuth),
919            ProviderIdentity::new(
920                MbedCryptoProvider::PROVIDER_UUID.to_string(),
921                MbedCryptoProvider::DEFAULT_PROVIDER_NAME.to_string(),
922            ),
923            key_name2,
924        );
925        let key_info2 = KeyInfo {
926            id: vec![0x12, 0x22, 0x32],
927            attributes: test_key_attributes(),
928        };
929
930        let app_name3 = "😈 Application Three 😈".to_string();
931        let key_name3 = "😈 Key Three 😈".to_string();
932        let key_identity_3 = KeyIdentity::new(
933            ApplicationIdentity::new(app_name3, AuthType::NoAuth),
934            ProviderIdentity::new(
935                CoreProvider::PROVIDER_UUID.to_string(),
936                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
937            ),
938            key_name3,
939        );
940        let key_info3 = KeyInfo {
941            id: vec![0x13, 0x23, 0x33],
942            attributes: test_key_attributes(),
943        };
944        {
945            let mut manager = SQLiteKeyInfoManager::new(path.clone()).unwrap();
946
947            let _ = manager
948                .insert(key_identity_1.clone(), key_info1.clone())
949                .unwrap();
950            let _ = manager
951                .insert(key_identity_2.clone(), key_info2.clone())
952                .unwrap();
953            let _ = manager
954                .insert(key_identity_3.clone(), key_info3.clone())
955                .unwrap();
956        }
957        // The local hashmap is dropped when leaving the inner scope.
958        {
959            let mut manager = SQLiteKeyInfoManager::new(path.clone()).unwrap();
960
961            assert_eq!(manager.remove(&key_identity_1).unwrap().unwrap(), key_info1);
962            assert_eq!(manager.remove(&key_identity_2).unwrap().unwrap(), key_info2);
963            assert_eq!(manager.remove(&key_identity_3).unwrap().unwrap(), key_info3);
964        }
965
966        fs::remove_file(&path).unwrap();
967    }
968
969    #[cfg(feature = "mbed-crypto-provider")]
970    #[test]
971    fn create_and_load_internal_keys() {
972        let path = PathBuf::from(
973            env!("OUT_DIR").to_owned()
974                + "/kim/sqlite/create_and_load_mappings_internal_keys.sqlite3",
975        );
976        fs::remove_file(&path).unwrap_or_default();
977
978        let key_name1 = "😀 Key One 😀".to_string();
979        let key_identity_1 = KeyIdentity::new(
980            ApplicationIdentity::new_internal(),
981            ProviderIdentity::new(
982                CoreProvider::PROVIDER_UUID.to_string(),
983                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
984            ),
985            key_name1,
986        );
987        let key_info1 = test_key_info();
988
989        let key_name2 = "😇 Key Two 😇".to_string();
990        let key_identity_2 = KeyIdentity::new(
991            ApplicationIdentity::new_internal(),
992            ProviderIdentity::new(
993                MbedCryptoProvider::PROVIDER_UUID.to_string(),
994                MbedCryptoProvider::DEFAULT_PROVIDER_NAME.to_string(),
995            ),
996            key_name2,
997        );
998        let key_info2 = KeyInfo {
999            id: vec![0x12, 0x22, 0x32],
1000            attributes: test_key_attributes(),
1001        };
1002
1003        {
1004            let mut manager = SQLiteKeyInfoManager::new(path.clone()).unwrap();
1005
1006            let _ = manager
1007                .insert(key_identity_1.clone(), key_info1.clone())
1008                .unwrap();
1009            let _ = manager
1010                .insert(key_identity_2.clone(), key_info2.clone())
1011                .unwrap();
1012        }
1013        // The local hashmap is dropped when leaving the inner scope.
1014        {
1015            let mut manager = SQLiteKeyInfoManager::new(path.clone()).unwrap();
1016
1017            assert_eq!(
1018                manager
1019                    .get_all(key_identity_1.provider.clone())
1020                    .unwrap()
1021                    .len(),
1022                1
1023            );
1024            assert_eq!(
1025                manager
1026                    .get_all(key_identity_2.provider.clone())
1027                    .unwrap()
1028                    .len(),
1029                1
1030            );
1031
1032            // get() should return the key info of the internal key!
1033            assert_eq!(&key_info1, manager.get(&key_identity_1).unwrap().unwrap());
1034
1035            // get() should not work for the same key if it is marked as External!
1036            let mut key_identity3 = key_identity_2.clone();
1037            key_identity3.application = ApplicationIdentity::new(
1038                key_identity_2.application().name().to_string(),
1039                AuthType::UnixPeerCredentials,
1040            );
1041            assert_eq!(None, manager.get(&key_identity3).unwrap());
1042
1043            assert_eq!(manager.remove(&key_identity_1).unwrap().unwrap(), key_info1);
1044            assert_eq!(manager.remove(&key_identity_2).unwrap().unwrap(), key_info2);
1045            assert_eq!(
1046                manager
1047                    .get_all(key_identity_1.provider.clone())
1048                    .unwrap()
1049                    .len(),
1050                0
1051            );
1052        }
1053
1054        fs::remove_file(&path).unwrap();
1055    }
1056
1057    fn new_key_identity(key_name: String) -> KeyIdentity {
1058        KeyIdentity::new(
1059            ApplicationIdentity::new("Testing Application 😎".to_string(), AuthType::NoAuth),
1060            ProviderIdentity::new(
1061                CoreProvider::PROVIDER_UUID.to_string(),
1062                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
1063            ),
1064            key_name,
1065        )
1066    }
1067
1068    #[test]
1069    fn check_permissions() {
1070        let path =
1071            PathBuf::from(env!("OUT_DIR").to_owned() + "/kim/sqlite/check_permissions.sqlite3");
1072        fs::remove_file(&path).unwrap_or_default();
1073
1074        let app_name1 = "App1".to_string();
1075        let key_name1 = "Key1".to_string();
1076        let key_identity_1 = KeyIdentity::new(
1077            ApplicationIdentity::new(app_name1, AuthType::NoAuth),
1078            ProviderIdentity::new(
1079                CoreProvider::PROVIDER_UUID.to_string(),
1080                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
1081            ),
1082            key_name1,
1083        );
1084        let key_info1 = test_key_info();
1085
1086        let mut manager = SQLiteKeyInfoManager::new(path.clone()).unwrap();
1087
1088        let _ = manager.insert(key_identity_1.clone(), key_info1).unwrap();
1089
1090        let permissions = Permissions::from_mode(FILE_PERMISSION);
1091        assert_eq!(
1092            fs::metadata(&path).unwrap().permissions().mode() & permissions.mode(),
1093            permissions.mode()
1094        );
1095
1096        let _ = manager.remove(&key_identity_1).unwrap().unwrap();
1097
1098        fs::remove_file(&path).unwrap();
1099    }
1100}