1 use crate::cri_attributes::*; 2 #[cfg(feature = "verify")] 3 use crate::error::X509Error; 4 use crate::error::X509Result; 5 use crate::extensions::*; 6 use crate::x509::{ 7 parse_signature_value, AlgorithmIdentifier, SubjectPublicKeyInfo, X509Name, X509Version, 8 }; 9 10 use der_parser::ber::BitStringObject; 11 use der_parser::der::*; 12 use der_parser::oid::Oid; 13 use der_parser::*; 14 use nom::Offset; 15 #[cfg(feature = "verify")] 16 use oid_registry::*; 17 use std::collections::HashMap; 18 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> { 27 /// Parse a certification signing request (CSR) 28 /// 29 /// <pre> 30 /// CertificationRequest ::= SEQUENCE { 31 /// certificationRequestInfo CertificationRequestInfo, 32 /// signatureAlgorithm AlgorithmIdentifier{{ SignatureAlgorithms }}, 33 /// signature BIT STRING 34 /// } 35 /// </pre> 36 /// 37 /// certificateRequestInfo is the "Certification request information", it is the value being 38 /// signed; signatureAlgorithm identifies the signature algorithm; and signature is the result 39 /// of signing the certification request information with the subject's private key. from_der(i: &'a [u8]) -> X509Result<Self>40 pub fn from_der(i: &'a [u8]) -> X509Result<Self> { 41 parse_der_sequence_defined_g(|i, _| { 42 let (i, certification_request_info) = X509CertificationRequestInfo::from_der(i)?; 43 let (i, signature_algorithm) = AlgorithmIdentifier::from_der(i)?; 44 let (i, signature_value) = parse_signature_value(i)?; 45 let cert = X509CertificationRequest { 46 certification_request_info, 47 signature_algorithm, 48 signature_value, 49 }; 50 Ok((i, cert)) 51 })(i) 52 } 53 requested_extensions(&self) -> Option<impl Iterator<Item = &ParsedExtension<'a>>>54 pub fn requested_extensions(&self) -> Option<impl Iterator<Item = &ParsedExtension<'a>>> { 55 self.certification_request_info 56 .attributes 57 .values() 58 .find_map(|attr| { 59 if let ParsedCriAttribute::ExtensionRequest(requested) = &attr.parsed_attribute { 60 Some( 61 requested 62 .extensions 63 .values() 64 .map(|ext| &ext.parsed_extension), 65 ) 66 } else { 67 None 68 } 69 }) 70 } 71 72 /// Verify the cryptographic signature of this certification request 73 /// 74 /// Uses the public key contained in the CSR, which must be the one of the entity 75 /// requesting the certification for this verification to succeed. 76 #[cfg(feature = "verify")] verify_signature(&self) -> Result<(), X509Error>77 pub fn verify_signature(&self) -> Result<(), X509Error> { 78 use ring::signature; 79 let spki = &self.certification_request_info.subject_pki; 80 let signature_alg = &self.signature_algorithm.algorithm; 81 // identify verification algorithm 82 let verification_alg: &dyn signature::VerificationAlgorithm = 83 if *signature_alg == OID_PKCS1_SHA1WITHRSA { 84 &signature::RSA_PKCS1_1024_8192_SHA1_FOR_LEGACY_USE_ONLY 85 } else if *signature_alg == OID_PKCS1_SHA256WITHRSA { 86 &signature::RSA_PKCS1_2048_8192_SHA256 87 } else if *signature_alg == OID_PKCS1_SHA384WITHRSA { 88 &signature::RSA_PKCS1_2048_8192_SHA384 89 } else if *signature_alg == OID_PKCS1_SHA512WITHRSA { 90 &signature::RSA_PKCS1_2048_8192_SHA512 91 } else if *signature_alg == OID_SIG_ECDSA_WITH_SHA256 { 92 &signature::ECDSA_P256_SHA256_ASN1 93 } else if *signature_alg == OID_SIG_ECDSA_WITH_SHA384 { 94 &signature::ECDSA_P384_SHA384_ASN1 95 } else { 96 return Err(X509Error::SignatureUnsupportedAlgorithm); 97 }; 98 // get public key 99 let key = signature::UnparsedPublicKey::new(verification_alg, spki.subject_public_key.data); 100 // verify signature 101 let sig = self.signature_value.data; 102 key.verify(self.certification_request_info.raw, sig) 103 .or(Err(X509Error::SignatureVerificationError)) 104 } 105 } 106 107 #[derive(Debug, PartialEq)] 108 pub struct X509CertificationRequestInfo<'a> { 109 pub version: X509Version, 110 pub subject: X509Name<'a>, 111 pub subject_pki: SubjectPublicKeyInfo<'a>, 112 pub attributes: HashMap<Oid<'a>, X509CriAttribute<'a>>, 113 pub raw: &'a [u8], 114 } 115 116 impl<'a> X509CertificationRequestInfo<'a> { 117 /// Parse a certification request info structure 118 /// 119 /// Certification request information is defined by the following ASN.1 structure: 120 /// 121 /// <pre> 122 /// CertificationRequestInfo ::= SEQUENCE { 123 /// version INTEGER { v1(0) } (v1,...), 124 /// subject Name, 125 /// subjectPKInfo SubjectPublicKeyInfo{{ PKInfoAlgorithms }}, 126 /// attributes [0] Attributes{{ CRIAttributes }} 127 /// } 128 /// </pre> 129 /// 130 /// version is the version number; subject is the distinguished name of the certificate 131 /// subject; subject_pki contains information about the public key being certified, and 132 /// attributes is a collection of attributes providing additional information about the 133 /// subject of the certificate. from_der(i: &'a [u8]) -> X509Result<Self>134 pub fn from_der(i: &'a [u8]) -> X509Result<Self> { 135 let start_i = i; 136 parse_der_sequence_defined_g(move |i, _| { 137 let (i, version) = X509Version::from_der_required(i)?; 138 let (i, subject) = X509Name::from_der(i)?; 139 let (i, subject_pki) = SubjectPublicKeyInfo::from_der(i)?; 140 let (i, attributes) = parse_cri_attributes(i)?; 141 let len = start_i.offset(i); 142 let tbs = X509CertificationRequestInfo { 143 version, 144 subject, 145 subject_pki, 146 attributes, 147 raw: &start_i[..len], 148 }; 149 Ok((i, tbs)) 150 })(i) 151 } 152 } 153