crypto: Test a key share cycle.
parent
798656dac5
commit
e1c220e2f7
|
@ -586,7 +586,12 @@ impl KeyRequestMachine {
|
|||
mod test {
|
||||
use dashmap::DashMap;
|
||||
use matrix_sdk_common::{
|
||||
events::{forwarded_room_key::ForwardedRoomKeyEventContent, ToDeviceEvent},
|
||||
api::r0::to_device::DeviceIdOrAllDevices,
|
||||
events::{
|
||||
forwarded_room_key::ForwardedRoomKeyEventContent,
|
||||
room::encrypted::EncryptedEventContent, room_key_request::RoomKeyRequestEventContent,
|
||||
ToDeviceEvent,
|
||||
},
|
||||
identifiers::{room_id, user_id, DeviceIdBox, RoomId, UserId},
|
||||
};
|
||||
use matrix_sdk_test::async_test;
|
||||
|
@ -628,6 +633,18 @@ mod test {
|
|||
Account::new(&bob_id(), &bob_device_id())
|
||||
}
|
||||
|
||||
fn bob_machine() -> KeyRequestMachine {
|
||||
let user_id = Arc::new(bob_id());
|
||||
let store = Store::new(user_id.clone(), Box::new(MemoryStore::new()));
|
||||
|
||||
KeyRequestMachine::new(
|
||||
user_id,
|
||||
Arc::new(bob_device_id()),
|
||||
store,
|
||||
Arc::new(DashMap::new()),
|
||||
)
|
||||
}
|
||||
|
||||
fn get_machine() -> KeyRequestMachine {
|
||||
let user_id = Arc::new(alice_id());
|
||||
let store = Store::new(user_id.clone(), Box::new(MemoryStore::new()));
|
||||
|
@ -884,4 +901,140 @@ mod test {
|
|||
.should_share_session(&bob_device, Some(&session))
|
||||
.is_ok());
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn key_share_cycle() {
|
||||
let alice_machine = get_machine();
|
||||
let alice_account = account();
|
||||
|
||||
let bob_machine = bob_machine();
|
||||
let bob_account = bob_account();
|
||||
|
||||
// Create Olm sessions for our two accounts.
|
||||
let (alice_session, bob_session) = alice_account.create_session_for(&bob_account).await;
|
||||
|
||||
let alice_device = ReadOnlyDevice::from_account(&alice_account).await;
|
||||
let bob_device = ReadOnlyDevice::from_account(&bob_account).await;
|
||||
|
||||
// Populate our stores with Olm sessions and a Megolm session.
|
||||
|
||||
alice_machine
|
||||
.store
|
||||
.save_sessions(&[alice_session])
|
||||
.await
|
||||
.unwrap();
|
||||
alice_machine
|
||||
.store
|
||||
.save_devices(&[bob_device])
|
||||
.await
|
||||
.unwrap();
|
||||
bob_machine
|
||||
.store
|
||||
.save_sessions(&[bob_session])
|
||||
.await
|
||||
.unwrap();
|
||||
bob_machine
|
||||
.store
|
||||
.save_devices(&[alice_device])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let (group_session, inbound_group_session) = bob_account
|
||||
.create_group_session_pair_with_defaults(&room_id())
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
bob_machine
|
||||
.store
|
||||
.save_inbound_group_sessions(&[inbound_group_session])
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
// Alice wants to request the outbound group session from bob.
|
||||
alice_machine
|
||||
.create_outgoing_key_request(
|
||||
&room_id(),
|
||||
bob_account.identity_keys.curve25519(),
|
||||
group_session.session_id(),
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
group_session.mark_shared_with(&alice_id(), &alice_device_id());
|
||||
|
||||
// Put the outbound session into bobs store.
|
||||
bob_machine
|
||||
.outbound_group_sessions
|
||||
.insert(room_id(), group_session);
|
||||
|
||||
// Get the request and convert it into a event.
|
||||
let request = alice_machine
|
||||
.outgoing_to_device_requests
|
||||
.iter()
|
||||
.next()
|
||||
.unwrap();
|
||||
let id = request.request_id;
|
||||
let content = request
|
||||
.request
|
||||
.to_device()
|
||||
.unwrap()
|
||||
.messages
|
||||
.get(&alice_id())
|
||||
.unwrap()
|
||||
.get(&DeviceIdOrAllDevices::AllDevices)
|
||||
.unwrap();
|
||||
let content: RoomKeyRequestEventContent = serde_json::from_str(content.get()).unwrap();
|
||||
|
||||
drop(request);
|
||||
alice_machine
|
||||
.mark_outgoing_request_as_sent(&id)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let event = ToDeviceEvent {
|
||||
sender: alice_id(),
|
||||
content,
|
||||
};
|
||||
|
||||
// Bob doesn't have any outgoing requests.
|
||||
assert!(bob_machine.outgoing_to_device_requests.is_empty());
|
||||
|
||||
// Receive the room key request from alice.
|
||||
bob_machine.receive_incoming_key_request(&event);
|
||||
bob_machine.collect_incoming_key_requests().await.unwrap();
|
||||
// Now bob does have an outgoing request.
|
||||
assert!(!bob_machine.outgoing_to_device_requests.is_empty());
|
||||
|
||||
// Get the request and convert it to a encrypted to-device event.
|
||||
let request = bob_machine
|
||||
.outgoing_to_device_requests
|
||||
.iter()
|
||||
.next()
|
||||
.unwrap();
|
||||
|
||||
let id = request.request_id;
|
||||
let content = request
|
||||
.request
|
||||
.to_device()
|
||||
.unwrap()
|
||||
.messages
|
||||
.get(&alice_id())
|
||||
.unwrap()
|
||||
.get(&DeviceIdOrAllDevices::DeviceId(alice_device_id()))
|
||||
.unwrap();
|
||||
let content: EncryptedEventContent = serde_json::from_str(content.get()).unwrap();
|
||||
|
||||
drop(request);
|
||||
bob_machine
|
||||
.mark_outgoing_request_as_sent(&id)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let _event = ToDeviceEvent {
|
||||
sender: bob_id(),
|
||||
content,
|
||||
};
|
||||
|
||||
// TODO test that alice can receive, decrypt and add the requested key
|
||||
// to the store.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#[cfg(test)]
|
||||
use matrix_sdk_common::events::{room::encrypted::EncryptedEventContent, EventType};
|
||||
use std::{
|
||||
collections::BTreeMap,
|
||||
convert::{TryFrom, TryInto},
|
||||
|
@ -617,6 +619,61 @@ impl Account {
|
|||
self.create_group_session_pair(room_id, EncryptionSettings::default(), [].iter())
|
||||
.await
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub(crate) async fn create_session_for(&self, other: &Account) -> (Session, Session) {
|
||||
other.generate_one_time_keys_helper(1).await;
|
||||
let one_time = other.signed_one_time_keys().await.unwrap();
|
||||
|
||||
let device = ReadOnlyDevice::from_account(other).await;
|
||||
|
||||
let mut our_session = self
|
||||
.create_outbound_session(device.clone(), &one_time)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
let message = our_session
|
||||
.encrypt(&device, EventType::Dummy, json!({}))
|
||||
.await
|
||||
.unwrap();
|
||||
let content = if let EncryptedEventContent::OlmV1Curve25519AesSha2(c) = message {
|
||||
c
|
||||
} else {
|
||||
panic!("Invalid encrypted event algorithm");
|
||||
};
|
||||
|
||||
let own_ciphertext = content
|
||||
.ciphertext
|
||||
.get(other.identity_keys.curve25519())
|
||||
.unwrap();
|
||||
let message_type: u8 = own_ciphertext.message_type.try_into().unwrap();
|
||||
|
||||
let message =
|
||||
OlmMessage::from_type_and_ciphertext(message_type.into(), own_ciphertext.body.clone())
|
||||
.unwrap();
|
||||
let message = if let OlmMessage::PreKey(m) = message {
|
||||
m
|
||||
} else {
|
||||
panic!("Wrong Olm message type");
|
||||
};
|
||||
|
||||
let our_device = ReadOnlyDevice::from_account(self).await;
|
||||
let other_session = other
|
||||
.create_inbound_session(
|
||||
our_device
|
||||
.keys()
|
||||
.get(&DeviceKeyId::from_parts(
|
||||
DeviceKeyAlgorithm::Curve25519,
|
||||
our_device.device_id(),
|
||||
))
|
||||
.unwrap(),
|
||||
message,
|
||||
)
|
||||
.await
|
||||
.unwrap();
|
||||
|
||||
(our_session, other_session)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq for Account {
|
||||
|
|
|
@ -99,6 +99,16 @@ pub enum OutgoingRequests {
|
|||
ToDeviceRequest(ToDeviceRequest),
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl OutgoingRequests {
|
||||
pub fn to_device(&self) -> Option<&ToDeviceRequest> {
|
||||
match self {
|
||||
OutgoingRequests::ToDeviceRequest(r) => Some(r),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<KeysQueryRequest> for OutgoingRequests {
|
||||
fn from(request: KeysQueryRequest) -> Self {
|
||||
OutgoingRequests::KeysQuery(request)
|
||||
|
|
Loading…
Reference in New Issue