attestation_doc_validation/
error.rs

1//! Module for categorizing errors returned during attestation
2use thiserror::Error;
3
4use crate::{nsm::error::NsmError as InnerNsm, time};
5
6/// Generic Result type for the top level functions of the library
7pub type AttestResult<T> = Result<T, AttestError>;
8/// Generic Result type for the attestation doc module
9pub type AttestationResult<T> = Result<T, AttestationError>;
10/// Generic Result type for the cert module
11pub type CertResult<T> = Result<T, CertError>;
12
13/// Top level wrapper to show which step in the attesation process failed.
14#[allow(clippy::module_name_repetitions)]
15#[derive(Error, Debug)]
16pub enum AttestError
17where
18    Self: Send + Sync,
19{
20    #[error("An error occurred while attesting the connection received: {0}")]
21    AttestationError(#[from] AttestationError),
22    #[error("An error occurred while validating the TLS Certificate received: {0}")]
23    CertError(#[from] CertError),
24    #[error("An error occurred interfacing with the Nitro Security Module: {0}")]
25    NsmError(#[from] InnerNsm),
26    #[error("An error occured decoding the public key from the attestation doc's userdata")]
27    DecodeError(#[from] base64::DecodeError),
28    #[error("An error occured parsing the expiry date from the attestation doc's userdata")]
29    DateParseError(#[from] chrono::ParseError),
30}
31
32/// Wrapping type to record the specific error that occurred while validating the attestation document.
33#[allow(clippy::module_name_repetitions)]
34#[derive(Error, Debug)]
35pub enum AttestationError
36where
37    Self: Send + Sync,
38{
39    #[error("COSE error: `{0}`")]
40    InvalidCose(String),
41    #[error(transparent)]
42    InvalidCbor(#[from] serde_cbor::error::Error),
43    #[error("A part of the attestation doc structure was deemed invalid")]
44    DocStructureInvalid,
45    #[error("The COSE signature does not match the public key provided in the attestation doc")]
46    InvalidCoseSignature,
47    #[error(
48        "The PCRs found were different to the expected values.\n\nExpected:\n{0}\n\nReceived:\n{1}"
49    )]
50    UnexpectedPCRs(String, String),
51    #[error("PCR{0} was missing in the attestation doc")]
52    MissingPCR(usize),
53    #[error("User data was not set in the attestation doc")]
54    MissingUserData,
55    #[error("User data in attestation doc did not contain the certificate public key")]
56    UserDataMismatch,
57    #[error("Nonce in the attestation doc did not match the nonce provided,\n\nExpected: {expected}\nReceived: {received:?}")]
58    NonceMismatch {
59        expected: String,
60        received: Option<String>,
61    },
62    #[error("The module id was missing from the attestation doc")]
63    MissingModuleId,
64    #[error("The digest in the attestation was not SHA384")]
65    DigestAlgorithmInvalid,
66    #[error("The PCRs in the attestation doc were invalid")]
67    InvalidPCRs,
68    #[error("The CA bundle length in the attestation doc was invalid")]
69    InvalidCABundle,
70    #[error("The public key length in the attestation doc was invalid")]
71    InvalidPublicKey,
72    #[error("The nonce length in the attestation doc was invalid")]
73    InvalidNonce,
74    #[error("The user data length in the attestation doc was invalid")]
75    InvalidUserData,
76    #[error("The supplied attestation doc has expired")]
77    ExpiredDocument,
78}
79
80/// Wrapping type to record the specific error that occurred while validating the TLS Cert.
81#[allow(clippy::module_name_repetitions)]
82#[derive(Error, Debug)]
83pub enum CertError
84where
85    Self: Send + Sync,
86{
87    // Webpki errors don't implement stderr, so must be serialized before wrapping in custom err.
88    #[error("Failed to validate the trust chain for the provided cert — {0}")]
89    InvalidTrustChain(String),
90    #[error("The certificate in the attestation doc was detected as not having the NSM as root")]
91    UntrustedCert,
92    #[error("The received certificate had no Subject Alt Name extension")]
93    NoSubjectAltNames,
94    #[error("Attempts to parse certificate from PEM and DER encoding failed")]
95    DecodeError,
96    #[error("Unable to parse attestation doc bytes from Subject Alt Name extension")]
97    ParseError,
98    #[error(transparent)]
99    HexError(#[from] hex::FromHexError),
100    #[error(transparent)]
101    TimeError(#[from] time::Error),
102    #[error("Failed to parse cert from pem encoding")]
103    PemError(#[from] x509_parser::error::PEMError),
104    #[error("Failed to parse x509 cert from pem encoding")]
105    X509Error,
106    #[error("No cert given")]
107    NoCertGiven,
108}
109
110impl std::convert::From<webpki::Error> for CertError {
111    fn from(value: webpki::Error) -> Self {
112        Self::InvalidTrustChain(value.to_string())
113    }
114}