crypto: Move the olm encryption logic into the Session struct.
parent
3d6872607e
commit
3f1439fe28
|
@ -32,13 +32,10 @@ use super::{device::Device, store::Result as StoreResult, CryptoStore};
|
||||||
|
|
||||||
use matrix_sdk_common::api;
|
use matrix_sdk_common::api;
|
||||||
use matrix_sdk_common::events::{
|
use matrix_sdk_common::events::{
|
||||||
forwarded_room_key::ForwardedRoomKeyEventContent,
|
forwarded_room_key::ForwardedRoomKeyEventContent, room::encrypted::EncryptedEventContent,
|
||||||
room::encrypted::{CiphertextInfo, EncryptedEventContent, OlmV1Curve25519AesSha2Content},
|
room::message::MessageEventContent, room_key::RoomKeyEventContent,
|
||||||
room::message::MessageEventContent,
|
room_key_request::RoomKeyRequestEventContent, Algorithm, AnySyncRoomEvent, AnyToDeviceEvent,
|
||||||
room_key::RoomKeyEventContent,
|
EventJson, EventType, SyncMessageEvent, ToDeviceEvent,
|
||||||
room_key_request::RoomKeyRequestEventContent,
|
|
||||||
Algorithm, AnySyncRoomEvent, AnyToDeviceEvent, EventJson, EventType, SyncMessageEvent,
|
|
||||||
ToDeviceEvent,
|
|
||||||
};
|
};
|
||||||
use matrix_sdk_common::identifiers::{DeviceId, RoomId, UserId};
|
use matrix_sdk_common::identifiers::{DeviceId, RoomId, UserId};
|
||||||
use matrix_sdk_common::uuid::Uuid;
|
use matrix_sdk_common::uuid::Uuid;
|
||||||
|
@ -50,7 +47,7 @@ use api::r0::{
|
||||||
to_device::{send_event_to_device::Request as ToDeviceRequest, DeviceIdOrAllDevices},
|
to_device::{send_event_to_device::Request as ToDeviceRequest, DeviceIdOrAllDevices},
|
||||||
};
|
};
|
||||||
|
|
||||||
use serde_json::{json, Value};
|
use serde_json::Value;
|
||||||
use tracing::{debug, error, info, instrument, trace, warn};
|
use tracing::{debug, error, info, instrument, trace, warn};
|
||||||
|
|
||||||
/// A map from the algorithm and device id to a one-time key.
|
/// A map from the algorithm and device id to a one-time key.
|
||||||
|
@ -807,52 +804,12 @@ impl OlmMachine {
|
||||||
event_type: EventType,
|
event_type: EventType,
|
||||||
content: Value,
|
content: Value,
|
||||||
) -> OlmResult<EncryptedEventContent> {
|
) -> OlmResult<EncryptedEventContent> {
|
||||||
let identity_keys = self.account.identity_keys();
|
let message = session
|
||||||
|
.encrypt(self.account.clone(), recipient_device, event_type, content)
|
||||||
// TODO most of this could go into the session, the session already
|
.await;
|
||||||
// stores the curve key of the device, if we also store the ed25519 key
|
|
||||||
// with the session we'll only need to pass in the account to the
|
|
||||||
// session and all of this can live in the session.
|
|
||||||
|
|
||||||
let recipient_signing_key = recipient_device
|
|
||||||
.get_key(KeyAlgorithm::Ed25519)
|
|
||||||
.ok_or(EventError::MissingSigningKey)?;
|
|
||||||
let recipient_sender_key = recipient_device
|
|
||||||
.get_key(KeyAlgorithm::Curve25519)
|
|
||||||
.ok_or(EventError::MissingSigningKey)?;
|
|
||||||
|
|
||||||
let payload = json!({
|
|
||||||
"sender": self.user_id,
|
|
||||||
"sender_device": self.device_id,
|
|
||||||
"keys": {
|
|
||||||
"ed25519": identity_keys.ed25519(),
|
|
||||||
},
|
|
||||||
"recipient": recipient_device.user_id(),
|
|
||||||
"recipient_keys": {
|
|
||||||
"ed25519": recipient_signing_key,
|
|
||||||
},
|
|
||||||
"type": event_type,
|
|
||||||
"content": content,
|
|
||||||
});
|
|
||||||
|
|
||||||
let plaintext = cjson::to_string(&payload)
|
|
||||||
.unwrap_or_else(|_| panic!(format!("Can't serialize {} to canonical JSON", payload)));
|
|
||||||
|
|
||||||
let ciphertext = session.encrypt(&plaintext).await.to_tuple();
|
|
||||||
|
|
||||||
let message_type: usize = ciphertext.0.into();
|
|
||||||
|
|
||||||
let ciphertext = CiphertextInfo::new(ciphertext.1, (message_type as u32).into());
|
|
||||||
|
|
||||||
let mut content = BTreeMap::new();
|
|
||||||
|
|
||||||
content.insert(recipient_sender_key.to_owned(), ciphertext);
|
|
||||||
|
|
||||||
self.store.save_sessions(&[session]).await?;
|
self.store.save_sessions(&[session]).await?;
|
||||||
|
|
||||||
Ok(EncryptedEventContent::OlmV1Curve25519AesSha2(
|
message
|
||||||
OlmV1Curve25519AesSha2Content::new(content, identity_keys.curve25519().to_owned()),
|
|
||||||
))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Should the client share a group session for the given room.
|
/// Should the client share a group session for the given room.
|
||||||
|
|
|
@ -49,8 +49,8 @@ use super::{InboundGroupSession, OutboundGroupSession, Session};
|
||||||
/// devices.
|
/// devices.
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct Account {
|
pub struct Account {
|
||||||
user_id: Arc<UserId>,
|
pub(crate) user_id: Arc<UserId>,
|
||||||
device_id: Arc<Box<DeviceId>>,
|
pub(crate) device_id: Arc<Box<DeviceId>>,
|
||||||
inner: Arc<Mutex<OlmAccount>>,
|
inner: Arc<Mutex<OlmAccount>>,
|
||||||
identity_keys: Arc<IdentityKeys>,
|
identity_keys: Arc<IdentityKeys>,
|
||||||
shared: Arc<AtomicBool>,
|
shared: Arc<AtomicBool>,
|
||||||
|
|
|
@ -149,7 +149,7 @@ pub(crate) mod test {
|
||||||
|
|
||||||
let plaintext = "Hello world";
|
let plaintext = "Hello world";
|
||||||
|
|
||||||
let message = bob_session.encrypt(plaintext).await;
|
let message = bob_session.encrypt_helper(plaintext).await;
|
||||||
|
|
||||||
let prekey_message = match message.clone() {
|
let prekey_message = match message.clone() {
|
||||||
OlmMessage::PreKey(m) => m,
|
OlmMessage::PreKey(m) => m,
|
||||||
|
|
|
@ -12,22 +12,35 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
use matrix_sdk_common::instant::Instant;
|
use std::collections::BTreeMap;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use matrix_sdk_common::locks::Mutex;
|
|
||||||
|
|
||||||
pub use olm_rs::account::IdentityKeys;
|
|
||||||
use olm_rs::errors::OlmSessionError;
|
use olm_rs::errors::OlmSessionError;
|
||||||
use olm_rs::session::OlmSession;
|
use olm_rs::session::OlmSession;
|
||||||
use olm_rs::PicklingMode;
|
use olm_rs::PicklingMode;
|
||||||
|
|
||||||
|
use serde_json::{json, Value};
|
||||||
|
|
||||||
pub use olm_rs::{
|
pub use olm_rs::{
|
||||||
session::{OlmMessage, PreKeyMessage},
|
session::{OlmMessage, PreKeyMessage},
|
||||||
utility::OlmUtility,
|
utility::OlmUtility,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use super::Account;
|
||||||
|
use crate::error::{EventError, OlmResult};
|
||||||
|
use crate::Device;
|
||||||
|
|
||||||
|
use matrix_sdk_common::{
|
||||||
|
api::r0::keys::KeyAlgorithm,
|
||||||
|
events::{
|
||||||
|
room::encrypted::{CiphertextInfo, EncryptedEventContent, OlmV1Curve25519AesSha2Content},
|
||||||
|
EventType,
|
||||||
|
},
|
||||||
|
instant::Instant,
|
||||||
|
locks::Mutex,
|
||||||
|
};
|
||||||
|
|
||||||
/// Cryptographic session that enables secure communication between two
|
/// Cryptographic session that enables secure communication between two
|
||||||
/// `Account`s
|
/// `Account`s
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
@ -71,12 +84,61 @@ impl Session {
|
||||||
/// # Arguments
|
/// # Arguments
|
||||||
///
|
///
|
||||||
/// * `plaintext` - The plaintext that should be encrypted.
|
/// * `plaintext` - The plaintext that should be encrypted.
|
||||||
pub async fn encrypt(&mut self, plaintext: &str) -> OlmMessage {
|
pub(crate) async fn encrypt_helper(&mut self, plaintext: &str) -> OlmMessage {
|
||||||
let message = self.inner.lock().await.encrypt(plaintext);
|
let message = self.inner.lock().await.encrypt(plaintext);
|
||||||
self.last_use_time = Arc::new(Instant::now());
|
self.last_use_time = Arc::new(Instant::now());
|
||||||
message
|
message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Encrypt the given event content content as an m.room.encrypted event
|
||||||
|
/// content.
|
||||||
|
pub async fn encrypt(
|
||||||
|
&mut self,
|
||||||
|
account: Account,
|
||||||
|
recipient_device: &Device,
|
||||||
|
event_type: EventType,
|
||||||
|
content: Value,
|
||||||
|
) -> OlmResult<EncryptedEventContent> {
|
||||||
|
let recipient_signing_key = recipient_device
|
||||||
|
.get_key(KeyAlgorithm::Ed25519)
|
||||||
|
.ok_or(EventError::MissingSigningKey)?;
|
||||||
|
let recipient_sender_key = recipient_device
|
||||||
|
.get_key(KeyAlgorithm::Curve25519)
|
||||||
|
.ok_or(EventError::MissingSigningKey)?;
|
||||||
|
|
||||||
|
let payload = json!({
|
||||||
|
"sender": account.user_id.to_string(),
|
||||||
|
"sender_device": account.device_id.as_ref(),
|
||||||
|
"keys": {
|
||||||
|
"ed25519": account.identity_keys().ed25519(),
|
||||||
|
},
|
||||||
|
"recipient": recipient_device.user_id(),
|
||||||
|
"recipient_keys": {
|
||||||
|
"ed25519": recipient_signing_key,
|
||||||
|
},
|
||||||
|
"type": event_type,
|
||||||
|
"content": content,
|
||||||
|
});
|
||||||
|
|
||||||
|
let plaintext = cjson::to_string(&payload)
|
||||||
|
.unwrap_or_else(|_| panic!(format!("Can't serialize {} to canonical JSON", payload)));
|
||||||
|
|
||||||
|
let ciphertext = self.encrypt_helper(&plaintext).await.to_tuple();
|
||||||
|
|
||||||
|
let message_type = ciphertext.0;
|
||||||
|
let ciphertext = CiphertextInfo::new(ciphertext.1, (message_type as u32).into());
|
||||||
|
|
||||||
|
let mut content = BTreeMap::new();
|
||||||
|
content.insert(recipient_sender_key.to_owned(), ciphertext);
|
||||||
|
|
||||||
|
Ok(EncryptedEventContent::OlmV1Curve25519AesSha2(
|
||||||
|
OlmV1Curve25519AesSha2Content::new(
|
||||||
|
content,
|
||||||
|
account.identity_keys().curve25519().to_owned(),
|
||||||
|
),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
/// Check if a pre-key Olm message was encrypted for this session.
|
/// Check if a pre-key Olm message was encrypted for this session.
|
||||||
///
|
///
|
||||||
/// Returns true if it matches, false if not and a OlmSessionError if there
|
/// Returns true if it matches, false if not and a OlmSessionError if there
|
||||||
|
|
Loading…
Reference in New Issue