x509_ocsp/
request.rs

1//! OCSP Request
2
3use crate::{ext::Nonce, CertId, Version};
4use alloc::vec::Vec;
5use const_oid::db::rfc6960::ID_PKIX_OCSP_NONCE;
6use core::{default::Default, option::Option};
7use der::{asn1::BitString, Decode, Sequence};
8use spki::AlgorithmIdentifierOwned;
9use x509_cert::{
10    certificate::Certificate,
11    ext::{pkix::name::GeneralName, Extensions},
12};
13
14/// OCSPRequest structure as defined in [RFC 6960 Section 4.1.1].
15///
16/// ```text
17/// OCSPRequest ::= SEQUENCE {
18///    tbsRequest              TBSRequest,
19///    optionalSignature   [0] EXPLICIT Signature OPTIONAL }
20/// ```
21///
22/// [RFC 6960 Section 4.1.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.1.1
23#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
24#[allow(missing_docs)]
25pub struct OcspRequest {
26    pub tbs_request: TbsRequest,
27
28    #[asn1(context_specific = "0", optional = "true", tag_mode = "EXPLICIT")]
29    pub optional_signature: Option<Signature>,
30}
31
32impl OcspRequest {
33    /// Returns the request's nonce value, if any. This method will return `None` if the request
34    /// has no `Nonce` extension or decoding of the `Nonce` extension fails.
35    pub fn nonce(&self) -> Option<Nonce> {
36        self.tbs_request.nonce()
37    }
38}
39
40/// TBSRequest structure as defined in [RFC 6960 Section 4.1.1].
41///
42/// ```text
43/// TBSRequest ::= SEQUENCE {
44///    version             [0] EXPLICIT Version DEFAULT v1,
45///    requestorName       [1] EXPLICIT GeneralName OPTIONAL,
46///    requestList             SEQUENCE OF Request,
47///    requestExtensions   [2] EXPLICIT Extensions OPTIONAL }
48/// ```
49///
50/// [RFC 6960 Section 4.1.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.1.1
51#[derive(Clone, Debug, Default, Eq, PartialEq, Sequence)]
52#[allow(missing_docs)]
53pub struct TbsRequest {
54    #[asn1(
55        context_specific = "0",
56        default = "Default::default",
57        tag_mode = "EXPLICIT"
58    )]
59    pub version: Version,
60
61    #[asn1(context_specific = "1", optional = "true", tag_mode = "EXPLICIT")]
62    pub requestor_name: Option<GeneralName>,
63
64    pub request_list: Vec<Request>,
65
66    #[asn1(context_specific = "2", optional = "true", tag_mode = "EXPLICIT")]
67    pub request_extensions: Option<Extensions>,
68}
69
70impl TbsRequest {
71    /// Returns the request's nonce value, if any. This method will return `None` if the request
72    /// has no `Nonce` extension or decoding of the `Nonce` extension fails.
73    pub fn nonce(&self) -> Option<Nonce> {
74        match &self.request_extensions {
75            Some(extns) => {
76                let mut filter = extns.iter().filter(|e| e.extn_id == ID_PKIX_OCSP_NONCE);
77                match filter.next() {
78                    Some(extn) => Nonce::from_der(extn.extn_value.as_bytes()).ok(),
79                    None => None,
80                }
81            }
82            None => None,
83        }
84    }
85}
86
87/// Signature structure as defined in [RFC 6960 Section 4.1.1].
88///
89/// ```text
90/// Signature ::= SEQUENCE {
91///    signatureAlgorithm      AlgorithmIdentifier,
92///    signature               BIT STRING,
93///    certs                  [0] EXPLICIT SEQUENCE OF Certificate OPTIONAL }
94/// ```
95///
96/// [RFC 6960 Section 4.1.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.1.1
97#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
98#[allow(missing_docs)]
99pub struct Signature {
100    pub signature_algorithm: AlgorithmIdentifierOwned,
101    pub signature: BitString,
102
103    #[asn1(context_specific = "0", optional = "true", tag_mode = "EXPLICIT")]
104    pub certs: Option<Vec<Certificate>>,
105}
106
107/// Request structure as defined in [RFC 6960 Section 4.1.1].
108///
109/// ```text
110/// Request ::= SEQUENCE {
111///    reqCert                     CertID,
112///    singleRequestExtensions     [0] EXPLICIT Extensions OPTIONAL }
113/// ```
114///
115/// [RFC 6960 Section 4.1.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.1.1
116#[derive(Clone, Debug, Eq, PartialEq, Sequence)]
117#[allow(missing_docs)]
118pub struct Request {
119    pub req_cert: CertId,
120
121    #[asn1(context_specific = "0", optional = "true", tag_mode = "EXPLICIT")]
122    pub single_request_extensions: Option<Extensions>,
123}
124
125#[cfg(feature = "builder")]
126mod builder {
127    use crate::{builder::Error, CertId, Request};
128    use const_oid::AssociatedOid;
129    use digest::Digest;
130    use x509_cert::{ext::AsExtension, name::Name, serial_number::SerialNumber, Certificate};
131
132    impl Request {
133        /// Returns a new `Request` with the specified `CertID`
134        pub fn new(req_cert: CertId) -> Self {
135            Self {
136                req_cert,
137                single_request_extensions: None,
138            }
139        }
140
141        /// Generates a `CertID` by running the issuer's subject and key through the specified
142        /// [`Digest`].
143        ///
144        /// [RFC 6960 Section 4.1.1]
145        ///
146        /// [RFC 6960 Section 4.1.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.1.1
147        pub fn from_issuer<D>(
148            issuer: &Certificate,
149            serial_number: SerialNumber,
150        ) -> Result<Self, Error>
151        where
152            D: Digest + AssociatedOid,
153        {
154            Ok(Self::new(CertId::from_issuer::<D>(issuer, serial_number)?))
155        }
156
157        /// Generates a `CertID` by running the issuer's subject and key through the specified
158        /// [`Digest`] and pulls the serial from `cert`. This does not ensure that `cert` is actually
159        /// issued by `issuer`.
160        ///
161        /// [RFC 6960 Section 4.1.1]
162        ///
163        /// [RFC 6960 Section 4.1.1]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.1.1
164        pub fn from_cert<D>(issuer: &Certificate, cert: &Certificate) -> Result<Self, Error>
165        where
166            D: Digest + AssociatedOid,
167        {
168            Ok(Self::new(CertId::from_cert::<D>(issuer, cert)?))
169        }
170
171        /// Adds a single request extension as specified in [RFC 6960 Section 4.4]. Errors when the
172        /// extension encoding fails.
173        ///
174        /// [RFC 6960 Section 4.4]: https://datatracker.ietf.org/doc/html/rfc6960#section-4.4
175        pub fn with_extension(mut self, ext: impl AsExtension) -> Result<Self, Error> {
176            let ext = ext.to_extension(&Name::default(), &[])?;
177            match self.single_request_extensions {
178                Some(ref mut exts) => exts.push(ext),
179                None => self.single_request_extensions = Some(alloc::vec![ext]),
180            }
181            Ok(self)
182        }
183    }
184}