Skip to content

Commit

Permalink
Merge pull request #334 from whisperfish/service-address-no-more
Browse files Browse the repository at this point in the history
Replace ServiceAddress by libsignal_protocol::ServiceId
  • Loading branch information
rubdos authored Nov 5, 2024
2 parents b0fcd8b + b0f6067 commit f4313db
Show file tree
Hide file tree
Showing 18 changed files with 222 additions and 440 deletions.
46 changes: 23 additions & 23 deletions src/account_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ use aes::cipher::{KeyIvInit, StreamCipher as _};
use hmac::digest::Output;
use hmac::{Hmac, Mac};
use libsignal_protocol::{
kem, GenericSignedPreKey, IdentityKey, IdentityKeyPair, IdentityKeyStore,
KeyPair, KyberPreKeyRecord, PrivateKey, ProtocolStore, PublicKey,
SenderKeyStore, SignedPreKeyRecord, Timestamp,
kem, Aci, GenericSignedPreKey, IdentityKey, IdentityKeyPair,
IdentityKeyStore, KeyPair, KyberPreKeyRecord, PrivateKey, ProtocolStore,
PublicKey, SenderKeyStore, ServiceIdKind, SignedPreKeyRecord, Timestamp,
};
use prost::Message;
use serde::{Deserialize, Serialize};
Expand All @@ -30,15 +30,15 @@ use crate::proto::sync_message::PniChangeNumber;
use crate::proto::{DeviceName, SyncMessage};
use crate::provisioning::generate_registration_id;
use crate::push_service::{
AvatarWrite, DeviceActivationRequest, DeviceInfo, HttpAuthOverride,
RecaptchaAttributes, RegistrationMethod, ReqwestExt, ServiceIdType,
VerifyAccountResponse, DEFAULT_DEVICE_ID,
AvatarWrite, CaptchaAttributes, DeviceActivationRequest, DeviceInfo,
HttpAuthOverride, RegistrationMethod, ReqwestExt, VerifyAccountResponse,
DEFAULT_DEVICE_ID,
};
use crate::sender::OutgoingPushMessage;
use crate::service_address::ServiceIdExt;
use crate::session_store::SessionStoreExt;
use crate::timestamp::TimestampExt as _;
use crate::utils::{random_length_padding, BASE64_RELAXED};
use crate::ServiceAddress;
use crate::{
configuration::{Endpoint, ServiceCredentials},
pre_keys::PreKeyState,
Expand Down Expand Up @@ -95,13 +95,13 @@ impl AccountManager {
>(
&mut self,
protocol_store: &mut P,
service_id_type: ServiceIdType,
service_id_kind: ServiceIdKind,
csprng: &mut R,
use_last_resort_key: bool,
) -> Result<(), ServiceError> {
let prekey_status = match self
.service
.get_pre_key_status(service_id_type)
.get_pre_key_status(service_id_kind)
.instrument(tracing::span!(
tracing::Level::DEBUG,
"Fetching pre key status"
Expand Down Expand Up @@ -203,7 +203,7 @@ impl AccountManager {
};

self.service
.register_pre_keys(service_id_type, pre_key_state)
.register_pre_keys(service_id_kind, pre_key_state)
.instrument(tracing::span!(
tracing::Level::DEBUG,
"Uploading pre keys"
Expand Down Expand Up @@ -495,7 +495,7 @@ impl AccountManager {

pub async fn retrieve_profile(
&mut self,
address: ServiceAddress,
address: Aci,
) -> Result<Profile, ProfileManagerError> {
let profile_key =
self.profile_key.expect("set profile key in AccountManager");
Expand Down Expand Up @@ -624,10 +624,10 @@ impl AccountManager {
Endpoint::service("/v1/challenge"),
HttpAuthOverride::NoOverride,
)?
.json(&RecaptchaAttributes {
r#type: String::from("recaptcha"),
token: String::from(token),
captcha: String::from(captcha),
.json(&CaptchaAttributes {
challenge_type: "captcha",
token,
captcha,
})
.send()
.await?
Expand All @@ -642,19 +642,19 @@ impl AccountManager {
/// Should be called as the primary device to migrate from pre-PNI to PNI.
///
/// This is the equivalent of Android's PnpInitializeDevicesJob or iOS' PniHelloWorldManager.
#[tracing::instrument(skip(self, aci_protocol_store, pni_protocol_store, sender, local_aci), fields(local_aci = %local_aci))]
#[tracing::instrument(skip(self, aci_protocol_store, pni_protocol_store, sender, local_aci), fields(local_aci = %local_aci.service_id_string()))]
pub async fn pnp_initialize_devices<
// XXX So many constraints here, all imposed by the MessageSender
R: rand::Rng + rand::CryptoRng,
Aci: PreKeysStore + SessionStoreExt,
Pni: PreKeysStore,
AciStore: PreKeysStore + SessionStoreExt,
PniStore: PreKeysStore,
AciOrPni: ProtocolStore + SenderKeyStore + SessionStoreExt + Sync + Clone,
>(
&mut self,
aci_protocol_store: &mut Aci,
pni_protocol_store: &mut Pni,
aci_protocol_store: &mut AciStore,
pni_protocol_store: &mut PniStore,
mut sender: MessageSender<AciOrPni>,
local_aci: ServiceAddress,
local_aci: Aci,
e164: PhoneNumber,
) -> Result<(), MessageSenderError> {
let mut csprng = rand::thread_rng();
Expand All @@ -665,7 +665,7 @@ impl AccountManager {

// For every linked device, we generate a new set of pre-keys, and send them to the device.
let local_device_ids = aci_protocol_store
.get_sub_device_sessions(&local_aci)
.get_sub_device_sessions(&local_aci.into())
.await?;

let mut device_messages =
Expand Down Expand Up @@ -809,7 +809,7 @@ impl AccountManager {
let content: ContentBody = msg.into();
let msg = sender
.create_encrypted_message(
&local_aci,
&local_aci.into(),
None,
local_device_id.into(),
&content.into_proto().encode_to_vec(),
Expand Down
19 changes: 11 additions & 8 deletions src/cipher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ use libsignal_protocol::{
CiphertextMessageType, DeviceId, IdentityKeyStore, KyberPreKeyStore,
PreKeySignalMessage, PreKeyStore, ProtocolAddress, ProtocolStore,
PublicKey, SealedSenderDecryptionResult, SenderCertificate,
SenderKeyDistributionMessage, SenderKeyStore, SessionStore, SignalMessage,
SignalProtocolError, SignedPreKeyStore, Timestamp,
SenderKeyDistributionMessage, SenderKeyStore, ServiceId, SessionStore,
SignalMessage, SignalProtocolError, SignedPreKeyStore, Timestamp,
};
use prost::Message;
use uuid::Uuid;
Expand All @@ -22,7 +22,7 @@ use crate::{
sender::OutgoingPushMessage,
session_store::SessionStoreExt,
utils::BASE64_RELAXED,
ServiceAddress,
ServiceIdExt,
};
/// Decrypts incoming messages and encrypts outgoing messages.
///
Expand Down Expand Up @@ -271,13 +271,16 @@ where
)
.await?;

let sender = ServiceAddress::try_from(sender_uuid.as_str())
.map_err(|e| {
tracing::error!("{:?}", e);
let Some(sender) =
ServiceId::parse_from_service_id_string(&sender_uuid)
else {
return Err(
SignalProtocolError::InvalidSealedSenderMessage(
"invalid sender UUID".to_string(),
)
})?;
.into(),
);
};

let needs_receipt = if envelope.source_service_id.is_some() {
tracing::warn!(?envelope, "Received an unidentified delivery over an identified channel. Marking needs_receipt=false");
Expand Down Expand Up @@ -446,7 +449,7 @@ fn strip_padding(contents: &mut Vec<u8>) -> Result<(), ServiceError> {
/// Equivalent of `SignalServiceCipher::getPreferredProtocolAddress`
pub async fn get_preferred_protocol_address<S: SessionStore>(
session_store: &S,
address: &ServiceAddress,
address: &ServiceId,
device_id: DeviceId,
) -> Result<ProtocolAddress, libsignal_protocol::error::SignalProtocolError> {
let address = address.to_protocol_address(device_id);
Expand Down
9 changes: 5 additions & 4 deletions src/content.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use libsignal_protocol::ProtocolAddress;
use libsignal_protocol::{ProtocolAddress, ServiceId};
use std::fmt;
use uuid::Uuid;

Expand All @@ -12,15 +12,16 @@ pub use crate::{
SyncMessage, TypingMessage,
},
push_service::ServiceError,
ServiceIdExt,
};

mod data_message;
mod story_message;

#[derive(Clone, Debug)]
pub struct Metadata {
pub sender: crate::ServiceAddress,
pub destination: crate::ServiceAddress,
pub sender: ServiceId,
pub destination: ServiceId,
pub sender_device: u32,
pub timestamp: u64,
pub needs_receipt: bool,
Expand All @@ -37,7 +38,7 @@ impl fmt::Display for Metadata {
write!(
f,
"Metadata {{ sender: {}, guid: {} }}",
self.sender.to_service_id(),
self.sender.service_id_string(),
// XXX: should this still be optional?
self.server_guid
.map(|u| u.to_string())
Expand Down
93 changes: 12 additions & 81 deletions src/envelope.rs
Original file line number Diff line number Diff line change
@@ -1,30 +1,12 @@
use std::convert::{TryFrom, TryInto};

use aes::cipher::block_padding::Pkcs7;
use aes::cipher::{BlockDecryptMut, KeyIvInit};
use libsignal_protocol::ServiceId;
use prost::Message;

use crate::{
configuration::SignalingKey, push_service::ServiceError,
utils::serde_optional_base64, ParseServiceAddressError, ServiceAddress,
};
use crate::{configuration::SignalingKey, push_service::ServiceError};

pub use crate::proto::Envelope;

impl TryFrom<EnvelopeEntity> for Envelope {
type Error = ParseServiceAddressError;

fn try_from(entity: EnvelopeEntity) -> Result<Self, Self::Error> {
match entity.source_uuid.as_deref() {
Some(uuid) => {
let address = uuid.try_into()?;
Ok(Envelope::new_with_source(entity, address))
},
None => Ok(Envelope::new_from_entity(entity)),
}
}
}

impl Envelope {
#[tracing::instrument(skip(input, signaling_key), fields(signaling_key_present = signaling_key.is_some(), input_size = input.len()))]
pub fn decrypt(
Expand Down Expand Up @@ -85,30 +67,6 @@ impl Envelope {
}
}

fn new_from_entity(entity: EnvelopeEntity) -> Self {
Envelope {
r#type: Some(entity.r#type),
timestamp: Some(entity.timestamp),
server_timestamp: Some(entity.server_timestamp),
server_guid: Some(entity.guid),
content: entity.content,
..Default::default()
}
}

fn new_with_source(entity: EnvelopeEntity, source: ServiceAddress) -> Self {
Envelope {
r#type: Some(entity.r#type),
source_device: Some(entity.source_device),
timestamp: Some(entity.timestamp),
server_timestamp: Some(entity.server_timestamp),
server_guid: Some(entity.guid),
source_service_id: Some(source.uuid.to_string()),
content: entity.content,
..Default::default()
}
}

pub fn is_unidentified_sender(&self) -> bool {
self.r#type() == crate::proto::envelope::Type::UnidentifiedSender
}
Expand All @@ -134,54 +92,27 @@ impl Envelope {
self.story.unwrap_or(false)
}

pub fn source_address(&self) -> ServiceAddress {
pub fn source_address(&self) -> ServiceId {
match self.source_service_id.as_deref() {
Some(service_id) => ServiceAddress::try_from(service_id)
.expect("invalid source ProtocolAddress UUID or prefix"),
Some(service_id) => {
ServiceId::parse_from_service_id_string(service_id)
.expect("invalid source ProtocolAddress UUID or prefix")
},
None => panic!("source_service_id is set"),
}
}

pub fn destination_address(&self) -> ServiceAddress {
pub fn destination_address(&self) -> ServiceId {
match self.destination_service_id.as_deref() {
Some(service_id) => ServiceAddress::try_from(service_id)
.expect("invalid destination ProtocolAddress UUID or prefix"),
Some(service_id) => ServiceId::parse_from_service_id_string(
service_id,
)
.expect("invalid destination ProtocolAddress UUID or prefix"),
None => panic!("destination_address is set"),
}
}
}

#[derive(serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct EnvelopeEntity {
pub r#type: i32,
pub timestamp: u64,
pub source: Option<String>,
pub source_uuid: Option<String>,
pub source_device: u32,
#[serde(default)]
pub destination_uuid: Option<String>,
#[serde(default, with = "serde_optional_base64")]
pub content: Option<Vec<u8>>,
pub server_timestamp: u64,
pub guid: String,
#[serde(default = "default_true")]
pub urgent: bool,
#[serde(default)]
pub story: bool,
#[serde(default, with = "serde_optional_base64")]
pub report_spam_token: Option<Vec<u8>>,
}

fn default_true() -> bool {
true
}

#[derive(serde::Serialize, serde::Deserialize)]
pub(crate) struct EnvelopeEntityList {
pub messages: Vec<EnvelopeEntity>,
}

pub(crate) const SUPPORTED_VERSION: u8 = 1;
pub(crate) const CIPHER_KEY_SIZE: usize = 32;
pub(crate) const MAC_KEY_SIZE: usize = 20;
Expand Down
5 changes: 2 additions & 3 deletions src/groups_v2/model.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
use std::{convert::TryFrom, convert::TryInto};

use derivative::Derivative;
use libsignal_protocol::ServiceId;
use serde::{Deserialize, Serialize};
use uuid::Uuid;
use zkgroup::profiles::ProfileKey;

use crate::ServiceAddress;

use super::GroupDecodingError;

#[derive(Copy, Debug, Clone, Serialize, Deserialize, PartialEq, Eq)]
Expand Down Expand Up @@ -34,7 +33,7 @@ impl PartialEq for Member {

#[derive(Clone, Debug, PartialEq, Eq)]
pub struct PendingMember {
pub address: ServiceAddress,
pub address: ServiceId,
pub role: Role,
pub added_by_uuid: Uuid,
pub timestamp: u64,
Expand Down
2 changes: 1 addition & 1 deletion src/groups_v2/operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ impl GroupOperations {
let added_by_uuid = self.decrypt_aci(&member.added_by_user_id)?;

Ok(PendingMember {
address: service_id.into(),
address: service_id,
role: inner_member.role.try_into()?,
added_by_uuid: added_by_uuid.into(),
timestamp: member.timestamp,
Expand Down
2 changes: 0 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ pub mod messagepipe;
pub mod models;
pub mod pre_keys;
pub mod profile_name;
pub mod profile_service;
#[allow(clippy::derive_partial_eq_without_eq)]
pub mod proto;
pub mod provisioning;
Expand Down Expand Up @@ -49,7 +48,6 @@ pub const GROUP_UPDATE_FLAG: u32 = 1;
pub const GROUP_LEAVE_FLAG: u32 = 2;

pub mod prelude {
pub use super::ServiceAddress;
pub use crate::{
cipher::ServiceCipher,
configuration::{
Expand Down
Loading

0 comments on commit f4313db

Please sign in to comment.