Add verify() to CertificateChain.
authorCarl Hetherington <cth@carlh.net>
Thu, 17 Jul 2014 14:04:11 +0000 (15:04 +0100)
committerCarl Hetherington <cth@carlh.net>
Thu, 17 Jul 2014 14:04:11 +0000 (15:04 +0100)
src/certificates.cc
src/certificates.h
test/certificates_test.cc

index 0a0393c652bdd6032c98c4a33d9f37a7eda804b6..b6e45c0e900719f284c5332c83a0c2384c4add2b 100644 (file)
@@ -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;
+}
index 96a8cbb7dee6995239cc318cc5ae738c374a4f4b..5a2b9324fb35524b4025e462053bf70c72e9d7ec 100644 (file)
@@ -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;
index 690afa774a6c6c19f6e64667b218c88c1516562c..538a0dae86f3cc0b500f96b7eb203649f06eebb4 100644 (file)
@@ -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 ());
+}