Skip to content

Commit

Permalink
Merge branch 'ps/rusttls' into SM-989-...
Browse files Browse the repository at this point in the history
  • Loading branch information
tangowithfoxtrot committed Nov 20, 2023
2 parents c72e4ba + ebd103e commit d8f0b84
Show file tree
Hide file tree
Showing 32 changed files with 677 additions and 398 deletions.
473 changes: 290 additions & 183 deletions Cargo.lock

Large diffs are not rendered by default.

12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ codegen-units = 1
# This is fine as long as we don't have any unhandled panics, but let's keep it disabled for now
# strip = true

# Using master until 0.25.1 is released to fix https://github.com/mozilla/uniffi-rs/issues/1798
# Using git dependency temporarily to add support for immutable records in generated code
[patch.crates-io]
uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" }
uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" }
uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" }
uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" }
uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "b369e7c15b1b7ebca34de9028209db11b7ff353d" }
uniffi = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" }
uniffi_build = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" }
uniffi_bindgen = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" }
uniffi_core = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" }
uniffi_macros = { git = "https://github.com/mozilla/uniffi-rs", rev = "0a03b713306d6ce3de033157fc2ce92a238c2e24" }
1 change: 1 addition & 0 deletions crates/bitwarden-api-api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ uuid = { version = "^1.3.3", features = ["serde"] }
[dependencies.reqwest]
version = "^0.11.18"
features = ["json", "multipart"]
default-features = false

[dev-dependencies]
1 change: 1 addition & 0 deletions crates/bitwarden-api-identity/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@ uuid = { version = "^1.3.3", features = ["serde"] }
[dependencies.reqwest]
version = "^0.11.18"
features = ["json", "multipart"]
default-features = false

[dev-dependencies]
8 changes: 7 additions & 1 deletion crates/bitwarden-json/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,19 @@ edition = "2021"
rust-version = "1.57"

[features]
default = ["use_native_tls"]

internal = ["bitwarden/internal"] # Internal testing methods
secrets = ["bitwarden/secrets"] # Secrets manager API

use_native_tls = ["bitwarden/use_native_tls"]
use_native_tls_vendored = ["bitwarden/use_native_tls_vendored"]
use_rustls = ["bitwarden/use_rustls"]

[dependencies]
schemars = ">=0.8.12, <0.9"
serde = { version = ">=1.0, <2.0", features = ["derive"] }
serde_json = ">=1.0.96, <2.0"
log = ">=0.4.18, <0.5"

bitwarden = { path = "../bitwarden" }
bitwarden = { path = "../bitwarden", default-features = false }
6 changes: 3 additions & 3 deletions crates/bitwarden-napi/package-lock.json

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

1 change: 0 additions & 1 deletion crates/bitwarden-napi/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
extern crate log;

use bitwarden_json::client::Client as JsonClient;
use napi::bindgen_prelude::*;
use napi_derive::napi;

#[napi]
Expand Down
11 changes: 5 additions & 6 deletions crates/bitwarden-py/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,17 @@ name = "bitwarden_py"
crate-type = ["cdylib"]

[dependencies]
pyo3 = { version = "0.19.1", features = ["extension-module"] }
pyo3-log = "0.8.3"
pyo3 = { version = "0.20.0", features = ["extension-module"] }
pyo3-log = "0.9.0"

bitwarden-json = { path = "../bitwarden-json", features = ["secrets"] }
openssl = { version = "0.10", features = ["vendored"] }
bitwarden-json = { path = "../bitwarden-json", features = ["secrets", "use_rustls"], default-features = false }

[build-dependencies]
pyo3-build-config = { version = "0.19.1" }
pyo3-build-config = { version = "0.20.0" }

