Skip to main content

structured_pkix/
ocsp.rs

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