spiffe/svid/x509/
mod.rs

1//! X.509-SVID types.
2
3mod validations;
4
5use crate::cert::errors::{CertificateError, PrivateKeyError};
6use crate::cert::parsing::to_certificate_vec;
7use crate::cert::{Certificate, PrivateKey};
8use crate::spiffe_id::{SpiffeId, SpiffeIdError};
9use crate::svid::x509::validations::{validate_leaf_certificate, validate_signing_certificates};
10use crate::svid::Svid;
11use std::convert::TryFrom;
12
13/// This type represents a [SPIFFE X509-SVID](https://github.com/spiffe/spiffe/blob/main/standards/X509-SVID.md).
14///
15/// Contains a [`SpiffeId`], a certificate chain as a vec of DER-encoded X.509 certificates,
16/// and a private key as a DER-encoded ASN.1 in PKCS#8 format.
17#[derive(Debug, Clone, Eq, PartialEq)]
18pub struct X509Svid {
19    spiffe_id: SpiffeId,
20    cert_chain: Vec<Certificate>,
21    private_key: PrivateKey,
22}
23
24impl Svid for X509Svid {}
25
26/// An error that may arise trying to parse a [`X509Svid`] from a `DER` encoded
27/// chain of certificates and private key.
28#[derive(Debug, thiserror::Error, PartialEq)]
29#[non_exhaustive]
30pub enum X509SvidError {
31    /// The chain of certificates is empty.
32    #[error("no certificates found in chain")]
33    EmptyChain,
34
35    /// 'CA' flag not allowed in leaf certificate.
36    #[error("leaf certificate must not have CA flag set to true")]
37    LeafCertificateHasCaFlag,
38
39    /// 'cRLSign' not allowed as key usage in leaf certificate.
40    #[error("leaf certificate must not have 'cRLSign' set as key usage")]
41    LeafCertificateHasCrlSign,
42
43    /// 'keyCertSign' not allowed as key usage in leaf certificate.
44    #[error("leaf certificate must not have 'keyCertSign' set as key usage")]
45    LeafCertificateHasKeyCertSign,
46
47    /// 'digitalSignature' as key usage must be present in leaf certificate.
48    #[error("leaf certificate must have 'digitalSignature' set as key usage")]
49    LeafCertificatedNoDigitalSignature,
50
51    /// 'CA' flag must be set in intermediate certificate.
52    #[error("signing certificate must have CA flag set to true")]
53    SigningCertificatedNoCa,
54
55    /// 'keyCertSign' as key usage must be present in intermediate certificate.
56    #[error("signing certificate must have 'keyCertSign' set as key usage")]
57    SigningCertificatedNoKeyCertSign,
58
59    /// No URI Subject Alternative Names found.
60    #[error("leaf certificate misses the SPIFFE-ID in the URI SAN")]
61    MissingSpiffeId,
62
63    /// The URI Subject Alternative Name is not a valid SPIFFE ID.
64    #[error("failed parsing SPIFFE ID from certificate URI SAN")]
65    InvalidSpiffeId(#[from] SpiffeIdError),
66
67    /// Error processing or validating the X.509 certificates.
68    #[error(transparent)]
69    Certificate(#[from] CertificateError),
70
71    /// Error processing the private key.
72    #[error(transparent)]
73    PrivateKey(#[from] PrivateKeyError),
74}
75
76impl X509Svid {
77    /// Creates a `X509Svid` from certificate chain and key ASN.1 DER-encoded data (binary format).
78    ///
79    /// # Arguments
80    ///
81    /// * `cert_chain_der` - Slice of bytes representing a chain of certificates as ASN.1 DER-encoded (concatenated
82    ///   with no intermediate padding if there are more than one certificate).
83    ///
84    /// * `private_key_der` - Slice of bytes representing a private key as ASN.1 DER in PKCS#8 format.
85    ///
86    /// # Errors
87    ///
88    /// If the function cannot parse the inputs, a [`X509SvidError`] variant will be returned.
89    pub fn parse_from_der(
90        cert_chain_der: &[u8],
91        private_key_der: &[u8],
92    ) -> Result<Self, X509SvidError> {
93        let cert_chain = to_certificate_vec(cert_chain_der)?;
94
95        let leaf = match cert_chain.first() {
96            None => return Err(X509SvidError::EmptyChain),
97            Some(c) => c,
98        };
99
100        let spiffe_id = validate_leaf_certificate(leaf)?;
101        validate_signing_certificates(&cert_chain[1..])?;
102        let private_key = PrivateKey::try_from(private_key_der)?;
103
104        Ok(X509Svid {
105            spiffe_id,
106            cert_chain,
107            private_key,
108        })
109    }
110
111    /// Returns the [`SpiffeId`] of the `X509Svid`.
112    pub fn spiffe_id(&self) -> &SpiffeId {
113        &self.spiffe_id
114    }
115
116    /// Returns the chain of [`Certificate`] of the `X509Svid`. The first certificate in the
117    /// chain is the leaf certificate.
118    pub fn cert_chain(&self) -> &Vec<Certificate> {
119        &self.cert_chain
120    }
121
122    /// Returns the leaf certificate of the chain.
123    pub fn leaf(&self) -> &Certificate {
124        &self.cert_chain[0]
125    }
126
127    /// Returns the private key of the `X509Svid`.
128    pub fn private_key(&self) -> &PrivateKey {
129        &self.private_key
130    }
131}