huskarl_core/crypto/cipher/error.rs
1use snafu::Snafu;
2
3use crate::error::Error;
4
5/// Errors that could occur during AEAD decryption.
6///
7/// The variants are load-bearing control flow between decryptor layers:
8/// [`NoMatchingKey`](Self::NoMatchingKey) drives the refresh-and-retry loop
9/// in [`RetryingDecryptor`](super::RetryingDecryptor) and candidate dispatch
10/// in [`MultiKeyDecryptor`](super::MultiKeyDecryptor) — the cipher analogue
11/// of [`VerifyError`](crate::crypto::verifier::VerifyError). Only its
12/// `Other` source is the concrete [`Error`].
13#[non_exhaustive]
14#[derive(Debug, Snafu)]
15pub enum DecryptError {
16 /// No key matched the requested algorithm/kid criteria — decryption was
17 /// not attempted.
18 #[snafu(display("no matching key"))]
19 NoMatchingKey,
20 /// Other kinds of errors that could occur during decryption, including
21 /// authentication failure.
22 #[snafu(transparent)]
23 Other {
24 /// The underlying error.
25 source: Error,
26 },
27}
28
29impl DecryptError {
30 /// If true, a failed decryption may succeed if retried.
31 #[must_use]
32 pub fn is_retryable(&self) -> bool {
33 match self {
34 DecryptError::NoMatchingKey => false,
35 DecryptError::Other { source } => source.is_retryable(),
36 }
37 }
38}
39
40/// Errors that could occur during AEAD unsealing.
41///
42/// Used as the source of [`ErrorKind::Crypto`](crate::error::ErrorKind::Crypto)
43/// errors — cipher implementations construct these to describe *why* an
44/// unseal failed without expanding the kind-level vocabulary.
45///
46/// This covers only failures the framing layer itself detects. An
47/// authentication-tag mismatch is raised by the inner
48/// [`AeadDecryptor`](super::AeadDecryptor) and flows through as
49/// [`DecryptError::Other`], not as an `UnsealError`.
50#[non_exhaustive]
51#[derive(Debug, Snafu)]
52pub enum UnsealError {
53 /// The bundle is malformed or uses an unsupported version.
54 #[snafu(display("invalid bundle"))]
55 InvalidBundle,
56}