1use 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#[derive(Clone, Debug, Copy, PartialEq, Eq, Enumerated, Default)]
32#[asn1(type = "INTEGER")]
33#[repr(u8)]
34pub enum Version {
35 #[default]
37 V1 = 0,
38}
39
40#[derive(Clone, Debug, PartialEq, Eq, Sequence)]
53pub struct CertReqInfo {
54 pub version: Version,
56
57 pub subject: Name,
59
60 pub public_key: SubjectPublicKeyInfo,
62
63 #[asn1(context_specific = "0", tag_mode = "IMPLICIT")]
65 pub attributes: Attributes,
66}
67
68#[derive(Clone, Debug, PartialEq, Eq, Sequence)]
80pub struct CertReq {
81 pub info: CertReqInfo,
83
84 pub algorithm: AlgorithmIdentifier,
86
87 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#[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 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 pub trait AsAttribute: AssociatedOid + Tagged + EncodeValue + Sized {
148 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 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}