Loading openssl-sys/src/lib.rs +4 −0 Original line number Diff line number Diff line Loading @@ -2644,6 +2644,7 @@ extern "C" { pub fn X509_sign(x: *mut X509, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> c_int; pub fn X509_get_pubkey(x: *mut X509) -> *mut EVP_PKEY; pub fn X509_to_X509_REQ(x: *mut X509, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> *mut X509_REQ; pub fn X509_verify_cert(ctx: *mut X509_STORE_CTX) -> c_int; pub fn X509_verify_cert_error_string(n: c_long) -> *const c_char; pub fn X509_get1_ocsp(x: *mut X509) -> *mut stack_st_OPENSSL_STRING; pub fn X509_check_issued(issuer: *mut X509, subject: *mut X509) -> c_int; Loading Loading @@ -2677,6 +2678,9 @@ extern "C" { pub fn X509_STORE_add_cert(store: *mut X509_STORE, x: *mut X509) -> c_int; pub fn X509_STORE_set_default_paths(store: *mut X509_STORE) -> c_int; pub fn X509_STORE_CTX_new() -> *mut X509_STORE_CTX; pub fn X509_STORE_CTX_cleanup(ctx: *mut X509_STORE_CTX); pub fn X509_STORE_CTX_init(ctx: *mut X509_STORE_CTX, store: *mut X509_STORE, x509: *mut X509, chain: *mut stack_st_X509) -> c_int; pub fn X509_STORE_CTX_free(ctx: *mut X509_STORE_CTX); pub fn X509_STORE_CTX_get_current_cert(ctx: *mut X509_STORE_CTX) -> *mut X509; pub fn X509_STORE_CTX_get_error(ctx: *mut X509_STORE_CTX) -> c_int; Loading openssl/src/x509/mod.rs +76 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,18 @@ impl X509StoreContext { pub fn ssl_idx() -> Result<Index<X509StoreContext, SslRef>, ErrorStack> { unsafe { cvt_n(ffi::SSL_get_ex_data_X509_STORE_CTX_idx()).map(|idx| Index::from_raw(idx)) } } /// Creates a new `X509StoreContext` instance. /// /// This corresponds to [`X509_STORE_CTX_new`]. /// /// [`X509_STORE_CTX_new`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_STORE_CTX_new.html pub fn new() -> Result<X509StoreContext, ErrorStack> { unsafe { ffi::init(); cvt_p(ffi::X509_STORE_CTX_new()).map(|p| X509StoreContext(p)) } } } impl X509StoreContextRef { Loading Loading @@ -95,6 +107,70 @@ impl X509StoreContextRef { unsafe { X509VerifyResult::from_raw(ffi::X509_STORE_CTX_get_error(self.as_ptr())) } } /// Initializes this context with the given certificate, certificates chain and certificate /// store. After initializing the context, the `with_context` closure is called with the prepared /// context. As long as the closure is running, the context stays initialized and can be used /// to e.g. verify a certificate. The context will be cleaned up, after the closure finished. /// /// * `trust` - The certificate store with the trusted certificates. /// * `cert` - The certificate that should be verified. /// * `cert_chain` - The certificates chain. /// * `with_context` - The closure that is called with the initialized context. /// /// This corresponds to [`X509_STORE_CTX_init`] before calling `with_context` and to /// [`X509_STORE_CTX_cleanup`] after calling `with_context`. /// /// [`X509_STORE_CTX_init`]: https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_init.html /// [`X509_STORE_CTX_cleanup`]: https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_cleanup.html pub fn 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> { struct Cleanup<'a>(&'a mut X509StoreContextRef); impl<'a> Drop for Cleanup<'a> { fn drop(&mut self) { self.0.cleanup(); } } unsafe { cvt(ffi::X509_STORE_CTX_init(self.as_ptr(), trust.as_ptr(), cert.as_ptr(), cert_chain.as_ptr()))?; let cleanup = Cleanup(self); with_context(cleanup.0) } } /// Verifies the stored certificate. /// It is required to call `init` in beforehand, to initialize the required values. /// /// This corresponds to [`X509_verify_cert`]. /// /// [`X509_verify_cert`]: https://www.openssl.org/docs/man1.0.2/crypto/X509_verify_cert.html /// /// # Result /// /// The Result must be `Ok(())` to be a valid certificate, otherwise the cert is not valid. pub fn verify_cert(&mut self) -> Result<(), ErrorStack> { unsafe { cvt(ffi::X509_verify_cert(self.as_ptr())).map(|_| ()) } } /// Cleans-up the context. /// /// This corresponds to [`X509_STORE_CTX_cleanup`]. /// /// [`X509_STORE_CTX_cleanup`]: https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_cleanup.html fn cleanup(&mut self) { unsafe { ffi::X509_STORE_CTX_cleanup(self.as_ptr()); } } /// Set the error code of the context. /// /// This corresponds to [`X509_STORE_CTX_set_error`]. Loading openssl/src/x509/tests.rs +35 −1 Original line number Diff line number Diff line Loading @@ -7,9 +7,10 @@ use nid::Nid; use pkey::{PKey, Private}; use rsa::Rsa; use stack::Stack; use x509::{X509, X509Name, X509Req, X509VerifyResult}; use x509::{X509, X509Name, X509Req, X509VerifyResult, X509StoreContext}; use x509::extension::{AuthorityKeyIdentifier, BasicConstraints, ExtendedKeyUsage, KeyUsage, SubjectAlternativeName, SubjectKeyIdentifier}; use x509::store::X509StoreBuilder; fn pkey() -> PKey<Private> { let rsa = Rsa::generate(2048).unwrap(); Loading Loading @@ -291,3 +292,36 @@ fn clone_x509() { let cert = X509::from_pem(cert).unwrap(); cert.clone(); } #[test] fn test_verify_cert() { let cert = include_bytes!("../../test/cert.pem"); let cert = X509::from_pem(cert).unwrap(); let ca = include_bytes!("../../test/root-ca.pem"); let ca = X509::from_pem(ca).unwrap(); let chain = Stack::new().unwrap(); let mut store_bldr = X509StoreBuilder::new().unwrap(); store_bldr.add_cert(ca).unwrap(); let store = store_bldr.build(); let mut context = X509StoreContext::new().unwrap(); assert!(context.init(&store, &cert, &chain, |c| c.verify_cert()).is_ok()); assert!(context.init(&store, &cert, &chain, |c| c.verify_cert()).is_ok()); } #[test] fn test_verify_fails() { let cert = include_bytes!("../../test/cert.pem"); let cert = X509::from_pem(cert).unwrap(); let ca = include_bytes!("../../test/alt_name_cert.pem"); let ca = X509::from_pem(ca).unwrap(); let chain = Stack::new().unwrap(); let mut store_bldr = X509StoreBuilder::new().unwrap(); store_bldr.add_cert(ca).unwrap(); let store = store_bldr.build(); let mut context = X509StoreContext::new().unwrap(); assert!(context.init(&store, &cert, &chain, |c| c.verify_cert()).is_err()); } Loading
openssl-sys/src/lib.rs +4 −0 Original line number Diff line number Diff line Loading @@ -2644,6 +2644,7 @@ extern "C" { pub fn X509_sign(x: *mut X509, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> c_int; pub fn X509_get_pubkey(x: *mut X509) -> *mut EVP_PKEY; pub fn X509_to_X509_REQ(x: *mut X509, pkey: *mut EVP_PKEY, md: *const EVP_MD) -> *mut X509_REQ; pub fn X509_verify_cert(ctx: *mut X509_STORE_CTX) -> c_int; pub fn X509_verify_cert_error_string(n: c_long) -> *const c_char; pub fn X509_get1_ocsp(x: *mut X509) -> *mut stack_st_OPENSSL_STRING; pub fn X509_check_issued(issuer: *mut X509, subject: *mut X509) -> c_int; Loading Loading @@ -2677,6 +2678,9 @@ extern "C" { pub fn X509_STORE_add_cert(store: *mut X509_STORE, x: *mut X509) -> c_int; pub fn X509_STORE_set_default_paths(store: *mut X509_STORE) -> c_int; pub fn X509_STORE_CTX_new() -> *mut X509_STORE_CTX; pub fn X509_STORE_CTX_cleanup(ctx: *mut X509_STORE_CTX); pub fn X509_STORE_CTX_init(ctx: *mut X509_STORE_CTX, store: *mut X509_STORE, x509: *mut X509, chain: *mut stack_st_X509) -> c_int; pub fn X509_STORE_CTX_free(ctx: *mut X509_STORE_CTX); pub fn X509_STORE_CTX_get_current_cert(ctx: *mut X509_STORE_CTX) -> *mut X509; pub fn X509_STORE_CTX_get_error(ctx: *mut X509_STORE_CTX) -> c_int; Loading
openssl/src/x509/mod.rs +76 −0 Original line number Diff line number Diff line Loading @@ -67,6 +67,18 @@ impl X509StoreContext { pub fn ssl_idx() -> Result<Index<X509StoreContext, SslRef>, ErrorStack> { unsafe { cvt_n(ffi::SSL_get_ex_data_X509_STORE_CTX_idx()).map(|idx| Index::from_raw(idx)) } } /// Creates a new `X509StoreContext` instance. /// /// This corresponds to [`X509_STORE_CTX_new`]. /// /// [`X509_STORE_CTX_new`]: https://www.openssl.org/docs/man1.1.0/crypto/X509_STORE_CTX_new.html pub fn new() -> Result<X509StoreContext, ErrorStack> { unsafe { ffi::init(); cvt_p(ffi::X509_STORE_CTX_new()).map(|p| X509StoreContext(p)) } } } impl X509StoreContextRef { Loading Loading @@ -95,6 +107,70 @@ impl X509StoreContextRef { unsafe { X509VerifyResult::from_raw(ffi::X509_STORE_CTX_get_error(self.as_ptr())) } } /// Initializes this context with the given certificate, certificates chain and certificate /// store. After initializing the context, the `with_context` closure is called with the prepared /// context. As long as the closure is running, the context stays initialized and can be used /// to e.g. verify a certificate. The context will be cleaned up, after the closure finished. /// /// * `trust` - The certificate store with the trusted certificates. /// * `cert` - The certificate that should be verified. /// * `cert_chain` - The certificates chain. /// * `with_context` - The closure that is called with the initialized context. /// /// This corresponds to [`X509_STORE_CTX_init`] before calling `with_context` and to /// [`X509_STORE_CTX_cleanup`] after calling `with_context`. /// /// [`X509_STORE_CTX_init`]: https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_init.html /// [`X509_STORE_CTX_cleanup`]: https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_cleanup.html pub fn 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> { struct Cleanup<'a>(&'a mut X509StoreContextRef); impl<'a> Drop for Cleanup<'a> { fn drop(&mut self) { self.0.cleanup(); } } unsafe { cvt(ffi::X509_STORE_CTX_init(self.as_ptr(), trust.as_ptr(), cert.as_ptr(), cert_chain.as_ptr()))?; let cleanup = Cleanup(self); with_context(cleanup.0) } } /// Verifies the stored certificate. /// It is required to call `init` in beforehand, to initialize the required values. /// /// This corresponds to [`X509_verify_cert`]. /// /// [`X509_verify_cert`]: https://www.openssl.org/docs/man1.0.2/crypto/X509_verify_cert.html /// /// # Result /// /// The Result must be `Ok(())` to be a valid certificate, otherwise the cert is not valid. pub fn verify_cert(&mut self) -> Result<(), ErrorStack> { unsafe { cvt(ffi::X509_verify_cert(self.as_ptr())).map(|_| ()) } } /// Cleans-up the context. /// /// This corresponds to [`X509_STORE_CTX_cleanup`]. /// /// [`X509_STORE_CTX_cleanup`]: https://www.openssl.org/docs/man1.0.2/crypto/X509_STORE_CTX_cleanup.html fn cleanup(&mut self) { unsafe { ffi::X509_STORE_CTX_cleanup(self.as_ptr()); } } /// Set the error code of the context. /// /// This corresponds to [`X509_STORE_CTX_set_error`]. Loading
openssl/src/x509/tests.rs +35 −1 Original line number Diff line number Diff line Loading @@ -7,9 +7,10 @@ use nid::Nid; use pkey::{PKey, Private}; use rsa::Rsa; use stack::Stack; use x509::{X509, X509Name, X509Req, X509VerifyResult}; use x509::{X509, X509Name, X509Req, X509VerifyResult, X509StoreContext}; use x509::extension::{AuthorityKeyIdentifier, BasicConstraints, ExtendedKeyUsage, KeyUsage, SubjectAlternativeName, SubjectKeyIdentifier}; use x509::store::X509StoreBuilder; fn pkey() -> PKey<Private> { let rsa = Rsa::generate(2048).unwrap(); Loading Loading @@ -291,3 +292,36 @@ fn clone_x509() { let cert = X509::from_pem(cert).unwrap(); cert.clone(); } #[test] fn test_verify_cert() { let cert = include_bytes!("../../test/cert.pem"); let cert = X509::from_pem(cert).unwrap(); let ca = include_bytes!("../../test/root-ca.pem"); let ca = X509::from_pem(ca).unwrap(); let chain = Stack::new().unwrap(); let mut store_bldr = X509StoreBuilder::new().unwrap(); store_bldr.add_cert(ca).unwrap(); let store = store_bldr.build(); let mut context = X509StoreContext::new().unwrap(); assert!(context.init(&store, &cert, &chain, |c| c.verify_cert()).is_ok()); assert!(context.init(&store, &cert, &chain, |c| c.verify_cert()).is_ok()); } #[test] fn test_verify_fails() { let cert = include_bytes!("../../test/cert.pem"); let cert = X509::from_pem(cert).unwrap(); let ca = include_bytes!("../../test/alt_name_cert.pem"); let ca = X509::from_pem(ca).unwrap(); let chain = Stack::new().unwrap(); let mut store_bldr = X509StoreBuilder::new().unwrap(); store_bldr.add_cert(ca).unwrap(); let store = store_bldr.build(); let mut context = X509StoreContext::new().unwrap(); assert!(context.init(&store, &cert, &chain, |c| c.verify_cert()).is_err()); }