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}