crypto: WIP change the types of the sas sturcts to allow in-room verifications.
parent
1bb5b42b1d
commit
b0ac9d3320
|
@ -42,6 +42,7 @@ use tracing::warn;
|
|||
use crate::{
|
||||
olm::{InboundGroupSession, PrivateCrossSigningIdentity, Session},
|
||||
store::{Changes, DeviceChanges},
|
||||
OutgoingRequest, OutgoingRequests,
|
||||
};
|
||||
#[cfg(test)]
|
||||
use crate::{OlmMachine, ReadOnlyAccount};
|
||||
|
@ -91,9 +92,16 @@ impl Device {
|
|||
///
|
||||
/// Returns a `Sas` object and to-device request that needs to be sent out.
|
||||
pub async fn start_verification(&self) -> StoreResult<(Sas, ToDeviceRequest)> {
|
||||
self.verification_machine
|
||||
let (sas, request) = self
|
||||
.verification_machine
|
||||
.start_sas(self.inner.clone())
|
||||
.await
|
||||
.await?;
|
||||
|
||||
if let OutgoingRequests::ToDeviceRequest(r) = request {
|
||||
Ok((sas, r))
|
||||
} else {
|
||||
panic!("Invalid verification request type");
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the Olm sessions that belong to this device.
|
||||
|
|
|
@ -30,14 +30,14 @@ use matrix_sdk_common::{
|
|||
|
||||
use super::{
|
||||
requests::VerificationRequest,
|
||||
sas::{content_to_request, Sas, VerificationResult},
|
||||
sas::{content_to_request, OutgoingContent, Sas, VerificationResult},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
olm::PrivateCrossSigningIdentity,
|
||||
requests::{OutgoingRequest, ToDeviceRequest},
|
||||
store::{CryptoStore, CryptoStoreError},
|
||||
ReadOnlyAccount, ReadOnlyDevice,
|
||||
OutgoingRequests, ReadOnlyAccount, ReadOnlyDevice,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -46,6 +46,7 @@ pub struct VerificationMachine {
|
|||
private_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
|
||||
pub(crate) store: Arc<Box<dyn CryptoStore>>,
|
||||
verifications: Arc<DashMap<String, Sas>>,
|
||||
room_verifications: Arc<DashMap<String, Sas>>,
|
||||
requests: Arc<DashMap<EventId, VerificationRequest>>,
|
||||
outgoing_to_device_messages: Arc<DashMap<Uuid, OutgoingRequest>>,
|
||||
}
|
||||
|
@ -63,13 +64,14 @@ impl VerificationMachine {
|
|||
verifications: DashMap::new().into(),
|
||||
requests: DashMap::new().into(),
|
||||
outgoing_to_device_messages: DashMap::new().into(),
|
||||
room_verifications: DashMap::new().into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn start_sas(
|
||||
&self,
|
||||
device: ReadOnlyDevice,
|
||||
) -> Result<(Sas, ToDeviceRequest), CryptoStoreError> {
|
||||
) -> Result<(Sas, OutgoingRequests), CryptoStoreError> {
|
||||
let identity = self.store.get_user_identity(device.user_id()).await?;
|
||||
let private_identity = self.private_identity.lock().await.clone();
|
||||
|
||||
|
@ -81,14 +83,17 @@ impl VerificationMachine {
|
|||
identity,
|
||||
);
|
||||
|
||||
let request = content_to_request(
|
||||
device.user_id(),
|
||||
device.device_id(),
|
||||
AnyToDeviceEventContent::KeyVerificationStart(content),
|
||||
);
|
||||
let request: OutgoingRequests = match content {
|
||||
OutgoingContent::Room(c) => todo!(),
|
||||
OutgoingContent::ToDevice(c) => {
|
||||
let request = content_to_request(device.user_id(), device.device_id(), c);
|
||||
|
||||
self.verifications
|
||||
.insert(sas.flow_id().to_string(), sas.clone());
|
||||
self.verifications
|
||||
.insert(sas.flow_id().to_string(), sas.clone());
|
||||
|
||||
request.into()
|
||||
}
|
||||
};
|
||||
|
||||
Ok((sas, request))
|
||||
}
|
||||
|
@ -170,9 +175,9 @@ impl VerificationMachine {
|
|||
);
|
||||
|
||||
let request = VerificationRequest::from_request_event(
|
||||
self.account.clone(),
|
||||
self.store.clone(),
|
||||
room_id,
|
||||
self.account.user_id(),
|
||||
self.account.device_id(),
|
||||
&m.sender,
|
||||
&m.event_id,
|
||||
r,
|
||||
|
|
|
@ -19,26 +19,38 @@ use std::sync::{Arc, Mutex};
|
|||
use matrix_sdk_common::{
|
||||
api::r0::message::send_message_event::Response as RoomMessageResponse,
|
||||
events::{
|
||||
key::verification::{ready::ReadyEventContent, Relation, VerificationMethod},
|
||||
key::verification::{
|
||||
ready::ReadyEventContent, start::StartEventContent, Relation, VerificationMethod,
|
||||
},
|
||||
room::message::KeyVerificationRequestEventContent,
|
||||
},
|
||||
identifiers::{DeviceId, DeviceIdBox, EventId, RoomId, UserId},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
olm::{PrivateCrossSigningIdentity, ReadOnlyAccount},
|
||||
store::CryptoStore,
|
||||
ReadOnlyDevice, Sas, UserIdentities, UserIdentity,
|
||||
};
|
||||
|
||||
use super::sas::{OutgoingContent, StartContent};
|
||||
|
||||
const SUPPORTED_METHODS: &[VerificationMethod] = &[VerificationMethod::MSasV1];
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
/// TODO
|
||||
pub struct VerificationRequest {
|
||||
inner: Arc<Mutex<InnerRequest>>,
|
||||
account: ReadOnlyAccount,
|
||||
store: Arc<Box<dyn CryptoStore>>,
|
||||
room_id: Arc<RoomId>,
|
||||
}
|
||||
|
||||
impl VerificationRequest {
|
||||
pub(crate) fn from_request_event(
|
||||
account: ReadOnlyAccount,
|
||||
store: Arc<Box<dyn CryptoStore>>,
|
||||
room_id: &RoomId,
|
||||
own_user_id: &UserId,
|
||||
own_device_id: &DeviceId,
|
||||
sender: &UserId,
|
||||
event_id: &EventId,
|
||||
content: &KeyVerificationRequestEventContent,
|
||||
|
@ -46,13 +58,15 @@ impl VerificationRequest {
|
|||
Self {
|
||||
inner: Arc::new(Mutex::new(InnerRequest::Requested(
|
||||
RequestState::from_request_event(
|
||||
own_user_id,
|
||||
own_device_id,
|
||||
account.user_id(),
|
||||
account.device_id(),
|
||||
sender,
|
||||
event_id,
|
||||
content,
|
||||
),
|
||||
))),
|
||||
account,
|
||||
store,
|
||||
room_id: room_id.clone().into(),
|
||||
}
|
||||
}
|
||||
|
@ -74,7 +88,6 @@ enum InnerRequest {
|
|||
Sent(RequestState<Sent>),
|
||||
Requested(RequestState<Requested>),
|
||||
Ready(RequestState<Ready>),
|
||||
Accepted(RequestState<Accepted>),
|
||||
Passive(RequestState<Passive>),
|
||||
}
|
||||
|
||||
|
@ -82,7 +95,7 @@ impl InnerRequest {
|
|||
fn accept(&mut self) -> Option<ReadyEventContent> {
|
||||
if let InnerRequest::Requested(s) = self {
|
||||
let (state, content) = s.clone().accept();
|
||||
*self = InnerRequest::Accepted(state);
|
||||
*self = InnerRequest::Ready(state);
|
||||
|
||||
Some(content)
|
||||
} else {
|
||||
|
@ -200,13 +213,12 @@ impl RequestState<Requested> {
|
|||
}
|
||||
}
|
||||
|
||||
fn accept(self) -> (RequestState<Accepted>, ReadyEventContent) {
|
||||
// TODO let the user pick a method here.
|
||||
fn accept(self) -> (RequestState<Ready>, ReadyEventContent) {
|
||||
let state = RequestState {
|
||||
own_user_id: self.own_user_id,
|
||||
own_device_id: self.own_device_id.clone(),
|
||||
other_user_id: self.other_user_id,
|
||||
state: Accepted {
|
||||
state: Ready {
|
||||
methods: self.state.methods.clone(),
|
||||
other_device_id: self.state.other_device_id.clone(),
|
||||
flow_id: self.state.flow_id.clone(),
|
||||
|
@ -238,17 +250,34 @@ struct Ready {
|
|||
pub flow_id: EventId,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct Accepted {
|
||||
/// The verification methods that were accepted
|
||||
pub methods: Vec<VerificationMethod>,
|
||||
impl RequestState<Ready> {
|
||||
fn into_started_sas(
|
||||
self,
|
||||
account: ReadOnlyAccount,
|
||||
private_identity: PrivateCrossSigningIdentity,
|
||||
other_device: ReadOnlyDevice,
|
||||
other_identity: UserIdentity,
|
||||
) -> Sas {
|
||||
todo!()
|
||||
// Sas::from_start_event(account, private_identity, other_device, other_identity, event)
|
||||
}
|
||||
|
||||
/// The device id of the device that responded to the verification request.
|
||||
pub other_device_id: DeviceIdBox,
|
||||
|
||||
/// The event id of the `m.key.verification.request` event which acts as an
|
||||
/// unique id identifying this verification flow.
|
||||
pub flow_id: EventId,
|
||||
fn start_sas(
|
||||
self,
|
||||
store: Arc<Box<dyn CryptoStore>>,
|
||||
account: ReadOnlyAccount,
|
||||
private_identity: PrivateCrossSigningIdentity,
|
||||
other_device: ReadOnlyDevice,
|
||||
other_identity: Option<UserIdentities>,
|
||||
) -> (Sas, OutgoingContent) {
|
||||
Sas::start(
|
||||
account,
|
||||
private_identity,
|
||||
other_device,
|
||||
store,
|
||||
other_identity,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
|
|
@ -0,0 +1,76 @@
|
|||
// 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.
|
||||
|
||||
#![allow(dead_code)]
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
||||
use matrix_sdk_common::{
|
||||
events::{
|
||||
key::verification::start::{StartEventContent, StartToDeviceEventContent},
|
||||
AnyMessageEventContent, AnyToDeviceEventContent, MessageEvent, ToDeviceEvent,
|
||||
},
|
||||
CanonicalJsonValue,
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum StartContent {
|
||||
ToDevice(StartToDeviceEventContent),
|
||||
Room(StartEventContent),
|
||||
}
|
||||
|
||||
impl StartContent {
|
||||
pub fn to_canonical_json(self) -> CanonicalJsonValue {
|
||||
let content = match self {
|
||||
StartContent::Room(c) => serde_json::to_value(c),
|
||||
StartContent::ToDevice(c) => serde_json::to_value(c),
|
||||
};
|
||||
|
||||
content
|
||||
.expect("Can't serialize content")
|
||||
.try_into()
|
||||
.expect("Can't canonicalize content")
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StartEventContent> for StartContent {
|
||||
fn from(content: StartEventContent) -> Self {
|
||||
StartContent::Room(content)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<StartToDeviceEventContent> for StartContent {
|
||||
fn from(content: StartToDeviceEventContent) -> Self {
|
||||
StartContent::ToDevice(content)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub enum OutgoingContent {
|
||||
Room(AnyMessageEventContent),
|
||||
ToDevice(AnyToDeviceEventContent),
|
||||
}
|
||||
|
||||
impl From<StartContent> for OutgoingContent {
|
||||
fn from(content: StartContent) -> Self {
|
||||
match content {
|
||||
StartContent::Room(c) => {
|
||||
OutgoingContent::Room(AnyMessageEventContent::KeyVerificationStart(c))
|
||||
}
|
||||
StartContent::ToDevice(c) => {
|
||||
OutgoingContent::ToDevice(AnyToDeviceEventContent::KeyVerificationStart(c))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -38,7 +38,7 @@ use crate::{
|
|||
ReadOnlyAccount, ToDeviceRequest,
|
||||
};
|
||||
|
||||
use super::sas_state::FlowId;
|
||||
use super::{event_enums::StartContent, sas_state::FlowId};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SasIds {
|
||||
|
@ -57,15 +57,12 @@ pub struct SasIds {
|
|||
///
|
||||
/// * `content` - The `m.key.verification.start` event content that started the
|
||||
/// interactive verification process.
|
||||
pub fn calculate_commitment(public_key: &str, content: &StartToDeviceEventContent) -> String {
|
||||
let json_content: CanonicalJsonValue = serde_json::to_value(content)
|
||||
.expect("Can't serialize content")
|
||||
.try_into()
|
||||
.expect("Can't canonicalize content");
|
||||
pub fn calculate_commitment(public_key: &str, content: impl Into<StartContent>) -> String {
|
||||
let content = content.into().to_canonical_json();
|
||||
|
||||
encode(
|
||||
Sha256::new()
|
||||
.chain(&format!("{}{}", public_key, json_content))
|
||||
.chain(&format!("{}{}", public_key, content))
|
||||
.finalize(),
|
||||
)
|
||||
}
|
||||
|
|
|
@ -17,12 +17,15 @@ use std::time::Instant;
|
|||
|
||||
use std::sync::Arc;
|
||||
|
||||
use matrix_sdk_common::events::{
|
||||
key::verification::{
|
||||
accept::AcceptToDeviceEventContent, cancel::CancelCode, mac::MacToDeviceEventContent,
|
||||
start::StartToDeviceEventContent,
|
||||
use matrix_sdk_common::{
|
||||
events::{
|
||||
key::verification::{
|
||||
accept::AcceptToDeviceEventContent, cancel::CancelCode, mac::MacToDeviceEventContent,
|
||||
start::StartToDeviceEventContent,
|
||||
},
|
||||
AnyToDeviceEvent, AnyToDeviceEventContent, ToDeviceEvent,
|
||||
},
|
||||
AnyToDeviceEvent, AnyToDeviceEventContent, ToDeviceEvent,
|
||||
identifiers::EventId,
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
@ -30,9 +33,12 @@ use crate::{
|
|||
ReadOnlyAccount,
|
||||
};
|
||||
|
||||
use super::sas_state::{
|
||||
Accepted, Canceled, Confirmed, Created, Done, FlowId, KeyReceived, MacReceived, SasState,
|
||||
Started,
|
||||
use super::{
|
||||
event_enums::OutgoingContent,
|
||||
sas_state::{
|
||||
Accepted, Canceled, Confirmed, Created, Done, FlowId, KeyReceived, MacReceived, SasState,
|
||||
Started,
|
||||
},
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
|
@ -52,12 +58,23 @@ impl InnerSas {
|
|||
account: ReadOnlyAccount,
|
||||
other_device: ReadOnlyDevice,
|
||||
other_identity: Option<UserIdentities>,
|
||||
) -> (InnerSas, StartToDeviceEventContent) {
|
||||
) -> (InnerSas, OutgoingContent) {
|
||||
let sas = SasState::<Created>::new(account, other_device, other_identity);
|
||||
let content = sas.as_content();
|
||||
(InnerSas::Created(sas), content)
|
||||
}
|
||||
|
||||
pub fn start_in_room(
|
||||
event_id: EventId,
|
||||
account: ReadOnlyAccount,
|
||||
other_device: ReadOnlyDevice,
|
||||
other_identity: Option<UserIdentities>,
|
||||
) -> (InnerSas, OutgoingContent) {
|
||||
let sas = SasState::<Created>::new_in_room(event_id, account, other_device, other_identity);
|
||||
let content = sas.as_content();
|
||||
(InnerSas::Created(sas), content)
|
||||
}
|
||||
|
||||
pub fn from_start_event(
|
||||
account: ReadOnlyAccount,
|
||||
other_device: ReadOnlyDevice,
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
mod event_enums;
|
||||
mod helpers;
|
||||
mod inner_sas;
|
||||
mod sas_state;
|
||||
|
@ -46,6 +47,8 @@ pub use helpers::content_to_request;
|
|||
use inner_sas::InnerSas;
|
||||
pub use sas_state::FlowId;
|
||||
|
||||
pub use event_enums::{OutgoingContent, StartContent};
|
||||
|
||||
#[derive(Debug)]
|
||||
/// A result of a verification flow.
|
||||
pub enum VerificationResult {
|
||||
|
@ -106,6 +109,30 @@ impl Sas {
|
|||
self.inner.lock().unwrap().set_creation_time(time)
|
||||
}
|
||||
|
||||
fn start_helper(
|
||||
inner_sas: InnerSas,
|
||||
content: OutgoingContent,
|
||||
account: ReadOnlyAccount,
|
||||
private_identity: PrivateCrossSigningIdentity,
|
||||
other_device: ReadOnlyDevice,
|
||||
store: Arc<Box<dyn CryptoStore>>,
|
||||
other_identity: Option<UserIdentities>,
|
||||
) -> (Sas, OutgoingContent) {
|
||||
let flow_id = inner_sas.verification_flow_id();
|
||||
|
||||
let sas = Sas {
|
||||
inner: Arc::new(Mutex::new(inner_sas)),
|
||||
account,
|
||||
private_identity,
|
||||
store,
|
||||
other_device,
|
||||
flow_id,
|
||||
other_identity,
|
||||
};
|
||||
|
||||
(sas, content)
|
||||
}
|
||||
|
||||
/// Start a new SAS auth flow with the given device.
|
||||
///
|
||||
/// # Arguments
|
||||
|
@ -122,25 +149,60 @@ impl Sas {
|
|||
other_device: ReadOnlyDevice,
|
||||
store: Arc<Box<dyn CryptoStore>>,
|
||||
other_identity: Option<UserIdentities>,
|
||||
) -> (Sas, StartToDeviceEventContent) {
|
||||
) -> (Sas, OutgoingContent) {
|
||||
let (inner, content) = InnerSas::start(
|
||||
account.clone(),
|
||||
other_device.clone(),
|
||||
other_identity.clone(),
|
||||
);
|
||||
let flow_id = inner.verification_flow_id();
|
||||
|
||||
let sas = Sas {
|
||||
inner: Arc::new(Mutex::new(inner)),
|
||||
Self::start_helper(
|
||||
inner,
|
||||
content,
|
||||
account,
|
||||
private_identity,
|
||||
store,
|
||||
other_device,
|
||||
flow_id,
|
||||
store,
|
||||
other_identity,
|
||||
};
|
||||
)
|
||||
}
|
||||
|
||||
(sas, content)
|
||||
/// Start a new SAS auth flow with the given device inside the given room.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `account` - Our own account.
|
||||
///
|
||||
/// * `other_device` - The other device which we are going to verify.
|
||||
///
|
||||
/// Returns the new `Sas` object and a `StartEventContent` that needs to be
|
||||
/// sent out through the server to the other device.
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn start_in_room(
|
||||
flow_id: EventId,
|
||||
room_id: RoomId,
|
||||
account: ReadOnlyAccount,
|
||||
private_identity: PrivateCrossSigningIdentity,
|
||||
other_device: ReadOnlyDevice,
|
||||
store: Arc<Box<dyn CryptoStore>>,
|
||||
other_identity: Option<UserIdentities>,
|
||||
) -> (Sas, OutgoingContent) {
|
||||
let (inner, content) = InnerSas::start_in_room(
|
||||
flow_id,
|
||||
account.clone(),
|
||||
other_device.clone(),
|
||||
other_identity.clone(),
|
||||
);
|
||||
|
||||
Self::start_helper(
|
||||
inner,
|
||||
content,
|
||||
account,
|
||||
private_identity,
|
||||
other_device,
|
||||
store,
|
||||
other_identity,
|
||||
)
|
||||
}
|
||||
|
||||
/// Create a new Sas object from a m.key.verification.start request.
|
||||
|
|
|
@ -30,19 +30,25 @@ use matrix_sdk_common::{
|
|||
cancel::{CancelCode, CancelToDeviceEventContent},
|
||||
key::KeyToDeviceEventContent,
|
||||
mac::MacToDeviceEventContent,
|
||||
start::{MSasV1Content, MSasV1ContentInit, StartMethod, StartToDeviceEventContent},
|
||||
HashAlgorithm, KeyAgreementProtocol, MessageAuthenticationCode,
|
||||
start::{
|
||||
MSasV1Content, MSasV1ContentInit, StartEventContent, StartMethod,
|
||||
StartToDeviceEventContent,
|
||||
},
|
||||
HashAlgorithm, KeyAgreementProtocol, MessageAuthenticationCode, Relation,
|
||||
ShortAuthenticationString, VerificationMethod,
|
||||
},
|
||||
AnyToDeviceEventContent, ToDeviceEvent,
|
||||
AnyMessageEventContent, AnyToDeviceEventContent, ToDeviceEvent,
|
||||
},
|
||||
identifiers::{DeviceId, RoomId, UserId},
|
||||
identifiers::{DeviceId, EventId, UserId},
|
||||
uuid::Uuid,
|
||||
};
|
||||
use tracing::error;
|
||||
|
||||
use super::helpers::{
|
||||
calculate_commitment, get_decimal, get_emoji, get_mac_content, receive_mac_event, SasIds,
|
||||
use super::{
|
||||
event_enums::{OutgoingContent, StartContent},
|
||||
helpers::{
|
||||
calculate_commitment, get_decimal, get_emoji, get_mac_content, receive_mac_event, SasIds,
|
||||
},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
|
@ -68,7 +74,7 @@ const MAX_EVENT_TIMEOUT: Duration = Duration::from_secs(60);
|
|||
#[derive(Clone, Debug)]
|
||||
pub enum FlowId {
|
||||
ToDevice(String),
|
||||
InRoom(RoomId),
|
||||
InRoom(EventId),
|
||||
}
|
||||
|
||||
impl FlowId {
|
||||
|
@ -200,7 +206,7 @@ pub struct Started {
|
|||
#[derive(Clone, Debug)]
|
||||
pub struct Accepted {
|
||||
accepted_protocols: Arc<AcceptedProtocols>,
|
||||
start_content: Arc<StartToDeviceEventContent>,
|
||||
start_content: Arc<StartContent>,
|
||||
commitment: String,
|
||||
}
|
||||
|
||||
|
@ -310,13 +316,45 @@ impl SasState<Created> {
|
|||
/// * `account` - Our own account.
|
||||
///
|
||||
/// * `other_device` - The other device which we are going to verify.
|
||||
///
|
||||
/// * `other_identity` - The identity of the other user if one exists.
|
||||
pub fn new(
|
||||
account: ReadOnlyAccount,
|
||||
other_device: ReadOnlyDevice,
|
||||
other_identity: Option<UserIdentities>,
|
||||
) -> SasState<Created> {
|
||||
let verification_flow_id = Uuid::new_v4().to_string();
|
||||
let flow_id = FlowId::ToDevice(Uuid::new_v4().to_string());
|
||||
Self::new_helper(flow_id, account, other_device, other_identity)
|
||||
}
|
||||
|
||||
/// Create a new SAS in-room verification flow.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `event_id` - The event id of the `m.key.verification.request` event
|
||||
/// that started the verification flow.
|
||||
///
|
||||
/// * `account` - Our own account.
|
||||
///
|
||||
/// * `other_device` - The other device which we are going to verify.
|
||||
///
|
||||
/// * `other_identity` - The identity of the other user if one exists.
|
||||
pub fn new_in_room(
|
||||
event_id: EventId,
|
||||
account: ReadOnlyAccount,
|
||||
other_device: ReadOnlyDevice,
|
||||
other_identity: Option<UserIdentities>,
|
||||
) -> SasState<Created> {
|
||||
let flow_id = FlowId::InRoom(event_id);
|
||||
Self::new_helper(flow_id, account, other_device, other_identity)
|
||||
}
|
||||
|
||||
fn new_helper(
|
||||
flow_id: FlowId,
|
||||
account: ReadOnlyAccount,
|
||||
other_device: ReadOnlyDevice,
|
||||
other_identity: Option<UserIdentities>,
|
||||
) -> SasState<Created> {
|
||||
SasState {
|
||||
inner: Arc::new(Mutex::new(OlmSas::new())),
|
||||
ids: SasIds {
|
||||
|
@ -324,7 +362,7 @@ impl SasState<Created> {
|
|||
other_device,
|
||||
other_identity,
|
||||
},
|
||||
verification_flow_id: FlowId::ToDevice(verification_flow_id).into(),
|
||||
verification_flow_id: flow_id.into(),
|
||||
|
||||
creation_time: Arc::new(Instant::now()),
|
||||
last_event_time: Arc::new(Instant::now()),
|
||||
|
@ -340,18 +378,34 @@ impl SasState<Created> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn as_start_content(&self) -> StartContent {
|
||||
match self.verification_flow_id.as_ref() {
|
||||
FlowId::ToDevice(s) => StartContent::ToDevice(StartToDeviceEventContent {
|
||||
transaction_id: self.verification_flow_id.to_string(),
|
||||
from_device: self.device_id().into(),
|
||||
method: StartMethod::MSasV1(
|
||||
MSasV1Content::new(self.state.protocol_definitions.clone())
|
||||
.expect("Invalid initial protocol definitions."),
|
||||
),
|
||||
}),
|
||||
FlowId::InRoom(e) => StartContent::Room(StartEventContent {
|
||||
from_device: self.device_id().into(),
|
||||
method: StartMethod::MSasV1(
|
||||
MSasV1Content::new(self.state.protocol_definitions.clone())
|
||||
.expect("Invalid initial protocol definitions."),
|
||||
),
|
||||
relation: Relation {
|
||||
event_id: e.clone(),
|
||||
},
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the content for the start event.
|
||||
///
|
||||
/// The content needs to be sent to the other device.
|
||||
pub fn as_content(&self) -> StartToDeviceEventContent {
|
||||
StartToDeviceEventContent {
|
||||
transaction_id: self.verification_flow_id.to_string(),
|
||||
from_device: self.device_id().into(),
|
||||
method: StartMethod::MSasV1(
|
||||
MSasV1Content::new(self.state.protocol_definitions.clone())
|
||||
.expect("Invalid initial protocol definitions."),
|
||||
),
|
||||
}
|
||||
pub fn as_content(&self) -> OutgoingContent {
|
||||
self.as_start_content().into()
|
||||
}
|
||||
|
||||
/// Receive a m.key.verification.accept event, changing the state into
|
||||
|
@ -372,7 +426,7 @@ impl SasState<Created> {
|
|||
let accepted_protocols =
|
||||
AcceptedProtocols::try_from(content.clone()).map_err(|c| self.clone().cancel(c))?;
|
||||
|
||||
let start_content = self.as_content().into();
|
||||
let start_content = self.as_start_content().into();
|
||||
|
||||
Ok(SasState {
|
||||
inner: self.inner,
|
||||
|
@ -416,7 +470,7 @@ impl SasState<Started> {
|
|||
let sas = OlmSas::new();
|
||||
|
||||
let pubkey = sas.public_key();
|
||||
let commitment = calculate_commitment(&pubkey, &event.content);
|
||||
let commitment = calculate_commitment(&pubkey, event.content.clone());
|
||||
|
||||
error!(
|
||||
"Calculated commitment for pubkey {} and content {:?} {}",
|
||||
|
@ -565,7 +619,10 @@ impl SasState<Accepted> {
|
|||
self.check_event(&event.sender, &event.content.transaction_id)
|
||||
.map_err(|c| self.clone().cancel(c))?;
|
||||
|
||||
let commitment = calculate_commitment(&event.content.key, &self.state.start_content);
|
||||
let commitment = calculate_commitment(
|
||||
&event.content.key,
|
||||
self.state.start_content.as_ref().clone(),
|
||||
);
|
||||
|
||||
if self.state.commitment != commitment {
|
||||
Err(self.cancel(CancelCode::InvalidMessage))
|
||||
|
|
Loading…
Reference in New Issue