Skip to main content
This is unreleased documentation for the main (development) branch of crypto-glue.

x509_cert/
request.rs

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