Skip to main content

pkix/
x509.rs

1/* Copyright (c) Fortanix, Inc.
2 *
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7use bitflags::bitflags;
8use yasna::{ASN1Error, ASN1ErrorKind, ASN1Result, BERReader, DERWriter, BERDecodable, Tag, tags::*};
9use num_integer::Integer;
10use num_bigint::{BigUint, BigInt};
11use std::{borrow::Cow, convert::TryFrom};
12use bit_vec::BitVec;
13use oid;
14
15use DerWrite;
16use types::*;
17use deserialize::FromBer;
18
19use crate::{ToDer, oid::{certificatePolicies, ID_QT_CPS, ID_QT_UNOTICE, ANY_POLICY}};
20
21pub type RsaPkcs15TbsCertificate<'a> = TbsCertificate<BigUint, RsaPkcs15<Sha256>, DerSequence<'a>>;
22pub type RsaPkcs15Certificate<'a> = Certificate<RsaPkcs15TbsCertificate<'a>, RsaPkcs15<Sha256>, BitVec>;
23
24pub type GenericTbsCertificate = TbsCertificate<BigUint, DerSequence<'static>, DerSequence<'static>>;
25
26pub type GenericCertificate = Certificate<GenericTbsCertificate, DerSequence<'static>, BitVec>;
27
28#[derive(Clone, Debug, Eq, PartialEq, Hash)]
29pub struct Certificate<T, A: SignatureAlgorithm, S> {
30    pub tbscert: T,
31    pub sigalg: A,
32    pub sig: S,
33}
34
35impl<T: DerWrite, A: SignatureAlgorithm + DerWrite, S: DerWrite> DerWrite for Certificate<T, A, S> {
36    fn write(&self, writer: DERWriter) {
37        writer.write_sequence(|writer| {
38            self.tbscert.write(writer.next());
39            self.sigalg.write(writer.next());
40            self.sig.write(writer.next());
41        });
42    }
43}
44
45impl<T: BERDecodable, A: SignatureAlgorithm + BERDecodable, S: BERDecodable> BERDecodable for Certificate<T, A, S> {
46    fn decode_ber<'a, 'b>(reader: BERReader<'a, 'b>) -> ASN1Result<Self> {
47        reader.read_sequence(|r| {
48            let tbscert = T::decode_ber(r.next())?;
49            let sigalg = A::decode_ber(r.next())?;
50            let sig = S::decode_ber(r.next())?;
51
52            Ok(Certificate { tbscert, sigalg, sig })
53        })
54    }
55}
56
57#[derive(Clone, Debug, Eq, PartialEq, Hash)]
58pub struct TbsCertificate<S: Integer, A: SignatureAlgorithm, K> {
59    pub version: u8,
60    pub serial: S,
61    pub sigalg: A,
62    pub issuer: Name,
63    pub validity_notbefore: DateTime,
64    pub validity_notafter: DateTime,
65    pub subject: Name,
66    pub spki: K,
67    pub extensions: Vec<Extension>,
68}
69
70impl<S: Integer, A: SignatureAlgorithm, K> TbsCertificate<S, A, K> {
71    /// Find the extension indicated by `oid`. If exactly one instance
72    /// of the extension is present, returns it. Otherwise, returns `None`.
73    pub fn get_extension(&self, oid: &ObjectIdentifier) -> Option<Extension> {
74        let mut iter = self.extensions.iter().filter(|e| e.oid == *oid);
75
76        match (iter.next(), iter.next()) {
77            (Some(ext), None) => Some(ext.to_owned()),
78            _ => None,
79        }
80    }
81}
82
83pub const TBS_CERTIFICATE_V1: u8 = 0;
84pub const TBS_CERTIFICATE_V2: u8 = 1;
85pub const TBS_CERTIFICATE_V3: u8 = 2;
86
87impl<S: DerWrite + Integer, A: DerWrite + SignatureAlgorithm, K: DerWrite> DerWrite
88    for TbsCertificate<S, A, K> {
89    fn write(&self, writer: DERWriter) {
90        writer.write_sequence(|writer| {
91            if self.version != TBS_CERTIFICATE_V1 { // default value
92                writer.next().write_tagged(Tag::context(0), |w| self.version.write(w));
93            }
94            self.serial.write(writer.next());
95            self.sigalg.write(writer.next());
96            self.issuer.write(writer.next());
97            writer.next().write_sequence(|writer| {
98                self.validity_notbefore.write(writer.next());
99                self.validity_notafter.write(writer.next());
100            });
101            self.subject.write(writer.next());
102            self.spki.write(writer.next());
103            if !self.extensions.is_empty() {
104                writer.next().write_tagged(Tag::context(3), |w| {
105                    w.write_sequence(|writer| {
106                        for ext in &self.extensions {
107                            ext.write(writer.next())
108                        }
109                    })
110                });
111            }
112        });
113    }
114}
115
116impl<S: BERDecodable + Integer, A: BERDecodable + SignatureAlgorithm, K: BERDecodable> BERDecodable for TbsCertificate<S, A, K> {
117    fn decode_ber<'a, 'b>(reader: BERReader<'a, 'b>) -> ASN1Result<Self> {
118        reader.read_sequence(|r| {
119            let version = r.read_optional(|r| r.read_tagged(Tag::context(0), |r| r.read_u8()))?.unwrap_or(0);
120            match version {
121                TBS_CERTIFICATE_V1 | TBS_CERTIFICATE_V2 | TBS_CERTIFICATE_V3 => { /* known version */ }
122                _ => { return Err(ASN1Error::new(ASN1ErrorKind::Invalid)); }
123            };
124            let serial = S::decode_ber(r.next())?;
125            let sigalg = A::decode_ber(r.next())?;
126            let issuer = Name::decode_ber(r.next())?;
127            let (validity_notbefore,
128                 validity_notafter) = r.next().read_sequence(|r| {
129                Ok((DateTime::decode_ber(r.next())?,
130                    DateTime::decode_ber(r.next())?))
131            })?;
132            let subject = Name::decode_ber(r.next())?;
133            let spki = K::decode_ber(r.next())?;
134            let extensions = r.read_optional(|r| {
135                if version != TBS_CERTIFICATE_V3 {
136                    return Err(ASN1Error::new(ASN1ErrorKind::Invalid));
137                }
138                r.read_tagged(Tag::context(3), |r| {
139                    r.read_sequence(|r| {
140                        let mut extensions = Vec::<Extension>::new();
141
142                        loop {
143                            let res = r.read_optional(|r| {
144                                Extension::decode_ber(r)
145                            });
146                            match res {
147                                Ok(Some(ext)) => extensions.push(ext),
148                                Ok(None) => break,
149                                Err(e) => return Err(e),
150                            }
151                        }
152
153                        Ok(extensions)
154                    })
155                })
156            })?.unwrap_or(vec![]);
157
158            Ok(TbsCertificate { version, serial, sigalg, issuer, validity_notbefore, validity_notafter,
159                                subject, spki, extensions })
160        })
161    }
162}
163
164/// X.509 `SubjectPublicKeyInfo` (SPKI) as defined in [RFC 5280 § 4.1.2.7].
165///
166/// ASN.1 structure containing an [`AlgorithmIdentifier`] and public key
167/// data in an algorithm specific format.
168///
169/// ```text
170///    SubjectPublicKeyInfo  ::=  SEQUENCE  {
171///         algorithm            AlgorithmIdentifier,
172///         subjectPublicKey     BIT STRING  }
173/// ```
174///
175/// [RFC 5280 § 4.1.2.7]: https://tools.ietf.org/html/rfc5280#section-4.1.2.7
176/// [`AlgorithmIdentifier`]: crate::algorithms::AlgorithmIdentifier
177#[derive(Clone, Debug, Eq, PartialEq, Hash)]
178pub struct SubjectPublicKeyInfo<A: SignatureAlgorithm = DerSequence<'static>> {
179    /// X.509 [`AlgorithmIdentifier`](crate::algorithms::AlgorithmIdentifier) for the public key type
180    pub algorithm: A,
181
182    /// Public key data
183    pub subject_public_key: BitVec,
184}
185
186impl<A: SignatureAlgorithm + DerWrite> DerWrite for SubjectPublicKeyInfo<A> {
187    fn write(&self, writer: DERWriter) {
188        writer.write_sequence(|writer| {
189            self.algorithm.write(writer.next());
190            self.subject_public_key.write(writer.next());
191        });
192    }
193}
194
195impl<A: SignatureAlgorithm + BERDecodable> BERDecodable for SubjectPublicKeyInfo<A> {
196    fn decode_ber(reader: BERReader) -> ASN1Result<Self> {
197        reader.read_sequence(|reader| {
198            let algorithm = A::decode_ber(reader.next())?;
199            let subject_public_key = BitVec::decode_ber(reader.next())?;
200            Ok(SubjectPublicKeyInfo {
201                algorithm,
202                subject_public_key,
203            })
204        })
205    }
206}
207
208define_version! {
209    /// Certificate `Version` as defined in [RFC 5280 Section 4.1].
210    ///
211    /// ```text
212    /// Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }
213    /// ```
214    ///
215    /// [RFC 5280 Section 4.1]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.1
216    Version {
217        V1 = 0,
218        V2 = 1,
219        V3 = 2,
220    }
221}
222
223derive_sequence! {
224    /// X.501 `AttributeTypeAndValue` as defined in [RFC 5280 Appendix A.1].
225    ///
226    /// ```text
227    /// AttributeTypeAndValue ::= SEQUENCE {
228    ///   type     AttributeType,
229    ///   value    AttributeValue
230    /// }
231    /// ```
232    ///
233    /// [RFC 5280 Appendix A.1]: https://datatracker.ietf.org/doc/html/rfc5280#appendix-A.1
234    AttributeTypeAndValue {
235        oid: ObjectIdentifier,
236        value: TaggedDerValue,
237    }
238}
239
240/// This trait can be used to indicate the value for the `critical` bit for
241/// types that can be encoded as X.509 `Extension`.
242pub trait IsCritical {
243    fn is_critical(&self) -> bool;
244}
245
246pub trait ToExtension {
247    fn to_extension(&self) -> Extension;
248}
249
250impl<T: HasOid + IsCritical + ToDer> ToExtension for T {
251    fn to_extension(&self) -> Extension {
252        Extension {
253            oid: T::oid().clone(),
254            critical: self.is_critical(),
255            value: self.to_der(),
256        }
257    }
258}
259
260impl IsCritical for BasicConstraints {
261    fn is_critical(&self) -> bool {
262        true
263    }
264}
265
266/// BasicConstraints type as defined in RFC 5280.
267#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
268pub struct BasicConstraints {
269    ca: bool,
270    path_len_constraint: Option<u64>,
271}
272
273impl BasicConstraints {
274    pub fn ca(path_len_constraint: Option<u64>) -> Self {
275        BasicConstraints { ca: true, path_len_constraint }
276    }
277
278    pub fn no_ca() -> Self {
279        BasicConstraints { ca: false, path_len_constraint: None }
280    }
281
282    /// Returns the value of the `cA` field, as defined in RFC 5280.
283    pub fn is_ca(&self) -> bool {
284        self.ca
285    }
286
287    /// Returns the value of the `pathLenConstraint` field, as defined in RFC 5280.
288    ///
289    /// Note that the RFC states that the `pathLenConstraint` field is meaningful only if the
290    /// `cA` boolean is asserted. It is up to the users of this method to enforce that statement.
291    pub fn path_len_constraint(&self) -> Option<u64> {
292        self.path_len_constraint
293    }
294}
295
296impl HasOid for BasicConstraints {
297    fn oid() -> &'static ObjectIdentifier {
298        &oid::basicConstraints
299    }
300}
301
302impl DerWrite for BasicConstraints {
303    fn write(&self, writer: DERWriter) {
304        writer.write_sequence(|writer| {
305            if self.ca { // do not write field if `ca` is equal to default value `false`
306                writer.next().write_bool(true);
307            }
308            if let Some(path_len) = self.path_len_constraint {
309                writer.next().write_u64(path_len);
310            }
311        });
312    }
313}
314
315impl BERDecodable for BasicConstraints {
316    fn decode_ber(reader: BERReader) -> ASN1Result<Self> {
317        reader.read_sequence(|r| {
318            let ca = r.read_default(false, |r| r.read_bool())?;
319            let path_len_constraint = r.read_optional(|r| r.read_u64())?;
320            Ok(BasicConstraints { ca, path_len_constraint })
321        })
322    }
323}
324
325#[deprecated(since="0.1.3", note="use `SubjectAltName` instead")]
326#[derive(Clone, Debug, Eq, PartialEq, Hash)]
327pub struct DnsAltNames<'a> {
328    pub names: Vec<Cow<'a, str>>,
329}
330
331#[allow(deprecated)]
332impl<'a> DerWrite for DnsAltNames<'a> {
333    fn write(&self, writer: DERWriter) {
334        writer.write_sequence(|writer| {
335            for name in &self.names {
336                writer.next().write_tagged_implicit(Tag::context(2), |w|
337                    name.as_bytes().write(w)
338                )
339            }
340        });
341    }
342}
343
344#[allow(deprecated)]
345impl<'a> BERDecodable for DnsAltNames<'a> {
346    fn decode_ber(reader: BERReader) -> ASN1Result<Self> {
347        reader.read_sequence(|seq_reader| {
348            let mut names = Vec::<Cow<'a, str>>::new();
349
350            loop {
351                let res = seq_reader.read_optional(|r| {
352                    r.read_tagged_implicit(Tag::context(2), |r| {
353                        String::from_utf8(r.read_bytes()?).map_err(|_| ASN1Error::new(ASN1ErrorKind::Invalid))
354                    })
355                });
356                match res {
357                    Ok(Some(s)) => names.push(Cow::Owned(s)),
358                    Ok(None) => break,
359                    Err(e) => return Err(e),
360                }
361            }
362
363            Ok(DnsAltNames { names })
364        })
365    }
366}
367
368#[derive(Clone, Debug, Eq, PartialEq, Hash)]
369pub struct SubjectAltName<'a> {
370    pub names: GeneralNames<'a>,
371}
372
373impl<'a> HasOid for SubjectAltName<'a> {
374    fn oid() -> &'static ObjectIdentifier {
375        &oid::subjectAltName
376    }
377}
378
379impl<'a> DerWrite for SubjectAltName<'a> {
380    fn write(&self, writer: DERWriter) {
381        self.names.write(writer)
382    }
383}
384
385impl<'a> BERDecodable for SubjectAltName<'a> {
386    fn decode_ber(reader: BERReader) -> ASN1Result<Self> {
387        Ok(SubjectAltName { names: GeneralNames::decode_ber(reader)? })
388    }
389}
390
391#[derive(Clone, Debug, Eq, PartialEq, Hash)]
392pub struct IssuerAltName<'a> {
393    pub names: GeneralNames<'a>,
394}
395
396impl<'a> HasOid for IssuerAltName<'a> {
397    fn oid() -> &'static ObjectIdentifier {
398        &oid::issuerAltName
399    }
400}
401
402impl<'a> DerWrite for IssuerAltName<'a> {
403    fn write(&self, writer: DERWriter) {
404        self.names.write(writer)
405    }
406}
407
408impl<'a> BERDecodable for IssuerAltName<'a> {
409    fn decode_ber(reader: BERReader) -> ASN1Result<Self> {
410        Ok(IssuerAltName { names: GeneralNames::decode_ber(reader)? })
411    }
412}
413
414
415/// Max number of meaningful bits in the key usage bit string.
416const KEY_USAGE_MAX_NUM_BITS: usize = 9;
417
418bitflags! {
419    #[repr(transparent)]
420    pub struct KeyUsage: u16 {
421        const DIGITAL_SIGNATURE = 0x8000;
422        const NON_REPUDIATION   = 0x4000;
423        const KEY_ENCIPHERMENT  = 0x2000;
424        const DATA_ENCIPHERMENT = 0x1000;
425        const KEY_AGREEMENT     = 0x0800;
426        const KEY_CERT_SIGN     = 0x0400;
427        const CRL_SIGN          = 0x0200;
428        const ENCIPHER_ONLY     = 0x0100;
429        const DECIPHER_ONLY     = 0x0080;
430    }
431}
432
433impl HasOid for KeyUsage {
434    fn oid() -> &'static ObjectIdentifier {
435        &oid::keyUsage
436    }
437}
438
439impl DerWrite for KeyUsage {
440    fn write(&self, writer: DERWriter) {
441        let bytes = self.bits().to_be_bytes();
442        let bit_vec = remove_trailing_zero(&BitVec::from_bytes(&bytes));
443        writer.write_bitvec(&bit_vec);
444    }
445}
446
447pub(crate) fn remove_trailing_zero(bit_vec: &BitVec) -> BitVec {
448    let mut ret = bit_vec.clone();
449    while ret.iter().last() == Some(false) {
450        ret.pop();
451    }
452    ret
453}
454
455impl BERDecodable for KeyUsage {
456    fn decode_ber(reader: BERReader) -> ASN1Result<Self> {
457        let mut bit_vec = reader.read_bitvec()?;
458        if bit_vec.len() > KEY_USAGE_MAX_NUM_BITS {
459            bit_vec.split_off(KEY_USAGE_MAX_NUM_BITS);
460        }
461        assert!(KEY_USAGE_MAX_NUM_BITS <= u16::BITS as usize);
462        let mut array = [0u8; 2];
463        let mut bit_bytes = bit_vec.to_bytes();
464        bit_bytes.resize(2, 0);
465        array.copy_from_slice(&bit_bytes[..2]);
466        let flags = u16::from_be_bytes(array);
467        Ok(KeyUsage::from_bits_truncate(flags))
468    }
469}
470
471impl IsCritical for KeyUsage {
472    fn is_critical(&self) -> bool {
473        true
474    }
475}
476
477
478derive_sequence_of!{
479    /// SubjectDirectoryAttributes as defined in [RFC 5280 Section 4.2.1.8].
480    ///
481    /// ```text
482    /// SubjectDirectoryAttributes ::= SEQUENCE SIZE (1..MAX) OF AttributeSet
483    /// ```
484    ///
485    /// [RFC 5280 Section 4.2.1.8]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.8
486    Attribute<'a> => SubjectDirectoryAttributes<'a>
487}
488
489impl HasOid for SubjectDirectoryAttributes<'_> {
490    fn oid() -> &'static ObjectIdentifier {
491        &oid::subjectDirectoryAttributes
492    }
493}
494
495impl IsCritical for SubjectDirectoryAttributes<'_> {
496    fn is_critical(&self) -> bool {
497        false
498    }
499}
500
501derive_sequence_of! {
502    /// CertificatePolicies as defined in [RFC 5280 Section 4.2.1.4].
503    ///
504    /// ```text
505    /// CertificatePolicies ::= SEQUENCE SIZE (1..MAX) OF PolicyInformation
506    /// ```
507    ///
508    /// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4
509    //  If this extension is
510    //  critical, the path validation software MUST be able to interpret this
511    //  extension (including the optional qualifier), or MUST reject the
512    //  certificate.
513    PolicyInformation => CertificatePolicies
514}
515
516impl HasOid for CertificatePolicies {
517    fn oid() -> &'static ObjectIdentifier {
518        &certificatePolicies
519    }
520}
521
522impl CertificatePolicies {
523    pub fn to_extension(&self, is_critical: bool) -> Extension {
524        Extension {
525            oid: Self::oid().clone(),
526            critical: is_critical,
527            value: self.to_der(),
528        }
529    }
530}
531
532/// PolicyInformation as defined in [RFC 5280 Section 4.2.1.4].
533///
534/// ```text
535/// PolicyInformation ::= SEQUENCE {
536///     policyIdentifier   CertPolicyId,
537///     policyQualifiers   SEQUENCE SIZE (1..MAX) OF PolicyQualifierInfo OPTIONAL
538/// }
539///
540/// CertPolicyId ::= OBJECT IDENTIFIER
541/// ```
542///
543/// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4
544#[derive(Clone, Debug, Eq, PartialEq, Hash)]
545pub struct PolicyInformation {
546    pub policy_identifier: CertPolicyId,
547    pub policy_qualifiers: Option<Vec<PolicyQualifierInfo>>,
548}
549
550pub type CertPolicyId = ObjectIdentifier;
551
552impl BERDecodable for PolicyInformation {
553    fn decode_ber(reader: BERReader) -> ASN1Result<Self> {
554        reader.read_sequence(|policy_info_r| {
555            let policy_identifier = CertPolicyId::decode_ber(policy_info_r.next())?;
556            let policy_qualifiers = policy_info_r
557                .read_optional(|qualifiers_r| qualifiers_r.collect_sequence_of(PolicyQualifierInfo::decode_ber))?;
558            Ok(Self {
559                policy_identifier,
560                policy_qualifiers,
561            })
562        })
563    }
564}
565
566impl DerWrite for PolicyInformation {
567    fn write(&self, writer: DERWriter) {
568        writer.write_sequence(|policy_info_w| {
569            self.policy_identifier.write(policy_info_w.next());
570            if let Some(ref qualifiers) = self.policy_qualifiers {
571                policy_info_w.next().write_sequence_of(|qualifiers_w| {
572                    for qual in qualifiers {
573                        qual.write(qualifiers_w.next());
574                    }
575                })
576            }
577        })
578    }
579}
580
581derive_sequence! {
582    /// PolicyQualifierInfo as defined in [RFC 5280 Section 4.2.1.4].
583    ///
584    /// ```text
585    /// PolicyQualifierInfo ::= SEQUENCE {
586    ///     policyQualifierId  PolicyQualifierId,
587    ///     qualifier          ANY DEFINED BY policyQualifierId
588    /// }
589    /// ```
590    ///
591    /// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4
592    PolicyQualifierInfo {
593        policyQualifierId: [_] UNTAGGED REQUIRED:  ObjectIdentifier,
594        qualifier:         [_] UNTAGGED OPTIONAL:  Option<DerAnyOwned>,
595    }
596}
597
598impl From<InternetPolicyQualifier> for PolicyQualifierInfo {
599    fn from(value: InternetPolicyQualifier) -> Self {
600        let oid: &ObjectIdentifier = value.oid();
601        match value {
602            InternetPolicyQualifier::CpsUri(cps_uri) => Self {
603                policyQualifierId: oid.clone(),
604                qualifier: Some(cps_uri.to_der().into()),
605            },
606            InternetPolicyQualifier::UserNotice(user_notice) => Self {
607                policyQualifierId: oid.clone(),
608                qualifier: Some(user_notice.to_der().into()),
609            },
610        }
611    }
612}
613
614/// Qualifier as defined in [RFC 5280 Section 4.2.1.4].
615/// ```text
616/// -- policyQualifierIds for Internet policy qualifiers
617///
618/// id-qt          OBJECT IDENTIFIER ::=  { id-pkix 2 }
619/// id-qt-cps      OBJECT IDENTIFIER ::=  { id-qt 1 }
620/// id-qt-unotice  OBJECT IDENTIFIER ::=  { id-qt 2 }
621///
622/// PolicyQualifierId ::= OBJECT IDENTIFIER ( id-qt-cps | id-qt-unotice )
623///
624/// Qualifier ::= CHOICE {
625///      cPSuri           CPSuri,
626///      userNotice       UserNotice }
627/// ```
628///
629/// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4
630#[derive(Clone, Debug, PartialEq, Eq, Hash)]
631pub enum InternetPolicyQualifier {
632    CpsUri(CpsUri),
633    UserNotice(UserNotice),
634}
635
636impl BERDecodable for InternetPolicyQualifier {
637    fn decode_ber(reader: BERReader) -> ASN1Result<Self> {
638        match reader.lookahead_tag()? {
639            TAG_IA5STRING => Ok(Self::CpsUri(CpsUri::decode_ber(reader)?)),
640            TAG_SEQUENCE => Ok(Self::UserNotice(UserNotice::decode_ber(reader)?)),
641            _ => Err(ASN1Error::new(ASN1ErrorKind::Invalid)),
642        }
643    }
644}
645
646impl DerWrite for InternetPolicyQualifier {
647    fn write(&self, writer: DERWriter) {
648        match self {
649            InternetPolicyQualifier::CpsUri(cps_uri) => cps_uri.write(writer),
650            InternetPolicyQualifier::UserNotice(user_notice) => user_notice.write(writer),
651        }
652    }
653}
654
655impl InternetPolicyQualifier {
656    pub fn oid(&self) -> &'static ObjectIdentifier {
657        match self {
658            InternetPolicyQualifier::CpsUri(_) => &ID_QT_CPS,
659            InternetPolicyQualifier::UserNotice(_) => &ID_QT_UNOTICE,
660        }
661    }
662}
663
664impl TryFrom<PolicyQualifierInfo> for InternetPolicyQualifier {
665    type Error = ASN1Error;
666
667    fn try_from(value: PolicyQualifierInfo) -> Result<Self, Self::Error> {
668        if value.policyQualifierId == *ID_QT_CPS
669            || value.policyQualifierId == *ID_QT_UNOTICE
670            || value.policyQualifierId == *ANY_POLICY
671        {
672            Ok(Self::from_ber(&value.qualifier.ok_or(ASN1Error::new(ASN1ErrorKind::Eof))?)?)
673        } else {
674            Err(ASN1Error::new(ASN1ErrorKind::Invalid))
675        }
676    }
677}
678
679/// CpsUri as defined in [RFC 5280 Section 4.2.1.4].
680///
681/// ```text
682/// CPSuri ::= IA5String
683/// ```
684///
685/// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4
686pub type CpsUri = Ia5String;
687
688derive_sequence! {
689    /// UserNotice as defined in [RFC 5280 Section 4.2.1.4].
690    ///
691    /// ```text
692    /// UserNotice ::= SEQUENCE {
693    ///     noticeRef        NoticeReference OPTIONAL,
694    ///     explicitText     DisplayText OPTIONAL
695    /// }
696    /// ```
697    ///
698    /// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4
699    UserNotice {
700        notice_ref:    [_] UNTAGGED OPTIONAL:  Option<NoticeReference>,
701        explicit_text: [_] UNTAGGED OPTIONAL:  Option<DisplayText>,
702    }
703}
704
705/// NoticeReference as defined in [RFC 5280 Section 4.2.1.4].
706///
707/// ```text
708/// NoticeReference ::= SEQUENCE {
709///      organization     DisplayText,
710///      noticeNumbers    SEQUENCE OF INTEGER }
711/// ```
712///
713/// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4
714#[derive(Clone, Debug, PartialEq, Eq, Hash)]
715pub struct NoticeReference {
716    pub organization: DisplayText,
717    pub notice_numbers: Vec<BigInt>,
718}
719
720impl BERDecodable for NoticeReference {
721    fn decode_ber(reader: BERReader) -> ASN1Result<Self> {
722        reader.read_sequence(|notice_ref_r| {
723            let organization = DisplayText::decode_ber(notice_ref_r.next())?;
724            let notice_numbers = notice_ref_r.next().collect_sequence_of(BigInt::decode_ber)?;
725            Ok(Self {
726                organization,
727                notice_numbers,
728            })
729        })
730    }
731}
732
733impl DerWrite for NoticeReference {
734    fn write(&self, writer: DERWriter) {
735        writer.write_sequence(|notice_ref_w| {
736            self.organization.write(notice_ref_w.next());
737            notice_ref_w.next().write_sequence_of(|notice_num_w| {
738                for number in &self.notice_numbers {
739                    number.write(notice_num_w.next());
740                }
741            })
742        })
743    }
744}
745
746/// DisplayText as defined in [RFC 5280 Section 4.2.1.4].
747///
748/// ```text
749/// DisplayText ::= CHOICE {
750///     ia5String        IA5String      (SIZE (1..200)),
751///     visibleString    VisibleString  (SIZE (1..200)),
752///     bmpString        BMPString      (SIZE (1..200)),
753///     utf8String       UTF8String     (SIZE (1..200))
754/// }
755/// ```
756///
757/// Only the ia5String and utf8String options are currently supported.
758///
759/// [RFC 5280 Section 4.2.1.4]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.4
760// TODO: add size validation
761#[derive(Clone, Debug, PartialEq, Eq, Hash)]
762pub enum DisplayText {
763    Ia5String(Ia5String),
764    VisibleString(String),
765    BmpString(String),
766    Utf8String(String),
767}
768
769impl BERDecodable for DisplayText {
770    fn decode_ber(reader: BERReader) -> ASN1Result<Self> {
771        match reader.lookahead_tag()? {
772            TAG_IA5STRING => Ok(Self::Ia5String(Ia5String::decode_ber(reader)?)),
773            TAG_VISIBLESTRING => Ok(Self::VisibleString(reader.read_visible_string()?)),
774            TAG_BMPSTRING => Ok(Self::BmpString(reader.read_bmp_string()?)),
775            TAG_UTF8STRING => Ok(Self::Utf8String(reader.read_utf8string()?)),
776            _ => Err(ASN1Error::new(ASN1ErrorKind::Invalid)),
777        }
778    }
779}
780
781impl DerWrite for DisplayText {
782    fn write(&self, writer: DERWriter) {
783        match self {
784            DisplayText::Ia5String(s) => s.write(writer),
785            DisplayText::VisibleString(s) => writer.write_visible_string(s),
786            DisplayText::BmpString(s) => writer.write_bmp_string(s),
787            DisplayText::Utf8String(s) => writer.write_utf8_string(s),
788        }
789    }
790}
791
792derive_sequence_of! {
793    /// ExtKeyUsageSyntax as defined in [RFC 5280 Section 4.2.1.12].
794    ///
795    /// ```text
796    /// ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId
797    ///
798    /// KeyPurposeId ::= OBJECT IDENTIFIER
799    /// ```
800    ///
801    /// [RFC 5280 Section 4.2.1.12]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.12
802    //  If this extension is
803    //  critical, the path validation software MUST be able to interpret this
804    //  extension (including the optional qualifier), or MUST reject the
805    //  certificate.
806    KeyPurposeId => ExtKeyUsageSyntax
807}
808
809pub type KeyPurposeId = ObjectIdentifier;
810
811impl HasOid for ExtKeyUsageSyntax {
812    fn oid() -> &'static ObjectIdentifier {
813        &oid::extKeyUsage
814    }
815}
816
817impl ExtKeyUsageSyntax {
818    pub fn to_extension(&self, is_critical: bool) -> Extension {
819        Extension {
820            oid: Self::oid().clone(),
821            critical: is_critical,
822            value: self.to_der(),
823        }
824    }
825}
826
827#[cfg(test)]
828mod tests {
829    use super::*;
830    use test::test_encode_decode;
831
832    #[test]
833    fn basic_constraints() {
834        let test_values = vec![
835            (BasicConstraints { ca: false, path_len_constraint: None    }, vec![0x30, 0x00]),
836            (BasicConstraints { ca: true,  path_len_constraint: None    }, vec![0x30, 0x03, 0x01, 0x01, 0xFF]),
837            (BasicConstraints { ca: true,  path_len_constraint: Some(4) }, vec![0x30, 0x06, 0x01, 0x01, 0xFF, 0x02, 0x01, 0x04]),
838            // Not valid according to RFC 5280, but can still be decoded:
839            (BasicConstraints { ca: false,  path_len_constraint: Some(4) }, vec![0x30, 0x03, 0x02, 0x01, 0x04]),
840        ];
841
842        for (basic_constraint, der) in test_values {
843            test_encode_decode(&basic_constraint, &der);
844        }
845    }
846
847    #[test]
848    #[allow(deprecated)]
849    fn dns_alt_names() {
850        let names = DnsAltNames {
851            names: vec![
852                Cow::Borrowed("www.example.com"),
853                Cow::Borrowed("example.com"),
854            ]
855        };
856
857        let der = &[0x30, 0x1e, 0x82, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65,
858                    0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f,
859                    0x6d, 0x82, 0x0b, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c,
860                    0x65, 0x2e, 0x63, 0x6f, 0x6d];
861
862        test_encode_decode(&names, der);
863    }
864
865    #[test]
866    fn subject_issuer_alt_name() {
867        let subject_alt_name = SubjectAltName {
868            names: GeneralNames(vec![
869                GeneralName::IpAddress(vec![127,0,0,1]),
870                GeneralName::RegisteredID(ObjectIdentifier::new(vec![1,2,3,4]))
871            ]),
872        };
873        let issuer_alt_name = IssuerAltName {
874            names: GeneralNames(vec![
875                GeneralName::IpAddress(vec![127,0,0,1]),
876                GeneralName::RegisteredID(ObjectIdentifier::new(vec![1,2,3,4]))
877            ]),
878        };
879
880        let der = &[
881            0x30, 0x0b, 0x87, 0x04, 0x7f, 0x00, 0x00, 0x01,
882            0x88, 0x03, 0x2a, 0x03, 0x04];
883
884        test_encode_decode(&subject_alt_name, der);
885        test_encode_decode(&issuer_alt_name, der);
886    }
887
888    #[test]
889    fn parse_v1_cert() {
890        let der = include_bytes!("../tests/data/v1_cert.der");
891        let cert = yasna::parse_der(der, |r| GenericCertificate::decode_ber(r)).unwrap();
892        assert_eq!(cert.tbscert.version, TBS_CERTIFICATE_V1);
893        assert_eq!(yasna::construct_der(|w| cert.write(w)), der);
894    }
895
896    #[test]
897    fn parse_v3_cert() {
898        let der = include_bytes!("../tests/data/v3_cert.der");
899        let cert = yasna::parse_der(der, |r| GenericCertificate::decode_ber(r)).unwrap();
900        assert_eq!(cert.tbscert.version, TBS_CERTIFICATE_V3);
901        assert_eq!(yasna::construct_der(|w| cert.write(w)), der);
902    }
903}
904
905
906/// Test cases for certificate extensions, such as Key Usage, Subject Directory
907/// Attributes, and more.
908#[cfg(test)]
909mod certificate_extension_tests {
910    use std::convert::TryInto;
911
912    use crate::oid::{
913        attributeTypeRole, ANY_POLICY, ANY_EXTENDED_KEY_USAGE, ID_KP_CLIENT_AUTH, ID_KP_CODE_SIGNING, ID_KP_EMAIL_PROTECTION,
914        ID_KP_OCSP_SIGNING, ID_KP_SERVER_AUTH, ID_KP_TIME_STAMPING
915    };
916    use crate::rfc3281::Role;
917    use crate::yasna::tags::TAG_BITSTRING;
918    use crate::{FromDer, ToDer, FromBer};
919
920    use super::*;
921
922    use b64_ct::{ToBase64, STANDARD};
923
924    /// This tests "When DER encoding a named bit list, trailing zeros MUST be
925    /// omitted." from https://datatracker.ietf.org/doc/html/rfc5280#appendix-B
926    #[test]
927    fn key_usage_can_decode_encode_short() {
928        let der = [3, 2, 1, 6];
929        let ret = KeyUsage::from_der(&der).expect("can decode short");
930        assert_eq!(ret, (KeyUsage::KEY_CERT_SIGN | KeyUsage::CRL_SIGN), "KeyUsage not equal");
931        assert_eq!(&der[..], &ret.to_der(), "KeyUsage DER not equal");
932    }
933
934    #[test]
935    fn key_usage_bits() {
936        struct Test {
937            input: KeyUsage,
938            expected_bits: Vec<u8>,
939        }
940        let tests = vec![
941            Test {
942                input: KeyUsage::DIGITAL_SIGNATURE
943                    | KeyUsage::DATA_ENCIPHERMENT
944                    | KeyUsage::KEY_AGREEMENT
945                    | KeyUsage::KEY_CERT_SIGN,
946                expected_bits: vec![
947                    TAG_BITSTRING.tag_number as u8,
948                    0x2,        // The length is 2 octets. 1 for the number of unused bits and 1 for the actual data.
949                    0b00000010, // number of unused bits:2
950                    0b10011100, // content with 2 padded zero
951                ],
952            },
953            Test {
954                input: KeyUsage::all(),
955                expected_bits: vec![
956                    TAG_BITSTRING.tag_number as u8,
957                    0x3,        // The length is 3 octets. 1 for the number of unused bits and 2 for the actual data.
958                    0b00000111, // number of unused bits:7
959                    0b11111111,
960                    0b10000000, // content with 7 padded zero
961                ],
962            },
963            Test {
964                input: KeyUsage::DECIPHER_ONLY,
965                expected_bits: vec![
966                    TAG_BITSTRING.tag_number as u8,
967                    0x3,        // The length is 3 octets. 1 for the number of unused bits and 2 for the actual data.
968                    0b00000111, // number of unused bits:7
969                    0b00000000,
970                    0b10000000, // content with 7 padded zero
971                ],
972            },
973            Test {
974                input: KeyUsage::CRL_SIGN | KeyUsage::ENCIPHER_ONLY,
975                expected_bits: vec![
976                    TAG_BITSTRING.tag_number as u8,
977                    0x2,        // The length is 2 octets. 1 for the number of unused bits and 1 for the actual data.
978                    0b00000000, // number of unused bits:0
979                    0b00000011, // content with 0 padded zero
980                ],
981            },
982        ];
983
984        for t in tests {
985            let der = t.input.to_der();
986            assert_eq!(
987                &der, &t.expected_bits,
988                "{:?}, {:02x?} != {:02x?}",
989                t.input, &der, &t.expected_bits
990            );
991            let echo = KeyUsage::from_der(&der).unwrap();
992            assert_eq!(echo, t.input);
993        }
994    }
995
996    const EXAMPLE_DER_WITH_ROLE: &[u8] = &[
997        0x30, 0x17, 0x30, 0x15, 0x06, 0x03, 0x55, 0x04, 0x48, 0x31, 0x0E, 0x30, 0x0C, 0xA1, 0x0A, 0x88, 0x08, 0x2A, 0x03, 0x04,
998        0x05, 0x06, 0x07, 0x08, 0x09,
999    ];
1000
1001    #[test]
1002    fn subject_directory_attributes_decode_encode_with_role() {
1003        let example_role_oid = ObjectIdentifier::from_slice(&[1, 2, 3, 4, 5, 6, 7, 8, 9]);
1004        let example_role = Role {
1005            role_authority: None,
1006            role_name: GeneralName::RegisteredID(example_role_oid),
1007        };
1008        let ret = SubjectDirectoryAttributes::from_der(EXAMPLE_DER_WITH_ROLE).expect("can decode");
1009        let attr = ret.0.first().expect("has one attribute");
1010        assert_eq!(&attr.oid, &*attributeTypeRole);
1011        assert_eq!(attr.value.first().unwrap().value, example_role.to_der());
1012        assert_eq!(ret.to_der(), EXAMPLE_DER_WITH_ROLE);
1013    }
1014
1015    #[test]
1016    fn subject_directory_attributes_construct() {
1017        let mut attributes = vec![];
1018        let utf8_string = String::from("a utf8 string");
1019        attributes.push(Attribute {
1020            oid: ObjectIdentifier::from_slice(&[1, 2, 840, 113549, 1, 1]),
1021            value: vec![DerSequence::from_der(
1022                &TaggedDerValue::from_tag_and_bytes(yasna::tags::TAG_UTF8STRING, utf8_string.clone().into_bytes())
1023                    .to_der(),
1024            )
1025            .unwrap()],
1026        });
1027        let example = SubjectDirectoryAttributes(attributes);
1028        let der = example.to_der();
1029        let example_decode = SubjectDirectoryAttributes::from_der(&der).expect("from der");
1030        assert_eq!(example_decode, example);
1031    }
1032
1033    #[test]
1034    fn subject_directory_attributes_construct_with_role() {
1035        let mut attributes = vec![];
1036        let example_role_oid = ObjectIdentifier::from_slice(&[1, 2, 3, 4, 5, 6, 7, 8, 9]);
1037        let example_role = Role {
1038            role_authority: None,
1039            role_name: GeneralName::RegisteredID(example_role_oid),
1040        };
1041        attributes.push(Attribute {
1042            oid: attributeTypeRole.clone(),
1043            value: vec![DerSequence::from_der(&example_role.to_der()).unwrap()],
1044        });
1045        let example = SubjectDirectoryAttributes(attributes);
1046        let der = example.to_der();
1047        assert_eq!(der, EXAMPLE_DER_WITH_ROLE);
1048        println!("{}", der.to_base64(STANDARD));
1049        let example_decode = SubjectDirectoryAttributes::from_der(&der).expect("from der");
1050        assert_eq!(example_decode, example);
1051    }
1052
1053    /// A simple smoke test to ensure that we can encode CertificatePolicies
1054    /// struct mentioning the Fortanix Service and Key Attestation Certificate
1055    /// Policies, and decode the DER value to get back the same struct.
1056    #[test]
1057    fn encode_fortanix_policies_smoke_test() {
1058        for policy_identifier in [
1059            vec![1, 3, 6, 1, 4, 1, 49690, 6, 1, 3].into(),
1060            vec![1, 3, 6, 1, 4, 1, 49690, 6, 1, 2].into(),
1061        ] {
1062            let policies = CertificatePolicies(vec![PolicyInformation {
1063                policy_identifier,
1064                policy_qualifiers: None,
1065            }]);
1066            let der = policies.to_der();
1067            let decoded = CertificatePolicies::from_ber(&der).expect("DER should be valid");
1068            assert_eq!(policies, decoded);
1069        }
1070    }
1071
1072    /// A simple smoke test to ensure that we can encode an anyPolicy policy with
1073    /// a policy qualifier, and decode the DER value to get back the same struct.
1074    #[test]
1075    fn encode_any_policy_smoke_test() {
1076        for internet_policy_qualifier in [
1077            InternetPolicyQualifier::CpsUri("https://example.com".to_string().into()), // not real
1078            InternetPolicyQualifier::UserNotice(UserNotice {
1079                notice_ref: Some(NoticeReference {
1080                    organization: DisplayText::Utf8String("Fake Corp".to_string()),
1081                    notice_numbers: vec![BigInt::from(1)],
1082                }),
1083                explicit_text: Some(DisplayText::Utf8String("Fake policy".to_string())),
1084            }),
1085        ] {
1086            let policy = PolicyInformation {
1087                policy_identifier: ANY_POLICY.clone(),
1088                policy_qualifiers: Some(vec![internet_policy_qualifier.clone().into()]),
1089            };
1090            let der = policy.to_der();
1091            let decoded = PolicyInformation::from_ber(&der).expect("DER should be valid");
1092            assert_eq!(policy, decoded);
1093            let decoded_internet_policy_qualifier: InternetPolicyQualifier = decoded
1094                .policy_qualifiers
1095                .unwrap()
1096                .first()
1097                .unwrap()
1098                .to_owned()
1099                .try_into()
1100                .unwrap();
1101            assert_eq!(internet_policy_qualifier, decoded_internet_policy_qualifier);
1102        }
1103    }
1104
1105    #[test]
1106    fn encode_internet_policy_qualifiers_smoke_test() {
1107        for internet_policy_qualifier in [
1108            InternetPolicyQualifier::CpsUri("https://example.com".to_string().into()), // not real
1109            InternetPolicyQualifier::UserNotice(UserNotice {
1110                notice_ref: Some(NoticeReference {
1111                    organization: DisplayText::Utf8String("Fake Corp".to_string()),
1112                    notice_numbers: vec![BigInt::from(1)],
1113                }),
1114                explicit_text: Some(DisplayText::Utf8String("Fake policy".to_string())),
1115            }),
1116        ] {
1117            let policy = PolicyInformation {
1118                policy_identifier: internet_policy_qualifier.oid().clone(),
1119                policy_qualifiers: Some(vec![internet_policy_qualifier.clone().into()]),
1120            };
1121            let der = policy.to_der();
1122            let decoded = PolicyInformation::from_ber(&der).expect("DER should be valid");
1123            assert_eq!(policy, decoded);
1124            let decoded_internet_policy_qualifier: InternetPolicyQualifier = decoded
1125                .policy_qualifiers
1126                .unwrap()
1127                .first()
1128                .unwrap()
1129                .to_owned()
1130                .try_into()
1131                .unwrap();
1132            assert_eq!(internet_policy_qualifier, decoded_internet_policy_qualifier);
1133        }
1134    }
1135
1136    /// Example [CertificatePolicies] extension extract from a `Fortanix DSM SaaS Key Attestation Authority` certificate:
1137    /// ```text
1138    /// Extension SEQUENCE (2 elem)
1139    /// extnID OBJECT IDENTIFIER 2.5.29.32 certificatePolicies (X.509 extension)
1140    /// extnValue OCTET STRING (17 byte) 300F300D060B2B0601040183841A060102
1141    ///   SEQUENCE (1 elem)
1142    ///     SEQUENCE (1 elem)
1143    ///       OBJECT IDENTIFIER 1.3.6.1.4.1.49690.6.1.2
1144    /// ```
1145    static EXAMPLE_CLUSTER_NODE_ENROLLMENT_POLICY_EXT: &[u8] = &[
1146        0x30, 0x18, 0x06, 0x03, 0x55, 0x1D, 0x20, 0x04, 0x11, 0x30, 0x0F, 0x30, 0x0D, 0x06, 0x0B, 0x2B, 0x06, 0x01, 0x04, 0x01,
1147        0x83, 0x84, 0x1A, 0x06, 0x01, 0x02,
1148    ];
1149
1150    #[test]
1151    fn decode_fortanix_policies_ext_test() {
1152        let ext = Extension::from_ber(EXAMPLE_CLUSTER_NODE_ENROLLMENT_POLICY_EXT).unwrap();
1153        let policies = CertificatePolicies::from_ber(&ext.value).expect("extension value should be valid");
1154        let expected_polices = CertificatePolicies(vec![PolicyInformation {
1155            policy_identifier: vec![1, 3, 6, 1, 4, 1, 49690, 6, 1, 2].into(),
1156            policy_qualifiers: None,
1157        }]);
1158        assert_eq!(expected_polices, policies);
1159        assert_eq!(ext, expected_polices.to_extension(false));
1160    }
1161
1162    /// A smoke test to check round-trip serialization and deserialization of
1163    /// the Extended Key Usage extension.
1164    #[test]
1165    fn extended_key_usage_encode_decode_round_trip_smoke_test() {
1166        for eku_purposes in [
1167            vec![ANY_EXTENDED_KEY_USAGE.clone()],
1168            vec![ID_KP_CLIENT_AUTH.clone(), ID_KP_SERVER_AUTH.clone()],
1169            vec![ID_KP_CODE_SIGNING.clone()],
1170            vec![ID_KP_EMAIL_PROTECTION.clone()],
1171            vec![ID_KP_OCSP_SIGNING.clone(), ID_KP_TIME_STAMPING.clone()],
1172            // Custom extended key usage purpose used for Fortanix key attestation:
1173            // id-kp-fortanix-key-attestation
1174            vec![vec![1, 3, 6, 1, 4, 1, 49690, 8, 1].into()]
1175        ] {
1176            let eku = ExtKeyUsageSyntax(eku_purposes);
1177            let eku_der = eku.to_der();
1178            let decoded_eku = ExtKeyUsageSyntax::from_ber(&eku_der).expect("DER-encoded EKU extension should be valid");
1179            assert_eq!(decoded_eku, eku);
1180        }
1181    }
1182}