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    /// Borrows the original response execution for new current-operation work,
370    /// preserving its producing ceiling and actual account without allocation.
371    #[must_use]
372    pub fn execution_in<'operation, W: Work>(
373        &self,
374        work: &'operation W,
375    ) -> structured_asn1::memory::Execution<'operation>
376    where
377        'a: 'operation,
378    {
379        self.algorithm.query_in(work)
380    }
381
382    /// Reads an original bare `BasicOCSPResponse`, for example in a `CAdES`
383    /// revocation-values attribute. This is not an `OCSPResponse` envelope.
384    /// RFC6960 §4.2.1 requires DER; the producing reader's depth, source and
385    /// current execution remain active. Reading does not authenticate it.
386    /// <https://www.rfc-editor.org/rfc/rfc6960#section-4.2.1>
387    pub fn read_element(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
388        let mut outer = parent.reread(element, Encoding::Der).field(BASIC)?;
389        let value = outer
390            .expect(Tag::constructed(universal::SEQUENCE))
391            .field(BASIC)?;
392        let response = read_basic(&outer, &value)?;
393        end(&outer, BASIC)?;
394        Ok(response)
395    }
396
397    /// Original responder identity, not a resolved signing authority.
398    #[must_use]
399    pub fn responder(&self) -> &ResponderId<'a> {
400        &self.responder
401    }
402    /// Time the responder signed this response, not the status update time.
403    #[must_use]
404    pub fn produced_at(&self) -> Time {
405        self.produced_at
406    }
407    /// Signed assertions in original order; duplicates are not collapsed.
408    #[must_use]
409    pub fn responses(&self) -> &[SingleResponse<'a>] {
410        &self.responses
411    }
412    /// Response-wide deferred extensions.
413    #[must_use]
414    pub fn extensions(&self) -> &Extensions<'a> {
415        &self.extensions
416    }
417    /// Signature algorithm selected by the responder.
418    #[must_use]
419    pub fn signature_algorithm(&self) -> AlgorithmIdentifier<'a> {
420        self.algorithm
421    }
422    /// Original signature BIT STRING.
423    #[must_use]
424    pub fn signature(&self) -> BitString<'a> {
425        self.signature.bit_string()
426    }
427    /// Signature bytes with original source context for deferred decoding.
428    #[must_use]
429    pub fn signature_value(&self) -> crate::signature::SignatureValue<'a> {
430        self.signature
431    }
432    /// Untrusted included certificates, not a discovered trust path.
433    #[must_use]
434    pub fn certificates(&self) -> &[Certificate<'a>] {
435        &self.certificates
436    }
437    /// Exact original DER `ResponseData` bytes supplied to signature verification.
438    #[must_use]
439    pub fn signed_bytes(&self) -> &'a [u8] {
440        self.signed
441    }
442    /// Original DER `BasicOCSPResponse` bytes.
443    #[must_use]
444    pub fn as_bytes(&self) -> &'a [u8] {
445        self.bytes
446    }
447    /// Original basic-response location inside the payload OCTET STRING.
448    #[must_use]
449    pub fn span(&self) -> Span {
450        self.span
451    }
452}
453
454impl<'a> Response<'a> {
455    /// Read exactly one OCSP response using the supplied source parser.
456    /// No new parser, budget reset or serialization bridge is introduced.
457    pub fn read(parser: &'a Parser, bytes: &'a [u8], base: u64) -> Result<Self> {
458        let mut reader = parser.read(bytes, base).field(FIELD)?;
459        let element = required(&mut reader, FIELD)?;
460        let result = Self::read_element(&reader, &element)?;
461        end(&reader, FIELD)?;
462        Ok(result)
463    }
464
465    /// Decode an embedded OCSP response under DER with its producing Reader.
466    /// RFC6960 §4 uses explicit tagging by default; §§4.2.1/4.2.2 require
467    /// original DER `ResponseData` for signatures and strict profile times.
468    /// <https://www.rfc-editor.org/rfc/rfc6960#section-4.2.1>
469    pub fn read_element(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
470        if element.tag() != Tag::constructed(universal::SEQUENCE) {
471            return Err(Error::new(
472                ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
473                FIELD,
474                element.span().start,
475            ));
476        }
477        let mut distinguished = parent.reread(element, Encoding::Der).field(FIELD)?;
478        let root = distinguished
479            .expect(Tag::constructed(universal::SEQUENCE))
480            .field(FIELD)?;
481        let mut reader = distinguished.enter(&root).field(FIELD)?;
482        let code = reader.expect(Tag::primitive(10)).field(FIELD)?;
483        reader.charge(9).field(FIELD)?;
484        let code = reader.integer(&code).field(FIELD)?.as_u64();
485        let failure = match code {
486            Some(0) => None,
487            Some(1) => Some(Failure::MalformedRequest),
488            Some(2) => Some(Failure::InternalError),
489            Some(3) => Some(Failure::TryLater),
490            Some(5) => Some(Failure::SignatureRequired),
491            Some(6) => Some(Failure::Unauthorized),
492            _ => {
493                return Err(Error::new(
494                    ErrorCode::MalformedValue,
495                    FIELD,
496                    root.span().start,
497                ));
498            }
499        };
500        if let Some(failure) = failure {
501            // RFC6960 §4.2.1: error responses do not set responseBytes.
502            end(&reader, FIELD)?;
503            return Ok(Self::Failure {
504                failure,
505                span: root.span(),
506            });
507        }
508        let wrapper = reader.expect(Tag::context(true, 0)).field(FIELD)?;
509        end(&reader, FIELD)?;
510        let mut explicit = reader.enter(&wrapper).field(FIELD)?;
511        let response_bytes = explicit
512            .expect(Tag::constructed(universal::SEQUENCE))
513            .field(FIELD)?;
514        end(&explicit, FIELD)?;
515        let mut bytes_reader = explicit.enter(&response_bytes).field(FIELD)?;
516        let kind = bytes_reader.read_oid().field(FIELD)?;
517        let payload = bytes_reader
518            .expect(Tag::primitive(universal::OCTET_STRING))
519            .field(FIELD)?;
520        end(&bytes_reader, FIELD)?;
521        Ok(Self::Successful(ResponseBytes {
522            encoded: element.as_bytes(),
523            kind,
524            payload: payload.contents(),
525            span: payload.contents_span(),
526            reader: bytes_reader,
527        }))
528    }
529}
530
531fn read_basic<'a>(parent: &Reader<'a>, element: &Element<'a>) -> Result<BasicResponse<'a>> {
532    let mut reader = sequence(parent, element, BASIC)?;
533    let signed = required(&mut reader, DATA)?;
534    let mut data = sequence(&reader, &signed, DATA)?;
535    let responder = required(&mut data, DATA)?;
536    if responder.tag() == Tag::context(true, 0) {
537        let mut version = data.enter(&responder).field(DATA)?;
538        let value = version.read_integer().field(DATA)?;
539        version.charge(9).field(DATA)?;
540        end(&version, DATA)?;
541        return Err(Error::new(
542            if value.as_u64() == Some(0) {
543                ErrorCode::MalformedValue
544            } else {
545                ErrorCode::UnsupportedVersion
546            },
547            DATA,
548            responder.span().start,
549        ));
550    }
551    let responder = read_responder(&data, &responder)?;
552    let produced = required(&mut data, DATA)?;
553    let produced_at = generalized(&data, &produced, DATA)?;
554    let assertions = data
555        .expect(Tag::constructed(universal::SEQUENCE))
556        .field(DATA)?;
557    let mut assertions_reader = data.enter(&assertions).field(SINGLE)?;
558    let work = parent.execution();
559    let mut responses = work.vector();
560    while let Some(assertion) = assertions_reader.next_element().field(SINGLE)? {
561        responses
562            .try_push(read_single(&assertions_reader, &assertion)?)
563            .map_err(|reason| Error::resource(reason, SINGLE, assertion.span().start))?;
564    }
565    if responses.is_empty() {
566        return Err(Error::new(
567            ErrorCode::EmptySequence,
568            SINGLE,
569            assertions.span().start,
570        ));
571    }
572    let extensions = optional_extensions(&mut data, 1, DATA)?;
573    end(&data, DATA)?;
574    let algorithm = required(&mut reader, BASIC)?;
575    let algorithm = algorithm::read(&reader, &algorithm, BASIC)?;
576    let signature = crate::signature::SignatureValue::read(&mut reader, BASIC)?;
577    let certificates = if let Some(wrapper) = reader.next_element().field(BASIC)? {
578        request::read_certificates(&reader, &wrapper, BASIC)?
579    } else {
580        work.vector().into_owned()
581    };
582    end(&reader, BASIC)?;
583    Ok(BasicResponse {
584        responder,
585        produced_at,
586        responses: responses.into_owned(),
587        extensions,
588        algorithm,
589        signature,
590        certificates,
591        signed: signed.as_bytes(),
592        bytes: element.as_bytes(),
593        span: element.span(),
594    })
595}
596
597fn read_responder<'a>(parent: &Reader<'a>, element: &Element<'a>) -> Result<ResponderId<'a>> {
598    if element.tag() != Tag::context(true, 1) && element.tag() != Tag::context(true, 2) {
599        return Err(Error::new(
600            ErrorCode::UnexpectedField,
601            DATA,
602            element.span().start,
603        ));
604    }
605    let mut wrapper = parent.enter(element).field(DATA)?;
606    let value = required(&mut wrapper, DATA)?;
607    end(&wrapper, DATA)?;
608    match element.tag() {
609        tag if tag == Tag::context(true, 1) => {
610            Ok(ResponderId::Name(name::read(&wrapper, &value, DATA)?))
611        }
612        tag if tag == Tag::context(true, 2) => {
613            if value.tag() != Tag::primitive(universal::OCTET_STRING)
614                || value.contents().len() != 20
615            {
616                return Err(Error::new(
617                    ErrorCode::MalformedValue,
618                    DATA,
619                    value.span().start,
620                ));
621            }
622            Ok(ResponderId::KeyHash(value.contents()))
623        }
624        _ => Err(Error::new(
625            ErrorCode::UnexpectedField,
626            DATA,
627            element.span().start,
628        )),
629    }
630}
631
632fn read_single<'a>(parent: &Reader<'a>, element: &Element<'a>) -> Result<SingleResponse<'a>> {
633    let mut reader = sequence(parent, element, SINGLE)?;
634    let id = required(&mut reader, SINGLE)?;
635    let id = read_id(&reader, &id, SINGLE)?;
636    let status = required(&mut reader, SINGLE)?;
637    let status = match status.tag() {
638        tag if tag == Tag::context(false, 0) => {
639            reader.null(&status).field(SINGLE)?;
640            RecordedStatus::Good
641        }
642        tag if tag == Tag::context(false, 2) => {
643            reader.null(&status).field(SINGLE)?;
644            RecordedStatus::Unknown
645        }
646        tag if tag == Tag::context(true, 1) => {
647            let mut revoked = reader.enter(&status).field(SINGLE)?;
648            let date = required(&mut revoked, SINGLE)?;
649            let time = generalized(&revoked, &date, SINGLE)?;
650            let reason = if let Some(wrapper) = revoked.next_element().field(SINGLE)? {
651                if wrapper.tag() != Tag::context(true, 0) {
652                    return Err(Error::new(
653                        ErrorCode::UnexpectedField,
654                        SINGLE,
655                        wrapper.span().start,
656                    ));
657                }
658                let mut explicit = revoked.enter(&wrapper).field(SINGLE)?;
659                let reason = explicit.expect(Tag::primitive(10)).field(SINGLE)?;
660                end(&explicit, SINGLE)?;
661                Some(crate::crl::reason_element(&explicit, &reason, SINGLE)?)
662            } else {
663                None
664            };
665            end(&revoked, SINGLE)?;
666            RecordedStatus::Revoked {
667                time,
668                reason,
669                offset: date.span().start,
670            }
671        }
672        _ => {
673            return Err(Error::new(
674                ErrorCode::UnexpectedField,
675                SINGLE,
676                status.span().start,
677            ));
678        }
679    };
680    let this = required(&mut reader, SINGLE)?;
681    let this_update = generalized(&reader, &this, SINGLE)?;
682    let mut next = reader.next_element().field(SINGLE)?;
683    let next_update =
684        if let Some(wrapper) = next.filter(|element| element.tag() == Tag::context(true, 0)) {
685            let mut explicit = reader.enter(&wrapper).field(SINGLE)?;
686            let value = required(&mut explicit, SINGLE)?;
687            end(&explicit, SINGLE)?;
688            let value = generalized(&explicit, &value, SINGLE)?;
689            next = reader.next_element().field(SINGLE)?;
690            Some(value)
691        } else {
692            None
693        };
694    let extensions = extensions_element(&reader, next.as_ref(), 1, SINGLE)?;
695    end(&reader, SINGLE)?;
696    Ok(SingleResponse {
697        id,
698        status,
699        this_update,
700        next_update,
701        extensions,
702        span: element.span(),
703    })
704}
705
706fn read_id<'a>(
707    parent: &Reader<'a>,
708    element: &Element<'a>,
709    field: &'static str,
710) -> Result<CertId<'a>> {
711    let mut reader = sequence(parent, element, field)?;
712    let algorithm = required(&mut reader, field)?;
713    let algorithm = algorithm::read(&reader, &algorithm, field)?;
714    let name = reader
715        .expect(Tag::primitive(universal::OCTET_STRING))
716        .field(field)?;
717    let key = reader
718        .expect(Tag::primitive(universal::OCTET_STRING))
719        .field(field)?;
720    let serial = reader.read_integer().field(field)?;
721    end(&reader, field)?;
722    Ok(CertId {
723        algorithm,
724        issuer_name_hash: name.contents(),
725        issuer_key_hash: key.contents(),
726        serial,
727        span: element.span(),
728    })
729}
730
731fn generalized(parent: &Reader<'_>, element: &Element<'_>, field: &'static str) -> Result<Time> {
732    if element.tag() != Tag::primitive(universal::GENERALIZED_TIME) {
733        return Err(Error::new(
734            ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
735            field,
736            element.span().start,
737        ));
738    }
739    time::read_in(parent, element, field)
740}
741fn sequence<'a>(
742    parent: &Reader<'a>,
743    element: &Element<'a>,
744    field: &'static str,
745) -> Result<Reader<'a>> {
746    if element.tag() != Tag::constructed(universal::SEQUENCE) {
747        return Err(Error::new(
748            ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
749            field,
750            element.span().start,
751        ));
752    }
753    parent.enter(element).field(field)
754}
755fn optional_extensions<'a>(
756    reader: &mut Reader<'a>,
757    tag: u32,
758    field: &'static str,
759) -> Result<Extensions<'a>> {
760    let element = reader.next_element().field(field)?;
761    extensions_element(reader, element.as_ref(), tag, field)
762}
763fn extensions_element<'a>(
764    parent: &Reader<'a>,
765    element: Option<&Element<'a>>,
766    tag: u32,
767    field: &'static str,
768) -> Result<Extensions<'a>> {
769    let Some(element) = element else {
770        return Ok(Extensions::empty(parent.memory()));
771    };
772    if element.tag() != Tag::context(true, tag) {
773        return Err(Error::new(
774            ErrorCode::UnexpectedField,
775            field,
776            element.span().start,
777        ));
778    }
779    let mut explicit = parent.enter(element).field(field)?;
780    let value = required(&mut explicit, field)?;
781    end(&explicit, field)?;
782    extension::read(&explicit, &value, field)
783}
784fn required<'a>(reader: &mut Reader<'a>, field: &'static str) -> Result<Element<'a>> {
785    let at = reader.offset();
786    reader
787        .next_element()
788        .field(field)?
789        .ok_or_else(|| Error::new(ErrorCode::MissingField, field, at))
790}
791fn end(reader: &structured_asn1::ScopedReader<'_, '_>, field: &'static str) -> Result<()> {
792    if reader.is_empty() {
793        Ok(())
794    } else {
795        Err(Error::new(ErrorCode::TrailingData, field, reader.offset()))
796    }
797}