diff options
| author | Carl Hetherington <cth@carlh.net> | 2014-07-18 00:15:34 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2014-07-18 00:15:34 +0100 |
| commit | 56e7a6f1768036df852a45d939b9adc038b17057 (patch) | |
| tree | 93cf6bb1fb7c9ebe43de09d7690e69cd75b634ea /src | |
| parent | 0b85b9216da9d6519a553de67103a9417504aba1 (diff) | |
Quite large reworking of signer/cert handling.
Diffstat (limited to 'src')
| -rw-r--r-- | src/certificate_chain.cc (renamed from src/signer_chain.cc) | 17 | ||||
| -rw-r--r-- | src/certificate_chain.h (renamed from src/signer_chain.h) | 8 | ||||
| -rw-r--r-- | src/certificates.cc | 15 | ||||
| -rw-r--r-- | src/certificates.h | 12 | ||||
| -rw-r--r-- | src/decrypted_kdm.cc | 14 | ||||
| -rw-r--r-- | src/decrypted_kdm.h | 4 | ||||
| -rw-r--r-- | src/signer.cc | 40 | ||||
| -rw-r--r-- | src/signer.h | 18 | ||||
| -rw-r--r-- | src/wscript | 4 |
9 files changed, 95 insertions, 37 deletions
diff --git a/src/signer_chain.cc b/src/certificate_chain.cc index 3b75b06c..dbed590b 100644 --- a/src/signer_chain.cc +++ b/src/certificate_chain.cc @@ -21,7 +21,7 @@ * @brief Functions to make signer chains. */ -#include "signer_chain.h" +#include "certificate_chain.h" #include "exceptions.h" #include "util.h" #include "KM_util.h" @@ -156,18 +156,17 @@ public_key_digest (boost::filesystem::path private_key, boost::filesystem::path return dig; } -/** Generate a chain of root, intermediate and leaf keys by running an OpenSSL binary. - * @param directory Directory to write the files to. - * @param openssl openssl binary path. - */ -void -dcp::make_signer_chain (boost::filesystem::path directory, boost::filesystem::path openssl) +boost::filesystem::path +dcp::make_certificate_chain (boost::filesystem::path openssl) { + boost::filesystem::path directory = boost::filesystem::unique_path (); + boost::filesystem::create_directories (directory); + boost::filesystem::path const cwd = boost::filesystem::current_path (); + boost::filesystem::current_path (directory); string quoted_openssl = "\"" + openssl.string() + "\""; - boost::filesystem::current_path (directory); command (quoted_openssl + " genrsa -out ca.key 2048"); { @@ -265,4 +264,6 @@ dcp::make_signer_chain (boost::filesystem::path directory, boost::filesystem::pa ); boost::filesystem::current_path (cwd); + + return directory; } diff --git a/src/signer_chain.h b/src/certificate_chain.h index f039caf3..6a6fc483 100644 --- a/src/signer_chain.h +++ b/src/certificate_chain.h @@ -26,9 +26,13 @@ namespace dcp { /** Create a chain of certificates for signing things. - * @param directory Directory to write files to. * @param openssl Name of openssl binary (if it is on the path) or full path. + * @return Directory (which should be deleted by the caller) containing: + * - ca.self-signed.pem self-signed root certificate + * - intermediate.signed.pem intermediate certificate + * - leaf.key leaf certificate private key + * - leaf.signed.pem leaf certificate */ -void make_signer_chain (boost::filesystem::path directory, boost::filesystem::path openssl); +boost::filesystem::path make_certificate_chain (boost::filesystem::path openssl); } diff --git a/src/certificates.cc b/src/certificates.cc index b331c6b6..46c60d6b 100644 --- a/src/certificates.cc +++ b/src/certificates.cc @@ -294,7 +294,7 @@ Certificate::public_key () const } /** @return Root certificate */ -shared_ptr<Certificate> +shared_ptr<const Certificate> CertificateChain::root () const { assert (!_certificates.empty()); @@ -302,7 +302,7 @@ CertificateChain::root () const } /** @return Leaf certificate */ -shared_ptr<Certificate> +shared_ptr<const Certificate> CertificateChain::leaf () const { assert (_certificates.size() >= 2); @@ -329,13 +329,13 @@ CertificateChain::leaf_to_root () const * @param c Certificate to add. */ void -CertificateChain::add (shared_ptr<Certificate> c) +CertificateChain::add (shared_ptr<const Certificate> c) { _certificates.push_back (c); } void -CertificateChain::remove (shared_ptr<Certificate> c) +CertificateChain::remove (shared_ptr<const Certificate> c) { _certificates.remove (c); } @@ -357,11 +357,12 @@ CertificateChain::remove (int i) } } -/** Verify the chain. +/** Check to see if the chain is valid (i.e. root signs the intermediate, intermediate + * signs the leaf and so on). * @return true if it's ok, false if not. */ bool -CertificateChain::verify () const +CertificateChain::valid () const { X509_STORE* store = X509_STORE_new (); if (!store) { @@ -416,7 +417,7 @@ CertificateChain::attempt_reorder () List original = _certificates; _certificates.sort (); do { - if (verify ()) { + if (valid ()) { return true; } } while (std::next_permutation (_certificates.begin(), _certificates.end ())); diff --git a/src/certificates.h b/src/certificates.h index 8ae562c9..06ce92a9 100644 --- a/src/certificates.h +++ b/src/certificates.h @@ -92,19 +92,19 @@ class CertificateChain public: CertificateChain () {} - void add (boost::shared_ptr<Certificate> c); - void remove (boost::shared_ptr<Certificate> c); + void add (boost::shared_ptr<const Certificate> c); + void remove (boost::shared_ptr<const Certificate> c); void remove (int); - boost::shared_ptr<Certificate> root () const; - boost::shared_ptr<Certificate> leaf () const; + boost::shared_ptr<const Certificate> root () const; + boost::shared_ptr<const Certificate> leaf () const; - typedef std::list<boost::shared_ptr<Certificate> > List; + typedef std::list<boost::shared_ptr<const Certificate> > List; List leaf_to_root () const; List root_to_leaf () const; - bool verify () const; + bool valid () const; bool attempt_reorder (); private: diff --git a/src/decrypted_kdm.cc b/src/decrypted_kdm.cc index 8a714b1e..556cd9d5 100644 --- a/src/decrypted_kdm.cc +++ b/src/decrypted_kdm.cc @@ -98,17 +98,16 @@ get (uint8_t ** p, int N) return g; } -DecryptedKDM::DecryptedKDM (EncryptedKDM const & kdm, boost::filesystem::path private_key) +DecryptedKDM::DecryptedKDM (EncryptedKDM const & kdm, string private_key) { /* Read the private key */ - - FILE* private_key_file = fopen_boost (private_key, "r"); - if (!private_key_file) { - throw FileError ("could not find RSA private key file", private_key, errno); + + BIO* bio = BIO_new_mem_buf (const_cast<char *> (private_key.c_str ()), -1); + if (!bio) { + throw MiscError ("could not create memory BIO"); } - RSA* rsa = PEM_read_RSAPrivateKey (private_key_file, 0, 0, 0); - fclose (private_key_file); + RSA* rsa = PEM_read_bio_RSAPrivateKey (bio, 0, 0, 0); if (!rsa) { throw FileError ("could not read RSA private key file", private_key, errno); } @@ -180,6 +179,7 @@ DecryptedKDM::DecryptedKDM (EncryptedKDM const & kdm, boost::filesystem::path pr } RSA_free (rsa); + BIO_free (bio); } DecryptedKDM::DecryptedKDM ( diff --git a/src/decrypted_kdm.h b/src/decrypted_kdm.h index 3c3d07db..dfba7563 100644 --- a/src/decrypted_kdm.h +++ b/src/decrypted_kdm.h @@ -48,9 +48,9 @@ class DecryptedKDM { public: /** @param kdm Encrypted KDM. - * @param private_key Private key file name. + * @param private_key Private key as a PEM-format string. */ - DecryptedKDM (EncryptedKDM const & kdm, boost::filesystem::path private_key); + DecryptedKDM (EncryptedKDM const & kdm, std::string private_key); /** Construct a DecryptedKDM. * @param cpl CPL that the keys are for. diff --git a/src/signer.cc b/src/signer.cc index a0d9912a..55684759 100644 --- a/src/signer.cc +++ b/src/signer.cc @@ -23,6 +23,8 @@ #include "signer.h" #include "exceptions.h" +#include "certificate_chain.h" +#include "util.h" #include <libcxml/cxml.h> #include <libxml++/libxml++.h> #include <xmlsec/xmldsig.h> @@ -37,6 +39,20 @@ using std::cout; using boost::shared_ptr; using namespace dcp; +Signer::Signer (boost::filesystem::path openssl) +{ + boost::filesystem::path directory = make_certificate_chain (openssl); + + _certificates.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (directory / "ca.self-signed.pem"))); + _certificates.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (directory / "intermediate.signed.pem"))); + _certificates.add (shared_ptr<dcp::Certificate> (new dcp::Certificate (directory / "leaf.signed.pem"))); + + _key = dcp::file_to_string (directory / "leaf.key"); + + boost::filesystem::remove_all (directory); +} + + /** Add a <Signer> and <ds:Signature> nodes to an XML node. * @param parent XML node to add to. * @param standard INTEROP or SMPTE. @@ -96,8 +112,8 @@ Signer::add_signature_value (xmlpp::Node* parent, string ns) const xmlpp::Node* key_info = cp.node_child("KeyInfo")->node (); /* Add the certificate chain to the KeyInfo child node of parent */ - list<shared_ptr<Certificate> > c = _certificates.leaf_to_root (); - for (list<shared_ptr<Certificate> >::iterator i = c.begin(); i != c.end(); ++i) { + CertificateChain::List c = _certificates.leaf_to_root (); + for (CertificateChain::List::iterator i = c.begin(); i != c.end(); ++i) { xmlpp::Element* data = key_info->add_child("X509Data", ns); { @@ -134,3 +150,23 @@ Signer::add_signature_value (xmlpp::Node* parent, string ns) const xmlSecDSigCtxDestroy (signature_context); } + +bool +Signer::valid () const +{ + if (!_certificates.valid ()) { + return false; + } + + BIO* bio = BIO_new_mem_buf (const_cast<char *> (_key.c_str ()), -1); + if (!bio) { + throw MiscError ("could not create memory BIO"); + } + + RSA* private_key = PEM_read_bio_RSAPrivateKey (bio, 0, 0, 0); + RSA* public_key = _certificates.leaf()->public_key (); + bool const valid = !BN_cmp (private_key->n, public_key->n); + BIO_free (bio); + + return valid; +} diff --git a/src/signer.h b/src/signer.h index 92745ff2..6fd17033 100644 --- a/src/signer.h +++ b/src/signer.h @@ -38,9 +38,11 @@ namespace dcp { /** @class Signer * @brief A class which can sign XML files. */ -class Signer : public boost::noncopyable +class Signer { public: + Signer (boost::filesystem::path openssl); + /** @param c Certificate chain to sign with. * @param k Key to sign with as a PEM-format string. */ @@ -55,6 +57,20 @@ public: CertificateChain const & certificates () const { return _certificates; } + + CertificateChain& certificates () { + return _certificates; + } + + std::string key () const { + return _key; + } + + void set_key (std::string k) { + _key = k; + } + + bool valid () const; private: diff --git a/src/wscript b/src/wscript index e9b3c955..87059b36 100644 --- a/src/wscript +++ b/src/wscript @@ -14,6 +14,7 @@ def build(bld): obj.source = """ argb_frame.cc asset.cc + certificate_chain.cc certificates.cc colour_matrix.cc content.cc @@ -49,7 +50,6 @@ def build(bld): reel_subtitle_asset.cc rgb_xyz.cc signer.cc - signer_chain.cc sound_mxf.cc sound_mxf_writer.cc sound_frame.cc @@ -68,6 +68,7 @@ def build(bld): headers = """ asset.h + certificate_chain.h certificates.h colour_matrix.h cpl.h @@ -103,7 +104,6 @@ def build(bld): ref.h argb_frame.h signer.h - signer_chain.h sound_frame.h sound_mxf.h sound_mxf_writer.h |
