1 //! Trust anchor-related structures as defined in RFC 5914
2 
3 use crate::ext::pkix::{certpolicy::CertificatePolicies, NameConstraints};
4 use crate::{ext::Extensions, name::Name};
5 use crate::{Certificate, TbsCertificate};
6 
7 use alloc::string::String;
8 use der::asn1::OctetString;
9 use der::flagset::{flags, FlagSet};
10 use der::{Choice, Enumerated, Sequence};
11 use spki::SubjectPublicKeyInfoOwned;
12 
13 /// Version identifier for TrustAnchorInfo
14 #[derive(Clone, Debug, Default, Copy, PartialEq, Eq, Enumerated)]
15 #[asn1(type = "INTEGER")]
16 #[repr(u8)]
17 pub enum Version {
18     /// Version 1 (default)
19     #[default]
20     V1 = 0,
21 }
22 
23 /// ```text
24 /// TrustAnchorInfo ::= SEQUENCE {
25 ///     version         TrustAnchorInfoVersion DEFAULT v1,
26 ///     pubKey          SubjectPublicKeyInfo,
27 ///     keyId           KeyIdentifier,
28 ///     taTitle         TrustAnchorTitle OPTIONAL,
29 ///     certPath        CertPathControls OPTIONAL,
30 ///     exts            [1] EXPLICIT Extensions   OPTIONAL,
31 ///     taTitleLangTag  [2] UTF8String OPTIONAL
32 /// }
33 ///
34 /// TrustAnchorInfoVersion ::= INTEGER { v1(1) }
35 ///
36 /// TrustAnchorTitle ::= UTF8String (SIZE (1..64))
37 /// ```
38 #[derive(Clone, Debug, PartialEq, Eq, Sequence)]
39 #[allow(missing_docs)]
40 pub struct TrustAnchorInfo {
41     #[asn1(default = "Default::default")]
42     pub version: Version,
43 
44     pub pub_key: SubjectPublicKeyInfoOwned,
45 
46     pub key_id: OctetString,
47 
48     #[asn1(optional = "true")]
49     pub ta_title: Option<String>,
50 
51     #[asn1(optional = "true")]
52     pub cert_path: Option<CertPathControls>,
53 
54     #[asn1(context_specific = "1", tag_mode = "EXPLICIT", optional = "true")]
55     pub extensions: Option<Extensions>,
56 
57     #[asn1(context_specific = "2", tag_mode = "IMPLICIT", optional = "true")]
58     pub ta_title_lang_tag: Option<String>,
59 }
60 
61 /// ```text
62 /// CertPathControls ::= SEQUENCE {
63 ///     taName              Name,
64 ///     certificate         [0] Certificate OPTIONAL,
65 ///     policySet           [1] CertificatePolicies OPTIONAL,
66 ///     policyFlags         [2] CertPolicyFlags OPTIONAL,
67 ///     nameConstr          [3] NameConstraints OPTIONAL,
68 ///     pathLenConstraint   [4] INTEGER (0..MAX) OPTIONAL
69 /// }
70 /// ```
71 #[derive(Clone, Debug, Eq, PartialEq, Sequence)]
72 #[allow(missing_docs)]
73 pub struct CertPathControls {
74     pub ta_name: Name,
75 
76     #[asn1(context_specific = "0", tag_mode = "IMPLICIT", optional = "true")]
77     pub certificate: Option<Certificate>,
78 
79     #[asn1(context_specific = "1", tag_mode = "IMPLICIT", optional = "true")]
80     pub policy_set: Option<CertificatePolicies>,
81 
82     #[asn1(context_specific = "2", tag_mode = "IMPLICIT", optional = "true")]
83     pub policy_flags: Option<CertPolicyFlags>,
84 
85     #[asn1(context_specific = "3", tag_mode = "IMPLICIT", optional = "true")]
86     pub name_constr: Option<NameConstraints>,
87 
88     #[asn1(context_specific = "4", tag_mode = "IMPLICIT", optional = "true")]
89     pub path_len_constraint: Option<u32>,
90 }
91 
92 flags! {
93     /// Certificate policies as defined in [RFC 5280 Section 4.2.1.13].
94     ///
95     /// ```text
96     /// CertPolicyFlags ::= BIT STRING {
97     ///     inhibitPolicyMapping    (0),
98     ///     requireExplicitPolicy   (1),
99     ///     inhibitAnyPolicy        (2)
100     /// }
101     /// ```
102     ///
103     /// [RFC 5280 Section 4.2.1.13]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.13
104     #[allow(missing_docs)]
105     pub enum CertPolicies: u8 {
106         InhibitPolicyMapping = 1 << 0,
107         RequireExplicitPolicy = 1 << 1,
108         InhibitAnyPolicy = 1 << 2,
109     }
110 }
111 
112 /// Certificate policy flags as defined in [RFC 5280 Section 4.2.1.13].
113 ///
114 /// [RFC 5280 Section 4.2.1.13]: https://datatracker.ietf.org/doc/html/rfc5280#section-4.2.1.13
115 pub type CertPolicyFlags = FlagSet<CertPolicies>;
116 
117 /// ```text
118 /// TrustAnchorChoice ::= CHOICE {
119 ///   certificate  Certificate,
120 ///   tbsCert      [1] EXPLICIT TBSCertificate,
121 ///   taInfo       [2] EXPLICIT TrustAnchorInfo
122 /// }
123 /// ```
124 #[derive(Clone, Debug, PartialEq, Eq, Choice)]
125 #[allow(clippy::large_enum_variant)]
126 #[allow(missing_docs)]
127 pub enum TrustAnchorChoice {
128     Certificate(Certificate),
129 
130     #[asn1(context_specific = "1", tag_mode = "EXPLICIT", constructed = "true")]
131     TbsCertificate(TbsCertificate),
132 
133     #[asn1(context_specific = "2", tag_mode = "EXPLICIT", constructed = "true")]
134     TaInfo(TrustAnchorInfo),
135 }
136