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