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