diff --git a/crates/bitwarden-crypto/src/keys/device_key.rs b/crates/bitwarden-crypto/src/keys/device_key.rs index 37bcd58f9..876ae7b75 100644 --- a/crates/bitwarden-crypto/src/keys/device_key.rs +++ b/crates/bitwarden-crypto/src/keys/device_key.rs @@ -1,6 +1,8 @@ +use std::str::FromStr; + use crate::{ - error::Result, AsymmetricCryptoKey, AsymmetricEncString, EncString, KeyDecryptable, - KeyEncryptable, SymmetricCryptoKey, UserKey, + error::Result, AsymmetricCryptoKey, AsymmetricEncString, CryptoError, EncString, + KeyDecryptable, KeyEncryptable, SymmetricCryptoKey, }; /// Device Key @@ -11,8 +13,10 @@ use crate::{ pub struct DeviceKey(SymmetricCryptoKey); #[derive(Debug)] +#[cfg_attr(feature = "mobile", derive(uniffi::Record))] pub struct TrustDeviceResponse { - pub device_key: DeviceKey, + /// Base64 encoded device key + pub device_key: String, /// UserKey encrypted with DevicePublicKey pub protected_user_key: AsymmetricEncString, /// DevicePrivateKey encrypted with [DeviceKey] @@ -47,7 +51,7 @@ impl DeviceKey { .encrypt_with_key(&device_key.0)?; Ok(TrustDeviceResponse { - device_key, + device_key: device_key.to_base64(), protected_user_key, protected_device_private_key, protected_device_public_key, @@ -59,14 +63,27 @@ impl DeviceKey { &self, protected_device_private_key: EncString, protected_user_key: AsymmetricEncString, - ) -> Result { + ) -> Result { let device_private_key: Vec = protected_device_private_key.decrypt_with_key(&self.0)?; let device_private_key = AsymmetricCryptoKey::from_der(device_private_key.as_slice())?; let mut dec: Vec = protected_user_key.decrypt_with_key(&device_private_key)?; let user_key: SymmetricCryptoKey = dec.as_mut_slice().try_into()?; - Ok(UserKey(user_key)) + Ok(user_key) + } + + fn to_base64(&self) -> String { + self.0.to_base64() + } +} + +impl FromStr for DeviceKey { + type Err = CryptoError; + + fn from_str(s: &str) -> Result { + let key = s.parse::()?; + Ok(DeviceKey(key)) } } @@ -83,14 +100,16 @@ mod tests { let decrypted = result .device_key + .parse::() + .unwrap() .decrypt_user_key( result.protected_device_private_key, result.protected_user_key, ) .unwrap(); - assert_eq!(key.key, decrypted.0.key); - assert_eq!(key.mac_key, decrypted.0.mac_key); + assert_eq!(key.key, decrypted.key); + assert_eq!(key.mac_key, decrypted.mac_key); } #[test] @@ -120,7 +139,7 @@ mod tests { .decrypt_user_key(protected_device_private_key, protected_user_key) .unwrap(); - assert_eq!(decrypted.0.key, user_key.key); - assert_eq!(decrypted.0.mac_key, user_key.mac_key); + assert_eq!(decrypted.key, user_key.key); + assert_eq!(decrypted.mac_key, user_key.mac_key); } } diff --git a/crates/bitwarden-crypto/src/uniffi_support.rs b/crates/bitwarden-crypto/src/uniffi_support.rs index 0ff0194f9..7f1249da0 100644 --- a/crates/bitwarden-crypto/src/uniffi_support.rs +++ b/crates/bitwarden-crypto/src/uniffi_support.rs @@ -1,6 +1,6 @@ -use std::num::NonZeroU32; +use std::{num::NonZeroU32, str::FromStr}; -use crate::{CryptoError, EncString, UniffiCustomTypeConverter}; +use crate::{AsymmetricEncString, CryptoError, EncString, UniffiCustomTypeConverter}; uniffi::custom_type!(NonZeroU32, u32); @@ -29,3 +29,17 @@ impl UniffiCustomTypeConverter for EncString { obj.to_string() } } + +uniffi::custom_type!(AsymmetricEncString, String); + +impl UniffiCustomTypeConverter for AsymmetricEncString { + type Builtin = String; + + fn into_custom(val: Self::Builtin) -> uniffi::Result { + Self::from_str(&val).map_err(|e| e.into()) + } + + fn from_custom(obj: Self) -> Self::Builtin { + obj.to_string() + } +} diff --git a/crates/bitwarden-uniffi/src/auth/mod.rs b/crates/bitwarden-uniffi/src/auth/mod.rs index 75e0c5656..34d0de93f 100644 --- a/crates/bitwarden-uniffi/src/auth/mod.rs +++ b/crates/bitwarden-uniffi/src/auth/mod.rs @@ -3,7 +3,7 @@ use std::sync::Arc; use bitwarden::auth::{ password::MasterPasswordPolicyOptions, AuthRequestResponse, RegisterKeyResponse, }; -use bitwarden_crypto::{AsymmetricEncString, HashPurpose, Kdf}; +use bitwarden_crypto::{AsymmetricEncString, HashPurpose, Kdf, TrustDeviceResponse}; use crate::{error::Result, Client}; @@ -128,4 +128,9 @@ impl ClientAuth { .auth() .approve_auth_request(public_key)?) } + + /// Trust the current device + pub async fn t(&self) -> Result { + Ok(self.0 .0.write().await.auth().trust_device()?) + } } diff --git a/crates/bitwarden/src/auth/client_auth.rs b/crates/bitwarden/src/auth/client_auth.rs index f08daf0b7..5f2002133 100644 --- a/crates/bitwarden/src/auth/client_auth.rs +++ b/crates/bitwarden/src/auth/client_auth.rs @@ -122,7 +122,7 @@ impl<'a> ClientAuth<'a> { approve_auth_request(self.client, public_key) } - pub async fn trust_device(&self) -> Result { + pub fn trust_device(&self) -> Result { trust_device(self.client) } } diff --git a/crates/bitwarden/src/mobile/crypto.rs b/crates/bitwarden/src/mobile/crypto.rs index 37bb3b905..a48b29b15 100644 --- a/crates/bitwarden/src/mobile/crypto.rs +++ b/crates/bitwarden/src/mobile/crypto.rs @@ -57,6 +57,14 @@ pub enum InitUserCryptoMethod { method: AuthRequestMethod, }, + DeviceKey { + /// The device's DeviceKey + device_key: String, + /// The Device Private Key + protected_device_private_key: EncString, + /// The user's symmetric crypto key, encrypted with the Device Key. + device_protected_user_key: AsymmetricEncString, + }, } #[cfg(feature = "internal")] @@ -78,6 +86,8 @@ pub enum AuthRequestMethod { #[cfg(feature = "internal")] pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequest) -> Result<()> { + use bitwarden_crypto::DeviceKey; + use crate::auth::{auth_request_decrypt_master_key, auth_request_decrypt_user_key}; let login_method = crate::client::LoginMethod::User(crate::client::UserLoginMethod::Username { @@ -123,6 +133,17 @@ pub async fn initialize_user_crypto(client: &mut Client, req: InitUserCryptoRequ }; client.initialize_user_crypto_decrypted_key(user_key, private_key)?; } + InitUserCryptoMethod::DeviceKey { + device_key, + protected_device_private_key, + device_protected_user_key, + } => { + let device_key = device_key.parse::()?; + let user_key = device_key + .decrypt_user_key(protected_device_private_key, device_protected_user_key)?; + + client.initialize_user_crypto_decrypted_key(user_key, private_key)?; + } } Ok(()) diff --git a/crates/bitwarden/src/uniffi_support.rs b/crates/bitwarden/src/uniffi_support.rs index 7da53c8b5..b23a9cbef 100644 --- a/crates/bitwarden/src/uniffi_support.rs +++ b/crates/bitwarden/src/uniffi_support.rs @@ -1,4 +1,4 @@ -use std::{num::NonZeroU32, str::FromStr}; +use std::num::NonZeroU32; use bitwarden_crypto::{AsymmetricEncString, EncString}; use uuid::Uuid; @@ -7,20 +7,11 @@ use crate::UniffiCustomTypeConverter; uniffi::ffi_converter_forward!(NonZeroU32, bitwarden_crypto::UniFfiTag, crate::UniFfiTag); uniffi::ffi_converter_forward!(EncString, bitwarden_crypto::UniFfiTag, crate::UniFfiTag); - -uniffi::custom_type!(AsymmetricEncString, String); - -impl UniffiCustomTypeConverter for AsymmetricEncString { - type Builtin = String; - - fn into_custom(val: Self::Builtin) -> uniffi::Result { - Self::from_str(&val).map_err(|e| e.into()) - } - - fn from_custom(obj: Self) -> Self::Builtin { - obj.to_string() - } -} +uniffi::ffi_converter_forward!( + AsymmetricEncString, + bitwarden_crypto::UniFfiTag, + crate::UniFfiTag +); type DateTime = chrono::DateTime; uniffi::custom_type!(DateTime, std::time::SystemTime);