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