parsec_service/key_info_managers/on_disk_manager/
mod.rs

1// Copyright 2019 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3//! A key info manager storing key triple to key info mapping on files on disk
4//!
5//! The path where the mappings should be stored is configurable. Because of possible data races,
6//! there should not be two instances of this manager pointing to the same mapping folder at a time.
7//! Methods modifying the mapping will also block until the modifications are done on disk to be
8//! ensured to not lose mappings.
9//! Because application and key names can contain any UTF-8 characters, those strings are converted
10//! to base64 strings so that they can be used as filenames. Because of filenames limitations, some
11//! very long UTF-8 names might not be able to be represented as a filename and will fail. For
12//! example, for operating systems having a limit of 255 characters for filenames (Unix systems),
13//! names will be limited to 188 bytes of UTF-8 characters.
14//! For security reasons, only the PARSEC service should have the ability to modify these files.
15use crate::authenticators::{Application, ApplicationIdentity, Auth, INTERNAL_APP_NAME};
16use crate::utils::config::KeyInfoManagerType;
17
18use super::{KeyIdentity, KeyInfo, ManageKeyInfo, ProviderIdentity};
19use crate::providers::core::Provider as CoreProvider;
20#[cfg(feature = "cryptoauthlib-provider")]
21use crate::providers::cryptoauthlib::Provider as CryptoAuthLibProvider;
22#[cfg(feature = "mbed-crypto-provider")]
23use crate::providers::mbed_crypto::Provider as MbedCryptoProvider;
24#[cfg(feature = "pkcs11-provider")]
25use crate::providers::pkcs11::Provider as Pkcs11Provider;
26#[cfg(feature = "tpm-provider")]
27use crate::providers::tpm::Provider as TpmProvider;
28#[cfg(feature = "trusted-service-provider")]
29use crate::providers::trusted_service::Provider as TrustedServiceProvider;
30use anyhow::{Context, Result};
31use base64::Engine;
32use log::{error, info, warn};
33use parsec_interface::requests::{AuthType, ProviderId};
34use std::collections::HashMap;
35use std::convert::TryFrom;
36use std::ffi::OsStr;
37use std::fs::Permissions;
38use std::fs::{DirEntry, File};
39use std::io::{Error, ErrorKind, Read, Write};
40use std::ops::Deref;
41use std::os::unix::fs::PermissionsExt;
42use std::path::{Path, PathBuf};
43use std::{fmt, fs};
44
45/// Default path where the mapping files will be stored on disk
46pub const DEFAULT_MAPPINGS_PATH: &str = "/var/lib/parsec/mappings";
47
48/// Directory in which the internal keys file will be held
49const INTERNAL_KEYS_PARSEC_DIR: &str = INTERNAL_APP_NAME;
50
51///Permissions for all directories under database directory
52///Should only be visible to parsec user
53pub const DIR_PERMISSION: u32 = 0o700;
54
55///Permissions for all files under database directory
56///Should only be visible to parsec user
57pub const FILE_PERMISSION: u32 = 0o600;
58
59const CORE_PROVIDER: &str = "core";
60const PKCS11_PROVIDER: &str = "pkcs11";
61const MBEDCRYPTO_PROVIDER: &str = "mbedcrypto";
62const TPM_PROVIDER: &str = "tpm";
63const TRUSTEDS_PROVIDER: &str = "trusted-service";
64const CRYPTOAUTH_PROVIDER: &str = "cryptoauthlib";
65
66/// Provider names for internal storage.
67const PROVIDER_NAMES: [&str; 6] = [
68    CORE_PROVIDER,
69    PKCS11_PROVIDER,
70    MBEDCRYPTO_PROVIDER,
71    TPM_PROVIDER,
72    TRUSTEDS_PROVIDER,
73    CRYPTOAUTH_PROVIDER,
74];
75
76/// String wrapper for app names
77#[deprecated(since = "0.9.0", note = "ApplicationIdentity should be used instead.")]
78#[derive(Debug, Clone, Eq, PartialEq, Hash)]
79pub struct ApplicationName {
80    name: String,
81}
82
83#[allow(deprecated)]
84impl Deref for ApplicationName {
85    type Target = String;
86
87    fn deref(&self) -> &Self::Target {
88        &self.name
89    }
90}
91
92#[allow(deprecated)]
93#[deprecated(since = "0.9.0", note = "ApplicationIdentity should be used instead.")]
94impl ApplicationName {
95    /// Create ApplicationName from name string only
96    pub fn from_name(name: String) -> ApplicationName {
97        ApplicationName { name }
98    }
99}
100
101#[allow(deprecated)]
102impl fmt::Display for ApplicationName {
103    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104        write!(f, "{}", self.name)
105    }
106}
107
108#[allow(deprecated)]
109impl From<Application> for ApplicationName {
110    fn from(app: Application) -> Self {
111        ApplicationName::from_name(app.identity().name().clone())
112    }
113}
114
115/// Should only be used internally to map KeyTriple to the new KeyIdentity
116/// for the on_disk_manager KeyInfoManager.
117/// Structure corresponds to a unique identifier of the key.
118/// It is used internally by the Key ID manager to refer to a key.
119#[deprecated(since = "0.9.0", note = "KeyIdentity should be used instead.")]
120#[allow(deprecated)]
121#[derive(Debug, Clone, PartialEq, Eq, Hash)]
122pub struct KeyTriple {
123    app_name: ApplicationName,
124    provider_id: ProviderId,
125    key_name: String,
126}
127
128#[allow(deprecated)]
129#[deprecated(since = "0.9.0", note = "KeyIdentity should be used instead.")]
130impl KeyTriple {
131    /// Creates a new instance of KeyTriple.
132    pub fn new(app_name: ApplicationName, provider_id: ProviderId, key_name: String) -> KeyTriple {
133        KeyTriple {
134            app_name,
135            provider_id,
136            key_name,
137        }
138    }
139
140    /// Checks if this key belongs to a specific provider.
141    pub fn belongs_to_provider(&self, provider_id: ProviderId) -> bool {
142        self.provider_id == provider_id
143    }
144    /// Get the provider id
145    pub fn provider_id(&self) -> &ProviderId {
146        &self.provider_id
147    }
148
149    /// Get the key name
150    pub fn key_name(&self) -> &str {
151        &self.key_name
152    }
153
154    /// Get the app name
155    pub fn app_name(&self) -> &ApplicationName {
156        &self.app_name
157    }
158}
159
160#[allow(deprecated)]
161impl fmt::Display for KeyTriple {
162    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
163        write!(
164            f,
165            "KeyTriple: app_name=\"{}\" provider_id={} key_name=\"{}\"",
166            self.app_name, self.provider_id, self.key_name
167        )
168    }
169}
170
171#[allow(deprecated)]
172impl TryFrom<KeyIdentity> for KeyTriple {
173    type Error = String;
174
175    fn try_from(key_identity: KeyIdentity) -> std::result::Result<Self, Self::Error> {
176        let provider_id = match key_identity.provider.uuid().as_str() {
177            CoreProvider::PROVIDER_UUID => Ok(ProviderId::Core),
178            #[cfg(feature = "cryptoauthlib-provider")]
179            CryptoAuthLibProvider::PROVIDER_UUID => Ok(ProviderId::CryptoAuthLib),
180            #[cfg(feature = "mbed-crypto-provider")]
181            MbedCryptoProvider::PROVIDER_UUID => Ok(ProviderId::MbedCrypto),
182            #[cfg(feature = "pkcs11-provider")]
183            Pkcs11Provider::PROVIDER_UUID => Ok(ProviderId::Pkcs11),
184            #[cfg(feature = "tpm-provider")]
185            TpmProvider::PROVIDER_UUID => Ok(ProviderId::Tpm),
186            #[cfg(feature = "trusted-service-provider")]
187            TrustedServiceProvider::PROVIDER_UUID => Ok(ProviderId::TrustedService),
188            _ => Err(format!(
189                "Cannot convert from KeyIdentity to KeyTriple.
190                Provider \"{}\" is not recognised.
191                Could be it does not exist, or Parsec was not compiled with the required provider feature flags.",
192                key_identity.provider().uuid()
193            )),
194        }?;
195
196        Ok(KeyTriple {
197            provider_id,
198            app_name: ApplicationName::from_name(key_identity.application().name().to_string()),
199            key_name: key_identity.key_name,
200        })
201    }
202}
203
204#[allow(deprecated)]
205impl TryFrom<(KeyTriple, ProviderIdentity, Auth)> for KeyIdentity {
206    type Error = String;
207
208    fn try_from(
209        (key_triple, provider_identity, auth): (KeyTriple, ProviderIdentity, Auth),
210    ) -> std::result::Result<Self, Self::Error> {
211        // Result types required by clippy as Err result has the possibility of not being compiled.
212        let provider_uuid = match key_triple.provider_id {
213            ProviderId::Core => Ok::<String, Self::Error>(
214                CoreProvider::PROVIDER_UUID.to_string(),
215            ),
216            #[cfg(feature = "cryptoauthlib-provider")]
217            ProviderId::CryptoAuthLib => Ok::<String, Self::Error>(CryptoAuthLibProvider::PROVIDER_UUID.to_string()),
218            #[cfg(feature = "mbed-crypto-provider")]
219            ProviderId::MbedCrypto => Ok::<String, Self::Error>(MbedCryptoProvider::PROVIDER_UUID.to_string()),
220            #[cfg(feature = "pkcs11-provider")]
221            ProviderId::Pkcs11 => Ok::<String, Self::Error>(Pkcs11Provider::PROVIDER_UUID.to_string()),
222            #[cfg(feature = "tpm-provider")]
223            ProviderId::Tpm => Ok::<String, Self::Error>(TpmProvider::PROVIDER_UUID.to_string()),
224            #[cfg(feature = "trusted-service-provider")]
225            ProviderId::TrustedService => Ok::<String, Self::Error>(TrustedServiceProvider::PROVIDER_UUID.to_string()),
226            #[cfg(not(all(
227                feature = "cryptoauthlib-provider",
228                feature = "mbed-crypto-provider",
229                feature = "pkcs11-provider",
230                feature = "tpm-provider",
231                feature = "trusted-service-provider",
232            )))]
233            _ => Err(format!("Cannot convert from KeyTriple to KeyIdentity.\nProvider \"{}\" is not recognised.\nCould be it does not exist, or Parsec was not compiled with the required provider feature flags.", key_triple.provider_id)),
234        }?;
235
236        let app_identity = match auth {
237            Auth::Internal => ApplicationIdentity::new_internal(),
238            Auth::Client(auth_type) => {
239                ApplicationIdentity::new(key_triple.app_name().to_string(), auth_type)
240            }
241        };
242        Ok(KeyIdentity {
243            provider: ProviderIdentity::new(provider_uuid, provider_identity.name().clone()),
244            application: app_identity,
245            key_name: key_triple.key_name,
246        })
247    }
248}
249
250/// A key info manager storing key triple to key info mapping on files on disk
251#[derive(Debug)]
252pub struct OnDiskKeyInfoManager {
253    /// Internal mapping, used for non-modifying operations.
254    #[allow(deprecated)]
255    key_store: HashMap<KeyTriple, KeyInfo>,
256    /// Internal mapping with Internal Keys, used for non-modifying operations.
257    #[allow(deprecated)]
258    key_store_internal: HashMap<KeyTriple, KeyInfo>,
259    /// Folder where all the key triple to key info mappings are saved. This folder will be created
260    /// if it does already exist.
261    mappings_dir_path: PathBuf,
262    /// The AuthType currently being used by Parsec and hence used to namespace the OnDiskKeyInfoManager.
263    auth_type: AuthType,
264}
265
266/// Encodes a KeyTriple's data into base64 strings that can be used as filenames.
267/// The ProviderId will not be converted as a base64 as it can always be represented as a String
268/// being a number from 0 and 255.
269#[allow(deprecated)]
270fn key_triple_to_base64_filenames(key_triple: &KeyTriple) -> (String, String, String) {
271    (
272        base64::engine::general_purpose::URL_SAFE.encode(key_triple.app_name.as_bytes()),
273        (key_triple.provider_id as u8).to_string(),
274        base64::engine::general_purpose::URL_SAFE.encode(key_triple.key_name.as_bytes()),
275    )
276}
277
278/// Decodes base64 bytes to its original String value.
279///
280/// # Errors
281///
282/// Returns an error as a string if either the decoding or the bytes conversion to UTF-8 failed.
283fn base64_data_to_string(base64_bytes: &[u8]) -> Result<String, String> {
284    match base64::engine::general_purpose::URL_SAFE.decode(base64_bytes) {
285        Ok(decode_bytes) => match String::from_utf8(decode_bytes) {
286            Ok(string) => Ok(string),
287            Err(error) => Err(error.to_string()),
288        },
289        Err(error) => Err(error.to_string()),
290    }
291}
292
293/// Decodes key triple's data to the original path.
294/// The Provider ID data is not converted as base64.
295///
296/// # Errors
297///
298/// Returns an error as a string if either the decoding or the bytes conversion to UTF-8 failed.
299#[allow(deprecated)]
300fn base64_data_triple_to_key_triple(
301    app_name: &[u8],
302    provider_id: ProviderId,
303    key_name: &[u8],
304) -> Result<KeyTriple, String> {
305    let app_name = ApplicationName::from_name(base64_data_to_string(app_name)?);
306    let key_name = base64_data_to_string(key_name)?;
307
308    Ok(KeyTriple {
309        app_name,
310        provider_id,
311        key_name,
312    })
313}
314
315/// Converts an OsStr reference to a byte array.
316///
317/// # Errors
318///
319/// Returns a custom std::io error if the conversion failed.
320fn os_str_to_u8_ref(os_str: &OsStr) -> std::io::Result<&[u8]> {
321    match os_str.to_str() {
322        Some(str) => Ok(str.as_bytes()),
323        None => Err(Error::new(
324            ErrorKind::Other,
325            "Conversion from PathBuf to String failed.",
326        )),
327    }
328}
329
330/// Converts an OsStr reference to a ProviderId value.
331///
332/// # Errors
333///
334/// Returns a custom std::io error if the conversion failed.
335fn os_str_to_provider_id(os_str: &OsStr) -> std::io::Result<ProviderId> {
336    match os_str.to_str() {
337        Some(str) => match str.parse::<u8>() {
338            Ok(provider_id_u8) => match ProviderId::try_from(provider_id_u8) {
339                Ok(provider_id) => Ok(provider_id),
340                Err(response_status) => {
341                    Err(Error::new(ErrorKind::Other, response_status.to_string()))
342                }
343            },
344            Err(_) => Err(Error::new(
345                ErrorKind::Other,
346                "Failed to convert Provider directory name to an u8 number.",
347            )),
348        },
349        None => Err(Error::new(
350            ErrorKind::Other,
351            "Conversion from PathBuf to String failed.",
352        )),
353    }
354}
355
356/// Splits a filename into provider_name + key name (for internal keys only)
357///
358/// # Errors
359///
360/// Returns None if no provider_name was detected
361fn split_provider_key_filename(filename: &str) -> Option<(String, String)> {
362    for name in PROVIDER_NAMES {
363        if filename.starts_with(name) {
364            return Some((name.to_string(), filename.replacen(name, "", 1)));
365        }
366    }
367    None
368}
369
370fn provider_id_to_str(provid: ProviderId) -> &'static str {
371    match provid {
372        ProviderId::Core => CORE_PROVIDER,
373        ProviderId::Pkcs11 => PKCS11_PROVIDER,
374        ProviderId::MbedCrypto => MBEDCRYPTO_PROVIDER,
375        ProviderId::Tpm => TPM_PROVIDER,
376        ProviderId::TrustedService => TRUSTEDS_PROVIDER,
377        ProviderId::CryptoAuthLib => CRYPTOAUTH_PROVIDER,
378    }
379}
380
381fn str_to_provider_id(provid: &str) -> Option<ProviderId> {
382    match provid {
383        CORE_PROVIDER => Some(ProviderId::Core),
384        PKCS11_PROVIDER => Some(ProviderId::Pkcs11),
385        MBEDCRYPTO_PROVIDER => Some(ProviderId::MbedCrypto),
386        TPM_PROVIDER => Some(ProviderId::Tpm),
387        TRUSTEDS_PROVIDER => Some(ProviderId::TrustedService),
388        CRYPTOAUTH_PROVIDER => Some(ProviderId::CryptoAuthLib),
389        _ => None,
390    }
391}
392
393fn prov_and_key_to_str(provider_id: ProviderId, key_name: &str) -> String {
394    let mut p_name = provider_id_to_str(provider_id).to_string();
395    p_name.push_str(key_name);
396    p_name
397}
398
399/// Lists all the directory paths in the given directory path.
400fn list_dirs(path: &Path) -> std::io::Result<Vec<PathBuf>> {
401    // read_dir returning an iterator over Result<DirEntry>, there is first a conversion to a path
402    // and then a check if the path is a directory or not.
403    let dir_entries: std::io::Result<Vec<DirEntry>> = path.read_dir()?.collect();
404    Ok(dir_entries?
405        .iter()
406        .map(|dir_entry| dir_entry.path())
407        .filter(|dir_path| dir_path.is_dir())
408        .collect())
409}
410
411/// Lists all the file paths in the given directory path.
412fn list_files(path: &Path) -> std::io::Result<Vec<PathBuf>> {
413    let dir_entries: std::io::Result<Vec<DirEntry>> = path.read_dir()?.collect();
414    Ok(dir_entries?
415        .iter()
416        .map(|dir_entry| dir_entry.path())
417        .filter(|dir_path| dir_path.is_file())
418        .collect())
419}
420
421/// Filesystem-based `KeyInfoManager`
422///
423/// The `OnDiskKeyInfoManager` relies on access control mechanisms provided by the OS for
424/// the filesystem to ensure security of the mappings.
425#[allow(deprecated)]
426impl OnDiskKeyInfoManager {
427    /// Creates an instance of the on-disk manager from the mapping files. This function will
428    /// create the mappings directory if it does not already exist.
429    /// The mappings folder is composed of three levels: two levels of directory and one level
430    /// of files. The key triple to key info mappings are represented on disk as the following:
431    ///
432    /// mappings_dir_path/
433    /// |---app1/
434    /// |   |---provider1/
435    /// |   |   |---key1
436    /// |   |   |---key2
437    /// |   |   |   ...
438    /// |   |   |---keyP
439    /// |   |---provider2/
440    /// |   |   ...
441    /// |   |---providerM/
442    /// |---app2/
443    /// |   ...
444    /// |---appN/
445    /// |---parsec/
446    /// |   |---provider1-INTERNAL1
447    /// |   |---provider2-INTERNAL2
448    ///
449    /// where the path of a key name from the mappings directory is the key triple (application,
450    /// provider, key) and the data inside the key name file is the key info serialised in binary
451    /// format.
452    /// The INTERNAL files under the parsec directory stores the information of those keys that are
453    /// internally generated. The file name of the INTERNAL files has as its first component the
454    /// provider name of the provider that generated the internal key.
455    /// Each mapping is contained in its own file to prevent the modification of one mapping
456    /// impacting the other ones.
457    ///
458    /// # Errors
459    ///
460    /// Returns an std::io error if the function failed reading the mapping files.
461    fn new(mappings_dir_path: PathBuf, auth_type: AuthType) -> Result<OnDiskKeyInfoManager> {
462        let mut key_store = HashMap::new();
463        let mut key_store_internal = HashMap::new();
464
465        // Will ignore if the mappings directory already exists.
466        fs::create_dir_all(&mappings_dir_path).with_context(|| {
467            format!(
468                "Failed to create Key Info Mappings directory at {:?}",
469                mappings_dir_path
470            )
471        })?;
472
473        // The INTERNAL files are the only files that on the second level in the directory structure
474        // and store the information of internal keys
475        let parsec_dir = mappings_dir_path.join(INTERNAL_KEYS_PARSEC_DIR);
476        fs::create_dir_all(&parsec_dir)
477            .with_context(|| format!("Failed to create Parsec directory at {:?}", parsec_dir))?;
478        fs::set_permissions(&parsec_dir, Permissions::from_mode(DIR_PERMISSION))?;
479
480        for internal_key_path in list_files(&parsec_dir)?.iter() {
481            let key_name_internal = base64_data_to_string(os_str_to_u8_ref(
482                internal_key_path
483                    .file_name()
484                    .expect("The key name directory path should contain a final component."),
485            )?)
486            .map_err(|e| Error::new(ErrorKind::Other, e))?;
487
488            // If provider name is not recognized, ignore the key.
489            let keytriple = match split_provider_key_filename(&key_name_internal) {
490                None => continue,
491                Some((prov, key_name)) => KeyTriple::new(
492                    ApplicationName::from_name(INTERNAL_KEYS_PARSEC_DIR.to_string()),
493                    // Provider name has been recognized, so if None is returned here something has
494                    // gone terribly wrong.
495                    str_to_provider_id(&prov).unwrap(),
496                    key_name,
497                ),
498            };
499
500            let mut key_info = Vec::new();
501            let mut key_info_file = File::open(internal_key_path).with_context(|| {
502                format!(
503                    "Failed to open Key Info Mappings file at {:?}",
504                    internal_key_path
505                )
506            })?;
507            let _ = key_info_file.read_to_end(&mut key_info)?;
508            let key_info = bincode::deserialize(&key_info[..]).map_err(|e| {
509                format_error!("Error deserializing key info", e);
510                Error::new(ErrorKind::Other, "error deserializing key info")
511            })?;
512            let _ = key_store_internal.insert(keytriple, key_info);
513        }
514
515        for app_name_dir_path in list_dirs(&mappings_dir_path)?.iter() {
516            for provider_dir_path in list_dirs(app_name_dir_path)?.iter() {
517                for key_name_file_path in list_files(provider_dir_path)?.iter() {
518                    let mut key_info = Vec::new();
519                    let mut key_info_file = File::open(key_name_file_path).with_context(|| {
520                        format!(
521                            "Failed to open Key Info Mappings file at {:?}",
522                            key_name_file_path
523                        )
524                    })?;
525                    let _ = key_info_file.read_to_end(&mut key_info)?;
526                    let key_info = bincode::deserialize(&key_info[..]).map_err(|e| {
527                        format_error!("Error deserializing key info", e);
528                        Error::new(ErrorKind::Other, "error deserializing key info")
529                    })?;
530                    match base64_data_triple_to_key_triple(
531                        os_str_to_u8_ref(app_name_dir_path.file_name().expect(
532                            "The application name directory path should contain a final component.",
533                        ))?,
534                        os_str_to_provider_id(provider_dir_path.file_name().expect(
535                            "The provider directory path should contain a final component.",
536                        ))?,
537                        os_str_to_u8_ref(key_name_file_path.file_name().expect(
538                            "The key name directory path should contain a final component.",
539                        ))?,
540                    ) {
541                        Ok(key_triple) => {
542                            if crate::utils::GlobalConfig::log_error_details() {
543                                warn!(
544                                    "Inserting Key Triple ({}) mapping read from disk.",
545                                    key_triple.clone()
546                                );
547                            }
548                            let _ = key_store.insert(key_triple, key_info);
549                        }
550                        Err(string) => {
551                            format_error!(
552                                "Failed to convert the mapping path found to an UTF-8 string",
553                                string
554                            );
555                            return Err(
556                                Error::new(ErrorKind::Other, "error parsing mapping path").into()
557                            );
558                        }
559                    }
560                }
561            }
562        }
563
564        if !crate::utils::GlobalConfig::log_error_details() {
565            info!("Found {} mapping files", key_store.len());
566        }
567
568        let permissions = Permissions::from_mode(DIR_PERMISSION);
569        fs::set_permissions(&mappings_dir_path, permissions)?;
570
571        Ok(OnDiskKeyInfoManager {
572            key_store,
573            key_store_internal,
574            mappings_dir_path,
575            auth_type,
576        })
577    }
578
579    /// Saves the key triple to key info mapping in its own file.
580    /// The filename will be `mappings/[APP_NAME]/[PROVIDER_NAME]/[KEY_NAME]` under the same path as the
581    /// on-disk manager. It will contain the Key info data.
582    fn save_mapping(
583        &self,
584        key_triple: &KeyTriple,
585        key_info: &KeyInfo,
586        auth: &Auth,
587    ) -> std::io::Result<()> {
588        if crate::utils::GlobalConfig::log_error_details() {
589            warn!(
590                "Saving Key Triple ({}) mapping to disk.",
591                key_triple.clone()
592            );
593        }
594        let (app_name, prov, key_name) = key_triple_to_base64_filenames(key_triple);
595        let key_name_file_path = match auth {
596            Auth::Internal => {
597                let prov_key_name =
598                    prov_and_key_to_str(key_triple.provider_id, &key_triple.key_name);
599                let prov_key_name =
600                    base64::engine::general_purpose::URL_SAFE.encode(prov_key_name.as_bytes());
601                // INTERNAL_KEYS_PARSEC_DIR has already been created with the necessary permissions
602                self.mappings_dir_path
603                    .join(INTERNAL_KEYS_PARSEC_DIR)
604                    .join(prov_key_name)
605            }
606            Auth::Client(_) => {
607                // Create the directories with base64 names.
608                let app_dir_path = self.mappings_dir_path.join(app_name);
609                let provider_dir_path = app_dir_path.join(prov);
610                let key_name_file_path = provider_dir_path.join(key_name);
611                // Will ignore if they already exist.
612                fs::create_dir_all(&provider_dir_path).map_err(|e| {
613                    format_error!(
614                        format!(
615                            "Failed to create provider directory as {:?}",
616                            &provider_dir_path
617                        ),
618                        e
619                    );
620                    e
621                })?;
622                let dir_permissions = Permissions::from_mode(DIR_PERMISSION);
623                fs::set_permissions(&app_dir_path, dir_permissions.clone())?;
624                fs::set_permissions(&provider_dir_path, dir_permissions)?;
625
626                if key_name_file_path.exists() {
627                    fs::remove_file(&key_name_file_path)?;
628                }
629                key_name_file_path
630            }
631        };
632
633        // Create the mapping file with the corresponding permissions and write the key information
634        let mut mapping_file = File::create(&key_name_file_path).map_err(|e| {
635            error!(
636                "Failed to create Key Info Mapping file at {:?}",
637                key_name_file_path
638            );
639            e
640        })?;
641
642        let file_permissions = Permissions::from_mode(FILE_PERMISSION);
643        fs::set_permissions(&key_name_file_path, file_permissions)?;
644        mapping_file.write_all(&bincode::serialize(key_info).map_err(|e| {
645            format_error!("Error serializing key info", e);
646            Error::new(ErrorKind::Other, "error serializing key info")
647        })?)
648    }
649
650    /// Removes the mapping file.
651    /// Will do nothing if the mapping file does not exist.
652    fn delete_mapping(&self, key_triple: &KeyTriple, auth: &Auth) -> std::io::Result<()> {
653        let (app_name, prov, key_name) = key_triple_to_base64_filenames(key_triple);
654        let key_name_file_path = match auth {
655            Auth::Internal => {
656                let prov_key_name = prov_and_key_to_str(key_triple.provider_id, &key_name);
657
658                // INTERNAL_KEYS_PARSEC_DIR has already been created with the necessary permissions
659                self.mappings_dir_path
660                    .join(INTERNAL_KEYS_PARSEC_DIR)
661                    .join(prov_key_name)
662            }
663            Auth::Client(_) => self
664                .mappings_dir_path
665                .join(app_name)
666                .join(prov)
667                .join(key_name),
668        };
669        if key_name_file_path.exists() {
670            fs::remove_file(key_name_file_path)
671        } else {
672            Ok(())
673        }
674    }
675}
676
677#[allow(deprecated)]
678impl ManageKeyInfo for OnDiskKeyInfoManager {
679    fn key_info_manager_type(&self) -> KeyInfoManagerType {
680        KeyInfoManagerType::OnDisk
681    }
682
683    fn get(&self, key_identity: &KeyIdentity) -> Result<Option<&KeyInfo>, String> {
684        let key_triple = KeyTriple::try_from(key_identity.clone())?;
685        // An Option<&Vec<u8>> can not automatically coerce to an Option<&[u8]>, it needs to be
686        // done by hand.
687        let curr_key_store = match key_identity.application().auth() {
688            &Auth::Internal => &self.key_store_internal,
689            _ => &self.key_store,
690        };
691
692        if let Some(key_info) = curr_key_store.get(&key_triple) {
693            Ok(Some(key_info))
694        } else {
695            Ok(None)
696        }
697    }
698
699    fn get_all(&self, provider_identity: ProviderIdentity) -> Result<Vec<KeyIdentity>, String> {
700        let provider_id = ProviderId::try_from(provider_identity.clone())?;
701        let mut key_identites = Vec::new();
702
703        let key_triples_internal = self
704            .key_store_internal
705            .keys()
706            .filter(|key_triple| key_triple.belongs_to_provider(provider_id));
707
708        for key_triple_internal in key_triples_internal {
709            let key_identity = KeyIdentity::try_from((
710                key_triple_internal.clone(),
711                provider_identity.clone(),
712                Auth::Internal,
713            ))?;
714            key_identites.push(key_identity)
715        }
716        let key_triples_external = self
717            .key_store
718            .keys()
719            .filter(|key_triple| key_triple.belongs_to_provider(provider_id));
720
721        for key_triple_external in key_triples_external {
722            let key_identity = KeyIdentity::try_from((
723                key_triple_external.clone(),
724                provider_identity.clone(),
725                Auth::Client(self.auth_type),
726            ))?;
727            key_identites.push(key_identity)
728        }
729        Ok(key_identites)
730    }
731
732    fn insert(
733        &mut self,
734        key_identity: KeyIdentity,
735        key_info: KeyInfo,
736    ) -> Result<Option<KeyInfo>, String> {
737        let key_triple = KeyTriple::try_from(key_identity.clone())?;
738        if let Err(err) =
739            self.save_mapping(&key_triple, &key_info, key_identity.application().auth())
740        {
741            Err(err.to_string())
742        } else if key_identity.application().is_internal() {
743            Ok(self.key_store_internal.insert(key_triple, key_info))
744        } else {
745            Ok(self.key_store.insert(key_triple, key_info))
746        }
747    }
748
749    fn remove(&mut self, key_identity: &KeyIdentity) -> Result<Option<KeyInfo>, String> {
750        let key_triple = KeyTriple::try_from(key_identity.clone())?;
751        if let Err(err) = self.delete_mapping(&key_triple, key_identity.application().auth()) {
752            return Err(err.to_string());
753        }
754        if key_identity.application().is_internal() {
755            Ok(self.key_store_internal.remove(&key_triple))
756        } else if !key_identity.application().is_internal() {
757            Ok(self.key_store.remove(&key_triple))
758        } else {
759            Ok(None)
760        }
761    }
762
763    fn exists(&self, key_identity: &KeyIdentity) -> Result<bool, String> {
764        let key_triple = KeyTriple::try_from(key_identity.clone())?;
765        match *key_identity.application().auth() {
766            Auth::Internal => Ok(self.key_store_internal.contains_key(&key_triple)),
767            Auth::Client(_) => Ok(self.key_store.contains_key(&key_triple)),
768        }
769    }
770}
771
772/// OnDiskKeyInfoManager builder
773#[derive(Debug, Default)]
774pub struct OnDiskKeyInfoManagerBuilder {
775    mappings_dir_path: Option<PathBuf>,
776    auth_type: Option<AuthType>,
777}
778
779impl OnDiskKeyInfoManagerBuilder {
780    /// Create a new OnDiskKeyInfoManagerBuilder
781    pub fn new() -> OnDiskKeyInfoManagerBuilder {
782        OnDiskKeyInfoManagerBuilder {
783            mappings_dir_path: None,
784            auth_type: None,
785        }
786    }
787
788    /// Add a mappings directory path to the builder
789    pub fn with_mappings_dir_path(mut self, path: PathBuf) -> OnDiskKeyInfoManagerBuilder {
790        self.mappings_dir_path = Some(path);
791
792        self
793    }
794
795    /// Add an authentication type to the builder
796    pub fn with_auth_type(mut self, default_auth_type: AuthType) -> OnDiskKeyInfoManagerBuilder {
797        self.auth_type = Some(default_auth_type);
798
799        self
800    }
801
802    /// Build into a OnDiskKeyInfoManager
803    pub fn build(self) -> Result<OnDiskKeyInfoManager> {
804        OnDiskKeyInfoManager::new(
805            self.mappings_dir_path
806                .unwrap_or_else(|| PathBuf::from(DEFAULT_MAPPINGS_PATH)),
807            self.auth_type.ok_or_else(|| {
808                Error::new(
809                    ErrorKind::InvalidData,
810                    "AuthType must be supplied to OnDiskKeyInfoManager",
811                )
812            })?,
813        )
814    }
815}
816
817#[cfg(test)]
818mod test {
819    use super::super::{KeyIdentity, KeyInfo, ManageKeyInfo};
820    use super::OnDiskKeyInfoManager;
821    use crate::key_info_managers::{ApplicationIdentity, ProviderIdentity};
822    use crate::providers::core::Provider as CoreProvider;
823    #[cfg(feature = "mbed-crypto-provider")]
824    use crate::providers::mbed_crypto::Provider as MbedCryptoProvider;
825    use parsec_interface::operations::psa_algorithm::{
826        Algorithm, AsymmetricSignature, Hash, SignHash,
827    };
828    use parsec_interface::operations::psa_key_attributes::{
829        Attributes, Lifetime, Policy, Type, UsageFlags,
830    };
831    use parsec_interface::requests::AuthType;
832    use std::fs;
833    use std::path::PathBuf;
834
835    fn test_key_attributes() -> Attributes {
836        Attributes {
837            lifetime: Lifetime::Persistent,
838            key_type: Type::Derive,
839            bits: 1024,
840            policy: Policy {
841                usage_flags: {
842                    let mut usage_flags = UsageFlags::default();
843                    let _ = usage_flags.set_sign_hash();
844                    usage_flags
845                },
846                permitted_algorithms: Algorithm::AsymmetricSignature(
847                    AsymmetricSignature::RsaPkcs1v15Sign {
848                        hash_alg: SignHash::Specific(Hash::Sha256),
849                    },
850                ),
851            },
852        }
853    }
854
855    fn test_key_info() -> KeyInfo {
856        KeyInfo {
857            id: vec![0x11, 0x22, 0x33],
858            attributes: test_key_attributes(),
859        }
860    }
861
862    #[test]
863    fn insert_get_key_info() {
864        let path = PathBuf::from(env!("OUT_DIR").to_owned() + "/insert_get_key_info_mappings");
865        let mut manager = OnDiskKeyInfoManager::new(path.clone(), AuthType::NoAuth).unwrap();
866
867        let key_identity = new_key_identity("insert_get_key_info".to_string());
868        let key_info = test_key_info();
869
870        assert!(manager.get(&key_identity).unwrap().is_none());
871
872        assert!(manager
873            .insert(key_identity.clone(), key_info.clone())
874            .unwrap()
875            .is_none());
876
877        let stored_key_info = manager
878            .get(&key_identity)
879            .unwrap()
880            .expect("Failed to get key info")
881            .clone();
882
883        assert_eq!(stored_key_info, key_info);
884        assert!(manager.remove(&key_identity).unwrap().is_some());
885        fs::remove_dir_all(path).unwrap();
886    }
887
888    #[test]
889    fn insert_remove_key() {
890        let path = PathBuf::from(env!("OUT_DIR").to_owned() + "/insert_remove_key_mappings");
891        let mut manager = OnDiskKeyInfoManager::new(path.clone(), AuthType::NoAuth).unwrap();
892
893        let key_identity = new_key_identity("insert_remove_key".to_string());
894        let key_info = test_key_info();
895
896        let _ = manager.insert(key_identity.clone(), key_info).unwrap();
897
898        assert!(manager.remove(&key_identity).unwrap().is_some());
899        fs::remove_dir_all(path).unwrap();
900    }
901
902    #[test]
903    fn remove_unexisting_key() {
904        let path = PathBuf::from(env!("OUT_DIR").to_owned() + "/remove_unexisting_key_mappings");
905        let mut manager = OnDiskKeyInfoManager::new(path.clone(), AuthType::NoAuth).unwrap();
906
907        let key_identity = new_key_identity("remove_unexisting_key".to_string());
908        assert_eq!(manager.remove(&key_identity).unwrap(), None);
909        fs::remove_dir_all(path).unwrap();
910    }
911
912    #[test]
913    fn exists() {
914        let path = PathBuf::from(env!("OUT_DIR").to_owned() + "/exists_mappings");
915        let mut manager = OnDiskKeyInfoManager::new(path.clone(), AuthType::NoAuth).unwrap();
916
917        let key_identity = new_key_identity("exists".to_string());
918        let key_info = test_key_info();
919
920        assert!(!manager.exists(&key_identity).unwrap());
921
922        let _ = manager.insert(key_identity.clone(), key_info).unwrap();
923        assert!(manager.exists(&key_identity).unwrap());
924
925        let _ = manager.remove(&key_identity).unwrap();
926        assert!(!manager.exists(&key_identity).unwrap());
927        fs::remove_dir_all(path).unwrap();
928    }
929
930    #[test]
931    fn insert_overwrites() {
932        let path = PathBuf::from(env!("OUT_DIR").to_owned() + "/insert_overwrites_mappings");
933        let mut manager = OnDiskKeyInfoManager::new(path.clone(), AuthType::NoAuth).unwrap();
934
935        let key_identity = new_key_identity("insert_overwrites".to_string());
936        let key_info_1 = test_key_info();
937        let key_info_2 = KeyInfo {
938            id: vec![0xaa, 0xbb, 0xcc],
939            attributes: test_key_attributes(),
940        };
941
942        let _ = manager.insert(key_identity.clone(), key_info_1).unwrap();
943        let _ = manager
944            .insert(key_identity.clone(), key_info_2.clone())
945            .unwrap();
946
947        let stored_key_info = manager
948            .get(&key_identity)
949            .unwrap()
950            .expect("Failed to get key info")
951            .clone();
952
953        assert_eq!(stored_key_info, key_info_2);
954        assert!(manager.remove(&key_identity).unwrap().is_some());
955        fs::remove_dir_all(path).unwrap();
956    }
957
958    #[test]
959    fn big_names_ascii() {
960        let path = PathBuf::from(env!("OUT_DIR").to_owned() + "/big_names_ascii_mappings");
961        let mut manager = OnDiskKeyInfoManager::new(path.clone(), AuthType::NoAuth).unwrap();
962
963        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();
964        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();
965
966        let key_identity = KeyIdentity::new(
967            ApplicationIdentity::new(big_app_name_ascii, AuthType::NoAuth),
968            ProviderIdentity::new(
969                CoreProvider::PROVIDER_UUID.to_string(),
970                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
971            ),
972            big_key_name_ascii,
973        );
974        let key_info = test_key_info();
975
976        let _ = manager
977            .insert(key_identity.clone(), key_info.clone())
978            .unwrap();
979        assert_eq!(manager.remove(&key_identity).unwrap().unwrap(), key_info);
980        fs::remove_dir_all(path).unwrap();
981    }
982
983    #[test]
984    fn big_names_emoticons() {
985        let path = PathBuf::from(env!("OUT_DIR").to_owned() + "/big_names_emoticons_mappings");
986        let mut manager = OnDiskKeyInfoManager::new(path.clone(), AuthType::NoAuth).unwrap();
987
988        let big_app_name_emoticons = "😀😁😂😃😄😅😆😇😈😉😊😋😌😍😎😏😐😑😒😓😔😕😖😗😘😙😚😛😜😝😞😟😠😡😢😣😤😥😦😧😨😩😪😫😬😭😮".to_string();
989        let big_key_name_emoticons = "😀😁😂😃😄😅😆😇😈😉😊😋😌😍😎😏😐😑😒😓😔😕😖😗😘😙😚😛😜😝😞😟😠😡😢😣😤😥😦😧😨😩😪😫😬😭😮".to_string();
990
991        let key_identity = KeyIdentity::new(
992            ApplicationIdentity::new(big_app_name_emoticons, AuthType::NoAuth),
993            ProviderIdentity::new(
994                CoreProvider::PROVIDER_UUID.to_string(),
995                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
996            ),
997            big_key_name_emoticons,
998        );
999        let key_info = test_key_info();
1000
1001        let _ = manager
1002            .insert(key_identity.clone(), key_info.clone())
1003            .unwrap();
1004        assert_eq!(manager.remove(&key_identity).unwrap().unwrap(), key_info);
1005        fs::remove_dir_all(path).unwrap();
1006    }
1007
1008    #[cfg(feature = "mbed-crypto-provider")]
1009    #[test]
1010    fn create_and_load() {
1011        let path = PathBuf::from(env!("OUT_DIR").to_owned() + "/create_and_load_mappings");
1012
1013        let app_name1 = "😀 Application One 😀".to_string();
1014        let key_name1 = "😀 Key One 😀".to_string();
1015        let key_identity_1 = KeyIdentity::new(
1016            ApplicationIdentity::new(app_name1, AuthType::NoAuth),
1017            ProviderIdentity::new(
1018                CoreProvider::PROVIDER_UUID.to_string(),
1019                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
1020            ),
1021            key_name1,
1022        );
1023        let key_info1 = test_key_info();
1024
1025        let app_name2 = "😇 Application Two 😇".to_string();
1026        let key_name2 = "😇 Key Two 😇".to_string();
1027        let key_identity_2 = KeyIdentity::new(
1028            ApplicationIdentity::new(app_name2, AuthType::NoAuth),
1029            ProviderIdentity::new(
1030                MbedCryptoProvider::PROVIDER_UUID.to_string(),
1031                MbedCryptoProvider::DEFAULT_PROVIDER_NAME.to_string(),
1032            ),
1033            key_name2,
1034        );
1035        let key_info2 = KeyInfo {
1036            id: vec![0x12, 0x22, 0x32],
1037            attributes: test_key_attributes(),
1038        };
1039
1040        let app_name3 = "😈 Application Three 😈".to_string();
1041        let key_name3 = "😈 Key Three 😈".to_string();
1042        let key_identity_3 = KeyIdentity::new(
1043            ApplicationIdentity::new(app_name3, AuthType::NoAuth),
1044            ProviderIdentity::new(
1045                CoreProvider::PROVIDER_UUID.to_string(),
1046                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
1047            ),
1048            key_name3,
1049        );
1050        let key_info3 = KeyInfo {
1051            id: vec![0x13, 0x23, 0x33],
1052            attributes: test_key_attributes(),
1053        };
1054        {
1055            let mut manager = OnDiskKeyInfoManager::new(path.clone(), AuthType::NoAuth).unwrap();
1056
1057            let _ = manager
1058                .insert(key_identity_1.clone(), key_info1.clone())
1059                .unwrap();
1060            let _ = manager
1061                .insert(key_identity_2.clone(), key_info2.clone())
1062                .unwrap();
1063            let _ = manager
1064                .insert(key_identity_3.clone(), key_info3.clone())
1065                .unwrap();
1066        }
1067        // The local hashmap is dropped when leaving the inner scope.
1068        {
1069            let mut manager = OnDiskKeyInfoManager::new(path.clone(), AuthType::NoAuth).unwrap();
1070
1071            assert_eq!(manager.remove(&key_identity_1).unwrap().unwrap(), key_info1);
1072            assert_eq!(manager.remove(&key_identity_2).unwrap().unwrap(), key_info2);
1073            assert_eq!(manager.remove(&key_identity_3).unwrap().unwrap(), key_info3);
1074        }
1075
1076        fs::remove_dir_all(path).unwrap();
1077    }
1078
1079    #[cfg(feature = "mbed-crypto-provider")]
1080    #[test]
1081    fn create_and_load_internal_keys() {
1082        let path = PathBuf::from(env!("OUT_DIR").to_owned() + "/create_and_load_internal_mappings");
1083
1084        let key_name1 = "😀 Key One 😀".to_string();
1085        let key_identity_1 = KeyIdentity::new(
1086            ApplicationIdentity::new_internal(),
1087            ProviderIdentity::new(
1088                CoreProvider::PROVIDER_UUID.to_string(),
1089                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
1090            ),
1091            key_name1,
1092        );
1093        let key_info1 = test_key_info();
1094        let key_name2 = "😇 Key Two 😇".to_string();
1095        let key_identity_2 = KeyIdentity::new(
1096            ApplicationIdentity::new_internal(),
1097            ProviderIdentity::new(
1098                MbedCryptoProvider::PROVIDER_UUID.to_string(),
1099                MbedCryptoProvider::DEFAULT_PROVIDER_NAME.to_string(),
1100            ),
1101            key_name2,
1102        );
1103        let key_info2 = KeyInfo {
1104            id: vec![0x12, 0x22, 0x32],
1105            attributes: test_key_attributes(),
1106        };
1107
1108        {
1109            let mut manager = OnDiskKeyInfoManager::new(path.clone(), AuthType::NoAuth).unwrap();
1110            let _ = manager
1111                .insert(key_identity_1.clone(), key_info1.clone())
1112                .unwrap();
1113            let _ = manager
1114                .insert(key_identity_2.clone(), key_info2.clone())
1115                .unwrap();
1116        }
1117        // The local hashmap is dropped when leaving the inner scope.
1118        {
1119            let mut manager = OnDiskKeyInfoManager::new(path.clone(), AuthType::NoAuth).unwrap();
1120
1121            assert_eq!(
1122                manager
1123                    .get_all(key_identity_1.provider.clone())
1124                    .unwrap()
1125                    .len(),
1126                1
1127            );
1128            assert_eq!(
1129                manager
1130                    .get_all(key_identity_2.provider.clone())
1131                    .unwrap()
1132                    .len(),
1133                1
1134            );
1135
1136            // get() should return the key info of the internal key!
1137            assert_eq!(&key_info1, manager.get(&key_identity_1).unwrap().unwrap());
1138
1139            // get() should not work for the same key if it is marked as External!
1140            let mut key_identity3 = key_identity_2.clone();
1141            key_identity3.application = ApplicationIdentity::new(
1142                key_identity_2.application().name().to_string(),
1143                AuthType::UnixPeerCredentials,
1144            );
1145            assert_eq!(None, manager.get(&key_identity3).unwrap());
1146
1147            assert_eq!(manager.remove(&key_identity_1).unwrap().unwrap(), key_info1);
1148            assert_eq!(manager.remove(&key_identity_2).unwrap().unwrap(), key_info2);
1149            assert_eq!(
1150                manager
1151                    .get_all(key_identity_1.provider.clone())
1152                    .unwrap()
1153                    .len(),
1154                0
1155            );
1156        }
1157
1158        fs::remove_dir_all(path).unwrap();
1159    }
1160
1161    fn new_key_identity(key_name: String) -> KeyIdentity {
1162        KeyIdentity::new(
1163            ApplicationIdentity::new("Testing Application 😎".to_string(), AuthType::NoAuth),
1164            ProviderIdentity::new(
1165                CoreProvider::PROVIDER_UUID.to_string(),
1166                CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
1167            ),
1168            key_name,
1169        )
1170    }
1171
1172    #[cfg(feature = "mbed-crypto-provider")]
1173    mod permissions_test {
1174        use super::*;
1175        use crate::key_info_managers::on_disk_manager::DIR_PERMISSION;
1176        use crate::key_info_managers::on_disk_manager::FILE_PERMISSION;
1177        use std::fs::Permissions;
1178        use std::io;
1179        use std::os::unix::fs::PermissionsExt;
1180        use std::path::Path;
1181
1182        // loop through every directory and file and check permissions
1183        fn check_permissions(dir: &Path) -> io::Result<()> {
1184            let file_permissions = Permissions::from_mode(FILE_PERMISSION);
1185            let dir_permissions = Permissions::from_mode(DIR_PERMISSION);
1186            if dir.is_dir() {
1187                for entry in fs::read_dir(dir)? {
1188                    let path = entry?.path();
1189                    if path.is_dir() {
1190                        assert_eq!(
1191                            fs::metadata(&path)?.permissions().mode() & dir_permissions.mode(),
1192                            dir_permissions.mode()
1193                        );
1194                        check_permissions(&path)?;
1195                    } else {
1196                        assert_eq!(
1197                            fs::metadata(&path)?.permissions().mode() & file_permissions.mode(),
1198                            file_permissions.mode()
1199                        );
1200                    }
1201                }
1202            }
1203            Ok(())
1204        }
1205
1206        #[test]
1207        fn check_kim_permissions() {
1208            let dir_permissions = Permissions::from_mode(DIR_PERMISSION);
1209            let path = PathBuf::from(env!("OUT_DIR").to_owned() + "/check_permissions");
1210            let app_name1 = "App1".to_string();
1211            let key_name1 = "Key1".to_string();
1212            let key_identity_1 = KeyIdentity::new(
1213                ApplicationIdentity::new(app_name1, AuthType::NoAuth),
1214                ProviderIdentity::new(
1215                    CoreProvider::PROVIDER_UUID.to_string(),
1216                    CoreProvider::DEFAULT_PROVIDER_NAME.to_string(),
1217                ),
1218                key_name1,
1219            );
1220            let key_info1 = test_key_info();
1221
1222            let app_name2 = "App2".to_string();
1223            let key_name2 = "Key2".to_string();
1224            let key_identity_2 = KeyIdentity::new(
1225                ApplicationIdentity::new(app_name2, AuthType::NoAuth),
1226                ProviderIdentity::new(
1227                    MbedCryptoProvider::PROVIDER_UUID.to_string(),
1228                    MbedCryptoProvider::DEFAULT_PROVIDER_NAME.to_string(),
1229                ),
1230                key_name2,
1231            );
1232            let key_info2 = KeyInfo {
1233                id: vec![0x12, 0x22, 0x32],
1234                attributes: test_key_attributes(),
1235            };
1236
1237            let mut manager = OnDiskKeyInfoManager::new(path.clone(), AuthType::NoAuth).unwrap();
1238            assert_eq!(
1239                fs::metadata(path.clone()).unwrap().permissions().mode() & dir_permissions.mode(),
1240                dir_permissions.mode()
1241            );
1242            let _ = manager.insert(key_identity_1.clone(), key_info1).unwrap();
1243            let _ = manager.insert(key_identity_2.clone(), key_info2).unwrap();
1244
1245            let _ = check_permissions(&path).is_ok();
1246            let _ = manager.remove(&key_identity_1).unwrap().unwrap();
1247            let _ = manager.remove(&key_identity_2).unwrap().unwrap();
1248
1249            fs::remove_dir_all(path).unwrap();
1250        }
1251    }
1252}