1use crate::{
4 attr::{Attribute, AttributeValue, Attributes},
5 ext::Extension,
6 name::Name,
7};
8
9use alloc::vec::Vec;
10
11use const_oid::db::rfc5912::ID_EXTENSION_REQ;
12use const_oid::{AssociatedOid, ObjectIdentifier};
13use der::asn1::BitString;
14use der::{
15 asn1::{Any, SetOfVec},
16 Decode, Enumerated, Sequence,
17};
18use spki::{AlgorithmIdentifierOwned, SubjectPublicKeyInfoOwned};
19
20#[cfg(feature = "pem")]
21use der::pem::PemLabel;
22
23#[derive(Clone, Debug, Copy, PartialEq, Eq, Enumerated, Default)]
27#[asn1(type = "INTEGER")]
28#[repr(u8)]
29pub enum Version {
30 #[default]
32 V1 = 0,
33}
34
35#[derive(Clone, Debug, PartialEq, Eq, Sequence)]
48pub struct CertReqInfo {
49 pub version: Version,
51
52 pub subject: Name,
54
55 pub public_key: SubjectPublicKeyInfoOwned,
57
58 #[asn1(context_specific = "0", tag_mode = "IMPLICIT")]
60 pub attributes: Attributes,
61}
62
63#[derive(Clone, Debug, PartialEq, Eq, Sequence)]
75pub struct CertReq {
76 pub info: CertReqInfo,
78
79 pub algorithm: AlgorithmIdentifierOwned,
81
82 pub signature: BitString,
84}
85
86#[cfg(feature = "pem")]
87impl PemLabel for CertReq {
88 const PEM_LABEL: &'static str = "CERTIFICATE REQUEST";
89}
90
91impl<'a> TryFrom<&'a [u8]> for CertReq {
92 type Error = der::Error;
93
94 fn try_from(bytes: &'a [u8]) -> Result<Self, Self::Error> {
95 Self::from_der(bytes)
96 }
97}
98
99#[derive(Clone, Debug, PartialEq, Eq, Default)]
107pub struct ExtensionReq(pub Vec<Extension>);
108
109impl AssociatedOid for ExtensionReq {
110 const OID: ObjectIdentifier = ID_EXTENSION_REQ;
111}
112
113impl_newtype!(ExtensionReq, Vec<Extension>);
114
115impl TryFrom<ExtensionReq> for Attribute {
116 type Error = der::Error;
117
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
129pub mod attributes {
130 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 pub trait AsAttribute: AssociatedOid + Tagged + EncodeValue + Sized {
143 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 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 {
177 fn tag(&self) -> Tag {
178 self.0.tag()
179 }
180 }
181
182 impl EncodeValue for ChallengePassword {
183 fn value_len(&self) -> Result<Length> {
184 self.0.value_len()
185 }
186
187 fn encode_value(&self, encoder: &mut impl Writer) -> Result<()> {
188 self.0.encode_value(encoder)
189 }
190 }
191}