diff options
| author | Carl Hetherington <cth@carlh.net> | 2014-07-17 15:04:11 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2014-07-17 15:04:11 +0100 |
| commit | a0c90120cb62cfbaf32eb32a7cb09891cb7c539a (patch) | |
| tree | 5d4207e79953610e42c9a61ad1fb4a6a6a33e3db | |
| parent | 194f38bccf78e51de0a35367590c2133bb093020 (diff) | |
Add verify() to CertificateChain.
| -rw-r--r-- | src/certificates.cc | 49 | ||||
| -rw-r--r-- | src/certificates.h | 6 | ||||
| -rw-r--r-- | test/certificates_test.cc | 15 |
3 files changed, 70 insertions, 0 deletions
diff --git a/src/certificates.cc b/src/certificates.cc index 0a0393c6..b6e45c0e 100644 --- a/src/certificates.cc +++ b/src/certificates.cc @@ -324,3 +324,52 @@ CertificateChain::add (shared_ptr<Certificate> c) { _certificates.push_back (c); } + +/** Verify the chain. + * @return true if it's ok, false if not. + */ +bool +CertificateChain::verify () const +{ + X509_STORE* store = X509_STORE_new (); + if (!store) { + return false; + } + + for (list<shared_ptr<Certificate> >::const_iterator i = _certificates.begin(); i != _certificates.end(); ++i) { + list<shared_ptr<Certificate> >::const_iterator j = i; + ++j; + if (j == _certificates.end ()) { + break; + } + + if (!X509_STORE_add_cert (store, (*i)->x509 ())) { + X509_STORE_free (store); + return false; + } + + X509_STORE_CTX* ctx = X509_STORE_CTX_new (); + if (!ctx) { + X509_STORE_free (store); + return false; + } + + X509_STORE_set_flags (store, 0); + if (!X509_STORE_CTX_init (ctx, store, (*j)->x509 (), 0)) { + X509_STORE_CTX_free (ctx); + X509_STORE_free (store); + return false; + } + + int v = X509_verify_cert (ctx); + X509_STORE_CTX_free (ctx); + + if (v == 0) { + X509_STORE_free (store); + return false; + } + } + + X509_STORE_free (store); + return true; +} diff --git a/src/certificates.h b/src/certificates.h index 96a8cbb7..5a2b9324 100644 --- a/src/certificates.h +++ b/src/certificates.h @@ -65,6 +65,10 @@ public: std::string subject () const; std::string common_name () const; + X509* x509 () const { + return _certificate; + } + RSA* public_key () const; std::string thumbprint () const; @@ -95,6 +99,8 @@ public: std::list<boost::shared_ptr<Certificate> > leaf_to_root () const; + bool verify () const; + private: friend class ::certificates; std::list<boost::shared_ptr<Certificate> > _certificates; diff --git a/test/certificates_test.cc b/test/certificates_test.cc index 690afa77..538a0dae 100644 --- a/test/certificates_test.cc +++ b/test/certificates_test.cc @@ -81,3 +81,18 @@ BOOST_AUTO_TEST_CASE (certificates) dcp::Certificate test (c.root()->certificate (true)); BOOST_CHECK_EQUAL (test.certificate(), c.root()->certificate()); } + +/** Check that dcp::CertificateChain::validate() basically works */ +BOOST_AUTO_TEST_CASE (certificates_validation) +{ + dcp::CertificateChain good; + good.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/ca.self-signed.pem")))); + good.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/intermediate.signed.pem")))); + good.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/leaf.signed.pem")))); + BOOST_CHECK (good.verify ()); + + dcp::CertificateChain bad; + bad.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/intermediate.signed.pem")))); + bad.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (boost::filesystem::path ("test/ref/crypt/leaf.signed.pem")))); + BOOST_CHECK (!bad.verify ()); +} |
