Skip to content

Commit

Permalink
Initial CryptoService impl
Browse files Browse the repository at this point in the history
  • Loading branch information
dani-garcia committed Aug 19, 2024
1 parent 449788a commit 7e9bd88
Show file tree
Hide file tree
Showing 14 changed files with 1,846 additions and 0 deletions.
78 changes: 78 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

116 changes: 116 additions & 0 deletions crates/bitwarden-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,119 @@ mod util;

pub use bitwarden_crypto::ZeroizingAllocator;
pub use client::{Client, ClientSettings, DeviceType};

#[allow(warnings)]
#[cfg(test)]
mod testcrypto {

// TEST IMPL OF THE NEW ENCRYPTABLE/DECRYPTABLE TRAITS
// Note that these never touch the keys at all, they just use the context and key references to
// encrypt/decrypt

use bitwarden_crypto::{
key_refs, service::*, AsymmetricCryptoKey, CryptoError, EncString, KeyEncryptable,
SymmetricCryptoKey,
};

key_refs! {
#[symmetric]
pub enum MySymmKeyRef {
User,
Organization(uuid::Uuid),
#[local]
Local(&'static str),
}

#[asymmetric]
pub enum MyAsymmKeyRef {
UserPrivateKey,
#[local]
Local(&'static str),
}
}

#[derive(Clone)]
struct Cipher {
key: Option<EncString>,
name: EncString,
}

#[derive(Clone)]
struct CipherView {
key: Option<EncString>,
name: String,
}

const CIPHER_KEY: MySymmKeyRef = MySymmKeyRef::Local("cipher_key");

impl Encryptable<MySymmKeyRef, MyAsymmKeyRef, MySymmKeyRef, Cipher> for CipherView {
fn encrypt(
&self,
ctx: &mut CryptoServiceContext<MySymmKeyRef, MyAsymmKeyRef>,
key: MySymmKeyRef,
) -> Result<Cipher, bitwarden_crypto::CryptoError> {
let cipher_key = match &self.key {
Some(cipher_key) => {
ctx.decrypt_and_store_symmetric_key(key, CIPHER_KEY, cipher_key)?
}
None => key,
};

Ok(Cipher {
key: self.key.clone(),
name: self.name.encrypt(ctx, cipher_key)?,
})
}
}

impl Decryptable<MySymmKeyRef, MyAsymmKeyRef, MySymmKeyRef, CipherView> for Cipher {
fn decrypt(
&self,
ctx: &mut CryptoServiceContext<MySymmKeyRef, MyAsymmKeyRef>,
key: MySymmKeyRef,
) -> Result<CipherView, CryptoError> {
let cipher_key = match &self.key {
Some(cipher_key) => {
ctx.decrypt_and_store_symmetric_key(key, CIPHER_KEY, cipher_key)?
}
None => key,
};

Ok(CipherView {
key: self.key.clone(),
name: self.name.decrypt(ctx, cipher_key)?,
})
}
}

#[test]
fn test_cipher() {
let user_key = SymmetricCryptoKey::generate(rand::thread_rng());

let org_id = uuid::Uuid::parse_str("91b000b6-81ce-47f4-9802-3390e0b895ed").unwrap();
let org_key = SymmetricCryptoKey::generate(rand::thread_rng());

let cipher_key = SymmetricCryptoKey::generate(rand::thread_rng());
let cipher_key_user_enc = cipher_key.to_vec().encrypt_with_key(&user_key).unwrap();
let cipher_view = CipherView {
key: Some(cipher_key_user_enc.clone()),
name: "test".to_string(),
};

let service: CryptoService<MySymmKeyRef, MyAsymmKeyRef> = CryptoService::new();
// Ideally we'd decrypt the keys directly into the service, but that's not implemented yet
#[allow(deprecated)]
{
service.insert_symmetric_key(MySymmKeyRef::User, user_key);
service.insert_symmetric_key(MySymmKeyRef::Organization(org_id), org_key);
}

let cipher_enc2 = service
.encrypt(MySymmKeyRef::User, cipher_view.clone())
.unwrap();

let cipher_view2 = service.decrypt(MySymmKeyRef::User, &cipher_enc2).unwrap();

assert_eq!(cipher_view.name, cipher_view2.name);
}
}
1 change: 1 addition & 0 deletions crates/bitwarden-crypto/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ cbc = { version = ">=0.1.2, <0.2", features = ["alloc", "zeroize"] }
generic-array = { version = ">=0.14.7, <1.0", features = ["zeroize"] }
hkdf = ">=0.12.3, <0.13"
hmac = ">=0.12.1, <0.13"
memsec = { version = "0.7.0", features = ["alloc_ext"] }
num-bigint = ">=0.4, <0.5"
num-traits = ">=0.2.15, <0.3"
pbkdf2 = { version = ">=0.12.1, <0.13", default-features = false }
Expand Down
2 changes: 2 additions & 0 deletions crates/bitwarden-crypto/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ pub enum CryptoError {
MissingKey(Uuid),
#[error("The item was missing a required field: {0}")]
MissingField(&'static str),
#[error("Missing Key for Ref. {0}")]
MissingKey2(String),

#[error("EncString error, {0}")]
EncString(#[from] EncStringParseError),
Expand Down
1 change: 1 addition & 0 deletions crates/bitwarden-crypto/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ mod wordlist;
pub use wordlist::EFF_LONG_WORD_LIST;
mod allocator;
pub use allocator::ZeroizingAllocator;
pub mod service;

#[cfg(feature = "uniffi")]
uniffi::setup_scaffolding!();
Expand Down
Loading

0 comments on commit 7e9bd88

Please sign in to comment.