crypto: Add another SAS state so we know when both parties accepted
parent
113587247e
commit
9052843acb
|
@ -24,6 +24,7 @@ use ruma::{
|
|||
use super::{
|
||||
sas_state::{
|
||||
Accepted, Confirmed, Created, KeyReceived, MacReceived, SasState, Started, WaitingForDone,
|
||||
WeAccepted,
|
||||
},
|
||||
FlowId,
|
||||
};
|
||||
|
@ -41,6 +42,7 @@ pub enum InnerSas {
|
|||
Created(SasState<Created>),
|
||||
Started(SasState<Started>),
|
||||
Accepted(SasState<Accepted>),
|
||||
WeAccepted(SasState<WeAccepted>),
|
||||
KeyReceived(SasState<KeyReceived>),
|
||||
Confirmed(SasState<Confirmed>),
|
||||
MacReceived(SasState<MacReceived>),
|
||||
|
@ -65,6 +67,7 @@ impl InnerSas {
|
|||
match self {
|
||||
InnerSas::Created(s) => s.started_from_request,
|
||||
InnerSas::Started(s) => s.started_from_request,
|
||||
InnerSas::WeAccepted(s) => s.started_from_request,
|
||||
InnerSas::Accepted(s) => s.started_from_request,
|
||||
InnerSas::KeyReceived(s) => s.started_from_request,
|
||||
InnerSas::Confirmed(s) => s.started_from_request,
|
||||
|
@ -75,6 +78,19 @@ impl InnerSas {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn has_been_accepted(&self) -> bool {
|
||||
match self {
|
||||
InnerSas::Created(_) | InnerSas::Started(_) | InnerSas::Cancelled(_) => false,
|
||||
InnerSas::Accepted(_)
|
||||
| InnerSas::WeAccepted(_)
|
||||
| InnerSas::KeyReceived(_)
|
||||
| InnerSas::Confirmed(_)
|
||||
| InnerSas::MacReceived(_)
|
||||
| InnerSas::WaitingForDone(_)
|
||||
| InnerSas::Done(_) => true,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn supports_emoji(&self) -> bool {
|
||||
match self {
|
||||
InnerSas::Created(_) => false,
|
||||
|
@ -83,6 +99,11 @@ impl InnerSas {
|
|||
.accepted_protocols
|
||||
.short_auth_string
|
||||
.contains(&ShortAuthenticationString::Emoji),
|
||||
InnerSas::WeAccepted(s) => s
|
||||
.state
|
||||
.accepted_protocols
|
||||
.short_auth_string
|
||||
.contains(&ShortAuthenticationString::Emoji),
|
||||
InnerSas::Accepted(s) => s
|
||||
.state
|
||||
.accepted_protocols
|
||||
|
@ -144,9 +165,11 @@ impl InnerSas {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn accept(&self) -> Option<OwnedAcceptContent> {
|
||||
pub fn accept(self) -> Option<(InnerSas, OwnedAcceptContent)> {
|
||||
if let InnerSas::Started(s) = self {
|
||||
Some(s.as_content())
|
||||
let sas = s.into_accepted();
|
||||
let content = sas.as_content();
|
||||
Some((InnerSas::WeAccepted(sas), content))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
@ -165,6 +188,7 @@ impl InnerSas {
|
|||
InnerSas::MacReceived(s) => s.set_creation_time(time),
|
||||
InnerSas::Done(s) => s.set_creation_time(time),
|
||||
InnerSas::WaitingForDone(s) => s.set_creation_time(time),
|
||||
InnerSas::WeAccepted(s) => s.set_creation_time(time),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -177,6 +201,7 @@ impl InnerSas {
|
|||
InnerSas::Created(s) => s.cancel(cancelled_by_us, code),
|
||||
InnerSas::Started(s) => s.cancel(cancelled_by_us, code),
|
||||
InnerSas::Accepted(s) => s.cancel(cancelled_by_us, code),
|
||||
InnerSas::WeAccepted(s) => s.cancel(cancelled_by_us, code),
|
||||
InnerSas::KeyReceived(s) => s.cancel(cancelled_by_us, code),
|
||||
InnerSas::MacReceived(s) => s.cancel(cancelled_by_us, code),
|
||||
_ => return (self, None),
|
||||
|
@ -245,7 +270,7 @@ impl InnerSas {
|
|||
(InnerSas::Cancelled(s), Some(content))
|
||||
}
|
||||
},
|
||||
InnerSas::Started(s) => match s.into_key_received(sender, c) {
|
||||
InnerSas::WeAccepted(s) => match s.into_key_received(sender, c) {
|
||||
Ok(s) => {
|
||||
let content = s.as_content();
|
||||
(InnerSas::KeyReceived(s), Some(content))
|
||||
|
@ -347,6 +372,7 @@ impl InnerSas {
|
|||
InnerSas::MacReceived(s) => s.timed_out(),
|
||||
InnerSas::WaitingForDone(s) => s.timed_out(),
|
||||
InnerSas::Done(s) => s.timed_out(),
|
||||
InnerSas::WeAccepted(s) => s.timed_out(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -361,6 +387,7 @@ impl InnerSas {
|
|||
InnerSas::MacReceived(s) => s.verification_flow_id.clone(),
|
||||
InnerSas::WaitingForDone(s) => s.verification_flow_id.clone(),
|
||||
InnerSas::Done(s) => s.verification_flow_id.clone(),
|
||||
InnerSas::WeAccepted(s) => s.verification_flow_id.clone(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -119,6 +119,11 @@ impl Sas {
|
|||
self.inner.lock().unwrap().have_we_confirmed()
|
||||
}
|
||||
|
||||
/// Has the verification been accepted by both parties.
|
||||
pub fn has_been_accepted(&self) -> bool {
|
||||
self.inner.lock().unwrap().has_been_accepted()
|
||||
}
|
||||
|
||||
/// Get the cancel code of this SAS verification if it has been cancelled
|
||||
pub fn cancel_code(&self) -> Option<CancelCode> {
|
||||
self.inner.lock().unwrap().cancel_code()
|
||||
|
@ -310,7 +315,14 @@ impl Sas {
|
|||
&self,
|
||||
settings: AcceptSettings,
|
||||
) -> Option<OutgoingVerificationRequest> {
|
||||
self.inner.lock().unwrap().accept().map(|c| match settings.apply(c) {
|
||||
let mut guard = self.inner.lock().unwrap();
|
||||
let sas: InnerSas = (*guard).clone();
|
||||
|
||||
if let Some((sas, content)) = sas.accept() {
|
||||
*guard = sas;
|
||||
let content = settings.apply(content);
|
||||
|
||||
Some(match content {
|
||||
OwnedAcceptContent::ToDevice(c) => {
|
||||
let content = AnyToDeviceEventContent::KeyVerificationAccept(c);
|
||||
self.content_to_request(content).into()
|
||||
|
@ -322,6 +334,9 @@ impl Sas {
|
|||
}
|
||||
.into(),
|
||||
})
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Confirm the Sas verification.
|
||||
|
|
|
@ -241,6 +241,15 @@ pub struct Accepted {
|
|||
commitment: String,
|
||||
}
|
||||
|
||||
/// The SAS state we're going to be in after we accepted our
|
||||
/// verification start event.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct WeAccepted {
|
||||
we_started: bool,
|
||||
pub accepted_protocols: Arc<AcceptedProtocols>,
|
||||
commitment: String,
|
||||
}
|
||||
|
||||
/// The SAS state we're going to be in after we received the public key of the
|
||||
/// other participant.
|
||||
///
|
||||
|
@ -548,6 +557,24 @@ impl SasState<Started> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn into_accepted(self) -> SasState<WeAccepted> {
|
||||
SasState {
|
||||
inner: self.inner,
|
||||
ids: self.ids,
|
||||
verification_flow_id: self.verification_flow_id,
|
||||
creation_time: self.creation_time,
|
||||
last_event_time: self.last_event_time,
|
||||
started_from_request: self.started_from_request,
|
||||
state: Arc::new(WeAccepted {
|
||||
we_started: false,
|
||||
accepted_protocols: self.state.accepted_protocols.clone(),
|
||||
commitment: self.state.commitment.clone(),
|
||||
}),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SasState<WeAccepted> {
|
||||
/// Get the content for the accept event.
|
||||
///
|
||||
/// The content needs to be sent to the other device.
|
||||
|
@ -1093,7 +1120,7 @@ mod test {
|
|||
};
|
||||
use serde_json::json;
|
||||
|
||||
use super::{Accepted, Created, SasState, Started};
|
||||
use super::{Accepted, Created, SasState, Started, WeAccepted};
|
||||
use crate::{
|
||||
verification::event_enums::{AcceptContent, KeyContent, MacContent, StartContent},
|
||||
ReadOnlyAccount, ReadOnlyDevice,
|
||||
|
@ -1115,7 +1142,7 @@ mod test {
|
|||
"BOBDEVCIE".into()
|
||||
}
|
||||
|
||||
async fn get_sas_pair() -> (SasState<Created>, SasState<Started>) {
|
||||
async fn get_sas_pair() -> (SasState<Created>, SasState<WeAccepted>) {
|
||||
let alice = ReadOnlyAccount::new(&alice_id(), &alice_device_id());
|
||||
let alice_device = ReadOnlyDevice::from_account(&alice).await;
|
||||
|
||||
|
@ -1135,8 +1162,9 @@ mod test {
|
|||
&start_content.as_start_content(),
|
||||
false,
|
||||
);
|
||||
let bob_sas = bob_sas.unwrap().into_accepted();
|
||||
|
||||
(alice_sas, bob_sas.unwrap())
|
||||
(alice_sas, bob_sas)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
|
|
Loading…
Reference in New Issue