crypto: Add a method to check it the SAS flow supports emoji
parent
9863bc4a1c
commit
4f7902d6f0
|
@ -121,6 +121,12 @@ impl Sas {
|
||||||
self.inner.decimals()
|
self.inner.decimals()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Does this verification flow support emoji for the short authentication
|
||||||
|
/// string.
|
||||||
|
pub fn supports_emoji(&self) -> bool {
|
||||||
|
self.inner.supports_emoji()
|
||||||
|
}
|
||||||
|
|
||||||
/// Is the verification process done.
|
/// Is the verification process done.
|
||||||
pub fn is_done(&self) -> bool {
|
pub fn is_done(&self) -> bool {
|
||||||
self.inner.is_done()
|
self.inner.is_done()
|
||||||
|
|
|
@ -18,7 +18,10 @@ use std::time::Instant;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use matrix_sdk_common::{
|
use matrix_sdk_common::{
|
||||||
events::{key::verification::cancel::CancelCode, AnyMessageEvent, AnyToDeviceEvent},
|
events::{
|
||||||
|
key::verification::{cancel::CancelCode, ShortAuthenticationString},
|
||||||
|
AnyMessageEvent, AnyToDeviceEvent,
|
||||||
|
},
|
||||||
identifiers::{EventId, RoomId},
|
identifiers::{EventId, RoomId},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -61,6 +64,37 @@ impl InnerSas {
|
||||||
(InnerSas::Created(sas), content)
|
(InnerSas::Created(sas), content)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn supports_emoji(&self) -> bool {
|
||||||
|
match self {
|
||||||
|
InnerSas::Created(_) => false,
|
||||||
|
InnerSas::Started(s) => s
|
||||||
|
.state
|
||||||
|
.accepted_protocols
|
||||||
|
.short_auth_string
|
||||||
|
.contains(&ShortAuthenticationString::Emoji),
|
||||||
|
InnerSas::Accepted(s) => s
|
||||||
|
.state
|
||||||
|
.accepted_protocols
|
||||||
|
.short_auth_string
|
||||||
|
.contains(&ShortAuthenticationString::Emoji),
|
||||||
|
InnerSas::KeyRecieved(s) => s
|
||||||
|
.state
|
||||||
|
.accepted_protocols
|
||||||
|
.short_auth_string
|
||||||
|
.contains(&ShortAuthenticationString::Emoji),
|
||||||
|
InnerSas::Confirmed(_) => false,
|
||||||
|
InnerSas::MacReceived(s) => s
|
||||||
|
.state
|
||||||
|
.accepted_protocols
|
||||||
|
.short_auth_string
|
||||||
|
.contains(&ShortAuthenticationString::Emoji),
|
||||||
|
InnerSas::WaitingForDone(_) => false,
|
||||||
|
InnerSas::WaitingForDoneUnconfirmed(_) => false,
|
||||||
|
InnerSas::Done(_) => false,
|
||||||
|
InnerSas::Canceled(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn start_in_room(
|
pub fn start_in_room(
|
||||||
event_id: EventId,
|
event_id: EventId,
|
||||||
room_id: RoomId,
|
room_id: RoomId,
|
||||||
|
|
|
@ -110,6 +110,12 @@ impl Sas {
|
||||||
&self.flow_id
|
&self.flow_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Does this verification flow support displaying emoji for the short
|
||||||
|
/// authentication string.
|
||||||
|
pub fn supports_emoji(&self) -> bool {
|
||||||
|
self.inner.lock().unwrap().supports_emoji()
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub(crate) fn set_creation_time(&self, time: Instant) {
|
pub(crate) fn set_creation_time(&self, time: Instant) {
|
||||||
|
|
|
@ -98,12 +98,12 @@ impl FlowId {
|
||||||
/// 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)]
|
||||||
struct AcceptedProtocols {
|
pub struct AcceptedProtocols {
|
||||||
method: VerificationMethod,
|
pub method: VerificationMethod,
|
||||||
key_agreement_protocol: KeyAgreementProtocol,
|
pub key_agreement_protocol: KeyAgreementProtocol,
|
||||||
hash: HashAlgorithm,
|
pub hash: HashAlgorithm,
|
||||||
message_auth_code: MessageAuthenticationCode,
|
pub message_auth_code: MessageAuthenticationCode,
|
||||||
short_auth_string: Vec<ShortAuthenticationString>,
|
pub short_auth_string: Vec<ShortAuthenticationString>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TryFrom<AcceptV1Content> for AcceptedProtocols {
|
impl TryFrom<AcceptV1Content> for AcceptedProtocols {
|
||||||
|
@ -133,6 +133,53 @@ impl TryFrom<AcceptV1Content> for AcceptedProtocols {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl TryFrom<&MSasV1Content> for AcceptedProtocols {
|
||||||
|
type Error = CancelCode;
|
||||||
|
|
||||||
|
fn try_from(method_content: &MSasV1Content) -> Result<Self, Self::Error> {
|
||||||
|
if !method_content
|
||||||
|
.key_agreement_protocols
|
||||||
|
.contains(&KeyAgreementProtocol::Curve25519HkdfSha256)
|
||||||
|
|| !method_content
|
||||||
|
.message_authentication_codes
|
||||||
|
.contains(&MessageAuthenticationCode::HkdfHmacSha256)
|
||||||
|
|| !method_content.hashes.contains(&HashAlgorithm::Sha256)
|
||||||
|
|| (!method_content
|
||||||
|
.short_authentication_string
|
||||||
|
.contains(&ShortAuthenticationString::Decimal)
|
||||||
|
&& !method_content
|
||||||
|
.short_authentication_string
|
||||||
|
.contains(&ShortAuthenticationString::Emoji))
|
||||||
|
{
|
||||||
|
Err(CancelCode::UnknownMethod)
|
||||||
|
} else {
|
||||||
|
let mut short_auth_string = vec![];
|
||||||
|
|
||||||
|
if method_content
|
||||||
|
.short_authentication_string
|
||||||
|
.contains(&ShortAuthenticationString::Decimal)
|
||||||
|
{
|
||||||
|
short_auth_string.push(ShortAuthenticationString::Decimal)
|
||||||
|
}
|
||||||
|
|
||||||
|
if method_content
|
||||||
|
.short_authentication_string
|
||||||
|
.contains(&ShortAuthenticationString::Emoji)
|
||||||
|
{
|
||||||
|
short_auth_string.push(ShortAuthenticationString::Emoji);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Self {
|
||||||
|
method: VerificationMethod::MSasV1,
|
||||||
|
hash: HashAlgorithm::Sha256,
|
||||||
|
key_agreement_protocol: KeyAgreementProtocol::Curve25519HkdfSha256,
|
||||||
|
message_auth_code: MessageAuthenticationCode::HkdfHmacSha256,
|
||||||
|
short_auth_string,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[cfg(not(tarpaulin_include))]
|
#[cfg(not(tarpaulin_include))]
|
||||||
impl Default for AcceptedProtocols {
|
impl Default for AcceptedProtocols {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
|
@ -176,7 +223,7 @@ pub struct SasState<S: Clone> {
|
||||||
pub verification_flow_id: Arc<FlowId>,
|
pub verification_flow_id: Arc<FlowId>,
|
||||||
|
|
||||||
/// The SAS state we're in.
|
/// The SAS state we're in.
|
||||||
state: Arc<S>,
|
pub state: Arc<S>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(tarpaulin_include))]
|
#[cfg(not(tarpaulin_include))]
|
||||||
|
@ -200,14 +247,14 @@ pub struct Created {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Started {
|
pub struct Started {
|
||||||
commitment: String,
|
commitment: String,
|
||||||
protocol_definitions: MSasV1Content,
|
pub accepted_protocols: Arc<AcceptedProtocols>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The SAS state we're going to be in after the other side accepted our
|
/// The SAS state we're going to be in after the other side accepted our
|
||||||
/// verification start event.
|
/// verification start event.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Accepted {
|
pub struct Accepted {
|
||||||
accepted_protocols: Arc<AcceptedProtocols>,
|
pub accepted_protocols: Arc<AcceptedProtocols>,
|
||||||
start_content: Arc<StartContent>,
|
start_content: Arc<StartContent>,
|
||||||
commitment: String,
|
commitment: String,
|
||||||
}
|
}
|
||||||
|
@ -220,7 +267,7 @@ pub struct Accepted {
|
||||||
pub struct KeyReceived {
|
pub struct KeyReceived {
|
||||||
their_pubkey: String,
|
their_pubkey: String,
|
||||||
we_started: bool,
|
we_started: bool,
|
||||||
accepted_protocols: Arc<AcceptedProtocols>,
|
pub accepted_protocols: Arc<AcceptedProtocols>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The SAS state we're going to be in after the user has confirmed that the
|
/// The SAS state we're going to be in after the user has confirmed that the
|
||||||
|
@ -228,7 +275,7 @@ pub struct KeyReceived {
|
||||||
/// other side.
|
/// other side.
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct Confirmed {
|
pub struct Confirmed {
|
||||||
accepted_protocols: Arc<AcceptedProtocols>,
|
pub accepted_protocols: Arc<AcceptedProtocols>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The SAS state we're going to be in after we receive a MAC event from the
|
/// The SAS state we're going to be in after we receive a MAC event from the
|
||||||
|
@ -240,6 +287,7 @@ pub struct MacReceived {
|
||||||
their_pubkey: String,
|
their_pubkey: String,
|
||||||
verified_devices: Arc<[ReadOnlyDevice]>,
|
verified_devices: Arc<[ReadOnlyDevice]>,
|
||||||
verified_master_keys: Arc<[UserIdentities]>,
|
verified_master_keys: Arc<[UserIdentities]>,
|
||||||
|
pub accepted_protocols: Arc<AcceptedProtocols>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The SAS state we're going to be in after we receive a MAC event in a DM. DMs
|
/// The SAS state we're going to be in after we receive a MAC event in a DM. DMs
|
||||||
|
@ -490,6 +538,22 @@ impl SasState<Started> {
|
||||||
other_identity: Option<UserIdentities>,
|
other_identity: Option<UserIdentities>,
|
||||||
content: &StartContent,
|
content: &StartContent,
|
||||||
) -> Result<SasState<Started>, SasState<Canceled>> {
|
) -> Result<SasState<Started>, SasState<Canceled>> {
|
||||||
|
let canceled = || SasState {
|
||||||
|
inner: Arc::new(Mutex::new(OlmSas::new())),
|
||||||
|
|
||||||
|
creation_time: Arc::new(Instant::now()),
|
||||||
|
last_event_time: Arc::new(Instant::now()),
|
||||||
|
|
||||||
|
ids: SasIds {
|
||||||
|
account: account.clone(),
|
||||||
|
other_device: other_device.clone(),
|
||||||
|
other_identity: other_identity.clone(),
|
||||||
|
},
|
||||||
|
|
||||||
|
verification_flow_id: content.flow_id().into(),
|
||||||
|
state: Arc::new(Canceled::new(CancelCode::UnknownMethod)),
|
||||||
|
};
|
||||||
|
|
||||||
if let StartMethod::MSasV1(method_content) = content.method() {
|
if let StartMethod::MSasV1(method_content) = content.method() {
|
||||||
let sas = OlmSas::new();
|
let sas = OlmSas::new();
|
||||||
|
|
||||||
|
@ -501,60 +565,31 @@ impl SasState<Started> {
|
||||||
pubkey, content, commitment
|
pubkey, content, commitment
|
||||||
);
|
);
|
||||||
|
|
||||||
let sas = SasState {
|
if let Ok(accepted_protocols) = AcceptedProtocols::try_from(method_content) {
|
||||||
inner: Arc::new(Mutex::new(sas)),
|
Ok(SasState {
|
||||||
|
inner: Arc::new(Mutex::new(sas)),
|
||||||
|
|
||||||
ids: SasIds {
|
ids: SasIds {
|
||||||
account,
|
account,
|
||||||
other_device,
|
other_device,
|
||||||
other_identity,
|
other_identity,
|
||||||
},
|
},
|
||||||
|
|
||||||
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: content.flow_id().into(),
|
verification_flow_id: content.flow_id().into(),
|
||||||
|
|
||||||
state: Arc::new(Started {
|
state: Arc::new(Started {
|
||||||
protocol_definitions: method_content.clone(),
|
accepted_protocols: accepted_protocols.into(),
|
||||||
commitment,
|
commitment,
|
||||||
}),
|
}),
|
||||||
};
|
})
|
||||||
|
|
||||||
if !method_content
|
|
||||||
.key_agreement_protocols
|
|
||||||
.contains(&KeyAgreementProtocol::Curve25519HkdfSha256)
|
|
||||||
|| !method_content
|
|
||||||
.message_authentication_codes
|
|
||||||
.contains(&MessageAuthenticationCode::HkdfHmacSha256)
|
|
||||||
|| !method_content.hashes.contains(&HashAlgorithm::Sha256)
|
|
||||||
|| (!method_content
|
|
||||||
.short_authentication_string
|
|
||||||
.contains(&ShortAuthenticationString::Decimal)
|
|
||||||
&& !method_content
|
|
||||||
.short_authentication_string
|
|
||||||
.contains(&ShortAuthenticationString::Emoji))
|
|
||||||
{
|
|
||||||
Err(sas.cancel(CancelCode::UnknownMethod))
|
|
||||||
} else {
|
} else {
|
||||||
Ok(sas)
|
Err(canceled())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Err(SasState {
|
Err(canceled())
|
||||||
inner: Arc::new(Mutex::new(OlmSas::new())),
|
|
||||||
|
|
||||||
creation_time: Arc::new(Instant::now()),
|
|
||||||
last_event_time: Arc::new(Instant::now()),
|
|
||||||
|
|
||||||
ids: SasIds {
|
|
||||||
account,
|
|
||||||
other_device,
|
|
||||||
other_identity,
|
|
||||||
},
|
|
||||||
|
|
||||||
verification_flow_id: content.flow_id().into(),
|
|
||||||
state: Arc::new(Canceled::new(CancelCode::UnknownMethod)),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -566,18 +601,24 @@ impl SasState<Started> {
|
||||||
/// been started because of a
|
/// been started because of a
|
||||||
/// m.key.verification.request -> m.key.verification.ready flow.
|
/// m.key.verification.request -> m.key.verification.ready flow.
|
||||||
pub fn as_content(&self) -> AcceptContent {
|
pub fn as_content(&self) -> AcceptContent {
|
||||||
let accepted_protocols = AcceptedProtocols::default();
|
|
||||||
|
|
||||||
let method = AcceptMethod::MSasV1(
|
let method = AcceptMethod::MSasV1(
|
||||||
AcceptV1ContentInit {
|
AcceptV1ContentInit {
|
||||||
commitment: self.state.commitment.clone(),
|
commitment: self.state.commitment.clone(),
|
||||||
hash: accepted_protocols.hash,
|
hash: self.state.accepted_protocols.hash.clone(),
|
||||||
key_agreement_protocol: accepted_protocols.key_agreement_protocol,
|
key_agreement_protocol: self
|
||||||
message_authentication_code: accepted_protocols.message_auth_code,
|
.state
|
||||||
|
.accepted_protocols
|
||||||
|
.key_agreement_protocol
|
||||||
|
.clone(),
|
||||||
|
message_authentication_code: self
|
||||||
|
.state
|
||||||
|
.accepted_protocols
|
||||||
|
.message_auth_code
|
||||||
|
.clone(),
|
||||||
short_authentication_string: self
|
short_authentication_string: self
|
||||||
.state
|
.state
|
||||||
.protocol_definitions
|
.accepted_protocols
|
||||||
.short_authentication_string
|
.short_auth_string
|
||||||
.clone(),
|
.clone(),
|
||||||
}
|
}
|
||||||
.into(),
|
.into(),
|
||||||
|
@ -620,8 +661,6 @@ impl SasState<Started> {
|
||||||
self.check_event(&sender, &content.flow_id().as_str())
|
self.check_event(&sender, &content.flow_id().as_str())
|
||||||
.map_err(|c| self.clone().cancel(c))?;
|
.map_err(|c| self.clone().cancel(c))?;
|
||||||
|
|
||||||
let accepted_protocols = AcceptedProtocols::default();
|
|
||||||
|
|
||||||
let their_pubkey = content.public_key().to_owned();
|
let their_pubkey = content.public_key().to_owned();
|
||||||
|
|
||||||
self.inner
|
self.inner
|
||||||
|
@ -639,7 +678,7 @@ impl SasState<Started> {
|
||||||
state: Arc::new(KeyReceived {
|
state: Arc::new(KeyReceived {
|
||||||
we_started: false,
|
we_started: false,
|
||||||
their_pubkey,
|
their_pubkey,
|
||||||
accepted_protocols: Arc::new(accepted_protocols),
|
accepted_protocols: self.state.accepted_protocols.clone(),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -823,6 +862,7 @@ impl SasState<KeyReceived> {
|
||||||
their_pubkey: self.state.their_pubkey.clone(),
|
their_pubkey: self.state.their_pubkey.clone(),
|
||||||
verified_devices: devices.into(),
|
verified_devices: devices.into(),
|
||||||
verified_master_keys: master_keys.into(),
|
verified_master_keys: master_keys.into(),
|
||||||
|
accepted_protocols: self.state.accepted_protocols.clone(),
|
||||||
}),
|
}),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue