Skip to main content

libsignal_protocol/
error.rs

1//
2// Copyright 2020-2021 Signal Messenger, LLC.
3// SPDX-License-Identifier: AGPL-3.0-only
4//
5
6use std::fmt::{Display, Formatter};
7use std::panic::UnwindSafe;
8
9use displaydoc::Display;
10use libsignal_core::curve::{CurveError, KeyType};
11use thiserror::Error;
12use uuid::Uuid;
13
14use crate::kem;
15
16pub type Result<T> = std::result::Result<T, SignalProtocolError>;
17
18#[derive(Debug, Display, Error)]
19pub enum SignalProtocolError {
20    /// invalid argument: {0}
21    InvalidArgument(String),
22    /// invalid state for call to {0} to succeed: {1}
23    InvalidState(&'static str, String),
24
25    /// protobuf encoding was invalid
26    InvalidProtobufEncoding,
27
28    /// ciphertext serialized bytes were too short <{0}>
29    CiphertextMessageTooShort(usize),
30    /// ciphertext version was too old <{0}>
31    LegacyCiphertextVersion(u8),
32    /// ciphertext version was unrecognized <{0}>
33    UnrecognizedCiphertextVersion(u8),
34    /// unrecognized message version <{0}>
35    UnrecognizedMessageVersion(u32),
36
37    /// no key type identifier
38    NoKeyTypeIdentifier,
39    /// bad key type <{0:#04x}>
40    BadKeyType(u8),
41    /// bad key length <{1}> for key with type <{0}>
42    BadKeyLength(KeyType, usize),
43
44    /// invalid key agreement
45    InvalidKeyAgreement,
46
47    /// invalid signature detected
48    SignatureValidationFailed,
49
50    /// untrusted identity for address {0}
51    UntrustedIdentity(crate::ProtocolAddress),
52
53    /// invalid prekey identifier
54    InvalidPreKeyId,
55    /// invalid signed prekey identifier
56    InvalidSignedPreKeyId,
57    /// invalid Kyber prekey identifier
58    InvalidKyberPreKeyId,
59
60    /// invalid MAC key length <{0}>
61    InvalidMacKeyLength(usize),
62
63    /// missing sender key state for distribution ID {distribution_id}
64    NoSenderKeyState { distribution_id: Uuid },
65
66    /// protocol address is invalid: {name}.{device_id}
67    InvalidProtocolAddress { name: String, device_id: u32 },
68    /// {0}
69    SessionNotFound(SessionNotFound),
70    /// invalid session: {0}
71    InvalidSessionStructure(&'static str),
72    /// invalid sender key session with distribution ID {distribution_id}
73    InvalidSenderKeySession { distribution_id: Uuid },
74    /// session for {0} has invalid registration ID {1:X}
75    InvalidRegistrationId(crate::ProtocolAddress, u32),
76
77    /// message with old counter {0} / {1}
78    DuplicatedMessage(u32, u32),
79    /// invalid {0:?} message: {1}
80    InvalidMessage(crate::CiphertextMessageType, String),
81
82    /// error while invoking an ffi callback: {0}
83    FfiBindingError(String),
84    /// error in method call '{0}': {1}
85    ApplicationCallbackError(
86        &'static str,
87        #[source] Box<dyn std::error::Error + Send + Sync + UnwindSafe + 'static>,
88    ),
89
90    /// invalid sealed sender message: {0}
91    InvalidSealedSenderMessage(String),
92    /// unknown sealed sender message version {0}
93    UnknownSealedSenderVersion(u8),
94    /// self send of a sealed sender message
95    SealedSenderSelfSend,
96    /// unknown server certificate ID: {0}
97    UnknownSealedSenderServerCertificateId(u32),
98
99    /// bad KEM key type <{0:#04x}>
100    BadKEMKeyType(u8),
101    /// unexpected KEM key type <{0:#04x}> (expected <{1:#04x}>)
102    WrongKEMKeyType(u8, u8),
103    /// bad KEM key length <{1}> for key with type <{0}>
104    BadKEMKeyLength(kem::KeyType, usize),
105    /// bad KEM ciphertext length <{1}> for key with type <{0}>
106    BadKEMCiphertextLength(kem::KeyType, usize),
107}
108
109#[derive(Debug)]
110pub struct SessionNotFound {
111    pub address: Option<crate::ProtocolAddress>,
112    pub op: &'static str,
113}
114
115impl SessionNotFound {
116    pub const fn without_address(op: &'static str) -> Self {
117        Self { address: None, op }
118    }
119
120    pub const fn new(address: crate::ProtocolAddress, op: &'static str) -> Self {
121        Self {
122            address: Some(address),
123            op,
124        }
125    }
126}
127
128impl Display for SessionNotFound {
129    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
130        write!(f, "session")?;
131        if let Some(address) = &self.address {
132            write!(f, " with {address}")?;
133        }
134        write!(f, " not found: {}", self.op)
135    }
136}
137
138impl SignalProtocolError {
139    /// Convenience factory for [`SignalProtocolError::ApplicationCallbackError`].
140    #[inline]
141    pub fn for_application_callback<E: std::error::Error + Send + Sync + UnwindSafe + 'static>(
142        method: &'static str,
143    ) -> impl FnOnce(E) -> Self {
144        move |error| Self::ApplicationCallbackError(method, Box::new(error))
145    }
146}
147
148impl From<CurveError> for SignalProtocolError {
149    fn from(e: CurveError) -> Self {
150        match e {
151            CurveError::NoKeyTypeIdentifier => Self::NoKeyTypeIdentifier,
152            CurveError::BadKeyType(raw) => Self::BadKeyType(raw),
153            CurveError::BadKeyLength(key_type, len) => Self::BadKeyLength(key_type, len),
154            CurveError::InvalidKeyAgreement => Self::InvalidKeyAgreement,
155        }
156    }
157}