crypto: Add some initial code for megolm session sharing.

master
Damir Jelić 2020-04-08 15:06:57 +02:00
parent 816295cd48
commit f19e251de1
1 changed files with 77 additions and 3 deletions

View File

@ -13,14 +13,14 @@
// limitations under the License. // limitations under the License.
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::convert::{TryFrom, TryInto}; use std::convert::TryInto;
#[cfg(feature = "sqlite-cryptostore")] #[cfg(feature = "sqlite-cryptostore")]
use std::path::Path; use std::path::Path;
use std::result::Result as StdResult; use std::result::Result as StdResult;
use std::sync::Arc; use std::sync::Arc;
use super::error::{OlmError, Result, SignatureError, VerificationResult}; use super::error::{OlmError, Result, SignatureError, VerificationResult};
use super::olm::{Account, InboundGroupSession}; use super::olm::{Account, InboundGroupSession, OutboundGroupSession};
use super::store::memorystore::MemoryStore; use super::store::memorystore::MemoryStore;
#[cfg(feature = "sqlite-cryptostore")] #[cfg(feature = "sqlite-cryptostore")]
use super::store::sqlite::SqliteStore; use super::store::sqlite::SqliteStore;
@ -35,12 +35,13 @@ use serde_json::{json, Value};
use tokio::sync::Mutex; use tokio::sync::Mutex;
use tracing::{debug, error, info, instrument, trace, warn}; use tracing::{debug, error, info, instrument, trace, warn};
use ruma_client_api::r0::client_exchange::DeviceIdOrAllDevices;
use ruma_client_api::r0::keys::{ use ruma_client_api::r0::keys::{
AlgorithmAndDeviceId, DeviceKeys, KeyAlgorithm, OneTimeKey, SignedKey, AlgorithmAndDeviceId, DeviceKeys, KeyAlgorithm, OneTimeKey, SignedKey,
}; };
use ruma_client_api::r0::sync::sync_events::IncomingResponse as SyncResponse; use ruma_client_api::r0::sync::sync_events::IncomingResponse as SyncResponse;
use ruma_events::{ use ruma_events::{
collections::all::RoomEvent, collections::all::{Event, RoomEvent},
room::encrypted::{EncryptedEvent, EncryptedEventContent}, room::encrypted::{EncryptedEvent, EncryptedEventContent},
to_device::{ to_device::{
AnyToDeviceEvent as ToDeviceEvent, ToDeviceEncrypted, ToDeviceForwardedRoomKey, AnyToDeviceEvent as ToDeviceEvent, ToDeviceEncrypted, ToDeviceForwardedRoomKey,
@ -48,6 +49,7 @@ use ruma_events::{
}, },
Algorithm, EventResult, Algorithm, EventResult,
}; };
use ruma_identifiers::RoomId;
use ruma_identifiers::{DeviceId, UserId}; use ruma_identifiers::{DeviceId, UserId};
pub type OneTimeKeys = HashMap<AlgorithmAndDeviceId, OneTimeKey>; pub type OneTimeKeys = HashMap<AlgorithmAndDeviceId, OneTimeKey>;
@ -72,6 +74,8 @@ pub struct OlmMachine {
/// Set of users that we need to query keys for. This is a subset of /// Set of users that we need to query keys for. This is a subset of
/// the tracked users in the CryptoStore. /// the tracked users in the CryptoStore.
users_for_key_query: HashSet<UserId>, users_for_key_query: HashSet<UserId>,
/// The currently active outbound group sessions.
outbound_group_session: HashMap<RoomId, OutboundGroupSession>,
} }
impl OlmMachine { impl OlmMachine {
@ -89,6 +93,7 @@ impl OlmMachine {
uploaded_signed_key_count: None, uploaded_signed_key_count: None,
store: Box::new(MemoryStore::new()), store: Box::new(MemoryStore::new()),
users_for_key_query: HashSet::new(), users_for_key_query: HashSet::new(),
outbound_group_session: HashMap::new(),
}) })
} }
@ -122,6 +127,7 @@ impl OlmMachine {
uploaded_signed_key_count: None, uploaded_signed_key_count: None,
store: Box::new(store), store: Box::new(store),
users_for_key_query: HashSet::new(), users_for_key_query: HashSet::new(),
outbound_group_session: HashMap::new(),
}) })
} }
@ -780,6 +786,74 @@ impl OlmMachine {
} }
} }
async fn create_outbound_group_session(&mut self, room_id: &RoomId) -> Result<()> {
let session = OutboundGroupSession::new(room_id);
let account = self.account.lock().await;
let identity_keys = account.identity_keys();
let sender_key = identity_keys.curve25519();
let signing_key = identity_keys.ed25519();
let inbound_session = InboundGroupSession::new(
sender_key,
signing_key,
&room_id,
&session.session_key().await,
)?;
self.store
.save_inbound_group_session(inbound_session)
.await?;
self.outbound_group_session
.insert(room_id.to_owned(), session);
Ok(())
}
// TODO accept an algorithm here
async fn share_megolm_session<'a, I>(
&mut self,
room_id: &RoomId,
users: I,
) -> Result<HashMap<UserId, HashMap<DeviceIdOrAllDevices, Event>>>
where
I: IntoIterator<Item = &'a UserId>,
{
if !self.outbound_group_session.contains_key(room_id) {
self.create_outbound_group_session(room_id).await?
}
let session = self.outbound_group_session.get(room_id).unwrap();
let key_content = json!({
"algorithm": Algorithm::MegolmV1AesSha2,
"room_id": room_id,
"session_id": session.session_id(),
"session_key": session.session_key().await,
"chain_index": session.message_index().await,
});
for user_id in users {
for device in self.store.get_user_devices(user_id).await?.devices() {
let sender_key = if let Some(k) = device.keys(&KeyAlgorithm::Curve25519) {
k
} else {
warn!(
"The device {} of user {} doesn't have a curve 25519 key",
user_id,
device.device_id()
);
continue;
};
// TODO abor if the device isn't verified
let session = self.store.get_sessions(sender_key);
}
}
todo!()
}
fn add_forwarded_room_key( fn add_forwarded_room_key(
&self, &self,
_sender_key: &str, _sender_key: &str,