1 use crate::cri_attributes::*; 2 use crate::error::{X509Error, X509Result}; 3 use crate::extensions::*; 4 use crate::traits::FromDer; 5 use crate::x509::{ 6 parse_signature_value, AlgorithmIdentifier, SubjectPublicKeyInfo, X509Name, X509Version, 7 }; 8 9 use der_parser::ber::BitStringObject; 10 use der_parser::der::*; 11 use der_parser::oid::Oid; 12 use der_parser::*; 13 use nom::Offset; 14 #[cfg(feature = "verify")] 15 use oid_registry::*; 16 use std::collections::HashMap; 17 18 /// Certification Signing Request (CSR) 19 #[derive(Debug, PartialEq)] 20 pub struct X509CertificationRequest<'a> { 21 pub certification_request_info: X509CertificationRequestInfo<'a>, 22 pub signature_algorithm: AlgorithmIdentifier<'a>, 23 pub signature_value: BitStringObject<'a>, 24 } 25 26 impl<'a> X509CertificationRequest<'a> { requested_extensions(&self) -> Option<impl Iterator<Item = &ParsedExtension>>27 pub fn requested_extensions(&self) -> Option<impl Iterator<Item = &ParsedExtension>> { 28 self.certification_request_info 29 .iter_attributes() 30 .find_map(|attr| { 31 if let ParsedCriAttribute::ExtensionRequest(requested) = &attr.parsed_attribute { 32 Some(requested.extensions.iter().map(|ext| &ext.parsed_extension)) 33 } else { 34 None 35 } 36 }) 37 } 38 39 /// Verify the cryptographic signature of this certification request 40 /// 41 /// Uses the public key contained in the CSR, which must be the one of the entity 42 /// requesting the certification for this verification to succeed. 43 #[cfg(feature = "verify")] verify_signature(&self) -> Result<(), X509Error>44 pub fn verify_signature(&self) -> Result<(), X509Error> { 45 use ring::signature; 46 let spki = &self.certification_request_info.subject_pki; 47 let signature_alg = &self.signature_algorithm.algorithm; 48 // identify verification algorithm 49 let verification_alg: &dyn signature::VerificationAlgorithm = 50 if *signature_alg == OID_PKCS1_SHA1WITHRSA { 51 &signature::RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY 52 } else if *signature_alg == OID_PKCS1_SHA256WITHRSA { 53 &signature::RSA_PKCS1_2048_8192_SHA256 54 } else if *signature_alg == OID_PKCS1_SHA384WITHRSA { 55 &signature::RSA_PKCS1_2048_8192_SHA384 56 } else if *signature_alg == OID_PKCS1_SHA512WITHRSA { 57 &signature::RSA_PKCS1_2048_8192_SHA512 58 } else if *signature_alg == OID_SIG_ECDSA_WITH_SHA256 { 59 &signature::ECDSA_P256_SHA256_ASN1 60 } else if *signature_alg == OID_SIG_ECDSA_WITH_SHA384 { 61 &signature::ECDSA_P384_SHA384_ASN1 62 } else if *signature_alg == OID_SIG_ED25519 { 63 &signature::ED25519 64 } else { 65 return Err(X509Error::SignatureUnsupportedAlgorithm); 66 }; 67 // get public key 68 let key = signature::UnparsedPublicKey::new(verification_alg, spki.subject_public_key.data); 69 // verify signature 70 let sig = self.signature_value.data; 71 key.verify(self.certification_request_info.raw, sig) 72 .or(Err(X509Error::SignatureVerificationError)) 73 } 74 } 75 76 /// <pre> 77 /// CertificationRequest ::= SEQUENCE { 78 /// certificationRequestInfo CertificationRequestInfo, 79 /// signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }}, 80 /// signature BIT STRING 81 /// } 82 /// </pre> 83 impl<'a> FromDer<'a> for X509CertificationRequest<'a> { from_der(i: &'a [u8]) -> X509Result<'a, Self>84 fn from_der(i: &'a [u8]) -> X509Result<'a, Self> { 85 parse_der_sequence_defined_g(|i, _| { 86 let (i, certification_request_info) = X509CertificationRequestInfo::from_der(i)?; 87 let (i, signature_algorithm) = AlgorithmIdentifier::from_der(i)?; 88 let (i, signature_value) = parse_signature_value(i)?; 89 let cert = X509CertificationRequest { 90 certification_request_info, 91 signature_algorithm, 92 signature_value, 93 }; 94 Ok((i, cert)) 95 })(i) 96 } 97 } 98 99 /// Certification Request Info structure 100 /// 101 /// Certification request information is defined by the following ASN.1 structure: 102 /// 103 /// <pre> 104 /// CertificationRequestInfo ::= SEQUENCE { 105 /// version INTEGER { v1(0) } (v1,...), 106 /// subject Name, 107 /// subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }}, 108 /// attributes [0] Attributes{{ CRIAttributes }} 109 /// } 110 /// </pre> 111 /// 112 /// version is the version number; subject is the distinguished name of the certificate 113 /// subject; subject_pki contains information about the public key being certified, and 114 /// attributes is a collection of attributes providing additional information about the 115 /// subject of the certificate. 116 #[derive(Debug, PartialEq)] 117 pub struct X509CertificationRequestInfo<'a> { 118 pub version: X509Version, 119 pub subject: X509Name<'a>, 120 pub subject_pki: SubjectPublicKeyInfo<'a>, 121 attributes: Vec<X509CriAttribute<'a>>, 122 pub raw: &'a [u8], 123 } 124 125 impl<'a> X509CertificationRequestInfo<'a> { 126 /// Get the CRL entry extensions. 127 #[inline] attributes(&self) -> &[X509CriAttribute]128 pub fn attributes(&self) -> &[X509CriAttribute] { 129 &self.attributes 130 } 131 132 /// Returns an iterator over the CRL entry extensions 133 #[inline] iter_attributes(&self) -> impl Iterator<Item = &X509CriAttribute>134 pub fn iter_attributes(&self) -> impl Iterator<Item = &X509CriAttribute> { 135 self.attributes.iter() 136 } 137 138 /// Searches for a CRL entry extension with the given `Oid`. 139 /// 140 /// Note: if there are several extensions with the same `Oid`, the first one is returned. find_attribute(&self, oid: &Oid) -> Option<&X509CriAttribute>141 pub fn find_attribute(&self, oid: &Oid) -> Option<&X509CriAttribute> { 142 self.attributes.iter().find(|&ext| ext.oid == *oid) 143 } 144 145 /// Builds and returns a map of CRL entry extensions. 146 /// 147 /// If an extension is present twice, this will fail and return `DuplicateExtensions`. attributes_map(&self) -> Result<HashMap<Oid, &X509CriAttribute>, X509Error>148 pub fn attributes_map(&self) -> Result<HashMap<Oid, &X509CriAttribute>, X509Error> { 149 self.attributes 150 .iter() 151 .try_fold(HashMap::new(), |mut m, ext| { 152 if m.contains_key(&ext.oid) { 153 return Err(X509Error::DuplicateAttributes); 154 } 155 m.insert(ext.oid.clone(), ext); 156 Ok(m) 157 }) 158 } 159 } 160 161 /// <pre> 162 /// CertificationRequestInfo ::= SEQUENCE { 163 /// version INTEGER { v1(0) } (v1,...), 164 /// subject Name, 165 /// subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }}, 166 /// attributes [0] Attributes{{ CRIAttributes }} 167 /// } 168 /// </pre> 169 impl<'a> FromDer<'a> for X509CertificationRequestInfo<'a> { from_der(i: &'a [u8]) -> X509Result<Self>170 fn from_der(i: &'a [u8]) -> X509Result<Self> { 171 let start_i = i; 172 parse_der_sequence_defined_g(move |i, _| { 173 let (i, version) = X509Version::from_der_required(i)?; 174 let (i, subject) = X509Name::from_der(i)?; 175 let (i, subject_pki) = SubjectPublicKeyInfo::from_der(i)?; 176 let (i, attributes) = parse_cri_attributes(i)?; 177 let len = start_i.offset(i); 178 let tbs = X509CertificationRequestInfo { 179 version, 180 subject, 181 subject_pki, 182 attributes, 183 raw: &start_i[..len], 184 }; 185 Ok((i, tbs)) 186 })(i) 187 } 188 } 189