Skip to main content

structured_cms/
personal.rs

1//! Provider-neutral personal key containers (RFC7292 / RFC5958).
2//!
3//! Reading is inspection, never authentication or permission to use a key.
4//! [`process()`] authenticates the complete original safe before extraction;
5//! passwords, cryptographic engines, key selection and trust remain explicit
6//! caller contracts. Private-key values are borrowed, not decoded by a backend.
7//! No type containing private plaintext implements `Debug` or allocating Clone.
8
9use crate::{ContentInfo, Error, ErrorCode, Octets, Result, SignedData};
10use crate::{attribute::Attribute, enveloped::EncodedValue, signer::required};
11use structured_asn1::memory::{OwnedVec, Work};
12use structured_asn1::{Element, Integer, Oid, Reader, Tag, universal};
13use structured_pkix::AlgorithmIdentifier;
14
15mod process;
16pub mod protection;
17pub use process::{
18    Backend, Cause, Decision, Failure, Fragments, Origin, Plaintext, Source, legacy_password,
19    process,
20};
21
22const FIELD: &str = "personal";
23const DATA: Oid<'static> = Oid::from_bytes(&[42, 134, 72, 134, 247, 13, 1, 7, 1]);
24const SIGNED: Oid<'static> = Oid::from_bytes(&[42, 134, 72, 134, 247, 13, 1, 7, 2]);
25const ENCRYPTED: Oid<'static> = Oid::from_bytes(&[42, 134, 72, 134, 247, 13, 1, 7, 6]);
26
27/// Original PFX integrity mode. Absence of a MAC is not authenticated data.
28#[expect(
29    clippy::large_enum_variant,
30    reason = "one PFX mode lives inline; boxing would add allocation and indirection to every inspected container"
31)]
32pub enum Integrity<'a> {
33    /// Password integrity over the exact logical `AuthenticatedSafe` octets.
34    Password {
35        /// BER `AuthenticatedSafe` encoding, excluding OCTET STRING headers.
36        safe: Octets<'a>,
37        /// Optional original MAC; None remains unauthenticated inspection.
38        mac: Option<MacData<'a>>,
39    },
40    /// Public-key integrity. The existing CMS processor owns signature rules.
41    Signed(SignedData<'a>),
42}
43
44/// Original PFX v3. Parsing does not invoke passwords or provider operations.
45pub struct Pfx<'a> {
46    integrity: Integrity<'a>,
47    original: EncodedValue<'a>,
48}
49impl<'a> Pfx<'a> {
50    /// Reads one complete BER/DER PFX at the producing source position.
51    pub fn read(parent: &mut Reader<'a>) -> Result<Self> {
52        let element = required(parent, FIELD)?;
53        let value = Self::read_element(parent, &element)?;
54        end(parent)?;
55        Ok(value)
56    }
57    /// Reads an embedded original PFX, without rejecting enclosing siblings.
58    pub fn read_element(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
59        let mut inside = sequence(parent, element)?;
60        let version = number(&mut inside)?;
61        if version.as_u64() != Some(3) {
62            return Err(invalid(ErrorCode::UnsupportedVersion, element));
63        }
64        let envelope = required(&mut inside, FIELD)?;
65        let (info, reader) = ContentInfo::read_element(&inside, &envelope)?;
66        let mac = inside
67            .next_element()
68            .map_err(encoding)?
69            .map(|value| MacData::read(&inside, &value))
70            .transpose()?;
71        end(&inside)?;
72        let integrity = if equal_oid(&inside, info.kind(), DATA)? {
73            Integrity::Password {
74                safe: Octets::read(&reader, info.content(), FIELD)?,
75                mac,
76            }
77        } else if equal_oid(&inside, info.kind(), SIGNED)? {
78            // RFC7292 §4: MacData occurs ONLY in password integrity mode.
79            // https://www.rfc-editor.org/rfc/rfc7292#section-4
80            if mac.is_some() {
81                return Err(invalid(ErrorCode::FieldOrder, element));
82            }
83            let signed = SignedData::read_element(&reader, info.content())?;
84            if !equal_oid(&reader, signed.content().kind(), DATA)? {
85                return Err(invalid(ErrorCode::UnexpectedContentType, info.content()));
86            }
87            if signed.content().content().is_none() {
88                return Err(invalid(ErrorCode::DetachedContent, info.content()));
89            }
90            Integrity::Signed(signed)
91        } else {
92            return Err(invalid(ErrorCode::UnexpectedContentType, &envelope));
93        };
94        Ok(Self {
95            integrity,
96            original: EncodedValue::new(parent, *element),
97        })
98    }
99    /// Whole original PFX and its lazy original/current reader boundary.
100    #[must_use]
101    pub fn original(&self) -> &EncodedValue<'a> {
102        &self.original
103    }
104    /// Original immutable integrity mode and its exact protected data.
105    #[must_use]
106    pub fn integrity(&self) -> &Integrity<'a> {
107        &self.integrity
108    }
109    pub(crate) fn safe(&self) -> &Octets<'a> {
110        match &self.integrity {
111            Integrity::Password { safe, .. } => safe,
112            Integrity::Signed(signed) => signed.content().content().expect("checked attached PFX"),
113        }
114    }
115}
116
117/// Original `MacData`, including ignored legacy fields in PBMAC1 mode.
118pub struct MacData<'a> {
119    /// Original digest/MAC algorithm; PBMAC1 is distinguished explicitly.
120    pub algorithm: AlgorithmIdentifier<'a>,
121    /// Encoded expected MAC octets.
122    pub digest: Octets<'a>,
123    /// Original legacy salt. RFC9879 §4 requires ignoring it for PBMAC1.
124    pub salt: Octets<'a>,
125    /// Original legacy iteration count. None denotes schema DEFAULT 1.
126    /// In PBMAC1 mode this field is ignored, not used as a KDF limit/input.
127    pub iterations: Option<Integer<'a>>,
128    /// Validated PBMAC1 parameters, or None for the legacy MAC scheme.
129    pub pbmac1: Option<protection::Pair<'a>>,
130}
131impl<'a> MacData<'a> {
132    /// Reads `MacData` and RFC9879 mandatory PBMAC1 parameter constraints.
133    pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
134        let mut inside = sequence(parent, element)?;
135        let digest_info = required(&mut inside, FIELD)?;
136        let mut digest_info = sequence(&inside, &digest_info)?;
137        let algorithm = algorithm(&mut digest_info)?;
138        let value = required(&mut digest_info, FIELD)?;
139        let digest = Octets::read(&digest_info, &value, FIELD)?;
140        end(&digest_info)?;
141        let value = required(&mut inside, FIELD)?;
142        let salt = Octets::read(&inside, &value, FIELD)?;
143        let iterations = if inside.is_empty() {
144            None
145        } else {
146            Some(number(&mut inside)?)
147        };
148        end(&inside)?;
149        // RFC9879 §4 ignores this field for MAC computation, not for DER
150        // encoding. X.690 §11.5 still omits the schema DEFAULT in either mode.
151        if let Some(rounds) = iterations {
152            default_one(parent, rounds, element)?;
153        }
154        let pbmac1 = if equal_oid(parent, algorithm.algorithm(), protection::PBMAC1)? {
155            let pair = protection::Pair::read(algorithm, parent)?;
156            if let Some(width) = protection::hmac_width(pair.scheme, parent)?
157                && digest.len() != width
158            {
159                return Err(invalid(ErrorCode::DigestWidth, element));
160            }
161            if let Some(kdf) = pair.pbkdf2.as_ref()
162                && kdf.key_length.is_none()
163            {
164                return Err(invalid(ErrorCode::MissingField, element));
165            }
166            Some(pair)
167        } else {
168            match structured_pkix::algorithm::digest::algorithm(&algorithm, &parent.execution())
169                .map_err(Error::pkix)?
170            {
171                structured_asn1::digest::Resolution::Supported(hash)
172                    if digest.len() != hash.width() =>
173                {
174                    return Err(invalid(ErrorCode::DigestWidth, element));
175                }
176                structured_asn1::digest::Resolution::Malformed => {
177                    return Err(invalid(ErrorCode::AlgorithmSyntax, element));
178                }
179                _ => {}
180            }
181            if let Some(rounds) = iterations {
182                positive(rounds, element)?;
183            }
184            None
185        };
186        Ok(Self {
187            algorithm,
188            digest,
189            salt,
190            iterations,
191            pbmac1,
192        })
193    }
194}
195
196/// One protected `AuthenticatedSafe` member. Unrecognized content stays explicit.
197pub enum Safe<'a> {
198    /// Unencrypted `SafeContents` BER encoding, including its SEQUENCE TLV.
199    Data(Octets<'a>),
200    /// Password-encrypted `SafeContents`.
201    Encrypted(EncryptedData<'a>),
202    /// Public-key encrypted `SafeContents`, reusing all common recipient types.
203    Enveloped(crate::enveloped::EnvelopedData<'a>),
204    /// An open content type without a schema owned by this format.
205    Other {
206        /// Original content type.
207        kind: Oid<'a>,
208        /// Original inner value and producing context.
209        value: EncodedValue<'a>,
210    },
211}
212impl<'a> Safe<'a> {
213    /// Reads one original `ContentInfo` member; no cryptography is performed.
214    pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
215        let (info, reader) = ContentInfo::read_element(parent, element)?;
216        if equal_oid(parent, info.kind(), DATA)? {
217            Ok(Self::Data(Octets::read(&reader, info.content(), FIELD)?))
218        } else if equal_oid(parent, info.kind(), ENCRYPTED)? {
219            Ok(Self::Encrypted(EncryptedData::read(
220                &reader,
221                info.content(),
222            )?))
223        } else if equal_oid(parent, info.kind(), crate::enveloped::IDENTIFIER)? {
224            Ok(Self::Enveloped(
225                crate::enveloped::EnvelopedData::read_element(&reader, info.content())?,
226            ))
227        } else {
228            Ok(Self::Other {
229                kind: info.kind(),
230                value: EncodedValue::new(&reader, *info.content()),
231            })
232        }
233    }
234}
235
236/// CMS `EncryptedData`, RFC5652 §8, used by PKCS#12 password privacy.
237pub struct EncryptedData<'a> {
238    /// Original content algorithm and attached/detached encrypted octets.
239    pub content: crate::enveloped::EncryptedContent<'a>,
240    /// Every original unprotected attribute, not authenticated bag metadata.
241    pub attributes: Option<OwnedVec<Attribute<'a>>>,
242    /// Parsed password-protection parameters, prepared once before callbacks.
243    pub protection: protection::Protection<'a>,
244}
245impl<'a> EncryptedData<'a> {
246    /// Reads a complete original `EncryptedData` SEQUENCE and version rule.
247    pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
248        let mut inside = sequence(parent, element)?;
249        let version = number(&mut inside)?;
250        let info = required(&mut inside, FIELD)?;
251        let content = crate::enveloped::encrypted_content(&inside, &info)?;
252        let attributes = inside
253            .next_element()
254            .map_err(encoding)?
255            .map(|set| attributes(&inside, &set, Tag::context(true, 1)))
256            .transpose()?;
257        end(&inside)?;
258        if version.as_u64() != Some(if attributes.is_some() { 2 } else { 0 }) {
259            return Err(invalid(ErrorCode::VersionMismatch, element));
260        }
261        if attributes.as_ref().is_some_and(|a| a.is_empty()) {
262            return Err(invalid(ErrorCode::EmptyAttributes, element));
263        }
264        let protection = protection::Protection::read(content.algorithm, parent)?;
265        Ok(Self {
266            content,
267            attributes,
268            protection,
269        })
270    }
271}
272
273/// RFC5958 `OneAsymmetricKey` / PKCS#8 `PrivateKeyInfo`.
274pub struct PrivateKey<'a> {
275    /// Zero is v1; one is v2. Validated against public-key presence.
276    pub version: u64,
277    /// Original algorithm, not a key/backend selection.
278    pub algorithm: AlgorithmIdentifier<'a>,
279    /// Original secret key contents. Borrowed, including BER fragments.
280    pub secret: Octets<'a>,
281    /// Original optional key attributes, distinct from bag attributes.
282    pub attributes: Option<OwnedVec<Attribute<'a>>>,
283    /// Validated original IMPLICIT BIT STRING, including BER segmentation.
284    pub public_key: Option<EncodedValue<'a>>,
285}
286impl<'a> PrivateKey<'a> {
287    /// Reads the original key container without normalizing or copying secrets.
288    pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
289        let mut inside = sequence(parent, element)?;
290        let version = number(&mut inside)?
291            .as_u64()
292            .ok_or_else(|| invalid(ErrorCode::ValueTooLarge, element))?;
293        let algorithm = algorithm(&mut inside)?;
294        let value = required(&mut inside, FIELD)?;
295        let secret = Octets::read(&inside, &value, FIELD)?;
296        let mut next = inside.next_element().map_err(encoding)?;
297        let attributes = if let Some(set) = next.filter(|v| v.tag() == Tag::context(true, 0)) {
298            let attributes = attributes(&inside, &set, Tag::context(true, 0))?;
299            next = inside.next_element().map_err(encoding)?;
300            Some(attributes)
301        } else {
302            None
303        };
304        let public_key = if let Some(bits) = next {
305            if bits.tag() != Tag::context(false, 1) && bits.tag() != Tag::context(true, 1) {
306                return Err(invalid(ErrorCode::UnexpectedTag, &bits));
307            }
308            structured_pkix::der::implicit_bit_string(&inside, &bits, FIELD)
309                .map_err(Error::pkix)?;
310            Some(EncodedValue::new(&inside, bits))
311        } else {
312            None
313        };
314        end(&inside)?;
315        if version != u64::from(public_key.is_some()) {
316            return Err(invalid(ErrorCode::VersionMismatch, element));
317        }
318        Ok(Self {
319            version,
320            algorithm,
321            secret,
322            attributes,
323            public_key,
324        })
325    }
326}
327
328/// `EncryptedPrivateKeyInfo`, with original protection parameters/ciphertext.
329pub struct ShroudedKey<'a> {
330    /// Original protection algorithm.
331    pub algorithm: AlgorithmIdentifier<'a>,
332    /// Original encrypted private-key contents.
333    pub encrypted: Octets<'a>,
334    /// Structural password-protection interpretation; unknown remains open.
335    pub protection: protection::Protection<'a>,
336}
337impl<'a> ShroudedKey<'a> {
338    /// Reads the whole original encrypted key, without KDF/decryption work.
339    pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
340        let mut inside = sequence(parent, element)?;
341        let algorithm = algorithm(&mut inside)?;
342        let value = required(&mut inside, FIELD)?;
343        let encrypted = Octets::read(&inside, &value, FIELD)?;
344        end(&inside)?;
345        let protection = protection::Protection::read(algorithm, parent)?;
346        Ok(Self {
347            algorithm,
348            encrypted,
349            protection,
350        })
351    }
352}
353
354/// A typed original bag value, including open types and nested bags.
355#[expect(
356    clippy::large_enum_variant,
357    reason = "one bag is decoded/visited at a time; inline protection facts avoid an extra heap owner per shrouded key"
358)]
359pub enum BagValue<'a> {
360    /// Plain PKCS#8 key.
361    Key(PrivateKey<'a>),
362    /// Shrouded PKCS#8 key.
363    Shrouded(ShroudedKey<'a>),
364    /// X.509 certificate bytes (not implicitly parsed/authenticated).
365    Certificate(Octets<'a>),
366    /// SDSI base64 certificate text with shared IA5 syntax validation.
367    Sdsi(Octets<'a>),
368    /// X.509 CRL bytes (not implicitly authenticated).
369    Crl(Octets<'a>),
370    /// A registered or unknown secret value.
371    Secret {
372        /// Original secret-type OID.
373        kind: Oid<'a>,
374        /// Whole original open value.
375        value: EncodedValue<'a>,
376    },
377    /// An open bag/certificate/CRL type, without guessed normalization.
378    Other {
379        /// Original type OID.
380        kind: Oid<'a>,
381        /// Whole original open value.
382        value: EncodedValue<'a>,
383    },
384    /// Nested `SafeContents`, visited iteratively by the processor.
385    Contents(EncodedValue<'a>),
386}
387/// `SafeBag` with original identity/attributes and decoded value.
388pub struct Bag<'a> {
389    /// Original bag identifier, including unknown extensions.
390    pub kind: Oid<'a>,
391    /// Original whole bag encoding and producing context.
392    pub original: EncodedValue<'a>,
393    /// Parsed original value, never a product-selected key.
394    pub value: BagValue<'a>,
395    /// Optional original attributes, including repeated/empty unknown values.
396    pub attributes: Option<OwnedVec<Attribute<'a>>>,
397}
398impl<'a> Bag<'a> {
399    /// Reads one complete original `SafeBag`. All six standard alternatives use
400    /// the existing shared field kernels, not a second BER grammar.
401    pub fn read(parent: &Reader<'a>, element: &Element<'a>) -> Result<Self> {
402        let mut inside = sequence(parent, element)?;
403        let kind = inside.read_oid().map_err(encoding)?;
404        let wrapper = inside.expect(Tag::context(true, 0)).map_err(encoding)?;
405        let mut explicit = inside.enter(&wrapper).map_err(encoding)?;
406        let value = required(&mut explicit, FIELD)?;
407        end(&explicit)?;
408        let attributes = inside
409            .next_element()
410            .map_err(encoding)?
411            .map(|set| attributes(&inside, &set, Tag::constructed(universal::SET)))
412            .transpose()?;
413        end(&inside)?;
414        // RFC7292 §4.2: BAG-TYPE is extensible. Unknown does not mean KeyBag.
415        let value = if bag_id(parent, kind, 1)? {
416            BagValue::Key(PrivateKey::read(&explicit, &value)?)
417        } else if bag_id(parent, kind, 2)? {
418            BagValue::Shrouded(ShroudedKey::read(&explicit, &value)?)
419        } else if bag_id(parent, kind, 6)? {
420            tag(&value, Tag::constructed(universal::SEQUENCE))?;
421            BagValue::Contents(EncodedValue::new(&explicit, value))
422        } else if bag_id(parent, kind, 3)? || bag_id(parent, kind, 4)? || bag_id(parent, kind, 5)? {
423            let mut typed = sequence(&explicit, &value)?;
424            let inner_kind = typed.read_oid().map_err(encoding)?;
425            let wrapper = typed.expect(Tag::context(true, 0)).map_err(encoding)?;
426            let mut inner = typed.enter(&wrapper).map_err(encoding)?;
427            let content = required(&mut inner, FIELD)?;
428            end(&inner)?;
429            end(&typed)?;
430            let certificate = Oid::from_bytes(&[42, 134, 72, 134, 247, 13, 1, 9, 22, 1]);
431            let sdsi = Oid::from_bytes(&[42, 134, 72, 134, 247, 13, 1, 9, 22, 2]);
432            let crl = Oid::from_bytes(&[42, 134, 72, 134, 247, 13, 1, 9, 23, 1]);
433            if bag_id(parent, kind, 5)? {
434                structured_pkix::der::conforms(&inner, &content, FIELD).map_err(Error::pkix)?;
435                BagValue::Secret {
436                    kind: inner_kind,
437                    value: EncodedValue::new(&inner, content),
438                }
439            } else if bag_id(parent, kind, 3)? && equal_oid(parent, inner_kind, certificate)? {
440                BagValue::Certificate(Octets::read(&inner, &content, FIELD)?)
441            } else if bag_id(parent, kind, 3)? && equal_oid(parent, inner_kind, sdsi)? {
442                BagValue::Sdsi(Octets::read_ia5(&inner, &content, FIELD)?)
443            } else if bag_id(parent, kind, 4)? && equal_oid(parent, inner_kind, crl)? {
444                BagValue::Crl(Octets::read(&inner, &content, FIELD)?)
445            } else {
446                structured_pkix::der::conforms(&inner, &content, FIELD).map_err(Error::pkix)?;
447                BagValue::Other {
448                    kind: inner_kind,
449                    value: EncodedValue::new(&inner, content),
450                }
451            }
452        } else {
453            structured_pkix::der::conforms(&explicit, &value, FIELD).map_err(Error::pkix)?;
454            BagValue::Other {
455                kind,
456                value: EncodedValue::new(&explicit, value),
457            }
458        };
459        Ok(Self {
460            kind,
461            original: EncodedValue::new(parent, *element),
462            value,
463            attributes,
464        })
465    }
466}
467
468fn bag_id(parent: &Reader<'_>, oid: Oid<'_>, last: u8) -> Result<bool> {
469    equal_oid(
470        parent,
471        oid,
472        Oid::from_bytes(&[42, 134, 72, 134, 247, 13, 1, 12, 10, 1, last]),
473    )
474}
475pub(super) fn equal_oid(parent: &Reader<'_>, left: Oid<'_>, right: Oid<'_>) -> Result<bool> {
476    parent.charge(1).map_err(encoding)?;
477    if left.as_bytes().len() != right.as_bytes().len() {
478        return Ok(false);
479    }
480    parent
481        .charge(left.as_bytes().len() as u64)
482        .map_err(encoding)?;
483    Ok(left == right)
484}
485fn attributes<'a>(
486    parent: &Reader<'a>,
487    set: &Element<'a>,
488    expected: Tag,
489) -> Result<OwnedVec<Attribute<'a>>> {
490    tag(set, expected)?;
491    let mut inside = parent.enter(set).map_err(encoding)?;
492    let execution = parent.execution();
493    let mut out = execution.vector();
494    let mut previous = None;
495    while let Some(value) = inside.next_element().map_err(encoding)? {
496        if inside.encoding().is_der() {
497            if let Some(bytes) = previous
498                && !structured_pkix::der::set_ordered(&inside, bytes, &value, FIELD)
499                    .map_err(Error::pkix)?
500            {
501                return Err(invalid(ErrorCode::SetOrder, &value));
502            }
503            previous = Some(value.as_bytes());
504        }
505        let attribute = Attribute::read(&inside, &value, FIELD)?;
506        // DER values were already walked by Attribute::read. BER inspection
507        // must reopen the saved value context: the list cursor is two levels
508        // above attrValues and would grant nested values those levels for free.
509        if !inside.encoding().is_der() {
510            for (ordinal, item) in attribute.values().iter().enumerate() {
511                let reader = attribute
512                    .value_reader_in(ordinal, &inside, FIELD)?
513                    .expect("ordinal comes from this attribute's original values");
514                structured_pkix::der::conforms(&reader, item, FIELD).map_err(Error::pkix)?;
515            }
516        }
517        out.try_push(attribute)
518            .map_err(|e| Error::resource(e, FIELD, value.span().start))?;
519    }
520    Ok(out.into_owned())
521}
522pub(super) fn sequence<'a>(parent: &Reader<'a>, element: &Element<'a>) -> Result<Reader<'a>> {
523    tag(element, Tag::constructed(universal::SEQUENCE))?;
524    parent.enter(element).map_err(encoding)
525}
526pub(super) fn tag(element: &Element<'_>, expected: Tag) -> Result<()> {
527    if element.tag() != expected {
528        return Err(invalid(ErrorCode::UnexpectedTag, element));
529    }
530    Ok(())
531}
532pub(super) fn end(parent: &Reader<'_>) -> Result<()> {
533    if !parent.is_empty() {
534        return Err(Error::schema(
535            ErrorCode::TrailingData,
536            FIELD,
537            parent.offset(),
538        ));
539    }
540    Ok(())
541}
542pub(super) fn number<'a>(parent: &mut Reader<'a>) -> Result<Integer<'a>> {
543    parent.read_integer().map_err(encoding)
544}
545pub(super) fn positive(value: Integer<'_>, element: &Element<'_>) -> Result<()> {
546    if value.is_negative() || value.as_u64() == Some(0) {
547        return Err(invalid(ErrorCode::MalformedValue, element));
548    }
549    Ok(())
550}
551fn default_one(parent: &Reader<'_>, value: Integer<'_>, element: &Element<'_>) -> Result<()> {
552    if parent.encoding().is_der() && value.as_u64() == Some(1) {
553        return Err(invalid(ErrorCode::DefaultWritten, element));
554    }
555    Ok(())
556}
557pub(super) fn algorithm<'a>(parent: &mut Reader<'a>) -> Result<AlgorithmIdentifier<'a>> {
558    let element = required(parent, FIELD)?;
559    structured_pkix::algorithm::read(parent, &element, FIELD).map_err(Error::pkix)
560}
561pub(super) fn invalid(code: ErrorCode, element: &Element<'_>) -> Error {
562    Error::schema(code, FIELD, element.span().start)
563}
564pub(super) fn encoding(error: structured_asn1::Error) -> Error {
565    Error::encoding(error, FIELD)
566}