x509_certificate/
rfc5280.rs

1// This Source Code Form is subject to the terms of the Mozilla Public
2// License, v. 2.0. If a copy of the MPL was not distributed with this
3// file, You can obtain one at https://mozilla.org/MPL/2.0/.
4
5/*! ASN.1 types defined RFC 5280. */
6
7use {
8    crate::{asn1time::*, rfc3280::*},
9    bcder::{
10        decode::{BytesSource, Constructed, DecodeError, IntoSource, Source},
11        encode,
12        encode::{PrimitiveContent, Values},
13        BitString, Captured, Integer, Mode, OctetString, Oid, Tag,
14    },
15    bytes::Bytes,
16    std::{
17        fmt::{Debug, Formatter},
18        io::Write,
19        ops::{Deref, DerefMut},
20    },
21};
22
23/// Algorithm identifier.
24///
25/// ```ASN.1
26/// AlgorithmIdentifier  ::=  SEQUENCE  {
27///   algorithm               OBJECT IDENTIFIER,
28///   parameters              ANY DEFINED BY algorithm OPTIONAL  }
29/// ```
30#[derive(Clone, Eq, PartialEq)]
31pub struct AlgorithmIdentifier {
32    pub algorithm: Oid,
33    pub parameters: Option<AlgorithmParameter>,
34}
35
36impl Debug for AlgorithmIdentifier {
37    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
38        let mut s = f.debug_struct("AlgorithmIdentifier");
39        s.field("algorithm", &format_args!("{}", self.algorithm));
40        s.field("parameters", &self.parameters);
41        s.finish()
42    }
43}
44
45impl AlgorithmIdentifier {
46    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
47        cons.take_sequence(|cons| Self::take_sequence(cons))
48    }
49
50    pub fn take_opt_from<S: Source>(
51        cons: &mut Constructed<S>,
52    ) -> Result<Option<Self>, DecodeError<S::Error>> {
53        cons.take_opt_sequence(|cons| Self::take_sequence(cons))
54    }
55
56    fn take_sequence<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
57        let algorithm = Oid::take_from(cons)?;
58        let parameters = cons.capture_all()?;
59
60        let parameters = if parameters.is_empty() {
61            None
62        } else {
63            Some(AlgorithmParameter(parameters))
64        };
65
66        Ok(Self {
67            algorithm,
68            parameters,
69        })
70    }
71
72    fn encoded_values(&self, mode: Mode) -> impl Values + '_ {
73        // parameters is strictly OPTIONAL, which means we can omit it completely.
74        // However, it is common to see this field encoded as NULL and some
75        // parsers seem to insist the NULL be there or else they refuse to
76        // parse the ASN.1. So we ensure this field is always set.
77        let captured = if let Some(params) = self.parameters.as_ref() {
78            params.clone()
79        } else {
80            AlgorithmParameter(Captured::from_values(mode, ().encode_as(Tag::NULL)))
81        };
82
83        encode::sequence((self.algorithm.clone().encode(), captured))
84    }
85}
86
87impl Values for AlgorithmIdentifier {
88    fn encoded_len(&self, mode: Mode) -> usize {
89        self.encoded_values(mode).encoded_len(mode)
90    }
91
92    fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
93        self.encoded_values(mode).write_encoded(mode, target)
94    }
95}
96
97/// A parameter for an algorithm.
98///
99/// This type doesn't exist in the ASN.1. We've implemented it to
100/// make (de)serialization simpler.
101#[derive(Clone, Debug)]
102pub struct AlgorithmParameter(Captured);
103
104impl AlgorithmParameter {
105    pub fn from_captured(captured: Captured) -> Self {
106        Self(captured)
107    }
108
109    /// Construct a new instance consisting of a single OID.
110    pub fn from_oid(oid: Oid) -> Self {
111        let captured = Captured::from_values(Mode::Der, oid.encode());
112
113        Self(captured)
114    }
115
116    /// Attempt to decode a single OID from the captured value.
117    pub fn decode_oid(&self) -> Result<Oid, DecodeError<<BytesSource as Source>::Error>> {
118        let source = BytesSource::new(Bytes::copy_from_slice(self.0.as_slice()));
119
120        Constructed::decode(source, Mode::Der, Oid::take_from)
121    }
122}
123
124impl Deref for AlgorithmParameter {
125    type Target = Captured;
126
127    fn deref(&self) -> &Self::Target {
128        &self.0
129    }
130}
131
132impl DerefMut for AlgorithmParameter {
133    fn deref_mut(&mut self) -> &mut Self::Target {
134        &mut self.0
135    }
136}
137
138impl PartialEq for AlgorithmParameter {
139    fn eq(&self, other: &Self) -> bool {
140        self.0.as_slice() == other.0.as_slice()
141    }
142}
143
144impl Eq for AlgorithmParameter {}
145
146impl Values for AlgorithmParameter {
147    fn encoded_len(&self, mode: Mode) -> usize {
148        self.0.encoded_len(mode)
149    }
150
151    fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
152        self.0.write_encoded(mode, target)
153    }
154}
155
156/// An X.509 certificate.
157///
158/// This is the main data structure representing an X.509 certificate.
159///
160/// ```ASN.1
161/// Certificate  ::=  SEQUENCE  {
162///   tbsCertificate       TBSCertificate,
163///   signatureAlgorithm   AlgorithmIdentifier,
164///   signature            BIT STRING  }
165/// ```
166#[derive(Clone, Eq, PartialEq)]
167pub struct Certificate {
168    pub tbs_certificate: TbsCertificate,
169    pub signature_algorithm: AlgorithmIdentifier,
170    pub signature: BitString,
171}
172
173impl Debug for Certificate {
174    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
175        let mut s = f.debug_struct("Certificate");
176        s.field("tbs_certificate", &self.tbs_certificate);
177        s.field("signature_algorithm", &self.signature_algorithm);
178        s.field(
179            "signature",
180            &format_args!(
181                "{} (unused {})",
182                hex::encode(self.signature.octet_bytes()),
183                self.signature.unused()
184            ),
185        );
186        s.finish()
187    }
188}
189
190impl Certificate {
191    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
192        cons.take_sequence(|cons| Self::from_sequence(cons))
193    }
194
195    pub fn from_sequence<S: Source>(
196        cons: &mut Constructed<S>,
197    ) -> Result<Self, DecodeError<S::Error>> {
198        let tbs_certificate = TbsCertificate::take_from(cons)?;
199        let signature_algorithm = AlgorithmIdentifier::take_from(cons)?;
200        let signature = BitString::take_from(cons)?;
201
202        Ok(Self {
203            tbs_certificate,
204            signature_algorithm,
205            signature,
206        })
207    }
208
209    pub fn encode_ref(&self) -> impl Values + '_ {
210        encode::sequence((
211            self.tbs_certificate.encode_ref(),
212            &self.signature_algorithm,
213            self.signature.encode_ref(),
214        ))
215    }
216
217    /// Iterate over extensions defined on this certificate.
218    pub fn iter_extensions(&self) -> impl Iterator<Item = &Extension> {
219        self.tbs_certificate
220            .extensions
221            .iter()
222            .flat_map(|x| x.iter())
223    }
224}
225
226/// TBS Certificate.
227///
228/// This holds most of the metadata within an X.509 certificate.
229///
230/// ```ASN.1
231/// TBSCertificate  ::=  SEQUENCE  {
232///      version         [0]  Version DEFAULT v1,
233///      serialNumber         CertificateSerialNumber,
234///      signature            AlgorithmIdentifier,
235///      issuer               Name,
236///      validity             Validity,
237///      subject              Name,
238///      subjectPublicKeyInfo SubjectPublicKeyInfo,
239///      issuerUniqueID  [1]  IMPLICIT UniqueIdentifier OPTIONAL,
240///                           -- If present, version MUST be v2 or v3
241///      subjectUniqueID [2]  IMPLICIT UniqueIdentifier OPTIONAL,
242///                           -- If present, version MUST be v2 or v3
243///      extensions      [3]  Extensions OPTIONAL
244///                           -- If present, version MUST be v3 --  }
245/// ```
246#[derive(Clone, Eq, PartialEq)]
247pub struct TbsCertificate {
248    pub version: Option<Version>,
249    pub serial_number: CertificateSerialNumber,
250    pub signature: AlgorithmIdentifier,
251    pub issuer: Name,
252    pub validity: Validity,
253    pub subject: Name,
254    pub subject_public_key_info: SubjectPublicKeyInfo,
255    pub issuer_unique_id: Option<UniqueIdentifier>,
256    pub subject_unique_id: Option<UniqueIdentifier>,
257    pub extensions: Option<Extensions>,
258
259    /// Raw bytes this instance was constructed from.
260    ///
261    /// This is what signature verification should be performed against.
262    pub raw_data: Option<Vec<u8>>,
263}
264
265impl Debug for TbsCertificate {
266    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
267        let mut s = f.debug_struct("TbsCertificate");
268        s.field("version", &self.version);
269        s.field("serial_number", &self.serial_number);
270        s.field("signature", &self.signature);
271        s.field("issuer", &self.issuer);
272        s.field("validity", &self.validity);
273        s.field("subject", &self.subject);
274        s.field("subject_public_key_info", &self.subject_public_key_info);
275        s.field("issuer_unique_id", &self.issuer_unique_id);
276        s.field("subject_unique_id", &self.subject_unique_id);
277        s.field("extensions", &self.extensions);
278        s.field(
279            "raw_data",
280            &format_args!("{:?}", self.raw_data.as_ref().map(hex::encode)),
281        );
282        s.finish()
283    }
284}
285
286impl TbsCertificate {
287    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
288        // The TbsCertificate data is what's signed by the issuing certificate. To
289        // facilitate signature verification, we stash away the raw data so they
290        // can be accessed later.
291        let mut res = None;
292
293        let captured = cons.capture(|cons| {
294            cons.take_sequence(|cons| {
295                let version = cons.take_opt_constructed_if(Tag::CTX_0, Version::take_from)?;
296                let serial_number = CertificateSerialNumber::take_from(cons)?;
297                let signature = AlgorithmIdentifier::take_from(cons)?;
298                let issuer = Name::take_from(cons)?;
299                let validity = Validity::take_from(cons)?;
300                let subject = Name::take_from(cons)?;
301                let subject_public_key_info = SubjectPublicKeyInfo::take_from(cons)?;
302                let issuer_unique_id = cons.take_opt_constructed_if(Tag::CTX_1, |cons| {
303                    UniqueIdentifier::take_from(cons)
304                })?;
305                let subject_unique_id = cons.take_opt_constructed_if(Tag::CTX_2, |cons| {
306                    UniqueIdentifier::take_from(cons)
307                })?;
308                let extensions =
309                    cons.take_opt_constructed_if(Tag::CTX_3, Extensions::take_from)?;
310
311                res = Some(Self {
312                    version,
313                    serial_number,
314                    signature,
315                    issuer,
316                    validity,
317                    subject,
318                    subject_public_key_info,
319                    issuer_unique_id,
320                    subject_unique_id,
321                    extensions,
322                    raw_data: None,
323                });
324
325                Ok(())
326            })
327        })?;
328
329        let mut res = res.unwrap();
330        res.raw_data = Some(captured.to_vec());
331
332        Ok(res)
333    }
334
335    pub fn encode_ref(&self) -> impl Values + '_ {
336        encode::sequence((
337            self.version
338                .as_ref()
339                .map(|v| encode::Constructed::new(Tag::CTX_0, u8::from(*v).encode())),
340            (&self.serial_number).encode(),
341            &self.signature,
342            self.issuer.encode_ref(),
343            self.validity.encode_ref(),
344            self.subject.encode_ref(),
345            self.subject_public_key_info.encode_ref(),
346            self.issuer_unique_id
347                .as_ref()
348                .map(|id| id.encode_ref_as(Tag::CTX_1)),
349            self.subject_unique_id
350                .as_ref()
351                .map(|id| id.encode_ref_as(Tag::CTX_2)),
352            self.extensions
353                .as_ref()
354                .map(|extensions| encode::Constructed::new(Tag::CTX_3, extensions.encode_ref())),
355        ))
356    }
357}
358
359#[derive(Clone, Copy, Debug, Eq, PartialEq)]
360pub enum Version {
361    V1 = 0,
362    V2 = 1,
363    V3 = 2,
364}
365
366impl Version {
367    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
368        match cons.take_primitive_if(Tag::INTEGER, Integer::i8_from_primitive)? {
369            0 => Ok(Self::V1),
370            1 => Ok(Self::V2),
371            2 => Ok(Self::V3),
372            _ => Err(cons.content_err("unexpected Version value")),
373        }
374    }
375
376    pub fn take_opt_from<S: Source>(
377        cons: &mut Constructed<S>,
378    ) -> Result<Option<Self>, DecodeError<S::Error>> {
379        match cons.take_opt_primitive_if(Tag::INTEGER, Integer::i8_from_primitive)? {
380            Some(0) => Ok(Some(Self::V1)),
381            Some(1) => Ok(Some(Self::V2)),
382            Some(2) => Ok(Some(Self::V3)),
383            _ => Err(cons.content_err("unexpected Version value")),
384        }
385    }
386
387    pub fn encode(self) -> impl Values {
388        u8::from(self).encode()
389    }
390}
391
392impl From<Version> for u8 {
393    fn from(v: Version) -> Self {
394        match v {
395            Version::V1 => 0,
396            Version::V2 => 1,
397            Version::V3 => 2,
398        }
399    }
400}
401
402pub type CertificateSerialNumber = Integer;
403
404#[derive(Clone, Debug, Eq, PartialEq)]
405pub struct Validity {
406    pub not_before: Time,
407    pub not_after: Time,
408}
409
410impl Validity {
411    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
412        cons.take_sequence(|cons| {
413            let not_before = Time::take_from(cons)?;
414            let not_after = Time::take_from(cons)?;
415
416            Ok(Self {
417                not_before,
418                not_after,
419            })
420        })
421    }
422
423    pub fn encode_ref(&self) -> impl Values + '_ {
424        encode::sequence((self.not_before.encode_ref(), self.not_after.encode_ref()))
425    }
426}
427
428pub type UniqueIdentifier = BitString;
429
430/// Subject public key info.
431///
432/// ```ASN.1
433/// SubjectPublicKeyInfo  ::=  SEQUENCE  {
434///   algorithm            AlgorithmIdentifier,
435///   subjectPublicKey     BIT STRING  }
436/// ```
437#[derive(Clone, Eq, PartialEq)]
438pub struct SubjectPublicKeyInfo {
439    pub algorithm: AlgorithmIdentifier,
440    pub subject_public_key: BitString,
441}
442
443impl Debug for SubjectPublicKeyInfo {
444    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
445        let mut s = f.debug_struct("SubjectPublicKeyInfo");
446        s.field("algorithm", &self.algorithm);
447        s.field(
448            "subject_public_key",
449            &format_args!(
450                "{} (unused {})",
451                hex::encode(self.subject_public_key.octet_bytes().as_ref()),
452                self.subject_public_key.unused()
453            ),
454        );
455        s.finish()
456    }
457}
458
459impl SubjectPublicKeyInfo {
460    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
461        cons.take_sequence(|cons| {
462            let algorithm = AlgorithmIdentifier::take_from(cons)?;
463            let subject_public_key = BitString::take_from(cons)?;
464
465            Ok(Self {
466                algorithm,
467                subject_public_key,
468            })
469        })
470    }
471
472    pub fn encode_ref(&self) -> impl Values + '_ {
473        encode::sequence((&self.algorithm, self.subject_public_key.encode_ref()))
474    }
475}
476
477/// Extensions
478///
479/// ```ASN.1
480/// Extensions  ::=  SEQUENCE SIZE (1..MAX) OF Extension
481/// ```
482#[derive(Clone, Debug, Default, Eq, PartialEq)]
483pub struct Extensions(Vec<Extension>);
484
485impl Extensions {
486    pub fn take_opt_from<S: Source>(
487        cons: &mut Constructed<S>,
488    ) -> Result<Option<Self>, DecodeError<S::Error>> {
489        cons.take_opt_sequence(|cons| Self::from_sequence(cons))
490    }
491
492    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
493        cons.take_sequence(|cons| Self::from_sequence(cons))
494    }
495
496    pub fn from_sequence<S: Source>(
497        cons: &mut Constructed<S>,
498    ) -> Result<Self, DecodeError<S::Error>> {
499        let mut extensions = Vec::new();
500
501        while let Some(extension) = Extension::take_opt_from(cons)? {
502            extensions.push(extension);
503        }
504
505        Ok(Self(extensions))
506    }
507
508    pub fn encode_ref(&self) -> impl Values + '_ {
509        encode::sequence(&self.0)
510    }
511
512    pub fn encode_ref_as(&self, tag: Tag) -> impl Values + '_ {
513        encode::sequence_as(tag, &self.0)
514    }
515}
516
517impl Deref for Extensions {
518    type Target = Vec<Extension>;
519
520    fn deref(&self) -> &Self::Target {
521        &self.0
522    }
523}
524
525impl DerefMut for Extensions {
526    fn deref_mut(&mut self) -> &mut Self::Target {
527        &mut self.0
528    }
529}
530
531/// Extension.
532///
533/// ```ASN.1
534/// Extension  ::=  SEQUENCE  {
535///      extnID      OBJECT IDENTIFIER,
536///      critical    BOOLEAN DEFAULT FALSE,
537///      extnValue   OCTET STRING
538///                  -- contains the DER encoding of an ASN.1 value
539///                  -- corresponding to the extension type identified
540///                  -- by extnID
541///      }
542/// ```
543#[derive(Clone, Eq, PartialEq)]
544pub struct Extension {
545    pub id: Oid,
546    pub critical: Option<bool>,
547    pub value: OctetString,
548}
549
550impl Debug for Extension {
551    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
552        let mut s = f.debug_struct("Extension");
553        s.field("id", &format_args!("{}", self.id));
554        s.field("critical", &self.critical);
555        s.field(
556            "value",
557            &format_args!("{}", hex::encode(self.value.clone().into_bytes().as_ref())),
558        );
559        s.finish()
560    }
561}
562
563impl Extension {
564    pub fn take_opt_from<S: Source>(
565        cons: &mut Constructed<S>,
566    ) -> Result<Option<Self>, DecodeError<S::Error>> {
567        cons.take_opt_sequence(|cons| Self::from_sequence(cons))
568    }
569
570    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
571        cons.take_sequence(|cons| Self::from_sequence(cons))
572    }
573
574    fn from_sequence<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
575        let id = Oid::take_from(cons)?;
576        let critical = cons.take_opt_bool()?;
577        let value = OctetString::take_from(cons)?;
578
579        Ok(Self {
580            id,
581            critical,
582            value,
583        })
584    }
585
586    pub fn encode_ref(&self) -> impl Values + '_ {
587        encode::sequence((
588            self.id.encode_ref(),
589            if self.critical == Some(true) {
590                Some(true.encode())
591            } else {
592                None
593            },
594            self.value.encode_ref(),
595        ))
596    }
597
598    /// Attempt to decode a single OID present in an outer sequence.
599    ///
600    /// If this works, we return Some. Else None.
601    pub fn try_decode_sequence_single_oid(&self) -> Option<Oid> {
602        Constructed::decode(self.value.clone().into_source(), Mode::Der, |cons| {
603            cons.take_sequence(Oid::take_from)
604        })
605        .ok()
606    }
607}
608
609impl Values for Extension {
610    fn encoded_len(&self, mode: Mode) -> usize {
611        self.encode_ref().encoded_len(mode)
612    }
613
614    fn write_encoded<W: Write>(&self, mode: Mode, target: &mut W) -> Result<(), std::io::Error> {
615        self.encode_ref().write_encoded(mode, target)
616    }
617}
618
619/// Certificate list.
620///
621/// ```ASN.1
622/// CertificateList  ::=  SEQUENCE  {
623///      tbsCertList          TBSCertList,
624///      signatureAlgorithm   AlgorithmIdentifier,
625///      signature            BIT STRING  }
626/// ```
627#[derive(Clone, Debug, Eq, PartialEq)]
628pub struct CertificateList {
629    pub tbs_cert_list: TbsCertList,
630    pub signature_algorithm: AlgorithmIdentifier,
631    pub signature: BitString,
632}
633
634impl CertificateList {
635    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
636        cons.take_sequence(|cons| Self::from_sequence(cons))
637    }
638
639    pub fn take_opt_from<S: Source>(
640        cons: &mut Constructed<S>,
641    ) -> Result<Option<Self>, DecodeError<S::Error>> {
642        cons.take_opt_sequence(|cons| Self::from_sequence(cons))
643    }
644
645    pub fn from_sequence<S: Source>(
646        cons: &mut Constructed<S>,
647    ) -> Result<Self, DecodeError<S::Error>> {
648        let tbs_cert_list = TbsCertList::take_from(cons)?;
649        let signature_algorithm = AlgorithmIdentifier::take_from(cons)?;
650        let signature = BitString::take_from(cons)?;
651
652        Ok(Self {
653            tbs_cert_list,
654            signature_algorithm,
655            signature,
656        })
657    }
658}
659
660/// Tbs Certificate list.
661///
662/// ```ASN.1
663/// TBSCertList  ::=  SEQUENCE  {
664///   version                 Version OPTIONAL,
665///     -- if present, MUST be v2
666///   signature               AlgorithmIdentifier,
667///   issuer                  Name,
668///   thisUpdate              Time,
669///   nextUpdate              Time OPTIONAL,
670///   revokedCertificates     SEQUENCE OF SEQUENCE  {
671///     userCertificate         CertificateSerialNumber,
672///     revocationDate          Time,
673///     crlEntryExtensions      Extensions OPTIONAL
674///                                 -- if present, MUST be v2
675///  }  OPTIONAL,
676///  crlExtensions           [0] Extensions OPTIONAL }
677///                                -- if present, MUST be v2
678/// ```
679#[derive(Clone, Debug, Eq, PartialEq)]
680pub struct TbsCertList {
681    pub version: Option<Version>,
682    pub signature: AlgorithmIdentifier,
683    pub issuer: Name,
684    pub this_update: Time,
685    pub next_update: Option<Time>,
686    pub revoked_certificates: Vec<(CertificateSerialNumber, Time, Option<Extensions>)>,
687    pub crl_extensions: Option<Extensions>,
688}
689
690impl TbsCertList {
691    pub fn take_from<S: Source>(cons: &mut Constructed<S>) -> Result<Self, DecodeError<S::Error>> {
692        let version = Version::take_opt_from(cons)?;
693        let signature = AlgorithmIdentifier::take_from(cons)?;
694        let issuer = Name::take_from(cons)?;
695        let this_update = Time::take_from(cons)?;
696        let next_update = Time::take_opt_from(cons)?;
697        let revoked_certificates = Vec::new();
698        let crl_extensions = None::<Extensions>;
699
700        Ok(Self {
701            version,
702            signature,
703            issuer,
704            this_update,
705            next_update,
706            revoked_certificates,
707            crl_extensions,
708        })
709    }
710}