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