[target.'cfg(not(target_arch="wasm32"))'.dependencies]
tokio = { version = "1.28.2", features = ["rt-multi-thread", "macros"] }
pyo3-asyncio = { version = "0.19.0", features = [
pyo3-asyncio = { version = "0.20.0", features = [
"attributes",
"tokio-runtime",
] }
7 changes: 2 additions & 5 deletions crates/bitwarden-uniffi/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,10 @@ chrono = { version = ">=0.4.26, <0.5", features = [
"std",
], default-features = false }
env_logger = "0.10.0"
uniffi = "=0.25.0"
uniffi = "=0.25.1"
schemars = { version = ">=0.8, <0.9", optional = true }

bitwarden = { path = "../bitwarden", features = ["mobile", "internal"] }

[build-dependencies]
uniffi = { version = "=0.25.0", features = ["build"] }

[target.'cfg(any(target_os = "android", target_os = "ios"))'.dependencies]
openssl = { version = "0.10", features = ["vendored"] }
uniffi = { version = "=0.25.1", features = ["build"] }
1 change: 1 addition & 0 deletions crates/bitwarden-uniffi/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
```bash
cargo +nightly rustdoc -p bitwarden -- -Zunstable-options --output-format json
cargo +nightly rustdoc -p bitwarden-uniffi -- -Zunstable-options --output-format json
npm run schemas

npx ts-node ./support/docs/docs.ts > languages/kotlin/doc.md
```
35 changes: 35 additions & 0 deletions crates/bitwarden-uniffi/src/crypto.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use std::sync::Arc;

use bitwarden::mobile::crypto::{InitOrgCryptoRequest, InitUserCryptoRequest};

use crate::{error::Result, Client};

#[derive(uniffi::Object)]
pub struct ClientCrypto(pub(crate) Arc<Client>);

#[uniffi::export]
impl ClientCrypto {
/// 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?)
}

/// 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?)
}
}
5 changes: 3 additions & 2 deletions crates/bitwarden-uniffi/src/docs.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bitwarden::{
auth::password::MasterPasswordPolicyOptions,
client::kdf::Kdf,
mobile::crypto::InitCryptoRequest,
mobile::crypto::{InitOrgCryptoRequest, InitUserCryptoRequest},
tool::{ExportFormat, PassphraseGeneratorRequest, PasswordGeneratorRequest},
vault::{
Cipher, CipherView, Collection, Folder, FolderView, Send, SendListView, SendView,
Expand All @@ -24,7 +24,8 @@ pub enum DocRef {
SendListView(SendListView),

// Crypto
InitCryptoRequest(InitCryptoRequest),
InitUserCryptoRequest(InitUserCryptoRequest),
InitOrgCryptoRequest(InitOrgCryptoRequest),

// Generators
PasswordGeneratorRequest(PasswordGeneratorRequest),
Expand Down
22 changes: 3 additions & 19 deletions crates/bitwarden-uniffi/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ use std::sync::Arc;

use async_lock::RwLock;
use auth::ClientAuth;
use bitwarden::{client::client_settings::ClientSettings, mobile::crypto::InitCryptoRequest};
use bitwarden::client::client_settings::ClientSettings;

pub mod auth;
pub mod crypto;
mod error;
pub mod tool;
mod uniffi_support;
Expand All @@ -15,16 +16,14 @@ pub mod vault;
#[cfg(feature = "docs")]
pub mod docs;

use crypto::ClientCrypto;
use error::Result;
use tool::ClientGenerators;
use vault::ClientVault;

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

#[derive(uniffi::Object)]
pub struct ClientCrypto(Arc<Client>);

#[uniffi::export]
impl Client {
/// Initialize a new instance of the SDK client
Expand Down Expand Up @@ -58,18 +57,3 @@ impl Client {
msg
}
}

#[uniffi::export]
impl ClientCrypto {
/// Initialization method for the crypto. Needs to be called before any other crypto operations.
pub async fn initialize_crypto(&self, req: InitCryptoRequest) -> Result<()> {
Ok(self
.0
.0
.write()
.await
.crypto()
.initialize_crypto(req)
.await?)
}
}
2 changes: 2 additions & 0 deletions crates/bitwarden-uniffi/uniffi.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
[bindings.kotlin]
package_name = "com.bitwarden.sdk"
cdylib_name = "bitwarden_uniffi"
generate_immutable_records = true

[bindings.swift]
ffi_module_name = "BitwardenFFI"
module_name = "BitwardenSDK"
generate_immutable_records = true
2 changes: 1 addition & 1 deletion crates/bitwarden-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ crate-type = ["cdylib", "rlib"]
[dependencies]
js-sys = "0.3.63"
serde = {version = "1.0.163", features = ["derive"] }
wasm-bindgen = { version = "0.2.86", features = ["serde-serialize"] }
wasm-bindgen = { version = "=0.2.87", features = ["serde-serialize"] }
wasm-bindgen-futures = "0.4.36"
console_error_panic_hook = "0.1.7"
console_log = { version = "1.0.0", features = ["color"] }
Expand Down
10 changes: 7 additions & 3 deletions crates/bitwarden/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,16 +13,20 @@ edition = "2021"
rust-version = "1.57"

[features]
default = ["secrets"]
default = ["secrets", "use_native_tls"]

secrets = [] # Secrets manager API
internal = [] # Internal testing methods
mobile = ["uniffi", "internal"] # Mobile-specific features

use_native_tls = ["reqwest/native-tls"]
use_native_tls_vendored = ["reqwest/native-tls-vendored"]
use_rustls = ["reqwest/rustls-tls"]

[dependencies]
base64 = ">=0.21.2, <0.22"
lazy_static = ">=1.4.0, <2.0"
reqwest = { version = ">=0.11, <0.12", features = ["json"] }
reqwest = { version = ">=0.11, <0.12", features = ["json"], default-features = false }
serde = { version = ">=1.0, <2.0", features = ["derive"] }
serde_json = ">=1.0.96, <2.0"
serde_qs = ">=0.12.0, <0.13"
Expand Down Expand Up @@ -50,7 +54,7 @@ chrono = { version = ">=0.4.26, <0.5", features = [
"serde",
"std",
], default-features = false }
uniffi = { version = "=0.25.0", optional = true }
uniffi = { version = "=0.25.1", optional = true }

# 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", features = ["js"] }
Expand Down
4 changes: 4 additions & 0 deletions crates/bitwarden/src/client/encryption_settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,10 @@ impl EncryptionSettings {

let private_key = self.private_key.as_ref().ok_or(Error::VaultLocked)?;

// Make sure we only keep the keys given in the arguments and not any of the previous
// ones, which might be from organizations that the user is no longer a part of anymore
self.org_keys.clear();

// Decrypt the org keys with the private key
for (org_id, org_enc_key) in org_enc_keys {
let data = match org_enc_key {
Expand Down
13 changes: 10 additions & 3 deletions crates/bitwarden/src/mobile/client_crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ use crate::Client;
#[cfg(feature = "internal")]
use crate::{
error::Result,
mobile::crypto::{initialize_crypto, InitCryptoRequest},
mobile::crypto::{
initialize_org_crypto, initialize_user_crypto, InitOrgCryptoRequest, InitUserCryptoRequest,
},
};

pub struct ClientCrypto<'a> {
Expand All @@ -11,8 +13,13 @@ pub struct ClientCrypto<'a> {

impl<'a> ClientCrypto<'a> {
#[cfg(feature = "internal")]
pub async fn initialize_crypto(&mut self, req: InitCryptoRequest) -> Result<()> {
initialize_crypto(self.client, req).await
pub async fn initialize_user_crypto(&mut self, req: InitUserCryptoRequest) -> Result<()> {
initialize_user_crypto(self.client, req).await
}

#[cfg(feature = "internal")]
pub async fn initialize_org_crypto(&mut self, req: InitOrgCryptoRequest) -> Result<()> {
initialize_org_crypto(self.client, req).await
}
}

Expand Down
57 changes: 39 additions & 18 deletions crates/bitwarden/src/mobile/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,42 +9,63 @@ use crate::{client::kdf::Kdf, crypto::EncString, error::Result, Client};
#[derive(Serialize, Deserialize, Debug, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[cfg_attr(feature = "mobile", derive(uniffi::Record))]
pub struct InitCryptoRequest {
pub struct InitUserCryptoRequest {
/// The user's KDF parameters, as received from the prelogin request
pub kdf_params: Kdf,
/// The user's email address
pub email: String,
/// The user's master password
pub password: String,
/// The user's encrypted symmetric crypto key
pub user_key: String,
/// The user's encryptred private key
/// The user's encrypted private key
pub private_key: String,
/// The encryption keys for all the organizations the user is a part of
pub organization_keys: HashMap<uuid::Uuid, String>,
/// The initialization method to use
pub method: InitUserCryptoMethod,
}

#[cfg(feature = "internal")]
pub async fn initialize_crypto(client: &mut Client, req: InitCryptoRequest) -> Result<()> {
#[derive(Serialize, Deserialize, Debug, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[cfg_attr(feature = "mobile", derive(uniffi::Enum))]
pub enum InitUserCryptoMethod {
Password {
/// The user's master password
password: String,
/// The user's encrypted symmetric crypto key
user_key: String,
},
}

#[cfg(feature = "internal")]
pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequest) -> Result<()> {
let login_method = crate::client::LoginMethod::User(crate::client::UserLoginMethod::Username {
client_id: "".to_string(),
email: req.email,
kdf: req.kdf_params,
});
client.set_login_method(login_method);

let user_key = req.user_key.parse::<EncString>()?;
let private_key = req.private_key.parse::<EncString>()?;
let private_key: EncString = req.private_key.parse()?;

client.initialize_user_crypto(&req.password, user_key, private_key)?;
match req.method {
InitUserCryptoMethod::Password { password, user_key } => {
let user_key: EncString = user_key.parse()?;
client.initialize_user_crypto(&password, user_key, private_key)?;
}
}

let organization_keys = req
.organization_keys
.into_iter()
.map(|(k, v)| Ok((k, v.parse::<EncString>()?)))
.collect::<Result<Vec<_>>>()?;
Ok(())
}

client.initialize_org_crypto(organization_keys)?;
#[cfg(feature = "internal")]
#[derive(Serialize, Deserialize, Debug, JsonSchema)]
#[serde(rename_all = "camelCase", deny_unknown_fields)]
#[cfg_attr(feature = "mobile", derive(uniffi::Record))]
pub struct InitOrgCryptoRequest {
/// The encryption keys for all the organizations the user is a part of
pub organization_keys: HashMap<uuid::Uuid, EncString>,
}

#[cfg(feature = "internal")]
pub async fn initialize_org_crypto(client: &mut Client, req: InitOrgCryptoRequest) -> Result<()> {
let organization_keys = req.organization_keys.into_iter().collect();
client.initialize_org_crypto(organization_keys)?;
Ok(())
}
Loading

0 comments on commit d8f0b84

Please sign in to comment.