Skip to main content

structured_pkix/
ocsp.rs

1//! OCSP request and response evidence over original caller-supplied DER ranges.
2//!
3//! Decoding does not authenticate a responder, validate a request binding or
4//! establish certificate status. No transport, clock or trust discovery occurs.
5
6use crate::algorithm::{self, AlgorithmIdentifier};
7use crate::error::{Error, ErrorCode, Located, Result};
8use crate::extension::{self, Extensions};
9use crate::name::{self, Name};
10use crate::{Certificate, Time, oid, time};
11use structured_asn1::memory::{Memory, OwnedVec, Work};
12use structured_asn1::{
13    BitString, Element, Encoding, Integer, Oid, Parser, Reader, Span, Tag, universal,
14};
15
16const FIELD: &str = "ocspResponse";
17const BASIC: &str = "ocspResponse.basic";
18const DATA: &str = "ocspResponse.responseData";
19const SINGLE: &str = "ocspResponse.singleResponse";
20
21mod digest;
22pub use digest::{CertMatch, ResponderMatch};
23
24mod nonce;
25pub use nonce::{NonceBinding, NonceSizeError, RequestNonce};
26
27mod authentication;
28pub use authentication::{
29    SignatureAuthentication, SignatureError, SignatureFailure, SignedResponse,
30};
31
32mod delegation;
33pub(crate) use delegation::read_no_check;
34
35mod lookup;
36pub use delegation::{
37    DelegateFacts, Delegation, DelegationFailure, ResponderRevocation, check_delegate,
38};
39pub use lookup::Lookup;
40
41mod freshness;
42pub use freshness::UpdateWindow;
43
44mod authority;
45pub use authority::{AuthorityBinding, AuthorityFailure, AuthoritySource, ScopedResponse};
46
47mod extensions;
48pub use extensions::ExtensionProcessing;
49
50mod retention;
51
52mod evidence;
53pub use evidence::{
54    BoundEvidence, Evaluation, Evidence, RecipientBinding, Request, TargetEvidence, TargetReading,
55};
56
57pub mod request;
58pub use request::{OcspRequest, RequestEntry, RequestSignature};
59
60/// Unsigned protocol failure from RFC6960 §4.2.1, never a certificate verdict.
61#[derive(Debug, Clone, Copy, PartialEq, Eq)]
62pub enum Failure {
63    /// Request did not conform to the protocol.
64    MalformedRequest,
65    /// Responder reached an inconsistent state.
66    InternalError,
67    /// Responder cannot currently answer.
68    TryLater,
69    /// Responder requires a signed request.
70    SignatureRequired,
71    /// Request unauthorized or responder unable to answer authoritatively.
72    Unauthorized,
73}
74
75/// A decoded envelope preserves unsupported response types and unsigned errors.
76#[derive(Debug)]
77pub enum Response<'a> {
78    /// Successful wire envelope, whose typed body is decoded on demand.
79    Successful(ResponseBytes<'a>),
80    /// Protocol error. No signed status information accompanies it.
81    Failure {
82        /// Error code chosen by the responder.
83        failure: Failure,
84        /// Original envelope location.
85        span: Span,
86    },
87}
88
89/// Original successful response payload and its producing reader. Keeping the
90/// envelope separate avoids allocating a large basic response for protocol
91/// failures or unsupported types; decoding moves the existing reader.
92#[derive(Debug)]
93pub struct ResponseBytes<'a> {
94    encoded: &'a [u8],
95    kind: Oid<'a>,
96    payload: &'a [u8],
97    span: Span,
98    reader: Reader<'a>,
99}
100
101impl<'a> ResponseBytes<'a> {
102    /// Whole original successful `OCSPResponse` DER, including status and
103    /// `responseBytes` wrapper. RFC6960 §4.2.1 separates this envelope from the
104    /// signed `BasicOCSPResponse` payload. Reference digests must not substitute
105    /// the payload or a re-encoded envelope for these original bytes.
106    /// <https://www.rfc-editor.org/rfc/rfc6960#section-4.2.1>
107    #[must_use]
108    pub fn as_bytes(&self) -> &'a [u8] {
109        self.encoded
110    }
111    /// Original response syntax identifier.
112    #[must_use]
113    pub fn kind(&self) -> Oid<'a> {
114        self.kind
115    }
116    /// Original encoded response payload.
117    #[must_use]
118    pub fn payload(&self) -> &'a [u8] {
119        self.payload
120    }
121    /// Original payload content location.
122    #[must_use]
123    pub fn span(&self) -> Span {
124        self.span
125    }
126    /// Borrows the original basic-response payload under a current operation.
127    /// The envelope is not consumed or cloned. Its original producing parser,
128    /// source offsets and actual depth remain active, while the supplied query
129    /// funds new decoding, catalogue growth and lazy certificate processing.
130    /// `None` is only an unsupported response syntax, never a malformed known
131    /// basic response or a source/current-operation resource refusal.
132    pub fn basic_in<'query>(&self, query: &Reader<'query>) -> Result<Option<BasicResponse<'query>>>
133    where
134        'a: 'query,
135    {
136        // RFC6960 §4.2.1 leaves an unsupported responseType's octets opaque.
137        // Classifying its OID consumes metadata work, not a payload nesting
138        // level. Keep both source and current query work ceilings before the
139        // comparison; only the known basic syntax opens a nested reader.
140        // https://www.rfc-editor.org/rfc/rfc6960.html#section-4.2.1
141        self.reader
142            .execution_query(query)
143            .charge_work(19)
144            .map_err(|reason| Error::resource(reason, FIELD, self.span.start))?;
145        if self.kind != oid::OCSP_BASIC {
146            return Ok(None);
147        }
148        let mut nested = self
149            .reader
150            .parser()
151            .read_nested_query_in(
152                query,
153                self.payload,
154                self.span.start,
155                Encoding::Der,
156                self.reader.depth(),
157            )
158            .field(BASIC)?;
159        let root = required(&mut nested, BASIC)?;
160        let basic = read_basic(&nested, &root)?;
161        end(&nested, BASIC)?;
162        Ok(Some(basic))
163    }
164    /// Decode the mandatory basic response syntax using current execution.
165    /// `None` means unsupported syntax. The producing reader's cumulative
166    /// work/depth limits remain active; no extra parser or reader copy is made.
167    pub fn into_basic(self, execution: &Memory) -> Result<Option<BasicResponse<'a>>> {
168        let reader = self.reader.with_execution(execution);
169        reader.charge(19).field(FIELD)?;
170        if self.kind != oid::OCSP_BASIC {
171            return Ok(None);
172        }
173        let mut nested = reader
174            .parser()
175            .read_nested_query_in(
176                &reader,
177                self.payload,
178                self.span.start,
179                Encoding::Der,
180                reader.depth(),
181            )
182            .field(BASIC)?;
183        let root = required(&mut nested, BASIC)?;
184        let basic = read_basic(&nested, &root)?;
185        end(&nested, BASIC)?;
186        Ok(Some(basic))
187    }
188}
189
190/// Responder identity used to locate the actual signing certificate.
191#[derive(Debug)]
192pub enum ResponderId<'a> {
193    /// Subject distinguished name of the signer.
194    Name(Name<'a>),
195    /// SHA-1 of original subjectPublicKey contents, excluding ASN.1 wrapper
196    /// and the BIT STRING unused-bits count (RFC6960 verified errata6165–6167).
197    KeyHash(&'a [u8]),
198}
199
200impl<'a> ResponderId<'a> {
201    /// Decode one original RFC6960 §4.2.1 `ResponderID` choice using its
202    /// producing reader, including the EXPLICIT context wrapper and fixed
203    /// SHA-1 key-hash width. Source profile encoding is supplied by that reader;
204    /// no new parser, normalized copy or budget reset is introduced.
205    /// <https://www.rfc-editor.org/rfc/rfc6960.html#section-4.2.1>
206    pub fn read_element(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
207        read_responder(parent, element)
208    }
209}
210
211/// Certificate identity retains its original encoded hash algorithm and octets.
212#[derive(Debug, Clone, Copy)]
213pub struct CertId<'a> {
214    algorithm: AlgorithmIdentifier<'a>,
215    issuer_name_hash: &'a [u8],
216    issuer_key_hash: &'a [u8],
217    serial: Integer<'a>,
218    span: Span,
219}
220
221impl<'a> CertId<'a> {
222    /// Hash algorithm, including original parameters.
223    #[must_use]
224    pub fn algorithm(self) -> AlgorithmIdentifier<'a> {
225        self.algorithm
226    }
227    /// Hash of the target certificate's original issuer DER name.
228    #[must_use]
229    pub fn issuer_name_hash(self) -> &'a [u8] {
230        self.issuer_name_hash
231    }
232    /// Hash of the issuer's original subjectPublicKey BIT STRING contents.
233    #[must_use]
234    pub fn issuer_key_hash(self) -> &'a [u8] {
235        self.issuer_key_hash
236    }
237    /// Original arbitrary-width serial INTEGER.
238    #[must_use]
239    pub fn serial(self) -> Integer<'a> {
240        self.serial
241    }
242    /// Original `CertID` location.
243    #[must_use]
244    pub fn span(self) -> Span {
245        self.span
246    }
247}
248
249/// A responder's assertion, independently of authentication and applicability.
250#[derive(Debug, Clone, Copy, PartialEq, Eq)]
251pub enum Status {
252    /// Positive revocation inquiry; not proof that a certificate was issued.
253    Good,
254    /// Responder states revocation or hold, retaining its original date/reason.
255    Revoked {
256        /// Recorded revocation or hold time.
257        time: Time,
258        /// Encoded optional reason, without substituting a policy decision.
259        reason: Option<crate::crl::Reason>,
260    },
261    /// This responder does not know the requested certificate's status.
262    Unknown,
263    /// The certificate was never issued (RFC6960 §2.2): a "revoked" hold
264    /// dated 1970-01-01T00:00:00Z under the extended revoked definition. Read
265    /// through [`BasicResponse::status_of`] or [`Evidence::status`], never from
266    /// the assertion alone.
267    NotIssued,
268}
269
270#[derive(Debug)]
271enum RecordedStatus {
272    Good,
273    Unknown,
274    Revoked {
275        time: Time,
276        reason: Option<crate::crl::Reason>,
277        offset: u64,
278    },
279}
280
281/// One signed assertion with deferred extension semantics.
282#[derive(Debug)]
283pub struct SingleResponse<'a> {
284    id: CertId<'a>,
285    status: RecordedStatus,
286    this_update: Time,
287    next_update: Option<Time>,
288    extensions: Extensions<'a>,
289    span: Span,
290}
291
292impl<'a> SingleResponse<'a> {
293    /// Original certificate identity.
294    #[must_use]
295    pub fn id(&self) -> CertId<'a> {
296        self.id
297    }
298    /// Unauthenticated status assertion read on its own: a non-issued answer
299    /// stays [`Status::Revoked`] here, since telling it apart needs the
300    /// response-wide extended revoked definition.
301    #[must_use]
302    pub fn status(&self) -> Status {
303        match self.status {
304            RecordedStatus::Good => Status::Good,
305            RecordedStatus::Unknown => Status::Unknown,
306            RecordedStatus::Revoked { time, reason, .. } => Status::Revoked { time, reason },
307        }
308    }
309
310    /// UTC-qualified recorded revocation time, when this assertion is revoked.
311    /// This never decides whether a future date may be ignored by the product.
312    pub fn revocation_relation<W: Work>(
313        &self,
314        now: crate::temporal::Reading,
315        utc: &crate::temporal::LeapTable<'_>,
316        execution: &W,
317    ) -> Result<Option<crate::time::Relation>> {
318        match self.status {
319            RecordedStatus::Good | RecordedStatus::Unknown => Ok(None),
320            RecordedStatus::Revoked { time, offset, .. } => crate::time::relation_in(
321                time.instant(),
322                now,
323                utc,
324                execution,
325                ("ocspResponse.singleResponse.revocationTime", offset),
326            )
327            .map(Some),
328        }
329    }
330    /// Most recent time the responder knew this status to be correct.
331    #[must_use]
332    pub fn this_update(&self) -> Time {
333        self.this_update
334    }
335    /// Recommended update boundary, absent when newer information is always
336    /// available. No lifetime is invented for an absent value.
337    #[must_use]
338    pub fn next_update(&self) -> Option<Time> {
339        self.next_update
340    }
341    /// Deferred extensions, still using their source parser and current account.
342    #[must_use]
343    pub fn extensions(&self) -> &Extensions<'a> {
344        &self.extensions
345    }
346    /// Original assertion location.
347    #[must_use]
348    pub fn span(&self) -> Span {
349        self.span
350    }
351}
352
353/// `BasicOCSPResponse` retains the exact signed `ResponseData` encoding.
354#[derive(Debug)]
355pub struct BasicResponse<'a> {
356    responder: ResponderId<'a>,
357    produced_at: Time,
358    responses: OwnedVec<SingleResponse<'a>>,
359    extensions: Extensions<'a>,
360    algorithm: AlgorithmIdentifier<'a>,
361    signature: crate::signature::SignatureValue<'a>,
362    certificates: OwnedVec<Certificate<'a>>,
363    signed: &'a [u8],
364    bytes: &'a [u8],
365    span: Span,
366}
367
368impl<'a> BasicResponse<'a> {
369    /// Reads an original bare `BasicOCSPResponse`, for example in a `CAdES`
370    /// revocation-values attribute. This is not an `OCSPResponse` envelope.
371    /// RFC6960 §4.2.1 requires DER; the producing reader's depth, source and
372    /// current execution remain active. Reading does not authenticate it.
373    /// <https://www.rfc-editor.org/rfc/rfc6960#section-4.2.1>
374    pub fn read_element(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
375        let mut outer = parent.reread(element, Encoding::Der).field(BASIC)?;
376        let value = outer
377            .expect(Tag::constructed(universal::SEQUENCE))
378            .field(BASIC)?;
379        let response = read_basic(&outer, &value)?;
380        end(&outer, BASIC)?;
381        Ok(response)
382    }
383
384    /// Original responder identity, not a resolved signing authority.
385    #[must_use]
386    pub fn responder(&self) -> &ResponderId<'a> {
387        &self.responder
388    }
389    /// Time the responder signed this response, not the status update time.
390    #[must_use]
391    pub fn produced_at(&self) -> Time {
392        self.produced_at
393    }
394    /// Signed assertions in original order; duplicates are not collapsed.
395    #[must_use]
396    pub fn responses(&self) -> &[SingleResponse<'a>] {
397        &self.responses
398    }
399    /// Response-wide deferred extensions.
400    #[must_use]
401    pub fn extensions(&self) -> &Extensions<'a> {
402        &self.extensions
403    }
404    /// Signature algorithm selected by the responder.
405    #[must_use]
406    pub fn signature_algorithm(&self) -> AlgorithmIdentifier<'a> {
407        self.algorithm
408    }
409    /// Original signature BIT STRING.
410    #[must_use]
411    pub fn signature(&self) -> BitString<'a> {
412        self.signature.bit_string()
413    }
414    /// Signature bytes with original source context for deferred decoding.
415    #[must_use]
416    pub fn signature_value(&self) -> crate::signature::SignatureValue<'a> {
417        self.signature
418    }
419    /// Untrusted included certificates, not a discovered trust path.
420    #[must_use]
421    pub fn certificates(&self) -> &[Certificate<'a>] {
422        &self.certificates
423    }
424    /// Exact original DER `ResponseData` bytes supplied to signature verification.
425    #[must_use]
426    pub fn signed_bytes(&self) -> &'a [u8] {
427        self.signed
428    }
429    /// Original DER `BasicOCSPResponse` bytes.
430    #[must_use]
431    pub fn as_bytes(&self) -> &'a [u8] {
432        self.bytes
433    }
434    /// Original basic-response location inside the payload OCTET STRING.
435    #[must_use]
436    pub fn span(&self) -> Span {
437        self.span
438    }
439}
440
441impl<'a> Response<'a> {
442    /// Read exactly one OCSP response using the supplied source parser.
443    /// No new parser, budget reset or serialization bridge is introduced.
444    pub fn read(parser: &'a Parser, bytes: &'a [u8], base: u64) -> Result<Self> {
445        let mut reader = parser.read(bytes, base).field(FIELD)?;
446        let element = required(&mut reader, FIELD)?;
447        let result = Self::read_element(&reader, &element)?;
448        end(&reader, FIELD)?;
449        Ok(result)
450    }
451
452    /// Decode an embedded OCSP response under DER with its producing Reader.
453    /// RFC6960 §4 uses explicit tagging by default; §§4.2.1/4.2.2 require
454    /// original DER `ResponseData` for signatures and strict profile times.
455    /// <https://www.rfc-editor.org/rfc/rfc6960#section-4.2.1>
456    pub fn read_element(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
457        if element.tag() != Tag::constructed(universal::SEQUENCE) {
458            return Err(Error::new(
459                ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
460                FIELD,
461                element.span().start,
462            ));
463        }
464        let mut distinguished = parent.reread(element, Encoding::Der).field(FIELD)?;
465        let root = distinguished
466            .expect(Tag::constructed(universal::SEQUENCE))
467            .field(FIELD)?;
468        let mut reader = distinguished.enter(&root).field(FIELD)?;
469        let code = reader.expect(Tag::primitive(10)).field(FIELD)?;
470        reader.charge(9).field(FIELD)?;
471        let code = reader.integer(&code).field(FIELD)?.as_u64();
472        let failure = match code {
473            Some(0) => None,
474            Some(1) => Some(Failure::MalformedRequest),
475            Some(2) => Some(Failure::InternalError),
476            Some(3) => Some(Failure::TryLater),
477            Some(5) => Some(Failure::SignatureRequired),
478            Some(6) => Some(Failure::Unauthorized),
479            _ => {
480                return Err(Error::new(
481                    ErrorCode::MalformedValue,
482                    FIELD,
483                    root.span().start,
484                ));
485            }
486        };
487        if let Some(failure) = failure {
488            // RFC6960 §4.2.1: error responses do not set responseBytes.
489            end(&reader, FIELD)?;
490            return Ok(Self::Failure {
491                failure,
492                span: root.span(),
493            });
494        }
495        let wrapper = reader.expect(Tag::context(true, 0)).field(FIELD)?;
496        end(&reader, FIELD)?;
497        let mut explicit = reader.enter(&wrapper).field(FIELD)?;
498        let response_bytes = explicit
499            .expect(Tag::constructed(universal::SEQUENCE))
500            .field(FIELD)?;
501        end(&explicit, FIELD)?;
502        let mut bytes_reader = explicit.enter(&response_bytes).field(FIELD)?;
503        let kind = bytes_reader.read_oid().field(FIELD)?;
504        let payload = bytes_reader
505            .expect(Tag::primitive(universal::OCTET_STRING))
506            .field(FIELD)?;
507        end(&bytes_reader, FIELD)?;
508        Ok(Self::Successful(ResponseBytes {
509            encoded: element.as_bytes(),
510            kind,
511            payload: payload.contents(),
512            span: payload.contents_span(),
513            reader: bytes_reader,
514        }))
515    }
516}
517
518fn read_basic<'a>(parent: &Reader<'a>, element: &Element<'a>) -> Result<BasicResponse<'a>> {
519    let mut reader = sequence(parent, element, BASIC)?;
520    let signed = required(&mut reader, DATA)?;
521    let mut data = sequence(&reader, &signed, DATA)?;
522    let responder = required(&mut data, DATA)?;
523    if responder.tag() == Tag::context(true, 0) {
524        let mut version = data.enter(&responder).field(DATA)?;
525        let value = version.read_integer().field(DATA)?;
526        version.charge(9).field(DATA)?;
527        end(&version, DATA)?;
528        return Err(Error::new(
529            if value.as_u64() == Some(0) {
530                ErrorCode::MalformedValue
531            } else {
532                ErrorCode::UnsupportedVersion
533            },
534            DATA,
535            responder.span().start,
536        ));
537    }
538    let responder = read_responder(&data, &responder)?;
539    let produced = required(&mut data, DATA)?;
540    let produced_at = generalized(&data, &produced, DATA)?;
541    let assertions = data
542        .expect(Tag::constructed(universal::SEQUENCE))
543        .field(DATA)?;
544    let mut assertions_reader = data.enter(&assertions).field(SINGLE)?;
545    let work = parent.execution();
546    let mut responses = work.vector();
547    while let Some(assertion) = assertions_reader.next_element().field(SINGLE)? {
548        responses
549            .try_push(read_single(&assertions_reader, &assertion)?)
550            .map_err(|reason| Error::resource(reason, SINGLE, assertion.span().start))?;
551    }
552    if responses.is_empty() {
553        return Err(Error::new(
554            ErrorCode::EmptySequence,
555            SINGLE,
556            assertions.span().start,
557        ));
558    }
559    let extensions = optional_extensions(&mut data, 1, DATA)?;
560    end(&data, DATA)?;
561    let algorithm = required(&mut reader, BASIC)?;
562    let algorithm = algorithm::read(&reader, &algorithm, BASIC)?;
563    let signature = crate::signature::SignatureValue::read(&mut reader, BASIC)?;
564    let certificates = if let Some(wrapper) = reader.next_element().field(BASIC)? {
565        request::read_certificates(&reader, &wrapper, BASIC)?
566    } else {
567        work.vector().into_owned()
568    };
569    end(&reader, BASIC)?;
570    Ok(BasicResponse {
571        responder,
572        produced_at,
573        responses: responses.into_owned(),
574        extensions,
575        algorithm,
576        signature,
577        certificates,
578        signed: signed.as_bytes(),
579        bytes: element.as_bytes(),
580        span: element.span(),
581    })
582}
583
584fn read_responder<'a>(parent: &Reader<'a>, element: &Element<'a>) -> Result<ResponderId<'a>> {
585    if element.tag() != Tag::context(true, 1) && element.tag() != Tag::context(true, 2) {
586        return Err(Error::new(
587            ErrorCode::UnexpectedField,
588            DATA,
589            element.span().start,
590        ));
591    }
592    let mut wrapper = parent.enter(element).field(DATA)?;
593    let value = required(&mut wrapper, DATA)?;
594    end(&wrapper, DATA)?;
595    match element.tag() {
596        tag if tag == Tag::context(true, 1) => {
597            Ok(ResponderId::Name(name::read(&wrapper, &value, DATA)?))
598        }
599        tag if tag == Tag::context(true, 2) => {
600            if value.tag() != Tag::primitive(universal::OCTET_STRING)
601                || value.contents().len() != 20
602            {
603                return Err(Error::new(
604                    ErrorCode::MalformedValue,
605                    DATA,
606                    value.span().start,
607                ));
608            }
609            Ok(ResponderId::KeyHash(value.contents()))
610        }
611        _ => Err(Error::new(
612            ErrorCode::UnexpectedField,
613            DATA,
614            element.span().start,
615        )),
616    }
617}
618
619fn read_single<'a>(parent: &Reader<'a>, element: &Element<'a>) -> Result<SingleResponse<'a>> {
620    let mut reader = sequence(parent, element, SINGLE)?;
621    let id = required(&mut reader, SINGLE)?;
622    let id = read_id(&reader, &id, SINGLE)?;
623    let status = required(&mut reader, SINGLE)?;
624    let status = match status.tag() {
625        tag if tag == Tag::context(false, 0) => {
626            reader.null(&status).field(SINGLE)?;
627            RecordedStatus::Good
628        }
629        tag if tag == Tag::context(false, 2) => {
630            reader.null(&status).field(SINGLE)?;
631            RecordedStatus::Unknown
632        }
633        tag if tag == Tag::context(true, 1) => {
634            let mut revoked = reader.enter(&status).field(SINGLE)?;
635            let date = required(&mut revoked, SINGLE)?;
636            let time = generalized(&revoked, &date, SINGLE)?;
637            let reason = if let Some(wrapper) = revoked.next_element().field(SINGLE)? {
638                if wrapper.tag() != Tag::context(true, 0) {
639                    return Err(Error::new(
640                        ErrorCode::UnexpectedField,
641                        SINGLE,
642                        wrapper.span().start,
643                    ));
644                }
645                let mut explicit = revoked.enter(&wrapper).field(SINGLE)?;
646                let reason = explicit.expect(Tag::primitive(10)).field(SINGLE)?;
647                end(&explicit, SINGLE)?;
648                Some(crate::crl::reason_element(&explicit, &reason, SINGLE)?)
649            } else {
650                None
651            };
652            end(&revoked, SINGLE)?;
653            RecordedStatus::Revoked {
654                time,
655                reason,
656                offset: date.span().start,
657            }
658        }
659        _ => {
660            return Err(Error::new(
661                ErrorCode::UnexpectedField,
662                SINGLE,
663                status.span().start,
664            ));
665        }
666    };
667    let this = required(&mut reader, SINGLE)?;
668    let this_update = generalized(&reader, &this, SINGLE)?;
669    let mut next = reader.next_element().field(SINGLE)?;
670    let next_update =
671        if let Some(wrapper) = next.filter(|element| element.tag() == Tag::context(true, 0)) {
672            let mut explicit = reader.enter(&wrapper).field(SINGLE)?;
673            let value = required(&mut explicit, SINGLE)?;
674            end(&explicit, SINGLE)?;
675            let value = generalized(&explicit, &value, SINGLE)?;
676            next = reader.next_element().field(SINGLE)?;
677            Some(value)
678        } else {
679            None
680        };
681    let extensions = extensions_element(&reader, next.as_ref(), 1, SINGLE)?;
682    end(&reader, SINGLE)?;
683    Ok(SingleResponse {
684        id,
685        status,
686        this_update,
687        next_update,
688        extensions,
689        span: element.span(),
690    })
691}
692
693fn read_id<'a>(
694    parent: &Reader<'a>,
695    element: &Element<'a>,
696    field: &'static str,
697) -> Result<CertId<'a>> {
698    let mut reader = sequence(parent, element, field)?;
699    let algorithm = required(&mut reader, field)?;
700    let algorithm = algorithm::read(&reader, &algorithm, field)?;
701    let name = reader
702        .expect(Tag::primitive(universal::OCTET_STRING))
703        .field(field)?;
704    let key = reader
705        .expect(Tag::primitive(universal::OCTET_STRING))
706        .field(field)?;
707    let serial = reader.read_integer().field(field)?;
708    end(&reader, field)?;
709    Ok(CertId {
710        algorithm,
711        issuer_name_hash: name.contents(),
712        issuer_key_hash: key.contents(),
713        serial,
714        span: element.span(),
715    })
716}
717
718fn generalized(parent: &Reader<'_>, element: &Element<'_>, field: &'static str) -> Result<Time> {
719    if element.tag() != Tag::primitive(universal::GENERALIZED_TIME) {
720        return Err(Error::new(
721            ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
722            field,
723            element.span().start,
724        ));
725    }
726    time::read_in(parent, element, field)
727}
728fn sequence<'a>(
729    parent: &Reader<'a>,
730    element: &Element<'a>,
731    field: &'static str,
732) -> Result<Reader<'a>> {
733    if element.tag() != Tag::constructed(universal::SEQUENCE) {
734        return Err(Error::new(
735            ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
736            field,
737            element.span().start,
738        ));
739    }
740    parent.enter(element).field(field)
741}
742fn optional_extensions<'a>(
743    reader: &mut Reader<'a>,
744    tag: u32,
745    field: &'static str,
746) -> Result<Extensions<'a>> {
747    let element = reader.next_element().field(field)?;
748    extensions_element(reader, element.as_ref(), tag, field)
749}
750fn extensions_element<'a>(
751    parent: &Reader<'a>,
752    element: Option<&Element<'a>>,
753    tag: u32,
754    field: &'static str,
755) -> Result<Extensions<'a>> {
756    let Some(element) = element else {
757        return Ok(Extensions::empty(parent.memory()));
758    };
759    if element.tag() != Tag::context(true, tag) {
760        return Err(Error::new(
761            ErrorCode::UnexpectedField,
762            field,
763            element.span().start,
764        ));
765    }
766    let mut explicit = parent.enter(element).field(field)?;
767    let value = required(&mut explicit, field)?;
768    end(&explicit, field)?;
769    extension::read(&explicit, &value, field)
770}
771fn required<'a>(reader: &mut Reader<'a>, field: &'static str) -> Result<Element<'a>> {
772    let at = reader.offset();
773    reader
774        .next_element()
775        .field(field)?
776        .ok_or_else(|| Error::new(ErrorCode::MissingField, field, at))
777}
778fn end(reader: &structured_asn1::ScopedReader<'_, '_>, field: &'static str) -> Result<()> {
779    if reader.is_empty() {
780        Ok(())
781    } else {
782        Err(Error::new(ErrorCode::TrailingData, field, reader.offset()))
783    }
784}