diff --git a/crates/bitwarden-uniffi/src/auth/mod.rs b/crates/bitwarden-uniffi/src/auth/mod.rs index 2a451ffdfc..62b7090457 100644 --- a/crates/bitwarden-uniffi/src/auth/mod.rs +++ b/crates/bitwarden-uniffi/src/auth/mod.rs @@ -2,6 +2,7 @@ use std::sync::Arc; use bitwarden::auth::{ password::MasterPasswordPolicyOptions, AuthRequestResponse, RegisterKeyResponse, + RegisterTdeKeyResponse, }; use bitwarden_crypto::{AsymmetricEncString, HashPurpose, Kdf, TrustDeviceResponse}; @@ -78,6 +79,21 @@ impl ClientAuth { .make_register_keys(email, password, kdf)?) } + /// Generate keys needed for TDE process + pub async fn make_register_tde_keys( + &self, + org_public_key: String, + remember_device: bool, + ) -> Result { + Ok(self + .0 + .0 + .write() + .await + .auth() + .make_register_tde_keys(org_public_key, remember_device)?) + } + /// Validate the user password /// /// To retrieve the user's password hash, use [`ClientAuth::hash_password`] with diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index 5f20021337..5029d389b7 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -20,6 +20,7 @@ use crate::{ MasterPasswordPolicyOptions, }, register::{make_register_keys, register}, + tde::{make_register_tde_keys, RegisterTdeKeyResponse}, AuthRequestResponse, RegisterKeyResponse, RegisterRequest, }, client::Kdf, @@ -73,6 +74,14 @@ impl<'a> ClientAuth<'a> { make_register_keys(email, password, kdf) } + pub fn make_register_tde_keys( + &mut self, + org_public_key: String, + remember_device: bool, + ) -> Result { + make_register_tde_keys(self.client, org_public_key, remember_device) + } + pub async fn register(&mut self, input: &RegisterRequest) -> Result<()> { register(self.client, input).await } diff --git a/crates/bitwarden/src/auth/mod.rs b/crates/bitwarden/src/auth/mod.rs index 7918694e23..c01754d0af 100644 --- a/crates/bitwarden/src/auth/mod.rs +++ b/crates/bitwarden/src/auth/mod.rs @@ -20,6 +20,10 @@ mod auth_request; pub use auth_request::AuthRequestResponse; #[cfg(feature = "mobile")] pub(crate) use auth_request::{auth_request_decrypt_master_key, auth_request_decrypt_user_key}; +#[cfg(feature = "mobile")] +mod tde; +#[cfg(feature = "mobile")] +pub use tde::RegisterTdeKeyResponse; #[cfg(feature = "internal")] use crate::{client::Kdf, error::Result}; diff --git a/crates/bitwarden/src/auth/tde.rs b/crates/bitwarden/src/auth/tde.rs new file mode 100644 index 0000000000..919ec25e1f --- /dev/null +++ b/crates/bitwarden/src/auth/tde.rs @@ -0,0 +1,52 @@ +use base64::{engine::general_purpose::STANDARD, Engine}; +use bitwarden_crypto::{ + AsymmetricEncString, AsymmetricPublicCryptoKey, DeviceKey, EncString, SymmetricCryptoKey, + TrustDeviceResponse, UserKey, +}; + +use crate::{error::Result, Client}; + +pub(super) fn make_register_tde_keys( + client: &mut Client, + org_public_key: String, + remember_device: bool, +) -> Result { + let public_key = AsymmetricPublicCryptoKey::from_der(&STANDARD.decode(org_public_key)?)?; + + let mut rng = rand::thread_rng(); + + // Generate a new user key and key pair, and encrypt the user key with the org public key for + // admin password reset + let user_key = UserKey::new(SymmetricCryptoKey::generate(&mut rng)); + let key_pair = user_key.make_key_pair()?; + + let admin_reset = + AsymmetricEncString::encrypt_rsa2048_oaep_sha1(&user_key.0.to_vec(), &public_key)?; + + let device_key = if remember_device { + Some(DeviceKey::trust_device(&user_key.0)?) + } else { + None + }; + + // Initialize the crypto with the generated user key, this way it doesn't need to leave the + // client + client.initialize_user_crypto_decrypted_key(user_key.0, key_pair.private.clone())?; + + Ok(RegisterTdeKeyResponse { + private_key: key_pair.private, + public_key: key_pair.public, + + admin_reset, + device_key, + }) +} + +#[cfg_attr(feature = "mobile", derive(uniffi::Record))] +pub struct RegisterTdeKeyResponse { + pub private_key: EncString, + pub public_key: String, + + pub admin_reset: AsymmetricEncString, + pub device_key: Option, +}