A few encryption-related fixes and comments.
authorCarl Hetherington <cth@carlh.net>
Wed, 18 Sep 2013 17:46:58 +0000 (18:46 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 18 Sep 2013 17:46:58 +0000 (18:46 +0100)
src/cpl.cc
src/cpl.h
src/crypt_chain.cc
src/encryption.h
src/exceptions.h
src/util.cc
src/util.h
test/encryption_test.cc
test/tests.cc

index bd29573a03df4bd73efb0470f37f886dda7874bb..d70bee25a45dfa6476b2cd0dd16aff32041e2065 100644 (file)
@@ -347,7 +347,7 @@ CPL::equals (CPL const & other, EqualityOptions opt, boost::function<void (NoteT
 shared_ptr<xmlpp::Document>
 CPL::make_kdm (
        CertificateChain const & certificates,
-       string const & signer_key,
+       boost::filesystem::path signer_key,
        shared_ptr<const Certificate> recipient_cert,
        boost::posix_time::ptime from,
        boost::posix_time::ptime until,
@@ -401,8 +401,8 @@ CPL::make_kdm (
                                kdm_required_extensions->add_child("CompositionPlaylistId")->add_child_text("urn:uuid:" + _id);
                                kdm_required_extensions->add_child("ContentTitleText")->add_child_text(_name);
                                kdm_required_extensions->add_child("ContentAuthenticator")->add_child_text(certificates.leaf()->thumbprint());
-                               kdm_required_extensions->add_child("ContentKeysNotValidBefore")->add_child_text("XXX");
-                               kdm_required_extensions->add_child("ContentKeysNotValidAfter")->add_child_text("XXX");
+                               kdm_required_extensions->add_child("ContentKeysNotValidBefore")->add_child_text(ptime_to_string (from));
+                               kdm_required_extensions->add_child("ContentKeysNotValidAfter")->add_child_text(ptime_to_string (until));
 
                                {
                                        xmlpp::Element* authorized_device_info = kdm_required_extensions->add_child("AuthorizedDeviceInfo");
index d3b4e54437b10ae8805058cc96caad2adcbe9b7d..aa07036d3e93c66017a17b9fcbea4aa23a6824a7 100644 (file)
--- a/src/cpl.h
+++ b/src/cpl.h
@@ -25,6 +25,7 @@
 #include <boost/function.hpp>
 #include <boost/date_time/posix_time/posix_time.hpp>
 #include <boost/optional.hpp>
+#include <boost/filesystem.hpp>
 #include <libxml++/libxml++.h>
 #include "types.h"
 #include "certificates.h"
@@ -96,7 +97,7 @@ public:
 
        /** Make a KDM for this CPL.
         *  @param certificates
-        *  @param signer_key
+        *  @param signer_key Filename of private key to sign the KDM with.
         *  @param recipient_cert The certificate of the projector that this KDM is targeted at.  This will contain the
         *  projector's public key (P) which is used to encrypt the content keys.
         *  @param from Time that the KDM should be valid from.
@@ -105,7 +106,7 @@ public:
         */
        boost::shared_ptr<xmlpp::Document> make_kdm (
                CertificateChain const & certificates,
-               std::string const & signer_key,
+               boost::filesystem::path signer_key,
                boost::shared_ptr<const Certificate> recipient_cert,
                boost::posix_time::ptime from,
                boost::posix_time::ptime until,
index d495c970400eb17ab5f949f26d2743760a93a7d2..2737f12cf5b36fb91170fa6d8f2af727ac2ba9e7 100644 (file)
@@ -47,6 +47,8 @@ static void command (char const * c)
 void
 libdcp::make_crypt_chain (boost::filesystem::path directory)
 {
+       boost::filesystem::path const cwd = boost::filesystem::current_path ();
+
        boost::filesystem::current_path (directory);
        command ("openssl genrsa -out ca.key 2048");
 
@@ -161,4 +163,6 @@ libdcp::make_crypt_chain (boost::filesystem::path directory)
        }
 
        command ("openssl x509 -req -sha256 -days 3648 -CA intermediate.signed.pem -CAkey intermediate.key -set_serial 7 -in leaf.csr -extfile leaf.cnf -extensions v3_ca -out leaf.signed.pem");
+
+       boost::filesystem::current_path (cwd);
 }
index f143f0df0489c77ff3eadc623383d339dc11054f..b6d79b19d063d4fbf3486e6844dd8fd1abdb0810 100644 (file)
@@ -17,7 +17,7 @@
 
 */
 
-#include <string>
+#include <boost/filesystem.hpp>
 #include "certificates.h"
 
 namespace libdcp {
@@ -25,13 +25,14 @@ namespace libdcp {
 class Encryption
 {
 public:
-       Encryption (CertificateChain c, std::string const & k)
+       Encryption (CertificateChain c, boost::filesystem::path k)
                : certificates (c)
                , signer_key (k)
        {}
 
        CertificateChain certificates;
-       std::string signer_key;
+       /** Filename of signer key */
+       boost::filesystem::path signer_key;
 };
 
 }
index 4c53a66dd1664c10d1dc1352ac99306f71cbcfdd..de744812dcfd25dbb93bd5dc06ffaa77c381e898 100644 (file)
@@ -20,6 +20,8 @@
 #ifndef LIBDCP_EXCEPTIONS_H
 #define LIBDCP_EXCEPTIONS_H
 
+#include <boost/filesystem.hpp>
+
 /** @file  src/exceptions.h
  *  @brief Exceptions thrown by libdcp.
  */
@@ -31,7 +33,7 @@ namespace libdcp
 class FileError : public std::exception
 {
 public:
-       FileError (std::string const & message, std::string const & filename)
+       FileError (std::string const & message, boost::filesystem::path filename)
                : _message (message)
                , _filename (filename)
        {}
@@ -44,7 +46,7 @@ public:
        }
        
        /** @return filename of file that was involved */
-       std::string filename () const {
+       boost::filesystem::path filename () const {
                return _filename;
        }
 
@@ -52,14 +54,14 @@ private:
        /** error message */
        std::string _message;
        /** filename of file that was involved */
-       std::string _filename;
+       boost::filesystem::path _filename;
 };
 
 /** @brief An exception related to an MXF file */
 class MXFFileError : public FileError
 {
 public:
-       MXFFileError (std::string const & message, std::string const & filename)
+       MXFFileError (std::string const & message, boost::filesystem::path filename)
                : FileError (message, filename)
        {}
 };
index 4035ffd1840806f6d82eb7724d1f37dc15167b8f..f2728a38d25bbc042025e4e23f6def45e505d752 100644 (file)
@@ -239,13 +239,36 @@ libdcp::init ()
        if (xmlSecInit() < 0) {
                throw MiscError ("could not initialise xmlsec");
        }
+
+#ifdef XMLSEC_CRYPTO_DYNAMIC_LOADING
+       if (xmlSecCryptoDLLoadLibrary(BAD_CAST XMLSEC_CRYPTO) < 0) {
+               throw MiscError ("unable to load default xmlsec-crypto library");
+       }
+#endif 
+
+       if (xmlSecCryptoAppInit(0) < 0) {
+               throw MiscError ("could not initialise crypto");
+       }
+
+       if (xmlSecCryptoInit() < 0) {
+               throw MiscError ("could not initialise xmlsec-crypto");
+       }
 }
 
+/** Sign an XML node.  This function takes a certificate chain (to prove that the sender is bona fide) and
+ *  a private key with which to sign the node.
+ *
+ *  @param parent Node to sign.
+ *  @param certificates Certificate chain for the signer.
+ *  @param signer_key Filename of the private key of the signer.
+ *  @param ns Namespace to use for the signature XML nodes.
+ */
 void
-libdcp::add_signature_value (xmlpp::Element* parent, CertificateChain const & certificates, string const & signer_key, string const & ns)
+libdcp::add_signature_value (xmlpp::Element* parent, CertificateChain const & certificates, boost::filesystem::path signer_key, string const & ns)
 {
        parent->add_child("SignatureValue", ns);
-       
+
+       /* Add the certificate chain to a KeyInfo child node of parent */
        xmlpp::Element* key_info = parent->add_child("KeyInfo", ns);
        list<shared_ptr<Certificate> > c = certificates.leaf_to_root ();
        for (list<shared_ptr<Certificate> >::iterator i = c.begin(); i != c.end(); ++i) {
@@ -260,23 +283,26 @@ libdcp::add_signature_value (xmlpp::Element* parent, CertificateChain const & ce
                data->add_child("X509Certificate", ns)->add_child_text((*i)->certificate());
        }
 
-       xmlSecKeysMngrPtr keys_manager = xmlSecKeysMngrCreate();
-       if (!keys_manager) {
-               throw MiscError ("could not create keys manager");
+       xmlSecDSigCtxPtr signature_context = xmlSecDSigCtxCreate (0);
+       if (signature_context == 0) {
+               throw MiscError ("could not create signature context");
        }
-       
-       xmlSecDSigCtx signature_context;
-       
-       if (xmlSecDSigCtxInitialize (&signature_context, keys_manager) < 0) {
-               throw MiscError ("could not initialise XMLSEC context");
+
+       signature_context->signKey = xmlSecCryptoAppKeyLoad (signer_key.c_str(), xmlSecKeyDataFormatPem, 0, 0, 0);
+       if (signature_context->signKey == 0) {
+               throw FileError ("could not load private key file", signer_key);
        }
-       
-       if (xmlSecDSigCtxSign (&signature_context, parent->cobj()) < 0) {
+
+       /* XXX: set key name to the file name: is this right? */
+       if (xmlSecKeySetName (signature_context->signKey, reinterpret_cast<const xmlChar *> (signer_key.c_str())) < 0) {
+               throw MiscError ("could not set key name");
+       }
+
+       if (xmlSecDSigCtxSign (signature_context, parent->cobj ()) < 0) {
                throw MiscError ("could not sign");
        }
-       
-       xmlSecDSigCtxFinalize (&signature_context);
-       xmlSecKeysMngrDestroy (keys_manager);
+
+       xmlSecDSigCtxDestroy (signature_context);
 }
 
 
@@ -298,8 +324,9 @@ libdcp::add_signer (xmlpp::Element* parent, CertificateChain const & certificate
        }
 }
 
+/** @param signer_key Filename of private key to sign with */
 void
-libdcp::sign (xmlpp::Element* parent, CertificateChain const & certificates, string const & signer_key, bool interop)
+libdcp::sign (xmlpp::Element* parent, CertificateChain const & certificates, boost::filesystem::path signer_key, bool interop)
 {
        add_signer (parent, certificates, "dsig");
 
@@ -412,3 +439,10 @@ libdcp::utc_offset_to_string (int b)
        o << setw(2) << setfill('0') << hours << ":" << setw(2) << setfill('0') << minutes;
        return o.str ();
 }
+
+string
+libdcp::ptime_to_string (boost::posix_time::ptime t)
+{
+       struct tm t_tm = boost::posix_time::to_tm (t);
+       return tm_to_string (&t_tm);
+}
index 8001559309ca3dbdd4fdf6a5970d1f089a9d010c..4f5901980739c4461e6f32f1165a0c81cae27b84 100644 (file)
@@ -28,6 +28,8 @@
 #include <stdint.h>
 #include <boost/shared_ptr.hpp>
 #include <boost/function.hpp>
+#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/filesystem.hpp>
 #include <openjpeg.h>
 #include "types.h"
 
@@ -69,14 +71,15 @@ extern boost::shared_ptr<XYZFrame> decompress_j2k (uint8_t* data, int64_t size,
 
 extern void init ();
 
-extern void sign (xmlpp::Element* parent, CertificateChain const & certificates, std::string const & signer_key, bool interop);
-extern void add_signature_value (xmlpp::Element* parent, CertificateChain const & certificates, std::string const & signer_key, std::string const & ns);
+extern void sign (xmlpp::Element* parent, CertificateChain const & certificates, boost::filesystem::path signer_key, bool interop);
+extern void add_signature_value (xmlpp::Element* parent, CertificateChain const & certificates, boost::filesystem::path signer_key, std::string const & ns);
 extern void add_signer (xmlpp::Element* parent, CertificateChain const & certificates, std::string const & ns);
 
 extern int base64_decode (std::string const & in, unsigned char* out, int out_length);
 
 extern std::string tm_to_string (struct tm *);
 extern std::string utc_offset_to_string (int);
+extern std::string ptime_to_string (boost::posix_time::ptime);
        
 }
 
index eb32afaa8362b43a2ef91040e00dfecd0428c573..0df798f23e07e935304c899b233bd73a69fa06e7 100644 (file)
@@ -17,7 +17,7 @@
 
 */
 
-/* Load a certificate chain from build/test/data/*.pem and then build
+/* Load a certificate chain from build/test/data/ *.pem and then build
    an encrypted DCP and a KDM using it.
 */
 BOOST_AUTO_TEST_CASE (encryption)
@@ -39,9 +39,9 @@ BOOST_AUTO_TEST_CASE (encryption)
        libdcp::DCP d ("build/test/DCP/bar");
 
        libdcp::CertificateChain chain;
-       chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate ("build/test/data/ca.self-signed.pem")));
-       chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate ("build/test/data/intermediate.signed.pem")));
-       chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate ("build/test/data/leaf.signed.pem")));
+       chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate ("build/test/crypt/ca.self-signed.pem")));
+       chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate ("build/test/crypt/intermediate.signed.pem")));
+       chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate ("build/test/crypt/leaf.signed.pem")));
 
        shared_ptr<libdcp::Encryption> crypt (
                new libdcp::Encryption (
@@ -61,6 +61,7 @@ BOOST_AUTO_TEST_CASE (encryption)
                                                         24,
                                                         true,
                                                         libdcp::Size (32, 32),
+                                                        false,
                                                         mxf_metadata
                                                         ));
 
