Skip to main content

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#[cfg(feature = "internal")]
10use tracing::info;
11
12#[cfg(any(feature = "secrets", feature = "internal"))]
13use crate::OrganizationId;
14#[cfg(any(feature = "internal", feature = "secrets"))]
15use crate::key_management::{KeySlotIds, SymmetricKeySlotId};
16use crate::{MissingPrivateKeyError, error::UserIdAlreadySetError};
17
18#[allow(missing_docs)]
19#[bitwarden_error(flat)]
20#[derive(Debug, Error)]
21pub enum EncryptionSettingsError {
22    #[error("Cryptography error, {0}")]
23    Crypto(#[from] bitwarden_crypto::CryptoError),
24
25    #[error("Cryptography Initialization error")]
26    CryptoInitialization,
27
28    #[error(transparent)]
29    MissingPrivateKey(#[from] MissingPrivateKeyError),
30
31    #[error(transparent)]
32    UserIdAlreadySet(#[from] UserIdAlreadySetError),
33
34    #[error("Wrong Pin")]
35    WrongPin,
36
37    /// No PIN envelope is available, e.g. an AfterFirstUnlock PIN after an app restart
38    #[error("Pin unlock not available")]
39    PinUnlockNotAvailable,
40
41    /// The user-key could not be set to the state, and the sdk will remain locked
42    #[error("Unable to set user-key to state")]
43    UserKeyStateUpdateFailed,
44
45    #[error("Unable to retrieve user-key from state")]
46    UserKeyStateRetrievalFailed,
47
48    #[error("Invalid upgrade token")]
49    InvalidUpgradeToken,
50
51    /// Retrieval of the key-connector-key from key-connector failed
52    #[error("Key connector retrieval failed")]
53    KeyConnectorRetrievalFailed,
54
55    /// The local user data key could not be initialized.
56    #[error("Unable to initialize local user data key")]
57    LocalUserDataKeyInitFailed,
58
59    /// The local user data key could not be loaded into the key store context.
60    #[error("Unable to load local user data key into key store")]
61    LocalUserDataKeyLoadFailed,
62
63    /// The migration (re-wrap) of the local user data key failed after a user key upgrade
64    #[error("Unable to migrate local user data key after user key upgrade")]
65    LocalUserDataMigrationFailed,
66}
67
68#[allow(missing_docs)]
69pub struct EncryptionSettings {}
70
71impl EncryptionSettings {
72    /// Initialize the encryption settings with only a single decrypted organization key.
73    /// This is used only for logging in Secrets Manager with an access token
74    #[cfg(feature = "secrets")]
75    pub(crate) fn new_single_org_key(
76        organization_id: OrganizationId,
77        key: SymmetricCryptoKey,
78        store: &KeyStore<KeySlotIds>,
79    ) {
80        // FIXME: [PM-18098] When this is part of crypto we won't need to use deprecated methods
81        #[allow(deprecated)]
82        store
83            .context_mut()
84            .set_symmetric_key(SymmetricKeySlotId::Organization(organization_id), key)
85            .expect("Mutable context");
86    }
87
88    #[cfg(feature = "internal")]
89    #[bitwarden_logging::instrument(err)]
90    pub(crate) fn set_org_keys(
91        org_enc_keys: Vec<(OrganizationId, UnsignedSharedKey)>,
92        store: &KeyStore<KeySlotIds>,
93    ) -> Result<(), EncryptionSettingsError> {
94        use crate::key_management::PrivateKeySlotId;
95
96        let mut ctx = store.context_mut();
97
98        // FIXME: [PM-11690] - Early abort to handle private key being corrupt
99        if org_enc_keys.is_empty() {
100            info!("No organization keys to set");
101            return Ok(());
102        }
103
104        if !ctx.has_private_key(PrivateKeySlotId::UserPrivateKey) {
105            info!("User private key is missing, cannot set organization keys");
106            return Err(MissingPrivateKeyError.into());
107        }
108
109        // Make sure we only keep the keys given in the arguments and not any of the previous
110        // ones, which might be from organizations that the user is no longer a part of anymore
111        ctx.retain_symmetric_keys(|key_ref| {
112            !matches!(key_ref, SymmetricKeySlotId::Organization(_))
113        });
114
115        info!("Decrypting organization keys");
116        // Decrypt the org keys with the private key
117        for (org_id, org_enc_key) in org_enc_keys {
118            let _span =
119                tracing::span!(tracing::Level::INFO, "decapsulate_org_key", org_id = %org_id)
120                    .entered();
121            match org_enc_key.decapsulate(PrivateKeySlotId::UserPrivateKey, &mut ctx) {
122                Err(e) => {
123                    tracing::error!("Failed to decapsulate organization key: {}", e);
124                    return Err(e.into());
125                }
126                Ok(org_symmetric_key) => {
127                    tracing::info!(
128                        org_id = %org_id,
129                        "Successfully decapsulated organization key for org",
130                    );
131                    ctx.persist_symmetric_key(
132                        org_symmetric_key,
133                        SymmetricKeySlotId::Organization(org_id),
134                    )?;
135                }
136            }
137        }
138
139        Ok(())
140    }
141}