1 //! The standard defining the format of public key certificates. 2 //! 3 //! An `X509` certificate binds an identity to a public key, and is either 4 //! signed by a certificate authority (CA) or self-signed. An entity that gets 5 //! a hold of a certificate can both verify your identity (via a CA) and encrypt 6 //! data with the included public key. `X509` certificates are used in many 7 //! Internet protocols, including SSL/TLS, which is the basis for HTTPS, 8 //! the secure protocol for browsing the web. 9 10 use cfg_if::cfg_if; 11 use foreign_types::{ForeignType, ForeignTypeRef}; 12 use libc::{c_int, c_long, c_uint}; 13 use std::cmp::{self, Ordering}; 14 use std::error::Error; 15 use std::ffi::{CStr, CString}; 16 use std::fmt; 17 use std::marker::PhantomData; 18 use std::mem; 19 use std::path::Path; 20 use std::ptr; 21 use std::slice; 22 use std::str; 23 24 use crate::asn1::{ 25 Asn1BitStringRef, Asn1IntegerRef, Asn1ObjectRef, Asn1StringRef, Asn1TimeRef, Asn1Type, 26 }; 27 use crate::bio::MemBioSlice; 28 use crate::conf::ConfRef; 29 use crate::error::ErrorStack; 30 use crate::ex_data::Index; 31 use crate::hash::{DigestBytes, MessageDigest}; 32 use crate::nid::Nid; 33 use crate::pkey::{HasPrivate, HasPublic, PKey, PKeyRef, Public}; 34 use crate::ssl::SslRef; 35 use crate::stack::{Stack, StackRef, Stackable}; 36 use crate::string::OpensslString; 37 use crate::util::{ForeignTypeExt, ForeignTypeRefExt}; 38 use crate::{cvt, cvt_n, cvt_p}; 39 use openssl_macros::corresponds; 40 41 #[cfg(any(ossl102, libressl261))] 42 pub mod verify; 43 44 pub mod extension; 45 pub mod store; 46 47 #[cfg(test)] 48 mod tests; 49 50 foreign_type_and_impl_send_sync! { 51 type CType = ffi::X509_STORE_CTX; 52 fn drop = ffi::X509_STORE_CTX_free; 53 54 /// An `X509` certificate store context. 55 pub struct X509StoreContext; 56 57 /// A reference to an [`X509StoreContext`]. 58 pub struct X509StoreContextRef; 59 } 60 61 impl X509StoreContext { 62 /// Returns the index which can be used to obtain a reference to the `Ssl` associated with a 63 /// context. 64 #[corresponds(SSL_get_ex_data_X509_STORE_CTX_idx)] ssl_idx() -> Result<Index<X509StoreContext, SslRef>, ErrorStack>65 pub fn ssl_idx() -> Result<Index<X509StoreContext, SslRef>, ErrorStack> { 66 unsafe { cvt_n(ffi::SSL_get_ex_data_X509_STORE_CTX_idx()).map(|idx| Index::from_raw(idx)) } 67 } 68 69 /// Creates a new `X509StoreContext` instance. 70 #[corresponds(X509_STORE_CTX_new)] new() -> Result<X509StoreContext, ErrorStack>71 pub fn new() -> Result<X509StoreContext, ErrorStack> { 72 unsafe { 73 ffi::init(); 74 cvt_p(ffi::X509_STORE_CTX_new()).map(X509StoreContext) 75 } 76 } 77 } 78 79 impl X509StoreContextRef { 80 /// Returns application data pertaining to an `X509` store context. 81 #[corresponds(X509_STORE_CTX_get_ex_data)] ex_data<T>(&self, index: Index<X509StoreContext, T>) -> Option<&T>82 pub fn ex_data<T>(&self, index: Index<X509StoreContext, T>) -> Option<&T> { 83 unsafe { 84 let data = ffi::X509_STORE_CTX_get_ex_data(self.as_ptr(), index.as_raw()); 85 if data.is_null() { 86 None 87 } else { 88 Some(&*(data as *const T)) 89 } 90 } 91 } 92 93 /// Returns the error code of the context. 94 #[corresponds(X509_STORE_CTX_get_error)] error(&self) -> X509VerifyResult95 pub fn error(&self) -> X509VerifyResult { 96 unsafe { X509VerifyResult::from_raw(ffi::X509_STORE_CTX_get_error(self.as_ptr())) } 97 } 98 99 /// Initializes this context with the given certificate, certificates chain and certificate 100 /// store. After initializing the context, the `with_context` closure is called with the prepared 101 /// context. As long as the closure is running, the context stays initialized and can be used 102 /// to e.g. verify a certificate. The context will be cleaned up, after the closure finished. 103 /// 104 /// * `trust` - The certificate store with the trusted certificates. 105 /// * `cert` - The certificate that should be verified. 106 /// * `cert_chain` - The certificates chain. 107 /// * `with_context` - The closure that is called with the initialized context. 108 /// 109 /// This corresponds to [`X509_STORE_CTX_init`] before calling `with_context` and to 110 /// [`X509_STORE_CTX_cleanup`] after calling `with_context`. 111 /// 112 /// [`X509_STORE_CTX_init`]: https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_init.html 113 /// [`X509_STORE_CTX_cleanup`]: https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_cleanup.html init<F, T>( &mut self, trust: &store::X509StoreRef, cert: &X509Ref, cert_chain: &StackRef<X509>, with_context: F, ) -> Result<T, ErrorStack> where F: FnOnce(&mut X509StoreContextRef) -> Result<T, ErrorStack>,114 pub fn init<F, T>( 115 &mut self, 116 trust: &store::X509StoreRef, 117 cert: &X509Ref, 118 cert_chain: &StackRef<X509>, 119 with_context: F, 120 ) -> Result<T, ErrorStack> 121 where 122 F: FnOnce(&mut X509StoreContextRef) -> Result<T, ErrorStack>, 123 { 124 struct Cleanup<'a>(&'a mut X509StoreContextRef); 125 126 impl<'a> Drop for Cleanup<'a> { 127 fn drop(&mut self) { 128 unsafe { 129 ffi::X509_STORE_CTX_cleanup(self.0.as_ptr()); 130 } 131 } 132 } 133 134 unsafe { 135 cvt(ffi::X509_STORE_CTX_init( 136 self.as_ptr(), 137 trust.as_ptr(), 138 cert.as_ptr(), 139 cert_chain.as_ptr(), 140 ))?; 141 142 let cleanup = Cleanup(self); 143 with_context(cleanup.0) 144 } 145 } 146 147 /// Verifies the stored certificate. 148 /// 149 /// Returns `true` if verification succeeds. The `error` method will return the specific 150 /// validation error if the certificate was not valid. 151 /// 152 /// This will only work inside of a call to `init`. 153 #[corresponds(X509_verify_cert)] verify_cert(&mut self) -> Result<bool, ErrorStack>154 pub fn verify_cert(&mut self) -> Result<bool, ErrorStack> { 155 unsafe { cvt_n(ffi::X509_verify_cert(self.as_ptr())).map(|n| n != 0) } 156 } 157 158 /// Set the error code of the context. 159 #[corresponds(X509_STORE_CTX_set_error)] set_error(&mut self, result: X509VerifyResult)160 pub fn set_error(&mut self, result: X509VerifyResult) { 161 unsafe { 162 ffi::X509_STORE_CTX_set_error(self.as_ptr(), result.as_raw()); 163 } 164 } 165 166 /// Returns a reference to the certificate which caused the error or None if 167 /// no certificate is relevant to the error. 168 #[corresponds(X509_STORE_CTX_get_current_cert)] current_cert(&self) -> Option<&X509Ref>169 pub fn current_cert(&self) -> Option<&X509Ref> { 170 unsafe { 171 let ptr = ffi::X509_STORE_CTX_get_current_cert(self.as_ptr()); 172 X509Ref::from_const_ptr_opt(ptr) 173 } 174 } 175 176 /// Returns a non-negative integer representing the depth in the certificate 177 /// chain where the error occurred. If it is zero it occurred in the end 178 /// entity certificate, one if it is the certificate which signed the end 179 /// entity certificate and so on. 180 #[corresponds(X509_STORE_CTX_get_error_depth)] error_depth(&self) -> u32181 pub fn error_depth(&self) -> u32 { 182 unsafe { ffi::X509_STORE_CTX_get_error_depth(self.as_ptr()) as u32 } 183 } 184 185 /// Returns a reference to a complete valid `X509` certificate chain. 186 #[corresponds(X509_STORE_CTX_get0_chain)] chain(&self) -> Option<&StackRef<X509>>187 pub fn chain(&self) -> Option<&StackRef<X509>> { 188 unsafe { 189 let chain = X509_STORE_CTX_get0_chain(self.as_ptr()); 190 191 if chain.is_null() { 192 None 193 } else { 194 Some(StackRef::from_ptr(chain)) 195 } 196 } 197 } 198 } 199 200 /// A builder used to construct an `X509`. 201 pub struct X509Builder(X509); 202 203 impl X509Builder { 204 /// Creates a new builder. 205 #[corresponds(X509_new)] new() -> Result<X509Builder, ErrorStack>206 pub fn new() -> Result<X509Builder, ErrorStack> { 207 unsafe { 208 ffi::init(); 209 cvt_p(ffi::X509_new()).map(|p| X509Builder(X509(p))) 210 } 211 } 212 213 /// Sets the notAfter constraint on the certificate. 214 #[corresponds(X509_set1_notAfter)] set_not_after(&mut self, not_after: &Asn1TimeRef) -> Result<(), ErrorStack>215 pub fn set_not_after(&mut self, not_after: &Asn1TimeRef) -> Result<(), ErrorStack> { 216 unsafe { cvt(X509_set1_notAfter(self.0.as_ptr(), not_after.as_ptr())).map(|_| ()) } 217 } 218 219 /// Sets the notBefore constraint on the certificate. 220 #[corresponds(X509_set1_notBefore)] set_not_before(&mut self, not_before: &Asn1TimeRef) -> Result<(), ErrorStack>221 pub fn set_not_before(&mut self, not_before: &Asn1TimeRef) -> Result<(), ErrorStack> { 222 unsafe { cvt(X509_set1_notBefore(self.0.as_ptr(), not_before.as_ptr())).map(|_| ()) } 223 } 224 225 /// Sets the version of the certificate. 226 /// 227 /// Note that the version is zero-indexed; that is, a certificate corresponding to version 3 of 228 /// the X.509 standard should pass `2` to this method. 229 #[corresponds(X509_set_version)] set_version(&mut self, version: i32) -> Result<(), ErrorStack>230 pub fn set_version(&mut self, version: i32) -> Result<(), ErrorStack> { 231 unsafe { cvt(ffi::X509_set_version(self.0.as_ptr(), version as c_long)).map(|_| ()) } 232 } 233 234 /// Sets the serial number of the certificate. 235 #[corresponds(X509_set_serialNumber)] set_serial_number(&mut self, serial_number: &Asn1IntegerRef) -> Result<(), ErrorStack>236 pub fn set_serial_number(&mut self, serial_number: &Asn1IntegerRef) -> Result<(), ErrorStack> { 237 unsafe { 238 cvt(ffi::X509_set_serialNumber( 239 self.0.as_ptr(), 240 serial_number.as_ptr(), 241 )) 242 .map(|_| ()) 243 } 244 } 245 246 /// Sets the issuer name of the certificate. 247 #[corresponds(X509_set_issuer_name)] set_issuer_name(&mut self, issuer_name: &X509NameRef) -> Result<(), ErrorStack>248 pub fn set_issuer_name(&mut self, issuer_name: &X509NameRef) -> Result<(), ErrorStack> { 249 unsafe { 250 cvt(ffi::X509_set_issuer_name( 251 self.0.as_ptr(), 252 issuer_name.as_ptr(), 253 )) 254 .map(|_| ()) 255 } 256 } 257 258 /// Sets the subject name of the certificate. 259 /// 260 /// When building certificates, the `C`, `ST`, and `O` options are common when using the openssl command line tools. 261 /// The `CN` field is used for the common name, such as a DNS name. 262 /// 263 /// ``` 264 /// use openssl::x509::{X509, X509NameBuilder}; 265 /// 266 /// let mut x509_name = openssl::x509::X509NameBuilder::new().unwrap(); 267 /// x509_name.append_entry_by_text("C", "US").unwrap(); 268 /// x509_name.append_entry_by_text("ST", "CA").unwrap(); 269 /// x509_name.append_entry_by_text("O", "Some organization").unwrap(); 270 /// x509_name.append_entry_by_text("CN", "www.example.com").unwrap(); 271 /// let x509_name = x509_name.build(); 272 /// 273 /// let mut x509 = openssl::x509::X509::builder().unwrap(); 274 /// x509.set_subject_name(&x509_name).unwrap(); 275 /// ``` 276 #[corresponds(X509_set_subject_name)] set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack>277 pub fn set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack> { 278 unsafe { 279 cvt(ffi::X509_set_subject_name( 280 self.0.as_ptr(), 281 subject_name.as_ptr(), 282 )) 283 .map(|_| ()) 284 } 285 } 286 287 /// Sets the public key associated with the certificate. 288 #[corresponds(X509_set_pubkey)] set_pubkey<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> where T: HasPublic,289 pub fn set_pubkey<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> 290 where 291 T: HasPublic, 292 { 293 unsafe { cvt(ffi::X509_set_pubkey(self.0.as_ptr(), key.as_ptr())).map(|_| ()) } 294 } 295 296 /// Returns a context object which is needed to create certain X509 extension values. 297 /// 298 /// Set `issuer` to `None` if the certificate will be self-signed. 299 #[corresponds(X509V3_set_ctx)] x509v3_context<'a>( &'a self, issuer: Option<&'a X509Ref>, conf: Option<&'a ConfRef>, ) -> X509v3Context<'a>300 pub fn x509v3_context<'a>( 301 &'a self, 302 issuer: Option<&'a X509Ref>, 303 conf: Option<&'a ConfRef>, 304 ) -> X509v3Context<'a> { 305 unsafe { 306 let mut ctx = mem::zeroed(); 307 308 let issuer = match issuer { 309 Some(issuer) => issuer.as_ptr(), 310 None => self.0.as_ptr(), 311 }; 312 let subject = self.0.as_ptr(); 313 ffi::X509V3_set_ctx( 314 &mut ctx, 315 issuer, 316 subject, 317 ptr::null_mut(), 318 ptr::null_mut(), 319 0, 320 ); 321 322 // nodb case taken care of since we zeroed ctx above 323 if let Some(conf) = conf { 324 ffi::X509V3_set_nconf(&mut ctx, conf.as_ptr()); 325 } 326 327 X509v3Context(ctx, PhantomData) 328 } 329 } 330 331 /// Adds an X509 extension value to the certificate. 332 /// 333 /// This works just as `append_extension` except it takes ownership of the `X509Extension`. append_extension(&mut self, extension: X509Extension) -> Result<(), ErrorStack>334 pub fn append_extension(&mut self, extension: X509Extension) -> Result<(), ErrorStack> { 335 self.append_extension2(&extension) 336 } 337 338 /// Adds an X509 extension value to the certificate. 339 #[corresponds(X509_add_ext)] append_extension2(&mut self, extension: &X509ExtensionRef) -> Result<(), ErrorStack>340 pub fn append_extension2(&mut self, extension: &X509ExtensionRef) -> Result<(), ErrorStack> { 341 unsafe { 342 cvt(ffi::X509_add_ext(self.0.as_ptr(), extension.as_ptr(), -1))?; 343 Ok(()) 344 } 345 } 346 347 /// Signs the certificate with a private key. 348 #[corresponds(X509_sign)] sign<T>(&mut self, key: &PKeyRef<T>, hash: MessageDigest) -> Result<(), ErrorStack> where T: HasPrivate,349 pub fn sign<T>(&mut self, key: &PKeyRef<T>, hash: MessageDigest) -> Result<(), ErrorStack> 350 where 351 T: HasPrivate, 352 { 353 unsafe { cvt(ffi::X509_sign(self.0.as_ptr(), key.as_ptr(), hash.as_ptr())).map(|_| ()) } 354 } 355 356 /// Signs the certificate with a private key but without a digest. 357 /// 358 /// This is the only way to sign with Ed25519 keys as BoringSSL doesn't support the null 359 /// message digest. 360 #[cfg(boringssl)] 361 #[corresponds(X509_sign)] sign_without_digest<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> where T: HasPrivate,362 pub fn sign_without_digest<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> 363 where 364 T: HasPrivate, 365 { 366 unsafe { cvt(ffi::X509_sign(self.0.as_ptr(), key.as_ptr(), ptr::null())).map(|_| ()) } 367 } 368 369 /// Consumes the builder, returning the certificate. build(self) -> X509370 pub fn build(self) -> X509 { 371 self.0 372 } 373 } 374 375 foreign_type_and_impl_send_sync! { 376 type CType = ffi::X509; 377 fn drop = ffi::X509_free; 378 379 /// An `X509` public key certificate. 380 pub struct X509; 381 /// Reference to `X509`. 382 pub struct X509Ref; 383 } 384 385 #[cfg(boringssl)] 386 type X509LenTy = c_uint; 387 #[cfg(not(boringssl))] 388 type X509LenTy = c_int; 389 390 impl X509Ref { 391 /// Returns this certificate's subject name. 392 #[corresponds(X509_get_subject_name)] subject_name(&self) -> &X509NameRef393 pub fn subject_name(&self) -> &X509NameRef { 394 unsafe { 395 let name = ffi::X509_get_subject_name(self.as_ptr()); 396 X509NameRef::from_const_ptr_opt(name).expect("subject name must not be null") 397 } 398 } 399 400 /// Returns the hash of the certificates subject 401 #[corresponds(X509_subject_name_hash)] subject_name_hash(&self) -> u32402 pub fn subject_name_hash(&self) -> u32 { 403 unsafe { ffi::X509_subject_name_hash(self.as_ptr()) as u32 } 404 } 405 406 /// Returns this certificate's issuer name. 407 #[corresponds(X509_get_issuer_name)] issuer_name(&self) -> &X509NameRef408 pub fn issuer_name(&self) -> &X509NameRef { 409 unsafe { 410 let name = ffi::X509_get_issuer_name(self.as_ptr()); 411 X509NameRef::from_const_ptr_opt(name).expect("issuer name must not be null") 412 } 413 } 414 415 /// Returns the hash of the certificates issuer 416 #[corresponds(X509_issuer_name_hash)] issuer_name_hash(&self) -> u32417 pub fn issuer_name_hash(&self) -> u32 { 418 unsafe { ffi::X509_issuer_name_hash(self.as_ptr()) as u32 } 419 } 420 421 /// Returns this certificate's subject alternative name entries, if they exist. 422 #[corresponds(X509_get_ext_d2i)] subject_alt_names(&self) -> Option<Stack<GeneralName>>423 pub fn subject_alt_names(&self) -> Option<Stack<GeneralName>> { 424 unsafe { 425 let stack = ffi::X509_get_ext_d2i( 426 self.as_ptr(), 427 ffi::NID_subject_alt_name, 428 ptr::null_mut(), 429 ptr::null_mut(), 430 ); 431 Stack::from_ptr_opt(stack as *mut _) 432 } 433 } 434 435 /// Returns this certificate's issuer alternative name entries, if they exist. 436 #[corresponds(X509_get_ext_d2i)] issuer_alt_names(&self) -> Option<Stack<GeneralName>>437 pub fn issuer_alt_names(&self) -> Option<Stack<GeneralName>> { 438 unsafe { 439 let stack = ffi::X509_get_ext_d2i( 440 self.as_ptr(), 441 ffi::NID_issuer_alt_name, 442 ptr::null_mut(), 443 ptr::null_mut(), 444 ); 445 Stack::from_ptr_opt(stack as *mut _) 446 } 447 } 448 449 /// Returns this certificate's [`authority information access`] entries, if they exist. 450 /// 451 /// [`authority information access`]: https://tools.ietf.org/html/rfc5280#section-4.2.2.1 452 #[corresponds(X509_get_ext_d2i)] authority_info(&self) -> Option<Stack<AccessDescription>>453 pub fn authority_info(&self) -> Option<Stack<AccessDescription>> { 454 unsafe { 455 let stack = ffi::X509_get_ext_d2i( 456 self.as_ptr(), 457 ffi::NID_info_access, 458 ptr::null_mut(), 459 ptr::null_mut(), 460 ); 461 Stack::from_ptr_opt(stack as *mut _) 462 } 463 } 464 465 #[corresponds(X509_get_pubkey)] public_key(&self) -> Result<PKey<Public>, ErrorStack>466 pub fn public_key(&self) -> Result<PKey<Public>, ErrorStack> { 467 unsafe { 468 let pkey = cvt_p(ffi::X509_get_pubkey(self.as_ptr()))?; 469 Ok(PKey::from_ptr(pkey)) 470 } 471 } 472 473 /// Returns a digest of the DER representation of the certificate. 474 #[corresponds(X509_digest)] digest(&self, hash_type: MessageDigest) -> Result<DigestBytes, ErrorStack>475 pub fn digest(&self, hash_type: MessageDigest) -> Result<DigestBytes, ErrorStack> { 476 unsafe { 477 let mut digest = DigestBytes { 478 buf: [0; ffi::EVP_MAX_MD_SIZE as usize], 479 len: ffi::EVP_MAX_MD_SIZE as usize, 480 }; 481 let mut len = ffi::EVP_MAX_MD_SIZE as c_uint; 482 cvt(ffi::X509_digest( 483 self.as_ptr(), 484 hash_type.as_ptr(), 485 digest.buf.as_mut_ptr() as *mut _, 486 &mut len, 487 ))?; 488 digest.len = len as usize; 489 490 Ok(digest) 491 } 492 } 493 494 #[deprecated(since = "0.10.9", note = "renamed to digest")] fingerprint(&self, hash_type: MessageDigest) -> Result<Vec<u8>, ErrorStack>495 pub fn fingerprint(&self, hash_type: MessageDigest) -> Result<Vec<u8>, ErrorStack> { 496 self.digest(hash_type).map(|b| b.to_vec()) 497 } 498 499 /// Returns the certificate's Not After validity period. 500 #[corresponds(X509_getm_notAfter)] not_after(&self) -> &Asn1TimeRef501 pub fn not_after(&self) -> &Asn1TimeRef { 502 unsafe { 503 let date = X509_getm_notAfter(self.as_ptr()); 504 Asn1TimeRef::from_const_ptr_opt(date).expect("not_after must not be null") 505 } 506 } 507 508 /// Returns the certificate's Not Before validity period. 509 #[corresponds(X509_getm_notBefore)] not_before(&self) -> &Asn1TimeRef510 pub fn not_before(&self) -> &Asn1TimeRef { 511 unsafe { 512 let date = X509_getm_notBefore(self.as_ptr()); 513 Asn1TimeRef::from_const_ptr_opt(date).expect("not_before must not be null") 514 } 515 } 516 517 /// Returns the certificate's signature 518 #[corresponds(X509_get0_signature)] signature(&self) -> &Asn1BitStringRef519 pub fn signature(&self) -> &Asn1BitStringRef { 520 unsafe { 521 let mut signature = ptr::null(); 522 X509_get0_signature(&mut signature, ptr::null_mut(), self.as_ptr()); 523 Asn1BitStringRef::from_const_ptr_opt(signature).expect("signature must not be null") 524 } 525 } 526 527 /// Returns the certificate's signature algorithm. 528 #[corresponds(X509_get0_signature)] signature_algorithm(&self) -> &X509AlgorithmRef529 pub fn signature_algorithm(&self) -> &X509AlgorithmRef { 530 unsafe { 531 let mut algor = ptr::null(); 532 X509_get0_signature(ptr::null_mut(), &mut algor, self.as_ptr()); 533 X509AlgorithmRef::from_const_ptr_opt(algor) 534 .expect("signature algorithm must not be null") 535 } 536 } 537 538 /// Returns the list of OCSP responder URLs specified in the certificate's Authority Information 539 /// Access field. 540 #[corresponds(X509_get1_ocsp)] ocsp_responders(&self) -> Result<Stack<OpensslString>, ErrorStack>541 pub fn ocsp_responders(&self) -> Result<Stack<OpensslString>, ErrorStack> { 542 unsafe { cvt_p(ffi::X509_get1_ocsp(self.as_ptr())).map(|p| Stack::from_ptr(p)) } 543 } 544 545 /// Checks that this certificate issued `subject`. 546 #[corresponds(X509_check_issued)] issued(&self, subject: &X509Ref) -> X509VerifyResult547 pub fn issued(&self, subject: &X509Ref) -> X509VerifyResult { 548 unsafe { 549 let r = ffi::X509_check_issued(self.as_ptr(), subject.as_ptr()); 550 X509VerifyResult::from_raw(r) 551 } 552 } 553 554 /// Returns certificate version. If this certificate has no explicit version set, it defaults to 555 /// version 1. 556 /// 557 /// Note that `0` return value stands for version 1, `1` for version 2 and so on. 558 #[corresponds(X509_get_version)] 559 #[cfg(ossl110)] version(&self) -> i32560 pub fn version(&self) -> i32 { 561 unsafe { ffi::X509_get_version(self.as_ptr()) as i32 } 562 } 563 564 /// Check if the certificate is signed using the given public key. 565 /// 566 /// Only the signature is checked: no other checks (such as certificate chain validity) 567 /// are performed. 568 /// 569 /// Returns `true` if verification succeeds. 570 #[corresponds(X509_verify)] verify<T>(&self, key: &PKeyRef<T>) -> Result<bool, ErrorStack> where T: HasPublic,571 pub fn verify<T>(&self, key: &PKeyRef<T>) -> Result<bool, ErrorStack> 572 where 573 T: HasPublic, 574 { 575 unsafe { cvt_n(ffi::X509_verify(self.as_ptr(), key.as_ptr())).map(|n| n != 0) } 576 } 577 578 /// Returns this certificate's serial number. 579 #[corresponds(X509_get_serialNumber)] serial_number(&self) -> &Asn1IntegerRef580 pub fn serial_number(&self) -> &Asn1IntegerRef { 581 unsafe { 582 let r = ffi::X509_get_serialNumber(self.as_ptr()); 583 Asn1IntegerRef::from_const_ptr_opt(r).expect("serial number must not be null") 584 } 585 } 586 587 to_pem! { 588 /// Serializes the certificate into a PEM-encoded X509 structure. 589 /// 590 /// The output will have a header of `-----BEGIN CERTIFICATE-----`. 591 #[corresponds(PEM_write_bio_X509)] 592 to_pem, 593 ffi::PEM_write_bio_X509 594 } 595 596 to_der! { 597 /// Serializes the certificate into a DER-encoded X509 structure. 598 #[corresponds(i2d_X509)] 599 to_der, 600 ffi::i2d_X509 601 } 602 603 to_pem! { 604 /// Converts the certificate to human readable text. 605 #[corresponds(X509_print)] 606 to_text, 607 ffi::X509_print 608 } 609 } 610 611 impl ToOwned for X509Ref { 612 type Owned = X509; 613 to_owned(&self) -> X509614 fn to_owned(&self) -> X509 { 615 unsafe { 616 X509_up_ref(self.as_ptr()); 617 X509::from_ptr(self.as_ptr()) 618 } 619 } 620 } 621 622 impl Ord for X509Ref { cmp(&self, other: &Self) -> cmp::Ordering623 fn cmp(&self, other: &Self) -> cmp::Ordering { 624 // X509_cmp returns a number <0 for less than, 0 for equal and >0 for greater than. 625 // It can't fail if both pointers are valid, which we know is true. 626 let cmp = unsafe { ffi::X509_cmp(self.as_ptr(), other.as_ptr()) }; 627 cmp.cmp(&0) 628 } 629 } 630 631 impl PartialOrd for X509Ref { partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>632 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { 633 Some(self.cmp(other)) 634 } 635 } 636 637 impl PartialOrd<X509> for X509Ref { partial_cmp(&self, other: &X509) -> Option<cmp::Ordering>638 fn partial_cmp(&self, other: &X509) -> Option<cmp::Ordering> { 639 <X509Ref as PartialOrd<X509Ref>>::partial_cmp(self, other) 640 } 641 } 642 643 impl PartialEq for X509Ref { eq(&self, other: &Self) -> bool644 fn eq(&self, other: &Self) -> bool { 645 self.cmp(other) == cmp::Ordering::Equal 646 } 647 } 648 649 impl PartialEq<X509> for X509Ref { eq(&self, other: &X509) -> bool650 fn eq(&self, other: &X509) -> bool { 651 <X509Ref as PartialEq<X509Ref>>::eq(self, other) 652 } 653 } 654 655 impl Eq for X509Ref {} 656 657 impl X509 { 658 /// Returns a new builder. builder() -> Result<X509Builder, ErrorStack>659 pub fn builder() -> Result<X509Builder, ErrorStack> { 660 X509Builder::new() 661 } 662 663 from_pem! { 664 /// Deserializes a PEM-encoded X509 structure. 665 /// 666 /// The input should have a header of `-----BEGIN CERTIFICATE-----`. 667 #[corresponds(PEM_read_bio_X509)] 668 from_pem, 669 X509, 670 ffi::PEM_read_bio_X509 671 } 672 673 from_der! { 674 /// Deserializes a DER-encoded X509 structure. 675 #[corresponds(d2i_X509)] 676 from_der, 677 X509, 678 ffi::d2i_X509 679 } 680 681 /// Deserializes a list of PEM-formatted certificates. 682 #[corresponds(PEM_read_bio_X509)] stack_from_pem(pem: &[u8]) -> Result<Vec<X509>, ErrorStack>683 pub fn stack_from_pem(pem: &[u8]) -> Result<Vec<X509>, ErrorStack> { 684 unsafe { 685 ffi::init(); 686 let bio = MemBioSlice::new(pem)?; 687 688 let mut certs = vec![]; 689 loop { 690 let r = 691 ffi::PEM_read_bio_X509(bio.as_ptr(), ptr::null_mut(), None, ptr::null_mut()); 692 if r.is_null() { 693 let err = ffi::ERR_peek_last_error(); 694 if ffi::ERR_GET_LIB(err) as X509LenTy == ffi::ERR_LIB_PEM 695 && ffi::ERR_GET_REASON(err) == ffi::PEM_R_NO_START_LINE 696 { 697 ffi::ERR_clear_error(); 698 break; 699 } 700 701 return Err(ErrorStack::get()); 702 } else { 703 certs.push(X509(r)); 704 } 705 } 706 707 Ok(certs) 708 } 709 } 710 } 711 712 impl Clone for X509 { clone(&self) -> X509713 fn clone(&self) -> X509 { 714 X509Ref::to_owned(self) 715 } 716 } 717 718 impl fmt::Debug for X509 { fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result719 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { 720 let serial = match &self.serial_number().to_bn() { 721 Ok(bn) => match bn.to_hex_str() { 722 Ok(hex) => hex.to_string(), 723 Err(_) => "".to_string(), 724 }, 725 Err(_) => "".to_string(), 726 }; 727 let mut debug_struct = formatter.debug_struct("X509"); 728 debug_struct.field("serial_number", &serial); 729 debug_struct.field("signature_algorithm", &self.signature_algorithm().object()); 730 debug_struct.field("issuer", &self.issuer_name()); 731 debug_struct.field("subject", &self.subject_name()); 732 if let Some(subject_alt_names) = &self.subject_alt_names() { 733 debug_struct.field("subject_alt_names", subject_alt_names); 734 } 735 debug_struct.field("not_before", &self.not_before()); 736 debug_struct.field("not_after", &self.not_after()); 737 738 if let Ok(public_key) = &self.public_key() { 739 debug_struct.field("public_key", public_key); 740 }; 741 // TODO: Print extensions once they are supported on the X509 struct. 742 743 debug_struct.finish() 744 } 745 } 746 747 impl AsRef<X509Ref> for X509Ref { as_ref(&self) -> &X509Ref748 fn as_ref(&self) -> &X509Ref { 749 self 750 } 751 } 752 753 impl Stackable for X509 { 754 type StackType = ffi::stack_st_X509; 755 } 756 757 impl Ord for X509 { cmp(&self, other: &Self) -> cmp::Ordering758 fn cmp(&self, other: &Self) -> cmp::Ordering { 759 X509Ref::cmp(self, other) 760 } 761 } 762 763 impl PartialOrd for X509 { partial_cmp(&self, other: &Self) -> Option<cmp::Ordering>764 fn partial_cmp(&self, other: &Self) -> Option<cmp::Ordering> { 765 X509Ref::partial_cmp(self, other) 766 } 767 } 768 769 impl PartialOrd<X509Ref> for X509 { partial_cmp(&self, other: &X509Ref) -> Option<cmp::Ordering>770 fn partial_cmp(&self, other: &X509Ref) -> Option<cmp::Ordering> { 771 X509Ref::partial_cmp(self, other) 772 } 773 } 774 775 impl PartialEq for X509 { eq(&self, other: &Self) -> bool776 fn eq(&self, other: &Self) -> bool { 777 X509Ref::eq(self, other) 778 } 779 } 780 781 impl PartialEq<X509Ref> for X509 { eq(&self, other: &X509Ref) -> bool782 fn eq(&self, other: &X509Ref) -> bool { 783 X509Ref::eq(self, other) 784 } 785 } 786 787 impl Eq for X509 {} 788 789 /// A context object required to construct certain `X509` extension values. 790 pub struct X509v3Context<'a>(ffi::X509V3_CTX, PhantomData<(&'a X509Ref, &'a ConfRef)>); 791 792 impl<'a> X509v3Context<'a> { as_ptr(&self) -> *mut ffi::X509V3_CTX793 pub fn as_ptr(&self) -> *mut ffi::X509V3_CTX { 794 &self.0 as *const _ as *mut _ 795 } 796 } 797 798 foreign_type_and_impl_send_sync! { 799 type CType = ffi::X509_EXTENSION; 800 fn drop = ffi::X509_EXTENSION_free; 801 802 /// Permit additional fields to be added to an `X509` v3 certificate. 803 pub struct X509Extension; 804 /// Reference to `X509Extension`. 805 pub struct X509ExtensionRef; 806 } 807 808 impl Stackable for X509Extension { 809 type StackType = ffi::stack_st_X509_EXTENSION; 810 } 811 812 impl X509Extension { 813 /// Constructs an X509 extension value. See `man x509v3_config` for information on supported 814 /// names and their value formats. 815 /// 816 /// Some extension types, such as `subjectAlternativeName`, require an `X509v3Context` to be 817 /// provided. 818 /// 819 /// See the extension module for builder types which will construct certain common extensions. new( conf: Option<&ConfRef>, context: Option<&X509v3Context<'_>>, name: &str, value: &str, ) -> Result<X509Extension, ErrorStack>820 pub fn new( 821 conf: Option<&ConfRef>, 822 context: Option<&X509v3Context<'_>>, 823 name: &str, 824 value: &str, 825 ) -> Result<X509Extension, ErrorStack> { 826 let name = CString::new(name).unwrap(); 827 let value = CString::new(value).unwrap(); 828 unsafe { 829 ffi::init(); 830 let conf = conf.map_or(ptr::null_mut(), ConfRef::as_ptr); 831 let context = context.map_or(ptr::null_mut(), X509v3Context::as_ptr); 832 let name = name.as_ptr() as *mut _; 833 let value = value.as_ptr() as *mut _; 834 835 cvt_p(ffi::X509V3_EXT_nconf(conf, context, name, value)).map(X509Extension) 836 } 837 } 838 839 /// Constructs an X509 extension value. See `man x509v3_config` for information on supported 840 /// extensions and their value formats. 841 /// 842 /// Some extension types, such as `nid::SUBJECT_ALTERNATIVE_NAME`, require an `X509v3Context` to 843 /// be provided. 844 /// 845 /// See the extension module for builder types which will construct certain common extensions. new_nid( conf: Option<&ConfRef>, context: Option<&X509v3Context<'_>>, name: Nid, value: &str, ) -> Result<X509Extension, ErrorStack>846 pub fn new_nid( 847 conf: Option<&ConfRef>, 848 context: Option<&X509v3Context<'_>>, 849 name: Nid, 850 value: &str, 851 ) -> Result<X509Extension, ErrorStack> { 852 let value = CString::new(value).unwrap(); 853 unsafe { 854 ffi::init(); 855 let conf = conf.map_or(ptr::null_mut(), ConfRef::as_ptr); 856 let context = context.map_or(ptr::null_mut(), X509v3Context::as_ptr); 857 let name = name.as_raw(); 858 let value = value.as_ptr() as *mut _; 859 860 cvt_p(ffi::X509V3_EXT_nconf_nid(conf, context, name, value)).map(X509Extension) 861 } 862 } 863 864 /// Adds an alias for an extension 865 /// 866 /// # Safety 867 /// 868 /// This method modifies global state without locking and therefore is not thread safe 869 #[corresponds(X509V3_EXT_add_alias)] add_alias(to: Nid, from: Nid) -> Result<(), ErrorStack>870 pub unsafe fn add_alias(to: Nid, from: Nid) -> Result<(), ErrorStack> { 871 ffi::init(); 872 cvt(ffi::X509V3_EXT_add_alias(to.as_raw(), from.as_raw())).map(|_| ()) 873 } 874 } 875 876 /// A builder used to construct an `X509Name`. 877 pub struct X509NameBuilder(X509Name); 878 879 impl X509NameBuilder { 880 /// Creates a new builder. new() -> Result<X509NameBuilder, ErrorStack>881 pub fn new() -> Result<X509NameBuilder, ErrorStack> { 882 unsafe { 883 ffi::init(); 884 cvt_p(ffi::X509_NAME_new()).map(|p| X509NameBuilder(X509Name(p))) 885 } 886 } 887 888 /// Add a field entry by str. 889 /// 890 /// This corresponds to [`X509_NAME_add_entry_by_txt`]. 891 /// 892 /// [`X509_NAME_add_entry_by_txt`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_add_entry_by_txt.html append_entry_by_text(&mut self, field: &str, value: &str) -> Result<(), ErrorStack>893 pub fn append_entry_by_text(&mut self, field: &str, value: &str) -> Result<(), ErrorStack> { 894 unsafe { 895 let field = CString::new(field).unwrap(); 896 assert!(value.len() <= isize::max_value() as usize); 897 cvt(ffi::X509_NAME_add_entry_by_txt( 898 self.0.as_ptr(), 899 field.as_ptr() as *mut _, 900 ffi::MBSTRING_UTF8, 901 value.as_ptr(), 902 value.len() as isize, 903 -1, 904 0, 905 )) 906 .map(|_| ()) 907 } 908 } 909 910 /// Add a field entry by str with a specific type. 911 /// 912 /// This corresponds to [`X509_NAME_add_entry_by_txt`]. 913 /// 914 /// [`X509_NAME_add_entry_by_txt`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_add_entry_by_txt.html append_entry_by_text_with_type( &mut self, field: &str, value: &str, ty: Asn1Type, ) -> Result<(), ErrorStack>915 pub fn append_entry_by_text_with_type( 916 &mut self, 917 field: &str, 918 value: &str, 919 ty: Asn1Type, 920 ) -> Result<(), ErrorStack> { 921 unsafe { 922 let field = CString::new(field).unwrap(); 923 assert!(value.len() <= isize::max_value() as usize); 924 cvt(ffi::X509_NAME_add_entry_by_txt( 925 self.0.as_ptr(), 926 field.as_ptr() as *mut _, 927 ty.as_raw(), 928 value.as_ptr(), 929 value.len() as isize, 930 -1, 931 0, 932 )) 933 .map(|_| ()) 934 } 935 } 936 937 /// Add a field entry by NID. 938 /// 939 /// This corresponds to [`X509_NAME_add_entry_by_NID`]. 940 /// 941 /// [`X509_NAME_add_entry_by_NID`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_add_entry_by_NID.html append_entry_by_nid(&mut self, field: Nid, value: &str) -> Result<(), ErrorStack>942 pub fn append_entry_by_nid(&mut self, field: Nid, value: &str) -> Result<(), ErrorStack> { 943 unsafe { 944 assert!(value.len() <= isize::max_value() as usize); 945 cvt(ffi::X509_NAME_add_entry_by_NID( 946 self.0.as_ptr(), 947 field.as_raw(), 948 ffi::MBSTRING_UTF8, 949 value.as_ptr() as *mut _, 950 value.len() as isize, 951 -1, 952 0, 953 )) 954 .map(|_| ()) 955 } 956 } 957 958 /// Add a field entry by NID with a specific type. 959 /// 960 /// This corresponds to [`X509_NAME_add_entry_by_NID`]. 961 /// 962 /// [`X509_NAME_add_entry_by_NID`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_add_entry_by_NID.html append_entry_by_nid_with_type( &mut self, field: Nid, value: &str, ty: Asn1Type, ) -> Result<(), ErrorStack>963 pub fn append_entry_by_nid_with_type( 964 &mut self, 965 field: Nid, 966 value: &str, 967 ty: Asn1Type, 968 ) -> Result<(), ErrorStack> { 969 unsafe { 970 assert!(value.len() <= isize::max_value() as usize); 971 cvt(ffi::X509_NAME_add_entry_by_NID( 972 self.0.as_ptr(), 973 field.as_raw(), 974 ty.as_raw(), 975 value.as_ptr() as *mut _, 976 value.len() as isize, 977 -1, 978 0, 979 )) 980 .map(|_| ()) 981 } 982 } 983 984 /// Return an `X509Name`. build(self) -> X509Name985 pub fn build(self) -> X509Name { 986 self.0 987 } 988 } 989 990 foreign_type_and_impl_send_sync! { 991 type CType = ffi::X509_NAME; 992 fn drop = ffi::X509_NAME_free; 993 994 /// The names of an `X509` certificate. 995 pub struct X509Name; 996 /// Reference to `X509Name`. 997 pub struct X509NameRef; 998 } 999 1000 impl X509Name { 1001 /// Returns a new builder. builder() -> Result<X509NameBuilder, ErrorStack>1002 pub fn builder() -> Result<X509NameBuilder, ErrorStack> { 1003 X509NameBuilder::new() 1004 } 1005 1006 /// Loads subject names from a file containing PEM-formatted certificates. 1007 /// 1008 /// This is commonly used in conjunction with `SslContextBuilder::set_client_ca_list`. load_client_ca_file<P: AsRef<Path>>(file: P) -> Result<Stack<X509Name>, ErrorStack>1009 pub fn load_client_ca_file<P: AsRef<Path>>(file: P) -> Result<Stack<X509Name>, ErrorStack> { 1010 let file = CString::new(file.as_ref().as_os_str().to_str().unwrap()).unwrap(); 1011 unsafe { cvt_p(ffi::SSL_load_client_CA_file(file.as_ptr())).map(|p| Stack::from_ptr(p)) } 1012 } 1013 1014 from_der! { 1015 /// Deserializes a DER-encoded X509 name structure. 1016 /// 1017 /// This corresponds to [`d2i_X509_NAME`]. 1018 /// 1019 /// [`d2i_X509_NAME`]: https://www.openssl.org/docs/manmaster/man3/d2i_X509_NAME.html 1020 from_der, 1021 X509Name, 1022 ffi::d2i_X509_NAME 1023 } 1024 } 1025 1026 impl Stackable for X509Name { 1027 type StackType = ffi::stack_st_X509_NAME; 1028 } 1029 1030 impl X509NameRef { 1031 /// Returns the name entries by the nid. entries_by_nid(&self, nid: Nid) -> X509NameEntries<'_>1032 pub fn entries_by_nid(&self, nid: Nid) -> X509NameEntries<'_> { 1033 X509NameEntries { 1034 name: self, 1035 nid: Some(nid), 1036 loc: -1, 1037 } 1038 } 1039 1040 /// Returns an iterator over all `X509NameEntry` values entries(&self) -> X509NameEntries<'_>1041 pub fn entries(&self) -> X509NameEntries<'_> { 1042 X509NameEntries { 1043 name: self, 1044 nid: None, 1045 loc: -1, 1046 } 1047 } 1048 1049 /// Compare two names, like [`Ord`] but it may fail. 1050 /// 1051 /// With OpenSSL versions from 3.0.0 this may return an error if the underlying `X509_NAME_cmp` 1052 /// call fails. 1053 /// For OpenSSL versions before 3.0.0 it will never return an error, but due to a bug it may 1054 /// spuriously return `Ordering::Less` if the `X509_NAME_cmp` call fails. 1055 #[corresponds(X509_NAME_cmp)] try_cmp(&self, other: &X509NameRef) -> Result<Ordering, ErrorStack>1056 pub fn try_cmp(&self, other: &X509NameRef) -> Result<Ordering, ErrorStack> { 1057 let cmp = unsafe { ffi::X509_NAME_cmp(self.as_ptr(), other.as_ptr()) }; 1058 if cfg!(ossl300) && cmp == -2 { 1059 return Err(ErrorStack::get()); 1060 } 1061 Ok(cmp.cmp(&0)) 1062 } 1063 1064 to_der! { 1065 /// Serializes the certificate into a DER-encoded X509 name structure. 1066 /// 1067 /// This corresponds to [`i2d_X509_NAME`]. 1068 /// 1069 /// [`i2d_X509_NAME`]: https://www.openssl.org/docs/man1.1.0/crypto/i2d_X509_NAME.html 1070 to_der, 1071 ffi::i2d_X509_NAME 1072 } 1073 } 1074 1075 impl fmt::Debug for X509NameRef { fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result1076 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { 1077 formatter.debug_list().entries(self.entries()).finish() 1078 } 1079 } 1080 1081 /// A type to destructure and examine an `X509Name`. 1082 pub struct X509NameEntries<'a> { 1083 name: &'a X509NameRef, 1084 nid: Option<Nid>, 1085 loc: c_int, 1086 } 1087 1088 impl<'a> Iterator for X509NameEntries<'a> { 1089 type Item = &'a X509NameEntryRef; 1090 next(&mut self) -> Option<&'a X509NameEntryRef>1091 fn next(&mut self) -> Option<&'a X509NameEntryRef> { 1092 unsafe { 1093 match self.nid { 1094 Some(nid) => { 1095 // There is a `Nid` specified to search for 1096 self.loc = 1097 ffi::X509_NAME_get_index_by_NID(self.name.as_ptr(), nid.as_raw(), self.loc); 1098 if self.loc == -1 { 1099 return None; 1100 } 1101 } 1102 None => { 1103 // Iterate over all `Nid`s 1104 self.loc += 1; 1105 if self.loc >= ffi::X509_NAME_entry_count(self.name.as_ptr()) { 1106 return None; 1107 } 1108 } 1109 } 1110 1111 let entry = ffi::X509_NAME_get_entry(self.name.as_ptr(), self.loc); 1112 1113 Some(X509NameEntryRef::from_const_ptr_opt(entry).expect("entry must not be null")) 1114 } 1115 } 1116 } 1117 1118 foreign_type_and_impl_send_sync! { 1119 type CType = ffi::X509_NAME_ENTRY; 1120 fn drop = ffi::X509_NAME_ENTRY_free; 1121 1122 /// A name entry associated with a `X509Name`. 1123 pub struct X509NameEntry; 1124 /// Reference to `X509NameEntry`. 1125 pub struct X509NameEntryRef; 1126 } 1127 1128 impl X509NameEntryRef { 1129 /// Returns the field value of an `X509NameEntry`. 1130 /// 1131 /// This corresponds to [`X509_NAME_ENTRY_get_data`]. 1132 /// 1133 /// [`X509_NAME_ENTRY_get_data`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_ENTRY_get_data.html data(&self) -> &Asn1StringRef1134 pub fn data(&self) -> &Asn1StringRef { 1135 unsafe { 1136 let data = ffi::X509_NAME_ENTRY_get_data(self.as_ptr()); 1137 Asn1StringRef::from_ptr(data) 1138 } 1139 } 1140 1141 /// Returns the `Asn1Object` value of an `X509NameEntry`. 1142 /// This is useful for finding out about the actual `Nid` when iterating over all `X509NameEntries`. 1143 /// 1144 /// This corresponds to [`X509_NAME_ENTRY_get_object`]. 1145 /// 1146 /// [`X509_NAME_ENTRY_get_object`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_ENTRY_get_object.html object(&self) -> &Asn1ObjectRef1147 pub fn object(&self) -> &Asn1ObjectRef { 1148 unsafe { 1149 let object = ffi::X509_NAME_ENTRY_get_object(self.as_ptr()); 1150 Asn1ObjectRef::from_ptr(object) 1151 } 1152 } 1153 } 1154 1155 impl fmt::Debug for X509NameEntryRef { fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result1156 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { 1157 formatter.write_fmt(format_args!("{:?} = {:?}", self.object(), self.data())) 1158 } 1159 } 1160 1161 /// A builder used to construct an `X509Req`. 1162 pub struct X509ReqBuilder(X509Req); 1163 1164 impl X509ReqBuilder { 1165 /// Returns a builder for a certificate request. 1166 /// 1167 /// This corresponds to [`X509_REQ_new`]. 1168 /// 1169 ///[`X509_REQ_new`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_new.html new() -> Result<X509ReqBuilder, ErrorStack>1170 pub fn new() -> Result<X509ReqBuilder, ErrorStack> { 1171 unsafe { 1172 ffi::init(); 1173 cvt_p(ffi::X509_REQ_new()).map(|p| X509ReqBuilder(X509Req(p))) 1174 } 1175 } 1176 1177 /// Set the numerical value of the version field. 1178 /// 1179 /// This corresponds to [`X509_REQ_set_version`]. 1180 /// 1181 ///[`X509_REQ_set_version`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_set_version.html set_version(&mut self, version: i32) -> Result<(), ErrorStack>1182 pub fn set_version(&mut self, version: i32) -> Result<(), ErrorStack> { 1183 unsafe { 1184 cvt(ffi::X509_REQ_set_version( 1185 self.0.as_ptr(), 1186 version as c_long, 1187 )) 1188 .map(|_| ()) 1189 } 1190 } 1191 1192 /// Set the issuer name. 1193 /// 1194 /// This corresponds to [`X509_REQ_set_subject_name`]. 1195 /// 1196 /// [`X509_REQ_set_subject_name`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_set_subject_name.html set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack>1197 pub fn set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack> { 1198 unsafe { 1199 cvt(ffi::X509_REQ_set_subject_name( 1200 self.0.as_ptr(), 1201 subject_name.as_ptr(), 1202 )) 1203 .map(|_| ()) 1204 } 1205 } 1206 1207 /// Set the public key. 1208 /// 1209 /// This corresponds to [`X509_REQ_set_pubkey`]. 1210 /// 1211 /// [`X509_REQ_set_pubkey`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_set_pubkey.html set_pubkey<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> where T: HasPublic,1212 pub fn set_pubkey<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> 1213 where 1214 T: HasPublic, 1215 { 1216 unsafe { cvt(ffi::X509_REQ_set_pubkey(self.0.as_ptr(), key.as_ptr())).map(|_| ()) } 1217 } 1218 1219 /// Return an `X509v3Context`. This context object can be used to construct 1220 /// certain `X509` extensions. x509v3_context<'a>(&'a self, conf: Option<&'a ConfRef>) -> X509v3Context<'a>1221 pub fn x509v3_context<'a>(&'a self, conf: Option<&'a ConfRef>) -> X509v3Context<'a> { 1222 unsafe { 1223 let mut ctx = mem::zeroed(); 1224 1225 ffi::X509V3_set_ctx( 1226 &mut ctx, 1227 ptr::null_mut(), 1228 ptr::null_mut(), 1229 self.0.as_ptr(), 1230 ptr::null_mut(), 1231 0, 1232 ); 1233 1234 // nodb case taken care of since we zeroed ctx above 1235 if let Some(conf) = conf { 1236 ffi::X509V3_set_nconf(&mut ctx, conf.as_ptr()); 1237 } 1238 1239 X509v3Context(ctx, PhantomData) 1240 } 1241 } 1242 1243 /// Permits any number of extension fields to be added to the certificate. add_extensions( &mut self, extensions: &StackRef<X509Extension>, ) -> Result<(), ErrorStack>1244 pub fn add_extensions( 1245 &mut self, 1246 extensions: &StackRef<X509Extension>, 1247 ) -> Result<(), ErrorStack> { 1248 unsafe { 1249 cvt(ffi::X509_REQ_add_extensions( 1250 self.0.as_ptr(), 1251 extensions.as_ptr(), 1252 )) 1253 .map(|_| ()) 1254 } 1255 } 1256 1257 /// Sign the request using a private key. 1258 /// 1259 /// This corresponds to [`X509_REQ_sign`]. 1260 /// 1261 /// [`X509_REQ_sign`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_sign.html sign<T>(&mut self, key: &PKeyRef<T>, hash: MessageDigest) -> Result<(), ErrorStack> where T: HasPrivate,1262 pub fn sign<T>(&mut self, key: &PKeyRef<T>, hash: MessageDigest) -> Result<(), ErrorStack> 1263 where 1264 T: HasPrivate, 1265 { 1266 unsafe { 1267 cvt(ffi::X509_REQ_sign( 1268 self.0.as_ptr(), 1269 key.as_ptr(), 1270 hash.as_ptr(), 1271 )) 1272 .map(|_| ()) 1273 } 1274 } 1275 1276 /// Sign the request using a private key without a digest. 1277 /// 1278 /// This is the only way to sign with Ed25519 keys as BoringSSL doesn't support the null 1279 /// message digest. 1280 /// 1281 /// This corresponds to [`X509_REQ_sign`]. 1282 /// 1283 /// [`X509_REQ_sign`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_sign.html 1284 #[cfg(boringssl)] sign_without_digest<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> where T: HasPrivate,1285 pub fn sign_without_digest<T>(&mut self, key: &PKeyRef<T>) -> Result<(), ErrorStack> 1286 where 1287 T: HasPrivate, 1288 { 1289 unsafe { 1290 cvt(ffi::X509_REQ_sign( 1291 self.0.as_ptr(), 1292 key.as_ptr(), 1293 ptr::null(), 1294 )) 1295 .map(|_| ()) 1296 } 1297 } 1298 1299 /// Returns the `X509Req`. build(self) -> X509Req1300 pub fn build(self) -> X509Req { 1301 self.0 1302 } 1303 } 1304 1305 foreign_type_and_impl_send_sync! { 1306 type CType = ffi::X509_REQ; 1307 fn drop = ffi::X509_REQ_free; 1308 1309 /// An `X509` certificate request. 1310 pub struct X509Req; 1311 /// Reference to `X509Req`. 1312 pub struct X509ReqRef; 1313 } 1314 1315 impl X509Req { 1316 /// A builder for `X509Req`. builder() -> Result<X509ReqBuilder, ErrorStack>1317 pub fn builder() -> Result<X509ReqBuilder, ErrorStack> { 1318 X509ReqBuilder::new() 1319 } 1320 1321 from_pem! { 1322 /// Deserializes a PEM-encoded PKCS#10 certificate request structure. 1323 /// 1324 /// The input should have a header of `-----BEGIN CERTIFICATE REQUEST-----`. 1325 /// 1326 /// This corresponds to [`PEM_read_bio_X509_REQ`]. 1327 /// 1328 /// [`PEM_read_bio_X509_REQ`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_read_bio_X509_REQ.html 1329 from_pem, 1330 X509Req, 1331 ffi::PEM_read_bio_X509_REQ 1332 } 1333 1334 from_der! { 1335 /// Deserializes a DER-encoded PKCS#10 certificate request structure. 1336 /// 1337 /// This corresponds to [`d2i_X509_REQ`]. 1338 /// 1339 /// [`d2i_X509_REQ`]: https://www.openssl.org/docs/man1.1.0/crypto/d2i_X509_REQ.html 1340 from_der, 1341 X509Req, 1342 ffi::d2i_X509_REQ 1343 } 1344 } 1345 1346 impl X509ReqRef { 1347 to_pem! { 1348 /// Serializes the certificate request to a PEM-encoded PKCS#10 structure. 1349 /// 1350 /// The output will have a header of `-----BEGIN CERTIFICATE REQUEST-----`. 1351 /// 1352 /// This corresponds to [`PEM_write_bio_X509_REQ`]. 1353 /// 1354 /// [`PEM_write_bio_X509_REQ`]: https://www.openssl.org/docs/man1.0.2/crypto/PEM_write_bio_X509_REQ.html 1355 to_pem, 1356 ffi::PEM_write_bio_X509_REQ 1357 } 1358 1359 to_der! { 1360 /// Serializes the certificate request to a DER-encoded PKCS#10 structure. 1361 /// 1362 /// This corresponds to [`i2d_X509_REQ`]. 1363 /// 1364 /// [`i2d_X509_REQ`]: https://www.openssl.org/docs/man1.0.2/crypto/i2d_X509_REQ.html 1365 to_der, 1366 ffi::i2d_X509_REQ 1367 } 1368 1369 to_pem! { 1370 /// Converts the request to human readable text. 1371 #[corresponds(X509_Req_print)] 1372 to_text, 1373 ffi::X509_REQ_print 1374 } 1375 1376 /// Returns the numerical value of the version field of the certificate request. 1377 /// 1378 /// This corresponds to [`X509_REQ_get_version`] 1379 /// 1380 /// [`X509_REQ_get_version`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_get_version.html version(&self) -> i321381 pub fn version(&self) -> i32 { 1382 unsafe { X509_REQ_get_version(self.as_ptr()) as i32 } 1383 } 1384 1385 /// Returns the subject name of the certificate request. 1386 /// 1387 /// This corresponds to [`X509_REQ_get_subject_name`] 1388 /// 1389 /// [`X509_REQ_get_subject_name`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_get_subject_name.html subject_name(&self) -> &X509NameRef1390 pub fn subject_name(&self) -> &X509NameRef { 1391 unsafe { 1392 let name = X509_REQ_get_subject_name(self.as_ptr()); 1393 X509NameRef::from_const_ptr_opt(name).expect("subject name must not be null") 1394 } 1395 } 1396 1397 /// Returns the public key of the certificate request. 1398 /// 1399 /// This corresponds to [`X509_REQ_get_pubkey"] 1400 /// 1401 /// [`X509_REQ_get_pubkey`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_get_pubkey.html public_key(&self) -> Result<PKey<Public>, ErrorStack>1402 pub fn public_key(&self) -> Result<PKey<Public>, ErrorStack> { 1403 unsafe { 1404 let key = cvt_p(ffi::X509_REQ_get_pubkey(self.as_ptr()))?; 1405 Ok(PKey::from_ptr(key)) 1406 } 1407 } 1408 1409 /// Check if the certificate request is signed using the given public key. 1410 /// 1411 /// Returns `true` if verification succeeds. 1412 /// 1413 /// This corresponds to [`X509_REQ_verify"]. 1414 /// 1415 /// [`X509_REQ_verify`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_verify.html verify<T>(&self, key: &PKeyRef<T>) -> Result<bool, ErrorStack> where T: HasPublic,1416 pub fn verify<T>(&self, key: &PKeyRef<T>) -> Result<bool, ErrorStack> 1417 where 1418 T: HasPublic, 1419 { 1420 unsafe { cvt_n(ffi::X509_REQ_verify(self.as_ptr(), key.as_ptr())).map(|n| n != 0) } 1421 } 1422 1423 /// Returns the extensions of the certificate request. 1424 /// 1425 /// This corresponds to [`X509_REQ_get_extensions"] extensions(&self) -> Result<Stack<X509Extension>, ErrorStack>1426 pub fn extensions(&self) -> Result<Stack<X509Extension>, ErrorStack> { 1427 unsafe { 1428 let extensions = cvt_p(ffi::X509_REQ_get_extensions(self.as_ptr()))?; 1429 Ok(Stack::from_ptr(extensions)) 1430 } 1431 } 1432 } 1433 1434 /// The result of peer certificate verification. 1435 #[derive(Copy, Clone, PartialEq, Eq)] 1436 pub struct X509VerifyResult(c_int); 1437 1438 impl fmt::Debug for X509VerifyResult { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result1439 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 1440 fmt.debug_struct("X509VerifyResult") 1441 .field("code", &self.0) 1442 .field("error", &self.error_string()) 1443 .finish() 1444 } 1445 } 1446 1447 impl fmt::Display for X509VerifyResult { fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result1448 fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { 1449 fmt.write_str(self.error_string()) 1450 } 1451 } 1452 1453 impl Error for X509VerifyResult {} 1454 1455 impl X509VerifyResult { 1456 /// Creates an `X509VerifyResult` from a raw error number. 1457 /// 1458 /// # Safety 1459 /// 1460 /// Some methods on `X509VerifyResult` are not thread safe if the error 1461 /// number is invalid. from_raw(err: c_int) -> X509VerifyResult1462 pub unsafe fn from_raw(err: c_int) -> X509VerifyResult { 1463 X509VerifyResult(err) 1464 } 1465 1466 /// Return the integer representation of an `X509VerifyResult`. 1467 #[allow(clippy::trivially_copy_pass_by_ref)] as_raw(&self) -> c_int1468 pub fn as_raw(&self) -> c_int { 1469 self.0 1470 } 1471 1472 /// Return a human readable error string from the verification error. 1473 /// 1474 /// This corresponds to [`X509_verify_cert_error_string`]. 1475 /// 1476 /// [`X509_verify_cert_error_string`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_verify_cert_error_string.html 1477 #[allow(clippy::trivially_copy_pass_by_ref)] error_string(&self) -> &'static str1478 pub fn error_string(&self) -> &'static str { 1479 ffi::init(); 1480 1481 unsafe { 1482 let s = ffi::X509_verify_cert_error_string(self.0 as c_long); 1483 str::from_utf8(CStr::from_ptr(s).to_bytes()).unwrap() 1484 } 1485 } 1486 1487 /// Successful peer certificate verification. 1488 pub const OK: X509VerifyResult = X509VerifyResult(ffi::X509_V_OK); 1489 /// Application verification failure. 1490 pub const APPLICATION_VERIFICATION: X509VerifyResult = 1491 X509VerifyResult(ffi::X509_V_ERR_APPLICATION_VERIFICATION); 1492 } 1493 1494 foreign_type_and_impl_send_sync! { 1495 type CType = ffi::GENERAL_NAME; 1496 fn drop = ffi::GENERAL_NAME_free; 1497 1498 /// An `X509` certificate alternative names. 1499 pub struct GeneralName; 1500 /// Reference to `GeneralName`. 1501 pub struct GeneralNameRef; 1502 } 1503 1504 impl GeneralNameRef { ia5_string(&self, ffi_type: c_int) -> Option<&str>1505 fn ia5_string(&self, ffi_type: c_int) -> Option<&str> { 1506 unsafe { 1507 if (*self.as_ptr()).type_ != ffi_type { 1508 return None; 1509 } 1510 1511 #[cfg(boringssl)] 1512 let d = (*self.as_ptr()).d.ptr; 1513 #[cfg(not(boringssl))] 1514 let d = (*self.as_ptr()).d; 1515 1516 let ptr = ASN1_STRING_get0_data(d as *mut _); 1517 let len = ffi::ASN1_STRING_length(d as *mut _); 1518 1519 let slice = slice::from_raw_parts(ptr as *const u8, len as usize); 1520 // IA5Strings are stated to be ASCII (specifically IA5). Hopefully 1521 // OpenSSL checks that when loading a certificate but if not we'll 1522 // use this instead of from_utf8_unchecked just in case. 1523 str::from_utf8(slice).ok() 1524 } 1525 } 1526 1527 /// Returns the contents of this `GeneralName` if it is an `rfc822Name`. email(&self) -> Option<&str>1528 pub fn email(&self) -> Option<&str> { 1529 self.ia5_string(ffi::GEN_EMAIL) 1530 } 1531 1532 /// Returns the contents of this `GeneralName` if it is a `dNSName`. dnsname(&self) -> Option<&str>1533 pub fn dnsname(&self) -> Option<&str> { 1534 self.ia5_string(ffi::GEN_DNS) 1535 } 1536 1537 /// Returns the contents of this `GeneralName` if it is an `uniformResourceIdentifier`. uri(&self) -> Option<&str>1538 pub fn uri(&self) -> Option<&str> { 1539 self.ia5_string(ffi::GEN_URI) 1540 } 1541 1542 /// Returns the contents of this `GeneralName` if it is an `iPAddress`. ipaddress(&self) -> Option<&[u8]>1543 pub fn ipaddress(&self) -> Option<&[u8]> { 1544 unsafe { 1545 if (*self.as_ptr()).type_ != ffi::GEN_IPADD { 1546 return None; 1547 } 1548 #[cfg(boringssl)] 1549 let d: *const ffi::ASN1_STRING = std::mem::transmute((*self.as_ptr()).d); 1550 #[cfg(not(boringssl))] 1551 let d = (*self.as_ptr()).d; 1552 1553 let ptr = ASN1_STRING_get0_data(d as *mut _); 1554 let len = ffi::ASN1_STRING_length(d as *mut _); 1555 1556 Some(slice::from_raw_parts(ptr as *const u8, len as usize)) 1557 } 1558 } 1559 } 1560 1561 impl fmt::Debug for GeneralNameRef { fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result1562 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { 1563 if let Some(email) = self.email() { 1564 formatter.write_str(email) 1565 } else if let Some(dnsname) = self.dnsname() { 1566 formatter.write_str(dnsname) 1567 } else if let Some(uri) = self.uri() { 1568 formatter.write_str(uri) 1569 } else if let Some(ipaddress) = self.ipaddress() { 1570 let result = String::from_utf8_lossy(ipaddress); 1571 formatter.write_str(&result) 1572 } else { 1573 formatter.write_str("(empty)") 1574 } 1575 } 1576 } 1577 1578 impl Stackable for GeneralName { 1579 type StackType = ffi::stack_st_GENERAL_NAME; 1580 } 1581 1582 foreign_type_and_impl_send_sync! { 1583 type CType = ffi::ACCESS_DESCRIPTION; 1584 fn drop = ffi::ACCESS_DESCRIPTION_free; 1585 1586 /// `AccessDescription` of certificate authority information. 1587 pub struct AccessDescription; 1588 /// Reference to `AccessDescription`. 1589 pub struct AccessDescriptionRef; 1590 } 1591 1592 impl AccessDescriptionRef { 1593 /// Returns the access method OID. method(&self) -> &Asn1ObjectRef1594 pub fn method(&self) -> &Asn1ObjectRef { 1595 unsafe { Asn1ObjectRef::from_ptr((*self.as_ptr()).method) } 1596 } 1597 1598 // Returns the access location. location(&self) -> &GeneralNameRef1599 pub fn location(&self) -> &GeneralNameRef { 1600 unsafe { GeneralNameRef::from_ptr((*self.as_ptr()).location) } 1601 } 1602 } 1603 1604 impl Stackable for AccessDescription { 1605 type StackType = ffi::stack_st_ACCESS_DESCRIPTION; 1606 } 1607 1608 foreign_type_and_impl_send_sync! { 1609 type CType = ffi::X509_ALGOR; 1610 fn drop = ffi::X509_ALGOR_free; 1611 1612 /// An `X509` certificate signature algorithm. 1613 pub struct X509Algorithm; 1614 /// Reference to `X509Algorithm`. 1615 pub struct X509AlgorithmRef; 1616 } 1617 1618 impl X509AlgorithmRef { 1619 /// Returns the ASN.1 OID of this algorithm. object(&self) -> &Asn1ObjectRef1620 pub fn object(&self) -> &Asn1ObjectRef { 1621 unsafe { 1622 let mut oid = ptr::null(); 1623 X509_ALGOR_get0(&mut oid, ptr::null_mut(), ptr::null_mut(), self.as_ptr()); 1624 Asn1ObjectRef::from_const_ptr_opt(oid).expect("algorithm oid must not be null") 1625 } 1626 } 1627 } 1628 1629 foreign_type_and_impl_send_sync! { 1630 type CType = ffi::X509_OBJECT; 1631 fn drop = X509_OBJECT_free; 1632 1633 /// An `X509` or an X509 certificate revocation list. 1634 pub struct X509Object; 1635 /// Reference to `X509Object` 1636 pub struct X509ObjectRef; 1637 } 1638 1639 impl X509ObjectRef { x509(&self) -> Option<&X509Ref>1640 pub fn x509(&self) -> Option<&X509Ref> { 1641 unsafe { 1642 let ptr = X509_OBJECT_get0_X509(self.as_ptr()); 1643 X509Ref::from_const_ptr_opt(ptr) 1644 } 1645 } 1646 } 1647 1648 impl Stackable for X509Object { 1649 type StackType = ffi::stack_st_X509_OBJECT; 1650 } 1651 1652 cfg_if! { 1653 if #[cfg(any(boringssl, ossl110, libressl273))] { 1654 use ffi::{X509_getm_notAfter, X509_getm_notBefore, X509_up_ref, X509_get0_signature}; 1655 } else { 1656 #[allow(bad_style)] 1657 unsafe fn X509_getm_notAfter(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME { 1658 (*(*(*x).cert_info).validity).notAfter 1659 } 1660 1661 #[allow(bad_style)] 1662 unsafe fn X509_getm_notBefore(x: *mut ffi::X509) -> *mut ffi::ASN1_TIME { 1663 (*(*(*x).cert_info).validity).notBefore 1664 } 1665 1666 #[allow(bad_style)] 1667 unsafe fn X509_up_ref(x: *mut ffi::X509) { 1668 ffi::CRYPTO_add_lock( 1669 &mut (*x).references, 1670 1, 1671 ffi::CRYPTO_LOCK_X509, 1672 "mod.rs\0".as_ptr() as *const _, 1673 line!() as c_int, 1674 ); 1675 } 1676 1677 #[allow(bad_style)] 1678 unsafe fn X509_get0_signature( 1679 psig: *mut *const ffi::ASN1_BIT_STRING, 1680 palg: *mut *const ffi::X509_ALGOR, 1681 x: *const ffi::X509, 1682 ) { 1683 if !psig.is_null() { 1684 *psig = (*x).signature; 1685 } 1686 if !palg.is_null() { 1687 *palg = (*x).sig_alg; 1688 } 1689 } 1690 } 1691 } 1692 1693 cfg_if! { 1694 if #[cfg(any(boringssl, ossl110, libressl350))] { 1695 use ffi::{ 1696 X509_ALGOR_get0, ASN1_STRING_get0_data, X509_STORE_CTX_get0_chain, X509_set1_notAfter, 1697 X509_set1_notBefore, X509_REQ_get_version, X509_REQ_get_subject_name, 1698 }; 1699 } else { 1700 use ffi::{ 1701 ASN1_STRING_data as ASN1_STRING_get0_data, 1702 X509_STORE_CTX_get_chain as X509_STORE_CTX_get0_chain, 1703 X509_set_notAfter as X509_set1_notAfter, 1704 X509_set_notBefore as X509_set1_notBefore, 1705 }; 1706 1707 #[allow(bad_style)] 1708 unsafe fn X509_REQ_get_version(x: *mut ffi::X509_REQ) -> ::libc::c_long { 1709 ffi::ASN1_INTEGER_get((*(*x).req_info).version) 1710 } 1711 1712 #[allow(bad_style)] 1713 unsafe fn X509_REQ_get_subject_name(x: *mut ffi::X509_REQ) -> *mut ::ffi::X509_NAME { 1714 (*(*x).req_info).subject 1715 } 1716 1717 #[allow(bad_style)] 1718 unsafe fn X509_ALGOR_get0( 1719 paobj: *mut *const ffi::ASN1_OBJECT, 1720 pptype: *mut c_int, 1721 pval: *mut *mut ::libc::c_void, 1722 alg: *const ffi::X509_ALGOR, 1723 ) { 1724 if !paobj.is_null() { 1725 *paobj = (*alg).algorithm; 1726 } 1727 assert!(pptype.is_null()); 1728 assert!(pval.is_null()); 1729 } 1730 } 1731 } 1732 1733 cfg_if! { 1734 if #[cfg(any(ossl110, boringssl, libressl270))] { 1735 use ffi::X509_OBJECT_get0_X509; 1736 } else { 1737 #[allow(bad_style)] 1738 unsafe fn X509_OBJECT_get0_X509(x: *mut ffi::X509_OBJECT) -> *mut ffi::X509 { 1739 if (*x).type_ == ffi::X509_LU_X509 { 1740 (*x).data.x509 1741 } else { 1742 ptr::null_mut() 1743 } 1744 } 1745 } 1746 } 1747 1748 cfg_if! { 1749 if #[cfg(any(ossl110, libressl350))] { 1750 use ffi::X509_OBJECT_free; 1751 } else if #[cfg(boringssl)] { 1752 use ffi::X509_OBJECT_free_contents as X509_OBJECT_free; 1753 } else { 1754 #[allow(bad_style)] 1755 unsafe fn X509_OBJECT_free(x: *mut ffi::X509_OBJECT) { 1756 ffi::X509_OBJECT_free_contents(x); 1757 ffi::CRYPTO_free(x as *mut libc::c_void); 1758 } 1759 } 1760 } 1761