summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2014-07-17 15:04:11 +0100
committerCarl Hetherington <cth@carlh.net>2014-07-17 15:04:11 +0100
commita0c90120cb62cfbaf32eb32a7cb09891cb7c539a (patch)
tree5d4207e79953610e42c9a61ad1fb4a6a6a33e3db
parent194f38bccf78e51de0a35367590c2133bb093020 (diff)
Add verify() to CertificateChain.
-rw-r--r--src/certificates.cc49
-rw-r--r--src/certificates.h6
-rw-r--r--test/certificates_test.cc15
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 ());
+}