aitp_tct/error.rs
1//! TCT-specific error type.
2
3/// Errors from TCT issuance and verification.
4#[derive(Debug, thiserror::Error)]
5#[non_exhaustive]
6pub enum TctError {
7 /// Version is not supported by this implementation.
8 #[error("TCT version is not supported")]
9 VersionUnknown,
10 /// Signature did not verify against issuer's public key.
11 #[error("TCT signature is invalid")]
12 SignatureInvalid,
13 /// The verifying key supplied by the caller does not correspond to
14 /// the key embedded in `tct.issuer`. RFC-AITP-0008 §3.3 requires
15 /// verifiers to establish this issuer-key binding before consulting
16 /// any revocation source; without it `tct.issuer` stays
17 /// attacker-controlled even after a valid signature, enabling
18 /// revocation evasion and steering of per-issuer revocation lookups.
19 #[error("TCT issuer does not match the verifying key")]
20 IssuerMismatch,
21 /// `audience` did not equal expected audience or did not equal subject.
22 #[error("TCT audience does not match")]
23 AudienceMismatch,
24 /// `expires_at` is in the past, or `issued_at` is in the future.
25 #[error("TCT has expired or is not yet valid")]
26 Expired,
27 /// `expires_at` exceeds the issuer Manifest's `expires_at`.
28 /// RFC-AITP-0004 §4.3 / RFC-AITP-0005 §9: a peer-issued TCT MUST
29 /// NOT outlive the issuer's published Manifest. Verifiers that
30 /// have resolved the issuer's Manifest MUST reject TCTs whose
31 /// `expires_at` exceeds the Manifest's.
32 #[error("TCT expires_at exceeds issuer Manifest expires_at")]
33 ExpiresAfterManifest,
34 /// `jti` appears in the issuer's deny list.
35 #[error("TCT jti is revoked")]
36 Revoked,
37 /// `grants` is empty (forbidden by RFC-AITP-0004 §4.1).
38 #[error("TCT grants must be non-empty")]
39 EmptyGrants,
40 /// One or more grant strings contain whitespace
41 /// (forbidden by RFC-AITP-0005 §4.2).
42 #[error("TCT grant must not contain whitespace: `{0}`")]
43 GrantWhitespace(String),
44 /// `cnf.jkt` does not equal the RFC 7638 thumbprint of the key
45 /// encoded in the subject AID (RFC-AITP-0005 §3).
46 #[error("TCT cnf.jkt does not match the subject key")]
47 CnfMalformed,
48 /// Decoded JWS payload did not deserialize as the artifact's claims
49 /// object — unknown claim outside `ext`, duplicate claim, missing
50 /// required claim, or a type mismatch (RFC-AITP-0001 §5.4.5 strict
51 /// parsing).
52 #[error("claims malformed: {0}")]
53 ClaimsMalformed(String),
54 /// Builder was missing a required field.
55 #[error("missing required field: {0}")]
56 MissingField(&'static str),
57 /// Canonicalization failed.
58 #[error("canonicalization failed: {0}")]
59 Canonicalization(String),
60 /// PoP nonce echo mismatch (RFC-AITP-0005 §6.2 step 2).
61 #[error("PoP nonce echo mismatch")]
62 PopNonceMismatch,
63 /// PoP signature failed verification.
64 #[error("PoP signature failed")]
65 PopFailed,
66 /// PoP challenge expired.
67 #[error("PoP challenge expired")]
68 PopChallengeExpired,
69 /// PoP response references a different jti than the challenge.
70 #[error("PoP response jti mismatch")]
71 PopJtiMismatch,
72 /// Crypto error.
73 #[error(transparent)]
74 Crypto(#[from] aitp_crypto::CryptoError),
75}