Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. Weโ€™ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make client internally mutable #837

Merged
merged 9 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/bitwarden-crypto/src/keys/asymmetric_crypto_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ impl AsymmetricEncryptable for AsymmetricPublicCryptoKey {

/// An asymmetric encryption key. Contains both the public and private key. Can be used to both
/// encrypt and decrypt [`AsymmetricEncString`](crate::AsymmetricEncString).
#[derive(Clone)]
pub struct AsymmetricCryptoKey {
// RsaPrivateKey is not a Copy type so this isn't completely necessary, but
// to keep the compiler from making stack copies when moving this struct around,
Expand Down
8 changes: 7 additions & 1 deletion crates/bitwarden-crypto/src/keys/key_encryptable.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{collections::HashMap, hash::Hash};
use std::{collections::HashMap, hash::Hash, sync::Arc};

use rayon::prelude::*;
use uuid::Uuid;
Expand All @@ -9,6 +9,12 @@ pub trait KeyContainer: Send + Sync {
fn get_key(&self, org_id: &Option<Uuid>) -> Option<&SymmetricCryptoKey>;
}

impl<T: KeyContainer> KeyContainer for Arc<T> {
fn get_key(&self, org_id: &Option<Uuid>) -> Option<&SymmetricCryptoKey> {
self.as_ref().get_key(org_id)
}
}

pub trait LocateKey {
fn locate_key<'a>(
&self,
Expand Down
1 change: 1 addition & 0 deletions crates/bitwarden-crypto/src/keys/symmetric_crypto_key.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use super::key_encryptable::CryptoKey;
use crate::CryptoError;

/// A symmetric encryption key. Used to encrypt and decrypt [`EncString`](crate::EncString)
#[derive(Clone)]
pub struct SymmetricCryptoKey {
// GenericArray is equivalent to [u8; N], which is a Copy type placed on the stack.
// To keep the compiler from making stack copies when moving this struct around,
Expand Down
58 changes: 18 additions & 40 deletions crates/bitwarden-uniffi/src/auth/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,31 +14,27 @@
#[uniffi::export(async_runtime = "tokio")]
impl ClientAuth {
/// **API Draft:** Calculate Password Strength
pub async fn password_strength(
pub fn password_strength(

Check warning on line 17 in crates/bitwarden-uniffi/src/auth/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/auth/mod.rs#L17

Added line #L17 was not covered by tests
&self,
password: String,
email: String,
additional_inputs: Vec<String>,
) -> u8 {
self.0
.0
.write()
.await
.auth()
.password_strength(password, email, additional_inputs)
}

/// Evaluate if the provided password satisfies the provided policy
pub async fn satisfies_policy(
pub fn satisfies_policy(

Check warning on line 30 in crates/bitwarden-uniffi/src/auth/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/auth/mod.rs#L30

Added line #L30 was not covered by tests
&self,
password: String,
strength: u8,
policy: MasterPasswordPolicyOptions,
) -> bool {
self.0
.0
.write()
.await
.auth()
.satisfies_policy(password, strength, &policy)
}
Expand All @@ -54,54 +50,44 @@
Ok(self
.0
.0
.read()
.await
.kdf()
.hash_password(email, password, kdf_params, purpose)
.await?)
}

/// Generate keys needed for registration process
pub async fn make_register_keys(
pub fn make_register_keys(

Check warning on line 59 in crates/bitwarden-uniffi/src/auth/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/auth/mod.rs#L59

Added line #L59 was not covered by tests
&self,
email: String,
password: String,
kdf: Kdf,
) -> Result<RegisterKeyResponse> {
Ok(self
.0
.0
.write()
.await
.auth()
.make_register_keys(email, password, kdf)?)
Ok(self.0 .0.auth().make_register_keys(email, password, kdf)?)

Check warning on line 65 in crates/bitwarden-uniffi/src/auth/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/auth/mod.rs#L65

Added line #L65 was not covered by tests
}

/// Generate keys needed for TDE process
pub async fn make_register_tde_keys(
pub fn make_register_tde_keys(

Check warning on line 69 in crates/bitwarden-uniffi/src/auth/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/auth/mod.rs#L69

Added line #L69 was not covered by tests
&self,
email: String,
org_public_key: String,
remember_device: bool,
) -> Result<RegisterTdeKeyResponse> {
Ok(self.0 .0.write().await.auth().make_register_tde_keys(
email,
org_public_key,
remember_device,
)?)
Ok(self
.0
.0
.auth()
.make_register_tde_keys(email, org_public_key, remember_device)?)

Check warning on line 79 in crates/bitwarden-uniffi/src/auth/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/auth/mod.rs#L75-L79

Added lines #L75 - L79 were not covered by tests
}

/// Validate the user password
///
/// To retrieve the user's password hash, use [`ClientAuth::hash_password`] with
/// `HashPurpose::LocalAuthentication` during login and persist it. If the login method has no
/// password, use the email OTP.
pub async fn validate_password(&self, password: String, password_hash: String) -> Result<bool> {
pub fn validate_password(&self, password: String, password_hash: String) -> Result<bool> {

Check warning on line 87 in crates/bitwarden-uniffi/src/auth/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/auth/mod.rs#L87

Added line #L87 was not covered by tests
Ok(self
.0
.0
.write()
.await
.auth()
.validate_password(password, password_hash)?)
}
Expand All @@ -112,38 +98,30 @@
/// password. Some example are login with device or TDE.
///
/// This works by comparing the provided password against the encrypted user key.
pub async fn validate_password_user_key(
pub fn validate_password_user_key(

Check warning on line 101 in crates/bitwarden-uniffi/src/auth/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/auth/mod.rs#L101

Added line #L101 was not covered by tests
&self,
password: String,
encrypted_user_key: String,
) -> Result<String> {
Ok(self
.0
.0
.write()
.await
.auth()
.validate_password_user_key(password, encrypted_user_key)?)
}

/// Initialize a new auth request
pub async fn new_auth_request(&self, email: String) -> Result<AuthRequestResponse> {
Ok(self.0 .0.write().await.auth().new_auth_request(&email)?)
pub fn new_auth_request(&self, email: String) -> Result<AuthRequestResponse> {
Ok(self.0 .0.auth().new_auth_request(&email)?)

Check warning on line 115 in crates/bitwarden-uniffi/src/auth/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/auth/mod.rs#L114-L115

Added lines #L114 - L115 were not covered by tests
}

/// Approve an auth request
pub async fn approve_auth_request(&self, public_key: String) -> Result<AsymmetricEncString> {
Ok(self
.0
.0
.write()
.await
.auth()
.approve_auth_request(public_key)?)
pub fn approve_auth_request(&self, public_key: String) -> Result<AsymmetricEncString> {
Ok(self.0 .0.auth().approve_auth_request(public_key)?)

Check warning on line 120 in crates/bitwarden-uniffi/src/auth/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/auth/mod.rs#L119-L120

Added lines #L119 - L120 were not covered by tests
}

/// Trust the current device
pub async fn trust_device(&self) -> Result<TrustDeviceResponse> {
Ok(self.0 .0.write().await.auth().trust_device()?)
pub fn trust_device(&self) -> Result<TrustDeviceResponse> {
Ok(self.0 .0.auth().trust_device()?)

Check warning on line 125 in crates/bitwarden-uniffi/src/auth/mod.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/auth/mod.rs#L124-L125

Added lines #L124 - L125 were not covered by tests
}
}
64 changes: 11 additions & 53 deletions crates/bitwarden-uniffi/src/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,83 +15,41 @@
/// Initialization method for the user crypto. Needs to be called before any other crypto
/// operations.
pub async fn initialize_user_crypto(&self, req: InitUserCryptoRequest) -> Result<()> {
Ok(self
.0
.0
.write()
.await
.crypto()
.initialize_user_crypto(req)
.await?)
Ok(self.0 .0.crypto().initialize_user_crypto(req).await?)

Check warning on line 18 in crates/bitwarden-uniffi/src/crypto.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/crypto.rs#L18

Added line #L18 was not covered by tests
}

/// Initialization method for the organization crypto. Needs to be called after
/// `initialize_user_crypto` but before any other crypto operations.
pub async fn initialize_org_crypto(&self, req: InitOrgCryptoRequest) -> Result<()> {
Ok(self
.0
.0
.write()
.await
.crypto()
.initialize_org_crypto(req)
.await?)
Ok(self.0 .0.crypto().initialize_org_crypto(req).await?)

Check warning on line 24 in crates/bitwarden-uniffi/src/crypto.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/crypto.rs#L24

Added line #L24 was not covered by tests
}

/// Get the uses's decrypted encryption key. Note: It's very important
/// to keep this key safe, as it can be used to decrypt all of the user's data
pub async fn get_user_encryption_key(&self) -> Result<String> {
Ok(self
.0
.0
.write()
.await
.crypto()
.get_user_encryption_key()
.await?)
Ok(self.0 .0.crypto().get_user_encryption_key().await?)

Check warning on line 30 in crates/bitwarden-uniffi/src/crypto.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/crypto.rs#L30

Added line #L30 was not covered by tests
}

/// Update the user's password, which will re-encrypt the user's encryption key with the new
/// password. This returns the new encrypted user key and the new password hash.
pub async fn update_password(&self, new_password: String) -> Result<UpdatePasswordResponse> {
Ok(self
.0
.0
.write()
.await
.crypto()
.update_password(new_password)?)
pub fn update_password(&self, new_password: String) -> Result<UpdatePasswordResponse> {
Ok(self.0 .0.crypto().update_password(new_password)?)

Check warning on line 36 in crates/bitwarden-uniffi/src/crypto.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/crypto.rs#L35-L36

Added lines #L35 - L36 were not covered by tests
}

/// Generates a PIN protected user key from the provided PIN. The result can be stored and later
/// used to initialize another client instance by using the PIN and the PIN key with
/// `initialize_user_crypto`.
pub async fn derive_pin_key(&self, pin: String) -> Result<DerivePinKeyResponse> {
Ok(self.0 .0.write().await.crypto().derive_pin_key(pin)?)
pub fn derive_pin_key(&self, pin: String) -> Result<DerivePinKeyResponse> {
Ok(self.0 .0.crypto().derive_pin_key(pin)?)

Check warning on line 43 in crates/bitwarden-uniffi/src/crypto.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/crypto.rs#L42-L43

Added lines #L42 - L43 were not covered by tests
}

/// Derives the pin protected user key from encrypted pin. Used when pin requires master
/// password on first unlock.
pub async fn derive_pin_user_key(&self, encrypted_pin: EncString) -> Result<EncString> {
Ok(self
.0
.0
.write()
.await
.crypto()
.derive_pin_user_key(encrypted_pin)?)
pub fn derive_pin_user_key(&self, encrypted_pin: EncString) -> Result<EncString> {
Ok(self.0 .0.crypto().derive_pin_user_key(encrypted_pin)?)

Check warning on line 49 in crates/bitwarden-uniffi/src/crypto.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/crypto.rs#L48-L49

Added lines #L48 - L49 were not covered by tests
}

pub async fn enroll_admin_password_reset(
&self,
public_key: String,
) -> Result<AsymmetricEncString> {
Ok(self
.0
.0
.write()
.await
.crypto()
.enroll_admin_password_reset(public_key)?)
pub fn enroll_admin_password_reset(&self, public_key: String) -> Result<AsymmetricEncString> {
Ok(self.0 .0.crypto().enroll_admin_password_reset(public_key)?)

Check warning on line 53 in crates/bitwarden-uniffi/src/crypto.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/crypto.rs#L52-L53

Added lines #L52 - L53 were not covered by tests
}
}
5 changes: 2 additions & 3 deletions crates/bitwarden-uniffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

use std::sync::Arc;

use async_lock::RwLock;
use auth::ClientAuth;
use bitwarden::client::client_settings::ClientSettings;

Expand All @@ -24,15 +23,15 @@
use vault::ClientVault;

#[derive(uniffi::Object)]
pub struct Client(RwLock<bitwarden::Client>);
pub struct Client(bitwarden::Client);

#[uniffi::export]
impl Client {
/// Initialize a new instance of the SDK client
#[uniffi::constructor]
pub fn new(settings: Option<ClientSettings>) -> Arc<Self> {
init_logger();
Arc::new(Self(RwLock::new(bitwarden::Client::new(settings))))
Arc::new(Self(bitwarden::Client::new(settings)))

Check warning on line 34 in crates/bitwarden-uniffi/src/lib.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/lib.rs#L34

Added line #L34 was not covered by tests
}

/// Crypto operations
Expand Down
30 changes: 10 additions & 20 deletions crates/bitwarden-uniffi/src/platform/fido2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,8 @@
&self,
request: MakeCredentialRequest,
) -> Result<MakeCredentialResult> {
let mut client = self.0 .0.write().await;

let mut platform = client.platform();
let mut fido2 = platform.fido2();
let platform = self.0 .0.platform();
let fido2 = platform.fido2();

Check warning on line 61 in crates/bitwarden-uniffi/src/platform/fido2.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/platform/fido2.rs#L60-L61

Added lines #L60 - L61 were not covered by tests
let ui = UniffiTraitBridge(self.1.as_ref());
let cs = UniffiTraitBridge(self.2.as_ref());
let mut auth = fido2.create_authenticator(&ui, &cs);
Expand All @@ -73,10 +71,8 @@
}

pub async fn get_assertion(&self, request: GetAssertionRequest) -> Result<GetAssertionResult> {
let mut client = self.0 .0.write().await;

let mut platform = client.platform();
let mut fido2 = platform.fido2();
let platform = self.0 .0.platform();
let fido2 = platform.fido2();

Check warning on line 75 in crates/bitwarden-uniffi/src/platform/fido2.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/platform/fido2.rs#L74-L75

Added lines #L74 - L75 were not covered by tests
let ui = UniffiTraitBridge(self.1.as_ref());
let cs = UniffiTraitBridge(self.2.as_ref());
let mut auth = fido2.create_authenticator(&ui, &cs);
Expand All @@ -92,10 +88,8 @@
&self,
rp_id: String,
) -> Result<Vec<Fido2CredentialView>> {
let mut client = self.0 .0.write().await;

let mut platform = client.platform();
let mut fido2 = platform.fido2();
let platform = self.0 .0.platform();
let fido2 = platform.fido2();

Check warning on line 92 in crates/bitwarden-uniffi/src/platform/fido2.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/platform/fido2.rs#L91-L92

Added lines #L91 - L92 were not covered by tests
let ui = UniffiTraitBridge(self.1.as_ref());
let cs = UniffiTraitBridge(self.2.as_ref());
let mut auth = fido2.create_authenticator(&ui, &cs);
Expand All @@ -119,10 +113,8 @@
request: String,
client_data: ClientData,
) -> Result<PublicKeyCredentialAuthenticatorAttestationResponse> {
let mut client = self.0 .0 .0.write().await;

let mut platform = client.platform();
let mut fido2 = platform.fido2();
let platform = self.0 .0 .0.platform();
let fido2 = platform.fido2();

Check warning on line 117 in crates/bitwarden-uniffi/src/platform/fido2.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/platform/fido2.rs#L116-L117

Added lines #L116 - L117 were not covered by tests
let ui = UniffiTraitBridge(self.0 .1.as_ref());
let cs = UniffiTraitBridge(self.0 .2.as_ref());
let mut client = fido2.create_client(&ui, &cs);
Expand All @@ -140,10 +132,8 @@
request: String,
client_data: ClientData,
) -> Result<PublicKeyCredentialAuthenticatorAssertionResponse> {
let mut client = self.0 .0 .0.write().await;

let mut platform = client.platform();
let mut fido2 = platform.fido2();
let platform = self.0 .0 .0.platform();
let fido2 = platform.fido2();

Check warning on line 136 in crates/bitwarden-uniffi/src/platform/fido2.rs

View check run for this annotation

Codecov / codecov/patch

crates/bitwarden-uniffi/src/platform/fido2.rs#L135-L136

Added lines #L135 - L136 were not covered by tests
let ui = UniffiTraitBridge(self.0 .1.as_ref());
let cs = UniffiTraitBridge(self.0 .2.as_ref());
let mut client = fido2.create_client(&ui, &cs);
Expand Down
Loading
Loading