Skip to content
Open
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 .github/CODEOWNERS
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ crates/bitwarden-crypto/** @bitwarden/team-key-management-dev
crates/bitwarden-exporters/** @bitwarden/team-tools-dev @bitwarden/team-platform-dev
crates/bitwarden-generators/** @bitwarden/team-tools-dev @bitwarden/team-platform-dev
crates/bitwarden-organization-crypto/** @bitwarden/team-key-management-dev
crates/bitwarden-organization-invite-link/** @bitwarden/team-admin-console-dev
crates/bitwarden-organizations/** @bitwarden/team-admin-console-dev
crates/bitwarden-policies/** @bitwarden/team-admin-console-dev
crates/bitwarden-send/** @bitwarden/team-tools-dev @bitwarden/team-platform-dev
Expand Down
16 changes: 16 additions & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ bitwarden-ipc = { path = "crates/bitwarden-ipc", version = "=3.0.0" }
bitwarden-logging = { path = "crates/bitwarden-logging", version = "=3.0.0" }
bitwarden-logging-macro = { path = "crates/bitwarden-logging-macro", version = "=3.0.0" }
bitwarden-organization-crypto = { path = "crates/bitwarden-organization-crypto", version = "=3.0.0" }
bitwarden-organization-invite-link = { path = "crates/bitwarden-organization-invite-link", version = "=3.0.0" }
bitwarden-organizations = { path = "crates/bitwarden-organizations", version = "=3.0.0" }
bitwarden-pm = { path = "crates/bitwarden-pm", version = "=3.0.0" }
bitwarden-policies = { path = "crates/bitwarden-policies", version = "=3.0.0" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ fn main() {
let key: &InviteKeyData = bundle.dangerous_get_raw_invite_key();

// 3. The second part is `InviteKeyEnvelope`. This is the invite
// key sealed (a.k.a. sealed) by the org key. `InviteKeyEnvelope`
// automatically serializes to `base64` when using serde,
// key sealed by the org key. `InviteKeyEnvelope` serializes to the
// Bitwarden EncString text format (`"2.iv|data|mac"`) when using serde,
// `String::from(&inviteKeyEnvelope)`, or wasm abi serialization.
let organization_wrapped_invitation_key: &InviteKeyEnvelope =
bundle.get_sealed_invite_key_envelope();
Expand Down
42 changes: 28 additions & 14 deletions crates/bitwarden-organization-crypto/src/invite_key_bundle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::str::FromStr;
use bitwarden_crypto::{
BitwardenLegacyKeyBytes, EncString, KeySlotIds, KeyStoreContext, SymmetricCryptoKey,
};
use bitwarden_encoding::{B64, B64Url, FromStrVisitor};
use bitwarden_encoding::{B64Url, FromStrVisitor};
use serde::{Deserialize, Serialize};
use subtle::{Choice, ConstantTimeEq};
use thiserror::Error;
Expand All @@ -25,6 +25,12 @@ pub enum InviteKeyBundleError {
MissingKeyId(String),
}

#[cfg(feature = "wasm")]
#[wasm_bindgen::prelude::wasm_bindgen(typescript_custom_section)]
const TS_INVITE_KEY_DATA: &'static str = r#"
export type InviteKeyData = Tagged<string, "InviteKeyData">;
"#;
Comment thread
BTreston marked this conversation as resolved.

/// Struct for holding the Invite Key's raw byte data. Supports WASM bindings,
/// automatically using base64Url encoding for both `wasm-bindgen` and `tsify`.
///
Expand Down Expand Up @@ -91,31 +97,32 @@ impl Serialize for InviteKeyData {
}
}

#[cfg(feature = "wasm")]
#[wasm_bindgen::prelude::wasm_bindgen(typescript_custom_section)]
const TS_INVITE_KEY_ENVELOPE: &'static str = r#"
export type InviteKeyEnvelope = Tagged<string, "InviteKeyEnvelope">;
"#;

/// Struct for holding the wrapped invite key data. Currently supports encstring
/// but the inner type must remain private as it may be extended in the future.
#[derive(Clone)]
pub struct InviteKeyEnvelope(EncString);

/// Serializes to the Bitwarden EncString text format, which is the
/// format expected by the server's `EncryptedInviteKey` field validator.
impl From<&InviteKeyEnvelope> for String {
fn from(key_data: &InviteKeyEnvelope) -> Self {
B64::from(
key_data
.0
.to_buffer()
.expect("`to_buffer` never fails for `EncString`"),
)
.to_string()
key_data.0.to_string()
Comment thread
BTreston marked this conversation as resolved.
}
}

impl FromStr for InviteKeyEnvelope {
type Err = InviteKeyBundleError;

fn from_str(s: &str) -> Result<Self, Self::Err> {
let data = B64::try_from(s).map_err(|_| InviteKeyBundleError::DecodingFailed)?;
Ok(InviteKeyEnvelope(
EncString::from_buffer(data.as_bytes())
.map_err(|_| InviteKeyBundleError::DecodingFailed)?,
))
s.parse::<EncString>()
.map(InviteKeyEnvelope)
.map_err(|_| InviteKeyBundleError::DecodingFailed)
}
}

Expand Down Expand Up @@ -274,7 +281,14 @@ mod tests {
.unwrap_symmetric_key(TestSymmKey::Organization, &key.sealed_key_envelope.0)
.unwrap();

ctx.assert_symmetric_keys_equal(raw_key_id, unsealed_key);
#[allow(deprecated)]
let raw_key = ctx.dangerous_get_symmetric_key(raw_key_id).unwrap().clone();
#[allow(deprecated)]
let unsealed = ctx
.dangerous_get_symmetric_key(unsealed_key)
.unwrap()
.clone();
assert_eq!(raw_key, unsealed);
}

#[test]
Expand Down
19 changes: 5 additions & 14 deletions crates/bitwarden-organization-crypto/src/wasm.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,16 @@
//! The wasm module holds serialization/encoding needed wasm bindings for
//! any types related to InviteKeyEnvelope. This means base64url for the
//! InviteKeyData type, and base64 for the InviteKey type. In order to minimize
//! complexity, the actual B64/B64Url encoding/decoding are limited to the
//! `From<String>` and `FromStr` implementations. All other serialization
//! goes through String to simplify maintenance.
//! InviteKeyData type, and Bitwarden EncString text format (`"2.iv|data|mac"`)
//! for the InviteKeyEnvelope type. In order to minimize complexity, the actual
//! encoding/decoding is limited to the `From<String>` and `FromStr`
//! implementations. All other serialization goes through String to simplify
//! maintenance.
use std::str::FromStr;

use wasm_bindgen::convert::{FromWasmAbi, IntoWasmAbi, OptionFromWasmAbi};

use crate::{InviteKeyBundleError, InviteKeyData, InviteKeyEnvelope};

#[wasm_bindgen::prelude::wasm_bindgen(typescript_custom_section)]
const TS_CUSTOM_TYPES: &'static str = r#"
export type InviteKeyData = Tagged<string, "InviteKeyData">;
"#;

impl wasm_bindgen::describe::WasmDescribe for InviteKeyData {
fn describe() {
<String as wasm_bindgen::describe::WasmDescribe>::describe();
Expand Down Expand Up @@ -56,11 +52,6 @@ impl TryFrom<wasm_bindgen::JsValue> for InviteKeyData {
}
}

#[wasm_bindgen::prelude::wasm_bindgen(typescript_custom_section)]
const TS_CUSTOM_TYPES: &'static str = r#"
export type InviteKeyEnvelope = Tagged<string, "InviteKeyEnvelope">;
"#;

impl wasm_bindgen::describe::WasmDescribe for InviteKeyEnvelope {
fn describe() {
<String as wasm_bindgen::describe::WasmDescribe>::describe();
Expand Down
39 changes: 39 additions & 0 deletions crates/bitwarden-organization-invite-link/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
[package]
name = "bitwarden-organization-invite-link"
description = """
Internal crate for the bitwarden crate. Do not use.
"""

version.workspace = true
authors.workspace = true
edition.workspace = true
rust-version.workspace = true
readme.workspace = true
homepage.workspace = true
repository.workspace = true
license-file.workspace = true
keywords.workspace = true

[features]
default = []
wasm = [
"bitwarden-core/wasm",
"bitwarden-crypto/wasm",
"bitwarden-error/wasm",
"bitwarden-organization-crypto/wasm",
"dep:tsify",
"dep:wasm-bindgen",
]

[dependencies]
bitwarden-core = { workspace = true }
bitwarden-crypto = { workspace = true }
bitwarden-error = { workspace = true }
bitwarden-organization-crypto = { workspace = true }
serde = { workspace = true }
thiserror = { workspace = true }
tsify = { workspace = true, optional = true }
wasm-bindgen = { workspace = true, optional = true }

[lints]
workspace = true
4 changes: 4 additions & 0 deletions crates/bitwarden-organization-invite-link/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# bitwarden-organization-invite-link

Contains the cryptographic operations for the Bitwarden admin console, including organization invite
key bundle generation.
Loading
Loading