crypto: Add methods to manually verify devices and users
This commit is contained in:
parent
ee838087ca
commit
d4fe6f5133
7 changed files with 74 additions and 19 deletions
|
@ -135,29 +135,42 @@ pub enum SessionUnpicklingError {
|
|||
SessionTimestampError,
|
||||
}
|
||||
|
||||
/// Error type describin different errors that happen when we check or create
|
||||
/// signatures for a Matrix JSON object.
|
||||
#[derive(Error, Debug)]
|
||||
pub enum SignatureError {
|
||||
#[error("the signature used a unsupported algorithm")]
|
||||
/// The signature was made using an unsupported algorithm.
|
||||
#[error("the signature used an unsupported algorithm")]
|
||||
UnsupportedAlgorithm,
|
||||
|
||||
#[error("the key id of the signing key is invalid")]
|
||||
/// The ID of the signing key isn't a valid key ID.
|
||||
#[error("the ID of the signing key is invalid")]
|
||||
InvalidKeyId(#[from] IdentifierError),
|
||||
|
||||
/// The signing key that should create or check a signature is missing.
|
||||
#[error("the signing key is missing from the object that signed the message")]
|
||||
MissingSigningKey,
|
||||
|
||||
#[error("the user id of the signing differs from the subkey user id")]
|
||||
/// The user id of signing key differs from the user id that provided the
|
||||
/// signature.
|
||||
#[error("the user id of the signing key differs user id that provided the signature")]
|
||||
UserIdMissmatch,
|
||||
|
||||
/// The provided JSON value that was signed and the signature should be
|
||||
/// checked isn't a valid JSON object.
|
||||
#[error("the provided JSON value isn't an object")]
|
||||
NotAnObject,
|
||||
|
||||
/// The provided JSON value that was signed and the signature should be
|
||||
/// checked isn't a valid JSON object.
|
||||
#[error("the provided JSON object doesn't contain a signatures field")]
|
||||
NoSignatureFound,
|
||||
|
||||
/// The signature couldn't be verified.
|
||||
#[error("the signature didn't match the provided key")]
|
||||
VerificationError,
|
||||
|
||||
/// The signed object couldn't be deserialized.
|
||||
#[error(transparent)]
|
||||
JsonError(#[from] SerdeError),
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ use std::{
|
|||
use atomic::Atomic;
|
||||
use matrix_sdk_common::locks::Mutex;
|
||||
use ruma::{
|
||||
api::client::r0::keys::upload_signatures::Request as SignatureUploadRequest,
|
||||
encryption::{DeviceKeys, SignedKey},
|
||||
events::{
|
||||
forwarded_room_key::ForwardedRoomKeyToDeviceEventContent,
|
||||
|
@ -103,7 +104,6 @@ where
|
|||
/// A device represents a E2EE capable client of an user.
|
||||
pub struct Device {
|
||||
pub(crate) inner: ReadOnlyDevice,
|
||||
pub(crate) private_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
|
||||
pub(crate) verification_machine: VerificationMachine,
|
||||
pub(crate) own_identity: Option<ReadOnlyOwnUserIdentity>,
|
||||
pub(crate) device_owner_identity: Option<ReadOnlyUserIdentities>,
|
||||
|
@ -204,6 +204,33 @@ impl Device {
|
|||
self.inner.is_cross_signing_trusted(&self.own_identity, &self.device_owner_identity)
|
||||
}
|
||||
|
||||
/// Manually verify this device.
|
||||
///
|
||||
/// This method will attempt to sign the device using our private cross
|
||||
/// signing key.
|
||||
///
|
||||
/// This method will always fail if the device belongs to someone else, we
|
||||
/// can only sign our own devices.
|
||||
///
|
||||
/// It can also fail if we don't have the private part of our self-signing
|
||||
/// key.
|
||||
///
|
||||
/// Returns a request that needs to be sent out for the device to be marked
|
||||
/// as verified.
|
||||
pub async fn verify(&self) -> Result<SignatureUploadRequest, SignatureError> {
|
||||
if self.user_id() == self.verification_machine.own_user_id() {
|
||||
Ok(self
|
||||
.verification_machine
|
||||
.private_identity
|
||||
.lock()
|
||||
.await
|
||||
.sign_device(&self.inner)
|
||||
.await?)
|
||||
} else {
|
||||
Err(SignatureError::UserIdMissmatch)
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the local trust state of the device to the given state.
|
||||
///
|
||||
/// This won't affect any cross signing trust state, this only sets a flag
|
||||
|
@ -280,7 +307,6 @@ impl UserDevices {
|
|||
pub fn get(&self, device_id: &DeviceId) -> Option<Device> {
|
||||
self.inner.get(device_id).map(|d| Device {
|
||||
inner: d.clone(),
|
||||
private_identity: self.private_identity.clone(),
|
||||
verification_machine: self.verification_machine.clone(),
|
||||
own_identity: self.own_identity.clone(),
|
||||
device_owner_identity: self.device_owner_identity.clone(),
|
||||
|
@ -302,7 +328,6 @@ impl UserDevices {
|
|||
pub fn devices(&self) -> impl Iterator<Item = Device> + '_ {
|
||||
self.inner.values().map(move |d| Device {
|
||||
inner: d.clone(),
|
||||
private_identity: self.private_identity.clone(),
|
||||
verification_machine: self.verification_machine.clone(),
|
||||
own_identity: self.own_identity.clone(),
|
||||
device_owner_identity: self.device_owner_identity.clone(),
|
||||
|
|
|
@ -23,6 +23,7 @@ use std::{
|
|||
};
|
||||
|
||||
use ruma::{
|
||||
api::client::r0::keys::upload_signatures::Request as SignatureUploadRequest,
|
||||
encryption::{CrossSigningKey, DeviceKeys, KeyUsage},
|
||||
events::{
|
||||
key::verification::VerificationMethod, room::message::KeyVerificationRequestEventContent,
|
||||
|
@ -33,8 +34,6 @@ use serde::{Deserialize, Serialize};
|
|||
use serde_json::to_value;
|
||||
|
||||
use super::{atomic_bool_deserializer, atomic_bool_serializer};
|
||||
#[cfg(test)]
|
||||
use crate::olm::PrivateCrossSigningIdentity;
|
||||
use crate::{
|
||||
error::SignatureError, olm::Utility, verification::VerificationMachine, CryptoStoreError,
|
||||
OutgoingVerificationRequest, ReadOnlyDevice, VerificationRequest,
|
||||
|
@ -190,6 +189,30 @@ impl UserIdentity {
|
|||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
/// Manually verify this user.
|
||||
///
|
||||
/// This method will attempt to sign the user identity using our private
|
||||
/// cross signing key.
|
||||
///
|
||||
/// This method fails if we don't have the private part of our user-signing
|
||||
/// key.
|
||||
///
|
||||
/// Returns a request that needs to be sent out for the user to be marked
|
||||
/// as verified.
|
||||
pub async fn verify(&self) -> Result<SignatureUploadRequest, SignatureError> {
|
||||
if self.user_id() == self.verification_machine.own_user_id() {
|
||||
Ok(self
|
||||
.verification_machine
|
||||
.private_identity
|
||||
.lock()
|
||||
.await
|
||||
.sign_user(&self.inner)
|
||||
.await?)
|
||||
} else {
|
||||
Err(SignatureError::UserIdMissmatch)
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a `VerificationRequest` object after the verification request
|
||||
/// content has been sent out.
|
||||
pub async fn request_verification(
|
||||
|
@ -667,7 +690,7 @@ impl ReadOnlyUserIdentity {
|
|||
}
|
||||
|
||||
#[cfg(test)]
|
||||
pub async fn from_private(identity: &PrivateCrossSigningIdentity) -> Self {
|
||||
pub async fn from_private(identity: &crate::olm::PrivateCrossSigningIdentity) -> Self {
|
||||
let master_key = identity.master_key.lock().await.as_ref().unwrap().public_key.clone();
|
||||
let self_signing_key =
|
||||
identity.self_signing_key.lock().await.as_ref().unwrap().public_key.clone();
|
||||
|
@ -699,7 +722,7 @@ impl ReadOnlyUserIdentity {
|
|||
/// * `self_signing_key` - The new self signing key of user identity.
|
||||
///
|
||||
/// Returns a `SignatureError` if we failed to update the identity.
|
||||
pub fn update(
|
||||
pub(crate) fn update(
|
||||
&mut self,
|
||||
master_key: MasterPubkey,
|
||||
self_signing_key: SelfSigningPubkey,
|
||||
|
@ -974,7 +997,6 @@ pub(crate) mod test {
|
|||
let first = Device {
|
||||
inner: first,
|
||||
verification_machine: verification_machine.clone(),
|
||||
private_identity: private_identity.clone(),
|
||||
own_identity: Some(identity.clone()),
|
||||
device_owner_identity: Some(ReadOnlyUserIdentities::Own(identity.clone())),
|
||||
};
|
||||
|
@ -982,7 +1004,6 @@ pub(crate) mod test {
|
|||
let second = Device {
|
||||
inner: second,
|
||||
verification_machine,
|
||||
private_identity,
|
||||
own_identity: Some(identity.clone()),
|
||||
device_owner_identity: Some(ReadOnlyUserIdentities::Own(identity.clone())),
|
||||
};
|
||||
|
@ -1019,7 +1040,6 @@ pub(crate) mod test {
|
|||
let mut device = Device {
|
||||
inner: device,
|
||||
verification_machine: verification_machine.clone(),
|
||||
private_identity: id.clone(),
|
||||
own_identity: Some(public_identity.clone()),
|
||||
device_owner_identity: Some(public_identity.clone().into()),
|
||||
};
|
||||
|
|
|
@ -39,7 +39,7 @@ pub mod store;
|
|||
mod utilities;
|
||||
mod verification;
|
||||
|
||||
pub use error::{MegolmError, OlmError};
|
||||
pub use error::{MegolmError, OlmError, SignatureError};
|
||||
pub use file_encryption::{
|
||||
decrypt_key_export, encrypt_key_export, AttachmentDecryptor, AttachmentEncryptor,
|
||||
DecryptorError, EncryptionInfo, KeyExportError,
|
||||
|
|
|
@ -330,7 +330,6 @@ impl Store {
|
|||
|
||||
Ok(self.inner.get_device(user_id, device_id).await?.map(|d| Device {
|
||||
inner: d,
|
||||
private_identity: self.identity.clone(),
|
||||
verification_machine: self.verification_machine.clone(),
|
||||
own_identity,
|
||||
device_owner_identity,
|
||||
|
|
|
@ -46,7 +46,7 @@ use crate::{
|
|||
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct VerificationMachine {
|
||||
private_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
|
||||
pub(crate) private_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
|
||||
pub(crate) store: VerificationStore,
|
||||
verifications: VerificationCache,
|
||||
requests: Arc<DashMap<UserId, DashMap<String, VerificationRequest>>>,
|
||||
|
|
|
@ -143,7 +143,6 @@ impl Sas {
|
|||
self.inner.lock().unwrap().set_creation_time(time)
|
||||
}
|
||||
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
fn start_helper(
|
||||
inner_sas: InnerSas,
|
||||
private_identity: PrivateCrossSigningIdentity,
|
||||
|
@ -159,7 +158,7 @@ impl Sas {
|
|||
|
||||
let identities = IdentitiesBeingVerified {
|
||||
private_identity,
|
||||
store: store.clone(),
|
||||
store,
|
||||
device_being_verified: other_device,
|
||||
identity_being_verified: other_identity,
|
||||
};
|
||||
|
@ -184,7 +183,6 @@ impl Sas {
|
|||
///
|
||||
/// Returns the new `Sas` object and a `StartEventContent` that needs to be
|
||||
/// sent out through the server to the other device.
|
||||
#[allow(clippy::too_many_arguments)]
|
||||
pub(crate) fn start(
|
||||
private_identity: PrivateCrossSigningIdentity,
|
||||
other_device: ReadOnlyDevice,
|
||||
|
|
Loading…
Reference in a new issue