Skip to content

Commit

Permalink
[PM-6261] Add Uniffi bindings for TDE (#608)
Browse files Browse the repository at this point in the history
Add Uniffi bindings for the TDE functionality.
  • Loading branch information
Hinton authored Feb 13, 2024
1 parent 42ca1b0 commit d722e17
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 29 deletions.
39 changes: 29 additions & 10 deletions crates/bitwarden-crypto/src/keys/device_key.rs
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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]
Expand Down Expand Up @@ -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,
Expand All @@ -59,14 +63,27 @@ impl DeviceKey {
&self,
protected_device_private_key: EncString,
protected_user_key: AsymmetricEncString,
) -> Result<UserKey> {
) -> Result<SymmetricCryptoKey> {
let device_private_key: Vec<u8> = 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<u8> = 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<Self, Self::Err> {
let key = s.parse::<SymmetricCryptoKey>()?;
Ok(DeviceKey(key))
}
}

Expand All @@ -83,14 +100,16 @@ mod tests {

let decrypted = result
.device_key
.parse::<DeviceKey>()
.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]
Expand Down Expand Up @@ -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);
}
}
18 changes: 16 additions & 2 deletions crates/bitwarden-crypto/src/uniffi_support.rs
Original file line number Diff line number Diff line change
@@ -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);

Expand Down Expand Up @@ -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> {
Self::from_str(&val).map_err(|e| e.into())
}

fn from_custom(obj: Self) -> Self::Builtin {
obj.to_string()
}
}
7 changes: 6 additions & 1 deletion crates/bitwarden-uniffi/src/auth/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -128,4 +128,9 @@ impl ClientAuth {
.auth()
.approve_auth_request(public_key)?)
}

/// Trust the current device
pub async fn t(&self) -> Result<TrustDeviceResponse> {
Ok(self.0 .0.write().await.auth().trust_device()?)
}
}
2 changes: 1 addition & 1 deletion crates/bitwarden/src/auth/client_auth.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ impl<'a> ClientAuth<'a> {
approve_auth_request(self.client, public_key)
}

pub async fn trust_device(&self) -> Result<TrustDeviceResponse> {
pub fn trust_device(&self) -> Result<TrustDeviceResponse> {
trust_device(self.client)
}
}
Expand Down
21 changes: 21 additions & 0 deletions crates/bitwarden/src/mobile/crypto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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")]
Expand All @@ -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 {
Expand Down Expand Up @@ -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::<DeviceKey>()?;
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(())
Expand Down
21 changes: 6 additions & 15 deletions crates/bitwarden/src/uniffi_support.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{num::NonZeroU32, str::FromStr};
use std::num::NonZeroU32;

use bitwarden_crypto::{AsymmetricEncString, EncString};
use uuid::Uuid;
Expand All @@ -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> {
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<chrono::Utc>;
uniffi::custom_type!(DateTime, std::time::SystemTime);
Expand Down

0 comments on commit d722e17

Please sign in to comment.