From 3c55a8768742ac9be58b2b85005fe0366838e868 Mon Sep 17 00:00:00 2001 From: Hinton Date: Tue, 5 Dec 2023 21:22:22 +0100 Subject: [PATCH 01/30] Experiment with using a separate crate for crypto --- Cargo.lock | 32 +++++++++++++ crates/bitwarden-crypto/Cargo.toml | 48 +++++++++++++++++++ .../src/aes.rs} | 7 ++- crates/bitwarden-crypto/src/error.rs | 21 ++++++++ crates/bitwarden-crypto/src/lib.rs | 38 +++++++++++++++ .../src}/shareable_key.rs | 4 +- .../src}/symmetric_crypto_key.rs | 10 ++-- crates/bitwarden/Cargo.toml | 1 + .../bitwarden/src/auth/login/access_token.rs | 3 +- crates/bitwarden/src/client/access_token.rs | 9 ++-- crates/bitwarden/src/client/client.rs | 2 +- .../src/client/encryption_settings.rs | 3 +- crates/bitwarden/src/crypto/enc_string.rs | 18 ++++--- crates/bitwarden/src/crypto/encryptable.rs | 4 +- .../bitwarden/src/crypto/key_encryptable.rs | 4 +- crates/bitwarden/src/crypto/master_key.rs | 11 +++-- crates/bitwarden/src/crypto/mod.rs | 6 --- crates/bitwarden/src/crypto/rsa.rs | 3 +- crates/bitwarden/src/crypto/user_key.rs | 7 ++- crates/bitwarden/src/error.rs | 2 + .../bitwarden/src/mobile/vault/client_totp.rs | 7 +-- .../bitwarden/src/vault/cipher/attachment.rs | 3 +- crates/bitwarden/src/vault/cipher/card.rs | 3 +- crates/bitwarden/src/vault/cipher/cipher.rs | 5 +- crates/bitwarden/src/vault/cipher/field.rs | 3 +- crates/bitwarden/src/vault/cipher/identity.rs | 3 +- .../bitwarden/src/vault/cipher/local_data.rs | 3 +- crates/bitwarden/src/vault/cipher/login.rs | 3 +- .../bitwarden/src/vault/cipher/secure_note.rs | 3 +- crates/bitwarden/src/vault/collection.rs | 3 +- crates/bitwarden/src/vault/folder.rs | 3 +- .../bitwarden/src/vault/password_history.rs | 3 +- crates/bitwarden/src/vault/send.rs | 8 ++-- 33 files changed, 216 insertions(+), 67 deletions(-) create mode 100644 crates/bitwarden-crypto/Cargo.toml rename crates/{bitwarden/src/crypto/aes_ops.rs => bitwarden-crypto/src/aes.rs} (97%) create mode 100644 crates/bitwarden-crypto/src/error.rs create mode 100644 crates/bitwarden-crypto/src/lib.rs rename crates/{bitwarden/src/crypto => bitwarden-crypto/src}/shareable_key.rs (93%) rename crates/{bitwarden/src/crypto => bitwarden-crypto/src}/symmetric_crypto_key.rs (94%) diff --git a/Cargo.lock b/Cargo.lock index 3a67b163f..9c40f722c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -330,6 +330,7 @@ dependencies = [ "base64 0.21.5", "bitwarden-api-api", "bitwarden-api-identity", + "bitwarden-crypto", "cbc", "chrono", "data-encoding", @@ -405,6 +406,37 @@ dependencies = [ "supports-color", ] +[[package]] +name = "bitwarden-crypto" +version = "0.1.0" +dependencies = [ + "aes", + "argon2", + "assert_matches", + "base64 0.21.5", + "cbc", + "chrono", + "hkdf", + "hmac", + "lazy_static", + "log", + "num-bigint", + "num-traits", + "pbkdf2", + "rand 0.8.5", + "rand_chacha 0.3.1", + "rsa", + "schemars", + "serde", + "sha1", + "sha2", + "subtle", + "thiserror", + "tokio", + "uniffi", + "wiremock", +] + [[package]] name = "bitwarden-json" version = "0.3.0" diff --git a/crates/bitwarden-crypto/Cargo.toml b/crates/bitwarden-crypto/Cargo.toml new file mode 100644 index 000000000..1698f8a09 --- /dev/null +++ b/crates/bitwarden-crypto/Cargo.toml @@ -0,0 +1,48 @@ +[package] +name = "bitwarden-crypto" +version = "0.1.0" +authors = ["Bitwarden Inc"] +license-file = "LICENSE" +repository = "https://github.com/bitwarden/sdk" +homepage = "https://bitwarden.com" +description = """ +Bitwarden Cryptographic primitives +""" +keywords = ["bitwarden"] +edition = "2021" +rust-version = "1.57" + +[dependencies] +aes = ">=0.8.2, <0.9" +argon2 = { version = ">=0.5.0, <0.6", features = [ + "alloc", +], default-features = false } +assert_matches = ">=1.5.0, <2.0" +base64 = ">=0.21.2, <0.22" +cbc = { version = ">=0.1.2, <0.2", features = ["alloc"] } +chrono = { version = ">=0.4.26, <0.5", features = [ + "clock", + "serde", + "std", +], default-features = false } +hkdf = ">=0.12.3, <0.13" +hmac = ">=0.12.1, <0.13" +lazy_static = ">=1.4.0, <2.0" +log = ">=0.4.18, <0.5" +num-bigint = ">=0.4, <0.5" +num-traits = ">=0.2.15, <0.3" +pbkdf2 = { version = ">=0.12.1, <0.13", default-features = false } +rand = ">=0.8.5, <0.9" +rsa = ">=0.9.2, <0.10" +schemars = { version = ">=0.8, <0.9", features = ["uuid1", "chrono"] } +serde = { version = ">=1.0, <2.0", features = ["derive"] } +sha1 = ">=0.10.5, <0.11" +sha2 = ">=0.10.6, <0.11" +subtle = ">=2.5.0, <3.0" +thiserror = ">=1.0.40, <2.0" +uniffi = { version = "=0.25.2", optional = true } + +[dev-dependencies] +rand_chacha = "0.3.1" +tokio = { version = "1.34.0", features = ["rt", "macros"] } +wiremock = "0.5.22" diff --git a/crates/bitwarden/src/crypto/aes_ops.rs b/crates/bitwarden-crypto/src/aes.rs similarity index 97% rename from crates/bitwarden/src/crypto/aes_ops.rs rename to crates/bitwarden-crypto/src/aes.rs index 182986c3b..bb647837d 100644 --- a/crates/bitwarden/src/crypto/aes_ops.rs +++ b/crates/bitwarden-crypto/src/aes.rs @@ -16,8 +16,8 @@ use hmac::Mac; use subtle::ConstantTimeEq; use crate::{ - crypto::{PbkdfSha256Hmac, PBKDF_SHA256_HMAC_OUT_SIZE}, error::{CryptoError, Result}, + PbkdfSha256Hmac, PBKDF_SHA256_HMAC_OUT_SIZE, }; /// Decrypt using AES-256 in CBC mode. @@ -50,7 +50,7 @@ pub fn decrypt_aes256_hmac( ) -> Result> { let res = generate_mac(&mac_key, iv, &data)?; if res.ct_ne(mac).into() { - return Err(CryptoError::InvalidMac.into()); + return Err(CryptoError::InvalidMac); } decrypt_aes256(iv, data, key) } @@ -125,9 +125,8 @@ mod tests { use base64::Engine; use rand::SeedableRng; - use crate::util::BASE64_ENGINE; - use super::*; + use crate::BASE64_ENGINE; /// Helper function for generating a `GenericArray` of size 32 with each element being /// a multiple of a given increment, starting from a given offset. diff --git a/crates/bitwarden-crypto/src/error.rs b/crates/bitwarden-crypto/src/error.rs new file mode 100644 index 000000000..cbcb0b36e --- /dev/null +++ b/crates/bitwarden-crypto/src/error.rs @@ -0,0 +1,21 @@ +use std::fmt::Debug; + +use thiserror::Error; + +#[derive(Debug, Error)] +pub enum CryptoError { + #[error("The provided key is not the expected type")] + InvalidKey, + #[error("The cipher's MAC doesn't match the expected value")] + InvalidMac, + #[error("Error while decrypting EncString")] + KeyDecrypt, + #[error("The cipher key has an invalid length")] + InvalidKeyLen, + #[error("There is no encryption key for the provided organization")] + NoKeyForOrg, + #[error("The value is not a valid UTF8 String")] + InvalidUtf8String, +} + +pub type Result = std::result::Result; diff --git a/crates/bitwarden-crypto/src/lib.rs b/crates/bitwarden-crypto/src/lib.rs new file mode 100644 index 000000000..5a414d77f --- /dev/null +++ b/crates/bitwarden-crypto/src/lib.rs @@ -0,0 +1,38 @@ +use ::aes::cipher::{generic_array::GenericArray, ArrayLength, Unsigned}; +use base64::{ + alphabet, + engine::{DecodePaddingMode, GeneralPurpose, GeneralPurposeConfig}, +}; +use hmac::digest::OutputSizeUser; + +pub mod aes; +mod error; +pub mod shareable_key; +pub mod symmetric_crypto_key; + +pub use error::CryptoError; +use error::Result; + +// TODO: Move into a util crate +const BASE64_ENGINE_CONFIG: GeneralPurposeConfig = GeneralPurposeConfig::new() + .with_encode_padding(true) + .with_decode_padding_mode(DecodePaddingMode::Indifferent); + +pub const BASE64_ENGINE: GeneralPurpose = + GeneralPurpose::new(&alphabet::STANDARD, BASE64_ENGINE_CONFIG); + +pub(crate) type PbkdfSha256Hmac = hmac::Hmac; +pub(crate) const PBKDF_SHA256_HMAC_OUT_SIZE: usize = + <::OutputSize as Unsigned>::USIZE; + +/// RFC5869 HKDF-Expand operation +fn hkdf_expand>(prk: &[u8], info: Option<&str>) -> Result> { + let hkdf = hkdf::Hkdf::::from_prk(prk).map_err(|_| CryptoError::InvalidKeyLen)?; + let mut key = GenericArray::::default(); + + let i = info.map(|i| i.as_bytes()).unwrap_or(&[]); + hkdf.expand(i, &mut key) + .map_err(|_| CryptoError::InvalidKeyLen)?; + + Ok(key) +} diff --git a/crates/bitwarden/src/crypto/shareable_key.rs b/crates/bitwarden-crypto/src/shareable_key.rs similarity index 93% rename from crates/bitwarden/src/crypto/shareable_key.rs rename to crates/bitwarden-crypto/src/shareable_key.rs index 4127b0712..c67245cfb 100644 --- a/crates/bitwarden/src/crypto/shareable_key.rs +++ b/crates/bitwarden-crypto/src/shareable_key.rs @@ -1,13 +1,13 @@ use aes::cipher::{generic_array::GenericArray, typenum::U64}; use hmac::{Hmac, Mac}; -use crate::crypto::{hkdf_expand, SymmetricCryptoKey}; +use crate::{hkdf_expand, symmetric_crypto_key::SymmetricCryptoKey}; /// Derive a shareable key using hkdf from secret and name. /// /// A specialized variant of this function was called `CryptoService.makeSendKey` in the Bitwarden /// `clients` repository. -pub(crate) fn derive_shareable_key( +pub fn derive_shareable_key( secret: [u8; 16], name: &str, info: Option<&str>, diff --git a/crates/bitwarden/src/crypto/symmetric_crypto_key.rs b/crates/bitwarden-crypto/src/symmetric_crypto_key.rs similarity index 94% rename from crates/bitwarden/src/crypto/symmetric_crypto_key.rs rename to crates/bitwarden-crypto/src/symmetric_crypto_key.rs index 7b2086f75..48004270c 100644 --- a/crates/bitwarden/src/crypto/symmetric_crypto_key.rs +++ b/crates/bitwarden-crypto/src/symmetric_crypto_key.rs @@ -3,11 +3,7 @@ use std::str::FromStr; use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::Engine; -use crate::{ - crypto::derive_shareable_key, - error::{CryptoError, Error}, - util::BASE64_ENGINE, -}; +use crate::{shareable_key::derive_shareable_key, CryptoError, BASE64_ENGINE}; /// A symmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::crypto::EncString) pub struct SymmetricCryptoKey { @@ -38,7 +34,7 @@ impl SymmetricCryptoKey { } impl FromStr for SymmetricCryptoKey { - type Err = Error; + type Err = CryptoError; fn from_str(s: &str) -> Result { let bytes = BASE64_ENGINE @@ -49,7 +45,7 @@ impl FromStr for SymmetricCryptoKey { } impl TryFrom<&[u8]> for SymmetricCryptoKey { - type Error = Error; + type Error = CryptoError; fn try_from(value: &[u8]) -> Result { if value.len() == Self::KEY_LEN + Self::MAC_LEN { diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index a9e432c27..85dad3e10 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -28,6 +28,7 @@ assert_matches = ">=1.5.0, <2.0" base64 = ">=0.21.2, <0.22" bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.2" } bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.2" } +bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0" } cbc = { version = ">=0.1.2, <0.2", features = ["alloc"] } chrono = { version = ">=0.4.26, <0.5", features = [ "clock", diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index 1ec8c8b34..d934097c1 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -1,4 +1,5 @@ use base64::Engine; +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -9,7 +10,7 @@ use crate::{ JWTToken, }, client::{AccessToken, LoginMethod, ServiceAccountLoginMethod}, - crypto::{EncString, KeyDecryptable, SymmetricCryptoKey}, + crypto::{EncString, KeyDecryptable}, error::{Error, Result}, util::BASE64_ENGINE, Client, diff --git a/crates/bitwarden/src/client/access_token.rs b/crates/bitwarden/src/client/access_token.rs index b68d78572..9b0234231 100644 --- a/crates/bitwarden/src/client/access_token.rs +++ b/crates/bitwarden/src/client/access_token.rs @@ -1,13 +1,12 @@ use std::str::FromStr; use base64::Engine; +use bitwarden_crypto::{ + shareable_key::derive_shareable_key, symmetric_crypto_key::SymmetricCryptoKey, +}; use uuid::Uuid; -use crate::{ - crypto::{derive_shareable_key, SymmetricCryptoKey}, - error::AccessTokenInvalidError, - util::BASE64_ENGINE, -}; +use crate::{error::AccessTokenInvalidError, util::BASE64_ENGINE}; pub struct AccessToken { pub service_account_id: Uuid, diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index 6d1503312..b1780c21b 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -1,3 +1,4 @@ +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use chrono::Utc; use reqwest::header::{self}; use uuid::Uuid; @@ -18,7 +19,6 @@ use crate::{ client_settings::{ClientSettings, DeviceType}, encryption_settings::EncryptionSettings, }, - crypto::SymmetricCryptoKey, error::{Error, Result}, }; diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index 7c16725e7..9d1baf4ad 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -1,5 +1,6 @@ use std::collections::HashMap; +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use rsa::RsaPrivateKey; use uuid::Uuid; #[cfg(feature = "internal")] @@ -12,8 +13,6 @@ use { rsa::{pkcs8::DecodePrivateKey, Oaep}, }; -use crate::crypto::SymmetricCryptoKey; - pub struct EncryptionSettings { user_key: SymmetricCryptoKey, private_key: Option, diff --git a/crates/bitwarden/src/crypto/enc_string.rs b/crates/bitwarden/src/crypto/enc_string.rs index 09f877c50..575aba758 100644 --- a/crates/bitwarden/src/crypto/enc_string.rs +++ b/crates/bitwarden/src/crypto/enc_string.rs @@ -2,16 +2,15 @@ use std::{fmt::Display, str::FromStr}; use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::Engine; +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use serde::{de::Visitor, Deserialize}; +use super::{KeyDecryptable, KeyEncryptable, LocateKey}; use crate::{ - crypto::{decrypt_aes256_hmac, SymmetricCryptoKey}, error::{CryptoError, EncStringParseError, Error, Result}, util::BASE64_ENGINE, }; -use super::{KeyDecryptable, KeyEncryptable, LocateKey}; - /// # Encrypted string primitive /// /// [EncString] is a Bitwarden specific primitive that represents an encrypted string. They are @@ -337,7 +336,7 @@ impl EncString { mac_key: GenericArray, key: GenericArray, ) -> Result { - let (iv, mac, data) = super::encrypt_aes256_hmac(data_dec, mac_key, key)?; + let (iv, mac, data) = bitwarden_crypto::aes::encrypt_aes256_hmac(data_dec, mac_key, key)?; Ok(EncString::AesCbc256_HmacSha256_B64 { iv, mac, data }) } @@ -376,7 +375,13 @@ impl KeyDecryptable> for EncString { match self { EncString::AesCbc256_HmacSha256_B64 { iv, mac, data } => { let mac_key = key.mac_key.ok_or(CryptoError::InvalidMac)?; - let dec = decrypt_aes256_hmac(iv, mac, data.clone(), mac_key, key.key)?; + let dec = bitwarden_crypto::aes::decrypt_aes256_hmac( + iv, + mac, + data.clone(), + mac_key, + key.key, + )?; Ok(dec) } _ => Err(CryptoError::InvalidKey.into()), @@ -399,9 +404,10 @@ impl KeyDecryptable for EncString { #[cfg(test)] mod tests { - use crate::crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; + use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use super::EncString; + use crate::crypto::{KeyDecryptable, KeyEncryptable}; #[test] fn test_enc_string_roundtrip() { diff --git a/crates/bitwarden/src/crypto/encryptable.rs b/crates/bitwarden/src/crypto/encryptable.rs index f1bc78f15..1e23fc700 100644 --- a/crates/bitwarden/src/crypto/encryptable.rs +++ b/crates/bitwarden/src/crypto/encryptable.rs @@ -1,14 +1,14 @@ use std::{collections::HashMap, hash::Hash}; +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use uuid::Uuid; +use super::{KeyDecryptable, KeyEncryptable}; use crate::{ client::encryption_settings::EncryptionSettings, error::{Error, Result}, }; -use super::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; - pub trait LocateKey { fn locate_key<'a>( &self, diff --git a/crates/bitwarden/src/crypto/key_encryptable.rs b/crates/bitwarden/src/crypto/key_encryptable.rs index 99c610bb2..f841a2205 100644 --- a/crates/bitwarden/src/crypto/key_encryptable.rs +++ b/crates/bitwarden/src/crypto/key_encryptable.rs @@ -1,8 +1,8 @@ use std::{collections::HashMap, hash::Hash}; -use crate::error::Result; +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; -use super::SymmetricCryptoKey; +use crate::error::Result; pub trait KeyEncryptable { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result; diff --git a/crates/bitwarden/src/crypto/master_key.rs b/crates/bitwarden/src/crypto/master_key.rs index fdcf93dde..240ca7426 100644 --- a/crates/bitwarden/src/crypto/master_key.rs +++ b/crates/bitwarden/src/crypto/master_key.rs @@ -1,11 +1,11 @@ use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::Engine; +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use rand::Rng; use sha2::Digest; use super::{ - hkdf_expand, EncString, KeyDecryptable, PbkdfSha256Hmac, SymmetricCryptoKey, UserKey, - PBKDF_SHA256_HMAC_OUT_SIZE, + hkdf_expand, EncString, KeyDecryptable, PbkdfSha256Hmac, UserKey, PBKDF_SHA256_HMAC_OUT_SIZE, }; use crate::{client::kdf::Kdf, error::Result, util::BASE64_ENGINE}; @@ -48,7 +48,7 @@ impl MasterKey { let stretched_key = stretch_master_key(self)?; let dec: Vec = user_key.decrypt_with_key(&stretched_key)?; - SymmetricCryptoKey::try_from(dec.as_slice()) + Ok(SymmetricCryptoKey::try_from(dec.as_slice())?) } } @@ -108,7 +108,7 @@ fn derive_key(secret: &[u8], salt: &[u8], kdf: &Kdf) -> Result Result { @@ -125,10 +125,11 @@ fn stretch_master_key(master_key: &MasterKey) -> Result { mod tests { use std::num::NonZeroU32; + use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use rand::SeedableRng; use super::{make_user_key, stretch_master_key, HashPurpose, MasterKey}; - use crate::{client::kdf::Kdf, crypto::SymmetricCryptoKey}; + use crate::client::kdf::Kdf; #[test] fn test_master_key_derive_pbkdf2() { diff --git a/crates/bitwarden/src/crypto/mod.rs b/crates/bitwarden/src/crypto/mod.rs index b030a5107..bd3a6263b 100644 --- a/crates/bitwarden/src/crypto/mod.rs +++ b/crates/bitwarden/src/crypto/mod.rs @@ -32,12 +32,6 @@ mod encryptable; pub use encryptable::{Decryptable, Encryptable, LocateKey}; mod key_encryptable; pub use key_encryptable::{KeyDecryptable, KeyEncryptable}; -mod aes_ops; -use aes_ops::{decrypt_aes256_hmac, encrypt_aes256_hmac}; -mod symmetric_crypto_key; -pub use symmetric_crypto_key::SymmetricCryptoKey; -mod shareable_key; -pub(crate) use shareable_key::derive_shareable_key; #[cfg(feature = "internal")] mod master_key; diff --git a/crates/bitwarden/src/crypto/rsa.rs b/crates/bitwarden/src/crypto/rsa.rs index f105dbfe2..2a57aebf3 100644 --- a/crates/bitwarden/src/crypto/rsa.rs +++ b/crates/bitwarden/src/crypto/rsa.rs @@ -1,11 +1,12 @@ use base64::Engine; +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use rsa::{ pkcs8::{EncodePrivateKey, EncodePublicKey}, RsaPrivateKey, RsaPublicKey, }; use crate::{ - crypto::{EncString, SymmetricCryptoKey}, + crypto::EncString, error::{Error, Result}, util::BASE64_ENGINE, }; diff --git a/crates/bitwarden/src/crypto/user_key.rs b/crates/bitwarden/src/crypto/user_key.rs index 7f5bae413..f5660100e 100644 --- a/crates/bitwarden/src/crypto/user_key.rs +++ b/crates/bitwarden/src/crypto/user_key.rs @@ -1,8 +1,7 @@ +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; + use crate::{ - crypto::{ - rsa::{make_key_pair, RsaKeyPair}, - SymmetricCryptoKey, - }, + crypto::rsa::{make_key_pair, RsaKeyPair}, error::Result, }; diff --git a/crates/bitwarden/src/error.rs b/crates/bitwarden/src/error.rs index 6a9b0d8aa..e8473acf0 100644 --- a/crates/bitwarden/src/error.rs +++ b/crates/bitwarden/src/error.rs @@ -25,6 +25,8 @@ pub enum Error { #[error("Cryptography error, {0}")] Crypto(#[from] CryptoError), + #[error("Cryptography error, {0}")] + Crypto2(#[from] bitwarden_crypto::CryptoError), #[error("Error parsing EncString: {0}")] InvalidEncString(#[from] EncStringParseError), diff --git a/crates/bitwarden/src/mobile/vault/client_totp.rs b/crates/bitwarden/src/mobile/vault/client_totp.rs index 75bfd204c..1d4ffd486 100644 --- a/crates/bitwarden/src/mobile/vault/client_totp.rs +++ b/crates/bitwarden/src/mobile/vault/client_totp.rs @@ -1,9 +1,10 @@ use chrono::{DateTime, Utc}; -use crate::error::Result; -use crate::vault::{generate_totp, TotpResponse}; - use super::client_vault::ClientVault; +use crate::{ + error::Result, + vault::{generate_totp, TotpResponse}, +}; impl<'a> ClientVault<'a> { /// Generate a TOTP code from a provided key. diff --git a/crates/bitwarden/src/vault/cipher/attachment.rs b/crates/bitwarden/src/vault/cipher/attachment.rs index 101c8f4bc..4cb78be13 100644 --- a/crates/bitwarden/src/vault/cipher/attachment.rs +++ b/crates/bitwarden/src/vault/cipher/attachment.rs @@ -1,8 +1,9 @@ +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, + crypto::{EncString, KeyDecryptable, KeyEncryptable}, error::Result, }; diff --git a/crates/bitwarden/src/vault/cipher/card.rs b/crates/bitwarden/src/vault/cipher/card.rs index 1545ad171..62c1e9c35 100644 --- a/crates/bitwarden/src/vault/cipher/card.rs +++ b/crates/bitwarden/src/vault/cipher/card.rs @@ -1,8 +1,9 @@ +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, + crypto::{EncString, KeyDecryptable, KeyEncryptable}, error::Result, }; diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index b95a2f090..0d6803ed8 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -1,3 +1,4 @@ +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -11,7 +12,7 @@ use super::{ }; use crate::{ client::encryption_settings::EncryptionSettings, - crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey}, error::Result, vault::password_history, }; @@ -215,7 +216,7 @@ impl Cipher { .as_ref() .map(|k| { let key: Vec = k.decrypt_with_key(key)?; - SymmetricCryptoKey::try_from(key.as_slice()) + Ok(SymmetricCryptoKey::try_from(key.as_slice())?) }) .transpose() } diff --git a/crates/bitwarden/src/vault/cipher/field.rs b/crates/bitwarden/src/vault/cipher/field.rs index 13f7dc9bb..e5583a52a 100644 --- a/crates/bitwarden/src/vault/cipher/field.rs +++ b/crates/bitwarden/src/vault/cipher/field.rs @@ -1,10 +1,11 @@ +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; use super::linked_id::LinkedIdType; use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, + crypto::{EncString, KeyDecryptable, KeyEncryptable}, error::Result, }; diff --git a/crates/bitwarden/src/vault/cipher/identity.rs b/crates/bitwarden/src/vault/cipher/identity.rs index d40991866..4485325be 100644 --- a/crates/bitwarden/src/vault/cipher/identity.rs +++ b/crates/bitwarden/src/vault/cipher/identity.rs @@ -1,8 +1,9 @@ +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, + crypto::{EncString, KeyDecryptable, KeyEncryptable}, error::Result, }; diff --git a/crates/bitwarden/src/vault/cipher/local_data.rs b/crates/bitwarden/src/vault/cipher/local_data.rs index 8d5fe8694..db912122f 100644 --- a/crates/bitwarden/src/vault/cipher/local_data.rs +++ b/crates/bitwarden/src/vault/cipher/local_data.rs @@ -1,8 +1,9 @@ +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::{ - crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, + crypto::{KeyDecryptable, KeyEncryptable}, error::Result, }; diff --git a/crates/bitwarden/src/vault/cipher/login.rs b/crates/bitwarden/src/vault/cipher/login.rs index 7a8e18411..dcdfb0284 100644 --- a/crates/bitwarden/src/vault/cipher/login.rs +++ b/crates/bitwarden/src/vault/cipher/login.rs @@ -1,10 +1,11 @@ +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, + crypto::{EncString, KeyDecryptable, KeyEncryptable}, error::Result, }; diff --git a/crates/bitwarden/src/vault/cipher/secure_note.rs b/crates/bitwarden/src/vault/cipher/secure_note.rs index 0c7b4c799..2a06494ff 100644 --- a/crates/bitwarden/src/vault/cipher/secure_note.rs +++ b/crates/bitwarden/src/vault/cipher/secure_note.rs @@ -1,9 +1,10 @@ +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; use crate::{ - crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}, + crypto::{KeyDecryptable, KeyEncryptable}, error::Result, }; diff --git a/crates/bitwarden/src/vault/collection.rs b/crates/bitwarden/src/vault/collection.rs index 58492ef17..0eaa58ae9 100644 --- a/crates/bitwarden/src/vault/collection.rs +++ b/crates/bitwarden/src/vault/collection.rs @@ -1,10 +1,11 @@ +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, - crypto::{EncString, KeyDecryptable, LocateKey, SymmetricCryptoKey}, + crypto::{EncString, KeyDecryptable, LocateKey}, error::Result, }; diff --git a/crates/bitwarden/src/vault/folder.rs b/crates/bitwarden/src/vault/folder.rs index f9ae06055..582c25770 100644 --- a/crates/bitwarden/src/vault/folder.rs +++ b/crates/bitwarden/src/vault/folder.rs @@ -1,10 +1,11 @@ +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey}, error::Result, }; diff --git a/crates/bitwarden/src/vault/password_history.rs b/crates/bitwarden/src/vault/password_history.rs index da6a4b19e..ecc1cb585 100644 --- a/crates/bitwarden/src/vault/password_history.rs +++ b/crates/bitwarden/src/vault/password_history.rs @@ -1,9 +1,10 @@ +use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}, + crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey}, error::Result, }; diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index 5c463a0cf..d69175b56 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -1,3 +1,6 @@ +use bitwarden_crypto::{ + shareable_key::derive_shareable_key, symmetric_crypto_key::SymmetricCryptoKey, +}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -5,10 +8,7 @@ use serde_repr::{Deserialize_repr, Serialize_repr}; use uuid::Uuid; use crate::{ - crypto::{ - derive_shareable_key, EncString, KeyDecryptable, KeyEncryptable, LocateKey, - SymmetricCryptoKey, - }, + crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey}, error::Result, }; From b4546010e1c02cfc29240a4246c93bab980b0448 Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 7 Dec 2023 11:09:56 +0100 Subject: [PATCH 02/30] Move more code to bitwarden-crypto --- Cargo.lock | 2 + crates/bitwarden-crypto/Cargo.toml | 7 +++ .../src}/enc_string.rs | 46 +++++++++---------- .../src}/encryptable.rs | 41 ++++++++--------- crates/bitwarden-crypto/src/error.rs | 28 +++++++++++ .../src}/key_encryptable.rs | 4 +- crates/bitwarden-crypto/src/lib.rs | 24 ++++++++-- .../crypto => bitwarden-crypto/src}/rsa.rs | 12 ++--- crates/bitwarden-crypto/src/uniffi_support.rs | 15 ++++++ crates/bitwarden-crypto/src/user_key.rs | 16 +++++++ crates/bitwarden/Cargo.toml | 10 ++-- .../bitwarden/src/auth/login/access_token.rs | 3 +- crates/bitwarden/src/auth/login/api_key.rs | 2 +- crates/bitwarden/src/auth/login/password.rs | 3 +- crates/bitwarden/src/auth/register.rs | 3 +- crates/bitwarden/src/client/access_token.rs | 4 +- crates/bitwarden/src/client/client.rs | 3 +- .../src/client/encryption_settings.rs | 11 ++++- crates/bitwarden/src/crypto/master_key.rs | 8 ++-- crates/bitwarden/src/crypto/mod.rs | 15 ------ crates/bitwarden/src/crypto/user_key.rs | 18 -------- crates/bitwarden/src/mobile/crypto.rs | 2 +- crates/bitwarden/src/mobile/mod.rs | 12 ----- .../src/mobile/vault/client_ciphers.rs | 3 +- .../src/mobile/vault/client_collection.rs | 3 +- .../src/mobile/vault/client_folders.rs | 3 +- .../mobile/vault/client_password_history.rs | 3 +- .../src/mobile/vault/client_sends.rs | 7 +-- .../src/secrets_manager/projects/create.rs | 2 +- .../projects/project_response.rs | 2 +- .../src/secrets_manager/projects/update.rs | 2 +- .../src/secrets_manager/secrets/create.rs | 2 +- .../src/secrets_manager/secrets/list.rs | 2 +- .../secrets/secret_response.rs | 2 +- .../src/secrets_manager/secrets/update.rs | 2 +- .../src/tool/generators/client_generator.rs | 6 ++- .../src/tool/generators/passphrase.rs | 7 +-- crates/bitwarden/src/uniffi_support.rs | 3 +- .../bitwarden/src/vault/cipher/attachment.rs | 14 +++--- crates/bitwarden/src/vault/cipher/card.rs | 11 ++--- crates/bitwarden/src/vault/cipher/cipher.rs | 28 +++++------ crates/bitwarden/src/vault/cipher/field.rs | 10 ++-- crates/bitwarden/src/vault/cipher/identity.rs | 11 ++--- .../bitwarden/src/vault/cipher/local_data.rs | 14 +++--- crates/bitwarden/src/vault/cipher/login.rs | 15 ++---- .../bitwarden/src/vault/cipher/secure_note.rs | 14 +++--- crates/bitwarden/src/vault/collection.rs | 15 +++--- crates/bitwarden/src/vault/folder.rs | 11 ++--- .../bitwarden/src/vault/password_history.rs | 17 +++---- crates/bitwarden/src/vault/send.rs | 23 ++++------ crates/bitwarden/src/vault/totp.rs | 6 ++- 51 files changed, 270 insertions(+), 257 deletions(-) rename crates/{bitwarden/src/crypto => bitwarden-crypto/src}/enc_string.rs (93%) rename crates/{bitwarden/src/crypto => bitwarden-crypto/src}/encryptable.rs (58%) rename crates/{bitwarden/src/crypto => bitwarden-crypto/src}/key_encryptable.rs (96%) rename crates/{bitwarden/src/crypto => bitwarden-crypto/src}/rsa.rs (71%) create mode 100644 crates/bitwarden-crypto/src/uniffi_support.rs create mode 100644 crates/bitwarden-crypto/src/user_key.rs delete mode 100644 crates/bitwarden/src/crypto/user_key.rs diff --git a/Cargo.lock b/Cargo.lock index 9c40f722c..199cb7a12 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -428,12 +428,14 @@ dependencies = [ "rsa", "schemars", "serde", + "serde_json", "sha1", "sha2", "subtle", "thiserror", "tokio", "uniffi", + "uuid", "wiremock", ] diff --git a/crates/bitwarden-crypto/Cargo.toml b/crates/bitwarden-crypto/Cargo.toml index 1698f8a09..3b4ee628a 100644 --- a/crates/bitwarden-crypto/Cargo.toml +++ b/crates/bitwarden-crypto/Cargo.toml @@ -12,6 +12,11 @@ keywords = ["bitwarden"] edition = "2021" rust-version = "1.57" +[features] +default = [] + +mobile = ["uniffi"] + [dependencies] aes = ">=0.8.2, <0.9" argon2 = { version = ">=0.5.0, <0.6", features = [ @@ -36,11 +41,13 @@ rand = ">=0.8.5, <0.9" rsa = ">=0.9.2, <0.10" schemars = { version = ">=0.8, <0.9", features = ["uuid1", "chrono"] } serde = { version = ">=1.0, <2.0", features = ["derive"] } +serde_json = ">=1.0.96, <2.0" sha1 = ">=0.10.5, <0.11" sha2 = ">=0.10.6, <0.11" subtle = ">=2.5.0, <3.0" thiserror = ">=1.0.40, <2.0" uniffi = { version = "=0.25.2", optional = true } +uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } [dev-dependencies] rand_chacha = "0.3.1" diff --git a/crates/bitwarden/src/crypto/enc_string.rs b/crates/bitwarden-crypto/src/enc_string.rs similarity index 93% rename from crates/bitwarden/src/crypto/enc_string.rs rename to crates/bitwarden-crypto/src/enc_string.rs index 575aba758..073ca9257 100644 --- a/crates/bitwarden/src/crypto/enc_string.rs +++ b/crates/bitwarden-crypto/src/enc_string.rs @@ -2,13 +2,11 @@ use std::{fmt::Display, str::FromStr}; use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::Engine; -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use serde::{de::Visitor, Deserialize}; -use super::{KeyDecryptable, KeyEncryptable, LocateKey}; use crate::{ - error::{CryptoError, EncStringParseError, Error, Result}, - util::BASE64_ENGINE, + error::EncStringParseError, CryptoError, KeyDecryptable, KeyEncryptable, LocateKey, Result, + SymmetricCryptoKey, BASE64_ENGINE, }; /// # Encrypted string primitive @@ -88,7 +86,7 @@ impl std::fmt::Debug for EncString { /// Deserializes an [EncString] from a string. impl FromStr for EncString { - type Err = Error; + type Err = CryptoError; fn from_str(s: &str) -> Result { let (enc_type, parts): (&str, Vec<_>) = { @@ -164,8 +162,7 @@ impl FromStr for EncString { } impl EncString { - #[cfg(feature = "mobile")] - pub(crate) fn from_buffer(buf: &[u8]) -> Result { + pub fn from_buffer(buf: &[u8]) -> Result { if buf.is_empty() { return Err(EncStringParseError::NoType.into()); } @@ -232,8 +229,7 @@ impl EncString { } } - #[cfg(feature = "mobile")] - pub(crate) fn to_buffer(&self) -> Result> { + pub fn to_buffer(&self) -> Result> { let mut buf; match self { @@ -331,12 +327,12 @@ impl serde::Serialize for EncString { } impl EncString { - pub(crate) fn encrypt_aes256_hmac( + pub fn encrypt_aes256_hmac( data_dec: &[u8], mac_key: GenericArray, key: GenericArray, ) -> Result { - let (iv, mac, data) = bitwarden_crypto::aes::encrypt_aes256_hmac(data_dec, mac_key, key)?; + let (iv, mac, data) = crate::aes::encrypt_aes256_hmac(data_dec, mac_key, key)?; Ok(EncString::AesCbc256_HmacSha256_B64 { iv, mac, data }) } @@ -375,16 +371,10 @@ impl KeyDecryptable> for EncString { match self { EncString::AesCbc256_HmacSha256_B64 { iv, mac, data } => { let mac_key = key.mac_key.ok_or(CryptoError::InvalidMac)?; - let dec = bitwarden_crypto::aes::decrypt_aes256_hmac( - iv, - mac, - data.clone(), - mac_key, - key.key, - )?; + let dec = crate::aes::decrypt_aes256_hmac(iv, mac, data.clone(), mac_key, key.key)?; Ok(dec) } - _ => Err(CryptoError::InvalidKey.into()), + _ => Err(CryptoError::InvalidKey), } } } @@ -398,16 +388,26 @@ impl KeyEncryptable for String { impl KeyDecryptable for EncString { fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { let dec: Vec = self.decrypt_with_key(key)?; - String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String.into()) + String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String) + } +} + +// Usually we wouldn't want to expose EncStrings in the API or the schemas, +// but we need them in the mobile API, so define it here to limit the scope +impl schemars::JsonSchema for EncString { + fn schema_name() -> String { + "EncString".to_string() + } + + fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { + gen.subschema_for::() } } #[cfg(test)] mod tests { - use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; - use super::EncString; - use crate::crypto::{KeyDecryptable, KeyEncryptable}; + use crate::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; #[test] fn test_enc_string_roundtrip() { diff --git a/crates/bitwarden/src/crypto/encryptable.rs b/crates/bitwarden-crypto/src/encryptable.rs similarity index 58% rename from crates/bitwarden/src/crypto/encryptable.rs rename to crates/bitwarden-crypto/src/encryptable.rs index 1e23fc700..ca97d9af9 100644 --- a/crates/bitwarden/src/crypto/encryptable.rs +++ b/crates/bitwarden-crypto/src/encryptable.rs @@ -1,18 +1,17 @@ use std::{collections::HashMap, hash::Hash}; -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use uuid::Uuid; -use super::{KeyDecryptable, KeyEncryptable}; -use crate::{ - client::encryption_settings::EncryptionSettings, - error::{Error, Result}, -}; +use crate::{CryptoError, KeyDecryptable, KeyEncryptable, Result, SymmetricCryptoKey}; + +pub trait KeyContainer { + fn get_key(&self, org_id: &Option) -> Option<&SymmetricCryptoKey>; +} pub trait LocateKey { fn locate_key<'a>( &self, - enc: &'a EncryptionSettings, + enc: &'a dyn KeyContainer, org_id: &Option, ) -> Option<&'a SymmetricCryptoKey> { enc.get_key(org_id) @@ -21,36 +20,40 @@ pub trait LocateKey { /// Deprecated: please use LocateKey and KeyDecryptable instead pub trait Encryptable { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result; + fn encrypt(self, enc: &dyn KeyContainer, org_id: &Option) -> Result; } /// Deprecated: please use LocateKey and KeyDecryptable instead pub trait Decryptable { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result; + fn decrypt(&self, enc: &dyn KeyContainer, org_id: &Option) -> Result; } impl + LocateKey, Output> Encryptable for T { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result { - let key = self.locate_key(enc, org_id).ok_or(Error::VaultLocked)?; + fn encrypt(self, enc: &dyn KeyContainer, org_id: &Option) -> Result { + let key = self + .locate_key(enc, org_id) + .ok_or(CryptoError::MissingKey)?; self.encrypt_with_key(key) } } impl + LocateKey, Output> Decryptable for T { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result { - let key = self.locate_key(enc, org_id).ok_or(Error::VaultLocked)?; + fn decrypt(&self, enc: &dyn KeyContainer, org_id: &Option) -> Result { + let key = self + .locate_key(enc, org_id) + .ok_or(CryptoError::MissingKey)?; self.decrypt_with_key(key) } } impl, Output> Encryptable> for Vec { - fn encrypt(self, enc: &EncryptionSettings, org_id: &Option) -> Result> { + fn encrypt(self, enc: &dyn KeyContainer, org_id: &Option) -> Result> { self.into_iter().map(|e| e.encrypt(enc, org_id)).collect() } } impl, Output> Decryptable> for Vec { - fn decrypt(&self, enc: &EncryptionSettings, org_id: &Option) -> Result> { + fn decrypt(&self, enc: &dyn KeyContainer, org_id: &Option) -> Result> { self.iter().map(|e| e.decrypt(enc, org_id)).collect() } } @@ -58,11 +61,7 @@ impl, Output> Decryptable> for Vec { impl, Output, Id: Hash + Eq> Encryptable> for HashMap { - fn encrypt( - self, - enc: &EncryptionSettings, - org_id: &Option, - ) -> Result> { + fn encrypt(self, enc: &dyn KeyContainer, org_id: &Option) -> Result> { self.into_iter() .map(|(id, e)| Ok((id, e.encrypt(enc, org_id)?))) .collect() @@ -74,7 +73,7 @@ impl, Output, Id: Hash + Eq + Copy> Decryptable, ) -> Result> { self.iter() diff --git a/crates/bitwarden-crypto/src/error.rs b/crates/bitwarden-crypto/src/error.rs index cbcb0b36e..540c0f720 100644 --- a/crates/bitwarden-crypto/src/error.rs +++ b/crates/bitwarden-crypto/src/error.rs @@ -16,6 +16,34 @@ pub enum CryptoError { NoKeyForOrg, #[error("The value is not a valid UTF8 String")] InvalidUtf8String, + #[error("Missing Key")] + MissingKey, + + #[error("EncString error, {0}")] + EncString(#[from] EncStringParseError), + + #[error("Rsa error, {0}")] + RsaError(#[from] RsaError), +} + +#[derive(Debug, Error)] +pub enum EncStringParseError { + #[error("No type detected, missing '.' separator")] + NoType, + #[error("Invalid type, got {enc_type} with {parts} parts")] + InvalidType { enc_type: String, parts: usize }, + #[error("Error decoding base64: {0}")] + InvalidBase64(#[from] base64::DecodeError), + #[error("Invalid length: expected {expected}, got {got}")] + InvalidLength { expected: usize, got: usize }, +} + +#[derive(Debug, Error)] +pub enum RsaError { + #[error("Unable to create public key")] + CreatePublicKey, + #[error("Unable to create private key")] + CreatePrivateKey, } pub type Result = std::result::Result; diff --git a/crates/bitwarden/src/crypto/key_encryptable.rs b/crates/bitwarden-crypto/src/key_encryptable.rs similarity index 96% rename from crates/bitwarden/src/crypto/key_encryptable.rs rename to crates/bitwarden-crypto/src/key_encryptable.rs index f841a2205..bd36268fc 100644 --- a/crates/bitwarden/src/crypto/key_encryptable.rs +++ b/crates/bitwarden-crypto/src/key_encryptable.rs @@ -1,8 +1,6 @@ use std::{collections::HashMap, hash::Hash}; -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; - -use crate::error::Result; +use crate::{error::Result, symmetric_crypto_key::SymmetricCryptoKey}; pub trait KeyEncryptable { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result; diff --git a/crates/bitwarden-crypto/src/lib.rs b/crates/bitwarden-crypto/src/lib.rs index 5a414d77f..6d078c083 100644 --- a/crates/bitwarden-crypto/src/lib.rs +++ b/crates/bitwarden-crypto/src/lib.rs @@ -5,13 +5,27 @@ use base64::{ }; use hmac::digest::OutputSizeUser; +#[cfg(feature = "mobile")] +uniffi::setup_scaffolding!(); + pub mod aes; mod error; -pub mod shareable_key; -pub mod symmetric_crypto_key; - -pub use error::CryptoError; -use error::Result; +mod key_encryptable; +pub use key_encryptable::{KeyDecryptable, KeyEncryptable}; +mod shareable_key; +mod symmetric_crypto_key; +pub use error::{CryptoError, Result}; +pub use shareable_key::derive_shareable_key; +pub use symmetric_crypto_key::SymmetricCryptoKey; +mod encryptable; +pub use encryptable::{Decryptable, Encryptable, KeyContainer, LocateKey}; +mod enc_string; +pub use enc_string::EncString; +pub mod rsa; +mod user_key; +pub use user_key::UserKey; +mod uniffi_support; +pub use uniffi_support::*; // TODO: Move into a util crate const BASE64_ENGINE_CONFIG: GeneralPurposeConfig = GeneralPurposeConfig::new() diff --git a/crates/bitwarden/src/crypto/rsa.rs b/crates/bitwarden-crypto/src/rsa.rs similarity index 71% rename from crates/bitwarden/src/crypto/rsa.rs rename to crates/bitwarden-crypto/src/rsa.rs index 2a57aebf3..b3d811eb0 100644 --- a/crates/bitwarden/src/crypto/rsa.rs +++ b/crates/bitwarden-crypto/src/rsa.rs @@ -1,14 +1,12 @@ use base64::Engine; -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; use rsa::{ pkcs8::{EncodePrivateKey, EncodePublicKey}, RsaPrivateKey, RsaPublicKey, }; use crate::{ - crypto::EncString, - error::{Error, Result}, - util::BASE64_ENGINE, + error::{Result, RsaError}, + EncString, SymmetricCryptoKey, BASE64_ENGINE, }; #[cfg_attr(feature = "mobile", derive(uniffi::Record))] @@ -19,7 +17,7 @@ pub struct RsaKeyPair { pub private: EncString, } -pub(super) fn make_key_pair(key: &SymmetricCryptoKey) -> Result { +pub fn make_key_pair(key: &SymmetricCryptoKey) -> Result { let mut rng = rand::thread_rng(); let bits = 2048; let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key"); @@ -27,12 +25,12 @@ pub(super) fn make_key_pair(key: &SymmetricCryptoKey) -> Result { let spki = pub_key .to_public_key_der() - .map_err(|_| Error::Internal("unable to create public key"))?; + .map_err(|_| RsaError::CreatePublicKey)?; let b64 = BASE64_ENGINE.encode(spki.as_bytes()); let pkcs = priv_key .to_pkcs8_der() - .map_err(|_| Error::Internal("unable to create private key"))?; + .map_err(|_| RsaError::CreatePrivateKey)?; let protected = EncString::encrypt_aes256_hmac(pkcs.as_bytes(), key.mac_key.unwrap(), key.key)?; diff --git a/crates/bitwarden-crypto/src/uniffi_support.rs b/crates/bitwarden-crypto/src/uniffi_support.rs new file mode 100644 index 000000000..98d618e32 --- /dev/null +++ b/crates/bitwarden-crypto/src/uniffi_support.rs @@ -0,0 +1,15 @@ +use crate::{CryptoError, EncString, UniffiCustomTypeConverter}; + +uniffi::custom_type!(EncString, String); + +impl UniffiCustomTypeConverter for EncString { + type Builtin = String; + + fn into_custom(val: Self::Builtin) -> uniffi::Result { + val.parse().map_err(|e: CryptoError| e.into()) + } + + fn from_custom(obj: Self) -> Self::Builtin { + obj.to_string() + } +} diff --git a/crates/bitwarden-crypto/src/user_key.rs b/crates/bitwarden-crypto/src/user_key.rs new file mode 100644 index 000000000..7ad289c7a --- /dev/null +++ b/crates/bitwarden-crypto/src/user_key.rs @@ -0,0 +1,16 @@ +use crate::{ + rsa::{make_key_pair, RsaKeyPair}, + Result, SymmetricCryptoKey, +}; + +pub struct UserKey(pub SymmetricCryptoKey); + +impl UserKey { + pub fn new(key: SymmetricCryptoKey) -> Self { + Self(key) + } + + pub fn make_key_pair(&self) -> Result { + make_key_pair(&self.0) + } +} diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 85dad3e10..11d21ec55 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -15,9 +15,13 @@ rust-version = "1.57" [features] default = ["secrets"] -secrets = [] # Secrets manager API -internal = [] # Internal testing methods -mobile = ["uniffi", "internal"] # Mobile-specific features +secrets = [] # Secrets manager API +internal = [] # Internal testing methods +mobile = [ + "uniffi", + "internal", + "bitwarden-crypto/mobile", +] # Mobile-specific features [dependencies] aes = ">=0.8.2, <0.9" diff --git a/crates/bitwarden/src/auth/login/access_token.rs b/crates/bitwarden/src/auth/login/access_token.rs index d934097c1..9671d08c4 100644 --- a/crates/bitwarden/src/auth/login/access_token.rs +++ b/crates/bitwarden/src/auth/login/access_token.rs @@ -1,5 +1,5 @@ use base64::Engine; -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; +use bitwarden_crypto::{EncString, KeyDecryptable, SymmetricCryptoKey}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -10,7 +10,6 @@ use crate::{ JWTToken, }, client::{AccessToken, LoginMethod, ServiceAccountLoginMethod}, - crypto::{EncString, KeyDecryptable}, error::{Error, Result}, util::BASE64_ENGINE, Client, diff --git a/crates/bitwarden/src/auth/login/api_key.rs b/crates/bitwarden/src/auth/login/api_key.rs index db5cbe01d..97f485670 100644 --- a/crates/bitwarden/src/auth/login/api_key.rs +++ b/crates/bitwarden/src/auth/login/api_key.rs @@ -1,3 +1,4 @@ +use bitwarden_crypto::EncString; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -8,7 +9,6 @@ use crate::{ JWTToken, }, client::{LoginMethod, UserLoginMethod}, - crypto::EncString, error::{Error, Result}, Client, }; diff --git a/crates/bitwarden/src/auth/login/password.rs b/crates/bitwarden/src/auth/login/password.rs index a320131ea..92b2c46bf 100644 --- a/crates/bitwarden/src/auth/login/password.rs +++ b/crates/bitwarden/src/auth/login/password.rs @@ -10,7 +10,6 @@ use crate::{ login::{determine_password_hash, TwoFactorRequest}, }, client::{kdf::Kdf, LoginMethod}, - crypto::EncString, Client, }; use crate::{ @@ -26,6 +25,8 @@ pub(crate) async fn login_password( client: &mut Client, input: &PasswordLoginRequest, ) -> Result { + use bitwarden_crypto::EncString; + use crate::client::UserLoginMethod; info!("password logging in"); diff --git a/crates/bitwarden/src/auth/register.rs b/crates/bitwarden/src/auth/register.rs index 206c1905b..3abf83e17 100644 --- a/crates/bitwarden/src/auth/register.rs +++ b/crates/bitwarden/src/auth/register.rs @@ -2,12 +2,13 @@ use bitwarden_api_identity::{ apis::accounts_api::accounts_register_post, models::{KeysRequestModel, RegisterRequestModel}, }; +use bitwarden_crypto::rsa::RsaKeyPair; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::{ client::kdf::Kdf, - crypto::{HashPurpose, MasterKey, RsaKeyPair}, + crypto::{HashPurpose, MasterKey}, error::Result, util::default_pbkdf2_iterations, Client, diff --git a/crates/bitwarden/src/client/access_token.rs b/crates/bitwarden/src/client/access_token.rs index 9b0234231..6ffd42f5c 100644 --- a/crates/bitwarden/src/client/access_token.rs +++ b/crates/bitwarden/src/client/access_token.rs @@ -1,9 +1,7 @@ use std::str::FromStr; use base64::Engine; -use bitwarden_crypto::{ - shareable_key::derive_shareable_key, symmetric_crypto_key::SymmetricCryptoKey, -}; +use bitwarden_crypto::{derive_shareable_key, SymmetricCryptoKey}; use uuid::Uuid; use crate::{error::AccessTokenInvalidError, util::BASE64_ENGINE}; diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index b1780c21b..5b8630700 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -1,4 +1,4 @@ -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; +use bitwarden_crypto::{EncString, SymmetricCryptoKey}; use chrono::Utc; use reqwest::header::{self}; use uuid::Uuid; @@ -8,7 +8,6 @@ use crate::auth::login::{AccessTokenLoginRequest, AccessTokenLoginResponse}; #[cfg(feature = "internal")] use crate::{ client::kdf::Kdf, - crypto::EncString, platform::{ generate_fingerprint, get_user_api_key, sync, FingerprintRequest, FingerprintResponse, SecretVerificationRequest, SyncRequest, SyncResponse, UserApiKeyResponse, diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index 9d1baf4ad..81022f2f0 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -1,13 +1,12 @@ use std::collections::HashMap; -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; +use bitwarden_crypto::{EncString, KeyContainer, SymmetricCryptoKey}; use rsa::RsaPrivateKey; use uuid::Uuid; #[cfg(feature = "internal")] use { crate::{ client::UserLoginMethod, - crypto::{EncString, KeyDecryptable}, error::{CryptoError, Result}, }, rsa::{pkcs8::DecodePrivateKey, Oaep}, @@ -58,6 +57,8 @@ impl EncryptionSettings { user_key: SymmetricCryptoKey, private_key: EncString, ) -> Result { + use bitwarden_crypto::KeyDecryptable; + let private_key = { let dec: Vec = private_key.decrypt_with_key(&user_key)?; Some(rsa::RsaPrivateKey::from_pkcs8_der(&dec).map_err(|_| CryptoError::InvalidKey)?) @@ -124,3 +125,9 @@ impl EncryptionSettings { } } } + +impl KeyContainer for EncryptionSettings { + fn get_key(&self, org_id: &Option) -> Option<&SymmetricCryptoKey> { + EncryptionSettings::get_key(self, org_id) + } +} diff --git a/crates/bitwarden/src/crypto/master_key.rs b/crates/bitwarden/src/crypto/master_key.rs index 240ca7426..6c963e013 100644 --- a/crates/bitwarden/src/crypto/master_key.rs +++ b/crates/bitwarden/src/crypto/master_key.rs @@ -1,12 +1,10 @@ use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::Engine; -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; +use bitwarden_crypto::{EncString, KeyDecryptable, SymmetricCryptoKey, UserKey}; use rand::Rng; use sha2::Digest; -use super::{ - hkdf_expand, EncString, KeyDecryptable, PbkdfSha256Hmac, UserKey, PBKDF_SHA256_HMAC_OUT_SIZE, -}; +use super::{hkdf_expand, PbkdfSha256Hmac, PBKDF_SHA256_HMAC_OUT_SIZE}; use crate::{client::kdf::Kdf, error::Result, util::BASE64_ENGINE}; #[derive(Copy, Clone)] @@ -125,7 +123,7 @@ fn stretch_master_key(master_key: &MasterKey) -> Result { mod tests { use std::num::NonZeroU32; - use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; + use bitwarden_crypto::SymmetricCryptoKey; use rand::SeedableRng; use super::{make_user_key, stretch_master_key, HashPurpose, MasterKey}; diff --git a/crates/bitwarden/src/crypto/mod.rs b/crates/bitwarden/src/crypto/mod.rs index bd3a6263b..e7ca509de 100644 --- a/crates/bitwarden/src/crypto/mod.rs +++ b/crates/bitwarden/src/crypto/mod.rs @@ -26,25 +26,10 @@ use hmac::digest::OutputSizeUser; use crate::error::{Error, Result}; -mod enc_string; -pub use enc_string::EncString; -mod encryptable; -pub use encryptable::{Decryptable, Encryptable, LocateKey}; -mod key_encryptable; -pub use key_encryptable::{KeyDecryptable, KeyEncryptable}; - #[cfg(feature = "internal")] mod master_key; #[cfg(feature = "internal")] pub(crate) use master_key::{HashPurpose, MasterKey}; -#[cfg(feature = "internal")] -mod user_key; -#[cfg(feature = "internal")] -pub(crate) use user_key::UserKey; -#[cfg(feature = "internal")] -mod rsa; -#[cfg(feature = "internal")] -pub use self::rsa::RsaKeyPair; #[cfg(feature = "internal")] mod fingerprint; diff --git a/crates/bitwarden/src/crypto/user_key.rs b/crates/bitwarden/src/crypto/user_key.rs deleted file mode 100644 index f5660100e..000000000 --- a/crates/bitwarden/src/crypto/user_key.rs +++ /dev/null @@ -1,18 +0,0 @@ -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; - -use crate::{ - crypto::rsa::{make_key_pair, RsaKeyPair}, - error::Result, -}; - -pub(crate) struct UserKey(pub(super) SymmetricCryptoKey); - -impl UserKey { - pub(crate) fn new(key: SymmetricCryptoKey) -> Self { - Self(key) - } - - pub(crate) fn make_key_pair(&self) -> Result { - make_key_pair(&self.0) - } -} diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index 9c2c8478f..7e6ac1eef 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -1,11 +1,11 @@ use std::collections::HashMap; +use bitwarden_crypto::EncString; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::{ client::kdf::Kdf, - crypto::EncString, error::{Error, Result}, Client, }; diff --git a/crates/bitwarden/src/mobile/mod.rs b/crates/bitwarden/src/mobile/mod.rs index fe3083aa8..e0ba50d00 100644 --- a/crates/bitwarden/src/mobile/mod.rs +++ b/crates/bitwarden/src/mobile/mod.rs @@ -8,15 +8,3 @@ mod client_kdf; pub use client_crypto::ClientCrypto; pub use client_kdf::ClientKdf; - -// Usually we wouldn't want to expose EncStrings in the API or the schemas, -// but we need them in the mobile API, so define it here to limit the scope -impl schemars::JsonSchema for crate::crypto::EncString { - fn schema_name() -> String { - "EncString".to_string() - } - - fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema { - gen.subschema_for::() - } -} diff --git a/crates/bitwarden/src/mobile/vault/client_ciphers.rs b/crates/bitwarden/src/mobile/vault/client_ciphers.rs index 87b77cfd5..4e34021ee 100644 --- a/crates/bitwarden/src/mobile/vault/client_ciphers.rs +++ b/crates/bitwarden/src/mobile/vault/client_ciphers.rs @@ -1,6 +1,7 @@ +use bitwarden_crypto::{Decryptable, Encryptable}; + use super::client_vault::ClientVault; use crate::{ - crypto::{Decryptable, Encryptable}, error::Result, vault::{Cipher, CipherListView, CipherView}, Client, diff --git a/crates/bitwarden/src/mobile/vault/client_collection.rs b/crates/bitwarden/src/mobile/vault/client_collection.rs index 80535406c..9cb5d1711 100644 --- a/crates/bitwarden/src/mobile/vault/client_collection.rs +++ b/crates/bitwarden/src/mobile/vault/client_collection.rs @@ -1,6 +1,7 @@ +use bitwarden_crypto::Decryptable; + use super::client_vault::ClientVault; use crate::{ - crypto::Decryptable, error::Result, vault::{Collection, CollectionView}, Client, diff --git a/crates/bitwarden/src/mobile/vault/client_folders.rs b/crates/bitwarden/src/mobile/vault/client_folders.rs index b6f6a72f4..fec3ad7db 100644 --- a/crates/bitwarden/src/mobile/vault/client_folders.rs +++ b/crates/bitwarden/src/mobile/vault/client_folders.rs @@ -1,6 +1,7 @@ +use bitwarden_crypto::{Decryptable, Encryptable}; + use super::client_vault::ClientVault; use crate::{ - crypto::{Decryptable, Encryptable}, error::Result, vault::{Folder, FolderView}, Client, diff --git a/crates/bitwarden/src/mobile/vault/client_password_history.rs b/crates/bitwarden/src/mobile/vault/client_password_history.rs index d873f8dfc..99727232b 100644 --- a/crates/bitwarden/src/mobile/vault/client_password_history.rs +++ b/crates/bitwarden/src/mobile/vault/client_password_history.rs @@ -1,6 +1,7 @@ +use bitwarden_crypto::{Decryptable, Encryptable}; + use super::client_vault::ClientVault; use crate::{ - crypto::{Decryptable, Encryptable}, error::Result, vault::{PasswordHistory, PasswordHistoryView}, Client, diff --git a/crates/bitwarden/src/mobile/vault/client_sends.rs b/crates/bitwarden/src/mobile/vault/client_sends.rs index b1de05f44..45d9a7825 100644 --- a/crates/bitwarden/src/mobile/vault/client_sends.rs +++ b/crates/bitwarden/src/mobile/vault/client_sends.rs @@ -1,8 +1,9 @@ use std::path::Path; +use bitwarden_crypto::{Decryptable, EncString, Encryptable, KeyDecryptable, KeyEncryptable}; + use super::client_vault::ClientVault; use crate::{ - crypto::{Decryptable, EncString, Encryptable, KeyDecryptable, KeyEncryptable}, error::{Error, Result}, vault::{Send, SendListView, SendView}, Client, @@ -47,7 +48,7 @@ impl<'a> ClientSends<'a> { let key = Send::get_key(&send.key, key)?; let buf = EncString::from_buffer(encrypted_buffer)?; - buf.decrypt_with_key(&key) + Ok(buf.decrypt_with_key(&key)?) } pub async fn encrypt(&self, send_view: SendView) -> Result { @@ -79,7 +80,7 @@ impl<'a> ClientSends<'a> { let key = Send::get_key(&send.key, key)?; let enc = buffer.encrypt_with_key(&key)?; - enc.to_buffer() + Ok(enc.to_buffer()?) } } diff --git a/crates/bitwarden/src/secrets_manager/projects/create.rs b/crates/bitwarden/src/secrets_manager/projects/create.rs index 996a3463e..ab3b7bd62 100644 --- a/crates/bitwarden/src/secrets_manager/projects/create.rs +++ b/crates/bitwarden/src/secrets_manager/projects/create.rs @@ -1,4 +1,5 @@ use bitwarden_api_api::models::ProjectCreateRequestModel; +use bitwarden_crypto::KeyEncryptable; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -6,7 +7,6 @@ use uuid::Uuid; use super::ProjectResponse; use crate::{ client::Client, - crypto::KeyEncryptable, error::{Error, Result}, }; diff --git a/crates/bitwarden/src/secrets_manager/projects/project_response.rs b/crates/bitwarden/src/secrets_manager/projects/project_response.rs index b8c82806b..1e6f6a158 100644 --- a/crates/bitwarden/src/secrets_manager/projects/project_response.rs +++ b/crates/bitwarden/src/secrets_manager/projects/project_response.rs @@ -1,4 +1,5 @@ use bitwarden_api_api::models::ProjectResponseModel; +use bitwarden_crypto::{Decryptable, EncString}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -6,7 +7,6 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString}, error::{Error, Result}, }; diff --git a/crates/bitwarden/src/secrets_manager/projects/update.rs b/crates/bitwarden/src/secrets_manager/projects/update.rs index 6a0479d88..e00609ff4 100644 --- a/crates/bitwarden/src/secrets_manager/projects/update.rs +++ b/crates/bitwarden/src/secrets_manager/projects/update.rs @@ -1,4 +1,5 @@ use bitwarden_api_api::models::ProjectUpdateRequestModel; +use bitwarden_crypto::KeyEncryptable; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -6,7 +7,6 @@ use uuid::Uuid; use super::ProjectResponse; use crate::{ client::Client, - crypto::KeyEncryptable, error::{Error, Result}, }; diff --git a/crates/bitwarden/src/secrets_manager/secrets/create.rs b/crates/bitwarden/src/secrets_manager/secrets/create.rs index a1bb81799..4f84223dc 100644 --- a/crates/bitwarden/src/secrets_manager/secrets/create.rs +++ b/crates/bitwarden/src/secrets_manager/secrets/create.rs @@ -1,11 +1,11 @@ use bitwarden_api_api::models::SecretCreateRequestModel; +use bitwarden_crypto::KeyEncryptable; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; use super::SecretResponse; use crate::{ - crypto::KeyEncryptable, error::{Error, Result}, Client, }; diff --git a/crates/bitwarden/src/secrets_manager/secrets/list.rs b/crates/bitwarden/src/secrets_manager/secrets/list.rs index 1f4ccba3f..7fa46d164 100644 --- a/crates/bitwarden/src/secrets_manager/secrets/list.rs +++ b/crates/bitwarden/src/secrets_manager/secrets/list.rs @@ -1,13 +1,13 @@ use bitwarden_api_api::models::{ SecretWithProjectsListResponseModel, SecretsWithProjectsInnerSecret, }; +use bitwarden_crypto::{Decryptable, EncString}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; use crate::{ client::{encryption_settings::EncryptionSettings, Client}, - crypto::{Decryptable, EncString}, error::{Error, Result}, }; diff --git a/crates/bitwarden/src/secrets_manager/secrets/secret_response.rs b/crates/bitwarden/src/secrets_manager/secrets/secret_response.rs index a7fe49200..fe1a4d342 100644 --- a/crates/bitwarden/src/secrets_manager/secrets/secret_response.rs +++ b/crates/bitwarden/src/secrets_manager/secrets/secret_response.rs @@ -1,6 +1,7 @@ use bitwarden_api_api::models::{ BaseSecretResponseModel, BaseSecretResponseModelListResponseModel, SecretResponseModel, }; +use bitwarden_crypto::{Decryptable, EncString}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -8,7 +9,6 @@ use uuid::Uuid; use crate::{ client::encryption_settings::EncryptionSettings, - crypto::{Decryptable, EncString}, error::{Error, Result}, }; diff --git a/crates/bitwarden/src/secrets_manager/secrets/update.rs b/crates/bitwarden/src/secrets_manager/secrets/update.rs index 970812c5a..f9e54f810 100644 --- a/crates/bitwarden/src/secrets_manager/secrets/update.rs +++ b/crates/bitwarden/src/secrets_manager/secrets/update.rs @@ -1,4 +1,5 @@ use bitwarden_api_api::models::SecretUpdateRequestModel; +use bitwarden_crypto::KeyEncryptable; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -6,7 +7,6 @@ use uuid::Uuid; use super::SecretResponse; use crate::{ client::Client, - crypto::KeyEncryptable, error::{Error, Result}, }; diff --git a/crates/bitwarden/src/tool/generators/client_generator.rs b/crates/bitwarden/src/tool/generators/client_generator.rs index 4675ad99d..e5df126ee 100644 --- a/crates/bitwarden/src/tool/generators/client_generator.rs +++ b/crates/bitwarden/src/tool/generators/client_generator.rs @@ -1,7 +1,9 @@ use crate::{ error::Result, - tool::generators::passphrase::{passphrase, PassphraseGeneratorRequest}, - tool::generators::password::{password, PasswordGeneratorRequest}, + tool::generators::{ + passphrase::{passphrase, PassphraseGeneratorRequest}, + password::{password, PasswordGeneratorRequest}, + }, Client, }; diff --git a/crates/bitwarden/src/tool/generators/passphrase.rs b/crates/bitwarden/src/tool/generators/passphrase.rs index e62fa8f9a..005d00493 100644 --- a/crates/bitwarden/src/tool/generators/passphrase.rs +++ b/crates/bitwarden/src/tool/generators/passphrase.rs @@ -1,10 +1,11 @@ +use rand::{seq::SliceRandom, Rng, RngCore}; +use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; + use crate::{ error::{Error, Result}, wordlist::EFF_LONG_WORD_LIST, }; -use rand::{seq::SliceRandom, Rng, RngCore}; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; /// Passphrase generator request options. #[derive(Serialize, Deserialize, Debug, JsonSchema)] diff --git a/crates/bitwarden/src/uniffi_support.rs b/crates/bitwarden/src/uniffi_support.rs index 701f142b9..65f4cc491 100644 --- a/crates/bitwarden/src/uniffi_support.rs +++ b/crates/bitwarden/src/uniffi_support.rs @@ -1,8 +1,9 @@ use std::{num::NonZeroU32, str::FromStr}; +use bitwarden_crypto::EncString; use uuid::Uuid; -use crate::{crypto::EncString, error::Error, UniffiCustomTypeConverter}; +use crate::{error::Error, UniffiCustomTypeConverter}; uniffi::custom_type!(NonZeroU32, u32); diff --git a/crates/bitwarden/src/vault/cipher/attachment.rs b/crates/bitwarden/src/vault/cipher/attachment.rs index 4cb78be13..f1503d6e4 100644 --- a/crates/bitwarden/src/vault/cipher/attachment.rs +++ b/crates/bitwarden/src/vault/cipher/attachment.rs @@ -1,12 +1,7 @@ -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; +use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable}, - error::Result, -}; - #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] @@ -33,7 +28,7 @@ pub struct AttachmentView { } impl KeyEncryptable for AttachmentView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(Attachment { id: self.id, url: self.url, @@ -46,7 +41,10 @@ impl KeyEncryptable for AttachmentView { } impl KeyDecryptable for Attachment { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key( + &self, + key: &SymmetricCryptoKey, + ) -> bitwarden_crypto::Result { Ok(AttachmentView { id: self.id.clone(), url: self.url.clone(), diff --git a/crates/bitwarden/src/vault/cipher/card.rs b/crates/bitwarden/src/vault/cipher/card.rs index 62c1e9c35..f0620de59 100644 --- a/crates/bitwarden/src/vault/cipher/card.rs +++ b/crates/bitwarden/src/vault/cipher/card.rs @@ -1,12 +1,7 @@ -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; +use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable}, - error::Result, -}; - #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] @@ -32,7 +27,7 @@ pub struct CardView { } impl KeyEncryptable for CardView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(Card { cardholder_name: self.cardholder_name.encrypt_with_key(key)?, exp_month: self.exp_month.encrypt_with_key(key)?, @@ -45,7 +40,7 @@ impl KeyEncryptable for CardView { } impl KeyDecryptable for Card { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(CardView { cardholder_name: self.cardholder_name.decrypt_with_key(key)?, exp_month: self.exp_month.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index 0d6803ed8..176f79078 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -1,4 +1,6 @@ -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; +use bitwarden_crypto::{ + EncString, KeyContainer, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey, +}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -10,12 +12,7 @@ use super::{ local_data::{LocalData, LocalDataView}, login, secure_note, }; -use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey}, - error::Result, - vault::password_history, -}; +use crate::vault::password_history; #[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema)] #[repr(u8)] @@ -136,7 +133,7 @@ pub struct CipherListView { } impl KeyEncryptable for CipherView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; let key = ciphers_key.as_ref().unwrap_or(key); @@ -170,7 +167,7 @@ impl KeyEncryptable for CipherView { } impl KeyDecryptable for Cipher { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; let key = ciphers_key.as_ref().unwrap_or(key); @@ -211,7 +208,7 @@ impl Cipher { fn get_cipher_key( key: &SymmetricCryptoKey, ciphers_key: &Option, - ) -> Result> { + ) -> bitwarden_crypto::Result> { ciphers_key .as_ref() .map(|k| { @@ -221,7 +218,7 @@ impl Cipher { .transpose() } - fn get_decrypted_subtitle(&self, key: &SymmetricCryptoKey) -> Result { + fn get_decrypted_subtitle(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(match self.r#type { CipherType::Login => { let Some(login) = &self.login else { @@ -287,7 +284,10 @@ impl Cipher { } impl KeyDecryptable for Cipher { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key( + &self, + key: &SymmetricCryptoKey, + ) -> bitwarden_crypto::Result { let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; let key = ciphers_key.as_ref().unwrap_or(key); @@ -318,7 +318,7 @@ impl KeyDecryptable for Cipher { impl LocateKey for Cipher { fn locate_key<'a>( &self, - enc: &'a EncryptionSettings, + enc: &'a dyn KeyContainer, _: &Option, ) -> Option<&'a SymmetricCryptoKey> { enc.get_key(&self.organization_id) @@ -327,7 +327,7 @@ impl LocateKey for Cipher { impl LocateKey for CipherView { fn locate_key<'a>( &self, - enc: &'a EncryptionSettings, + enc: &'a dyn KeyContainer, _: &Option, ) -> Option<&'a SymmetricCryptoKey> { enc.get_key(&self.organization_id) diff --git a/crates/bitwarden/src/vault/cipher/field.rs b/crates/bitwarden/src/vault/cipher/field.rs index e5583a52a..75b9a3c5b 100644 --- a/crates/bitwarden/src/vault/cipher/field.rs +++ b/crates/bitwarden/src/vault/cipher/field.rs @@ -1,13 +1,9 @@ -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; +use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; use super::linked_id::LinkedIdType; -use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable}, - error::Result, -}; #[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema)] #[repr(u8)] @@ -42,7 +38,7 @@ pub struct FieldView { } impl KeyEncryptable for FieldView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(Field { name: self.name.encrypt_with_key(key)?, value: self.value.encrypt_with_key(key)?, @@ -53,7 +49,7 @@ impl KeyEncryptable for FieldView { } impl KeyDecryptable for Field { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(FieldView { name: self.name.decrypt_with_key(key)?, value: self.value.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/cipher/identity.rs b/crates/bitwarden/src/vault/cipher/identity.rs index 4485325be..90af45f0e 100644 --- a/crates/bitwarden/src/vault/cipher/identity.rs +++ b/crates/bitwarden/src/vault/cipher/identity.rs @@ -1,12 +1,7 @@ -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; +use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable}, - error::Result, -}; - #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] @@ -56,7 +51,7 @@ pub struct IdentityView { } impl KeyEncryptable for IdentityView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(Identity { title: self.title.encrypt_with_key(key)?, first_name: self.first_name.encrypt_with_key(key)?, @@ -81,7 +76,7 @@ impl KeyEncryptable for IdentityView { } impl KeyDecryptable for Identity { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(IdentityView { title: self.title.decrypt_with_key(key)?, first_name: self.first_name.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/cipher/local_data.rs b/crates/bitwarden/src/vault/cipher/local_data.rs index db912122f..b0d5a04e5 100644 --- a/crates/bitwarden/src/vault/cipher/local_data.rs +++ b/crates/bitwarden/src/vault/cipher/local_data.rs @@ -1,12 +1,7 @@ -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; +use bitwarden_crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{ - crypto::{KeyDecryptable, KeyEncryptable}, - error::Result, -}; - #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] @@ -24,7 +19,7 @@ pub struct LocalDataView { } impl KeyEncryptable for LocalDataView { - fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(LocalData { last_used_date: self.last_used_date, last_launched: self.last_launched, @@ -33,7 +28,10 @@ impl KeyEncryptable for LocalDataView { } impl KeyDecryptable for LocalData { - fn decrypt_with_key(&self, _key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key( + &self, + _key: &SymmetricCryptoKey, + ) -> bitwarden_crypto::Result { Ok(LocalDataView { last_used_date: self.last_used_date, last_launched: self.last_launched, diff --git a/crates/bitwarden/src/vault/cipher/login.rs b/crates/bitwarden/src/vault/cipher/login.rs index dcdfb0284..763ee9c9c 100644 --- a/crates/bitwarden/src/vault/cipher/login.rs +++ b/crates/bitwarden/src/vault/cipher/login.rs @@ -1,14 +1,9 @@ -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; +use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable}, - error::Result, -}; - #[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema)] #[repr(u8)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -65,7 +60,7 @@ pub struct LoginView { } impl KeyEncryptable for LoginUriView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(LoginUri { uri: self.uri.encrypt_with_key(key)?, r#match: self.r#match, @@ -74,7 +69,7 @@ impl KeyEncryptable for LoginUriView { } impl KeyEncryptable for LoginView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(Login { username: self.username.encrypt_with_key(key)?, password: self.password.encrypt_with_key(key)?, @@ -87,7 +82,7 @@ impl KeyEncryptable for LoginView { } impl KeyDecryptable for LoginUri { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(LoginUriView { uri: self.uri.decrypt_with_key(key)?, r#match: self.r#match, @@ -96,7 +91,7 @@ impl KeyDecryptable for LoginUri { } impl KeyDecryptable for Login { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(LoginView { username: self.username.decrypt_with_key(key)?, password: self.password.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/cipher/secure_note.rs b/crates/bitwarden/src/vault/cipher/secure_note.rs index 2a06494ff..22c3c1058 100644 --- a/crates/bitwarden/src/vault/cipher/secure_note.rs +++ b/crates/bitwarden/src/vault/cipher/secure_note.rs @@ -1,13 +1,8 @@ -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; +use bitwarden_crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; -use crate::{ - crypto::{KeyDecryptable, KeyEncryptable}, - error::Result, -}; - #[derive(Clone, Copy, Serialize_repr, Deserialize_repr, Debug, JsonSchema)] #[repr(u8)] #[cfg_attr(feature = "mobile", derive(uniffi::Enum))] @@ -30,7 +25,7 @@ pub struct SecureNoteView { } impl KeyEncryptable for SecureNoteView { - fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(SecureNote { r#type: self.r#type, }) @@ -38,7 +33,10 @@ impl KeyEncryptable for SecureNoteView { } impl KeyDecryptable for SecureNote { - fn decrypt_with_key(&self, _key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key( + &self, + _key: &SymmetricCryptoKey, + ) -> bitwarden_crypto::Result { Ok(SecureNoteView { r#type: self.r#type, }) diff --git a/crates/bitwarden/src/vault/collection.rs b/crates/bitwarden/src/vault/collection.rs index 0eaa58ae9..0f0e89cfb 100644 --- a/crates/bitwarden/src/vault/collection.rs +++ b/crates/bitwarden/src/vault/collection.rs @@ -1,14 +1,8 @@ -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; +use bitwarden_crypto::{EncString, KeyContainer, KeyDecryptable, LocateKey, SymmetricCryptoKey}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; -use crate::{ - client::encryption_settings::EncryptionSettings, - crypto::{EncString, KeyDecryptable, LocateKey}, - error::Result, -}; - #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] @@ -40,14 +34,17 @@ pub struct CollectionView { impl LocateKey for Collection { fn locate_key<'a>( &self, - enc: &'a EncryptionSettings, + enc: &'a dyn KeyContainer, _: &Option, ) -> Option<&'a SymmetricCryptoKey> { enc.get_key(&Some(self.organization_id)) } } impl KeyDecryptable for Collection { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key( + &self, + key: &SymmetricCryptoKey, + ) -> bitwarden_crypto::Result { Ok(CollectionView { id: self.id, organization_id: self.organization_id, diff --git a/crates/bitwarden/src/vault/folder.rs b/crates/bitwarden/src/vault/folder.rs index 582c25770..b0ccef2ce 100644 --- a/crates/bitwarden/src/vault/folder.rs +++ b/crates/bitwarden/src/vault/folder.rs @@ -1,14 +1,9 @@ -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; +use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; -use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey}, - error::Result, -}; - #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase")] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] @@ -29,7 +24,7 @@ pub struct FolderView { impl LocateKey for FolderView {} impl KeyEncryptable for FolderView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(Folder { id: self.id, name: self.name.encrypt_with_key(key)?, @@ -40,7 +35,7 @@ impl KeyEncryptable for FolderView { impl LocateKey for Folder {} impl KeyDecryptable for Folder { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(FolderView { id: self.id, name: self.name.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/password_history.rs b/crates/bitwarden/src/vault/password_history.rs index ecc1cb585..ea8e3c952 100644 --- a/crates/bitwarden/src/vault/password_history.rs +++ b/crates/bitwarden/src/vault/password_history.rs @@ -1,13 +1,8 @@ -use bitwarden_crypto::symmetric_crypto_key::SymmetricCryptoKey; +use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey}, - error::Result, -}; - #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] @@ -26,7 +21,10 @@ pub struct PasswordHistoryView { impl LocateKey for PasswordHistoryView {} impl KeyEncryptable for PasswordHistoryView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key( + self, + key: &SymmetricCryptoKey, + ) -> bitwarden_crypto::Result { Ok(PasswordHistory { password: self.password.encrypt_with_key(key)?, last_used_date: self.last_used_date, @@ -36,7 +34,10 @@ impl KeyEncryptable for PasswordHistoryView { impl LocateKey for PasswordHistory {} impl KeyDecryptable for PasswordHistory { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key( + &self, + key: &SymmetricCryptoKey, + ) -> bitwarden_crypto::Result { Ok(PasswordHistoryView { password: self.password.decrypt_with_key(key)?, last_used_date: self.last_used_date, diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index d69175b56..a5198b694 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -1,5 +1,5 @@ use bitwarden_crypto::{ - shareable_key::derive_shareable_key, symmetric_crypto_key::SymmetricCryptoKey, + derive_shareable_key, EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey, }; use chrono::{DateTime, Utc}; use schemars::JsonSchema; @@ -7,11 +7,6 @@ use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; use uuid::Uuid; -use crate::{ - crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey}, - error::Result, -}; - #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] @@ -131,7 +126,7 @@ impl Send { pub(crate) fn get_key( send_key: &EncString, enc_key: &SymmetricCryptoKey, - ) -> Result { + ) -> bitwarden_crypto::Result { let key: Vec = send_key.decrypt_with_key(enc_key)?; let key = derive_shareable_key(key.try_into().unwrap(), "send", Some("send")); Ok(key) @@ -139,7 +134,7 @@ impl Send { } impl KeyDecryptable for SendText { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(SendTextView { text: self.text.decrypt_with_key(key)?, hidden: self.hidden, @@ -148,7 +143,7 @@ impl KeyDecryptable for SendText { } impl KeyEncryptable for SendTextView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(SendText { text: self.text.encrypt_with_key(key)?, hidden: self.hidden, @@ -157,7 +152,7 @@ impl KeyEncryptable for SendTextView { } impl KeyDecryptable for SendFile { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(SendFileView { id: self.id.clone(), file_name: self.file_name.decrypt_with_key(key)?, @@ -168,7 +163,7 @@ impl KeyDecryptable for SendFile { } impl KeyEncryptable for SendFileView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { Ok(SendFile { id: self.id.clone(), file_name: self.file_name.encrypt_with_key(key)?, @@ -180,7 +175,7 @@ impl KeyEncryptable for SendFileView { impl LocateKey for Send {} impl KeyDecryptable for Send { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key let key = Send::get_key(&self.key, key)?; @@ -211,7 +206,7 @@ impl KeyDecryptable for Send { } impl KeyDecryptable for Send { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key let key = Send::get_key(&self.key, key)?; @@ -234,7 +229,7 @@ impl KeyDecryptable for Send { impl LocateKey for SendView {} impl KeyEncryptable for SendView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key let key = Send::get_key(&self.key, key)?; diff --git a/crates/bitwarden/src/vault/totp.rs b/crates/bitwarden/src/vault/totp.rs index e080a85a9..b8ef1e2fd 100644 --- a/crates/bitwarden/src/vault/totp.rs +++ b/crates/bitwarden/src/vault/totp.rs @@ -1,6 +1,5 @@ use std::{collections::HashMap, str::FromStr}; -use crate::error::{Error, Result}; use chrono::{DateTime, Utc}; use data_encoding::BASE32; use hmac::{Hmac, Mac}; @@ -8,6 +7,8 @@ use reqwest::Url; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use crate::error::{Error, Result}; + type HmacSha1 = Hmac; type HmacSha256 = Hmac; type HmacSha512 = Hmac; @@ -213,9 +214,10 @@ fn derive_binary(hash: Vec) -> u32 { #[cfg(test)] mod tests { - use super::*; use chrono::Utc; + use super::*; + #[test] fn test_generate_totp() { let key = "WQIQ25BRKZYCJVYP".to_string(); From 7e0b3925dcac64a8ae4f8b16fb9e165d69b74ffe Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 4 Jan 2024 11:06:34 +0100 Subject: [PATCH 03/30] Move remaining files, improve docs --- crates/bitwarden-crypto/Cargo.toml | 1 - crates/bitwarden-crypto/src/aes.rs | 12 +-- .../src/enc_string/asymmetric.rs | 15 +--- crates/bitwarden-crypto/src/enc_string/mod.rs | 11 +-- .../src/enc_string/symmetric.rs | 17 +---- crates/bitwarden-crypto/src/error.rs | 7 +- crates/bitwarden-crypto/src/fingerprint.rs | 6 ++ .../src/{ => keys}/key_encryptable.rs | 2 +- .../src/{ => keys}/master_key.rs | 14 ++-- crates/bitwarden-crypto/src/keys/mod.rs | 14 ++++ .../src/{ => keys}/shareable_key.rs | 2 +- .../src/{ => keys}/symmetric_crypto_key.rs | 13 ++-- .../src/{ => keys}/user_key.rs | 0 crates/bitwarden-crypto/src/lib.rs | 74 ++++++------------- crates/bitwarden-crypto/src/rsa.rs | 11 ++- crates/bitwarden-crypto/src/util.rs | 31 +++++++- crates/bitwarden-crypto/src/wordlist.rs | 1 - crates/bitwarden/Cargo.toml | 2 +- crates/bitwarden/src/auth/mod.rs | 5 +- crates/bitwarden/src/auth/register.rs | 2 +- crates/bitwarden/src/client/client.rs | 11 +-- .../src/client/encryption_settings.rs | 5 +- crates/bitwarden/src/client/kdf.rs | 15 +++- crates/bitwarden/src/secrets_manager/state.rs | 3 +- .../bitwarden/src/tool/generators/username.rs | 6 +- crates/bitwarden/src/vault/cipher/card.rs | 3 +- crates/bitwarden/src/vault/cipher/identity.rs | 3 +- 27 files changed, 143 insertions(+), 143 deletions(-) rename crates/bitwarden-crypto/src/{ => keys}/key_encryptable.rs (97%) rename crates/bitwarden-crypto/src/{ => keys}/master_key.rs (97%) create mode 100644 crates/bitwarden-crypto/src/keys/mod.rs rename crates/bitwarden-crypto/src/{ => keys}/shareable_key.rs (95%) rename crates/bitwarden-crypto/src/{ => keys}/symmetric_crypto_key.rs (89%) rename crates/bitwarden-crypto/src/{ => keys}/user_key.rs (100%) diff --git a/crates/bitwarden-crypto/Cargo.toml b/crates/bitwarden-crypto/Cargo.toml index 5d97107d6..38b2b00d3 100644 --- a/crates/bitwarden-crypto/Cargo.toml +++ b/crates/bitwarden-crypto/Cargo.toml @@ -15,7 +15,6 @@ rust-version = "1.57" [features] default = [] -internal = [] mobile = ["uniffi"] [dependencies] diff --git a/crates/bitwarden-crypto/src/aes.rs b/crates/bitwarden-crypto/src/aes.rs index 3c0edfdef..cb4bf3102 100644 --- a/crates/bitwarden-crypto/src/aes.rs +++ b/crates/bitwarden-crypto/src/aes.rs @@ -2,11 +2,8 @@ //! //! Contains low level AES operations used by the rest of the library. //! -//! **Warning**: Consider carefully if you have to use these functions directly, as generally we -//! expose higher level functions that are easier to use and more secure. -//! -//! In most cases you should use the [EncString] with [KeyEncryptable][super::KeyEncryptable] & -//! [KeyDecryptable][super::KeyDecryptable] instead. +//! In most cases you should use the [EncString][crate::EncString] with +//! [KeyEncryptable][crate::KeyEncryptable] & [KeyDecryptable][crate::KeyDecryptable] instead. use aes::cipher::{ block_padding::Pkcs7, generic_array::GenericArray, typenum::U32, BlockDecryptMut, @@ -126,11 +123,10 @@ fn generate_mac(mac_key: &[u8], iv: &[u8], data: &[u8]) -> Result<[u8; 32]> { #[cfg(test)] mod tests { use aes::cipher::generic_array::sequence::GenericSequence; - use base64::Engine; + use base64::{engine::general_purpose::STANDARD, Engine}; use rand::SeedableRng; use super::*; - use crate::BASE64_ENGINE; /// Helper function for generating a `GenericArray` of size 32 with each element being /// a multiple of a given increment, starting from a given offset. @@ -178,7 +174,7 @@ mod tests { let iv = generate_vec(16, 0, 1); let iv: &[u8; 16] = iv.as_slice().try_into().unwrap(); let key = generate_generic_array(0, 1); - let data = BASE64_ENGINE.decode("ByUF8vhyX4ddU9gcooznwA==").unwrap(); + let data = STANDARD.decode("ByUF8vhyX4ddU9gcooznwA==").unwrap(); let decrypted = decrypt_aes256(iv, data, key).unwrap(); diff --git a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs index 20d07d097..eea16d865 100644 --- a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs @@ -1,17 +1,15 @@ use std::{fmt::Display, str::FromStr}; -use base64::Engine; -#[cfg(feature = "internal")] +use base64::{engine::general_purpose::STANDARD, Engine}; use rsa::{Oaep, RsaPrivateKey}; use serde::Deserialize; +use super::{from_b64_vec, split_enc_string}; use crate::{ error::{EncStringParseError, Result}, - CryptoError, BASE64_ENGINE, + CryptoError, }; -use super::{from_b64_vec, split_enc_string}; - /// # Encrypted string primitive /// /// [AsymmEncString] is a Bitwarden specific primitive that represents an asymmetrically encrypted string. They are @@ -103,7 +101,6 @@ impl FromStr for AsymmEncString { #[allow(unused)] impl AsymmEncString { /// TODO: Convert this to a trait method - #[cfg(feature = "internal")] pub fn decrypt(&self, key: &RsaPrivateKey) -> Result> { match self { Self::Rsa2048_OaepSha256_B64 { data } => key.decrypt(Oaep::new::(), data), @@ -132,10 +129,7 @@ impl Display for AsymmEncString { AsymmEncString::Rsa2048_OaepSha1_HmacSha256_B64 { data, mac } => vec![data, mac], }; - let encoded_parts: Vec = parts - .iter() - .map(|part| BASE64_ENGINE.encode(part)) - .collect(); + let encoded_parts: Vec = parts.iter().map(|part| STANDARD.encode(part)).collect(); write!(f, "{}.{}", self.enc_type(), encoded_parts.join("|"))?; @@ -191,7 +185,6 @@ impl schemars::JsonSchema for AsymmEncString { mod tests { use super::AsymmEncString; - #[cfg(feature = "internal")] #[test] fn test_enc_string_rsa2048_oaep_sha1_hmac_sha256_b64() { use rsa::{pkcs8::DecodePrivateKey, RsaPrivateKey}; diff --git a/crates/bitwarden-crypto/src/enc_string/mod.rs b/crates/bitwarden-crypto/src/enc_string/mod.rs index df8672d52..740e9589d 100644 --- a/crates/bitwarden-crypto/src/enc_string/mod.rs +++ b/crates/bitwarden-crypto/src/enc_string/mod.rs @@ -1,18 +1,15 @@ +/// Encrypted string types mod asymmetric; mod symmetric; use std::str::FromStr; pub use asymmetric::AsymmEncString; -use base64::Engine; +use base64::{engine::general_purpose::STANDARD, Engine}; pub use symmetric::EncString; -use crate::{ - error::{EncStringParseError, Result}, - BASE64_ENGINE, -}; +use crate::error::{EncStringParseError, Result}; -#[cfg(feature = "mobile")] fn check_length(buf: &[u8], expected: usize) -> Result<()> { if buf.len() < expected { return Err(EncStringParseError::InvalidLength { @@ -25,7 +22,7 @@ fn check_length(buf: &[u8], expected: usize) -> Result<()> { } fn from_b64_vec(s: &str) -> Result> { - Ok(BASE64_ENGINE + Ok(STANDARD .decode(s) .map_err(EncStringParseError::InvalidBase64)?) } diff --git a/crates/bitwarden-crypto/src/enc_string/symmetric.rs b/crates/bitwarden-crypto/src/enc_string/symmetric.rs index cce04be9b..120ba46ce 100644 --- a/crates/bitwarden-crypto/src/enc_string/symmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/symmetric.rs @@ -1,18 +1,15 @@ use std::{fmt::Display, str::FromStr}; use aes::cipher::{generic_array::GenericArray, typenum::U32}; -use base64::Engine; +use base64::{engine::general_purpose::STANDARD, Engine}; use serde::Deserialize; +use super::{check_length, from_b64, from_b64_vec, split_enc_string}; use crate::{ error::EncStringParseError, CryptoError, KeyDecryptable, KeyEncryptable, LocateKey, Result, - SymmetricCryptoKey, BASE64_ENGINE, + SymmetricCryptoKey, }; -#[cfg(feature = "mobile")] -use super::check_length; -use super::{from_b64, from_b64_vec, split_enc_string}; - /// # Encrypted string primitive /// /// [EncString] is a Bitwarden specific primitive that represents a symmetrically encrypted string. They are @@ -108,12 +105,10 @@ impl FromStr for EncString { impl EncString { /// Synthetic sugar for mapping `Option` to `Result>` - #[cfg(feature = "internal")] pub fn try_from_optional(s: Option) -> Result, CryptoError> { s.map(|s| s.parse()).transpose() } - #[cfg(feature = "mobile")] pub fn from_buffer(buf: &[u8]) -> Result { if buf.is_empty() { return Err(EncStringParseError::NoType.into()); @@ -180,10 +175,7 @@ impl Display for EncString { EncString::AesCbc256_HmacSha256_B64 { iv, mac, data } => vec![iv, data, mac], }; - let encoded_parts: Vec = parts - .iter() - .map(|part| BASE64_ENGINE.encode(part)) - .collect(); + let encoded_parts: Vec = parts.iter().map(|part| STANDARD.encode(part)).collect(); write!(f, "{}.{}", self.enc_type(), encoded_parts.join("|"))?; @@ -306,7 +298,6 @@ mod tests { assert_eq!(serde_json::to_string(&t).unwrap(), serialized); } - #[cfg(feature = "mobile")] #[test] fn test_enc_from_to_buffer() { let enc_str: &str = "2.pMS6/icTQABtulw52pq2lg==|XXbxKxDTh+mWiN1HjH2N1w==|Q6PkuT+KX/axrgN9ubD5Ajk2YNwxQkgs3WJM0S0wtG8="; diff --git a/crates/bitwarden-crypto/src/error.rs b/crates/bitwarden-crypto/src/error.rs index f69340fe2..d310c2355 100644 --- a/crates/bitwarden-crypto/src/error.rs +++ b/crates/bitwarden-crypto/src/error.rs @@ -2,7 +2,6 @@ use std::fmt::Debug; use thiserror::Error; -#[cfg(feature = "internal")] use crate::fingerprint::FingerprintError; #[derive(Debug, Error)] @@ -15,8 +14,6 @@ pub enum CryptoError { KeyDecrypt, #[error("The cipher key has an invalid length")] InvalidKeyLen, - #[error("There is no encryption key for the provided organization")] - NoKeyForOrg, #[error("The value is not a valid UTF8 String")] InvalidUtf8String, #[error("Missing Key")] @@ -31,7 +28,6 @@ pub enum CryptoError { #[error("Rsa error, {0}")] RsaError(#[from] RsaError), - #[cfg(feature = "internal")] #[error("Fingerprint error, {0}")] FingerprintError(#[from] FingerprintError), @@ -61,4 +57,5 @@ pub enum RsaError { CreatePrivateKey, } -pub type Result = std::result::Result; +/// Alias for `Result`. +pub(crate) type Result = std::result::Result; diff --git a/crates/bitwarden-crypto/src/fingerprint.rs b/crates/bitwarden-crypto/src/fingerprint.rs index 4cbe4ed05..2e67e3d8a 100644 --- a/crates/bitwarden-crypto/src/fingerprint.rs +++ b/crates/bitwarden-crypto/src/fingerprint.rs @@ -1,3 +1,9 @@ +//! # Fingerprint +//! +//! Provides a way to derive fingerprints from fingerprint material and public keys. This is most +//! commonly used for account fingerprints, where the fingerprint material is the user's id and the +//! public key is the user's public key. + use num_bigint::BigUint; use num_traits::cast::ToPrimitive; use sha2::Digest; diff --git a/crates/bitwarden-crypto/src/key_encryptable.rs b/crates/bitwarden-crypto/src/keys/key_encryptable.rs similarity index 97% rename from crates/bitwarden-crypto/src/key_encryptable.rs rename to crates/bitwarden-crypto/src/keys/key_encryptable.rs index bd36268fc..e05fd85a6 100644 --- a/crates/bitwarden-crypto/src/key_encryptable.rs +++ b/crates/bitwarden-crypto/src/keys/key_encryptable.rs @@ -1,6 +1,6 @@ use std::{collections::HashMap, hash::Hash}; -use crate::{error::Result, symmetric_crypto_key::SymmetricCryptoKey}; +use crate::{error::Result, keys::SymmetricCryptoKey}; pub trait KeyEncryptable { fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result; diff --git a/crates/bitwarden-crypto/src/master_key.rs b/crates/bitwarden-crypto/src/keys/master_key.rs similarity index 97% rename from crates/bitwarden-crypto/src/master_key.rs rename to crates/bitwarden-crypto/src/keys/master_key.rs index c61e0a1e1..36f1e2640 100644 --- a/crates/bitwarden-crypto/src/master_key.rs +++ b/crates/bitwarden-crypto/src/keys/master_key.rs @@ -1,14 +1,15 @@ use std::num::NonZeroU32; use aes::cipher::{generic_array::GenericArray, typenum::U32}; -use base64::Engine; +use base64::{engine::general_purpose::STANDARD, Engine}; use rand::Rng; use schemars::JsonSchema; use sha2::Digest; -use crate::{EncString, KeyDecryptable, Result, SymmetricCryptoKey, UserKey, BASE64_ENGINE}; - -use crate::util::{hkdf_expand, PbkdfSha256Hmac, PBKDF_SHA256_HMAC_OUT_SIZE}; +use crate::{ + util::{hkdf_expand, PbkdfSha256Hmac, PBKDF_SHA256_HMAC_OUT_SIZE}, + EncString, KeyDecryptable, Result, SymmetricCryptoKey, UserKey, +}; #[derive(Debug, Clone)] pub enum Kdf { @@ -47,7 +48,7 @@ impl MasterKey { ) .expect("hash is a valid fixed size"); - Ok(BASE64_ENGINE.encode(hash)) + Ok(STANDARD.encode(hash)) } pub fn make_user_key(&self) -> Result<(UserKey, EncString)> { @@ -141,9 +142,8 @@ mod tests { use rand::SeedableRng; - use crate::SymmetricCryptoKey; - use super::{make_user_key, stretch_master_key, HashPurpose, Kdf, MasterKey}; + use crate::SymmetricCryptoKey; #[test] fn test_master_key_derive_pbkdf2() { diff --git a/crates/bitwarden-crypto/src/keys/mod.rs b/crates/bitwarden-crypto/src/keys/mod.rs new file mode 100644 index 000000000..7210e98a6 --- /dev/null +++ b/crates/bitwarden-crypto/src/keys/mod.rs @@ -0,0 +1,14 @@ +mod key_encryptable; +pub use key_encryptable::{KeyDecryptable, KeyEncryptable}; + +mod master_key; +pub use master_key::{HashPurpose, Kdf, MasterKey}; + +mod shareable_key; +pub use shareable_key::derive_shareable_key; + +mod symmetric_crypto_key; +pub use symmetric_crypto_key::SymmetricCryptoKey; + +mod user_key; +pub use user_key::UserKey; diff --git a/crates/bitwarden-crypto/src/shareable_key.rs b/crates/bitwarden-crypto/src/keys/shareable_key.rs similarity index 95% rename from crates/bitwarden-crypto/src/shareable_key.rs rename to crates/bitwarden-crypto/src/keys/shareable_key.rs index 2cd75c630..a13f17155 100644 --- a/crates/bitwarden-crypto/src/shareable_key.rs +++ b/crates/bitwarden-crypto/src/keys/shareable_key.rs @@ -1,7 +1,7 @@ use aes::cipher::{generic_array::GenericArray, typenum::U64}; use hmac::{Hmac, Mac}; -use crate::{symmetric_crypto_key::SymmetricCryptoKey, util::hkdf_expand}; +use crate::{keys::SymmetricCryptoKey, util::hkdf_expand}; /// Derive a shareable key using hkdf from secret and name. /// diff --git a/crates/bitwarden-crypto/src/symmetric_crypto_key.rs b/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs similarity index 89% rename from crates/bitwarden-crypto/src/symmetric_crypto_key.rs rename to crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs index 3e881306e..6041b508e 100644 --- a/crates/bitwarden-crypto/src/symmetric_crypto_key.rs +++ b/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs @@ -1,11 +1,11 @@ use std::str::FromStr; use aes::cipher::{generic_array::GenericArray, typenum::U32}; -use base64::Engine; +use base64::{engine::general_purpose::STANDARD, Engine}; -use crate::{shareable_key::derive_shareable_key, CryptoError, BASE64_ENGINE}; +use crate::{keys::derive_shareable_key, CryptoError}; -/// A symmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::crypto::EncString) +/// A symmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::EncString) pub struct SymmetricCryptoKey { pub key: GenericArray, pub mac_key: Option>, @@ -29,10 +29,9 @@ impl SymmetricCryptoKey { buf.extend_from_slice(&mac); } - BASE64_ENGINE.encode(&buf) + STANDARD.encode(&buf) } - #[cfg(feature = "internal")] pub fn to_vec(&self) -> Vec { let mut buf = Vec::new(); buf.extend_from_slice(&self.key); @@ -47,9 +46,7 @@ impl FromStr for SymmetricCryptoKey { type Err = CryptoError; fn from_str(s: &str) -> Result { - let bytes = BASE64_ENGINE - .decode(s) - .map_err(|_| CryptoError::InvalidKey)?; + let bytes = STANDARD.decode(s).map_err(|_| CryptoError::InvalidKey)?; SymmetricCryptoKey::try_from(bytes.as_slice()) } } diff --git a/crates/bitwarden-crypto/src/user_key.rs b/crates/bitwarden-crypto/src/keys/user_key.rs similarity index 100% rename from crates/bitwarden-crypto/src/user_key.rs rename to crates/bitwarden-crypto/src/keys/user_key.rs diff --git a/crates/bitwarden-crypto/src/lib.rs b/crates/bitwarden-crypto/src/lib.rs index f490fa743..02131949c 100644 --- a/crates/bitwarden-crypto/src/lib.rs +++ b/crates/bitwarden-crypto/src/lib.rs @@ -1,76 +1,48 @@ //! # Bitwarden Cryptographic primitives //! -//! This module contains the cryptographic primitives used throughout the SDK. The module makes a -//! best effort to abstract away cryptographic concepts into concepts such as -//! [`EncString`] and [`SymmetricCryptoKey`]. +//! This crate contains the cryptographic primitives used throughout the SDK. The crate makes a +//! best effort to abstract away cryptographic concepts into concepts such as [`EncString`], +//! [`AsymmEncString`] and [`SymmetricCryptoKey`]. //! //! ## Conventions: //! //! - Pure Functions that deterministically "derive" keys from input are prefixed with `derive_`. -//! - Functions that generate new keys are prefixed with `make_`. +//! - Functions that generate non deterministically keys are prefixed with `make_`. //! -//! ## Differences from [`clients`](https://github.com/bitwarden/clients) +//! ## Differences from `clients` //! -//! There are some noteworthy differences compared to the other Bitwarden clients. These changes -//! are made in an effort to introduce conventions in how we name things, improve best practices -//! and abstracting away internal complexity. +//! There are some noteworthy differences compared to the other Bitwarden +//! [clients](https://github.com/bitwarden/clients). These changes are made in an effort to +//! introduce conventions in how we name things, improve best practices and abstracting away +//! internal complexity. //! //! - `CryptoService.makeSendKey` & `AccessService.createAccessToken` are replaced by the generic //! `derive_shareable_key` //! - MasterKey operations such as `makeMasterKey` and `hashMasterKey` are moved to the MasterKey //! struct. -use base64::{ - alphabet, - engine::{DecodePaddingMode, GeneralPurpose, GeneralPurposeConfig}, -}; - -#[cfg(feature = "mobile")] -uniffi::setup_scaffolding!(); - -pub mod aes; -mod error; -mod key_encryptable; -pub use key_encryptable::{KeyDecryptable, KeyEncryptable}; -mod shareable_key; -mod symmetric_crypto_key; -pub use error::{CryptoError, Result}; -pub use shareable_key::derive_shareable_key; -pub use symmetric_crypto_key::SymmetricCryptoKey; -mod encryptable; -pub use encryptable::{Decryptable, Encryptable, KeyContainer, LocateKey}; +mod aes; mod enc_string; pub use enc_string::{AsymmEncString, EncString}; -pub mod rsa; -mod user_key; -pub use user_key::UserKey; - +mod encryptable; +pub use encryptable::{Decryptable, Encryptable, KeyContainer, LocateKey}; +mod error; +pub use error::CryptoError; +pub(crate) use error::Result; +mod fingerprint; +pub use fingerprint::fingerprint; +mod keys; +pub use keys::*; +mod rsa; +pub use rsa::RsaKeyPair; mod util; - -#[cfg(feature = "internal")] mod wordlist; -#[cfg(feature = "internal")] pub use wordlist::EFF_LONG_WORD_LIST; -#[cfg(feature = "internal")] -mod fingerprint; -#[cfg(feature = "internal")] -pub use fingerprint::fingerprint; - -#[cfg(feature = "internal")] -mod master_key; -#[cfg(feature = "internal")] -pub use master_key::{HashPurpose, Kdf, MasterKey}; +#[cfg(feature = "mobile")] +uniffi::setup_scaffolding!(); #[cfg(feature = "mobile")] mod uniffi_support; #[cfg(feature = "mobile")] pub use uniffi_support::*; - -// TODO: Replace with standard base64 engine -const BASE64_ENGINE_CONFIG: GeneralPurposeConfig = GeneralPurposeConfig::new() - .with_encode_padding(true) - .with_decode_padding_mode(DecodePaddingMode::Indifferent); - -pub const BASE64_ENGINE: GeneralPurpose = - GeneralPurpose::new(&alphabet::STANDARD, BASE64_ENGINE_CONFIG); diff --git a/crates/bitwarden-crypto/src/rsa.rs b/crates/bitwarden-crypto/src/rsa.rs index b3d811eb0..ff665c247 100644 --- a/crates/bitwarden-crypto/src/rsa.rs +++ b/crates/bitwarden-crypto/src/rsa.rs @@ -1,4 +1,4 @@ -use base64::Engine; +use base64::{engine::general_purpose::STANDARD, Engine}; use rsa::{ pkcs8::{EncodePrivateKey, EncodePublicKey}, RsaPrivateKey, RsaPublicKey, @@ -6,9 +6,12 @@ use rsa::{ use crate::{ error::{Result, RsaError}, - EncString, SymmetricCryptoKey, BASE64_ENGINE, + EncString, SymmetricCryptoKey, }; +/// RSA Key Pair +/// +/// Consists of a public key and an encrypted private key. #[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct RsaKeyPair { /// Base64 encoded DER representation of the public key @@ -17,7 +20,7 @@ pub struct RsaKeyPair { pub private: EncString, } -pub fn make_key_pair(key: &SymmetricCryptoKey) -> Result { +pub(crate) fn make_key_pair(key: &SymmetricCryptoKey) -> Result { let mut rng = rand::thread_rng(); let bits = 2048; let priv_key = RsaPrivateKey::new(&mut rng, bits).expect("failed to generate a key"); @@ -27,7 +30,7 @@ pub fn make_key_pair(key: &SymmetricCryptoKey) -> Result { .to_public_key_der() .map_err(|_| RsaError::CreatePublicKey)?; - let b64 = BASE64_ENGINE.encode(spki.as_bytes()); + let b64 = STANDARD.encode(spki.as_bytes()); let pkcs = priv_key .to_pkcs8_der() .map_err(|_| RsaError::CreatePrivateKey)?; diff --git a/crates/bitwarden-crypto/src/util.rs b/crates/bitwarden-crypto/src/util.rs index c4c9fe641..8654f5a2f 100644 --- a/crates/bitwarden-crypto/src/util.rs +++ b/crates/bitwarden-crypto/src/util.rs @@ -1,12 +1,13 @@ -use crate::{CryptoError, Result}; use ::aes::cipher::{generic_array::GenericArray, ArrayLength, Unsigned}; use hmac::digest::OutputSizeUser; +use crate::{CryptoError, Result}; + pub(crate) type PbkdfSha256Hmac = hmac::Hmac; pub(crate) const PBKDF_SHA256_HMAC_OUT_SIZE: usize = <::OutputSize as Unsigned>::USIZE; -/// RFC5869 HKDF-Expand operation +/// [RFC5869](https://datatracker.ietf.org/doc/html/rfc5869) HKDF-Expand operation pub(crate) fn hkdf_expand>( prk: &[u8], info: Option<&str>, @@ -20,3 +21,29 @@ pub(crate) fn hkdf_expand>( Ok(key) } + +#[cfg(test)] +mod tests { + use super::*; + use aes::cipher::typenum::U64; + + #[test] + fn test_hkdf_expand() { + let prk = &[ + 23, 152, 120, 41, 214, 16, 156, 133, 71, 226, 178, 135, 208, 255, 66, 101, 189, 70, + 173, 30, 39, 215, 175, 236, 38, 180, 180, 62, 196, 4, 159, 70, + ]; + let info = Some("info"); + + let result: GenericArray = hkdf_expand(prk, info).unwrap(); + + let expected_output: [u8; 64] = [ + 6, 114, 42, 38, 87, 231, 30, 109, 30, 255, 104, 129, 255, 94, 92, 108, 124, 145, 215, + 208, 17, 60, 135, 22, 70, 158, 40, 53, 45, 182, 8, 63, 65, 87, 239, 234, 185, 227, 153, + 122, 115, 205, 144, 56, 102, 149, 92, 139, 217, 102, 119, 57, 37, 57, 251, 178, 18, 52, + 94, 77, 132, 215, 239, 100, + ]; + + assert_eq!(result.as_slice(), expected_output); + } +} diff --git a/crates/bitwarden-crypto/src/wordlist.rs b/crates/bitwarden-crypto/src/wordlist.rs index b0716d4af..4cc30ff74 100644 --- a/crates/bitwarden-crypto/src/wordlist.rs +++ b/crates/bitwarden-crypto/src/wordlist.rs @@ -1,5 +1,4 @@ // EFF's Long Wordlist from https://www.eff.org/dice -#[cfg(feature = "internal")] pub const EFF_LONG_WORD_LIST: &[&str] = &[ "abacus", "abdomen", diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index b64becbb7..b1395405e 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -16,7 +16,7 @@ rust-version = "1.57" default = ["secrets"] secrets = [] # Secrets manager API -internal = ["bitwarden-crypto/internal"] # Internal testing methods +internal = [] # Internal testing methods mobile = [ "uniffi", "internal", diff --git a/crates/bitwarden/src/auth/mod.rs b/crates/bitwarden/src/auth/mod.rs index 733e6700c..5e7690788 100644 --- a/crates/bitwarden/src/auth/mod.rs +++ b/crates/bitwarden/src/auth/mod.rs @@ -10,14 +10,13 @@ pub use jwt_token::JWTToken; #[cfg(feature = "internal")] mod register; #[cfg(feature = "internal")] +use bitwarden_crypto::{HashPurpose, MasterKey}; +#[cfg(feature = "internal")] pub use register::{RegisterKeyResponse, RegisterRequest}; #[cfg(feature = "internal")] use crate::{client::kdf::Kdf, error::Result}; -#[cfg(feature = "internal")] -use bitwarden_crypto::{HashPurpose, MasterKey}; - #[cfg(feature = "internal")] async fn determine_password_hash( email: &str, diff --git a/crates/bitwarden/src/auth/register.rs b/crates/bitwarden/src/auth/register.rs index 99ae51769..10e7e3632 100644 --- a/crates/bitwarden/src/auth/register.rs +++ b/crates/bitwarden/src/auth/register.rs @@ -2,7 +2,7 @@ use bitwarden_api_identity::{ apis::accounts_api::accounts_register_post, models::{KeysRequestModel, RegisterRequestModel}, }; -use bitwarden_crypto::{rsa::RsaKeyPair, HashPurpose, MasterKey}; +use bitwarden_crypto::{HashPurpose, MasterKey, RsaKeyPair}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index e6612657e..2f402a76f 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -1,16 +1,15 @@ -use bitwarden_crypto::SymmetricCryptoKey; use std::path::PathBuf; +use bitwarden_crypto::SymmetricCryptoKey; +#[cfg(feature = "internal")] +use bitwarden_crypto::{AsymmEncString, EncString}; use chrono::Utc; use reqwest::header::{self}; use uuid::Uuid; +use super::AccessToken; #[cfg(feature = "secrets")] use crate::auth::login::{AccessTokenLoginRequest, AccessTokenLoginResponse}; - -#[cfg(feature = "internal")] -use bitwarden_crypto::{AsymmEncString, EncString}; - #[cfg(feature = "internal")] use crate::{ client::kdf::Kdf, @@ -27,8 +26,6 @@ use crate::{ error::{Error, Result}, }; -use super::AccessToken; - #[derive(Debug)] pub(crate) struct ApiConfigurations { pub identity: bitwarden_api_identity::apis::configuration::Configuration, diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index 1cea84621..bd067397d 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -1,5 +1,7 @@ use std::collections::HashMap; +#[cfg(feature = "internal")] +use bitwarden_crypto::{AsymmEncString, EncString}; use bitwarden_crypto::{KeyContainer, SymmetricCryptoKey}; use rsa::RsaPrivateKey; use uuid::Uuid; @@ -12,9 +14,6 @@ use { rsa::pkcs8::DecodePrivateKey, }; -#[cfg(feature = "internal")] -use bitwarden_crypto::{AsymmEncString, EncString}; - pub struct EncryptionSettings { user_key: SymmetricCryptoKey, private_key: Option, diff --git a/crates/bitwarden/src/client/kdf.rs b/crates/bitwarden/src/client/kdf.rs index 4a18553d7..c76d82793 100644 --- a/crates/bitwarden/src/client/kdf.rs +++ b/crates/bitwarden/src/client/kdf.rs @@ -24,7 +24,20 @@ pub enum Kdf { impl From for bitwarden_crypto::Kdf { fn from(kdf: Kdf) -> Self { - kdf.into() + match kdf { + Kdf::PBKDF2 { iterations } => bitwarden_crypto::Kdf::PBKDF2 { + iterations: iterations.get(), + }, + Kdf::Argon2id { + iterations, + memory, + parallelism, + } => bitwarden_crypto::Kdf::Argon2id { + iterations: iterations.get(), + memory: memory.get(), + parallelism: parallelism.get(), + }, + } } } diff --git a/crates/bitwarden/src/secrets_manager/state.rs b/crates/bitwarden/src/secrets_manager/state.rs index 9d255024d..4efa4403b 100644 --- a/crates/bitwarden/src/secrets_manager/state.rs +++ b/crates/bitwarden/src/secrets_manager/state.rs @@ -1,3 +1,5 @@ +use std::{fmt::Debug, path::Path}; + use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable}; use serde::{Deserialize, Serialize}; @@ -5,7 +7,6 @@ use crate::{ client::AccessToken, error::{Error, Result}, }; -use std::{fmt::Debug, path::Path}; const STATE_VERSION: u32 = 1; diff --git a/crates/bitwarden/src/tool/generators/username.rs b/crates/bitwarden/src/tool/generators/username.rs index 0f544cd0a..20b101fa0 100644 --- a/crates/bitwarden/src/tool/generators/username.rs +++ b/crates/bitwarden/src/tool/generators/username.rs @@ -1,9 +1,10 @@ -use crate::{error::Result, util::capitalize_first_letter}; use bitwarden_crypto::EFF_LONG_WORD_LIST; use rand::{distributions::Distribution, seq::SliceRandom, Rng, RngCore}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use crate::{error::Result, util::capitalize_first_letter}; + #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Enum))] @@ -85,9 +86,10 @@ impl ForwarderServiceType { // Generate a username using the specified email forwarding service // This requires an HTTP client to be passed in, as the service will need to make API calls pub async fn generate(self, http: &reqwest::Client, website: Option) -> Result { - use crate::tool::generators::username_forwarders::*; use ForwarderServiceType::*; + use crate::tool::generators::username_forwarders::*; + match self { AddyIo { api_token, diff --git a/crates/bitwarden/src/vault/cipher/card.rs b/crates/bitwarden/src/vault/cipher/card.rs index 9c473149f..6c84e89f6 100644 --- a/crates/bitwarden/src/vault/cipher/card.rs +++ b/crates/bitwarden/src/vault/cipher/card.rs @@ -1,9 +1,8 @@ +use bitwarden_api_api::models::CipherCardModel; use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use bitwarden_api_api::models::CipherCardModel; - use crate::error::{Error, Result}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] diff --git a/crates/bitwarden/src/vault/cipher/identity.rs b/crates/bitwarden/src/vault/cipher/identity.rs index 88dc8b394..73c2ec7f8 100644 --- a/crates/bitwarden/src/vault/cipher/identity.rs +++ b/crates/bitwarden/src/vault/cipher/identity.rs @@ -1,9 +1,8 @@ +use bitwarden_api_api::models::CipherIdentityModel; use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use bitwarden_api_api::models::CipherIdentityModel; - use crate::error::{Error, Result}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] From 0af379f16bde8f96f6139fd93c05fcc869a961ba Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 4 Jan 2024 18:32:31 +0100 Subject: [PATCH 04/30] Fix build error --- crates/bitwarden-crypto/src/util.rs | 3 +- .../src/client/encryption_settings.rs | 7 ++-- crates/bitwarden/src/client/kdf.rs | 10 +++--- crates/bitwarden/src/error.rs | 35 ------------------- .../bitwarden/src/vault/cipher/attachment.rs | 11 +++--- crates/bitwarden/src/vault/cipher/card.rs | 8 +++-- crates/bitwarden/src/vault/cipher/cipher.rs | 16 ++++----- crates/bitwarden/src/vault/cipher/field.rs | 8 +++-- crates/bitwarden/src/vault/cipher/identity.rs | 8 +++-- .../bitwarden/src/vault/cipher/local_data.rs | 9 ++--- crates/bitwarden/src/vault/cipher/login.rs | 12 ++++--- .../bitwarden/src/vault/cipher/secure_note.rs | 9 ++--- crates/bitwarden/src/vault/collection.rs | 9 +++-- crates/bitwarden/src/vault/folder.rs | 8 +++-- .../bitwarden/src/vault/password_history.rs | 11 +++--- crates/bitwarden/src/vault/send.rs | 19 +++++----- 16 files changed, 72 insertions(+), 111 deletions(-) diff --git a/crates/bitwarden-crypto/src/util.rs b/crates/bitwarden-crypto/src/util.rs index 8654f5a2f..080c98aca 100644 --- a/crates/bitwarden-crypto/src/util.rs +++ b/crates/bitwarden-crypto/src/util.rs @@ -24,9 +24,10 @@ pub(crate) fn hkdf_expand>( #[cfg(test)] mod tests { - use super::*; use aes::cipher::typenum::U64; + use super::*; + #[test] fn test_hkdf_expand() { let prk = &[ diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index bd067397d..5b4f75c37 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -7,10 +7,7 @@ use rsa::RsaPrivateKey; use uuid::Uuid; #[cfg(feature = "internal")] use { - crate::{ - client::UserLoginMethod, - error::{CryptoError, Result}, - }, + crate::{client::UserLoginMethod, error::Result}, rsa::pkcs8::DecodePrivateKey, }; @@ -60,7 +57,7 @@ impl EncryptionSettings { user_key: SymmetricCryptoKey, private_key: EncString, ) -> Result { - use bitwarden_crypto::KeyDecryptable; + use bitwarden_crypto::{CryptoError, KeyDecryptable}; let private_key = { let dec: Vec = private_key.decrypt_with_key(&user_key)?; diff --git a/crates/bitwarden/src/client/kdf.rs b/crates/bitwarden/src/client/kdf.rs index c76d82793..ba7fd004a 100644 --- a/crates/bitwarden/src/client/kdf.rs +++ b/crates/bitwarden/src/client/kdf.rs @@ -25,17 +25,15 @@ pub enum Kdf { impl From for bitwarden_crypto::Kdf { fn from(kdf: Kdf) -> Self { match kdf { - Kdf::PBKDF2 { iterations } => bitwarden_crypto::Kdf::PBKDF2 { - iterations: iterations.get(), - }, + Kdf::PBKDF2 { iterations } => bitwarden_crypto::Kdf::PBKDF2 { iterations }, Kdf::Argon2id { iterations, memory, parallelism, } => bitwarden_crypto::Kdf::Argon2id { - iterations: iterations.get(), - memory: memory.get(), - parallelism: parallelism.get(), + iterations, + memory, + parallelism, }, } } diff --git a/crates/bitwarden/src/error.rs b/crates/bitwarden/src/error.rs index ef5a65318..c11913e6f 100644 --- a/crates/bitwarden/src/error.rs +++ b/crates/bitwarden/src/error.rs @@ -23,14 +23,9 @@ pub enum Error { #[error("The response received was missing some of the required fields")] MissingFields, - #[error("Cryptography error, {0}")] - Crypto(#[from] CryptoError), #[error("Cryptography error, {0}")] Crypto2(#[from] bitwarden_crypto::CryptoError), - #[error("Error parsing EncString: {0}")] - InvalidEncString(#[from] EncStringParseError), - #[error("Error parsing Identity response: {0}")] IdentityFail(crate::auth::api::response::IdentityTokenFailResponse), @@ -88,36 +83,6 @@ pub enum AccessTokenInvalidError { InvalidBase64Length { expected: usize, got: usize }, } -#[derive(Debug, Error)] -pub enum CryptoError { - #[error("The provided key is not the expected type")] - InvalidKey, - #[error("The cipher's MAC doesn't match the expected value")] - InvalidMac, - #[error("Error while decrypting EncString")] - KeyDecrypt, - #[error("The cipher key has an invalid length")] - InvalidKeyLen, - #[error("There is no encryption key for the provided organization")] - NoKeyForOrg, - #[error("The value is not a valid UTF8 String")] - InvalidUtf8String, -} - -#[derive(Debug, Error)] -pub enum EncStringParseError { - #[error("No type detected, missing '.' separator")] - NoType, - #[error("Invalid symmetric type, got type {enc_type} with {parts} parts")] - InvalidTypeSymm { enc_type: String, parts: usize }, - #[error("Invalid asymmetric type, got type {enc_type} with {parts} parts")] - InvalidTypeAsymm { enc_type: String, parts: usize }, - #[error("Error decoding base64: {0}")] - InvalidBase64(#[from] base64::DecodeError), - #[error("Invalid length: expected {expected}, got {got}")] - InvalidLength { expected: usize, got: usize }, -} - // Ensure that the error messages implement Send and Sync #[cfg(test)] const _: () = { diff --git a/crates/bitwarden/src/vault/cipher/attachment.rs b/crates/bitwarden/src/vault/cipher/attachment.rs index 51e05b3ec..fb153e447 100644 --- a/crates/bitwarden/src/vault/cipher/attachment.rs +++ b/crates/bitwarden/src/vault/cipher/attachment.rs @@ -1,4 +1,6 @@ -use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; +use bitwarden_crypto::{ + CryptoError, EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey, +}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -30,7 +32,7 @@ pub struct AttachmentView { } impl KeyEncryptable for AttachmentView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Attachment { id: self.id, url: self.url, @@ -43,10 +45,7 @@ impl KeyEncryptable for AttachmentView { } impl KeyDecryptable for Attachment { - fn decrypt_with_key( - &self, - key: &SymmetricCryptoKey, - ) -> bitwarden_crypto::Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(AttachmentView { id: self.id.clone(), url: self.url.clone(), diff --git a/crates/bitwarden/src/vault/cipher/card.rs b/crates/bitwarden/src/vault/cipher/card.rs index 6c84e89f6..062aeda89 100644 --- a/crates/bitwarden/src/vault/cipher/card.rs +++ b/crates/bitwarden/src/vault/cipher/card.rs @@ -1,5 +1,7 @@ use bitwarden_api_api::models::CipherCardModel; -use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; +use bitwarden_crypto::{ + CryptoError, EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey, +}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -30,7 +32,7 @@ pub struct CardView { } impl KeyEncryptable for CardView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Card { cardholder_name: self.cardholder_name.encrypt_with_key(key)?, exp_month: self.exp_month.encrypt_with_key(key)?, @@ -43,7 +45,7 @@ impl KeyEncryptable for CardView { } impl KeyDecryptable for Card { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(CardView { cardholder_name: self.cardholder_name.decrypt_with_key(key)?, exp_month: self.exp_month.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index 3adeeba4d..642933188 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -1,6 +1,7 @@ use bitwarden_api_api::models::CipherDetailsResponseModel; use bitwarden_crypto::{ - EncString, KeyContainer, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey, + CryptoError, EncString, KeyContainer, KeyDecryptable, KeyEncryptable, LocateKey, + SymmetricCryptoKey, }; use chrono::{DateTime, Utc}; use schemars::JsonSchema; @@ -137,7 +138,7 @@ pub struct CipherListView { } impl KeyEncryptable for CipherView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; let key = ciphers_key.as_ref().unwrap_or(key); @@ -171,7 +172,7 @@ impl KeyEncryptable for CipherView { } impl KeyDecryptable for Cipher { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; let key = ciphers_key.as_ref().unwrap_or(key); @@ -212,7 +213,7 @@ impl Cipher { fn get_cipher_key( key: &SymmetricCryptoKey, ciphers_key: &Option, - ) -> bitwarden_crypto::Result> { + ) -> Result, CryptoError> { ciphers_key .as_ref() .map(|k| { @@ -222,7 +223,7 @@ impl Cipher { .transpose() } - fn get_decrypted_subtitle(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn get_decrypted_subtitle(&self, key: &SymmetricCryptoKey) -> Result { Ok(match self.r#type { CipherType::Login => { let Some(login) = &self.login else { @@ -288,10 +289,7 @@ impl Cipher { } impl KeyDecryptable for Cipher { - fn decrypt_with_key( - &self, - key: &SymmetricCryptoKey, - ) -> bitwarden_crypto::Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { let ciphers_key = Cipher::get_cipher_key(key, &self.key)?; let key = ciphers_key.as_ref().unwrap_or(key); diff --git a/crates/bitwarden/src/vault/cipher/field.rs b/crates/bitwarden/src/vault/cipher/field.rs index 60192ee5e..fe52bb308 100644 --- a/crates/bitwarden/src/vault/cipher/field.rs +++ b/crates/bitwarden/src/vault/cipher/field.rs @@ -1,5 +1,7 @@ use bitwarden_api_api::models::CipherFieldModel; -use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; +use bitwarden_crypto::{ + CryptoError, EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey, +}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; @@ -40,7 +42,7 @@ pub struct FieldView { } impl KeyEncryptable for FieldView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Field { name: self.name.encrypt_with_key(key)?, value: self.value.encrypt_with_key(key)?, @@ -51,7 +53,7 @@ impl KeyEncryptable for FieldView { } impl KeyDecryptable for Field { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(FieldView { name: self.name.decrypt_with_key(key)?, value: self.value.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/cipher/identity.rs b/crates/bitwarden/src/vault/cipher/identity.rs index 73c2ec7f8..715cebc97 100644 --- a/crates/bitwarden/src/vault/cipher/identity.rs +++ b/crates/bitwarden/src/vault/cipher/identity.rs @@ -1,5 +1,7 @@ use bitwarden_api_api::models::CipherIdentityModel; -use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; +use bitwarden_crypto::{ + CryptoError, EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey, +}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -54,7 +56,7 @@ pub struct IdentityView { } impl KeyEncryptable for IdentityView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Identity { title: self.title.encrypt_with_key(key)?, first_name: self.first_name.encrypt_with_key(key)?, @@ -79,7 +81,7 @@ impl KeyEncryptable for IdentityView { } impl KeyDecryptable for Identity { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(IdentityView { title: self.title.decrypt_with_key(key)?, first_name: self.first_name.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/cipher/local_data.rs b/crates/bitwarden/src/vault/cipher/local_data.rs index b0d5a04e5..61aab9a3a 100644 --- a/crates/bitwarden/src/vault/cipher/local_data.rs +++ b/crates/bitwarden/src/vault/cipher/local_data.rs @@ -1,4 +1,4 @@ -use bitwarden_crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; +use bitwarden_crypto::{CryptoError, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -19,7 +19,7 @@ pub struct LocalDataView { } impl KeyEncryptable for LocalDataView { - fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> Result { Ok(LocalData { last_used_date: self.last_used_date, last_launched: self.last_launched, @@ -28,10 +28,7 @@ impl KeyEncryptable for LocalDataView { } impl KeyDecryptable for LocalData { - fn decrypt_with_key( - &self, - _key: &SymmetricCryptoKey, - ) -> bitwarden_crypto::Result { + fn decrypt_with_key(&self, _key: &SymmetricCryptoKey) -> Result { Ok(LocalDataView { last_used_date: self.last_used_date, last_launched: self.last_launched, diff --git a/crates/bitwarden/src/vault/cipher/login.rs b/crates/bitwarden/src/vault/cipher/login.rs index 94a35dbb2..3ccc46116 100644 --- a/crates/bitwarden/src/vault/cipher/login.rs +++ b/crates/bitwarden/src/vault/cipher/login.rs @@ -1,5 +1,7 @@ use bitwarden_api_api::models::{CipherLoginModel, CipherLoginUriModel}; -use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; +use bitwarden_crypto::{ + CryptoError, EncString, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey, +}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -63,7 +65,7 @@ pub struct LoginView { } impl KeyEncryptable for LoginUriView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(LoginUri { uri: self.uri.encrypt_with_key(key)?, r#match: self.r#match, @@ -72,7 +74,7 @@ impl KeyEncryptable for LoginUriView { } impl KeyEncryptable for LoginView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Login { username: self.username.encrypt_with_key(key)?, password: self.password.encrypt_with_key(key)?, @@ -85,7 +87,7 @@ impl KeyEncryptable for LoginView { } impl KeyDecryptable for LoginUri { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(LoginUriView { uri: self.uri.decrypt_with_key(key)?, r#match: self.r#match, @@ -94,7 +96,7 @@ impl KeyDecryptable for LoginUri { } impl KeyDecryptable for Login { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(LoginView { username: self.username.decrypt_with_key(key)?, password: self.password.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/cipher/secure_note.rs b/crates/bitwarden/src/vault/cipher/secure_note.rs index 0c8eab2a9..442ffc4be 100644 --- a/crates/bitwarden/src/vault/cipher/secure_note.rs +++ b/crates/bitwarden/src/vault/cipher/secure_note.rs @@ -1,5 +1,5 @@ use bitwarden_api_api::models::CipherSecureNoteModel; -use bitwarden_crypto::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; +use bitwarden_crypto::{CryptoError, KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_repr::{Deserialize_repr, Serialize_repr}; @@ -28,7 +28,7 @@ pub struct SecureNoteView { } impl KeyEncryptable for SecureNoteView { - fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn encrypt_with_key(self, _key: &SymmetricCryptoKey) -> Result { Ok(SecureNote { r#type: self.r#type, }) @@ -36,10 +36,7 @@ impl KeyEncryptable for SecureNoteView { } impl KeyDecryptable for SecureNote { - fn decrypt_with_key( - &self, - _key: &SymmetricCryptoKey, - ) -> bitwarden_crypto::Result { + fn decrypt_with_key(&self, _key: &SymmetricCryptoKey) -> Result { Ok(SecureNoteView { r#type: self.r#type, }) diff --git a/crates/bitwarden/src/vault/collection.rs b/crates/bitwarden/src/vault/collection.rs index 5cfbd96a1..f96becc39 100644 --- a/crates/bitwarden/src/vault/collection.rs +++ b/crates/bitwarden/src/vault/collection.rs @@ -1,5 +1,7 @@ use bitwarden_api_api::models::CollectionDetailsResponseModel; -use bitwarden_crypto::{EncString, KeyContainer, KeyDecryptable, LocateKey, SymmetricCryptoKey}; +use bitwarden_crypto::{ + CryptoError, EncString, KeyContainer, KeyDecryptable, LocateKey, SymmetricCryptoKey, +}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use uuid::Uuid; @@ -44,10 +46,7 @@ impl LocateKey for Collection { } } impl KeyDecryptable for Collection { - fn decrypt_with_key( - &self, - key: &SymmetricCryptoKey, - ) -> bitwarden_crypto::Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(CollectionView { id: self.id, organization_id: self.organization_id, diff --git a/crates/bitwarden/src/vault/folder.rs b/crates/bitwarden/src/vault/folder.rs index e7027e9fa..66ee595be 100644 --- a/crates/bitwarden/src/vault/folder.rs +++ b/crates/bitwarden/src/vault/folder.rs @@ -1,5 +1,7 @@ use bitwarden_api_api::models::FolderResponseModel; -use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}; +use bitwarden_crypto::{ + CryptoError, EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey, +}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -27,7 +29,7 @@ pub struct FolderView { impl LocateKey for FolderView {} impl KeyEncryptable for FolderView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(Folder { id: self.id, name: self.name.encrypt_with_key(key)?, @@ -38,7 +40,7 @@ impl KeyEncryptable for FolderView { impl LocateKey for Folder {} impl KeyDecryptable for Folder { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(FolderView { id: self.id, name: self.name.decrypt_with_key(key)?, diff --git a/crates/bitwarden/src/vault/password_history.rs b/crates/bitwarden/src/vault/password_history.rs index 6eea78ed2..c2709f335 100644 --- a/crates/bitwarden/src/vault/password_history.rs +++ b/crates/bitwarden/src/vault/password_history.rs @@ -1,5 +1,7 @@ use bitwarden_api_api::models::CipherPasswordHistoryModel; -use bitwarden_crypto::{EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey}; +use bitwarden_crypto::{ + CryptoError, EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey, +}; use chrono::{DateTime, Utc}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; @@ -24,10 +26,7 @@ pub struct PasswordHistoryView { impl LocateKey for PasswordHistoryView {} impl KeyEncryptable for PasswordHistoryView { - fn encrypt_with_key( - self, - key: &SymmetricCryptoKey, - ) -> bitwarden_crypto::Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(PasswordHistory { password: self.password.encrypt_with_key(key)?, last_used_date: self.last_used_date, @@ -40,7 +39,7 @@ impl KeyDecryptable for PasswordHistory { fn decrypt_with_key( &self, key: &SymmetricCryptoKey, - ) -> bitwarden_crypto::Result { + ) -> Result { Ok(PasswordHistoryView { password: self.password.decrypt_with_key(key)?, last_used_date: self.last_used_date, diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index 908527d2f..f710d905c 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -1,6 +1,7 @@ use bitwarden_api_api::models::{SendFileModel, SendResponseModel, SendTextModel}; use bitwarden_crypto::{ - derive_shareable_key, EncString, KeyDecryptable, KeyEncryptable, LocateKey, SymmetricCryptoKey, + derive_shareable_key, CryptoError, EncString, KeyDecryptable, KeyEncryptable, LocateKey, + SymmetricCryptoKey, }; use chrono::{DateTime, Utc}; use schemars::JsonSchema; @@ -129,7 +130,7 @@ impl Send { pub(crate) fn get_key( send_key: &EncString, enc_key: &SymmetricCryptoKey, - ) -> bitwarden_crypto::Result { + ) -> Result { let key: Vec = send_key.decrypt_with_key(enc_key)?; let key = derive_shareable_key(key.try_into().unwrap(), "send", Some("send")); Ok(key) @@ -137,7 +138,7 @@ impl Send { } impl KeyDecryptable for SendText { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(SendTextView { text: self.text.decrypt_with_key(key)?, hidden: self.hidden, @@ -146,7 +147,7 @@ impl KeyDecryptable for SendText { } impl KeyEncryptable for SendTextView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(SendText { text: self.text.encrypt_with_key(key)?, hidden: self.hidden, @@ -155,7 +156,7 @@ impl KeyEncryptable for SendTextView { } impl KeyDecryptable for SendFile { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { Ok(SendFileView { id: self.id.clone(), file_name: self.file_name.decrypt_with_key(key)?, @@ -166,7 +167,7 @@ impl KeyDecryptable for SendFile { } impl KeyEncryptable for SendFileView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { Ok(SendFile { id: self.id.clone(), file_name: self.file_name.encrypt_with_key(key)?, @@ -178,7 +179,7 @@ impl KeyEncryptable for SendFileView { impl LocateKey for Send {} impl KeyDecryptable for Send { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key let key = Send::get_key(&self.key, key)?; @@ -209,7 +210,7 @@ impl KeyDecryptable for Send { } impl KeyDecryptable for Send { - fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn decrypt_with_key(&self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key let key = Send::get_key(&self.key, key)?; @@ -232,7 +233,7 @@ impl KeyDecryptable for Send { impl LocateKey for SendView {} impl KeyEncryptable for SendView { - fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> bitwarden_crypto::Result { + fn encrypt_with_key(self, key: &SymmetricCryptoKey) -> Result { // For sends, we first decrypt the send key with the user key, and stretch it to it's full size // For the rest of the fields, we ignore the provided SymmetricCryptoKey and the stretched key let key = Send::get_key(&self.key, key)?; From 3c4e603128dca21b9a541ee83921d555f566b87e Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 4 Jan 2024 18:33:35 +0100 Subject: [PATCH 05/30] Fix naming --- crates/bitwarden/src/error.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bitwarden/src/error.rs b/crates/bitwarden/src/error.rs index c11913e6f..627e92e78 100644 --- a/crates/bitwarden/src/error.rs +++ b/crates/bitwarden/src/error.rs @@ -24,7 +24,7 @@ pub enum Error { MissingFields, #[error("Cryptography error, {0}")] - Crypto2(#[from] bitwarden_crypto::CryptoError), + Crypto(#[from] bitwarden_crypto::CryptoError), #[error("Error parsing Identity response: {0}")] IdentityFail(crate::auth::api::response::IdentityTokenFailResponse), From 9d7126b8b3c1dc8d9afbc95986aed527aa924e96 Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 4 Jan 2024 18:43:13 +0100 Subject: [PATCH 06/30] Fix clippy --- crates/bitwarden-crypto/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/crates/bitwarden-crypto/src/lib.rs b/crates/bitwarden-crypto/src/lib.rs index 02131949c..a4f5321a8 100644 --- a/crates/bitwarden-crypto/src/lib.rs +++ b/crates/bitwarden-crypto/src/lib.rs @@ -44,5 +44,3 @@ uniffi::setup_scaffolding!(); #[cfg(feature = "mobile")] mod uniffi_support; -#[cfg(feature = "mobile")] -pub use uniffi_support::*; From 05a761d9b94f6418a0c07db9979bf70c530add71 Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 8 Jan 2024 09:22:35 +0100 Subject: [PATCH 07/30] Improve comments --- .../src/enc_string/symmetric.rs | 4 ++-- .../bitwarden-crypto/src/keys/master_key.rs | 14 +++++++----- crates/bitwarden-crypto/src/keys/mod.rs | 2 ++ .../src/keys/symmetric_crypto_key.rs | 22 +++++++++++-------- crates/bitwarden-crypto/src/keys/user_key.rs | 3 +++ crates/bitwarden/src/vault/cipher/cipher.rs | 2 +- 6 files changed, 30 insertions(+), 17 deletions(-) diff --git a/crates/bitwarden-crypto/src/enc_string/symmetric.rs b/crates/bitwarden-crypto/src/enc_string/symmetric.rs index 120ba46ce..a27d14bbe 100644 --- a/crates/bitwarden-crypto/src/enc_string/symmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/symmetric.rs @@ -269,11 +269,11 @@ impl schemars::JsonSchema for EncString { #[cfg(test)] mod tests { use super::EncString; - use crate::{KeyDecryptable, KeyEncryptable, SymmetricCryptoKey}; + use crate::{generate_symmetric_key, KeyDecryptable, KeyEncryptable}; #[test] fn test_enc_string_roundtrip() { - let key = SymmetricCryptoKey::generate("test"); + let key = generate_symmetric_key("test"); let test_string = "encrypted_test_string".to_string(); let cipher = test_string.clone().encrypt_with_key(&key).unwrap(); diff --git a/crates/bitwarden-crypto/src/keys/master_key.rs b/crates/bitwarden-crypto/src/keys/master_key.rs index 36f1e2640..181aff303 100644 --- a/crates/bitwarden-crypto/src/keys/master_key.rs +++ b/crates/bitwarden-crypto/src/keys/master_key.rs @@ -30,7 +30,9 @@ pub enum HashPurpose { LocalAuthorization = 2, } -/// A Master Key. +/// Master Key. +/// +/// Derived from the users master password, used to protect the [UserKey]. pub struct MasterKey(SymmetricCryptoKey); impl MasterKey { @@ -39,7 +41,7 @@ impl MasterKey { derive_key(password, email, kdf).map(Self) } - /// Derive the master key hash, used for server authorization. + /// Derive the master key hash, used for local and remote password validation. pub fn derive_master_key_hash(&self, password: &[u8], purpose: HashPurpose) -> Result { let hash = pbkdf2::pbkdf2_array::( &self.0.key, @@ -51,10 +53,12 @@ impl MasterKey { Ok(STANDARD.encode(hash)) } + /// Generate a new random user key and encrypt it with the master key. pub fn make_user_key(&self) -> Result<(UserKey, EncString)> { make_user_key(rand::thread_rng(), self) } + /// Decrypt the users user key pub fn decrypt_user_key(&self, user_key: EncString) -> Result { let stretched_key = stretch_master_key(self)?; @@ -143,7 +147,7 @@ mod tests { use rand::SeedableRng; use super::{make_user_key, stretch_master_key, HashPurpose, Kdf, MasterKey}; - use crate::SymmetricCryptoKey; + use crate::{keys::symmetric_crypto_key::generate_symmetric_key, SymmetricCryptoKey}; #[test] fn test_master_key_derive_pbkdf2() { @@ -301,9 +305,9 @@ mod tests { #[test] fn test_make_user_key2() { - let master_key = MasterKey(SymmetricCryptoKey::generate("test1")); + let master_key = MasterKey(generate_symmetric_key("test1")); - let user_key = SymmetricCryptoKey::generate("test2"); + let user_key = generate_symmetric_key("test2"); let encrypted = master_key.encrypt_user_key(&user_key).unwrap(); let decrypted = master_key.decrypt_user_key(encrypted).unwrap(); diff --git a/crates/bitwarden-crypto/src/keys/mod.rs b/crates/bitwarden-crypto/src/keys/mod.rs index 7210e98a6..3b9995ae6 100644 --- a/crates/bitwarden-crypto/src/keys/mod.rs +++ b/crates/bitwarden-crypto/src/keys/mod.rs @@ -8,6 +8,8 @@ mod shareable_key; pub use shareable_key::derive_shareable_key; mod symmetric_crypto_key; +#[cfg(test)] +pub use symmetric_crypto_key::generate_symmetric_key; pub use symmetric_crypto_key::SymmetricCryptoKey; mod user_key; diff --git a/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs b/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs index 6041b508e..373d9c8e0 100644 --- a/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs +++ b/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs @@ -3,7 +3,7 @@ use std::str::FromStr; use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::{engine::general_purpose::STANDARD, Engine}; -use crate::{keys::derive_shareable_key, CryptoError}; +use crate::CryptoError; /// A symmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::EncString) pub struct SymmetricCryptoKey { @@ -15,12 +15,6 @@ impl SymmetricCryptoKey { const KEY_LEN: usize = 32; const MAC_LEN: usize = 32; - pub fn generate(name: &str) -> Self { - use rand::Rng; - let secret: [u8; 16] = rand::thread_rng().gen(); - derive_shareable_key(secret, name, None) - } - pub fn to_base64(&self) -> String { let mut buf = Vec::new(); buf.extend_from_slice(&self.key); @@ -78,15 +72,25 @@ impl std::fmt::Debug for SymmetricCryptoKey { } } +#[cfg(test)] +pub fn generate_symmetric_key(name: &str) -> SymmetricCryptoKey { + use rand::Rng; + + use crate::derive_shareable_key; + + let secret: [u8; 16] = rand::thread_rng().gen(); + derive_shareable_key(secret, name, None) +} + #[cfg(test)] mod tests { use std::str::FromStr; - use super::SymmetricCryptoKey; + use super::{generate_symmetric_key, SymmetricCryptoKey}; #[test] fn test_symmetric_crypto_key() { - let key = SymmetricCryptoKey::generate("test"); + let key = generate_symmetric_key("test"); let key2 = SymmetricCryptoKey::from_str(&key.to_base64()).unwrap(); assert_eq!(key.key, key2.key); assert_eq!(key.mac_key, key2.mac_key); diff --git a/crates/bitwarden-crypto/src/keys/user_key.rs b/crates/bitwarden-crypto/src/keys/user_key.rs index 7ad289c7a..6620236ec 100644 --- a/crates/bitwarden-crypto/src/keys/user_key.rs +++ b/crates/bitwarden-crypto/src/keys/user_key.rs @@ -3,6 +3,9 @@ use crate::{ Result, SymmetricCryptoKey, }; +/// User Key +/// +/// The User Key is the symmetric encryption key used to decrypt the user's vault. pub struct UserKey(pub SymmetricCryptoKey); impl UserKey { diff --git a/crates/bitwarden/src/vault/cipher/cipher.rs b/crates/bitwarden/src/vault/cipher/cipher.rs index 642933188..2cbd511f3 100644 --- a/crates/bitwarden/src/vault/cipher/cipher.rs +++ b/crates/bitwarden/src/vault/cipher/cipher.rs @@ -218,7 +218,7 @@ impl Cipher { .as_ref() .map(|k| { let key: Vec = k.decrypt_with_key(key)?; - Ok(SymmetricCryptoKey::try_from(key.as_slice())?) + SymmetricCryptoKey::try_from(key.as_slice()) }) .transpose() } From 9e446cfbb8e92d971badd21c1a6ad9f90030a398 Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 8 Jan 2024 11:48:30 +0100 Subject: [PATCH 08/30] Fix ambigous --- crates/bitwarden-crypto/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bitwarden-crypto/src/lib.rs b/crates/bitwarden-crypto/src/lib.rs index a4f5321a8..fff086d66 100644 --- a/crates/bitwarden-crypto/src/lib.rs +++ b/crates/bitwarden-crypto/src/lib.rs @@ -34,7 +34,7 @@ pub use fingerprint::fingerprint; mod keys; pub use keys::*; mod rsa; -pub use rsa::RsaKeyPair; +pub use crate::rsa::RsaKeyPair; mod util; mod wordlist; pub use wordlist::EFF_LONG_WORD_LIST; From c1e7f6fc82150542207c07a0b85f4e91316df8b0 Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 8 Jan 2024 12:26:25 +0100 Subject: [PATCH 09/30] Fix android --- .gitignore | 3 +-- crates/bitwarden-crypto/uniffi.toml | 8 ++++++++ crates/bitwarden/src/platform/generate_fingerprint.rs | 3 +-- 3 files changed, 10 insertions(+), 4 deletions(-) create mode 100644 crates/bitwarden-crypto/uniffi.toml diff --git a/.gitignore b/.gitignore index 23cbaba20..63c5875a3 100644 --- a/.gitignore +++ b/.gitignore @@ -50,8 +50,7 @@ languages/swift/BitwardenFFI.xcframework languages/swift/tmp languages/swift/.build languages/swift/.swiftpm -languages/kotlin/sdk/src/main/java/com/bitwarden/sdk/bitwarden_uniffi.kt -languages/kotlin/sdk/src/main/java/com/bitwarden/core/bitwarden.kt +languages/kotlin/sdk/src/main/java/com/bitwarden/**/*.kt # Schemas crates/bitwarden-napi/src-ts/bitwarden_client/schemas.ts diff --git a/crates/bitwarden-crypto/uniffi.toml b/crates/bitwarden-crypto/uniffi.toml new file mode 100644 index 000000000..f5826906b --- /dev/null +++ b/crates/bitwarden-crypto/uniffi.toml @@ -0,0 +1,8 @@ +[bindings.kotlin] +package_name = "com.bitwarden.crypto" +generate_immutable_records = true + +[bindings.swift] +ffi_module_name = "BitwardenCryptoFFI" +module_name = "BitwardenCrypto" +generate_immutable_records = true diff --git a/crates/bitwarden/src/platform/generate_fingerprint.rs b/crates/bitwarden/src/platform/generate_fingerprint.rs index f1fc16d44..34f7babad 100644 --- a/crates/bitwarden/src/platform/generate_fingerprint.rs +++ b/crates/bitwarden/src/platform/generate_fingerprint.rs @@ -59,13 +59,12 @@ pub(crate) fn generate_user_fingerprint( mod tests { use std::num::NonZeroU32; + use super::*; use crate::{ client::{kdf::Kdf, LoginMethod, UserLoginMethod}, Client, }; - use super::*; - #[test] fn test_generate_user_fingerprint() { let user_key = "2.oZg5RYpU2HjUAKI1DUQCkg==|PyRzI9kZpt66P2OedH8CHOeU0/lgKLkhIJiKDijdyFqIemBSIBoslhfQh/P1TK9xgZp0smgD6+5+yNbZfOpBaCVrsT3WWAO78xOWizduRe4=|xfDLDZSJ+yZAdh388flVg7SMDBJuMs0+CHTjutKs4uQ="; From 1c571f411302f48d3c58ac480e79be5e0ef78bdc Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 8 Jan 2024 13:00:40 +0100 Subject: [PATCH 10/30] Use mobile feature for crypto --- crates/bitwarden-uniffi/Cargo.toml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/crates/bitwarden-uniffi/Cargo.toml b/crates/bitwarden-uniffi/Cargo.toml index 4c4a170c6..32ceeb434 100644 --- a/crates/bitwarden-uniffi/Cargo.toml +++ b/crates/bitwarden-uniffi/Cargo.toml @@ -22,7 +22,9 @@ schemars = { version = ">=0.8, <0.9", optional = true } uniffi = "=0.25.2" bitwarden = { path = "../bitwarden", features = ["mobile", "internal"] } -bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0" } +bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0", features = [ + "mobile", +] } [build-dependencies] uniffi = { version = "=0.25.2", features = ["build"] } From c26c88880408517144afb4f2b9e88120e5a607f3 Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 8 Jan 2024 13:06:26 +0100 Subject: [PATCH 11/30] Move uniffi AsymmEncString to bitwarden crate --- crates/bitwarden-crypto/src/uniffi_support.rs | 18 ++-------------- crates/bitwarden/src/uniffi_support.rs | 21 +++++++++++++------ 2 files changed, 17 insertions(+), 22 deletions(-) diff --git a/crates/bitwarden-crypto/src/uniffi_support.rs b/crates/bitwarden-crypto/src/uniffi_support.rs index b35ca7cea..0ff0194f9 100644 --- a/crates/bitwarden-crypto/src/uniffi_support.rs +++ b/crates/bitwarden-crypto/src/uniffi_support.rs @@ -1,6 +1,6 @@ -use std::{num::NonZeroU32, str::FromStr}; +use std::num::NonZeroU32; -use crate::{AsymmEncString, CryptoError, EncString, UniffiCustomTypeConverter}; +use crate::{CryptoError, EncString, UniffiCustomTypeConverter}; uniffi::custom_type!(NonZeroU32, u32); @@ -29,17 +29,3 @@ impl UniffiCustomTypeConverter for EncString { obj.to_string() } } - -uniffi::custom_type!(AsymmEncString, String); - -impl UniffiCustomTypeConverter for AsymmEncString { - type Builtin = String; - - fn into_custom(val: Self::Builtin) -> uniffi::Result { - Self::from_str(&val).map_err(|e| e.into()) - } - - fn from_custom(obj: Self) -> Self::Builtin { - obj.to_string() - } -} diff --git a/crates/bitwarden/src/uniffi_support.rs b/crates/bitwarden/src/uniffi_support.rs index 477981dac..06431b03c 100644 --- a/crates/bitwarden/src/uniffi_support.rs +++ b/crates/bitwarden/src/uniffi_support.rs @@ -1,4 +1,4 @@ -use std::num::NonZeroU32; +use std::{num::NonZeroU32, str::FromStr}; use bitwarden_crypto::{AsymmEncString, EncString}; use uuid::Uuid; @@ -7,11 +7,6 @@ use crate::UniffiCustomTypeConverter; uniffi::ffi_converter_forward!(NonZeroU32, bitwarden_crypto::UniFfiTag, crate::UniFfiTag); uniffi::ffi_converter_forward!(EncString, bitwarden_crypto::UniFfiTag, crate::UniFfiTag); -uniffi::ffi_converter_forward!( - AsymmEncString, - bitwarden_crypto::UniFfiTag, - crate::UniFfiTag -); type DateTime = chrono::DateTime; uniffi::custom_type!(DateTime, std::time::SystemTime); @@ -41,3 +36,17 @@ impl UniffiCustomTypeConverter for Uuid { obj.to_string() } } + +uniffi::custom_type!(AsymmEncString, String); + +impl UniffiCustomTypeConverter for AsymmEncString { + type Builtin = String; + + fn into_custom(val: Self::Builtin) -> uniffi::Result { + Self::from_str(&val).map_err(|e| e.into()) + } + + fn from_custom(obj: Self) -> Self::Builtin { + obj.to_string() + } +} From 7e3f8a2140f54c4daceec6330b76470e3af5deda Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 8 Jan 2024 14:50:02 +0100 Subject: [PATCH 12/30] Fix ios --- crates/bitwarden-crypto/src/error.rs | 3 -- crates/bitwarden-crypto/src/uniffi_support.rs | 16 -------- crates/bitwarden/src/error.rs | 3 ++ crates/bitwarden/src/uniffi_support.rs | 41 ++++++++++++------- languages/swift/build.sh | 8 ++-- 5 files changed, 35 insertions(+), 36 deletions(-) diff --git a/crates/bitwarden-crypto/src/error.rs b/crates/bitwarden-crypto/src/error.rs index d310c2355..399131b21 100644 --- a/crates/bitwarden-crypto/src/error.rs +++ b/crates/bitwarden-crypto/src/error.rs @@ -30,9 +30,6 @@ pub enum CryptoError { #[error("Fingerprint error, {0}")] FingerprintError(#[from] FingerprintError), - - #[error("Number is zero")] - ZeroNumber, } #[derive(Debug, Error)] diff --git a/crates/bitwarden-crypto/src/uniffi_support.rs b/crates/bitwarden-crypto/src/uniffi_support.rs index 0ff0194f9..98d618e32 100644 --- a/crates/bitwarden-crypto/src/uniffi_support.rs +++ b/crates/bitwarden-crypto/src/uniffi_support.rs @@ -1,21 +1,5 @@ -use std::num::NonZeroU32; - use crate::{CryptoError, EncString, UniffiCustomTypeConverter}; -uniffi::custom_type!(NonZeroU32, u32); - -impl UniffiCustomTypeConverter for NonZeroU32 { - type Builtin = u32; - - fn into_custom(val: Self::Builtin) -> uniffi::Result { - Self::new(val).ok_or(CryptoError::ZeroNumber.into()) - } - - fn from_custom(obj: Self) -> Self::Builtin { - obj.get() - } -} - uniffi::custom_type!(EncString, String); impl UniffiCustomTypeConverter for EncString { diff --git a/crates/bitwarden/src/error.rs b/crates/bitwarden/src/error.rs index 627e92e78..bdd12abf5 100644 --- a/crates/bitwarden/src/error.rs +++ b/crates/bitwarden/src/error.rs @@ -49,6 +49,9 @@ pub enum Error { #[error("The state file could not be read")] InvalidStateFile, + #[error("Number is zero")] + ZeroNumber, + #[error("Internal error: {0}")] Internal(Cow<'static, str>), } diff --git a/crates/bitwarden/src/uniffi_support.rs b/crates/bitwarden/src/uniffi_support.rs index 06431b03c..106719e37 100644 --- a/crates/bitwarden/src/uniffi_support.rs +++ b/crates/bitwarden/src/uniffi_support.rs @@ -3,33 +3,31 @@ use std::{num::NonZeroU32, str::FromStr}; use bitwarden_crypto::{AsymmEncString, EncString}; use uuid::Uuid; -use crate::UniffiCustomTypeConverter; +use crate::{error::Error, UniffiCustomTypeConverter}; -uniffi::ffi_converter_forward!(NonZeroU32, bitwarden_crypto::UniFfiTag, crate::UniFfiTag); uniffi::ffi_converter_forward!(EncString, bitwarden_crypto::UniFfiTag, crate::UniFfiTag); -type DateTime = chrono::DateTime; -uniffi::custom_type!(DateTime, std::time::SystemTime); +uniffi::custom_type!(NonZeroU32, u32); -impl UniffiCustomTypeConverter for chrono::DateTime { - type Builtin = std::time::SystemTime; +impl UniffiCustomTypeConverter for NonZeroU32 { + type Builtin = u32; fn into_custom(val: Self::Builtin) -> uniffi::Result { - Ok(Self::from(val)) + Self::new(val).ok_or(Error::ZeroNumber.into()) } fn from_custom(obj: Self) -> Self::Builtin { - obj.into() + obj.get() } } -uniffi::custom_type!(Uuid, String); +uniffi::custom_type!(AsymmEncString, String); -impl UniffiCustomTypeConverter for Uuid { +impl UniffiCustomTypeConverter for AsymmEncString { type Builtin = String; fn into_custom(val: Self::Builtin) -> uniffi::Result { - Uuid::parse_str(val.as_str()).map_err(|e| e.into()) + Self::from_str(&val).map_err(|e| e.into()) } fn from_custom(obj: Self) -> Self::Builtin { @@ -37,13 +35,28 @@ impl UniffiCustomTypeConverter for Uuid { } } -uniffi::custom_type!(AsymmEncString, String); +type DateTime = chrono::DateTime; +uniffi::custom_type!(DateTime, std::time::SystemTime); -impl UniffiCustomTypeConverter for AsymmEncString { +impl UniffiCustomTypeConverter for chrono::DateTime { + type Builtin = std::time::SystemTime; + + fn into_custom(val: Self::Builtin) -> uniffi::Result { + Ok(Self::from(val)) + } + + fn from_custom(obj: Self) -> Self::Builtin { + obj.into() + } +} + +uniffi::custom_type!(Uuid, String); + +impl UniffiCustomTypeConverter for Uuid { type Builtin = String; fn into_custom(val: Self::Builtin) -> uniffi::Result { - Self::from_str(&val).map_err(|e| e.into()) + Uuid::parse_str(val.as_str()).map_err(|e| e.into()) } fn from_custom(obj: Self) -> Self::Builtin { diff --git a/languages/swift/build.sh b/languages/swift/build.sh index 69da98415..87f9cecdb 100755 --- a/languages/swift/build.sh +++ b/languages/swift/build.sh @@ -28,14 +28,16 @@ cargo run -p uniffi-bindgen generate \ --out-dir tmp/bindings # Move generated swift bindings -mv ./tmp/bindings/BitwardenSDK.swift ./Sources/BitwardenSdk/ mv ./tmp/bindings/BitwardenCore.swift ./Sources/BitwardenSdk/ +mv ./tmp/bindings/BitwardenCrypto.swift ./Sources/BitwardenSdk/ +mv ./tmp/bindings/BitwardenSDK.swift ./Sources/BitwardenSdk/ # Massage the generated files to fit xcframework mkdir tmp/Headers -mv ./tmp/bindings/BitwardenFFI.h ./tmp/Headers/ mv ./tmp/bindings/BitwardenCoreFFI.h ./tmp/Headers/ -cat ./tmp/bindings/BitwardenFFI.modulemap ./tmp/bindings/BitwardenCoreFFI.modulemap > ./tmp/Headers/module.modulemap +mv ./tmp/bindings/BitwardenCryptoFFI.h ./tmp/Headers/ +mv ./tmp/bindings/BitwardenFFI.h ./tmp/Headers/ +cat ./tmp/bindings/BitwardenFFI.modulemap ./tmp/bindings/BitwardenCoreFFI.modulemap ./tmp/bindings/BitwardenCryptoFFI.modulemap > ./tmp/Headers/module.modulemap # Build xcframework xcodebuild -create-xcframework \ From 075f175f6c16c1306ca9ae580543296db0550a0b Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 8 Jan 2024 16:14:20 +0100 Subject: [PATCH 13/30] Fix test --- crates/bitwarden/src/vault/send.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index 352884c30..3e77a2357 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -333,10 +333,11 @@ impl TryFrom for SendText { #[cfg(test)] mod tests { + use bitwarden_crypto::{KeyDecryptable, KeyEncryptable}; + use super::{Send, SendText, SendTextView, SendType}; use crate::{ client::{encryption_settings::EncryptionSettings, kdf::Kdf, UserLoginMethod}, - crypto::{KeyDecryptable, KeyEncryptable}, vault::SendView, }; From 490abc6b88b4035f26fcc773dfedbca65a02527c Mon Sep 17 00:00:00 2001 From: Hinton Date: Tue, 9 Jan 2024 17:02:54 +0100 Subject: [PATCH 14/30] Fix clippy --- crates/bitwarden/src/vault/send.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index feab0e895..99d401bbc 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -254,7 +254,7 @@ impl KeyEncryptable for SendView { key.to_vec() } // Existing send without key - _ => return Err(CryptoError::InvalidKey.into()), + _ => return Err(CryptoError::InvalidKey), }; let send_key = Send::derive_shareable_key(&k)?; From e5584fd55c881dd18569ca3cc49f8a4b6fcb6c6a Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 11 Jan 2024 13:36:54 +0100 Subject: [PATCH 15/30] fmt --- crates/bitwarden-crypto/src/enc_string/symmetric.rs | 3 +-- crates/bitwarden-crypto/src/keys/master_key.rs | 3 +-- crates/bitwarden/src/platform/generate_fingerprint.rs | 3 ++- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/crates/bitwarden-crypto/src/enc_string/symmetric.rs b/crates/bitwarden-crypto/src/enc_string/symmetric.rs index 94e82f274..2a20eee92 100644 --- a/crates/bitwarden-crypto/src/enc_string/symmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/symmetric.rs @@ -268,9 +268,8 @@ impl schemars::JsonSchema for EncString { #[cfg(test)] mod tests { - use crate::{derive_symmetric_key, KeyDecryptable, KeyEncryptable}; - use super::EncString; + use crate::{derive_symmetric_key, KeyDecryptable, KeyEncryptable}; #[test] fn test_enc_string_roundtrip() { diff --git a/crates/bitwarden-crypto/src/keys/master_key.rs b/crates/bitwarden-crypto/src/keys/master_key.rs index 795bd04a8..3ac1bdd0c 100644 --- a/crates/bitwarden-crypto/src/keys/master_key.rs +++ b/crates/bitwarden-crypto/src/keys/master_key.rs @@ -142,9 +142,8 @@ mod tests { use rand::SeedableRng; - use crate::{keys::symmetric_crypto_key::derive_symmetric_key, SymmetricCryptoKey}; - use super::{make_user_key, stretch_master_key, HashPurpose, Kdf, MasterKey}; + use crate::{keys::symmetric_crypto_key::derive_symmetric_key, SymmetricCryptoKey}; #[test] fn test_master_key_derive_pbkdf2() { diff --git a/crates/bitwarden/src/platform/generate_fingerprint.rs b/crates/bitwarden/src/platform/generate_fingerprint.rs index e0b3cf006..eff63bd03 100644 --- a/crates/bitwarden/src/platform/generate_fingerprint.rs +++ b/crates/bitwarden/src/platform/generate_fingerprint.rs @@ -1,4 +1,3 @@ -use crate::error::Result; use base64::{engine::general_purpose::STANDARD, Engine}; use bitwarden_crypto::fingerprint; use log::info; @@ -6,6 +5,8 @@ use rsa::pkcs8::EncodePublicKey; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; +use crate::error::Result; + #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] #[cfg_attr(feature = "mobile", derive(uniffi::Record))] From b0c1a7bb01a7f1ddee25c456a5a6bac68a73d11f Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 11 Jan 2024 13:41:02 +0100 Subject: [PATCH 16/30] Don't re-export HashPurpose --- crates/bitwarden/src/auth/password/validate.rs | 3 ++- crates/bitwarden/src/lib.rs | 4 ---- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/crates/bitwarden/src/auth/password/validate.rs b/crates/bitwarden/src/auth/password/validate.rs index c86c1c40d..531d98b82 100644 --- a/crates/bitwarden/src/auth/password/validate.rs +++ b/crates/bitwarden/src/auth/password/validate.rs @@ -1,7 +1,8 @@ +use bitwarden_crypto::HashPurpose; + use crate::{ auth::determine_password_hash, client::{LoginMethod, UserLoginMethod}, - crypto::HashPurpose, error::{Error, Result}, Client, }; diff --git a/crates/bitwarden/src/lib.rs b/crates/bitwarden/src/lib.rs index 24d9cba44..a0a1c1b95 100644 --- a/crates/bitwarden/src/lib.rs +++ b/crates/bitwarden/src/lib.rs @@ -70,10 +70,6 @@ mod util; #[cfg(feature = "internal")] pub mod vault; -pub mod crypto { - pub use bitwarden_crypto::HashPurpose; -} - pub use client::Client; // Ensure the readme docs compile From 6188a5e76cc217667e92a856b04d3d81440afbb4 Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 11 Jan 2024 13:42:14 +0100 Subject: [PATCH 17/30] Forgot to update a place --- crates/bitwarden-uniffi/src/auth/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bitwarden-uniffi/src/auth/mod.rs b/crates/bitwarden-uniffi/src/auth/mod.rs index 1dc102b3e..0532be56f 100644 --- a/crates/bitwarden-uniffi/src/auth/mod.rs +++ b/crates/bitwarden-uniffi/src/auth/mod.rs @@ -3,8 +3,8 @@ use std::sync::Arc; use bitwarden::{ auth::{password::MasterPasswordPolicyOptions, RegisterKeyResponse}, client::kdf::Kdf, - crypto::HashPurpose, }; +use bitwarden_crypto::HashPurpose; use crate::{error::Result, Client}; From 16cbe12d6c2dd1ab86e0bc419f495a63a0440146 Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 11 Jan 2024 14:08:09 +0100 Subject: [PATCH 18/30] Fix uniffi doc --- crates/bitwarden-uniffi/src/docs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bitwarden-uniffi/src/docs.rs b/crates/bitwarden-uniffi/src/docs.rs index e7acbdcae..155abe50a 100644 --- a/crates/bitwarden-uniffi/src/docs.rs +++ b/crates/bitwarden-uniffi/src/docs.rs @@ -1,7 +1,6 @@ use bitwarden::{ auth::password::MasterPasswordPolicyOptions, client::kdf::Kdf, - crypto::HashPurpose, mobile::crypto::{InitOrgCryptoRequest, InitUserCryptoRequest}, platform::FingerprintRequest, tool::{ExportFormat, PassphraseGeneratorRequest, PasswordGeneratorRequest}, @@ -10,6 +9,7 @@ use bitwarden::{ TotpResponse, }, }; +use bitwarden_crypto::HashPurpose; use schemars::JsonSchema; #[derive(JsonSchema)] From d31986736a8170ee0e21fc4e73af411868571acb Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 11 Jan 2024 16:01:58 +0100 Subject: [PATCH 19/30] Remove unused dependencies --- Cargo.lock | 7 ------- crates/bitwarden-crypto/Cargo.toml | 4 +--- crates/bitwarden/Cargo.toml | 7 ------- 3 files changed, 1 insertion(+), 17 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a4f975edf..a2d2fd6cc 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -346,20 +346,15 @@ checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" name = "bitwarden" version = "0.4.0" dependencies = [ - "argon2", "base64 0.21.5", "bitwarden-api-api", "bitwarden-api-identity", "bitwarden-crypto", - "cbc", "chrono", "data-encoding", "getrandom 0.2.11", "hmac", - "lazy_static", "log", - "num-bigint", - "num-traits", "rand 0.8.5", "rand_chacha 0.3.1", "reqwest", @@ -448,10 +443,8 @@ dependencies = [ "sha2", "subtle", "thiserror", - "tokio", "uniffi", "uuid", - "wiremock", ] [[package]] diff --git a/crates/bitwarden-crypto/Cargo.toml b/crates/bitwarden-crypto/Cargo.toml index 38b2b00d3..4b7ac6cc4 100644 --- a/crates/bitwarden-crypto/Cargo.toml +++ b/crates/bitwarden-crypto/Cargo.toml @@ -31,7 +31,7 @@ num-traits = ">=0.2.15, <0.3" pbkdf2 = { version = ">=0.12.1, <0.13", default-features = false } rand = ">=0.8.5, <0.9" rsa = ">=0.9.2, <0.10" -schemars = { version = ">=0.8, <0.9", features = ["uuid1", "chrono"] } +schemars = { version = ">=0.8, <0.9", features = ["uuid1"] } serde = { version = ">=1.0, <2.0", features = ["derive"] } sha1 = ">=0.10.5, <0.11" sha2 = ">=0.10.6, <0.11" @@ -43,5 +43,3 @@ uuid = { version = ">=1.3.3, <2.0", features = ["serde"] } [dev-dependencies] rand_chacha = "0.3.1" serde_json = ">=1.0.96, <2.0" -tokio = { version = "1.34.0", features = ["rt", "macros"] } -wiremock = "0.5.22" diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 3f3915bcc..34f92836a 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -26,14 +26,10 @@ mobile = [ wasm-bindgen = ["chrono/wasmbind"] [dependencies] -argon2 = { version = ">=0.5.0, <0.6", features = [ - "alloc", -], default-features = false } base64 = ">=0.21.2, <0.22" bitwarden-api-api = { path = "../bitwarden-api-api", version = "=0.2.3" } bitwarden-api-identity = { path = "../bitwarden-api-identity", version = "=0.2.3" } bitwarden-crypto = { path = "../bitwarden-crypto", version = "=0.1.0" } -cbc = { version = ">=0.1.2, <0.2", features = ["alloc"] } chrono = { version = ">=0.4.26, <0.5", features = [ "clock", "serde", @@ -43,10 +39,7 @@ data-encoding = ">=2.5.0, <3.0" # We don't use this directly (it's used by rand), but we need it here to enable WASM support getrandom = { version = ">=0.2.9, <0.3", features = ["js"] } hmac = ">=0.12.1, <0.13" -lazy_static = ">=1.4.0, <2.0" log = ">=0.4.18, <0.5" -num-bigint = ">=0.4, <0.5" -num-traits = ">=0.2.15, <0.3" rand = ">=0.8.5, <0.9" reqwest = { version = ">=0.11, <0.12", features = [ "json", From 0ae213a8931c5f119929292d5f280ae7a539b53e Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 11 Jan 2024 16:19:06 +0100 Subject: [PATCH 20/30] Remove bitwarden::Kdf --- crates/bitwarden-crypto/src/error.rs | 3 + .../bitwarden-crypto/src/keys/master_key.rs | 5 +- crates/bitwarden-crypto/src/uniffi_support.rs | 16 ++++ crates/bitwarden-uniffi/src/auth/mod.rs | 7 +- crates/bitwarden-uniffi/src/docs.rs | 3 +- crates/bitwarden/src/auth/client_auth.rs | 31 +++--- crates/bitwarden/src/auth/login/mod.rs | 40 ++++++++ crates/bitwarden/src/auth/login/password.rs | 2 +- crates/bitwarden/src/auth/mod.rs | 4 +- .../bitwarden/src/auth/password/validate.rs | 2 +- crates/bitwarden/src/auth/register.rs | 2 +- crates/bitwarden/src/client/client.rs | 12 +-- .../src/client/encryption_settings.rs | 3 +- crates/bitwarden/src/client/kdf.rs | 96 ------------------- crates/bitwarden/src/client/mod.rs | 1 - crates/bitwarden/src/error.rs | 3 - crates/bitwarden/src/mobile/client_kdf.rs | 2 +- crates/bitwarden/src/mobile/crypto.rs | 6 +- .../src/platform/generate_fingerprint.rs | 2 +- .../src/platform/get_user_api_key.rs | 2 +- crates/bitwarden/src/uniffi_support.rs | 17 +--- crates/bitwarden/src/vault/send.rs | 2 +- crates/bitwarden/tests/register.rs | 2 +- 23 files changed, 102 insertions(+), 161 deletions(-) delete mode 100644 crates/bitwarden/src/client/kdf.rs diff --git a/crates/bitwarden-crypto/src/error.rs b/crates/bitwarden-crypto/src/error.rs index 399131b21..d310c2355 100644 --- a/crates/bitwarden-crypto/src/error.rs +++ b/crates/bitwarden-crypto/src/error.rs @@ -30,6 +30,9 @@ pub enum CryptoError { #[error("Fingerprint error, {0}")] FingerprintError(#[from] FingerprintError), + + #[error("Number is zero")] + ZeroNumber, } #[derive(Debug, Error)] diff --git a/crates/bitwarden-crypto/src/keys/master_key.rs b/crates/bitwarden-crypto/src/keys/master_key.rs index 3ac1bdd0c..34be0d232 100644 --- a/crates/bitwarden-crypto/src/keys/master_key.rs +++ b/crates/bitwarden-crypto/src/keys/master_key.rs @@ -3,6 +3,7 @@ use std::num::NonZeroU32; use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::{engine::general_purpose::STANDARD, Engine}; use schemars::JsonSchema; +use serde::{Deserialize, Serialize}; use sha2::Digest; use crate::{ @@ -10,7 +11,9 @@ use crate::{ EncString, KeyDecryptable, Result, SymmetricCryptoKey, UserKey, }; -#[derive(Debug, Clone)] +#[derive(Serialize, Deserialize, Debug, JsonSchema, Clone)] +#[serde(rename_all = "camelCase", deny_unknown_fields)] +#[cfg_attr(feature = "mobile", derive(uniffi::Enum))] pub enum Kdf { PBKDF2 { iterations: NonZeroU32, diff --git a/crates/bitwarden-crypto/src/uniffi_support.rs b/crates/bitwarden-crypto/src/uniffi_support.rs index 98d618e32..0ff0194f9 100644 --- a/crates/bitwarden-crypto/src/uniffi_support.rs +++ b/crates/bitwarden-crypto/src/uniffi_support.rs @@ -1,5 +1,21 @@ +use std::num::NonZeroU32; + use crate::{CryptoError, EncString, UniffiCustomTypeConverter}; +uniffi::custom_type!(NonZeroU32, u32); + +impl UniffiCustomTypeConverter for NonZeroU32 { + type Builtin = u32; + + fn into_custom(val: Self::Builtin) -> uniffi::Result { + Self::new(val).ok_or(CryptoError::ZeroNumber.into()) + } + + fn from_custom(obj: Self) -> Self::Builtin { + obj.get() + } +} + uniffi::custom_type!(EncString, String); impl UniffiCustomTypeConverter for EncString { diff --git a/crates/bitwarden-uniffi/src/auth/mod.rs b/crates/bitwarden-uniffi/src/auth/mod.rs index 0532be56f..f67aa3a02 100644 --- a/crates/bitwarden-uniffi/src/auth/mod.rs +++ b/crates/bitwarden-uniffi/src/auth/mod.rs @@ -1,10 +1,7 @@ use std::sync::Arc; -use bitwarden::{ - auth::{password::MasterPasswordPolicyOptions, RegisterKeyResponse}, - client::kdf::Kdf, -}; -use bitwarden_crypto::HashPurpose; +use bitwarden::auth::{password::MasterPasswordPolicyOptions, RegisterKeyResponse}; +use bitwarden_crypto::{HashPurpose, Kdf}; use crate::{error::Result, Client}; diff --git a/crates/bitwarden-uniffi/src/docs.rs b/crates/bitwarden-uniffi/src/docs.rs index 155abe50a..3ba0e061b 100644 --- a/crates/bitwarden-uniffi/src/docs.rs +++ b/crates/bitwarden-uniffi/src/docs.rs @@ -1,6 +1,5 @@ use bitwarden::{ auth::password::MasterPasswordPolicyOptions, - client::kdf::Kdf, mobile::crypto::{InitOrgCryptoRequest, InitUserCryptoRequest}, platform::FingerprintRequest, tool::{ExportFormat, PassphraseGeneratorRequest, PasswordGeneratorRequest}, @@ -9,7 +8,7 @@ use bitwarden::{ TotpResponse, }, }; -use bitwarden_crypto::HashPurpose; +use bitwarden_crypto::{HashPurpose, Kdf}; use schemars::JsonSchema; #[derive(JsonSchema)] diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index 6c9ddbd4d..3f93ee8c2 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -1,22 +1,20 @@ +use bitwarden_crypto::Kdf; + #[cfg(feature = "secrets")] use crate::auth::login::{login_access_token, AccessTokenLoginRequest, AccessTokenLoginResponse}; -use crate::{auth::renew::renew_token, error::Result, Client}; #[cfg(feature = "internal")] -use crate::{ - auth::{ - login::{ - login_api_key, login_password, send_two_factor_email, ApiKeyLoginRequest, - ApiKeyLoginResponse, PasswordLoginRequest, PasswordLoginResponse, - TwoFactorEmailRequest, - }, - password::{ - password_strength, satisfies_policy, validate_password, MasterPasswordPolicyOptions, - }, - register::{make_register_keys, register}, - RegisterKeyResponse, RegisterRequest, +use crate::auth::{ + login::{ + login_api_key, login_password, send_two_factor_email, ApiKeyLoginRequest, + ApiKeyLoginResponse, PasswordLoginRequest, PasswordLoginResponse, TwoFactorEmailRequest, }, - client::kdf::Kdf, + password::{ + password_strength, satisfies_policy, validate_password, MasterPasswordPolicyOptions, + }, + register::{make_register_keys, register}, + RegisterKeyResponse, RegisterRequest, }; +use crate::{auth::renew::renew_token, error::Result, Client}; pub struct ClientAuth<'a> { pub(crate) client: &'a mut crate::Client, @@ -70,9 +68,10 @@ impl<'a> ClientAuth<'a> { } pub async fn prelogin(&mut self, email: String) -> Result { - use crate::auth::login::request_prelogin; + use crate::auth::login::{parse_prelogin, request_prelogin}; - request_prelogin(self.client, email).await?.try_into() + let response = request_prelogin(self.client, email).await?; + parse_prelogin(response) } pub async fn login_password( diff --git a/crates/bitwarden/src/auth/login/mod.rs b/crates/bitwarden/src/auth/login/mod.rs index d2f66b569..77732e786 100644 --- a/crates/bitwarden/src/auth/login/mod.rs +++ b/crates/bitwarden/src/auth/login/mod.rs @@ -45,3 +45,43 @@ pub(crate) async fn request_prelogin( let config = client.get_api_configurations().await; Ok(accounts_prelogin_post(&config.identity, Some(request_model)).await?) } + +#[cfg(feature = "internal")] +use bitwarden_crypto::Kdf; + +#[cfg(feature = "internal")] +pub(crate) fn parse_prelogin(response: PreloginResponseModel) -> Result { + use std::num::NonZeroU32; + + use bitwarden_api_identity::models::KdfType; + + use crate::util::{ + default_argon2_iterations, default_argon2_memory, default_argon2_parallelism, + default_pbkdf2_iterations, + }; + + let kdf = response.kdf.ok_or("KDF not found")?; + + Ok(match kdf { + KdfType::Variant0 => Kdf::PBKDF2 { + iterations: response + .kdf_iterations + .and_then(|e| NonZeroU32::new(e as u32)) + .unwrap_or_else(default_pbkdf2_iterations), + }, + KdfType::Variant1 => Kdf::Argon2id { + iterations: response + .kdf_iterations + .and_then(|e| NonZeroU32::new(e as u32)) + .unwrap_or_else(default_argon2_iterations), + memory: response + .kdf_memory + .and_then(|e| NonZeroU32::new(e as u32)) + .unwrap_or_else(default_argon2_memory), + parallelism: response + .kdf_parallelism + .and_then(|e| NonZeroU32::new(e as u32)) + .unwrap_or_else(default_argon2_parallelism), + }, + }) +} diff --git a/crates/bitwarden/src/auth/login/password.rs b/crates/bitwarden/src/auth/login/password.rs index 33dd807b2..e5d579aa2 100644 --- a/crates/bitwarden/src/auth/login/password.rs +++ b/crates/bitwarden/src/auth/login/password.rs @@ -6,7 +6,7 @@ use serde::{Deserialize, Serialize}; #[cfg(feature = "internal")] use crate::{ auth::{api::request::PasswordTokenRequest, login::TwoFactorRequest}, - client::{kdf::Kdf, LoginMethod}, + client::{Kdf, LoginMethod}, Client, }; use crate::{ diff --git a/crates/bitwarden/src/auth/mod.rs b/crates/bitwarden/src/auth/mod.rs index 5e7690788..e80ab28cf 100644 --- a/crates/bitwarden/src/auth/mod.rs +++ b/crates/bitwarden/src/auth/mod.rs @@ -15,7 +15,7 @@ use bitwarden_crypto::{HashPurpose, MasterKey}; pub use register::{RegisterKeyResponse, RegisterRequest}; #[cfg(feature = "internal")] -use crate::{client::kdf::Kdf, error::Result}; +use crate::{client::Kdf, error::Result}; #[cfg(feature = "internal")] async fn determine_password_hash( @@ -24,7 +24,7 @@ async fn determine_password_hash( password: &str, purpose: HashPurpose, ) -> Result { - let master_key = MasterKey::derive(password.as_bytes(), email.as_bytes(), &kdf.into())?; + let master_key = MasterKey::derive(password.as_bytes(), email.as_bytes(), kdf)?; Ok(master_key.derive_master_key_hash(password.as_bytes(), purpose)?) } diff --git a/crates/bitwarden/src/auth/password/validate.rs b/crates/bitwarden/src/auth/password/validate.rs index 531d98b82..f6d22e11a 100644 --- a/crates/bitwarden/src/auth/password/validate.rs +++ b/crates/bitwarden/src/auth/password/validate.rs @@ -41,7 +41,7 @@ mod tests { use std::num::NonZeroU32; use super::validate_password; - use crate::client::{kdf::Kdf, Client, LoginMethod, UserLoginMethod}; + use crate::client::{Client, Kdf, LoginMethod, UserLoginMethod}; let mut client = Client::new(None); client.set_login_method(LoginMethod::User(UserLoginMethod::Username { diff --git a/crates/bitwarden/src/auth/register.rs b/crates/bitwarden/src/auth/register.rs index 10e7e3632..24b090316 100644 --- a/crates/bitwarden/src/auth/register.rs +++ b/crates/bitwarden/src/auth/register.rs @@ -6,7 +6,7 @@ use bitwarden_crypto::{HashPurpose, MasterKey, RsaKeyPair}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; -use crate::{client::kdf::Kdf, error::Result, util::default_pbkdf2_iterations, Client}; +use crate::{client::Kdf, error::Result, util::default_pbkdf2_iterations, Client}; #[derive(Serialize, Deserialize, Debug, JsonSchema)] #[serde(rename_all = "camelCase", deny_unknown_fields)] diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index ade14a5da..f088c43f5 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -1,5 +1,6 @@ use std::path::PathBuf; +pub use bitwarden_crypto::Kdf; use bitwarden_crypto::SymmetricCryptoKey; #[cfg(feature = "internal")] use bitwarden_crypto::{AsymmEncString, EncString}; @@ -11,12 +12,9 @@ use super::AccessToken; #[cfg(feature = "secrets")] use crate::auth::login::{AccessTokenLoginRequest, AccessTokenLoginResponse}; #[cfg(feature = "internal")] -use crate::{ - client::kdf::Kdf, - platform::{ - get_user_api_key, sync, SecretVerificationRequest, SyncRequest, SyncResponse, - UserApiKeyResponse, - }, +use crate::platform::{ + get_user_api_key, sync, SecretVerificationRequest, SyncRequest, SyncResponse, + UserApiKeyResponse, }; use crate::{ client::{ @@ -262,7 +260,7 @@ impl Client { Some(LoginMethod::User( UserLoginMethod::Username { email, kdf, .. } | UserLoginMethod::ApiKey { email, kdf, .. }, - )) => MasterKey::derive(pin.as_bytes(), email.as_bytes(), &kdf.into())?, + )) => MasterKey::derive(pin.as_bytes(), email.as_bytes(), kdf)?, _ => return Err(Error::NotAuthenticated), }; diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index e794a0a7b..47c415ac4 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -38,8 +38,7 @@ impl EncryptionSettings { UserLoginMethod::Username { email, kdf, .. } | UserLoginMethod::ApiKey { email, kdf, .. } => { // Derive master key from password - let master_key = - MasterKey::derive(password.as_bytes(), email.as_bytes(), &kdf.into())?; + let master_key = MasterKey::derive(password.as_bytes(), email.as_bytes(), kdf)?; // Decrypt the user key let user_key = master_key.decrypt_user_key(user_key)?; diff --git a/crates/bitwarden/src/client/kdf.rs b/crates/bitwarden/src/client/kdf.rs deleted file mode 100644 index ba7fd004a..000000000 --- a/crates/bitwarden/src/client/kdf.rs +++ /dev/null @@ -1,96 +0,0 @@ -use std::num::NonZeroU32; - -#[cfg(feature = "internal")] -use bitwarden_api_identity::models::{KdfType, PreloginResponseModel}; -use schemars::JsonSchema; -use serde::{Deserialize, Serialize}; - -#[cfg(feature = "internal")] -use crate::error::{Error, Result}; - -#[derive(Serialize, Deserialize, Debug, JsonSchema, Clone)] -#[serde(rename_all = "camelCase", deny_unknown_fields)] -#[cfg_attr(feature = "mobile", derive(uniffi::Enum))] -pub enum Kdf { - PBKDF2 { - iterations: NonZeroU32, - }, - Argon2id { - iterations: NonZeroU32, - memory: NonZeroU32, - parallelism: NonZeroU32, - }, -} - -impl From for bitwarden_crypto::Kdf { - fn from(kdf: Kdf) -> Self { - match kdf { - Kdf::PBKDF2 { iterations } => bitwarden_crypto::Kdf::PBKDF2 { iterations }, - Kdf::Argon2id { - iterations, - memory, - parallelism, - } => bitwarden_crypto::Kdf::Argon2id { - iterations, - memory, - parallelism, - }, - } - } -} - -impl From<&Kdf> for bitwarden_crypto::Kdf { - fn from(kdf: &Kdf) -> Self { - match kdf { - Kdf::PBKDF2 { iterations } => bitwarden_crypto::Kdf::PBKDF2 { - iterations: *iterations, - }, - Kdf::Argon2id { - iterations, - memory, - parallelism, - } => bitwarden_crypto::Kdf::Argon2id { - iterations: *iterations, - memory: *memory, - parallelism: *parallelism, - }, - } - } -} - -#[cfg(feature = "internal")] -impl TryFrom for Kdf { - type Error = Error; - - fn try_from(response: PreloginResponseModel) -> Result { - use crate::util::{ - default_argon2_iterations, default_argon2_memory, default_argon2_parallelism, - default_pbkdf2_iterations, - }; - - let kdf = response.kdf.ok_or("KDF not found")?; - - Ok(match kdf { - KdfType::Variant0 => Kdf::PBKDF2 { - iterations: response - .kdf_iterations - .and_then(|e| NonZeroU32::new(e as u32)) - .unwrap_or_else(default_pbkdf2_iterations), - }, - KdfType::Variant1 => Kdf::Argon2id { - iterations: response - .kdf_iterations - .and_then(|e| NonZeroU32::new(e as u32)) - .unwrap_or_else(default_argon2_iterations), - memory: response - .kdf_memory - .and_then(|e| NonZeroU32::new(e as u32)) - .unwrap_or_else(default_argon2_memory), - parallelism: response - .kdf_parallelism - .and_then(|e| NonZeroU32::new(e as u32)) - .unwrap_or_else(default_argon2_parallelism), - }, - }) - } -} diff --git a/crates/bitwarden/src/client/mod.rs b/crates/bitwarden/src/client/mod.rs index 25a2f5db0..c3719fce2 100644 --- a/crates/bitwarden/src/client/mod.rs +++ b/crates/bitwarden/src/client/mod.rs @@ -6,7 +6,6 @@ pub(crate) mod access_token; mod client; pub mod client_settings; pub(crate) mod encryption_settings; -pub mod kdf; pub use access_token::AccessToken; pub use client::Client; diff --git a/crates/bitwarden/src/error.rs b/crates/bitwarden/src/error.rs index bdd12abf5..627e92e78 100644 --- a/crates/bitwarden/src/error.rs +++ b/crates/bitwarden/src/error.rs @@ -49,9 +49,6 @@ pub enum Error { #[error("The state file could not be read")] InvalidStateFile, - #[error("Number is zero")] - ZeroNumber, - #[error("Internal error: {0}")] Internal(Cow<'static, str>), } diff --git a/crates/bitwarden/src/mobile/client_kdf.rs b/crates/bitwarden/src/mobile/client_kdf.rs index 7024693db..aaa785a19 100644 --- a/crates/bitwarden/src/mobile/client_kdf.rs +++ b/crates/bitwarden/src/mobile/client_kdf.rs @@ -1,6 +1,6 @@ use bitwarden_crypto::HashPurpose; -use crate::{client::kdf::Kdf, error::Result, mobile::kdf::hash_password, Client}; +use crate::{client::Kdf, error::Result, mobile::kdf::hash_password, Client}; pub struct ClientKdf<'a> { pub(crate) client: &'a crate::Client, diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index 741db5632..8894b19db 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -5,7 +5,7 @@ use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use crate::{ - client::kdf::Kdf, + client::Kdf, error::{Error, Result}, Client, }; @@ -126,7 +126,7 @@ pub fn derive_pin_key(client: &mut Client, pin: String) -> Result MasterKey::derive(pin.as_bytes(), email.as_bytes(), &kdf.into())?, + )) => MasterKey::derive(pin.as_bytes(), email.as_bytes(), kdf)?, _ => return Err(Error::NotAuthenticated), }; @@ -144,7 +144,7 @@ pub fn derive_pin_key(client: &mut Client, pin: String) -> Result uniffi::Result { - Self::new(val).ok_or(Error::ZeroNumber.into()) - } - - fn from_custom(obj: Self) -> Self::Builtin { - obj.get() - } -} - uniffi::custom_type!(AsymmEncString, String); impl UniffiCustomTypeConverter for AsymmEncString { diff --git a/crates/bitwarden/src/vault/send.rs b/crates/bitwarden/src/vault/send.rs index 99d401bbc..329c44e44 100644 --- a/crates/bitwarden/src/vault/send.rs +++ b/crates/bitwarden/src/vault/send.rs @@ -347,7 +347,7 @@ mod tests { use super::{Send, SendText, SendTextView, SendType}; use crate::{ - client::{encryption_settings::EncryptionSettings, kdf::Kdf, UserLoginMethod}, + client::{encryption_settings::EncryptionSettings, Kdf, UserLoginMethod}, vault::SendView, }; diff --git a/crates/bitwarden/tests/register.rs b/crates/bitwarden/tests/register.rs index 956fe86ce..8e523e26f 100644 --- a/crates/bitwarden/tests/register.rs +++ b/crates/bitwarden/tests/register.rs @@ -5,10 +5,10 @@ async fn test_register_initialize_crypto() { use std::num::NonZeroU32; use bitwarden::{ - client::kdf::Kdf, mobile::crypto::{InitUserCryptoMethod, InitUserCryptoRequest}, Client, }; + use bitwarden_crypto::Kdf; let mut client = Client::new(None); From 4d686dd47f4f4f57eb14353646cfc39b3009157f Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 11 Jan 2024 16:22:19 +0100 Subject: [PATCH 21/30] Minor import tweaks --- crates/bitwarden/src/auth/client_auth.rs | 4 +--- crates/bitwarden/src/auth/login/mod.rs | 5 +---- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index 3f93ee8c2..f3b2c5ec9 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -1,5 +1,3 @@ -use bitwarden_crypto::Kdf; - #[cfg(feature = "secrets")] use crate::auth::login::{login_access_token, AccessTokenLoginRequest, AccessTokenLoginResponse}; #[cfg(feature = "internal")] @@ -14,7 +12,7 @@ use crate::auth::{ register::{make_register_keys, register}, RegisterKeyResponse, RegisterRequest, }; -use crate::{auth::renew::renew_token, error::Result, Client}; +use crate::{auth::renew::renew_token, client::Kdf, error::Result, Client}; pub struct ClientAuth<'a> { pub(crate) client: &'a mut crate::Client, diff --git a/crates/bitwarden/src/auth/login/mod.rs b/crates/bitwarden/src/auth/login/mod.rs index 77732e786..afd7873a4 100644 --- a/crates/bitwarden/src/auth/login/mod.rs +++ b/crates/bitwarden/src/auth/login/mod.rs @@ -1,6 +1,6 @@ #[cfg(feature = "internal")] use { - crate::{client::Client, error::Result}, + crate::{client::Kdf, error::Result, Client}, bitwarden_api_identity::{ apis::accounts_api::accounts_prelogin_post, models::{PreloginRequestModel, PreloginResponseModel}, @@ -46,9 +46,6 @@ pub(crate) async fn request_prelogin( Ok(accounts_prelogin_post(&config.identity, Some(request_model)).await?) } -#[cfg(feature = "internal")] -use bitwarden_crypto::Kdf; - #[cfg(feature = "internal")] pub(crate) fn parse_prelogin(response: PreloginResponseModel) -> Result { use std::num::NonZeroU32; From 4bf7bb2b60e63be4a58e346c75a2367a5330e401 Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 11 Jan 2024 16:28:04 +0100 Subject: [PATCH 22/30] Remove unnecessary into --- crates/bitwarden/src/auth/register.rs | 2 +- crates/bitwarden/src/mobile/client_kdf.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/crates/bitwarden/src/auth/register.rs b/crates/bitwarden/src/auth/register.rs index 24b090316..2b0c9503b 100644 --- a/crates/bitwarden/src/auth/register.rs +++ b/crates/bitwarden/src/auth/register.rs @@ -59,7 +59,7 @@ pub(super) fn make_register_keys( password: String, kdf: Kdf, ) -> Result { - let master_key = MasterKey::derive(password.as_bytes(), email.as_bytes(), &kdf.into())?; + let master_key = MasterKey::derive(password.as_bytes(), email.as_bytes(), &kdf)?; let master_password_hash = master_key.derive_master_key_hash(password.as_bytes(), HashPurpose::ServerAuthorization)?; let (user_key, encrypted_user_key) = master_key.make_user_key()?; diff --git a/crates/bitwarden/src/mobile/client_kdf.rs b/crates/bitwarden/src/mobile/client_kdf.rs index aaa785a19..4e62e5d59 100644 --- a/crates/bitwarden/src/mobile/client_kdf.rs +++ b/crates/bitwarden/src/mobile/client_kdf.rs @@ -14,7 +14,7 @@ impl<'a> ClientKdf<'a> { kdf_params: Kdf, purpose: HashPurpose, ) -> Result { - hash_password(self.client, email, password, kdf_params.into(), purpose).await + hash_password(self.client, email, password, kdf_params, purpose).await } } From d9481b3b899ec0efa8d5e1bf15b7f3c8afc2331f Mon Sep 17 00:00:00 2001 From: Hinton Date: Thu, 11 Jan 2024 16:29:43 +0100 Subject: [PATCH 23/30] Remove InvalidLen --- crates/bitwarden-crypto/src/error.rs | 3 --- crates/bitwarden-crypto/src/fingerprint.rs | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/crates/bitwarden-crypto/src/error.rs b/crates/bitwarden-crypto/src/error.rs index d310c2355..059cc88f1 100644 --- a/crates/bitwarden-crypto/src/error.rs +++ b/crates/bitwarden-crypto/src/error.rs @@ -19,9 +19,6 @@ pub enum CryptoError { #[error("Missing Key")] MissingKey, - #[error("Invalid length")] - InvalidLen, - #[error("EncString error, {0}")] EncString(#[from] EncStringParseError), diff --git a/crates/bitwarden-crypto/src/fingerprint.rs b/crates/bitwarden-crypto/src/fingerprint.rs index 2e67e3d8a..d3e69d577 100644 --- a/crates/bitwarden-crypto/src/fingerprint.rs +++ b/crates/bitwarden-crypto/src/fingerprint.rs @@ -26,7 +26,7 @@ pub fn fingerprint(fingerprint_material: &str, public_key: &[u8]) -> Result Date: Thu, 11 Jan 2024 16:41:50 +0100 Subject: [PATCH 24/30] Resolve linting errors --- crates/bitwarden/src/auth/client_auth.rs | 24 ++++++++++++++---------- crates/bitwarden/src/client/client.rs | 1 + 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index f3b2c5ec9..d4379d1eb 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -1,18 +1,22 @@ #[cfg(feature = "secrets")] use crate::auth::login::{login_access_token, AccessTokenLoginRequest, AccessTokenLoginResponse}; +use crate::{auth::renew::renew_token, error::Result, Client}; #[cfg(feature = "internal")] -use crate::auth::{ - login::{ - login_api_key, login_password, send_two_factor_email, ApiKeyLoginRequest, - ApiKeyLoginResponse, PasswordLoginRequest, PasswordLoginResponse, TwoFactorEmailRequest, +use crate::{ + auth::{ + login::{ + login_api_key, login_password, send_two_factor_email, ApiKeyLoginRequest, + ApiKeyLoginResponse, PasswordLoginRequest, PasswordLoginResponse, + TwoFactorEmailRequest, + }, + password::{ + password_strength, satisfies_policy, validate_password, MasterPasswordPolicyOptions, + }, + register::{make_register_keys, register}, + RegisterKeyResponse, RegisterRequest, }, - password::{ - password_strength, satisfies_policy, validate_password, MasterPasswordPolicyOptions, - }, - register::{make_register_keys, register}, - RegisterKeyResponse, RegisterRequest, + client::Kdf, }; -use crate::{auth::renew::renew_token, client::Kdf, error::Result, Client}; pub struct ClientAuth<'a> { pub(crate) client: &'a mut crate::Client, diff --git a/crates/bitwarden/src/client/client.rs b/crates/bitwarden/src/client/client.rs index f088c43f5..34d99c0a3 100644 --- a/crates/bitwarden/src/client/client.rs +++ b/crates/bitwarden/src/client/client.rs @@ -1,5 +1,6 @@ use std::path::PathBuf; +#[cfg(feature = "internal")] pub use bitwarden_crypto::Kdf; use bitwarden_crypto::SymmetricCryptoKey; #[cfg(feature = "internal")] From dd70d0ab1f716192345079da2838fcedef19d1d1 Mon Sep 17 00:00:00 2001 From: Hinton Date: Fri, 12 Jan 2024 18:17:40 +0100 Subject: [PATCH 25/30] fmt and clippy --- crates/bitwarden-crypto/src/enc_string/asymmetric.rs | 6 +++--- crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs | 3 +-- crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs | 3 +-- crates/bitwarden/src/client/encryption_settings.rs | 5 +++-- 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs index fcc66bee1..833d371e6 100644 --- a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs @@ -152,7 +152,7 @@ impl AsymmEncString { impl KeyDecryptable> for AsymmEncString { fn decrypt_with_key(&self, key: &AsymmetricCryptoKey) -> Result> { use AsymmEncString::*; - Ok(match self { + match self { Rsa2048_OaepSha256_B64 { data } => key.key.decrypt(Oaep::new::(), data), Rsa2048_OaepSha1_B64 { data } => key.key.decrypt(Oaep::new::(), data), #[allow(deprecated)] @@ -164,14 +164,14 @@ impl KeyDecryptable> for AsymmEncString { key.key.decrypt(Oaep::new::(), data) } } - .map_err(|_| CryptoError::KeyDecrypt)?) + .map_err(|_| CryptoError::KeyDecrypt) } } impl KeyDecryptable for AsymmEncString { fn decrypt_with_key(&self, key: &AsymmetricCryptoKey) -> Result { let dec: Vec = self.decrypt_with_key(key)?; - String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String.into()) + String::from_utf8(dec).map_err(|_| CryptoError::InvalidUtf8String) } } diff --git a/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs b/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs index 5bd4fc1f5..a4cb13d0d 100644 --- a/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs +++ b/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs @@ -1,8 +1,7 @@ use rsa::RsaPrivateKey; -use crate::error::{CryptoError, Result}; - use super::key_encryptable::CryptoKey; +use crate::error::{CryptoError, Result}; /// An asymmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::crypto::EncString) pub struct AsymmetricCryptoKey { diff --git a/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs b/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs index 39b3f3bed..31b00fd54 100644 --- a/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs +++ b/crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs @@ -4,9 +4,8 @@ use aes::cipher::{generic_array::GenericArray, typenum::U32}; use base64::{engine::general_purpose::STANDARD, Engine}; use rand::Rng; -use crate::CryptoError; - use super::key_encryptable::CryptoKey; +use crate::CryptoError; /// A symmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::EncString) pub struct SymmetricCryptoKey { diff --git a/crates/bitwarden/src/client/encryption_settings.rs b/crates/bitwarden/src/client/encryption_settings.rs index 2009bab28..612449cbd 100644 --- a/crates/bitwarden/src/client/encryption_settings.rs +++ b/crates/bitwarden/src/client/encryption_settings.rs @@ -1,12 +1,13 @@ use std::collections::HashMap; -#[cfg(feature = "internal")] -use crate::{client::UserLoginMethod, error::Result}; #[cfg(feature = "internal")] use bitwarden_crypto::{AsymmEncString, EncString}; use bitwarden_crypto::{AsymmetricCryptoKey, KeyContainer, SymmetricCryptoKey}; use uuid::Uuid; +#[cfg(feature = "internal")] +use crate::{client::UserLoginMethod, error::Result}; + pub struct EncryptionSettings { user_key: SymmetricCryptoKey, pub(crate) private_key: Option, From 6bf18e178e79c917c6a64dc6621994629890ddc6 Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 15 Jan 2024 10:53:28 +0100 Subject: [PATCH 26/30] Fix doc --- crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs b/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs index a4cb13d0d..a3e06800b 100644 --- a/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs +++ b/crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs @@ -3,7 +3,7 @@ use rsa::RsaPrivateKey; use super::key_encryptable::CryptoKey; use crate::error::{CryptoError, Result}; -/// An asymmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::crypto::EncString) +/// An asymmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::EncString) pub struct AsymmetricCryptoKey { pub(crate) key: RsaPrivateKey, } From f9d83e0654967c8cb6a9c8df8ff5a6c7e82de21f Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 15 Jan 2024 11:10:23 +0100 Subject: [PATCH 27/30] Remove test feature in crypto --- crates/bitwarden-crypto/src/enc_string/asymmetric.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs index 833d371e6..fad3334be 100644 --- a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs @@ -220,7 +220,6 @@ WjyxP5ZvXu7U96jaJRI8PFMoE06WeVYcdIzrID2HvqH+w0UQJFrLJ/0Mn4stFAEz XKZBokBGnjFnTnKcs7nv/O8= -----END PRIVATE KEY-----"; - #[cfg(feature = "internal")] #[test] fn test_enc_string_rsa2048_oaep_sha256_b64() { use crate::crypto::{AsymmetricCryptoKey, KeyDecryptable}; @@ -235,7 +234,6 @@ XKZBokBGnjFnTnKcs7nv/O8= assert_eq!(res, "EncryptMe!"); } - #[cfg(feature = "internal")] #[test] fn test_enc_string_rsa2048_oaep_sha1_b64() { use crate::crypto::{AsymmetricCryptoKey, KeyDecryptable}; @@ -250,7 +248,6 @@ XKZBokBGnjFnTnKcs7nv/O8= assert_eq!(res, "EncryptMe!"); } - #[cfg(feature = "internal")] #[test] fn test_enc_string_rsa2048_oaep_sha1_hmac_sha256_b64() { use crate::crypto::{AsymmetricCryptoKey, KeyDecryptable}; From f9dca857fbd7f94f6511d17590d0b504f993287c Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 15 Jan 2024 11:15:45 +0100 Subject: [PATCH 28/30] Fix tests --- crates/bitwarden-crypto/src/enc_string/asymmetric.rs | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs index fad3334be..0c48ce14a 100644 --- a/crates/bitwarden-crypto/src/enc_string/asymmetric.rs +++ b/crates/bitwarden-crypto/src/enc_string/asymmetric.rs @@ -189,7 +189,7 @@ impl schemars::JsonSchema for AsymmEncString { #[cfg(test)] mod tests { - use super::AsymmEncString; + use super::{AsymmEncString, AsymmetricCryptoKey, KeyDecryptable}; const RSA_PRIVATE_KEY: &str = "-----BEGIN PRIVATE KEY----- MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCXRVrCX+2hfOQS @@ -222,8 +222,6 @@ XKZBokBGnjFnTnKcs7nv/O8= #[test] fn test_enc_string_rsa2048_oaep_sha256_b64() { - use crate::crypto::{AsymmetricCryptoKey, KeyDecryptable}; - let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap(); let enc_str: &str = "3.YFqzW9LL/uLjCnl0RRLtndzGJ1FV27mcwQwGjfJPOVrgCX9nJSUYCCDd0iTIyOZ/zRxG47b6L1Z3qgkEfcxjmrSBq60gijc3E2TBMAg7OCLVcjORZ+i1sOVOudmOPWro6uA8refMrg4lqbieDlbLMzjVEwxfi5WpcL876cD0vYyRwvLO3bzFrsE7x33HHHtZeOPW79RqMn5efsB5Dj9wVheC9Ix9AYDjbo+rjg9qR6guwKmS7k2MSaIQlrDR7yu8LP+ePtiSjx+gszJV5jQGfcx60dtiLQzLS/mUD+RmU7B950Bpx0H7x56lT5yXZbWK5YkoP6qd8B8D2aKbP68Ywg=="; let enc_string: AsymmEncString = enc_str.parse().unwrap(); @@ -236,8 +234,6 @@ XKZBokBGnjFnTnKcs7nv/O8= #[test] fn test_enc_string_rsa2048_oaep_sha1_b64() { - use crate::crypto::{AsymmetricCryptoKey, KeyDecryptable}; - let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap(); let enc_str: &str = "4.ZheRb3PCfAunyFdQYPfyrFqpuvmln9H9w5nDjt88i5A7ug1XE0LJdQHCIYJl0YOZ1gCOGkhFu/CRY2StiLmT3iRKrrVBbC1+qRMjNNyDvRcFi91LWsmRXhONVSPjywzrJJXglsztDqGkLO93dKXNhuKpcmtBLsvgkphk/aFvxbaOvJ/FHdK/iV0dMGNhc/9tbys8laTdwBlI5xIChpRcrfH+XpSFM88+Bu03uK67N9G6eU1UmET+pISJwJvMuIDMqH+qkT7OOzgL3t6I0H2LDj+CnsumnQmDsvQzDiNfTR0IgjpoE9YH2LvPXVP2wVUkiTwXD9cG/E7XeoiduHyHjw=="; let enc_string: AsymmEncString = enc_str.parse().unwrap(); @@ -250,8 +246,6 @@ XKZBokBGnjFnTnKcs7nv/O8= #[test] fn test_enc_string_rsa2048_oaep_sha1_hmac_sha256_b64() { - use crate::crypto::{AsymmetricCryptoKey, KeyDecryptable}; - let private_key = AsymmetricCryptoKey::from_pem(RSA_PRIVATE_KEY).unwrap(); let enc_str: &str = "6.ThnNc67nNr7GELyuhGGfsXNP2zJnNqhrIsjntEQ27r2qmn8vwdHbTbfO0cwt6YgSibDN0PjiCZ1O3Wb/IFq+vwvyRwFqF9145wBF8CQCbkhV+M0XvO99kh0daovtt120Nve/5ETI5PbPag9VdalKRQWZypJaqQHm5TAQVf4F5wtLlCLMBkzqTk+wkFe7BPMTGn07T+O3eJbTxXvyMZewQ7icJF0MZVA7VyWX9qElmZ89FCKowbf1BMr5pbcQ+0KdXcSVW3to43VkTp7k7COwsuH3M/i1AuVP5YN8ixjyRpvaeGqX/ap2nCHK2Wj5VxgCGT7XEls6ZknnAp9nB9qVjQ==|s3ntw5H/KKD/qsS0lUghTHl5Sm9j6m7YEdNHf0OeAFQ="; let enc_string: AsymmEncString = enc_str.parse().unwrap(); From fb300ba02178ed21d036b3892858e5b2e69c529b Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 15 Jan 2024 12:10:10 +0100 Subject: [PATCH 29/30] Remove crypto/mod.rs, remove rsa from bitwarden crate --- Cargo.lock | 1 - crates/bitwarden/Cargo.toml | 1 - crates/bitwarden/src/crypto/mod.rs | 97 ------------------------------ 3 files changed, 99 deletions(-) delete mode 100644 crates/bitwarden/src/crypto/mod.rs diff --git a/Cargo.lock b/Cargo.lock index a2d2fd6cc..7a2afa40e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -358,7 +358,6 @@ dependencies = [ "rand 0.8.5", "rand_chacha 0.3.1", "reqwest", - "rsa", "rustls-platform-verifier", "schemars", "serde", diff --git a/crates/bitwarden/Cargo.toml b/crates/bitwarden/Cargo.toml index 34f92836a..d69279881 100644 --- a/crates/bitwarden/Cargo.toml +++ b/crates/bitwarden/Cargo.toml @@ -44,7 +44,6 @@ rand = ">=0.8.5, <0.9" reqwest = { version = ">=0.11, <0.12", features = [ "json", ], default-features = false } -rsa = ">=0.9.2, <0.10" schemars = { version = ">=0.8.9, <0.9", features = ["uuid1", "chrono"] } serde = { version = ">=1.0, <2.0", features = ["derive"] } serde_json = ">=1.0.96, <2.0" diff --git a/crates/bitwarden/src/crypto/mod.rs b/crates/bitwarden/src/crypto/mod.rs deleted file mode 100644 index f21fdb256..000000000 --- a/crates/bitwarden/src/crypto/mod.rs +++ /dev/null @@ -1,97 +0,0 @@ -//! # Cryptographic primitives -//! -//! This module contains the cryptographic primitives used throughout the SDK. The module makes a -//! best effort to abstract away cryptographic concepts into concepts such as -//! [`EncString`], [`SymmetricCryptoKey`] and [`AsymmetricCryptoKey`]. -//! -//! ## Conventions: -//! -//! - Pure Functions that deterministically "derive" keys from input are prefixed with `derive_`. -//! - Functions that generate new keys are prefixed with `make_`. -//! -//! ## Differences from [`clients`](https://github.com/bitwarden/clients) -//! -//! There are some noteworthy differences compared to the other Bitwarden clients. These changes -//! are made in an effort to introduce conventions in how we name things, improve best practices -//! and abstracting away internal complexity. -//! -//! - `CryptoService.makeSendKey` & `AccessService.createAccessToken` are replaced by the generic -//! `derive_shareable_key` -//! - MasterKey operations such as `makeMasterKey` and `hashMasterKey` are moved to the MasterKey -//! struct. -//! - -use aes::cipher::{generic_array::GenericArray, ArrayLength, Unsigned}; -use hmac::digest::OutputSizeUser; -#[cfg(any(test, feature = "internal"))] -use rand::{ - distributions::{Distribution, Standard}, - Rng, -}; - -use crate::error::Result; - -mod enc_string; -pub use enc_string::{AsymmEncString, EncString}; -mod encryptable; -pub use encryptable::{Decryptable, Encryptable, LocateKey}; -mod key_encryptable; -pub use key_encryptable::{CryptoKey, KeyDecryptable, KeyEncryptable}; -mod aes_ops; -use aes_ops::{decrypt_aes256_hmac, encrypt_aes256_hmac}; -mod symmetric_crypto_key; -pub use symmetric_crypto_key::SymmetricCryptoKey; -mod asymmetric_crypto_key; -pub use asymmetric_crypto_key::AsymmetricCryptoKey; - -mod shareable_key; -pub(crate) use shareable_key::derive_shareable_key; - -#[cfg(feature = "internal")] -mod master_key; -#[cfg(feature = "internal")] -pub use master_key::HashPurpose; -#[cfg(feature = "internal")] -pub(crate) use master_key::MasterKey; -#[cfg(feature = "internal")] -mod user_key; -#[cfg(feature = "internal")] -pub(crate) use user_key::UserKey; -#[cfg(feature = "internal")] -mod rsa; -#[cfg(feature = "internal")] -pub use self::rsa::RsaKeyPair; - -#[cfg(feature = "internal")] -mod fingerprint; -#[cfg(feature = "internal")] -pub(crate) use fingerprint::fingerprint; - -pub(crate) type PbkdfSha256Hmac = hmac::Hmac; -pub(crate) const PBKDF_SHA256_HMAC_OUT_SIZE: usize = - <::OutputSize as Unsigned>::USIZE; - -/// RFC5869 HKDF-Expand operation -fn hkdf_expand>(prk: &[u8], info: Option<&str>) -> Result> { - let hkdf = hkdf::Hkdf::::from_prk(prk).map_err(|_| "invalid prk length")?; - let mut key = GenericArray::::default(); - - let i = info.map(|i| i.as_bytes()).unwrap_or(&[]); - hkdf.expand(i, &mut key).map_err(|_| "invalid length")?; - - Ok(key) -} - -/// Generate random bytes that are cryptographically secure -#[cfg(any(test, feature = "internal"))] -pub(crate) fn generate_random_bytes() -> T -where - Standard: Distribution, -{ - rand::thread_rng().gen() -} - -pub fn pbkdf2(password: &[u8], salt: &[u8], rounds: u32) -> [u8; PBKDF_SHA256_HMAC_OUT_SIZE] { - pbkdf2::pbkdf2_array::(password, salt, rounds) - .expect("hash is a valid fixed size") -} From cf2a3b682b5a903feb925ca5eafe504fe2a0497d Mon Sep 17 00:00:00 2001 From: Hinton Date: Mon, 15 Jan 2024 15:44:14 +0100 Subject: [PATCH 30/30] Update bump and publish workflows --- .github/workflows/publish-rust-crates.yml | 11 +++++++++++ .github/workflows/version-bump.yml | 11 +++++++++-- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/.github/workflows/publish-rust-crates.yml b/.github/workflows/publish-rust-crates.yml index aef94b37e..231ad5626 100644 --- a/.github/workflows/publish-rust-crates.yml +++ b/.github/workflows/publish-rust-crates.yml @@ -29,6 +29,11 @@ on: required: true default: true type: boolean + publish_bitwarden-crypto: + description: "Publish bitwarden-crypto crate" + required: true + default: true + type: boolean defaults: run: @@ -61,6 +66,7 @@ jobs: PUBLISH_BITWARDEN: ${{ github.event.inputs.publish_bitwarden }} PUBLISH_BITWARDEN_API_API: ${{ github.event.inputs.publish_bitwarden-api-api }} PUBLISH_BITWARDEN_API_IDENTITY: ${{ github.event.inputs.publish_bitwarden-api-identity }} + PUBLISH_BITWARDEN_CRYPTO: ${{ github.event.inputs.publish_bitwarden-crypto }} run: | if [[ "$PUBLISH_BITWARDEN" == "false" ]] && [[ "$PUBLISH_BITWARDEN_API_API" == "false" ]] && [[ "$PUBLISH_BITWARDEN_API_IDENTITY" == "false" ]]; then echo "===================================" @@ -87,6 +93,11 @@ jobs: PACKAGES_LIST="$PACKAGES_LIST bitwarden-api-identity" fi + if [[ "$PUBLISH_BITWARDEN_CRYPTO" == "true" ]]; then + PACKAGES_COMMAND="$PACKAGES_COMMAND -p bitwarden-crypto" + PACKAGES_LIST="$PACKAGES_LIST bitwarden-crypto" + fi + echo "Packages command: " $PACKAGES_COMMAND echo "Packages list: " $PACKAGES_LIST diff --git a/.github/workflows/version-bump.yml b/.github/workflows/version-bump.yml index b27a6a989..f3c428c57 100644 --- a/.github/workflows/version-bump.yml +++ b/.github/workflows/version-bump.yml @@ -10,12 +10,13 @@ on: required: true type: choice options: - - napi - bitwarden - bitwarden-api-api - bitwarden-api-identity - - cli + - bitwarden-crypto - bitwarden-json + - cli + - napi version_number: description: "New version (example: '2024.1.0')" required: true @@ -116,6 +117,12 @@ jobs: if: ${{ inputs.project == 'bitwarden-api-identity' }} run: cargo-set-version set-version -p bitwarden-api-identity ${{ inputs.version_number }} + ### bitwarden-crypto + + - name: Bump bitwarden-crypto crate Version + if: ${{ inputs.project == 'bitwarden-crypto' }} + run: cargo-set-version set-version -p bitwarden-crypto ${{ inputs.version_number }} + ### cli - name: Bump cli Version