bitwarden_core/client/
encryption_settings.rs

1#[cfg(any(feature = "internal", feature = "secrets"))]
2use bitwarden_crypto::KeyStore;
3#[cfg(feature = "secrets")]
4use bitwarden_crypto::SymmetricCryptoKey;
5#[cfg(feature = "internal")]
6use bitwarden_crypto::UnsignedSharedKey;
7use bitwarden_error::bitwarden_error;
8use thiserror::Error;
9
10#[cfg(any(feature = "secrets", feature = "internal"))]
11use crate::OrganizationId;
12#[cfg(any(feature = "internal", feature = "secrets"))]
13use crate::key_management::{KeyIds, SymmetricKeyId};
14use crate::{MissingPrivateKeyError, error::UserIdAlreadySetError};
15
16#[allow(missing_docs)]
17#[bitwarden_error(flat)]
18#[derive(Debug, Error)]
19pub enum EncryptionSettingsError {
20    #[error("Cryptography error, {0}")]
21    Crypto(#[from] bitwarden_crypto::CryptoError),
22
23    #[error("Cryptography Initialization error")]
24    CryptoInitialization,
25
26    #[error(transparent)]
27    MissingPrivateKey(#[from] MissingPrivateKeyError),
28
29    #[error(transparent)]
30    UserIdAlreadySet(#[from] UserIdAlreadySetError),
31
32    #[error("Wrong Pin")]
33    WrongPin,
34}
35
36#[allow(missing_docs)]
37pub struct EncryptionSettings {}
38
39impl EncryptionSettings {
40    /// Initialize the encryption settings with only a single decrypted organization key.
41    /// This is used only for logging in Secrets Manager with an access token
42    #[cfg(feature = "secrets")]
43    pub(crate) fn new_single_org_key(
44        organization_id: OrganizationId,
45        key: SymmetricCryptoKey,
46        store: &KeyStore<KeyIds>,
47    ) {
48        // FIXME: [PM-18098] When this is part of crypto we won't need to use deprecated methods
49        #[allow(deprecated)]
50        store
51            .context_mut()
52            .set_symmetric_key(SymmetricKeyId::Organization(organization_id), key)
53            .expect("Mutable context");
54    }
55
56    #[cfg(feature = "internal")]
57    pub(crate) fn set_org_keys(
58        org_enc_keys: Vec<(OrganizationId, UnsignedSharedKey)>,
59        store: &KeyStore<KeyIds>,
60    ) -> Result<(), EncryptionSettingsError> {
61        use crate::key_management::AsymmetricKeyId;
62
63        let mut ctx = store.context_mut();
64
65        // FIXME: [PM-11690] - Early abort to handle private key being corrupt
66        if org_enc_keys.is_empty() {
67            return Ok(());
68        }
69
70        if !ctx.has_asymmetric_key(AsymmetricKeyId::UserPrivateKey) {
71            return Err(MissingPrivateKeyError.into());
72        }
73
74        // Make sure we only keep the keys given in the arguments and not any of the previous
75        // ones, which might be from organizations that the user is no longer a part of anymore
76        ctx.retain_symmetric_keys(|key_ref| !matches!(key_ref, SymmetricKeyId::Organization(_)));
77
78        // Decrypt the org keys with the private key
79        for (org_id, org_enc_key) in org_enc_keys {
80            ctx.decapsulate_key_unsigned(
81                AsymmetricKeyId::UserPrivateKey,
82                SymmetricKeyId::Organization(org_id),
83                &org_enc_key,
84            )?;
85        }
86
87        Ok(())
88    }
89}