1 //! PKCS#10 Certification Request types
2 
3 use crate::{
4     attr::{Attribute, AttributeValue, Attributes},
5     ext::Extension,
6     name::Name,
7 };
8 
9 use alloc::vec::Vec;
10 
11 use const_oid::db::rfc5912::ID_EXTENSION_REQ;
12 use const_oid::{AssociatedOid, ObjectIdentifier};
13 use der::asn1::BitString;
14 use der::{
15     asn1::{Any, SetOfVec},
16     Decode, Enumerated, Sequence,
17 };
18 use spki::{AlgorithmIdentifierOwned, SubjectPublicKeyInfoOwned};
19 
20 #[cfg(feature = "pem")]
21 use der::pem::PemLabel;
22 
23 /// Version identifier for certification request information.
24 ///
25 /// (RFC 2986 designates `0` as the only valid version)
26 #[derive(Clone, Debug, Copy, PartialEq, Eq, Enumerated, Default)]
27 #[asn1(type = "INTEGER")]
28 #[repr(u8)]
29 pub enum Version {
30     /// Denotes PKCS#8 v1
31     #[default]
32     V1 = 0,
33 }
34 
35 /// PKCS#10 `CertificationRequestInfo` as defined in [RFC 2986 Section 4].
36 ///
37 /// ```text
38 /// CertificationRequestInfo ::= SEQUENCE {
39 ///     version       INTEGER { v1(0) } (v1,...),
40 ///     subject       Name,
41 ///     subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }},
42 ///     attributes    [0] Attributes{{ CRIAttributes }}
43 /// }
44 /// ```
45 ///
46 /// [RFC 2986 Section 4]: https://datatracker.ietf.org/doc/html/rfc2986#section-4
47 #[derive(Clone, Debug, PartialEq, Eq, Sequence)]
48 pub struct CertReqInfo {
49     /// Certification request version.
50     pub version: Version,
51 
52     /// Subject name.
53     pub subject: Name,
54 
55     /// Subject public key info.
56     pub public_key: SubjectPublicKeyInfoOwned,
57 
58     /// Request attributes.
59     #[asn1(context_specific = "0", tag_mode = "IMPLICIT")]
60     pub attributes: Attributes,
61 }
62 
63 /// PKCS#10 `CertificationRequest` as defined in [RFC 2986 Section 4].
64 ///
65 /// ```text
66 /// CertificationRequest ::= SEQUENCE {
67 ///     certificationRequestInfo CertificationRequestInfo,
68 ///     signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }},
69 ///     signature          BIT STRING
70 /// }
71 /// ```
72 ///
73 /// [RFC 2986 Section 4]: https://datatracker.ietf.org/doc/html/rfc2986#section-4
74 #[derive(Clone, Debug, PartialEq, Eq, Sequence)]
75 pub struct CertReq {
76     /// Certification request information.
77     pub info: CertReqInfo,
78 
79     /// Signature algorithm identifier.
80     pub algorithm: AlgorithmIdentifierOwned,
81 
82     /// Signature.
83     pub signature: BitString,
84 }
85 
86 #[cfg(feature = "pem")]
87 impl PemLabel for CertReq {
88     const PEM_LABEL: &'static str = "CERTIFICATE REQUEST";
89 }
90 
91 impl<'a> TryFrom<&'a [u8]> for CertReq {
92     type Error = der::Error;
93 
try_from(bytes: &'a [u8]) -> Result<Self, Self::Error>94     fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
95         Self::from_der(bytes)
96     }
97 }
98 
99 /// `ExtensionReq` as defined in [RFC 5272 Section 3.1].
100 ///
101 /// ```text
102 /// ExtensionReq ::= SEQUENCE SIZE (1..MAX) OF Extension
103 /// ```
104 ///
105 /// [RFC 5272 Section 3.1]: https://datatracker.ietf.org/doc/html/rfc5272#section-3.1
106 #[derive(Clone, Debug, PartialEq, Eq, Default)]
107 pub struct ExtensionReq(pub Vec<Extension>);
108 
109 impl AssociatedOid for ExtensionReq {
110     const OID: ObjectIdentifier = ID_EXTENSION_REQ;
111 }
112 
113 impl_newtype!(ExtensionReq, Vec<Extension>);
114 
115 impl TryFrom<ExtensionReq> for Attribute {
116     type Error = der::Error;
117 
try_from(extension_req: ExtensionReq) -> der::Result<Attribute>118     fn try_from(extension_req: ExtensionReq) -> der::Result<Attribute> {
119         let mut values: SetOfVec<AttributeValue> = Default::default();
120         values.insert(Any::encode_from(&extension_req.0)?)?;
121 
122         Ok(Attribute {
123             oid: ExtensionReq::OID,
124             values,
125         })
126     }
127 }
128 
129 pub mod attributes {
130     //! Set of attributes that may be associated to a request
131 
132     use alloc::vec;
133     use const_oid::AssociatedOid;
134     use der::{
135         asn1::{Any, ObjectIdentifier, SetOfVec},
136         EncodeValue, Length, Result, Tag, Tagged, Writer,
137     };
138 
139     use crate::{attr::Attribute, ext::pkix::name::DirectoryString};
140 
141     /// Trait to be implement by request attributes
142     pub trait AsAttribute: AssociatedOid + Tagged + EncodeValue + Sized {
143         /// Returns the Attribute with the content encoded.
to_attribute(&self) -> Result<Attribute>144         fn to_attribute(&self) -> Result<Attribute> {
145             let inner: Any = der::asn1::Any::encode_from(self)?;
146 
147             let values = SetOfVec::try_from(vec![inner])?;
148 
149             Ok(Attribute {
150                 oid: Self::OID,
151                 values,
152             })
153         }
154     }
155 
156     /// `ChallengePassword` as defined in [RFC 2985 Section 5.4.1]
157     ///
158     /// ```text
159     /// challengePassword ATTRIBUTE ::= {
160     ///          WITH SYNTAX DirectoryString {pkcs-9-ub-challengePassword}
161     ///          EQUALITY MATCHING RULE caseExactMatch
162     ///          SINGLE VALUE TRUE
163     ///          ID pkcs-9-at-challengePassword
164     ///  }
165     /// ```
166     ///
167     /// [RFC 2985 Section 5.4.1]: https://www.rfc-editor.org/rfc/rfc2985#page-16
168     pub struct ChallengePassword(pub DirectoryString);
169 
170     impl AsAttribute for ChallengePassword {}
171 
172     impl AssociatedOid for ChallengePassword {
173         const OID: ObjectIdentifier = ObjectIdentifier::new_unwrap("1.2.840.113549.1.9.7");
174     }
175 
176     impl Tagged for ChallengePassword {
tag(&self) -> Tag177         fn tag(&self) -> Tag {
178             self.0.tag()
179         }
180     }
181 
182     impl EncodeValue for ChallengePassword {
value_len(&self) -> Result<Length>183         fn value_len(&self) -> Result<Length> {
184             self.0.value_len()
185         }
186 
encode_value(&self, encoder: &mut impl Writer) -> Result<()>187         fn encode_value(&self, encoder: &mut impl Writer) -> Result<()> {
188             self.0.encode_value(encoder)
189         }
190     }
191 }
192