Skip to main content

libsignal_service/push_service/
error.rs

1use aes::cipher::block_padding;
2use libsignal_core::curve::CurveError;
3use libsignal_protocol::{
4    FingerprintError, ServiceIdKind, SignalProtocolError,
5};
6use reqwest::StatusCode;
7use zkgroup::{ZkGroupDeserializationFailure, ZkGroupVerificationFailure};
8
9use crate::{
10    cipher::SealedSenderDecryptionError, groups_v2::GroupDecodingError,
11    websocket::registration::RegistrationLockFailure,
12};
13
14use super::{MismatchedDevices, ProofRequired, StaleDevices};
15
16#[derive(thiserror::Error, Debug)]
17pub enum ServiceError {
18    #[error("Service request timed out: {reason}")]
19    Timeout { reason: &'static str },
20
21    #[error("invalid URL: {0}")]
22    InvalidUrl(#[from] url::ParseError),
23
24    #[error("wrong address type: {0}")]
25    InvalidAddressType(ServiceIdKind),
26
27    #[error("invalid phone number")]
28    InvalidPhoneNumber,
29
30    #[error("Error sending request: {reason}")]
31    SendError { reason: String },
32
33    #[error("i/o error")]
34    IO(#[from] std::io::Error),
35
36    #[error("Error decoding JSON: {0}")]
37    JsonDecodeError(#[from] serde_json::Error),
38    #[error("Error decoding protobuf frame: {0}")]
39    ProtobufDecodeError(#[from] prost::DecodeError),
40    #[error("error encoding or decoding bincode: {0}")]
41    BincodeError(#[from] bincode::Error),
42    #[error("error decoding base64 string: {0}")]
43    Base64DecodeError(#[from] base64::DecodeError),
44
45    #[error("Rate limit exceeded: retry after {}", retry_after.map(|a| a.to_string()).unwrap_or_else(|| "unspecified".into()))]
46    RateLimitExceeded {
47        retry_after: Option<chrono::Duration>,
48    },
49    #[error("Authorization failed")]
50    Unauthorized,
51    #[error("Registration lock is set: {0:?}")]
52    Locked(RegistrationLockFailure),
53
54    #[error("Unexpected response: HTTP {status}: {body}")]
55    UnhandledResponseCode { status: StatusCode, body: String },
56
57    #[error("Websocket error: {0}")]
58    WsError(Box<reqwest_websocket::Error>),
59    #[error("Websocket closing: {reason}")]
60    WsClosing { reason: &'static str },
61
62    #[error("Invalid padding: {0}")]
63    Padding(#[from] block_padding::Error),
64
65    #[error("unknown padding version {0}")]
66    PaddingVersion(u32),
67
68    #[error("Invalid frame: {reason}")]
69    InvalidFrame { reason: &'static str },
70
71    #[error("MAC error")]
72    MacError,
73
74    #[error("Protocol error: {0}")]
75    SignalProtocolError(#[from] SignalProtocolError),
76
77    #[error("Sealed sender decryption error: {0}")]
78    SealedSenderDecryptionError(#[from] SealedSenderDecryptionError),
79
80    #[error("invalid device id: {0}")]
81    InvalidDeviceId(#[from] libsignal_core::InvalidDeviceId),
82
83    #[error("Proof required: {0:?}")]
84    ProofRequiredError(ProofRequired),
85
86    #[error("{0:?}")]
87    MismatchedDevicesException(MismatchedDevices),
88
89    #[error("{0:?}")]
90    StaleDevices(StaleDevices),
91
92    #[error(transparent)]
93    CredentialsCacheError(#[from] crate::groups_v2::CredentialsCacheError),
94
95    #[error("groups v2 (zero-knowledge) error")]
96    GroupsV2Error,
97
98    #[error(transparent)]
99    GroupsV2DecryptionError(#[from] GroupDecodingError),
100
101    #[error(transparent)]
102    ZkGroupDeserializationFailure(#[from] ZkGroupDeserializationFailure),
103
104    #[error(transparent)]
105    ZkGroupVerificationFailure(#[from] ZkGroupVerificationFailure),
106
107    #[error("unsupported content")]
108    UnsupportedContent,
109
110    #[error("Not found.")]
111    NotFoundError,
112
113    #[error("failed to decrypt field from device info: {0}")]
114    DecryptDeviceInfoFieldError(&'static str),
115
116    #[error("Unknown CDN version {0}")]
117    UnknownCdnVersion(u32),
118
119    #[error("Device limit reached: {current} out of {max} devices.")]
120    DeviceLimitReached { current: u32, max: u32 },
121
122    #[error("HTTP reqwest error: {0}")]
123    Http(#[from] reqwest::Error),
124
125    #[error(transparent)]
126    Curve(#[from] CurveError),
127
128    // HpkeError does not implement StdError, so we need a manual display,
129    // and manual From impl.
130    #[error("Cryptographic error: {0}")]
131    Hpke(signal_crypto::HpkeError),
132
133    // FingerprintError does not implement StdError, so we need a manual display,
134    // and manual From impl.
135    #[error("Fingerprint error: {0}")]
136    Fingerprint(FingerprintError),
137
138    #[error("CDSI lookup error: {0}")]
139    #[cfg(feature = "cdsi")]
140    CdsiLookupError(#[from] libsignal_net::cdsi::LookupError),
141}
142
143impl From<signal_crypto::HpkeError> for ServiceError {
144    fn from(value: signal_crypto::HpkeError) -> Self {
145        ServiceError::Hpke(value)
146    }
147}
148
149impl From<FingerprintError> for ServiceError {
150    fn from(value: FingerprintError) -> Self {
151        ServiceError::Fingerprint(value)
152    }
153}
154
155impl From<reqwest_websocket::Error> for ServiceError {
156    fn from(error: reqwest_websocket::Error) -> Self {
157        Self::WsError(Box::new(error))
158    }
159}