diff --git a/openssl/src/verify.rs b/openssl/src/verify.rs index 4074c216..866f4f14 100644 --- a/openssl/src/verify.rs +++ b/openssl/src/verify.rs @@ -7,6 +7,7 @@ use cvt; use error::ErrorStack; bitflags! { + /// Flags used to check an `X509` certificate. pub struct X509CheckFlags: c_uint { const ALWAYS_CHECK_SUBJECT = ffi::X509_CHECK_FLAG_ALWAYS_CHECK_SUBJECT; const FLAG_NO_WILDCARDS = ffi::X509_CHECK_FLAG_NO_WILDCARDS; @@ -24,17 +25,29 @@ foreign_type_and_impl_send_sync! { type CType = ffi::X509_VERIFY_PARAM; fn drop = ffi::X509_VERIFY_PARAM_free; + /// Adjust parameters associated with certificate verification. pub struct X509VerifyParam; + /// Reference to `X509VerifyParam`. pub struct X509VerifyParamRef; } impl X509VerifyParamRef { + /// Set the host flags. + /// + /// This corresponds to [`X509_VERIFY_PARAM_set_hostflags`]. + /// + /// [`X509_VERIFY_PARAM_set_hostflags`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_VERIFY_PARAM_set_hostflags.html pub fn set_hostflags(&mut self, hostflags: X509CheckFlags) { unsafe { ffi::X509_VERIFY_PARAM_set_hostflags(self.as_ptr(), hostflags.bits); } } + /// Set the expected DNS hostname. + /// + /// This corresponds to [`X509_VERIFY_PARAM_set1_host`]. + /// + /// [`X509_VERIFY_PARAM_set1_host`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_VERIFY_PARAM_set1_host.html pub fn set_host(&mut self, host: &str) -> Result<(), ErrorStack> { unsafe { cvt(ffi::X509_VERIFY_PARAM_set1_host( @@ -45,6 +58,11 @@ impl X509VerifyParamRef { } } + /// Set the expected IPv4 or IPv6 address. + /// + /// This corresponds to [`X509_VERIFY_PARAM_set1_ip`]. + /// + /// [`X509_VERIFY_PARAM_set1_ip`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_VERIFY_PARAM_set1_ip.htm://www.openssl.org/docs/man1.1.0/crypto/X509_VERIFY_PARAM_set1_ip.html pub fn set_ip(&mut self, ip: IpAddr) -> Result<(), ErrorStack> { unsafe { let mut buf = [0; 16]; diff --git a/openssl/src/x509/extension.rs b/openssl/src/x509/extension.rs index 5c276b4a..f173be92 100644 --- a/openssl/src/x509/extension.rs +++ b/openssl/src/x509/extension.rs @@ -1,9 +1,32 @@ +//! Add extensions to an `X509` certificate or certificate request. +//! +//! The extensions defined for X.509 v3 certificates provide methods for +//! associating additional attributes with users or public keys and for +//! managing relationships between CAs. The extensions created using this +//! module can be used with `X509v3Context` objects. +//! +//! # Example +//! +//! ```rust +//! extern crate openssl; +//! +//! use openssl::x509::extension::BasicConstraints; +//! use openssl::x509::X509Extension; +//! +//! fn main() { +//! let mut bc = BasicConstraints::new(); +//! let bc = bc.critical().ca().pathlen(1); +//! +//! let extension: X509Extension = bc.build().unwrap(); +//! } +//! ``` use std::fmt::Write; use error::ErrorStack; use nid::Nid; use x509::{X509Extension, X509v3Context}; +/// An extension which indicates whether a certificate is a CA certificate. pub struct BasicConstraints { critical: bool, ca: bool, @@ -11,6 +34,7 @@ pub struct BasicConstraints { } impl BasicConstraints { + /// Construct a new `BasicConstraints` extension. pub fn new() -> BasicConstraints { BasicConstraints { critical: false, @@ -19,21 +43,26 @@ impl BasicConstraints { } } + /// Sets the `critical` flag to `true`. The extension will be critical. pub fn critical(&mut self) -> &mut BasicConstraints { self.critical = true; self } + /// Sets the `ca` flag to `true`. pub fn ca(&mut self) -> &mut BasicConstraints { self.ca = true; self } + /// Sets the pathlen to an optional non-negative value. The pathlen is the + /// maximum number of CAs that can appear below this one in a chain. pub fn pathlen(&mut self, pathlen: u32) -> &mut BasicConstraints { self.pathlen = Some(pathlen); self } + /// Return the `BasicConstraints` extension as an `X509Extension`. pub fn build(&self) -> Result { let mut value = String::new(); if self.critical { @@ -52,6 +81,7 @@ impl BasicConstraints { } } +/// An extension consisting of a list of names of the permitted key usages. pub struct KeyUsage { critical: bool, digital_signature: bool, @@ -66,6 +96,7 @@ pub struct KeyUsage { } impl KeyUsage { + /// Construct a new `KeyUsage` extension. pub fn new() -> KeyUsage { KeyUsage { critical: false, @@ -81,56 +112,67 @@ impl KeyUsage { } } + /// Sets the `critical` flag to `true`. The extension will be critical. pub fn critical(&mut self) -> &mut KeyUsage { self.critical = true; self } + /// Sets the `digitalSignature` flag to `true`. pub fn digital_signature(&mut self) -> &mut KeyUsage { self.digital_signature = true; self } + /// Sets the `nonRepudiation` flag to `true`. pub fn non_repudiation(&mut self) -> &mut KeyUsage { self.non_repudiation = true; self } + /// Sets the `keyEncipherment` flag to `true`. pub fn key_encipherment(&mut self) -> &mut KeyUsage { self.key_encipherment = true; self } + /// Sets the `dataEncipherment` flag to `true`. pub fn data_encipherment(&mut self) -> &mut KeyUsage { self.data_encipherment = true; self } + /// Sets the `keyAgreement` flag to `true`. pub fn key_agreement(&mut self) -> &mut KeyUsage { self.key_agreement = true; self } + /// Sets the `keyCertSign` flag to `true`. pub fn key_cert_sign(&mut self) -> &mut KeyUsage { self.key_cert_sign = true; self } + /// Sets the `cRLSign` flag to `true`. pub fn crl_sign(&mut self) -> &mut KeyUsage { self.crl_sign = true; self } + /// Sets the `encipherOnly` flag to `true`. pub fn encipher_only(&mut self) -> &mut KeyUsage { self.encipher_only = true; self } + /// Sets the `decipherOnly` flag to `true`. pub fn decipher_only(&mut self) -> &mut KeyUsage { self.decipher_only = true; self } + /// Return the `KeyUsage` extension as an `X509Extension`. pub fn build(&self) -> Result { let mut value = String::new(); let mut first = true; @@ -168,6 +210,8 @@ impl KeyUsage { } } +/// An extension consisting of a list of usages indicating purposes +/// for which the certificate public key can be used for. pub struct ExtendedKeyUsage { critical: bool, server_auth: bool, @@ -185,6 +229,7 @@ pub struct ExtendedKeyUsage { } impl ExtendedKeyUsage { + /// Construct a new `ExtendedKeyUsage` extension. pub fn new() -> ExtendedKeyUsage { ExtendedKeyUsage { critical: false, @@ -203,66 +248,79 @@ impl ExtendedKeyUsage { } } + /// Sets the `critical` flag to `true`. The extension will be critical. pub fn critical(&mut self) -> &mut ExtendedKeyUsage { self.critical = true; self } + /// Sets the `serverAuth` flag to `true`. pub fn server_auth(&mut self) -> &mut ExtendedKeyUsage { self.server_auth = true; self } + /// Sets the `clientAuth` flag to `true`. pub fn client_auth(&mut self) -> &mut ExtendedKeyUsage { self.client_auth = true; self } + /// Sets the `codeSigning` flag to `true`. pub fn code_signing(&mut self) -> &mut ExtendedKeyUsage { self.code_signing = true; self } + /// Sets the `timeStamping` flag to `true`. pub fn time_stamping(&mut self) -> &mut ExtendedKeyUsage { self.time_stamping = true; self } + /// Sets the `msCodeInd` flag to `true`. pub fn ms_code_ind(&mut self) -> &mut ExtendedKeyUsage { self.ms_code_ind = true; self } + /// Sets the `msCodeCom` flag to `true`. pub fn ms_code_com(&mut self) -> &mut ExtendedKeyUsage { self.ms_code_com = true; self } + /// Sets the `msCTLSign` flag to `true`. pub fn ms_ctl_sign(&mut self) -> &mut ExtendedKeyUsage { self.ms_ctl_sign = true; self } + /// Sets the `msSGC` flag to `true`. pub fn ms_sgc(&mut self) -> &mut ExtendedKeyUsage { self.ms_sgc = true; self } + /// Sets the `msEFS` flag to `true`. pub fn ms_efs(&mut self) -> &mut ExtendedKeyUsage { self.ms_efs = true; self } + /// Sets the `nsSGC` flag to `true`. pub fn ns_sgc(&mut self) -> &mut ExtendedKeyUsage { self.ns_sgc = true; self } + /// Sets a flag not already defined. pub fn other(&mut self, other: &str) -> &mut ExtendedKeyUsage { self.other.push(other.to_owned()); self } + /// Return the `ExtendedKeyUsage` extension as an `X509Extension`. pub fn build(&self) -> Result { let mut value = String::new(); let mut first = true; @@ -290,20 +348,25 @@ impl ExtendedKeyUsage { } } +/// An extension that provides a means of identifying certificates that contain a +/// particular public key. pub struct SubjectKeyIdentifier { critical: bool, } impl SubjectKeyIdentifier { + /// Construct a new `SubjectKeyIdentifier` extension. pub fn new() -> SubjectKeyIdentifier { SubjectKeyIdentifier { critical: false } } + /// Sets the `critical` flag to `true`. The extension will be critical. pub fn critical(&mut self) -> &mut SubjectKeyIdentifier { self.critical = true; self } + /// Return a `SubjectKeyIdentifier` extension as an `X509Extension`. pub fn build(&self, ctx: &X509v3Context) -> Result { let mut value = String::new(); let mut first = true; @@ -313,6 +376,8 @@ impl SubjectKeyIdentifier { } } +/// An extension that provides a means of identifying the public key corresponding +/// to the private key used to sign a CRL. pub struct AuthorityKeyIdentifier { critical: bool, keyid: Option, @@ -320,6 +385,7 @@ pub struct AuthorityKeyIdentifier { } impl AuthorityKeyIdentifier { + /// Construct a new `AuthorityKeyIdentifier` extension. pub fn new() -> AuthorityKeyIdentifier { AuthorityKeyIdentifier { critical: false, @@ -328,21 +394,25 @@ impl AuthorityKeyIdentifier { } } + /// Sets the `critical` flag to `true`. The extension will be critical. pub fn critical(&mut self) -> &mut AuthorityKeyIdentifier { self.critical = true; self } + /// Sets the `keyid` flag. pub fn keyid(&mut self, always: bool) -> &mut AuthorityKeyIdentifier { self.keyid = Some(always); self } + /// Sets the `issuer` flag. pub fn issuer(&mut self, always: bool) -> &mut AuthorityKeyIdentifier { self.issuer = Some(always); self } + /// Return a `AuthorityKeyIdentifier` extension as an `X509Extension`. pub fn build(&self, ctx: &X509v3Context) -> Result { let mut value = String::new(); let mut first = true; @@ -361,12 +431,15 @@ impl AuthorityKeyIdentifier { } } +/// An extension that allows additional identities to be bound to the subject +/// of the certificate. pub struct SubjectAlternativeName { critical: bool, names: Vec, } impl SubjectAlternativeName { + /// Construct a new `SubjectAlternativeName` extension. pub fn new() -> SubjectAlternativeName { SubjectAlternativeName { critical: false, @@ -374,46 +447,55 @@ impl SubjectAlternativeName { } } + /// Sets the `critical` flag to `true`. The extension will be critical. pub fn critical(&mut self) -> &mut SubjectAlternativeName { self.critical = true; self } + /// Sets the `email` flag. pub fn email(&mut self, email: &str) -> &mut SubjectAlternativeName { self.names.push(format!("email:{}", email)); self } + /// Sets the `uri` flag. pub fn uri(&mut self, uri: &str) -> &mut SubjectAlternativeName { self.names.push(format!("URI:{}", uri)); self } + /// Sets the `dns` flag. pub fn dns(&mut self, dns: &str) -> &mut SubjectAlternativeName { self.names.push(format!("DNS:{}", dns)); self } + /// Sets the `rid` flag. pub fn rid(&mut self, rid: &str) -> &mut SubjectAlternativeName { self.names.push(format!("RID:{}", rid)); self } + /// Sets the `ip` flag. pub fn ip(&mut self, ip: &str) -> &mut SubjectAlternativeName { self.names.push(format!("IP:{}", ip)); self } + /// Sets the `dirName` flag. pub fn dir_name(&mut self, dir_name: &str) -> &mut SubjectAlternativeName { self.names.push(format!("dirName:{}", dir_name)); self } + /// Sets the `otherName` flag. pub fn other_name(&mut self, other_name: &str) -> &mut SubjectAlternativeName { self.names.push(format!("otherName:{}", other_name)); self } + /// Return a `SubjectAlternativeName` extension as an `X509Extension`. pub fn build(&self, ctx: &X509v3Context) -> Result { let mut value = String::new(); let mut first = true; diff --git a/openssl/src/x509/mod.rs b/openssl/src/x509/mod.rs index 9491afce..1e1ec339 100644 --- a/openssl/src/x509/mod.rs +++ b/openssl/src/x509/mod.rs @@ -1,3 +1,30 @@ +//! The standard defining the format of public key certificates. +//! +//! An `X509` certificate binds an identity to a public key, and is either +//! signed by a certificate authority (CA) or self-signed. An entity that gets +//! a hold of a certificate can both verify your identity (via a CA) and encrypt +//! data with the included public key. `X509` certificates are used in many +//! Internet protocols, including SSL/TLS, which is the basis for HTTPS, +//! the secure protocol for browsing the web. +//! +//! # Example +//! +//! ```rust +//! +//! extern crate openssl; +//! +//! use openssl::x509::X509; +//! +//! fn main() { +//! let cert = include_bytes!("cert_with_alt_name.pem"); +//! let cert = X509::from_pem(cert).unwrap(); +//! +//! let subject_alt_names = cert.subject_alt_names().unwrap(); +//! let mut san_iter = subject_alt_names.iter(); +//! println!("{:?}", san_iter.next().unwrap().dnsname().unwrap()); +//! } +//! ``` + use libc::{c_int, c_long}; use ffi; use foreign_types::{ForeignType, ForeignTypeRef}; @@ -40,15 +67,20 @@ pub mod store; #[cfg(test)] mod tests; +/// The file type of the encoded `X509` certificate. pub struct X509Filetype(c_int); impl X509Filetype { + /// Returns the raw OpenSSL value represented by this type. pub fn as_raw(&self) -> c_int { self.0 } + /// `PEM` encoded `X509` certificate. pub const PEM: X509Filetype = X509Filetype(ffi::X509_FILETYPE_PEM); + /// `ASN.1` encoded `X509` certificate. pub const ASN1: X509Filetype = X509Filetype(ffi::X509_FILETYPE_ASN1); + /// Default encoded `X509` certificate. pub const DEFAULT: X509Filetype = X509Filetype(ffi::X509_FILETYPE_DEFAULT); } @@ -56,7 +88,10 @@ foreign_type_and_impl_send_sync! { type CType = ffi::X509_STORE_CTX; fn drop = ffi::X509_STORE_CTX_free; + /// An `X509` certificate store context. pub struct X509StoreContext; + + /// Reference to `X509StoreContext`. pub struct X509StoreContextRef; } @@ -69,6 +104,11 @@ impl X509StoreContext { } impl X509StoreContextRef { + /// Returns application data pertaining to an `X509` store context. + /// + /// This corresponds to [`CRYPTO_get_ex_data`]. + /// + /// [`CRYPTO_get_ex_data`]: https://www.openssl.org/docs/man1.1.0/crypto/CRYPTO_get_ex_data.html pub fn ex_data(&self, index: Index) -> Option<&T> { unsafe { let data = ffi::X509_STORE_CTX_get_ex_data(self.as_ptr(), index.as_raw()); @@ -80,16 +120,32 @@ impl X509StoreContextRef { } } + /// Returns the error code of the context. + /// + /// This corresponds to [`X509_STORE_CTX_get_error`]. + /// + /// [`X509_STORE_CTX_get_error`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_STORE_CTX_get_error.html pub fn error(&self) -> X509VerifyResult { unsafe { X509VerifyResult::from_raw(ffi::X509_STORE_CTX_get_error(self.as_ptr())) } } + /// Set the error code of the context. + /// + /// This corresponds to [`X509_STORE_CTX_set_error`]. + /// + /// [`X509_STORE_CTX_set_error`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_STORE_CTX_set_error.html pub fn set_error(&mut self, result: X509VerifyResult) { unsafe { ffi::X509_STORE_CTX_set_error(self.as_ptr(), result.as_raw()); } } + /// Returns a reference to the certificate which caused the error or None if + /// no certificate is relevant to the error. + /// + /// This corresponds to [`X509_STORE_CTX_get_current_cert`]. + /// + /// [`X509_STORE_CTX_get_current_cert`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_STORE_CTX_get_current_cert.html pub fn current_cert(&self) -> Option<&X509Ref> { unsafe { let ptr = ffi::X509_STORE_CTX_get_current_cert(self.as_ptr()); @@ -101,10 +157,23 @@ impl X509StoreContextRef { } } + /// Returns a non-negative integer representing the depth in the certificate + /// chain where the error occurred. If it is zero it occurred in the end + /// entity certificate, one if it is the certificate which signed the end + /// entity certificate and so on. + /// + /// This corresponds to [`X509_STORE_CTX_get_error_depth`]. + /// + /// [`X509_STORE_CTX_get_error_depth`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_STORE_CTX_get_error_depth.html pub fn error_depth(&self) -> u32 { unsafe { ffi::X509_STORE_CTX_get_error_depth(self.as_ptr()) as u32 } } + /// Returns a reference to a complete valid `X509` certificate chain. + /// + /// This corresponds to [`X509_STORE_CTX_get0_chain`]. + /// + /// [`X509_STORE_CTX_get0_chain`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_STORE_CTX_get0_chain.html pub fn chain(&self) -> Option<&StackRef> { unsafe { let chain = X509_STORE_CTX_get_chain(self.as_ptr()); @@ -118,7 +187,7 @@ impl X509StoreContextRef { } } -/// A builder type which can create `X509` objects. +/// A builder used to construct an `X509`. pub struct X509Builder(X509); impl X509Builder { @@ -264,7 +333,9 @@ foreign_type_and_impl_send_sync! { type CType = ffi::X509; fn drop = ffi::X509_free; + /// An `X509` public key certificate. pub struct X509; + /// Reference to `X509`. pub struct X509Ref; } @@ -483,7 +554,7 @@ impl Stackable for X509 { type StackType = ffi::stack_st_X509; } -/// A context object required to construct certain X509 extension values. +/// A context object required to construct certain `X509` extension values. pub struct X509v3Context<'a>(ffi::X509V3_CTX, PhantomData<(&'a X509Ref, &'a ConfRef)>); impl<'a> X509v3Context<'a> { @@ -496,7 +567,9 @@ foreign_type_and_impl_send_sync! { type CType = ffi::X509_EXTENSION; fn drop = ffi::X509_EXTENSION_free; + /// Permit additional fields to be added to an `X509` v3 certificate. pub struct X509Extension; + /// Reference to `X509Extension`. pub struct X509ExtensionRef; } @@ -557,9 +630,11 @@ impl X509Extension { } } +/// A builder used to construct an `X509Name`. pub struct X509NameBuilder(X509Name); impl X509NameBuilder { + /// Creates a new builder. pub fn new() -> Result { unsafe { ffi::init(); @@ -567,6 +642,11 @@ impl X509NameBuilder { } } + /// Add a field entry by str. + /// + /// This corresponds to [`X509_NAME_add_entry_by_txt`]. + /// + /// [`X509_NAME_add_entry_by_txt`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_add_entry_by_txt.html pub fn append_entry_by_text(&mut self, field: &str, value: &str) -> Result<(), ErrorStack> { unsafe { let field = CString::new(field).unwrap(); @@ -583,6 +663,11 @@ impl X509NameBuilder { } } + /// Add a field entry by NID. + /// + /// This corresponds to [`X509_NAME_add_entry_by_NID`]. + /// + /// [`X509_NAME_add_entry_by_NID`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_add_entry_by_NID.html pub fn append_entry_by_nid(&mut self, field: Nid, value: &str) -> Result<(), ErrorStack> { unsafe { assert!(value.len() <= c_int::max_value() as usize); @@ -598,6 +683,7 @@ impl X509NameBuilder { } } + /// Return an `X509Name`. pub fn build(self) -> X509Name { self.0 } @@ -607,7 +693,9 @@ foreign_type_and_impl_send_sync! { type CType = ffi::X509_NAME; fn drop = ffi::X509_NAME_free; + /// The names of an `X509` certificate. pub struct X509Name; + /// Reference to `X509Name`. pub struct X509NameRef; } @@ -631,6 +719,7 @@ impl Stackable for X509Name { } impl X509NameRef { + /// Returns the name entries by the nid. pub fn entries_by_nid<'a>(&'a self, nid: Nid) -> X509NameEntries<'a> { X509NameEntries { name: self, @@ -640,6 +729,7 @@ impl X509NameRef { } } +/// A type to destructure and examine an `X509Name`. pub struct X509NameEntries<'a> { name: &'a X509NameRef, nid: Nid, @@ -670,11 +760,18 @@ foreign_type_and_impl_send_sync! { type CType = ffi::X509_NAME_ENTRY; fn drop = ffi::X509_NAME_ENTRY_free; + /// A name entry associated with a `X509Name`. pub struct X509NameEntry; + /// Reference to `X509NameEntry`. pub struct X509NameEntryRef; } impl X509NameEntryRef { + /// Returns the field value of an `X509NameEntry`. + /// + /// This corresponds to [`X509_NAME_ENTRY_get_data`]. + /// + /// [`X509_NAME_ENTRY_get_data`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_NAME_ENTRY_get_data.html pub fn data(&self) -> &Asn1StringRef { unsafe { let data = ffi::X509_NAME_ENTRY_get_data(self.as_ptr()); @@ -683,9 +780,15 @@ impl X509NameEntryRef { } } +/// A builder used to construct an `X509Req`. pub struct X509ReqBuilder(X509Req); impl X509ReqBuilder { + /// Returns a builder for a certificate request. + /// + /// This corresponds to [`X509_REQ_new`]. + /// + ///[`X509_REQ_new`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_new.html pub fn new() -> Result { unsafe { ffi::init(); @@ -693,10 +796,20 @@ impl X509ReqBuilder { } } + /// Set the numerical value of the version field. + /// + /// This corresponds to [`X509_REQ_set_version`]. + /// + ///[`X509_REQ_set_version`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_set_version.html pub fn set_version(&mut self, version: i32) -> Result<(), ErrorStack> { unsafe { cvt(ffi::X509_REQ_set_version(self.0.as_ptr(), version.into())).map(|_| ()) } } + /// Set the issuer name. + /// + /// This corresponds to [`X509_REQ_set_subject_name`]. + /// + /// [`X509_REQ_set_subject_name`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_set_subject_name.html pub fn set_subject_name(&mut self, subject_name: &X509NameRef) -> Result<(), ErrorStack> { unsafe { cvt(ffi::X509_REQ_set_subject_name( @@ -706,6 +819,11 @@ impl X509ReqBuilder { } } + /// Set the public key. + /// + /// This corresponds to [`X509_REQ_set_pubkey`]. + /// + /// [`X509_REQ_set_pubkey`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_set_pubkey.html pub fn set_pubkey(&mut self, key: &PKeyRef) -> Result<(), ErrorStack> where T: HasPublic, @@ -713,6 +831,8 @@ impl X509ReqBuilder { unsafe { cvt(ffi::X509_REQ_set_pubkey(self.0.as_ptr(), key.as_ptr())).map(|_| ()) } } + /// Return an `X509v3Context`. This context object can be used to construct + /// certain `X509` extensions. pub fn x509v3_context<'a>(&'a self, conf: Option<&'a ConfRef>) -> X509v3Context<'a> { unsafe { let mut ctx = mem::zeroed(); @@ -735,6 +855,7 @@ impl X509ReqBuilder { } } + /// Permits any number of extension fields to be added to the certificate. pub fn add_extensions( &mut self, extensions: &StackRef, @@ -747,6 +868,11 @@ impl X509ReqBuilder { } } + /// Sign the request using a private key. + /// + /// This corresponds to [`X509_REQ_sign`]. + /// + /// [`X509_REQ_sign`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_sign.html pub fn sign(&mut self, key: &PKeyRef, hash: MessageDigest) -> Result<(), ErrorStack> where T: HasPrivate, @@ -760,6 +886,7 @@ impl X509ReqBuilder { } } + /// Returns the `X509Req`. pub fn build(self) -> X509Req { self.0 } @@ -769,16 +896,19 @@ foreign_type_and_impl_send_sync! { type CType = ffi::X509_REQ; fn drop = ffi::X509_REQ_free; + /// An `X509` certificate request. pub struct X509Req; + /// Reference to `X509Req`. pub struct X509ReqRef; } impl X509Req { + /// A builder for `X509Req`. pub fn builder() -> Result { X509ReqBuilder::new() } - /// Reads CSR from PEM + /// Reads Certifcate Signing Request (CSR) from PEM. pub fn from_pem(buf: &[u8]) -> Result { let mem_bio = MemBioSlice::new(buf)?; unsafe { @@ -799,10 +929,20 @@ impl X509ReqRef { to_pem!(ffi::PEM_write_bio_X509_REQ); to_der!(ffi::i2d_X509_REQ); + /// Returns the numerical value of the version field of the certificate request. + /// + /// This corresponds to [`X509_REQ_get_version`] + /// + /// [`X509_REQ_get_version`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_get_version.html pub fn version(&self) -> i32 { unsafe { compat::X509_REQ_get_version(self.as_ptr()) as i32 } } + /// Returns the subject name of the certificate request. + /// + /// This corresponds to [`X509_REQ_get_subject_name`] + /// + /// [`X509_REQ_get_subject_name`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_REQ_get_subject_name.html pub fn subject_name(&self) -> &X509NameRef { unsafe { let name = compat::X509_REQ_get_subject_name(self.as_ptr()); @@ -812,6 +952,7 @@ impl X509ReqRef { } } +/// The result of peer certificate verification. #[derive(Copy, Clone, PartialEq, Eq)] pub struct X509VerifyResult(c_int); @@ -847,10 +988,16 @@ impl X509VerifyResult { X509VerifyResult(err) } + /// Return the integer representation of an `X509VerifyResult`. pub fn as_raw(&self) -> c_int { self.0 } + /// Return a human readable error string from the verification error. + /// + /// This corresponds to [`X509_verify_cert_error_string`]. + /// + /// [`X509_verify_cert_error_string`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_verify_cert_error_string.html pub fn error_string(&self) -> &'static str { ffi::init(); @@ -860,7 +1007,9 @@ impl X509VerifyResult { } } + /// Successful peer certifiate verification. pub const OK: X509VerifyResult = X509VerifyResult(ffi::X509_V_OK); + /// Application verification failure. pub const APPLICATION_VERIFICATION: X509VerifyResult = X509VerifyResult(ffi::X509_V_ERR_APPLICATION_VERIFICATION); } @@ -869,7 +1018,9 @@ foreign_type_and_impl_send_sync! { type CType = ffi::GENERAL_NAME; fn drop = ffi::GENERAL_NAME_free; + /// An `X509` certificate alternative names. pub struct GeneralName; + /// Reference to `GeneralName`. pub struct GeneralNameRef; } @@ -915,7 +1066,9 @@ foreign_type_and_impl_send_sync! { type CType = ffi::X509_ALGOR; fn drop = ffi::X509_ALGOR_free; + /// An `X509` certificate signature algorithm. pub struct X509Algorithm; + /// Reference to `X509Algorithm`. pub struct X509AlgorithmRef; } diff --git a/openssl/src/x509/store.rs b/openssl/src/x509/store.rs index 198679b5..e1e6de7d 100644 --- a/openssl/src/x509/store.rs +++ b/openssl/src/x509/store.rs @@ -1,3 +1,26 @@ +//! Describe a context in which to verify an `X509` certificate. +//! +//! The `X509` certificate store holds trusted CA certificates used to verify +//! peer certificates. +//! +//! # Example +//! +//! ```rust +//! extern crate openssl; +//! +//! use openssl::x509::X509; +//! use openssl::x509::store::{X509StoreBuilder, X509Store}; +//! +//! fn main() { +//! let cert = include_bytes!("cert.pem"); +//! let cert = X509::from_pem(cert).ok().expect("Failed to load PEM"); +//! +//! let mut builder = X509StoreBuilder::new().unwrap(); +//! let _ = builder.add_cert(cert); +//! +//! let store: X509Store = builder.build(); +//! } +//! ``` use ffi; use foreign_types::ForeignTypeRef; use std::mem; @@ -10,7 +33,9 @@ foreign_type! { type CType = ffi::X509_STORE; fn drop = ffi::X509_STORE_free; + /// A builder type used to construct an `X509Store`. pub struct X509StoreBuilder; + /// Reference to an `X509StoreBuilder`. pub struct X509StoreBuilderRef; } @@ -58,6 +83,8 @@ foreign_type! { type CType = ffi::X509_STORE; fn drop = ffi::X509_STORE_free; + /// A certificate store to hold trusted `X509` certificates. pub struct X509Store; + /// Reference to an `X509Store`. pub struct X509StoreRef; }