libsignal_service/provisioning/
mod.rs1mod cipher;
2mod pipe;
3
4use std::array::TryFromSliceError;
5use std::convert::TryInto;
6
7pub use cipher::ProvisioningCipher;
8
9use base64::Engine;
10use derivative::Derivative;
11use futures::StreamExt;
12use futures::{channel::mpsc::Sender, pin_mut, SinkExt};
13use libsignal_core::curve::CurveError;
14use libsignal_protocol::{
15 DeviceId, IdentityKey, IdentityKeyPair, PrivateKey, PublicKey,
16};
17use prost::Message;
18use serde::Deserialize;
19use url::Url;
20use uuid::Uuid;
21use zkgroup::profiles::ProfileKey;
22
23use pipe::{ProvisioningPipe, ProvisioningStep};
24
25use crate::prelude::ServiceError;
26use crate::push_service::DeviceActivationRequest;
27use crate::utils::BASE64_RELAXED;
28use crate::{
29 account_manager::encrypt_device_name,
30 pre_keys::PreKeysStore,
31 push_service::{
32 HttpAuth, LinkAccountAttributes, LinkCapabilities, LinkRequest,
33 LinkResponse, PushService, ServiceIds,
34 },
35};
36
37pub use crate::proto::{
38 ProvisionEnvelope, ProvisionMessage, ProvisioningVersion,
39};
40
41#[derive(thiserror::Error, Debug)]
42pub enum ProvisioningError {
43 #[error("no provisioning URL received")]
44 MissingUrl,
45 #[error("bad version number (unsupported)")]
46 BadVersionNumber,
47 #[error("missing public key")]
48 MissingPublicKey,
49 #[error("missing private key")]
50 MissingPrivateKey,
51 #[error("invalid public key")]
52 InvalidPublicKey(InvalidKeyError),
53 #[error("invalid privat key")]
54 InvalidPrivateKey(InvalidKeyError),
55 #[error("missing UUID")]
56 MissingUuid,
57 #[error("no provisioning message received")]
58 MissingMessage,
59 #[error("missing profile key")]
60 MissingProfileKey,
61 #[error("missing phone number")]
62 MissingPhoneNumber,
63 #[error("invalid phone number: {0}")]
64 InvalidPhoneNumber(phonenumber::ParseError),
65 #[error("missing provisioning code")]
66 MissingProvisioningCode,
67 #[error("mismatched MAC")]
68 MismatchedMac,
69 #[error("AES CBC padding error: {0}")]
70 AesPaddingError(aes::cipher::block_padding::UnpadError),
71
72 #[error("invalid provisioning step received")]
73 InvalidStep,
74
75 #[error("Protobuf decoding error: {0}")]
76 DecodeError(#[from] prost::DecodeError),
77 #[error("Websocket error: {reason}")]
78 WsError { reason: String },
79 #[error("Websocket closing")]
80 WsClosing,
81 #[error("Service error: {0}")]
82 ServiceError(#[from] ServiceError),
83 #[error("libsignal-protocol error: {0}")]
84 ProtocolError(#[from] libsignal_protocol::SignalProtocolError),
85 #[error("invalid device ID: {0}")]
86 InvalidDeviceId(#[from] libsignal_core::InvalidDeviceId),
87 #[error("ProvisioningCipher in encrypt-only mode")]
88 EncryptOnlyProvisioningCipher,
89 #[error("invalid profile key bytes")]
90 InvalidProfileKey(TryFromSliceError),
91}
92
93impl ProvisioningError {
94 pub fn invalid_public_key(e: impl Into<InvalidKeyError>) -> Self {
95 ProvisioningError::InvalidPublicKey(e.into())
96 }
97
98 pub fn invalid_private_key(e: impl Into<InvalidKeyError>) -> Self {
99 ProvisioningError::InvalidPrivateKey(e.into())
100 }
101}
102
103#[derive(Debug, thiserror::Error)]
104pub enum InvalidKeyError {
105 #[error("curve error: {0}")]
106 Curve(#[from] CurveError),
107 #[error("base64 decoding error: {0}")]
108 Base64(#[from] base64::DecodeError),
109 #[error("protocol error: {0}")]
110 Protocol(#[from] libsignal_protocol::SignalProtocolError),
111}
112
113pub fn generate_registration_id<R: rand::Rng + rand::CryptoRng>(
114 csprng: &mut R,
115) -> u32 {
116 csprng.random_range(1..16380)
117}
118
119#[derive(Debug, Deserialize)]
120#[serde(rename_all = "camelCase")]
121pub struct ConfirmCodeResponse {
122 pub uuid: Uuid,
123 pub storage_capable: bool,
124}
125
126#[derive(Debug)]
127pub enum SecondaryDeviceProvisioning {
128 Url(Url),
129 NewDeviceRegistration(NewDeviceRegistration),
130}
131
132#[derive(Derivative)]
133#[derivative(Debug)]
134pub struct NewDeviceRegistration {
135 pub phone_number: phonenumber::PhoneNumber,
136 pub device_id: DeviceId,
137 pub registration_id: u32,
138 pub pni_registration_id: u32,
139 pub service_ids: ServiceIds,
140 #[derivative(Debug = "ignore")]
141 pub aci_private_key: PrivateKey,
142 pub aci_public_key: IdentityKey,
143 #[derivative(Debug = "ignore")]
144 pub pni_private_key: PrivateKey,
145 pub pni_public_key: IdentityKey,
146 #[derivative(Debug = "ignore")]
147 pub profile_key: ProfileKey,
148}
149
150pub async fn link_device<
151 R: rand::Rng + rand::CryptoRng,
152 Aci: PreKeysStore,
153 Pni: PreKeysStore,
154>(
155 aci_store: &mut Aci,
156 pni_store: &mut Pni,
157 csprng: &mut R,
158 mut push_service: PushService,
159 password: &str,
160 device_name: &str,
161 mut tx: Sender<SecondaryDeviceProvisioning>,
162) -> Result<(), ProvisioningError> {
163 let ws = push_service
165 .ws(
166 "/v1/websocket/provisioning/",
167 "/v1/keepalive/provisioning",
168 &[],
169 None,
170 )
171 .await?;
172
173 let registration_id = csprng.random_range(1..256);
174 let pni_registration_id = csprng.random_range(1..256);
175
176 let provisioning_pipe = ProvisioningPipe::from_socket(ws, csprng);
177 let provision_stream = provisioning_pipe.stream();
178 pin_mut!(provision_stream);
179
180 if let ProvisioningStep::Url(url) = provision_stream
181 .next()
182 .await
183 .ok_or(ProvisioningError::MissingUrl)??
184 {
185 tx.send(SecondaryDeviceProvisioning::Url(url))
186 .await
187 .expect("failed to send provisioning Url in channel");
188 } else {
189 return Err(ProvisioningError::InvalidStep);
190 }
191
192 if let ProvisioningStep::Message(message) =
193 provision_stream
194 .next()
195 .await
196 .ok_or(ProvisioningError::MissingMessage)??
197 {
198 let aci_public_key = PublicKey::deserialize(
199 &message
200 .aci_identity_key_public
201 .ok_or(ProvisioningError::MissingPublicKey)?,
202 )
203 .map_err(ProvisioningError::invalid_public_key)?;
204 let aci_public_key = IdentityKey::new(aci_public_key);
205
206 let aci_private_key = PrivateKey::deserialize(
207 &message
208 .aci_identity_key_private
209 .ok_or(ProvisioningError::MissingPrivateKey)?,
210 )
211 .map_err(ProvisioningError::invalid_private_key)?;
212
213 let pni_public_key = PublicKey::deserialize(
214 &message
215 .pni_identity_key_public
216 .ok_or(ProvisioningError::MissingPublicKey)?,
217 )
218 .map_err(ProvisioningError::invalid_public_key)?;
219 let pni_public_key = IdentityKey::new(pni_public_key);
220
221 let pni_private_key = PrivateKey::deserialize(
222 &message
223 .pni_identity_key_private
224 .ok_or(ProvisioningError::MissingPrivateKey)?,
225 )
226 .map_err(ProvisioningError::invalid_private_key)?;
227
228 let profile_key = message
229 .profile_key
230 .ok_or(ProvisioningError::MissingProfileKey)?;
231
232 let phone_number = message
233 .number
234 .ok_or(ProvisioningError::MissingPhoneNumber)?;
235
236 let phone_number = phonenumber::parse(None, phone_number)
237 .map_err(ProvisioningError::InvalidPhoneNumber)?;
238
239 let provisioning_code = message
240 .provisioning_code
241 .ok_or(ProvisioningError::MissingProvisioningCode)?;
242
243 let aci_key_pair =
244 IdentityKeyPair::new(aci_public_key, aci_private_key);
245 let pni_key_pair =
246 IdentityKeyPair::new(pni_public_key, pni_private_key);
247
248 let (
249 _aci_pre_keys,
250 aci_signed_pre_key,
251 _aci_pq_pre_keys,
252 aci_pq_last_resort_pre_key,
253 ) = crate::pre_keys::replenish_pre_keys(
254 aci_store,
255 csprng,
256 &aci_key_pair,
257 true,
258 0,
259 0,
260 )
261 .await?;
262
263 let aci_pq_last_resort_pre_key =
264 aci_pq_last_resort_pre_key.expect("requested last resort key");
265 assert!(_aci_pre_keys.is_empty());
266 assert!(_aci_pq_pre_keys.is_empty());
267
268 let (
269 _pni_pre_keys,
270 pni_signed_pre_key,
271 _pni_pq_pre_keys,
272 pni_pq_last_resort_pre_key,
273 ) = crate::pre_keys::replenish_pre_keys(
274 pni_store,
275 csprng,
276 &pni_key_pair,
277 true,
278 0,
279 0,
280 )
281 .await?;
282
283 let pni_pq_last_resort_pre_key =
284 pni_pq_last_resort_pre_key.expect("requested last resort key");
285 assert!(_pni_pre_keys.is_empty());
286 assert!(_pni_pq_pre_keys.is_empty());
287
288 let encrypted_device_name = BASE64_RELAXED.encode(
289 encrypt_device_name(csprng, device_name, &aci_public_key)?
290 .encode_to_vec(),
291 );
292
293 let profile_key = ProfileKey::create(
294 profile_key
295 .as_slice()
296 .try_into()
297 .map_err(ProvisioningError::InvalidProfileKey)?,
298 );
299
300 let request = LinkRequest {
301 verification_code: provisioning_code,
302 account_attributes: LinkAccountAttributes {
303 registration_id,
304 pni_registration_id,
305 fetches_messages: true,
306 capabilities: LinkCapabilities::default(),
307 name: encrypted_device_name,
308 },
309 device_activation_request: DeviceActivationRequest {
310 aci_signed_pre_key: aci_signed_pre_key.try_into()?,
311 pni_signed_pre_key: pni_signed_pre_key.try_into()?,
312 aci_pq_last_resort_pre_key: aci_pq_last_resort_pre_key
313 .try_into()?,
314 pni_pq_last_resort_pre_key: pni_pq_last_resort_pre_key
315 .try_into()?,
316 },
317 };
318
319 let LinkResponse {
320 aci,
321 pni,
322 device_id,
323 } = push_service
324 .link_device(
325 &request,
326 HttpAuth {
327 username: phone_number.to_string(),
328 password: password.to_owned(),
329 },
330 )
331 .await?;
332
333 tx.send(SecondaryDeviceProvisioning::NewDeviceRegistration(
334 NewDeviceRegistration {
335 phone_number,
336 service_ids: ServiceIds { aci, pni },
337 device_id: device_id.try_into()?,
338 registration_id,
339 pni_registration_id,
340 aci_private_key,
341 aci_public_key,
342 pni_private_key,
343 pni_public_key,
344 profile_key,
345 },
346 ))
347 .await
348 .expect("failed to send provisioning message in rx channel");
349 } else {
350 return Err(ProvisioningError::InvalidStep);
351 }
352
353 Ok(())
354}