1use ruma_common::{
2 canonical_json::{JsonType, RedactionError},
3 serde::Base64DecodeError,
4 EventId, OwnedEventId, RoomVersionId,
5};
6use thiserror::Error;
7
8#[derive(Debug, Error)]
10#[non_exhaustive]
11#[allow(clippy::enum_variant_names)]
12pub enum Error {
13 #[error("JSON error: {0}")]
15 Json(#[from] JsonError),
16
17 #[error("Verification error: {0}")]
19 Verification(#[from] VerificationError),
20
21 #[error("Parse error: {0}")]
23 Parse(#[from] ParseError),
24
25 #[error("DER Parse error: {0}")]
27 DerParse(pkcs8::Error),
28
29 #[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#[derive(Debug, Error)]
51#[non_exhaustive]
52pub enum JsonError {
53 #[error("Value in {target:?} must be a JSON {of_type:?}")]
55 NotOfType {
56 target: String,
58 of_type: JsonType,
60 },
61
62 #[error("Values in {target:?} must be JSON {of_type:?}s")]
65 NotMultiplesOfType {
66 target: String,
69 of_type: JsonType,
71 },
72
73 #[error("JSON object must contain the field {0:?}")]
75 JsonFieldMissingFromObject(String),
76
77 #[error(transparent)]
79 Serde(#[from] serde_json::Error),
80}
81
82impl 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#[derive(Debug, Error)]
99#[non_exhaustive]
100pub enum VerificationError {
101 #[error("signature uses an unsupported algorithm")]
103 UnsupportedAlgorithm,
104
105 #[error("Could not find signatures for entity {0:?}")]
107 NoSignaturesForEntity(String),
108
109 #[error("Could not find public keys for entity {0:?}")]
111 NoPublicKeysForEntity(String),
112
113 #[error("Could not find public key {key_id:?} for entity {entity:?}")]
115 PublicKeyNotFound {
116 entity: String,
118
119 key_id: String,
121 },
122
123 #[error("Could not find supported signature for entity {0:?}")]
125 NoSupportedSignatureForEntity(String),
126
127 #[error("Could not verify signature: {0}")]
129 Signature(#[source] ed25519_dalek::SignatureError),
130}
131
132#[derive(Debug, Error)]
134#[non_exhaustive]
135pub enum ParseError {
136 #[error("Could not parse User ID: {0}")]
138 UserId(#[source] ruma_common::IdParseError),
139
140 #[error("Could not parse Event ID: {0}")]
142 EventId(#[source] ruma_common::IdParseError),
143
144 #[error("Event Id {0:?} should have a server name for the given room version {1:?}")]
147 ServerNameFromEventIdByRoomVersion(OwnedEventId, RoomVersionId),
148
149 #[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 parsed_key: Vec<u8>,
155 derived_key: Vec<u8>,
157 },
158
159 #[error("Algorithm OID does not match ed25519, expected {expected}, found {found}")]
163 Oid {
164 expected: pkcs8::ObjectIdentifier,
166 found: pkcs8::ObjectIdentifier,
168 },
169
170 #[error("Could not parse secret key")]
172 SecretKey,
173
174 #[error("Could not parse public key: {0}")]
176 PublicKey(#[source] ed25519_dalek::SignatureError),
177
178 #[error("Could not parse signature: {0}")]
180 Signature(#[source] ed25519_dalek::SignatureError),
181
182 #[error("Could not parse {of_type} base64 string {string:?}: {source}")]
184 Base64 {
185 of_type: String,
187 string: String,
189 #[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}