bitwarden_crypto_cipher_suite/
cipher_suite_client.rs1use bitwarden_core::{Client, FromClient, key_management::KeySlotIds};
2use bitwarden_crypto::{Kdf, KeyStore};
3#[cfg(feature = "wasm")]
4use wasm_bindgen::prelude::wasm_bindgen;
5
6#[cfg_attr(feature = "wasm", wasm_bindgen)]
12#[derive(FromClient)]
13pub struct CryptoCipherSuiteClient {
14 pub(crate) key_store: KeyStore<KeySlotIds>,
15}
16
17#[cfg_attr(feature = "wasm", wasm_bindgen)]
18impl CryptoCipherSuiteClient {
19 pub fn default_kdf_for_new_account(&self) -> Kdf {
24 self.key_store
25 .context()
26 .cipher_suite()
27 .default_kdf_for_new_account()
28 }
29
30 pub fn is_kdf_compliant(&self, kdf: Kdf) -> bool {
36 self.key_store
37 .context()
38 .cipher_suite()
39 .is_kdf_compliant(&kdf)
40 }
41}
42
43pub trait CryptoCipherSuiteClientExt {
45 fn crypto_cipher_suite(&self) -> CryptoCipherSuiteClient;
47}
48
49impl CryptoCipherSuiteClientExt for Client {
50 fn crypto_cipher_suite(&self) -> CryptoCipherSuiteClient {
51 CryptoCipherSuiteClient::from_client(self)
52 }
53}
54
55#[cfg(test)]
56mod tests {
57 use bitwarden_core::{Client, ClientSettings};
58 use bitwarden_crypto::CipherSuite;
59
60 use super::*;
61
62 fn client_with_suite(cipher_suite: CipherSuite) -> Client {
63 let client = Client::new(Some(ClientSettings::default()));
64 client
65 .internal
66 .get_key_store()
67 .set_cipher_suite(cipher_suite);
68 client
69 }
70
71 #[test]
72 fn default_kdf_for_new_account_is_argon2_under_standard() {
73 let kdf = client_with_suite(CipherSuite::Standard)
74 .crypto_cipher_suite()
75 .default_kdf_for_new_account();
76 assert!(matches!(kdf, Kdf::Argon2id { .. }));
77 }
78
79 #[test]
80 fn default_kdf_for_new_account_is_pbkdf2_under_fips() {
81 let kdf = client_with_suite(CipherSuite::Fips)
82 .crypto_cipher_suite()
83 .default_kdf_for_new_account();
84 assert!(matches!(kdf, Kdf::PBKDF2 { .. }));
85 }
86
87 #[test]
88 fn every_kdf_is_compliant_under_standard() {
89 let client = client_with_suite(CipherSuite::Standard).crypto_cipher_suite();
90 assert!(client.is_kdf_compliant(Kdf::default_argon2()));
91 assert!(client.is_kdf_compliant(Kdf::default_pbkdf2()));
92 }
93
94 #[test]
95 fn only_pbkdf2_is_compliant_under_fips() {
96 let client = client_with_suite(CipherSuite::Fips).crypto_cipher_suite();
97 assert!(client.is_kdf_compliant(Kdf::default_pbkdf2()));
98 assert!(!client.is_kdf_compliant(Kdf::default_argon2()));
99 }
100}