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: crate::signature::SignatureValue<'a>,
359    certificates: OwnedVec<Certificate<'a>>,
360    signed: &'a [u8],
361    bytes: &'a [u8],
362    span: Span,
363}
364
365impl<'a> BasicResponse<'a> {
366    /// Reads an original bare `BasicOCSPResponse`, for example in a `CAdES`
367    /// revocation-values attribute. This is not an `OCSPResponse` envelope.
368    /// RFC6960 §4.2.1 requires DER; the producing reader's depth, source and
369    /// current execution remain active. Reading does not authenticate it.
370    /// <https://www.rfc-editor.org/rfc/rfc6960#section-4.2.1>
371    pub fn read_element(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
372        let mut outer = parent.reread(element, Encoding::Der).field(BASIC)?;
373        let value = outer
374            .expect(Tag::constructed(universal::SEQUENCE))
375            .field(BASIC)?;
376        let response = read_basic(&outer, &value)?;
377        end(&outer, BASIC)?;
378        Ok(response)
379    }
380
381    /// Original responder identity, not a resolved signing authority.
382    #[must_use]
383    pub fn responder(&self) -> &ResponderId<'a> {
384        &self.responder
385    }
386    /// Time the responder signed this response, not the status update time.
387    #[must_use]
388    pub fn produced_at(&self) -> Time {
389        self.produced_at
390    }
391    /// Signed assertions in original order; duplicates are not collapsed.
392    #[must_use]
393    pub fn responses(&self) -> &[SingleResponse<'a>] {
394        &self.responses
395    }
396    /// Response-wide deferred extensions.
397    #[must_use]
398    pub fn extensions(&self) -> &Extensions<'a> {
399        &self.extensions
400    }
401    /// Signature algorithm selected by the responder.
402    #[must_use]
403    pub fn signature_algorithm(&self) -> AlgorithmIdentifier<'a> {
404        self.algorithm
405    }
406    /// Original signature BIT STRING.
407    #[must_use]
408    pub fn signature(&self) -> BitString<'a> {
409        self.signature.bit_string()
410    }
411    /// Signature bytes with original source context for deferred decoding.
412    #[must_use]
413    pub fn signature_value(&self) -> crate::signature::SignatureValue<'a> {
414        self.signature
415    }
416    /// Untrusted included certificates, not a discovered trust path.
417    #[must_use]
418    pub fn certificates(&self) -> &[Certificate<'a>] {
419        &self.certificates
420    }
421    /// Exact original DER `ResponseData` bytes supplied to signature verification.
422    #[must_use]
423    pub fn signed_bytes(&self) -> &'a [u8] {
424        self.signed
425    }
426    /// Original DER `BasicOCSPResponse` bytes.
427    #[must_use]
428    pub fn as_bytes(&self) -> &'a [u8] {
429        self.bytes
430    }
431    /// Original basic-response location inside the payload OCTET STRING.
432    #[must_use]
433    pub fn span(&self) -> Span {
434        self.span
435    }
436}
437
438impl<'a> Response<'a> {
439    /// Read exactly one OCSP response using the supplied source parser.
440    /// No new parser, budget reset or serialization bridge is introduced.
441    pub fn read(parser: &'a Parser, bytes: &'a [u8], base: u64) -> Result<Self> {
442        let mut reader = parser.read(bytes, base).field(FIELD)?;
443        let element = required(&mut reader, FIELD)?;
444        let result = Self::read_element(&reader, &element)?;
445        end(&reader, FIELD)?;
446        Ok(result)
447    }
448
449    /// Decode an embedded OCSP response under DER with its producing Reader.
450    /// RFC6960 §4 uses explicit tagging by default; §§4.2.1/4.2.2 require
451    /// original DER `ResponseData` for signatures and strict profile times.
452    /// <https://www.rfc-editor.org/rfc/rfc6960#section-4.2.1>
453    pub fn read_element(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
454        if element.tag() != Tag::constructed(universal::SEQUENCE) {
455            return Err(Error::new(
456                ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
457                FIELD,
458                element.span().start,
459            ));
460        }
461        let mut distinguished = parent.reread(element, Encoding::Der).field(FIELD)?;
462        let root = distinguished
463            .expect(Tag::constructed(universal::SEQUENCE))
464            .field(FIELD)?;
465        let mut reader = distinguished.enter(&root).field(FIELD)?;
466        let code = reader.expect(Tag::primitive(10)).field(FIELD)?;
467        reader.charge(9).field(FIELD)?;
468        let code = reader.integer(&code).field(FIELD)?.as_u64();
469        let failure = match code {
470            Some(0) => None,
471            Some(1) => Some(Failure::MalformedRequest),
472            Some(2) => Some(Failure::InternalError),
473            Some(3) => Some(Failure::TryLater),
474            Some(5) => Some(Failure::SignatureRequired),
475            Some(6) => Some(Failure::Unauthorized),
476            _ => {
477                return Err(Error::new(
478                    ErrorCode::MalformedValue,
479                    FIELD,
480                    root.span().start,
481                ));
482            }
483        };
484        if let Some(failure) = failure {
485            // RFC6960 §4.2.1: error responses do not set responseBytes.
486            end(&reader, FIELD)?;
487            return Ok(Self::Failure {
488                failure,
489                span: root.span(),
490            });
491        }
492        let wrapper = reader.expect(Tag::context(true, 0)).field(FIELD)?;
493        end(&reader, FIELD)?;
494        let mut explicit = reader.enter(&wrapper).field(FIELD)?;
495        let response_bytes = explicit
496            .expect(Tag::constructed(universal::SEQUENCE))
497            .field(FIELD)?;
498        end(&explicit, FIELD)?;
499        let mut bytes_reader = explicit.enter(&response_bytes).field(FIELD)?;
500        let kind = bytes_reader.read_oid().field(FIELD)?;
501        let payload = bytes_reader
502            .expect(Tag::primitive(universal::OCTET_STRING))
503            .field(FIELD)?;
504        end(&bytes_reader, FIELD)?;
505        Ok(Self::Successful(ResponseBytes {
506            encoded: element.as_bytes(),
507            kind,
508            payload: payload.contents(),
509            span: payload.contents_span(),
510            reader: bytes_reader,
511        }))
512    }
513}
514
515fn read_basic<'a>(parent: &Reader<'a>, element: &Element<'a>) -> Result<BasicResponse<'a>> {
516    let mut reader = sequence(parent, element, BASIC)?;
517    let signed = required(&mut reader, DATA)?;
518    let mut data = sequence(&reader, &signed, DATA)?;
519    let responder = required(&mut data, DATA)?;
520    if responder.tag() == Tag::context(true, 0) {
521        let mut version = data.enter(&responder).field(DATA)?;
522        let value = version.read_integer().field(DATA)?;
523        version.charge(9).field(DATA)?;
524        end(&version, DATA)?;
525        return Err(Error::new(
526            if value.as_u64() == Some(0) {
527                ErrorCode::MalformedValue
528            } else {
529                ErrorCode::UnsupportedVersion
530            },
531            DATA,
532            responder.span().start,
533        ));
534    }
535    let responder = read_responder(&data, &responder)?;
536    let produced = required(&mut data, DATA)?;
537    let produced_at = generalized(&data, &produced, DATA)?;
538    let assertions = data
539        .expect(Tag::constructed(universal::SEQUENCE))
540        .field(DATA)?;
541    let mut assertions_reader = data.enter(&assertions).field(SINGLE)?;
542    let work = parent.execution();
543    let mut responses = work.vector();
544    while let Some(assertion) = assertions_reader.next_element().field(SINGLE)? {
545        responses
546            .try_push(read_single(&assertions_reader, &assertion)?)
547            .map_err(|reason| Error::resource(reason, SINGLE, assertion.span().start))?;
548    }
549    if responses.is_empty() {
550        return Err(Error::new(
551            ErrorCode::EmptySequence,
552            SINGLE,
553            assertions.span().start,
554        ));
555    }
556    let extensions = optional_extensions(&mut data, 1, DATA)?;
557    end(&data, DATA)?;
558    let algorithm = required(&mut reader, BASIC)?;
559    let algorithm = algorithm::read(&reader, &algorithm, BASIC)?;
560    let signature = crate::signature::SignatureValue::read(&mut reader, BASIC)?;
561    let mut certificates = work.vector();
562    if let Some(wrapper) = reader.next_element().field(BASIC)? {
563        if wrapper.tag() != Tag::context(true, 0) {
564            return Err(Error::new(
565                ErrorCode::UnexpectedField,
566                BASIC,
567                wrapper.span().start,
568            ));
569        }
570        let mut explicit = reader.enter(&wrapper).field(BASIC)?;
571        let sequence = explicit
572            .expect(Tag::constructed(universal::SEQUENCE))
573            .field(BASIC)?;
574        end(&explicit, BASIC)?;
575        let mut inside = explicit.enter(&sequence).field(BASIC)?;
576        while let Some(certificate) = inside.next_element().field(BASIC)? {
577            certificates
578                .try_push(Certificate::read_element(&inside, &certificate)?)
579                .map_err(|reason| Error::resource(reason, BASIC, certificate.span().start))?;
580        }
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: certificates.into_owned(),
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)?;
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>(parent: &Reader<'a>, element: &Element<'a>) -> Result<CertId<'a>> {
707    let mut reader = sequence(parent, element, SINGLE)?;
708    let algorithm = required(&mut reader, SINGLE)?;
709    let algorithm = algorithm::read(&reader, &algorithm, SINGLE)?;
710    let name = reader
711        .expect(Tag::primitive(universal::OCTET_STRING))
712        .field(SINGLE)?;
713    let key = reader
714        .expect(Tag::primitive(universal::OCTET_STRING))
715        .field(SINGLE)?;
716    let serial = reader.read_integer().field(SINGLE)?;
717    end(&reader, SINGLE)?;
718    Ok(CertId {
719        algorithm,
720        issuer_name_hash: name.contents(),
721        issuer_key_hash: key.contents(),
722        serial,
723        span: element.span(),
724    })
725}
726
727fn generalized(parent: &Reader<'_>, element: &Element<'_>, field: &'static str) -> Result<Time> {
728    if element.tag() != Tag::primitive(universal::GENERALIZED_TIME) {
729        return Err(Error::new(
730            ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
731            field,
732            element.span().start,
733        ));
734    }
735    time::read_in(parent, element, field)
736}
737fn sequence<'a>(
738    parent: &Reader<'a>,
739    element: &Element<'a>,
740    field: &'static str,
741) -> Result<Reader<'a>> {
742    if element.tag() != Tag::constructed(universal::SEQUENCE) {
743        return Err(Error::new(
744            ErrorCode::Encoding(structured_asn1::ErrorCode::UnexpectedTag),
745            field,
746            element.span().start,
747        ));
748    }
749    parent.enter(element).field(field)
750}
751fn optional_extensions<'a>(
752    reader: &mut Reader<'a>,
753    tag: u32,
754    field: &'static str,
755) -> Result<Extensions<'a>> {
756    let element = reader.next_element().field(field)?;
757    extensions_element(reader, element.as_ref(), tag, field)
758}
759fn extensions_element<'a>(
760    parent: &Reader<'a>,
761    element: Option<&Element<'a>>,
762    tag: u32,
763    field: &'static str,
764) -> Result<Extensions<'a>> {
765    let Some(element) = element else {
766        return Ok(Extensions::empty(parent.memory()));
767    };
768    if element.tag() != Tag::context(true, tag) {
769        return Err(Error::new(
770            ErrorCode::UnexpectedField,
771            field,
772            element.span().start,
773        ));
774    }
775    let mut explicit = parent.enter(element).field(field)?;
776    let value = required(&mut explicit, field)?;
777    end(&explicit, field)?;
778    extension::read(&explicit, &value, field)
779}
780fn required<'a>(reader: &mut Reader<'a>, field: &'static str) -> Result<Element<'a>> {
781    let at = reader.offset();
782    reader
783        .next_element()
784        .field(field)?
785        .ok_or_else(|| Error::new(ErrorCode::MissingField, field, at))
786}
787fn end(reader: &structured_asn1::ScopedReader<'_, '_>, field: &'static str) -> Result<()> {
788    if reader.is_empty() {
789        Ok(())
790    } else {
791        Err(Error::new(ErrorCode::TrailingData, field, reader.offset()))
792    }
793}