ruma_signatures/
error.rs

1use ruma_common::{
2    canonical_json::{JsonType, RedactionError},
3    serde::Base64DecodeError,
4    EventId, OwnedEventId, RoomVersionId,
5};
6use thiserror::Error;
7
8/// `ruma-signature`'s error type, wraps a number of other error types.
9#[derive(Debug, Error)]
10#[non_exhaustive]
11#[allow(clippy::enum_variant_names)]
12pub enum Error {
13    /// [`JsonError`] wrapper.
14    #[error("JSON error: {0}")]
15    Json(#[from] JsonError),
16
17    /// [`VerificationError`] wrapper.
18    #[error("Verification error: {0}")]
19    Verification(#[from] VerificationError),
20
21    /// [`ParseError`] wrapper.
22    #[error("Parse error: {0}")]
23    Parse(#[from] ParseError),
24
25    /// Wrapper for [`pkcs8::Error`].
26    #[error("DER Parse error: {0}")]
27    DerParse(pkcs8::Error),
28
29    /// PDU was too large
30    #[error("PDU is larger than maximum of 65535 bytes")]
31    PduSize,
32}
33
34impl From<RedactionError> for Error {
35    fn from(err: RedactionError) -> Self {
36        match err {
37            RedactionError::NotOfType { field: target, of_type, .. } => {
38                JsonError::NotOfType { target, of_type }.into()
39            }
40            RedactionError::JsonFieldMissingFromObject(field) => {
41                JsonError::JsonFieldMissingFromObject(field).into()
42            }
43            #[allow(unreachable_patterns)]
44            _ => unreachable!(),
45        }
46    }
47}
48
49/// All errors related to JSON validation/parsing.
50#[derive(Debug, Error)]
51#[non_exhaustive]
52pub enum JsonError {
53    /// `target` is not of the correct type `of_type` ([`JsonType`]).
54    #[error("Value in {target:?} must be a JSON {of_type:?}")]
55    NotOfType {
56        /// An arbitrary "target" that doesn't have the required type.
57        target: String,
58        /// The JSON type the target was expected to be.
59        of_type: JsonType,
60    },
61
62    /// Like [`JsonError::NotOfType`], only called when the `target` is a multiple;
63    /// array, set, etc.
64    #[error("Values in {target:?} must be JSON {of_type:?}s")]
65    NotMultiplesOfType {
66        /// An arbitrary "target" where
67        /// each or one of it's elements doesn't have the required type.
68        target: String,
69        /// The JSON type the element was expected to be.
70        of_type: JsonType,
71    },
72
73    /// The given required field is missing from a JSON object.
74    #[error("JSON object must contain the field {0:?}")]
75    JsonFieldMissingFromObject(String),
76
77    /// A more generic JSON error from [`serde_json`].
78    #[error(transparent)]
79    Serde(#[from] serde_json::Error),
80}
81
82// TODO: make macro for this
83impl JsonError {
84    pub(crate) fn not_of_type<T: Into<String>>(target: T, of_type: JsonType) -> Error {
85        Self::NotOfType { target: target.into(), of_type }.into()
86    }
87
88    pub(crate) fn not_multiples_of_type<T: Into<String>>(target: T, of_type: JsonType) -> Error {
89        Self::NotMultiplesOfType { target: target.into(), of_type }.into()
90    }
91
92    pub(crate) fn field_missing_from_object<T: Into<String>>(target: T) -> Error {
93        Self::JsonFieldMissingFromObject(target.into()).into()
94    }
95}
96
97/// Errors relating to verification of signatures.
98#[derive(Debug, Error)]
99#[non_exhaustive]
100pub enum VerificationError {
101    /// The signature uses an unsupported algorithm.
102    #[error("signature uses an unsupported algorithm")]
103    UnsupportedAlgorithm,
104
105    /// The signatures for an entity cannot be found in the signatures map.
106    #[error("Could not find signatures for entity {0:?}")]
107    NoSignaturesForEntity(String),
108
109    /// The public keys for an entity cannot be found in the public keys map.
110    #[error("Could not find public keys for entity {0:?}")]
111    NoPublicKeysForEntity(String),
112
113    /// The public key with the given identifier cannot be found for the given entity.
114    #[error("Could not find public key {key_id:?} for entity {entity:?}")]
115    PublicKeyNotFound {
116        /// The entity for which the key is missing.
117        entity: String,
118
119        /// The identifier of the key that is missing.
120        key_id: String,
121    },
122
123    /// No signature with a supported algorithm was found for the given entity.
124    #[error("Could not find supported signature for entity {0:?}")]
125    NoSupportedSignatureForEntity(String),
126
127    /// The signature verification failed.
128    #[error("Could not verify signature: {0}")]
129    Signature(#[source] ed25519_dalek::SignatureError),
130}
131
132/// Errors relating to parsing of all sorts.
133#[derive(Debug, Error)]
134#[non_exhaustive]
135pub enum ParseError {
136    /// For user ID parsing errors.
137    #[error("Could not parse User ID: {0}")]
138    UserId(#[source] ruma_common::IdParseError),
139
140    /// For event ID parsing errors.
141    #[error("Could not parse Event ID: {0}")]
142    EventId(#[source] ruma_common::IdParseError),
143
144    /// For when an event ID, coupled with a specific room version, doesn't have a server name
145    /// embedded.
146    #[error("Event Id {0:?} should have a server name for the given room version {1:?}")]
147    ServerNameFromEventIdByRoomVersion(OwnedEventId, RoomVersionId),
148
149    /// For when the extracted/"parsed" public key from a PKCS#8 v2 document doesn't match the
150    /// public key derived from it's private key.
151    #[error("PKCS#8 Document public key does not match public key derived from private key; derived: {0:X?} (len {}), parsed: {1:X?} (len {})", .derived_key.len(), .parsed_key.len())]
152    DerivedPublicKeyDoesNotMatchParsedKey {
153        /// The parsed key.
154        parsed_key: Vec<u8>,
155        /// The derived key.
156        derived_key: Vec<u8>,
157    },
158
159    /// For when the ASN.1 Object Identifier on a PKCS#8 document doesn't match the expected one.
160    ///
161    /// e.g. the document describes a RSA key, while an ed25519 key was expected.
162    #[error("Algorithm OID does not match ed25519, expected {expected}, found {found}")]
163    Oid {
164        /// The expected OID.
165        expected: pkcs8::ObjectIdentifier,
166        /// The OID that was found instead.
167        found: pkcs8::ObjectIdentifier,
168    },
169
170    /// For when [`ed25519_dalek`] cannot parse a secret/private key.
171    #[error("Could not parse secret key")]
172    SecretKey,
173
174    /// For when [`ed25519_dalek`] cannot parse a public key.
175    #[error("Could not parse public key: {0}")]
176    PublicKey(#[source] ed25519_dalek::SignatureError),
177
178    /// For when [`ed25519_dalek`] cannot parse a signature.
179    #[error("Could not parse signature: {0}")]
180    Signature(#[source] ed25519_dalek::SignatureError),
181
182    /// For when parsing base64 gives an error.
183    #[error("Could not parse {of_type} base64 string {string:?}: {source}")]
184    Base64 {
185        /// The "type"/name of the base64 string
186        of_type: String,
187        /// The string itself.
188        string: String,
189        /// The originating error.
190        #[source]
191        source: Base64DecodeError,
192    },
193}
194
195impl ParseError {
196    pub(crate) fn from_event_id_by_room_version(
197        event_id: &EventId,
198        room_version: &RoomVersionId,
199    ) -> Error {
200        Self::ServerNameFromEventIdByRoomVersion(event_id.to_owned(), room_version.clone()).into()
201    }
202
203    pub(crate) fn derived_vs_parsed_mismatch<P: Into<Vec<u8>>, D: Into<Vec<u8>>>(
204        parsed: P,
205        derived: D,
206    ) -> Error {
207        Self::DerivedPublicKeyDoesNotMatchParsedKey {
208            parsed_key: parsed.into(),
209            derived_key: derived.into(),
210        }
211        .into()
212    }
213
214    pub(crate) fn base64<T1: Into<String>, T2: Into<String>>(
215        of_type: T1,
216        string: T2,
217        source: Base64DecodeError,
218    ) -> Error {
219        Self::Base64 { of_type: of_type.into(), string: string.into(), source }.into()
220    }
221}