bitwarden_core/client/
encryption_settings.rs1#[cfg(feature = "internal")]
2use bitwarden_crypto::{EncString, UnsignedSharedKey};
3#[cfg(any(feature = "internal", feature = "secrets"))]
4use bitwarden_crypto::{KeyStore, SymmetricCryptoKey};
5use bitwarden_error::bitwarden_error;
6use thiserror::Error;
7#[cfg(any(feature = "internal", feature = "secrets"))]
8use uuid::Uuid;
9
10#[cfg(any(feature = "internal", feature = "secrets"))]
11use crate::key_management::{KeyIds, SymmetricKeyId};
12use crate::{error::UserIdAlreadySetError, MissingPrivateKeyError, VaultLockedError};
13
14#[allow(missing_docs)]
15#[bitwarden_error(flat)]
16#[derive(Debug, Error)]
17pub enum EncryptionSettingsError {
18 #[error("Cryptography error, {0}")]
19 Crypto(#[from] bitwarden_crypto::CryptoError),
20
21 #[error(transparent)]
22 InvalidBase64(#[from] base64::DecodeError),
23
24 #[error(transparent)]
25 VaultLocked(#[from] VaultLockedError),
26
27 #[error("Invalid private key")]
28 InvalidPrivateKey,
29
30 #[error(transparent)]
31 MissingPrivateKey(#[from] MissingPrivateKeyError),
32
33 #[error(transparent)]
34 UserIdAlreadySetError(#[from] UserIdAlreadySetError),
35}
36
37#[allow(missing_docs)]
38pub struct EncryptionSettings {}
39
40impl EncryptionSettings {
41 #[cfg(feature = "internal")]
46 pub(crate) fn new_decrypted_key(
47 user_key: SymmetricCryptoKey,
48 private_key: EncString,
49 signing_key: Option<EncString>,
50 store: &KeyStore<KeyIds>,
51 ) -> Result<(), EncryptionSettingsError> {
52 use bitwarden_crypto::{
53 AsymmetricCryptoKey, CoseSerializable, CryptoError, KeyDecryptable, SigningKey,
54 };
55 use log::warn;
56
57 use crate::key_management::{AsymmetricKeyId, SigningKeyId, SymmetricKeyId};
58
59 let private_key = {
60 let dec: Vec<u8> = private_key.decrypt_with_key(&user_key)?;
61
62 AsymmetricCryptoKey::from_der(&dec)
65 .map_err(|_| {
66 warn!("Invalid private key");
67 })
68 .ok()
69
70 };
75 let signing_key = signing_key
76 .map(|key| {
77 let dec: Vec<u8> = key.decrypt_with_key(&user_key)?;
78 SigningKey::from_cose(dec.as_slice()).map_err(Into::<CryptoError>::into)
79 })
80 .transpose()?;
81
82 #[allow(deprecated)]
84 {
85 let mut ctx = store.context_mut();
86 ctx.set_symmetric_key(SymmetricKeyId::User, user_key)?;
87 if let Some(private_key) = private_key {
88 ctx.set_asymmetric_key(AsymmetricKeyId::UserPrivateKey, private_key)?;
89 }
90
91 if let Some(signing_key) = signing_key {
92 ctx.set_signing_key(SigningKeyId::UserSigningKey, signing_key)?;
93 }
94 }
95
96 Ok(())
97 }
98
99 #[cfg(feature = "secrets")]
102 pub(crate) fn new_single_org_key(
103 organization_id: Uuid,
104 key: SymmetricCryptoKey,
105 store: &KeyStore<KeyIds>,
106 ) {
107 #[allow(deprecated)]
109 store
110 .context_mut()
111 .set_symmetric_key(SymmetricKeyId::Organization(organization_id), key)
112 .expect("Mutable context");
113 }
114
115 #[cfg(feature = "internal")]
116 pub(crate) fn set_org_keys(
117 org_enc_keys: Vec<(Uuid, UnsignedSharedKey)>,
118 store: &KeyStore<KeyIds>,
119 ) -> Result<(), EncryptionSettingsError> {
120 use crate::key_management::AsymmetricKeyId;
121
122 let mut ctx = store.context_mut();
123
124 if org_enc_keys.is_empty() {
126 return Ok(());
127 }
128
129 if !ctx.has_asymmetric_key(AsymmetricKeyId::UserPrivateKey) {
130 return Err(MissingPrivateKeyError.into());
131 }
132
133 ctx.retain_symmetric_keys(|key_ref| !matches!(key_ref, SymmetricKeyId::Organization(_)));
136
137 for (org_id, org_enc_key) in org_enc_keys {
139 ctx.decapsulate_key_unsigned(
140 AsymmetricKeyId::UserPrivateKey,
141 SymmetricKeyId::Organization(org_id),
142 &org_enc_key,
143 )?;
144 }
145
146 Ok(())
147 }
148}