crypto: Add all the common accessors to the qr code verification
parent
728d298810
commit
80a30bcdd6
|
@ -33,7 +33,7 @@ use ruma::{
|
||||||
},
|
},
|
||||||
AnyMessageEventContent, AnyToDeviceEventContent,
|
AnyMessageEventContent, AnyToDeviceEventContent,
|
||||||
},
|
},
|
||||||
DeviceIdBox, DeviceKeyAlgorithm, UserId,
|
DeviceId, DeviceIdBox, DeviceKeyAlgorithm, RoomId, UserId,
|
||||||
};
|
};
|
||||||
use thiserror::Error;
|
use thiserror::Error;
|
||||||
|
|
||||||
|
@ -83,6 +83,7 @@ pub struct QrVerification {
|
||||||
inner: Arc<QrVerificationData>,
|
inner: Arc<QrVerificationData>,
|
||||||
state: Arc<Mutex<InnerState>>,
|
state: Arc<Mutex<InnerState>>,
|
||||||
identities: IdentitiesBeingVerified,
|
identities: IdentitiesBeingVerified,
|
||||||
|
we_started: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Debug for QrVerification {
|
impl std::fmt::Debug for QrVerification {
|
||||||
|
@ -115,6 +116,34 @@ impl QrVerification {
|
||||||
self.identities.other_user_id()
|
self.identities.other_user_id()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the device id of the other side.
|
||||||
|
pub fn other_device_id(&self) -> &DeviceId {
|
||||||
|
self.identities.other_device_id()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Did we initiate the verification request
|
||||||
|
pub fn we_started(&self) -> bool {
|
||||||
|
self.we_started
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the `CancelCode` that cancelled this verification request.
|
||||||
|
pub fn cancel_code(&self) -> Option<CancelCode> {
|
||||||
|
if let InnerState::Cancelled(c) = &*self.state.lock().unwrap() {
|
||||||
|
Some(c.state.cancel_code.to_owned())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Has the verification flow been cancelled by us.
|
||||||
|
pub fn cancelled_by_us(&self) -> Option<bool> {
|
||||||
|
if let InnerState::Cancelled(c) = &*self.state.lock().unwrap() {
|
||||||
|
Some(c.state.cancelled_by_us)
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Has the verification flow completed.
|
/// Has the verification flow completed.
|
||||||
pub fn is_done(&self) -> bool {
|
pub fn is_done(&self) -> bool {
|
||||||
matches!(&*self.state.lock().unwrap(), InnerState::Done(_))
|
matches!(&*self.state.lock().unwrap(), InnerState::Done(_))
|
||||||
|
@ -135,6 +164,14 @@ impl QrVerification {
|
||||||
&self.flow_id
|
&self.flow_id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get the room id if the verification is happening inside a room.
|
||||||
|
pub fn room_id(&self) -> Option<&RoomId> {
|
||||||
|
match self.flow_id() {
|
||||||
|
FlowId::ToDevice(_) => None,
|
||||||
|
FlowId::InRoom(r, _) => Some(r),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Generate a QR code object that is representing this verification flow.
|
/// Generate a QR code object that is representing this verification flow.
|
||||||
///
|
///
|
||||||
/// The `QrCode` can then be rendered as an image or as an unicode string.
|
/// The `QrCode` can then be rendered as an image or as an unicode string.
|
||||||
|
@ -159,6 +196,38 @@ impl QrVerification {
|
||||||
self.cancel_with_code(CancelCode::User).map(|c| self.content_to_request(c))
|
self.cancel_with_code(CancelCode::User).map(|c| self.content_to_request(c))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Cancel the verification.
|
||||||
|
///
|
||||||
|
/// This cancels the verification with given `CancelCode`.
|
||||||
|
///
|
||||||
|
/// **Note**: This method should generally not be used, the [`cancel()`]
|
||||||
|
/// method should be preferred. The SDK will automatically cancel with the
|
||||||
|
/// approprate cancel code, user initiated cancellations should only cancel
|
||||||
|
/// with the `CancelCode::User`
|
||||||
|
///
|
||||||
|
/// Returns None if the `Sas` object is already in a canceled state,
|
||||||
|
/// otherwise it returns a request that needs to be sent out.
|
||||||
|
///
|
||||||
|
/// [`cancel()`]: #method.cancel
|
||||||
|
pub fn cancel_with_code(&self, code: CancelCode) -> Option<OutgoingContent> {
|
||||||
|
let new_state = QrState::<Cancelled>::new(true, code);
|
||||||
|
let content = new_state.as_content(self.flow_id());
|
||||||
|
|
||||||
|
let mut state = self.state.lock().unwrap();
|
||||||
|
|
||||||
|
match &*state {
|
||||||
|
InnerState::Confirmed(_)
|
||||||
|
| InnerState::Created(_)
|
||||||
|
| InnerState::Scanned(_)
|
||||||
|
| InnerState::Reciprocated(_)
|
||||||
|
| InnerState::Done(_) => {
|
||||||
|
*state = InnerState::Cancelled(new_state);
|
||||||
|
Some(content)
|
||||||
|
}
|
||||||
|
InnerState::Cancelled(_) => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Notify the other side that we have successfully scanned the QR code and
|
/// Notify the other side that we have successfully scanned the QR code and
|
||||||
/// that the QR verification flow can start.
|
/// that the QR verification flow can start.
|
||||||
///
|
///
|
||||||
|
@ -209,25 +278,6 @@ impl QrVerification {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cancel_with_code(&self, code: CancelCode) -> Option<OutgoingContent> {
|
|
||||||
let new_state = QrState::<Cancelled>::new(true, code);
|
|
||||||
let content = new_state.as_content(self.flow_id());
|
|
||||||
|
|
||||||
let mut state = self.state.lock().unwrap();
|
|
||||||
|
|
||||||
match &*state {
|
|
||||||
InnerState::Confirmed(_)
|
|
||||||
| InnerState::Created(_)
|
|
||||||
| InnerState::Scanned(_)
|
|
||||||
| InnerState::Reciprocated(_)
|
|
||||||
| InnerState::Done(_) => {
|
|
||||||
*state = InnerState::Cancelled(new_state);
|
|
||||||
Some(content)
|
|
||||||
}
|
|
||||||
InnerState::Cancelled(_) => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn mark_as_done(
|
async fn mark_as_done(
|
||||||
&self,
|
&self,
|
||||||
new_state: QrState<Done>,
|
new_state: QrState<Done>,
|
||||||
|
@ -351,6 +401,7 @@ impl QrVerification {
|
||||||
own_master_key: String,
|
own_master_key: String,
|
||||||
other_device_key: String,
|
other_device_key: String,
|
||||||
identities: IdentitiesBeingVerified,
|
identities: IdentitiesBeingVerified,
|
||||||
|
we_started: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let secret = Self::generate_secret();
|
let secret = Self::generate_secret();
|
||||||
|
|
||||||
|
@ -362,7 +413,7 @@ impl QrVerification {
|
||||||
)
|
)
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
Self::new_helper(store, flow_id, inner, identities)
|
Self::new_helper(store, flow_id, inner, identities, we_started)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new_self_no_master(
|
pub(crate) fn new_self_no_master(
|
||||||
|
@ -371,6 +422,7 @@ impl QrVerification {
|
||||||
flow_id: FlowId,
|
flow_id: FlowId,
|
||||||
own_master_key: String,
|
own_master_key: String,
|
||||||
identities: IdentitiesBeingVerified,
|
identities: IdentitiesBeingVerified,
|
||||||
|
we_started: bool,
|
||||||
) -> QrVerification {
|
) -> QrVerification {
|
||||||
let secret = Self::generate_secret();
|
let secret = Self::generate_secret();
|
||||||
|
|
||||||
|
@ -382,7 +434,7 @@ impl QrVerification {
|
||||||
)
|
)
|
||||||
.into();
|
.into();
|
||||||
|
|
||||||
Self::new_helper(store, flow_id, inner, identities)
|
Self::new_helper(store, flow_id, inner, identities, we_started)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new_cross(
|
pub(crate) fn new_cross(
|
||||||
|
@ -391,6 +443,7 @@ impl QrVerification {
|
||||||
own_master_key: String,
|
own_master_key: String,
|
||||||
other_master_key: String,
|
other_master_key: String,
|
||||||
identities: IdentitiesBeingVerified,
|
identities: IdentitiesBeingVerified,
|
||||||
|
we_started: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let secret = Self::generate_secret();
|
let secret = Self::generate_secret();
|
||||||
|
|
||||||
|
@ -403,9 +456,10 @@ impl QrVerification {
|
||||||
let inner: QrVerificationData =
|
let inner: QrVerificationData =
|
||||||
VerificationData::new(event_id, own_master_key, other_master_key, secret).into();
|
VerificationData::new(event_id, own_master_key, other_master_key, secret).into();
|
||||||
|
|
||||||
Self::new_helper(store, flow_id, inner, identities)
|
Self::new_helper(store, flow_id, inner, identities, we_started)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
pub(crate) async fn from_scan(
|
pub(crate) async fn from_scan(
|
||||||
store: Arc<dyn CryptoStore>,
|
store: Arc<dyn CryptoStore>,
|
||||||
own_account: ReadOnlyAccount,
|
own_account: ReadOnlyAccount,
|
||||||
|
@ -414,6 +468,7 @@ impl QrVerification {
|
||||||
other_device_id: DeviceIdBox,
|
other_device_id: DeviceIdBox,
|
||||||
flow_id: FlowId,
|
flow_id: FlowId,
|
||||||
qr_code: QrVerificationData,
|
qr_code: QrVerificationData,
|
||||||
|
we_started: bool,
|
||||||
) -> Result<Self, ScanError> {
|
) -> Result<Self, ScanError> {
|
||||||
if flow_id.as_str() != qr_code.flow_id() {
|
if flow_id.as_str() != qr_code.flow_id() {
|
||||||
return Err(ScanError::FlowIdMismatch {
|
return Err(ScanError::FlowIdMismatch {
|
||||||
|
@ -510,6 +565,7 @@ impl QrVerification {
|
||||||
}))
|
}))
|
||||||
.into(),
|
.into(),
|
||||||
identities,
|
identities,
|
||||||
|
we_started,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -518,6 +574,7 @@ impl QrVerification {
|
||||||
flow_id: FlowId,
|
flow_id: FlowId,
|
||||||
inner: QrVerificationData,
|
inner: QrVerificationData,
|
||||||
identities: IdentitiesBeingVerified,
|
identities: IdentitiesBeingVerified,
|
||||||
|
we_started: bool,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let secret = inner.secret().to_owned();
|
let secret = inner.secret().to_owned();
|
||||||
|
|
||||||
|
@ -527,6 +584,7 @@ impl QrVerification {
|
||||||
inner: inner.into(),
|
inner: inner.into(),
|
||||||
state: Mutex::new(InnerState::Created(QrState { state: Created { secret } })).into(),
|
state: Mutex::new(InnerState::Created(QrState { state: Created { secret } })).into(),
|
||||||
identities,
|
identities,
|
||||||
|
we_started,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -747,6 +805,7 @@ mod test {
|
||||||
flow_id.clone(),
|
flow_id.clone(),
|
||||||
master_key.clone(),
|
master_key.clone(),
|
||||||
identities.clone(),
|
identities.clone(),
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(verification.inner.first_key(), &device_key);
|
assert_eq!(verification.inner.first_key(), &device_key);
|
||||||
|
@ -758,6 +817,7 @@ mod test {
|
||||||
master_key.clone(),
|
master_key.clone(),
|
||||||
device_key.clone(),
|
device_key.clone(),
|
||||||
identities.clone(),
|
identities.clone(),
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(verification.inner.first_key(), &master_key);
|
assert_eq!(verification.inner.first_key(), &master_key);
|
||||||
|
@ -775,6 +835,7 @@ mod test {
|
||||||
master_key.clone(),
|
master_key.clone(),
|
||||||
bob_master_key.clone(),
|
bob_master_key.clone(),
|
||||||
identities,
|
identities,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
assert_eq!(verification.inner.first_key(), &master_key);
|
assert_eq!(verification.inner.first_key(), &master_key);
|
||||||
|
@ -818,6 +879,7 @@ mod test {
|
||||||
flow_id.clone(),
|
flow_id.clone(),
|
||||||
master_key.clone(),
|
master_key.clone(),
|
||||||
identities,
|
identities,
|
||||||
|
false,
|
||||||
);
|
);
|
||||||
|
|
||||||
let bob_store = memory_store();
|
let bob_store = memory_store();
|
||||||
|
@ -838,6 +900,7 @@ mod test {
|
||||||
alice_account.device_id().to_owned(),
|
alice_account.device_id().to_owned(),
|
||||||
flow_id,
|
flow_id,
|
||||||
qr_code,
|
qr_code,
|
||||||
|
false,
|
||||||
)
|
)
|
||||||
.await
|
.await
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
|
@ -277,7 +277,7 @@ impl VerificationRequest {
|
||||||
/// Generate a QR code that can be used by another client to start a QR code
|
/// Generate a QR code that can be used by another client to start a QR code
|
||||||
/// based verification.
|
/// based verification.
|
||||||
pub async fn generate_qr_code(&self) -> Result<Option<QrVerification>, CryptoStoreError> {
|
pub async fn generate_qr_code(&self) -> Result<Option<QrVerification>, CryptoStoreError> {
|
||||||
self.inner.lock().unwrap().generate_qr_code().await
|
self.inner.lock().unwrap().generate_qr_code(self.we_started).await
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Start a QR code verification by providing a scanned QR code for this
|
/// Start a QR code verification by providing a scanned QR code for this
|
||||||
|
@ -303,6 +303,7 @@ impl VerificationRequest {
|
||||||
r.state.other_device_id.clone(),
|
r.state.other_device_id.clone(),
|
||||||
r.flow_id.as_ref().to_owned(),
|
r.flow_id.as_ref().to_owned(),
|
||||||
data,
|
data,
|
||||||
|
self.we_started,
|
||||||
)
|
)
|
||||||
.await?,
|
.await?,
|
||||||
))
|
))
|
||||||
|
@ -550,11 +551,11 @@ impl InnerRequest {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn generate_qr_code(&self) -> Result<Option<QrVerification>, CryptoStoreError> {
|
async fn generate_qr_code(&self, we_started: bool) -> Result<Option<QrVerification>, CryptoStoreError> {
|
||||||
match self {
|
match self {
|
||||||
InnerRequest::Created(_) => Ok(None),
|
InnerRequest::Created(_) => Ok(None),
|
||||||
InnerRequest::Requested(_) => Ok(None),
|
InnerRequest::Requested(_) => Ok(None),
|
||||||
InnerRequest::Ready(s) => s.generate_qr_code().await,
|
InnerRequest::Ready(s) => s.generate_qr_code(we_started).await,
|
||||||
InnerRequest::Passive(_) => Ok(None),
|
InnerRequest::Passive(_) => Ok(None),
|
||||||
InnerRequest::Done(_) => Ok(None),
|
InnerRequest::Done(_) => Ok(None),
|
||||||
InnerRequest::Cancelled(_) => Ok(None),
|
InnerRequest::Cancelled(_) => Ok(None),
|
||||||
|
@ -783,7 +784,10 @@ impl RequestState<Ready> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn generate_qr_code(&self) -> Result<Option<QrVerification>, CryptoStoreError> {
|
async fn generate_qr_code(
|
||||||
|
&self,
|
||||||
|
we_started: bool,
|
||||||
|
) -> Result<Option<QrVerification>, CryptoStoreError> {
|
||||||
// TODO return an error explaining why we can't generate a QR code?
|
// TODO return an error explaining why we can't generate a QR code?
|
||||||
|
|
||||||
// If we didn't state that we support showing QR codes or if the other
|
// If we didn't state that we support showing QR codes or if the other
|
||||||
|
@ -829,6 +833,7 @@ impl RequestState<Ready> {
|
||||||
.unwrap()
|
.unwrap()
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
identites,
|
identites,
|
||||||
|
we_started,
|
||||||
))
|
))
|
||||||
} else {
|
} else {
|
||||||
Some(QrVerification::new_self_no_master(
|
Some(QrVerification::new_self_no_master(
|
||||||
|
@ -837,6 +842,7 @@ impl RequestState<Ready> {
|
||||||
self.flow_id.as_ref().to_owned(),
|
self.flow_id.as_ref().to_owned(),
|
||||||
i.master_key().get_first_key().unwrap().to_owned(),
|
i.master_key().get_first_key().unwrap().to_owned(),
|
||||||
identites,
|
identites,
|
||||||
|
we_started,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -852,6 +858,7 @@ impl RequestState<Ready> {
|
||||||
.to_owned(),
|
.to_owned(),
|
||||||
i.master_key().get_first_key().unwrap().to_owned(),
|
i.master_key().get_first_key().unwrap().to_owned(),
|
||||||
identites,
|
identites,
|
||||||
|
we_started,
|
||||||
)),
|
)),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
Loading…
Reference in New Issue