1#[derive(Debug, thiserror::Error)]
18pub enum TrustError {
19 #[error("certificate generation failed: {reason}")]
21 CertificateGeneration {
22 reason: String,
24 },
25
26 #[error("certificate parsing failed: {reason}")]
28 CertificateParsing {
29 reason: String,
31 },
32
33 #[error("certificate verification failed: {reason}")]
35 CertificateVerification {
36 reason: String,
38 },
39
40 #[error("certificate revocation failed: {reason}")]
48 CertificateRevocation {
49 reason: String,
51 },
52
53 #[error("merkle tree operation failed: {reason}")]
55 MerkleTree {
56 reason: String,
58 },
59
60 #[error("seal failed: {reason}")]
62 Seal {
63 reason: String,
65 },
66
67 #[error("unseal failed")]
70 UnsealFailed,
71
72 #[error("attestation verification failed")]
75 AttestationFailed,
76
77 #[error("key management failed: {reason}")]
80 KeyManagement {
81 reason: String,
83 },
84
85 #[error("signing failed: {reason}")]
93 Signing {
94 reason: String,
96 },
97
98 #[error("invalid signature")]
107 InvalidSignature,
108
109 #[error("checkpoint encoding failed: {reason}")]
112 CheckpointEncoding {
113 reason: String,
115 },
116
117 #[error("checkpoint parsing failed: {reason}")]
121 CheckpointParsing {
122 reason: String,
124 },
125
126 #[error("invalid note verifier key: {reason}")]
129 VerifierKey {
130 reason: String,
132 },
133
134 #[error("note verification failed")]
138 NoteVerification,
139
140 #[error("log artifact encoding failed: {reason}")]
143 LogArtifactEncoding {
144 reason: String,
146 },
147
148 #[error("log artifact verification failed")]
152 LogArtifactVerification,
153}
154
155pub type TrustResult<T> = std::result::Result<T, TrustError>;
157
158#[cfg(test)]
159#[allow(clippy::unwrap_used, clippy::expect_used, clippy::panic)]
160mod tests {
161 use super::*;
162
163 #[test]
164 fn display_certificate_generation() {
165 let err = TrustError::CertificateGeneration {
166 reason: "rcgen rejected params".to_string(),
167 };
168 let display = err.to_string();
169 assert!(
170 display.contains("certificate generation failed"),
171 "got: {display}"
172 );
173 assert!(display.contains("rcgen rejected params"), "got: {display}");
174 }
175
176 #[test]
177 fn display_certificate_parsing() {
178 let err = TrustError::CertificateParsing {
179 reason: "malformed DER".to_string(),
180 };
181 let display = err.to_string();
182 assert!(
183 display.contains("certificate parsing failed"),
184 "got: {display}"
185 );
186 assert!(display.contains("malformed DER"), "got: {display}");
187 }
188
189 #[test]
190 fn display_certificate_verification() {
191 let err = TrustError::CertificateVerification {
192 reason: "issuer mismatch".to_string(),
193 };
194 let display = err.to_string();
195 assert!(
196 display.contains("certificate verification failed"),
197 "got: {display}"
198 );
199 assert!(display.contains("issuer mismatch"), "got: {display}");
200 }
201
202 #[test]
203 fn display_certificate_revocation() {
204 let err = TrustError::CertificateRevocation {
205 reason: "unknown fingerprint".to_string(),
206 };
207 let display = err.to_string();
208 assert!(
209 display.contains("certificate revocation failed"),
210 "got: {display}"
211 );
212 assert!(display.contains("unknown fingerprint"), "got: {display}");
213 }
214
215 #[test]
216 fn display_merkle_tree() {
217 let err = TrustError::MerkleTree {
218 reason: "index out of range".to_string(),
219 };
220 let display = err.to_string();
221 assert!(
222 display.contains("merkle tree operation failed"),
223 "got: {display}"
224 );
225 assert!(display.contains("index out of range"), "got: {display}");
226 }
227
228 #[test]
229 fn display_seal() {
230 let err = TrustError::Seal {
231 reason: "HKDF expand failed".to_string(),
232 };
233 let display = err.to_string();
234 assert!(display.contains("seal failed"), "got: {display}");
235 assert!(display.contains("HKDF expand failed"), "got: {display}");
236 }
237
238 #[test]
239 fn display_key_management() {
240 let err = TrustError::KeyManagement {
241 reason: "identity key file has invalid length".to_string(),
242 };
243 let display = err.to_string();
244 assert!(display.contains("key management failed"), "got: {display}");
245 assert!(
246 display.contains("identity key file has invalid length"),
247 "got: {display}"
248 );
249 }
250
251 #[test]
252 fn display_signing() {
253 let err = TrustError::Signing {
254 reason: "no signing key configured".to_string(),
255 };
256 let display = err.to_string();
257 assert!(display.contains("signing failed"), "got: {display}");
258 assert!(
259 display.contains("no signing key configured"),
260 "got: {display}"
261 );
262 }
263
264 #[test]
265 fn display_unseal_failed() {
266 let err = TrustError::UnsealFailed;
267 let display = err.to_string();
268 assert!(display.contains("unseal failed"), "got: {display}");
269 }
270
271 #[test]
272 fn display_attestation_failed() {
273 let err = TrustError::AttestationFailed;
274 let display = err.to_string();
275 assert!(
276 display.contains("attestation verification failed"),
277 "got: {display}"
278 );
279 }
280
281 #[test]
282 fn display_invalid_signature() {
283 let err = TrustError::InvalidSignature;
284 let display = err.to_string();
285 assert!(display.contains("invalid signature"), "got: {display}");
286 }
287
288 #[test]
289 fn display_checkpoint_encoding() {
290 let err = TrustError::CheckpointEncoding {
291 reason: "origin contains '+'".to_string(),
292 };
293 let display = err.to_string();
294 assert!(
295 display.contains("checkpoint encoding failed"),
296 "got: {display}"
297 );
298 assert!(display.contains("origin contains '+'"), "got: {display}");
299 }
300
301 #[test]
302 fn display_checkpoint_parsing() {
303 let err = TrustError::CheckpointParsing {
304 reason: "tree size has a leading zero".to_string(),
305 };
306 let display = err.to_string();
307 assert!(
308 display.contains("checkpoint parsing failed"),
309 "got: {display}"
310 );
311 assert!(
312 display.contains("tree size has a leading zero"),
313 "got: {display}"
314 );
315 }
316
317 #[test]
318 fn display_verifier_key() {
319 let err = TrustError::VerifierKey {
320 reason: "declared key ID does not match".to_string(),
321 };
322 let display = err.to_string();
323 assert!(
324 display.contains("invalid note verifier key"),
325 "got: {display}"
326 );
327 assert!(
328 display.contains("declared key ID does not match"),
329 "got: {display}"
330 );
331 }
332
333 #[test]
337 fn note_verification_display_is_single_and_generic() {
338 let display = TrustError::NoteVerification.to_string();
339 assert_eq!(display, "note verification failed");
340 for oracle_word in ["signature", "key", "envelope", "structure", "base64"] {
341 assert!(
342 !display.contains(oracle_word),
343 "non-oracle message must not mention {oracle_word}: {display}"
344 );
345 }
346 }
347
348 #[test]
349 fn display_log_artifact_encoding() {
350 let err = TrustError::LogArtifactEncoding {
351 reason: "tree size exceeds the JSON-safe bound".to_string(),
352 };
353 let display = err.to_string();
354 assert!(
355 display.contains("log artifact encoding failed"),
356 "got: {display}"
357 );
358 assert!(
359 display.contains("tree size exceeds the JSON-safe bound"),
360 "got: {display}"
361 );
362 }
363
364 #[test]
368 fn log_artifact_verification_display_is_single_and_generic() {
369 let display = TrustError::LogArtifactVerification.to_string();
370 assert_eq!(display, "log artifact verification failed");
371 for oracle_word in ["signature", "checkpoint", "root", "size", "hash", "format"] {
372 assert!(
373 !display.contains(oracle_word),
374 "non-oracle message must not mention {oracle_word}: {display}"
375 );
376 }
377 }
378
379 #[test]
380 fn trust_result_alias_accepts_ok_and_err() {
381 let ok: TrustResult<u8> = Ok(7);
382 let err: TrustResult<u8> = Err(TrustError::InvalidSignature);
383 assert!(ok.is_ok());
384 assert!(err.is_err());
385 }
386}