Skip to main content

wacore_libsignal/protocol/
error.rs

1//
2// Copyright 2020-2021 Signal Messenger, LLC.
3// SPDX-License-Identifier: AGPL-3.0-only
4//
5
6use std::panic::UnwindSafe;
7
8use crate::{
9    core::{
10        ProtocolAddress,
11        curve::{CurveError, KeyType},
12    },
13    crypto::CryptoProviderError,
14    protocol::CiphertextMessageType,
15};
16use thiserror::Error;
17
18pub type Result<T> = std::result::Result<T, SignalProtocolError>;
19
20#[derive(Debug, Error)]
21pub enum SignalProtocolError {
22    #[error("invalid argument: {0}")]
23    InvalidArgument(String),
24    #[error("invalid state for call to {0} to succeed: {1}")]
25    InvalidState(&'static str, String),
26
27    #[error("backend store error in {0}")]
28    BackendError(
29        &'static str,
30        #[source] Box<dyn std::error::Error + Send + Sync>,
31    ),
32
33    #[error("protobuf encoding was invalid")]
34    InvalidProtobufEncoding,
35
36    #[error("ciphertext serialized bytes were too short <{0}>")]
37    CiphertextMessageTooShort(usize),
38    #[error("ciphertext version was too old <{0}>")]
39    LegacyCiphertextVersion(u8),
40    #[error("ciphertext version was unrecognized <{0}>")]
41    UnrecognizedCiphertextVersion(u8),
42    #[error("unrecognized message version <{0}>")]
43    UnrecognizedMessageVersion(u32),
44
45    #[error("fingerprint version number mismatch them {0} us {1}")]
46    FingerprintVersionMismatch(u32, u32),
47    #[error("fingerprint parsing error")]
48    FingerprintParsingError,
49
50    #[error("no key type identifier")]
51    NoKeyTypeIdentifier,
52    #[error("bad key type <{0:#04x}>")]
53    BadKeyType(u8),
54    #[error("bad key length <{1}> for key with type <{0}>")]
55    BadKeyLength(KeyType, usize),
56
57    #[error("invalid signature detected")]
58    SignatureValidationFailed,
59
60    #[error("the active crypto provider failed the key agreement")]
61    KeyAgreementFailed(#[source] CryptoProviderError),
62
63    #[error("untrusted identity for address {0}")]
64    UntrustedIdentity(ProtocolAddress),
65
66    #[error("invalid prekey identifier")]
67    InvalidPreKeyId,
68    #[error("invalid signed prekey identifier")]
69    InvalidSignedPreKeyId,
70
71    #[error("invalid MAC key length <{0}>")]
72    InvalidMacKeyLength(usize),
73
74    #[error("no sender key state: {0}")]
75    NoSenderKeyState(String),
76
77    #[error("session with {0} not found")]
78    SessionNotFound(ProtocolAddress),
79    #[error("invalid session: {0}")]
80    InvalidSessionStructure(&'static str),
81    #[error("invalid sender key session")]
82    InvalidSenderKeySession,
83    #[error("session for {0} has invalid registration ID {1:X}")]
84    InvalidRegistrationId(ProtocolAddress, u32),
85
86    #[error("message with old counter {0} / {1}")]
87    DuplicatedMessage(u32, u32),
88    #[error("invalid {0:?} message: {1}")]
89    InvalidMessage(CiphertextMessageType, &'static str),
90    #[error("MAC verification failed for {0:?} message")]
91    BadMac(CiphertextMessageType),
92
93    #[error("error while invoking an ffi callback: {0}")]
94    FfiBindingError(String),
95    #[error("error in method call '{0}': {1}")]
96    ApplicationCallbackError(
97        &'static str,
98        #[source] Box<dyn std::error::Error + Send + Sync + UnwindSafe + 'static>,
99    ),
100
101    #[error("invalid sealed sender message: {0}")]
102    InvalidSealedSenderMessage(String),
103    #[error("unknown sealed sender message version {0}")]
104    UnknownSealedSenderVersion(u8),
105    #[error("self send of a sealed sender message")]
106    SealedSenderSelfSend,
107}
108
109impl From<CurveError> for SignalProtocolError {
110    fn from(e: CurveError) -> Self {
111        match e {
112            CurveError::NoKeyTypeIdentifier => Self::NoKeyTypeIdentifier,
113            CurveError::BadKeyType(raw) => Self::BadKeyType(raw),
114            CurveError::BadKeyLength(key_type, len) => Self::BadKeyLength(key_type, len),
115            CurveError::AgreementFailed(source) => Self::KeyAgreementFailed(source),
116        }
117    }
118}
119
120#[cfg(test)]
121mod tests {
122    use super::*;
123
124    #[derive(Debug, thiserror::Error)]
125    #[error("synthetic backend failure: {code}")]
126    struct DummyBackendError {
127        code: u32,
128    }
129
130    #[test]
131    fn backend_error_preserves_typed_source_via_downcast() {
132        let dummy = DummyBackendError { code: 42 };
133        let spe = SignalProtocolError::BackendError("test_context", Box::new(dummy));
134        let src = std::error::Error::source(&spe).expect("source preserved");
135        let inner = src
136            .downcast_ref::<DummyBackendError>()
137            .expect("downcasts to DummyBackendError");
138        assert_eq!(inner.code, 42);
139    }
140}