crypto: Pass the identity further through the SAS layer and try to verify it.
This commit is contained in:
parent
6d0b73cb3d
commit
38cf771f1f
4 changed files with 78 additions and 15 deletions
|
@ -13,6 +13,7 @@
|
|||
// limitations under the License.
|
||||
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
convert::TryFrom,
|
||||
sync::{atomic::AtomicBool, Arc},
|
||||
};
|
||||
|
@ -151,6 +152,15 @@ pub enum UserIdentities {
|
|||
Other(UserIdentity),
|
||||
}
|
||||
|
||||
impl UserIdentities {
|
||||
pub fn master_key(&self) -> &BTreeMap<String, String> {
|
||||
match self {
|
||||
UserIdentities::Own(i) => i.master_key(),
|
||||
UserIdentities::Other(i) => i.master_key(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct UserIdentity {
|
||||
user_id: Arc<UserId>,
|
||||
|
@ -172,6 +182,10 @@ impl UserIdentity {
|
|||
})
|
||||
}
|
||||
|
||||
pub fn master_key(&self) -> &BTreeMap<String, String> {
|
||||
&self.master_key.0.keys
|
||||
}
|
||||
|
||||
pub fn update(
|
||||
&mut self,
|
||||
master_key: MasterPubkey,
|
||||
|
@ -236,6 +250,10 @@ impl OwnUserIdentity {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn master_key(&self) -> &BTreeMap<String, String> {
|
||||
&self.master_key.0.keys
|
||||
}
|
||||
|
||||
pub fn is_identity_signed(&self, identity: &UserIdentity) -> Result<(), SignatureError> {
|
||||
self.user_signing_key
|
||||
.verify_master_key(&identity.master_key)
|
||||
|
|
|
@ -30,12 +30,13 @@ use matrix_sdk_common::{
|
|||
uuid::Uuid,
|
||||
};
|
||||
|
||||
use crate::{Account, ReadOnlyDevice};
|
||||
use crate::{user_identity::UserIdentities, Account, ReadOnlyDevice};
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct SasIds {
|
||||
pub account: Account,
|
||||
pub other_device: ReadOnlyDevice,
|
||||
pub other_identity: Option<UserIdentities>,
|
||||
}
|
||||
|
||||
/// Get a tuple of an emoji and a description of the emoji using a number.
|
||||
|
@ -160,6 +161,7 @@ pub fn receive_mac_event(
|
|||
event: &ToDeviceEvent<MacEventContent>,
|
||||
) -> Result<(Vec<ReadOnlyDevice>, Vec<String>), CancelCode> {
|
||||
let mut verified_devices = Vec::new();
|
||||
let mut verified_identities = Vec::new();
|
||||
|
||||
let info = extra_mac_info_receive(&ids, flow_id);
|
||||
|
||||
|
@ -201,6 +203,25 @@ pub fn receive_mac_event(
|
|||
} else {
|
||||
return Err(CancelCode::KeyMismatch);
|
||||
}
|
||||
} else if let Some(identity) = &ids.other_identity {
|
||||
if let Some(key) = identity.master_key().get(key_id.as_str()) {
|
||||
// TODO we should check that the master key signs the device,
|
||||
// this way we know the master key also trusts the device
|
||||
if key_mac
|
||||
== &sas
|
||||
.calculate_mac(key, &format!("{}{}", info, key_id))
|
||||
.expect("Can't calculate SAS MAC")
|
||||
{
|
||||
trace!(
|
||||
"Successfully verified the master key {} from {}",
|
||||
key_id,
|
||||
event.sender
|
||||
);
|
||||
verified_identities.push(identity)
|
||||
} else {
|
||||
return Err(CancelCode::KeyMismatch);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warn!(
|
||||
"Key ID {} in MAC event from {} {} doesn't belong to any device \
|
||||
|
|
|
@ -107,7 +107,11 @@ impl Sas {
|
|||
store: Arc<Box<dyn CryptoStore>>,
|
||||
other_identity: Option<UserIdentities>,
|
||||
) -> (Sas, StartEventContent) {
|
||||
let (inner, content) = InnerSas::start(account.clone(), other_device.clone());
|
||||
let (inner, content) = InnerSas::start(
|
||||
account.clone(),
|
||||
other_device.clone(),
|
||||
other_identity.clone(),
|
||||
);
|
||||
let flow_id = inner.verification_flow_id();
|
||||
|
||||
let sas = Sas {
|
||||
|
@ -139,7 +143,12 @@ impl Sas {
|
|||
event: &ToDeviceEvent<StartEventContent>,
|
||||
other_identity: Option<UserIdentities>,
|
||||
) -> Result<Sas, AnyToDeviceEventContent> {
|
||||
let inner = InnerSas::from_start_event(account.clone(), other_device.clone(), event)?;
|
||||
let inner = InnerSas::from_start_event(
|
||||
account.clone(),
|
||||
other_device.clone(),
|
||||
event,
|
||||
other_identity.clone(),
|
||||
)?;
|
||||
let flow_id = inner.verification_flow_id();
|
||||
Ok(Sas {
|
||||
inner: Arc::new(Mutex::new(inner)),
|
||||
|
@ -346,8 +355,12 @@ enum InnerSas {
|
|||
}
|
||||
|
||||
impl InnerSas {
|
||||
fn start(account: Account, other_device: ReadOnlyDevice) -> (InnerSas, StartEventContent) {
|
||||
let sas = SasState::<Created>::new(account, other_device);
|
||||
fn start(
|
||||
account: Account,
|
||||
other_device: ReadOnlyDevice,
|
||||
other_identity: Option<UserIdentities>,
|
||||
) -> (InnerSas, StartEventContent) {
|
||||
let sas = SasState::<Created>::new(account, other_device, other_identity);
|
||||
let content = sas.as_content();
|
||||
(InnerSas::Created(sas), content)
|
||||
}
|
||||
|
@ -356,8 +369,9 @@ impl InnerSas {
|
|||
account: Account,
|
||||
other_device: ReadOnlyDevice,
|
||||
event: &ToDeviceEvent<StartEventContent>,
|
||||
other_identity: Option<UserIdentities>,
|
||||
) -> Result<InnerSas, AnyToDeviceEventContent> {
|
||||
match SasState::<Started>::from_start_event(account, other_device, event) {
|
||||
match SasState::<Started>::from_start_event(account, other_device, event, other_identity) {
|
||||
Ok(s) => Ok(InnerSas::Started(s)),
|
||||
Err(s) => Err(s.as_content()),
|
||||
}
|
||||
|
@ -599,12 +613,13 @@ mod test {
|
|||
let bob = Account::new(&bob_id(), &bob_device_id());
|
||||
let bob_device = ReadOnlyDevice::from_account(&bob).await;
|
||||
|
||||
let alice_sas = SasState::<Created>::new(alice.clone(), bob_device);
|
||||
let alice_sas = SasState::<Created>::new(alice.clone(), bob_device, None);
|
||||
|
||||
let start_content = alice_sas.as_content();
|
||||
let event = wrap_to_device_event(alice_sas.user_id(), start_content);
|
||||
|
||||
let bob_sas = SasState::<Started>::from_start_event(bob.clone(), alice_device, &event);
|
||||
let bob_sas =
|
||||
SasState::<Started>::from_start_event(bob.clone(), alice_device, &event, None);
|
||||
|
||||
(alice_sas, bob_sas.unwrap())
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@ use matrix_sdk_common::{
|
|||
|
||||
use super::helpers::{get_decimal, get_emoji, get_mac_content, receive_mac_event, SasIds};
|
||||
|
||||
use crate::{Account, ReadOnlyDevice};
|
||||
use crate::{user_identity::UserIdentities, Account, ReadOnlyDevice};
|
||||
|
||||
const KEY_AGREEMENT_PROTOCOLS: &[KeyAgreementProtocol] =
|
||||
&[KeyAgreementProtocol::Curve25519HkdfSha256];
|
||||
|
@ -286,7 +286,11 @@ impl SasState<Created> {
|
|||
/// * `account` - Our own account.
|
||||
///
|
||||
/// * `other_device` - The other device which we are going to verify.
|
||||
pub fn new(account: Account, other_device: ReadOnlyDevice) -> SasState<Created> {
|
||||
pub fn new(
|
||||
account: Account,
|
||||
other_device: ReadOnlyDevice,
|
||||
other_identity: Option<UserIdentities>,
|
||||
) -> SasState<Created> {
|
||||
let verification_flow_id = Uuid::new_v4().to_string();
|
||||
|
||||
SasState {
|
||||
|
@ -294,6 +298,7 @@ impl SasState<Created> {
|
|||
ids: SasIds {
|
||||
account,
|
||||
other_device,
|
||||
other_identity,
|
||||
},
|
||||
verification_flow_id: Arc::new(verification_flow_id),
|
||||
|
||||
|
@ -382,6 +387,7 @@ impl SasState<Started> {
|
|||
account: Account,
|
||||
other_device: ReadOnlyDevice,
|
||||
event: &ToDeviceEvent<StartEventContent>,
|
||||
other_identity: Option<UserIdentities>,
|
||||
) -> Result<SasState<Started>, SasState<Canceled>> {
|
||||
if let StartMethod::MSasV1(content) = &event.content.method {
|
||||
let sas = OlmSas::new();
|
||||
|
@ -397,6 +403,7 @@ impl SasState<Started> {
|
|||
ids: SasIds {
|
||||
account,
|
||||
other_device,
|
||||
other_identity,
|
||||
},
|
||||
|
||||
creation_time: Arc::new(Instant::now()),
|
||||
|
@ -438,6 +445,7 @@ impl SasState<Started> {
|
|||
ids: SasIds {
|
||||
account,
|
||||
other_device,
|
||||
other_identity,
|
||||
},
|
||||
|
||||
verification_flow_id: Arc::new(event.content.transaction_id.clone()),
|
||||
|
@ -871,12 +879,13 @@ mod test {
|
|||
let bob = Account::new(&bob_id(), &bob_device_id());
|
||||
let bob_device = ReadOnlyDevice::from_account(&bob).await;
|
||||
|
||||
let alice_sas = SasState::<Created>::new(alice.clone(), bob_device);
|
||||
let alice_sas = SasState::<Created>::new(alice.clone(), bob_device, None);
|
||||
|
||||
let start_content = alice_sas.as_content();
|
||||
let event = wrap_to_device_event(alice_sas.user_id(), start_content);
|
||||
|
||||
let bob_sas = SasState::<Started>::from_start_event(bob.clone(), alice_device, &event);
|
||||
let bob_sas =
|
||||
SasState::<Started>::from_start_event(bob.clone(), alice_device, &event, None);
|
||||
|
||||
(alice_sas, bob_sas.unwrap())
|
||||
}
|
||||
|
@ -1027,7 +1036,7 @@ mod test {
|
|||
let bob = Account::new(&bob_id(), &bob_device_id());
|
||||
let bob_device = ReadOnlyDevice::from_account(&bob).await;
|
||||
|
||||
let alice_sas = SasState::<Created>::new(alice.clone(), bob_device);
|
||||
let alice_sas = SasState::<Created>::new(alice.clone(), bob_device, None);
|
||||
|
||||
let mut start_content = alice_sas.as_content();
|
||||
|
||||
|
@ -1039,7 +1048,7 @@ mod test {
|
|||
}
|
||||
|
||||
let event = wrap_to_device_event(alice_sas.user_id(), start_content);
|
||||
SasState::<Started>::from_start_event(bob.clone(), alice_device.clone(), &event)
|
||||
SasState::<Started>::from_start_event(bob.clone(), alice_device.clone(), &event, None)
|
||||
.expect_err("Didn't cancel on invalid MAC method");
|
||||
|
||||
let mut start_content = alice_sas.as_content();
|
||||
|
@ -1050,7 +1059,7 @@ mod test {
|
|||
});
|
||||
|
||||
let event = wrap_to_device_event(alice_sas.user_id(), start_content);
|
||||
SasState::<Started>::from_start_event(bob.clone(), alice_device, &event)
|
||||
SasState::<Started>::from_start_event(bob.clone(), alice_device, &event, None)
|
||||
.expect_err("Didn't cancel on unknown sas method");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue