Skip to content

Commit

Permalink
WIP: back port key_loader_facade changes
Browse files Browse the repository at this point in the history
  • Loading branch information
vaf-hub committed Oct 9, 2024
1 parent 15ad77c commit a1c240c
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 10 deletions.
89 changes: 81 additions & 8 deletions tuta-sdk/rust/sdk/src/key_loader_facade.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
use crate::crypto::key::{AsymmetricKeyPair, GenericAesKey, KeyLoadError};
use crate::crypto::key_encryption::decrypt_key_pair;
use crate::entities::sys::{Group, GroupKey};
use crate::custom_id::CustomId;
use crate::entities::sys::{Group, GroupKey, KeyPair};
use crate::generated_id::GeneratedId;
#[mockall_double::double]
use crate::typed_entity_client::TypedEntityClient;
#[mockall_double::double]
use crate::user_facade::UserFacade;
use crate::util::Versioned;
use crate::ListLoadDirection;
use crate::{IdTuple, ListLoadDirection};
use base64::Engine;
use futures::future::BoxFuture;
use std::cmp::Ordering;
Expand Down Expand Up @@ -209,12 +210,6 @@ impl KeyLoaderFacade {
) -> Result<AsymmetricKeyPair, KeyLoadError> {
let group: Group = self.entity_client.load(key_pair_group_id).await?;
let current_group_key = self.get_current_sym_group_key(&group._id).await?;

// if (requested_version > current_group_key.version) {
// group = (await (await this.cacheManagementFacade()).refreshKeyCache(keyPairGroupId)).group
// currentGroupKey = await this.getCurrentSymGroupKey(keyPairGroupId)
// }

if current_group_key.version == requested_version {
return self.get_and_decrypt_key_pair(&group, &current_group_key.object);
}
Expand All @@ -234,6 +229,84 @@ impl KeyLoaderFacade {
}
}

// async loadKeypair(key_pair_group_id: Id, requestedVersion: number): Promise<AsymmetricKeyPair> {
// let group = await this.entityClient.load(GroupTypeRef, key_pair_group_id)
// let current_group_key = await this.getCurrentSymGroupKey(key_pair_group_id)
//
// if (requestedVersion > current_group_key.version) {
// group = (await (await this.cacheManagementFacade()).refreshKeyCache(key_pair_group_id)).group
// current_group_key = await this.getCurrentSymGroupKey(key_pair_group_id)
// }
// return await this.loadKeyPairImpl(group, requestedVersion, current_group_key)
// }
//
// async loadCurrentKeyPair(groupId: Id): Promise<Versioned<AsymmetricKeyPair>> {
// let group = await this.entityClient.load(GroupTypeRef, groupId)
//
// let current_group_key = await this.getCurrentSymGroupKey(groupId)
// if (Number(group.groupKeyVersion) !== current_group_key.version) {
// // There is a race condition after rotating the group key were the group entity in the cache is not in sync with current key version in the key cache.
// // group.groupKeyVersion might be newer than current_group_key.version.
// // We reload group and user and refresh entity and key cache to synchronize both caches.
// group = (await (await this.cacheManagementFacade()).refreshKeyCache(groupId)).group
// current_group_key = await this.getCurrentSymGroupKey(groupId)
// if (Number(group.groupKeyVersion) !== current_group_key.version) {
// // we still do not have the proper state to get the current key pair
// throw new Error(`inconsistent key version state in cache and key cache for group ${groupId}`)
// }
// }
// return { object: this.validateAndDecryptKeyPair(group.currentKeys, groupId, current_group_key.object), version: Number(group.groupKeyVersion) }
// }

async fn load_key_pair_impl(
&self,
group: Group,
requested_version: i64,
current_group_key: VersionedAesKey,
) -> Result<AsymmetricKeyPair, KeyLoadError> {
let key_pair_group_id = group._id;
let key_pair: Option<KeyPair>;
let sym_group_key: GenericAesKey;
if requested_version > current_group_key.version {
return Err(KeyLoadError{reason: format!("Not possible to get newer key version than is cached for group {key_pair_group_id}")});
} else if requested_version == current_group_key.version {
sym_group_key = current_group_key.object;
if group.groupKeyVersion == current_group_key.version {
key_pair = group.currentKeys
} else {
let former_keys_list = group.formerGroupKeys.unwrap().list;
// we load by the version and thus can be sure that we are able to decrypt this key
let former_group_key: GroupKey = self
.entity_client
.load(IdTuple::new(
former_keys_list,
CustomId::from_custom_string(&current_group_key.version.to_string()),
))
.await?;
key_pair = former_group_key.keyPair
}
// }else {
// // load a former key pair: groupKeyVersion < groupKey.version
// let { symmetricGroupKey, groupKeyInstance } = self.find_former_group_key(group, current_group_key, requestedVersion).await?
// key_pair = groupKeyInstance.keyPair
// sym_group_key = symmetricGroupKey
}
Ok(self.validate_and_decrypt_key_pair(key_pair, key_pair_group_id, sym_group_key)?)
}

fn validate_and_decrypt_key_pair(
key_pair: Option<KeyPair>,
group_id: &GeneratedId,
group_key: GenericAesKey,
) -> Result<AsymmetricKeyPair, KeyLoadError> {
match key_pair {
None => Err(KeyLoadError {
reason: format!("no key pair on group {group_id}"),
}),
Some(kp) => Ok(decrypt_key_pair(&group_key, &kp)?),
}
}

fn get_and_decrypt_key_pair(
&self,
group: &Group,
Expand Down
12 changes: 10 additions & 2 deletions tuta-sdk/rust/sdk/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use crate::crypto::crypto_facade::CryptoFacade;
use crate::crypto::randomizer_facade::RandomizerFacade;
#[mockall_double::double]
use crate::crypto_entity_client::CryptoEntityClient;
use crate::custom_id::CustomId;
use crate::element_value::ElementValue;
use crate::entities::entity_facade::EntityFacade;
use crate::entities::tutanota::Mail;
Expand Down Expand Up @@ -224,16 +225,23 @@ pub enum ListLoadDirection {
DESC,
}

#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
#[repr(transparent)]
pub enum ElementId {
Generated(GeneratedId),
Custom(CustomId),
}

/// A set of keys used to identify an element within a List Element Type
#[derive(uniffi::Record, Debug, PartialEq, Clone, Serialize, Deserialize)]
pub struct IdTuple {
pub list_id: GeneratedId,
pub element_id: GeneratedId,
pub element_id: ElementId,
}

impl IdTuple {
#[must_use]
pub fn new(list_id: GeneratedId, element_id: GeneratedId) -> Self {
pub fn new(list_id: GeneratedId, element_id: ElementId) -> Self {
Self {
list_id,
element_id,
Expand Down

0 comments on commit a1c240c

Please sign in to comment.