@@ -73,13 +74,14 @@ BOOST_AUTO_TEST_CASE (encryption)
                                                   24,
                                                   2,
                                                   true,
+                                                  false,
                                                   mxf_metadata
                                                   ));
        
        cpl->add_reel (shared_ptr<libdcp::Reel> (new libdcp::Reel (mp, ms, shared_ptr<libdcp::SubtitleAsset> ())));
        d.add_cpl (cpl);
 
-       d.write_xml (xml_metadata, crypt);
+       d.write_xml (false, xml_metadata, crypt);
 
        shared_ptr<xmlpp::Document> kdm = cpl->make_kdm (
                crypt->certificates,
@@ -87,6 +89,7 @@ BOOST_AUTO_TEST_CASE (encryption)
                crypt->certificates.leaf(),
                boost::posix_time::time_from_string ("2013-01-01 00:00:00"),
                boost::posix_time::time_from_string ("2013-01-08 00:00:00"),
+               false,
                mxf_metadata,
                xml_metadata
                );
index 2543d025073a6a4d8beea1140820d1a10aa990c9..42198abdb5ffd943cccae3abc69d360c7bc99852 100644 (file)
@@ -84,11 +84,11 @@ static string test_corpus = "../libdcp-test";
 #include "recovery_test.cc"
 #include "certificates_test.cc"
 
-//BOOST_AUTO_TEST_CASE (crypt_chain)
-//{
-//     boost::filesystem::remove_all ("build/test/crypt");
-//     boost::filesystem::create_directory ("build/test/crypt");
-//     libdcp::make_crypt_chain ("build/test/crypt");
-//}
+BOOST_AUTO_TEST_CASE (crypt_chain)
+{
+       boost::filesystem::remove_all ("build/test/crypt");
+       boost::filesystem::create_directory ("build/test/crypt");
+       libdcp::make_crypt_chain ("build/test/crypt");
+}
 
-//#include "encryption_test.cc"
+#include "encryption_test.cc"