Skip to main content

cratestack_cose/claims/
error.rs

1//! Why a claim object was not signed or opened.
2
3use cratestack_core::CratestackError;
4use thiserror::Error;
5
6use crate::error::UNAUTHENTICATED;
7
8/// A failure of [`sign_claims`](crate::sign_claims) or
9/// [`open_claims`](crate::open_claims).
10///
11/// The variants a verifier can reach carry nothing about the bytes it was
12/// given, so a caller that forwards the error to the peer leaks nothing
13/// beyond the variant (`Unverified` covers an unknown `kid` and a bad
14/// signature alike). [`into_error`](Self::into_error) maps them onto the
15/// envelope's `401` / `500` split.
16///
17/// `#[non_exhaustive]`: match with a wildcard arm.
18#[derive(Debug, Error)]
19#[non_exhaustive]
20pub enum ClaimsError {
21    /// Not a canonical, tagged `COSE_Sign1` of the claim-object profile: a
22    /// wrong tag, a non-minimal or indefinite encoding, an unknown or
23    /// out-of-order header label, a non-empty unprotected header, a detached
24    /// payload, a missing `typ`, a MAC algorithm, trailing bytes, and so on.
25    /// A transport envelope presented here ends up in this variant.
26    #[error("not a canonical claim object")]
27    Malformed,
28    /// A well-formed claim object whose `typ` is not the one expected.
29    #[error("claim object has an unexpected type")]
30    WrongType,
31    /// No key the resolver returned verified the signature. An unknown `kid`
32    /// is this too: the two are deliberately not told apart.
33    #[error("claim object signature did not verify")]
34    Unverified,
35    /// The key resolver failed (an outage, not a verdict on the object).
36    #[error("claim key resolver unavailable")]
37    Resolver(#[source] CratestackError),
38    /// The signer failed (an outage, not a verdict on the inputs).
39    #[error("claim signer failed")]
40    Signer(#[source] CratestackError),
41    /// The caller's inputs or signer are wrong, whatever the message: a MAC
42    /// signer, a `kid` that is not 8 bytes, an empty or oversized `typ`,
43    /// `aud` or `cti`, or a signature of the wrong length.
44    #[error("claim object misuse: {0}")]
45    Misuse(&'static str),
46}
47
48impl ClaimsError {
49    /// The envelope's mapping (ADR 0006 ยง10): a verdict on the object is
50    /// `Unauthorized` carrying the one fixed message, a backend failure or
51    /// local misuse is `Internal`. A method, not a `From` impl: a second
52    /// `From<_> for CratestackError` in a graph makes inference ambiguous
53    /// (see `crate::error`).
54    pub fn into_error(self) -> CratestackError {
55        match self {
56            Self::Malformed | Self::WrongType | Self::Unverified => {
57                CratestackError::Unauthorized(UNAUTHENTICATED.to_owned())
58            }
59            other => CratestackError::Internal(format!("cose claims: {other}")),
60        }
61    }
62}