Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring ACI/PNI storage types #275

Merged
merged 13 commits into from
Jan 14, 2024
3 changes: 2 additions & 1 deletion libsignal-service-actix/examples/registering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,8 @@ async fn main() -> Result<(), Error> {
let mut push_service = AwcPushService::new(
servers,
Some(ServiceCredentials {
uuid: None,
aci: None,
pni: None,
phonenumber: phonenumber.clone(),
password,
signaling_key: None,
Expand Down
3 changes: 2 additions & 1 deletion libsignal-service-hyper/examples/registering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,8 @@ fn create_push_service(
HyperPushService::new(
SignalServers::Staging, // You might want to switch to Production servers
Some(ServiceCredentials {
uuid: None,
aci: None,
pni: None,
phonenumber,
password: Some(password),
signaling_key: None,
Expand Down
51 changes: 32 additions & 19 deletions libsignal-service/src/account_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use hmac::digest::Output;
use hmac::{Hmac, Mac};
use libsignal_protocol::{
kem, GenericSignedPreKey, IdentityKeyStore, KeyPair, KyberPreKeyRecord,
PreKeyRecord, PrivateKey, ProtocolStore, PublicKey, SignalProtocolError,
PreKeyRecord, PrivateKey, PublicKey, SignalProtocolError,
SignedPreKeyRecord,
};
use prost::Message;
Expand All @@ -16,7 +16,7 @@ use sha2::Sha256;
use tracing_futures::Instrument;
use zkgroup::profiles::ProfileKey;

use crate::pre_keys::KyberPreKeyEntity;
use crate::pre_keys::{KyberPreKeyEntity, PreKeysStore};
use crate::proto::DeviceName;
use crate::push_service::{AvatarWrite, RecaptchaAttributes, ServiceIdType};
use crate::ServiceAddress;
Expand Down Expand Up @@ -93,19 +93,22 @@ impl<Service: PushService> AccountManager<Service> {
#[tracing::instrument(skip(self, protocol_store, csprng))]
pub async fn update_pre_key_bundle<
R: rand::Rng + rand::CryptoRng,
P: ProtocolStore,
P: PreKeysStore,
>(
&mut self,
protocol_store: &mut P,
service_id_type: ServiceIdType,
csprng: &mut R,
pre_keys_offset_id: u32,
next_signed_pre_key_id: u32,
pq_pre_keys_offset_id: u32,
use_last_resort_key: bool,
) -> Result<(u32, u32, u32), ServiceError> {
let pre_keys_offset_id = protocol_store.next_pre_key_id().await?;
let next_signed_pre_key_id =
protocol_store.next_signed_pre_key_id().await?;
let pq_pre_keys_offset_id = protocol_store.next_pq_pre_key_id().await?;

let prekey_status = match self
.service
.get_pre_key_status(ServiceIdType::AccountIdentity)
.get_pre_key_status(service_id_type)
.instrument(tracing::span!(
tracing::Level::DEBUG,
"Fetching pre key status"
Expand Down Expand Up @@ -239,7 +242,7 @@ impl<Service: PushService> AccountManager<Service> {
};

self.service
.register_pre_keys(ServiceIdType::AccountIdentity, pre_key_state)
.register_pre_keys(service_id_type, pre_key_state)
.instrument(tracing::span!(
tracing::Level::DEBUG,
"Uploading pre keys"
Expand Down Expand Up @@ -315,7 +318,8 @@ impl<Service: PushService> AccountManager<Service> {
pub async fn link_device(
&mut self,
url: url::Url,
identity_store: &dyn IdentityKeyStore,
aci_identity_store: &dyn IdentityKeyStore,
pni_identity_store: &dyn IdentityKeyStore,
credentials: ServiceCredentials,
) -> Result<(), LinkError> {
let query: HashMap<_, _> = url.query_pairs().collect();
Expand All @@ -327,27 +331,36 @@ impl<Service: PushService> AccountManager<Service> {
let pub_key = PublicKey::deserialize(&pub_key)
.map_err(|_e| LinkError::InvalidPublicKey)?;

let identity_key_pair = identity_store.get_identity_key_pair().await?;
let aci_identity_key_pair =
aci_identity_store.get_identity_key_pair().await?;
let pni_identity_key_pair =
pni_identity_store.get_identity_key_pair().await?;

if credentials.uuid.is_none() {
tracing::warn!("No local UUID set");
if credentials.aci.is_none() {
tracing::warn!("No local ACI set");
}
if credentials.pni.is_none() {
tracing::warn!("No local PNI set");
}

let provisioning_code = self.new_device_provisioning_code().await?;

let msg = ProvisionMessage {
aci: credentials.uuid.as_ref().map(|u| u.to_string()),
aci: credentials.aci.as_ref().map(|u| u.to_string()),
aci_identity_key_public: Some(
identity_key_pair.public_key().serialize().into_vec(),
aci_identity_key_pair.public_key().serialize().into_vec(),
),
aci_identity_key_private: Some(
identity_key_pair.private_key().serialize(),
aci_identity_key_pair.private_key().serialize(),
),
number: Some(credentials.e164()),
// TODO: implement pni fields
pni_identity_key_public: None,
pni_identity_key_private: None,
pni: None,
pni_identity_key_public: Some(
pni_identity_key_pair.public_key().serialize().into_vec(),
),
pni_identity_key_private: Some(
pni_identity_key_pair.private_key().serialize(),
),
pni: credentials.pni.as_ref().map(uuid::Uuid::to_string),
profile_key: self.profile_key.as_ref().map(|x| x.bytes.to_vec()),
// CURRENT is not exposed by prost :(
provisioning_version: Some(i32::from(
Expand Down
5 changes: 3 additions & 2 deletions libsignal-service/src/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ pub type SignalingKey = [u8; CIPHER_KEY_SIZE + MAC_KEY_SIZE];

#[derive(Clone)]
pub struct ServiceCredentials {
pub uuid: Option<uuid::Uuid>,
pub aci: Option<uuid::Uuid>,
pub pni: Option<uuid::Uuid>,
pub phonenumber: phonenumber::PhoneNumber,
pub password: Option<String>,
pub signaling_key: Option<SignalingKey>,
Expand All @@ -49,7 +50,7 @@ impl ServiceCredentials {

pub fn login(&self) -> String {
let identifier = {
if let Some(uuid) = self.uuid.as_ref() {
if let Some(uuid) = self.aci.as_ref() {
uuid.to_string()
} else {
self.e164()
Expand Down
30 changes: 16 additions & 14 deletions libsignal-service/src/pre_keys.rs
Original file line number Diff line number Diff line change
@@ -1,43 +1,45 @@
use std::{convert::TryFrom, time::SystemTime};

use crate::utils::{serde_base64, serde_public_key};
use async_trait::async_trait;
use libsignal_protocol::{
error::SignalProtocolError, kem, GenericSignedPreKey, KeyPair,
KyberPreKeyRecord, KyberPreKeyStore, PreKeyRecord, PreKeyStore, PublicKey,
SignedPreKeyRecord, SignedPreKeyStore,
error::SignalProtocolError, kem, GenericSignedPreKey, IdentityKeyStore,
KeyPair, KyberPreKeyRecord, KyberPreKeyStore, PreKeyRecord, PreKeyStore,
PublicKey, SignedPreKeyRecord, SignedPreKeyStore,
};

use serde::{Deserialize, Serialize};

/// Stores the ID of keys published ahead of time
///
/// <https://signal.org/docs/specifications/x3dh/>
#[async_trait(?Send)]
pub trait PreKeysStore:
PreKeyStore + SignedPreKeyStore + KyberPreKeyStore
PreKeyStore + IdentityKeyStore + SignedPreKeyStore + KyberPreKeyStore
{
/// ID of the next pre key
fn pre_keys_offset_id(&self) -> Result<u32, SignalProtocolError>;
async fn next_pre_key_id(&self) -> Result<u32, SignalProtocolError>;

/// ID of the next signed pre key
fn next_signed_pre_key_id(&self) -> Result<u32, SignalProtocolError>;
async fn next_signed_pre_key_id(&self) -> Result<u32, SignalProtocolError>;

/// ID of the next PQ pre key
fn next_pq_pre_key_id(&self) -> Result<u32, SignalProtocolError>;
async fn next_pq_pre_key_id(&self) -> Result<u32, SignalProtocolError>;

/// set the ID of the next pre key
fn set_pre_keys_offset_id(
async fn set_next_pre_key_id(
&mut self,
id: u32,
) -> Result<(), SignalProtocolError>;

/// set the ID of the next signed pre key
fn set_next_signed_pre_key_id(
async fn set_next_signed_pre_key_id(
&mut self,
id: u32,
) -> Result<(), SignalProtocolError>;

/// set the ID of the next PQ pre key
fn set_next_pq_pre_key_id(
async fn set_next_pq_pre_key_id(
&mut self,
id: u32,
) -> Result<(), SignalProtocolError>;
Expand Down Expand Up @@ -132,7 +134,7 @@ pub(crate) async fn generate_last_resort_kyber_key<S: PreKeysStore>(
store: &mut S,
identity_key: &KeyPair,
) -> Result<KyberPreKeyRecord, SignalProtocolError> {
let id = store.next_pq_pre_key_id()?;
let id = store.next_pq_pre_key_id().await?;
let id = id.max(1); // TODO: Hack, keys start with 1

let record = KyberPreKeyRecord::generate(
Expand All @@ -142,7 +144,7 @@ pub(crate) async fn generate_last_resort_kyber_key<S: PreKeysStore>(
)?;

store.save_kyber_pre_key(id.into(), &record).await?;
store.set_next_pq_pre_key_id(id + 1)?;
store.set_next_pq_pre_key_id(id + 1).await?;

Ok(record)
}
Expand All @@ -155,7 +157,7 @@ pub(crate) async fn generate_signed_pre_key<
csprng: &mut R,
identity_key: &KeyPair,
) -> Result<SignedPreKeyRecord, SignalProtocolError> {
let id = store.next_signed_pre_key_id()?;
let id = store.next_signed_pre_key_id().await?;
let id = id.max(1); // TODO: Hack, keys start with 1

let key_pair = KeyPair::generate(csprng);
Expand All @@ -171,7 +173,7 @@ pub(crate) async fn generate_signed_pre_key<
SignedPreKeyRecord::new(id.into(), unix_time, &key_pair, &signature);

store.save_signed_pre_key(id.into(), &record).await?;
store.set_next_signed_pre_key_id(id + 1)?;
store.set_next_signed_pre_key_id(id + 1).await?;

Ok(record)
}
7 changes: 4 additions & 3 deletions libsignal-service/src/provisioning/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,11 +108,12 @@ pub struct NewDeviceRegistration {

pub async fn link_device<
R: rand::Rng + rand::CryptoRng,
S: PreKeysStore,
Aci: PreKeysStore,
Pni: PreKeysStore,
P: PushService,
>(
aci_store: &mut S,
pni_store: &mut S,
aci_store: &mut Aci,
pni_store: &mut Pni,
csprng: &mut R,
mut push_service: P,
password: &str,
Expand Down
2 changes: 1 addition & 1 deletion libsignal-service/src/push_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ pub const STICKER_PATH: &str = "stickers/%s/full/%d";
pub const KEEPALIVE_TIMEOUT_SECONDS: Duration = Duration::from_secs(55);
pub const DEFAULT_DEVICE_ID: u32 = 1;

#[derive(Debug, Clone, Copy)]
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum ServiceIdType {
/// Account Identity (ACI)
///
Expand Down
4 changes: 4 additions & 0 deletions libsignal-service/src/service_address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ impl ServiceAddress {
pub fn aci(&self) -> libsignal_protocol::Aci {
libsignal_protocol::Aci::from_uuid_bytes(self.uuid.into_bytes())
}

pub fn pni(&self) -> libsignal_protocol::Pni {
libsignal_protocol::Pni::from_uuid_bytes(self.uuid.into_bytes())
}
}

impl From<Uuid> for ServiceAddress {
Expand Down
Loading