crypto: Initial support for device tracking.
parent
5e22eb9faf
commit
56084a7809
|
@ -0,0 +1,71 @@
|
|||
// Copyright 2020 The Matrix.org Foundation C.I.C.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use ruma_client_api::r0::keys::{DeviceKeys, KeyAlgorithm};
|
||||
use ruma_events::Algorithm;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Device {
|
||||
user_id: String,
|
||||
device_id: String,
|
||||
algorithms: Vec<Algorithm>,
|
||||
keys: HashMap<KeyAlgorithm, String>,
|
||||
display_name: Option<String>,
|
||||
deleted: bool,
|
||||
trust_state: TrustState,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum TrustState {
|
||||
Verified,
|
||||
BlackListed,
|
||||
Ignored,
|
||||
Unset,
|
||||
}
|
||||
|
||||
impl Device {
|
||||
pub fn id(&self) -> &str {
|
||||
&self.device_id
|
||||
}
|
||||
|
||||
pub fn user_id(&self) -> &str {
|
||||
&self.user_id
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&DeviceKeys> for Device {
|
||||
fn from(device_keys: &DeviceKeys) -> Self {
|
||||
let mut keys = HashMap::new();
|
||||
|
||||
for (key_id, key) in device_keys.keys.iter() {
|
||||
let key_id = key_id.0;
|
||||
keys.insert(key_id, key.clone());
|
||||
}
|
||||
|
||||
Device {
|
||||
user_id: device_keys.user_id.to_string(),
|
||||
device_id: device_keys.device_id.clone(),
|
||||
algorithms: device_keys.algorithms.clone(),
|
||||
keys,
|
||||
display_name: device_keys
|
||||
.unsigned
|
||||
.as_ref()
|
||||
.map(|d| d.device_display_name.clone()),
|
||||
deleted: false,
|
||||
trust_state: TrustState::Unset,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -25,7 +25,7 @@ use super::olm::{Account, InboundGroupSession, Session};
|
|||
use super::store::memorystore::MemoryStore;
|
||||
#[cfg(feature = "sqlite-cryptostore")]
|
||||
use super::store::sqlite::SqliteStore;
|
||||
use super::CryptoStore;
|
||||
use super::{device::Device, CryptoStore};
|
||||
use crate::api;
|
||||
|
||||
use api::r0::keys;
|
||||
|
@ -188,13 +188,71 @@ impl OlmMachine {
|
|||
///
|
||||
/// * `response` - The keys query response of the request that the client
|
||||
/// performed.
|
||||
// TODO this should return a
|
||||
#[instrument]
|
||||
// TODO this should return a list of changed devices.
|
||||
pub async fn receive_keys_query_response(
|
||||
&mut self,
|
||||
response: &keys::get_keys::Response,
|
||||
) -> Result<()> {
|
||||
for (user_id, device_map) in &response.device_keys {
|
||||
let user_id_string = user_id.to_string();
|
||||
self.users_for_key_query.remove(&user_id_string);
|
||||
|
||||
for (device_id, device_keys) in device_map.iter() {
|
||||
// We don't need our own device in the device store.
|
||||
if user_id == &self.user_id && device_id == &self.device_id {
|
||||
continue;
|
||||
}
|
||||
|
||||
if user_id != &device_keys.user_id || device_id != &device_keys.device_id {
|
||||
warn!(
|
||||
"Mismatch in device keys payload of device {} from user {}",
|
||||
device_keys.device_id, device_keys.user_id
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
let curve_key_id =
|
||||
AlgorithmAndDeviceId(KeyAlgorithm::Curve25519, device_id.to_owned());
|
||||
let ed_key_id = AlgorithmAndDeviceId(KeyAlgorithm::Ed25519, device_id.to_owned());
|
||||
|
||||
let sender_key = if let Some(k) = device_keys.keys.get(&curve_key_id) {
|
||||
k
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
let signing_key = if let Some(k) = device_keys.keys.get(&ed_key_id) {
|
||||
k
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
|
||||
if self
|
||||
.verify_json(user_id, device_id, signing_key, &mut json!(&device_keys))
|
||||
.is_err()
|
||||
{
|
||||
warn!(
|
||||
"Failed to verify the device key signatures for {} {}",
|
||||
user_id, device_id
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
let device = self
|
||||
.store
|
||||
.get_user_device(&user_id_string, device_id)
|
||||
.await
|
||||
.expect("Can't load device");
|
||||
|
||||
if let Some(d) = device {
|
||||
todo!()
|
||||
} else {
|
||||
let device = Device::from(device_keys);
|
||||
info!("Found new device {:?}", device);
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Generate new one-time keys.
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
|
||||
mod error;
|
||||
// TODO remove this.
|
||||
mod device;
|
||||
mod machine;
|
||||
mod memory_stores;
|
||||
#[allow(dead_code)]
|
||||
|
|
|
@ -19,6 +19,7 @@ use async_trait::async_trait;
|
|||
use tokio::sync::Mutex;
|
||||
|
||||
use super::{Account, CryptoStore, CryptoStoreError, InboundGroupSession, Result, Session};
|
||||
use crate::crypto::device::Device;
|
||||
use crate::crypto::memory_stores::{GroupSessionStore, SessionStore};
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -86,4 +87,8 @@ impl CryptoStore for MemoryStore {
|
|||
async fn add_user_for_tracking(&mut self, user: &str) -> Result<bool> {
|
||||
Ok(self.tracked_users.insert(user.to_string()))
|
||||
}
|
||||
|
||||
async fn get_user_device(&self, user_id: &str, device_id: &str) -> Result<Option<Device>> {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ use serde_json::Error as SerdeError;
|
|||
use thiserror::Error;
|
||||
use tokio::sync::Mutex;
|
||||
|
||||
use super::device::Device;
|
||||
use super::olm::{Account, InboundGroupSession, Session};
|
||||
use olm_rs::errors::{OlmAccountError, OlmGroupSessionError, OlmSessionError};
|
||||
use olm_rs::PicklingMode;
|
||||
|
@ -81,4 +82,5 @@ pub trait CryptoStore: Debug + Send + Sync {
|
|||
) -> Result<Option<Arc<Mutex<InboundGroupSession>>>>;
|
||||
fn tracked_users(&self) -> &HashSet<String>;
|
||||
async fn add_user_for_tracking(&mut self, user: &str) -> Result<bool>;
|
||||
async fn get_user_device(&self, user_id: &str, device_id: &str) -> Result<Option<Device>>;
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@ use tokio::sync::Mutex;
|
|||
use zeroize::Zeroizing;
|
||||
|
||||
use super::{Account, CryptoStore, CryptoStoreError, InboundGroupSession, Result, Session};
|
||||
use crate::crypto::device::Device;
|
||||
use crate::crypto::memory_stores::{GroupSessionStore, SessionStore};
|
||||
|
||||
pub struct SqliteStore {
|
||||
|
@ -406,6 +407,10 @@ impl CryptoStore for SqliteStore {
|
|||
}
|
||||
|
||||
async fn add_user_for_tracking(&mut self, user: &str) -> Result<bool> {
|
||||
Ok(self.tracked_users.insert(user.to_string()))
|
||||
}
|
||||
|
||||
async fn get_user_device(&self, user_id: &str, device_id: &str) -> Result<Option<Device>> {
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -242,7 +242,8 @@ impl Room {
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_encryption_event(&mut self, event: &EncryptionEvent) -> bool {
|
||||
fn handle_encryption_event(&mut self, _: &EncryptionEvent) -> bool {
|
||||
// TODO store the encryption settings.
|
||||
self.encrypted = true;
|
||||
true
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue