crypto: Prepare the sas structs to handle in-room verifications.

master
Damir Jelić 2020-12-10 14:53:43 +01:00
parent b9ddbb11af
commit 1bb5b42b1d
6 changed files with 80 additions and 38 deletions

View File

@ -1825,7 +1825,7 @@ pub(crate) mod test {
let mut event = request_to_event(alice.user_id(), &request); let mut event = request_to_event(alice.user_id(), &request);
bob.handle_verification_event(&mut event).await; bob.handle_verification_event(&mut event).await;
let bob_sas = bob.get_verification(alice_sas.flow_id()).unwrap(); let bob_sas = bob.get_verification(alice_sas.flow_id().as_str()).unwrap();
assert!(alice_sas.emoji().is_none()); assert!(alice_sas.emoji().is_none());
assert!(bob_sas.emoji().is_none()); assert!(bob_sas.emoji().is_none());

View File

@ -88,7 +88,7 @@ impl VerificationMachine {
); );
self.verifications self.verifications
.insert(sas.flow_id().to_owned(), sas.clone()); .insert(sas.flow_id().to_string(), sas.clone());
Ok((sas, request)) Ok((sas, request))
} }
@ -367,7 +367,7 @@ mod test {
async fn full_flow() { async fn full_flow() {
let (alice_machine, bob) = setup_verification_machine().await; let (alice_machine, bob) = setup_verification_machine().await;
let alice = alice_machine.get_sas(bob.flow_id()).unwrap(); let alice = alice_machine.get_sas(bob.flow_id().as_str()).unwrap();
let mut event = alice let mut event = alice
.accept() .accept()
@ -428,7 +428,7 @@ mod test {
#[tokio::test] #[tokio::test]
async fn timing_out() { async fn timing_out() {
let (alice_machine, bob) = setup_verification_machine().await; let (alice_machine, bob) = setup_verification_machine().await;
let alice = alice_machine.get_sas(bob.flow_id()).unwrap(); let alice = alice_machine.get_sas(bob.flow_id().as_str()).unwrap();
assert!(!alice.timed_out()); assert!(!alice.timed_out());
assert!(alice_machine.outgoing_to_device_messages.is_empty()); assert!(alice_machine.outgoing_to_device_messages.is_empty());

View File

@ -38,6 +38,8 @@ use crate::{
ReadOnlyAccount, ToDeviceRequest, ReadOnlyAccount, ToDeviceRequest,
}; };
use super::sas_state::FlowId;
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct SasIds { pub struct SasIds {
pub account: ReadOnlyAccount, pub account: ReadOnlyAccount,
@ -298,12 +300,12 @@ fn extra_mac_info_send(ids: &SasIds, flow_id: &str) -> String {
/// # Panics /// # Panics
/// ///
/// This will panic if the public key of the other side wasn't set. /// This will panic if the public key of the other side wasn't set.
pub fn get_mac_content(sas: &OlmSas, ids: &SasIds, flow_id: &str) -> MacToDeviceEventContent { pub fn get_mac_content(sas: &OlmSas, ids: &SasIds, flow_id: &FlowId) -> MacToDeviceEventContent {
let mut mac: BTreeMap<String, String> = BTreeMap::new(); let mut mac: BTreeMap<String, String> = BTreeMap::new();
let key_id = DeviceKeyId::from_parts(DeviceKeyAlgorithm::Ed25519, ids.account.device_id()); let key_id = DeviceKeyId::from_parts(DeviceKeyAlgorithm::Ed25519, ids.account.device_id());
let key = ids.account.identity_keys().ed25519(); let key = ids.account.identity_keys().ed25519();
let info = extra_mac_info_send(ids, flow_id); let info = extra_mac_info_send(ids, flow_id.as_str());
mac.insert( mac.insert(
key_id.to_string(), key_id.to_string(),
@ -319,10 +321,13 @@ pub fn get_mac_content(sas: &OlmSas, ids: &SasIds, flow_id: &str) -> MacToDevice
.calculate_mac(&keys.join(","), &format!("{}KEY_IDS", &info)) .calculate_mac(&keys.join(","), &format!("{}KEY_IDS", &info))
.expect("Can't calculate SAS MAC"); .expect("Can't calculate SAS MAC");
MacToDeviceEventContent { match flow_id {
transaction_id: flow_id.to_owned(), FlowId::ToDevice(s) => MacToDeviceEventContent {
keys, transaction_id: s.to_string(),
mac, keys,
mac,
},
_ => todo!(),
} }
} }

View File

@ -31,7 +31,8 @@ use crate::{
}; };
use super::sas_state::{ use super::sas_state::{
Accepted, Canceled, Confirmed, Created, Done, KeyReceived, MacReceived, SasState, Started, Accepted, Canceled, Confirmed, Created, Done, FlowId, KeyReceived, MacReceived, SasState,
Started,
}; };
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -220,7 +221,7 @@ impl InnerSas {
} }
} }
pub fn verification_flow_id(&self) -> Arc<str> { pub fn verification_flow_id(&self) -> Arc<FlowId> {
match self { match self {
InnerSas::Created(s) => s.verification_flow_id.clone(), InnerSas::Created(s) => s.verification_flow_id.clone(),
InnerSas::Started(s) => s.verification_flow_id.clone(), InnerSas::Started(s) => s.verification_flow_id.clone(),

View File

@ -31,7 +31,7 @@ use matrix_sdk_common::{
}, },
AnyToDeviceEvent, AnyToDeviceEventContent, ToDeviceEvent, AnyToDeviceEvent, AnyToDeviceEventContent, ToDeviceEvent,
}, },
identifiers::{DeviceId, UserId}, identifiers::{DeviceId, EventId, RoomId, UserId},
}; };
use crate::{ use crate::{
@ -44,6 +44,7 @@ use crate::{
pub use helpers::content_to_request; pub use helpers::content_to_request;
use inner_sas::InnerSas; use inner_sas::InnerSas;
pub use sas_state::FlowId;
#[derive(Debug)] #[derive(Debug)]
/// A result of a verification flow. /// A result of a verification flow.
@ -65,7 +66,7 @@ pub struct Sas {
private_identity: PrivateCrossSigningIdentity, private_identity: PrivateCrossSigningIdentity,
other_device: ReadOnlyDevice, other_device: ReadOnlyDevice,
other_identity: Option<UserIdentities>, other_identity: Option<UserIdentities>,
flow_id: Arc<str>, flow_id: Arc<FlowId>,
} }
impl Sas { impl Sas {
@ -95,7 +96,7 @@ impl Sas {
} }
/// Get the unique ID that identifies this SAS verification flow. /// Get the unique ID that identifies this SAS verification flow.
pub fn flow_id(&self) -> &str { pub fn flow_id(&self) -> &FlowId {
&self.flow_id &self.flow_id
} }

View File

@ -36,7 +36,7 @@ use matrix_sdk_common::{
}, },
AnyToDeviceEventContent, ToDeviceEvent, AnyToDeviceEventContent, ToDeviceEvent,
}, },
identifiers::{DeviceId, UserId}, identifiers::{DeviceId, RoomId, UserId},
uuid::Uuid, uuid::Uuid,
}; };
use tracing::error; use tracing::error;
@ -65,6 +65,28 @@ const MAX_AGE: Duration = Duration::from_secs(60 * 5);
// The max time a SAS object will wait for a new event to arrive. // The max time a SAS object will wait for a new event to arrive.
const MAX_EVENT_TIMEOUT: Duration = Duration::from_secs(60); const MAX_EVENT_TIMEOUT: Duration = Duration::from_secs(60);
#[derive(Clone, Debug)]
pub enum FlowId {
ToDevice(String),
InRoom(RoomId),
}
impl FlowId {
pub fn to_string(&self) -> String {
match self {
FlowId::InRoom(r) => r.to_string(),
FlowId::ToDevice(t) => t.to_string(),
}
}
pub fn as_str(&self) -> &str {
match self {
FlowId::InRoom(r) => r.as_str(),
FlowId::ToDevice(t) => t.as_str(),
}
}
}
/// Struct containing the protocols that were agreed to be used for the SAS /// Struct containing the protocols that were agreed to be used for the SAS
/// flow. /// flow.
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -143,7 +165,7 @@ pub struct SasState<S: Clone> {
/// ///
/// This will be the transaction id for to-device events and the relates_to /// This will be the transaction id for to-device events and the relates_to
/// field for in-room events. /// field for in-room events.
pub verification_flow_id: Arc<str>, pub verification_flow_id: Arc<FlowId>,
/// The SAS state we're in. /// The SAS state we're in.
state: Arc<S>, state: Arc<S>,
@ -268,7 +290,7 @@ impl<S: Clone> SasState<S> {
} }
fn check_event(&self, sender: &UserId, flow_id: &str) -> Result<(), CancelCode> { fn check_event(&self, sender: &UserId, flow_id: &str) -> Result<(), CancelCode> {
if *flow_id != *self.verification_flow_id { if *flow_id != *self.verification_flow_id.as_str() {
Err(CancelCode::UnknownTransaction) Err(CancelCode::UnknownTransaction)
} else if sender != self.ids.other_device.user_id() { } else if sender != self.ids.other_device.user_id() {
Err(CancelCode::UserMismatch) Err(CancelCode::UserMismatch)
@ -302,7 +324,7 @@ impl SasState<Created> {
other_device, other_device,
other_identity, other_identity,
}, },
verification_flow_id: verification_flow_id.into(), verification_flow_id: FlowId::ToDevice(verification_flow_id).into(),
creation_time: Arc::new(Instant::now()), creation_time: Arc::new(Instant::now()),
last_event_time: Arc::new(Instant::now()), last_event_time: Arc::new(Instant::now()),
@ -413,7 +435,7 @@ impl SasState<Started> {
creation_time: Arc::new(Instant::now()), creation_time: Arc::new(Instant::now()),
last_event_time: Arc::new(Instant::now()), last_event_time: Arc::new(Instant::now()),
verification_flow_id: event.content.transaction_id.as_str().into(), verification_flow_id: FlowId::ToDevice(event.content.transaction_id.clone()).into(),
state: Arc::new(Started { state: Arc::new(Started {
protocol_definitions: content.clone(), protocol_definitions: content.clone(),
@ -452,7 +474,7 @@ impl SasState<Started> {
other_identity, other_identity,
}, },
verification_flow_id: event.content.transaction_id.as_str().into(), verification_flow_id: FlowId::ToDevice(event.content.transaction_id.clone()).into(),
state: Arc::new(Canceled::new(CancelCode::UnknownMethod)), state: Arc::new(Canceled::new(CancelCode::UnknownMethod)),
}) })
} }
@ -575,9 +597,14 @@ impl SasState<Accepted> {
/// ///
/// The content needs to be automatically sent to the other side. /// The content needs to be automatically sent to the other side.
pub fn as_content(&self) -> KeyToDeviceEventContent { pub fn as_content(&self) -> KeyToDeviceEventContent {
KeyToDeviceEventContent { match &*self.verification_flow_id {
transaction_id: self.verification_flow_id.to_string(), FlowId::ToDevice(s) => KeyToDeviceEventContent {
key: self.inner.lock().unwrap().public_key(), transaction_id: s.to_string(),
key: self.inner.lock().unwrap().public_key(),
},
FlowId::InRoom(r) => {
todo!("In-room verifications aren't implemented")
}
} }
} }
} }
@ -588,9 +615,12 @@ impl SasState<KeyReceived> {
/// The content needs to be automatically sent to the other side if and only /// The content needs to be automatically sent to the other side if and only
/// if we_started is false. /// if we_started is false.
pub fn as_content(&self) -> KeyToDeviceEventContent { pub fn as_content(&self) -> KeyToDeviceEventContent {
KeyToDeviceEventContent { match self.verification_flow_id.as_ref() {
transaction_id: self.verification_flow_id.to_string(), FlowId::ToDevice(s) => KeyToDeviceEventContent {
key: self.inner.lock().unwrap().public_key(), transaction_id: s.to_string(),
key: self.inner.lock().unwrap().public_key(),
},
_ => todo!(),
} }
} }
@ -603,7 +633,7 @@ impl SasState<KeyReceived> {
&self.inner.lock().unwrap(), &self.inner.lock().unwrap(),
&self.ids, &self.ids,
&self.state.their_pubkey, &self.state.their_pubkey,
&self.verification_flow_id, self.verification_flow_id.as_str(),
self.state.we_started, self.state.we_started,
) )
} }
@ -617,7 +647,7 @@ impl SasState<KeyReceived> {
&self.inner.lock().unwrap(), &self.inner.lock().unwrap(),
&self.ids, &self.ids,
&self.state.their_pubkey, &self.state.their_pubkey,
&self.verification_flow_id, self.verification_flow_id.as_str(),
self.state.we_started, self.state.we_started,
) )
} }
@ -639,7 +669,7 @@ impl SasState<KeyReceived> {
let (devices, master_keys) = receive_mac_event( let (devices, master_keys) = receive_mac_event(
&self.inner.lock().unwrap(), &self.inner.lock().unwrap(),
&self.ids, &self.ids,
&self.verification_flow_id, self.verification_flow_id.as_str(),
event, event,
) )
.map_err(|c| self.clone().cancel(c))?; .map_err(|c| self.clone().cancel(c))?;
@ -695,7 +725,7 @@ impl SasState<Confirmed> {
let (devices, master_keys) = receive_mac_event( let (devices, master_keys) = receive_mac_event(
&self.inner.lock().unwrap(), &self.inner.lock().unwrap(),
&self.ids, &self.ids,
&self.verification_flow_id, &self.verification_flow_id.as_str(),
event, event,
) )
.map_err(|c| self.clone().cancel(c))?; .map_err(|c| self.clone().cancel(c))?;
@ -754,7 +784,7 @@ impl SasState<MacReceived> {
&self.inner.lock().unwrap(), &self.inner.lock().unwrap(),
&self.ids, &self.ids,
&self.state.their_pubkey, &self.state.their_pubkey,
&self.verification_flow_id, &self.verification_flow_id.as_str(),
self.state.we_started, self.state.we_started,
) )
} }
@ -768,7 +798,7 @@ impl SasState<MacReceived> {
&self.inner.lock().unwrap(), &self.inner.lock().unwrap(),
&self.ids, &self.ids,
&self.state.their_pubkey, &self.state.their_pubkey,
&self.verification_flow_id, &self.verification_flow_id.as_str(),
self.state.we_started, self.state.we_started,
) )
} }
@ -828,11 +858,16 @@ impl Canceled {
impl SasState<Canceled> { impl SasState<Canceled> {
pub fn as_content(&self) -> AnyToDeviceEventContent { pub fn as_content(&self) -> AnyToDeviceEventContent {
AnyToDeviceEventContent::KeyVerificationCancel(CancelToDeviceEventContent { match self.verification_flow_id.as_ref() {
transaction_id: self.verification_flow_id.to_string(), FlowId::ToDevice(s) => {
reason: self.state.reason.to_string(), AnyToDeviceEventContent::KeyVerificationCancel(CancelToDeviceEventContent {
code: self.state.cancel_code.clone(), transaction_id: self.verification_flow_id.to_string(),
}) reason: self.state.reason.to_string(),
code: self.state.cancel_code.clone(),
})
}
_ => todo!(),
}
} }
} }