summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-01-03 20:41:32 +0000
committerCarl Hetherington <cth@carlh.net>2013-01-03 20:41:32 +0000
commit50b5f8f9df0439d2d8fa9004e0b4af2f3e1eb44c (patch)
tree7fd862d261d406a7f93b8531b01b892feb309c8a
parentaef58f7a1caf6a67c2c0b12ba3a6bc632d890f4e (diff)
Sort-of generates a signed CPL.
-rw-r--r--README6
-rw-r--r--src/dcp.cc54
-rw-r--r--src/dcp.h15
-rw-r--r--src/util.cc26
-rw-r--r--src/util.h2
-rw-r--r--src/wscript2
-rw-r--r--test/tests.cc6
-rw-r--r--test/wscript2
-rw-r--r--wscript3
9 files changed, 105 insertions, 11 deletions
diff --git a/README b/README
index 6fe5521b..deb4b528 100644
--- a/README
+++ b/README
@@ -20,10 +20,12 @@ nasty details of encryption.
== Dependencies
-boost filesystem library
-OpenSSL
+boost filesystem, signals2 and unit testing libraries
+openssl
libsigc++
libxml++
+xmlsec
+openjpeg (1.5.0 or above)
== Documentation
diff --git a/src/dcp.cc b/src/dcp.cc
index bd3cc80b..2a1a156b 100644
--- a/src/dcp.cc
+++ b/src/dcp.cc
@@ -28,6 +28,8 @@
#include <iostream>
#include <boost/filesystem.hpp>
#include <libxml++/libxml++.h>
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/app.h>
#include "dcp.h"
#include "asset.h"
#include "sound_asset.h"
@@ -60,7 +62,7 @@ void
DCP::write_xml () const
{
for (list<shared_ptr<const CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
- (*i)->write_xml (_encrypted, _certificates);
+ (*i)->write_xml (_encrypted, _certificates, _signer_key);
}
string pkl_uuid = make_uuid ();
@@ -424,7 +426,7 @@ CPL::add_reel (shared_ptr<const Reel> reel)
}
void
-CPL::write_xml (bool encrypted, CertificateChain const & certificates) const
+CPL::write_xml (bool encrypted, CertificateChain const & certificates, string const & signer_key) const
{
boost::filesystem::path p;
p /= _directory;
@@ -435,6 +437,10 @@ CPL::write_xml (bool encrypted, CertificateChain const & certificates) const
xmlpp::Document doc;
xmlpp::Element* cpl = doc.create_root_node("CompositionPlaylist", "http://www.smpte-ra.org/schemas/429-7/2006/CPL");
+ if (encrypted) {
+ cpl->set_namespace_declaration ("http://www.w3.org/2000/09/xmldsig#", "dsig");
+ }
+
cpl->add_child("Id")->add_child_text ("urn:uuid:" + _uuid);
cpl->add_child("AnnotationText")->add_child_text (_name);
cpl->add_child("IssueDate")->add_child_text (Metadata::instance()->issue_date);
@@ -474,12 +480,13 @@ CPL::write_xml (bool encrypted, CertificateChain const & certificates) const
}
xmlpp::Element* signature = cpl->add_child("Signature", "dsig");
+
{
xmlpp::Element* signed_info = signature->add_child ("SignedInfo", "dsig");
signed_info->add_child("CanonicalizationMethod", "dsig")->set_attribute ("Algorithm", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315");
signed_info->add_child("SignatureMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
{
- xmlpp::Element* reference = signature->add_child("Reference", "dsig");
+ xmlpp::Element* reference = signed_info->add_child("Reference", "dsig");
reference->set_attribute ("URI", "");
{
xmlpp::Element* transforms = reference->add_child("Transforms", "dsig");
@@ -488,21 +495,56 @@ CPL::write_xml (bool encrypted, CertificateChain const & certificates) const
);
}
reference->add_child("DigestMethod", "dsig")->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#sha1");
+ /* This will be filled in by the signing later */
+ reference->add_child("DigestValue", "dsig");
}
}
+ signature->add_child("SignatureValue", "dsig");
+
+ xmlpp::Element* key_info = signature->add_child("KeyInfo", "dsig");
list<shared_ptr<Certificate> > c = certificates.leaf_to_root ();
for (list<shared_ptr<Certificate> >::iterator i = c.begin(); i != c.end(); ++i) {
- xmlpp::Element* data = signature->add_child("X509Data", "dsig");
+ xmlpp::Element* data = key_info->add_child("X509Data", "dsig");
{
- xmlpp::Element* serial = data->add_child("X509IssuerSerial", "data");
+ xmlpp::Element* serial = data->add_child("X509IssuerSerial", "dsig");
serial->add_child("X509IssuerName", "dsig")->add_child_text(
Certificate::name_for_xml ((*i)->issuer())
);
serial->add_child("X509SerialNumber", "dsig")->add_child_text((*i)->serial());
- serial->add_child("X509Certificate", "dsig")->add_child_text("XXX");
}
}
+
+ xmlSecKeysMngrPtr keys_manager = xmlSecKeysMngrCreate();
+ if (!keys_manager) {
+ throw MiscError ("could not create keys manager");
+ }
+ if (xmlSecCryptoAppDefaultKeysMngrInit (keys_manager) < 0) {
+ throw MiscError ("could not initialise keys manager");
+ }
+
+ xmlSecKeyPtr const key = xmlSecCryptoAppKeyLoad (signer_key.c_str(), xmlSecKeyDataFormatPem, 0, 0, 0);
+ if (key == 0) {
+ throw MiscError ("could not load signer key");
+ }
+
+ if (xmlSecCryptoAppDefaultKeysMngrAdoptKey (keys_manager, key) < 0) {
+ xmlSecKeyDestroy (key);
+ throw MiscError ("could not use signer key");
+ }
+
+ xmlSecDSigCtx signature_context;
+
+ if (xmlSecDSigCtxInitialize (&signature_context, keys_manager) < 0) {
+ throw MiscError ("could not initialise XMLSEC context");
+ }
+
+ if (xmlSecDSigCtxSign (&signature_context, signature->cobj()) < 0) {
+ throw MiscError ("could not sign CPL");
+ }
+
+ xmlSecDSigCtxFinalize (&signature_context);
+ xmlSecKeysMngrDestroy (keys_manager);
}
doc.write_to_file_formatted (p.string(), "UTF-8");
diff --git a/src/dcp.h b/src/dcp.h
index ca011c36..e2e2314f 100644
--- a/src/dcp.h
+++ b/src/dcp.h
@@ -86,7 +86,7 @@ public:
bool equals (CPL const & other, EqualityOptions options, std::list<std::string>& notes) const;
- void write_xml (bool, CertificateChain const &) const;
+ void write_xml (bool, CertificateChain const &, std::string const &) const;
void write_to_assetmap (std::ostream& s) const;
void write_to_pkl (std::ostream& s) const;
@@ -151,6 +151,18 @@ public:
return _cpls;
}
+ void set_encrypted (bool e) {
+ _encrypted = e;
+ }
+
+ void set_certificates (CertificateChain const & c) {
+ _certificates = c;
+ }
+
+ void set_signer_key (std::string const & s) {
+ _signer_key = s;
+ }
+
/** Emitted with a parameter between 0 and 1 to indicate progress
* for long jobs.
*/
@@ -186,6 +198,7 @@ private:
bool _encrypted;
CertificateChain _certificates;
+ std::string _signer_key;
};
}
diff --git a/src/util.cc b/src/util.cc
index 2b3a6c8d..323fb1e4 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -27,6 +27,9 @@
#include <iomanip>
#include <boost/filesystem.hpp>
#include <openssl/sha.h>
+#include <xmlsec/xmldsig.h>
+#include <xmlsec/dl.h>
+#include <xmlsec/app.h>
#include "KM_util.h"
#include "KM_fileio.h"
#include "AS_DCP.h"
@@ -37,6 +40,7 @@
#include "lut.h"
using std::string;
+using std::cout;
using std::stringstream;
using std::min;
using std::max;
@@ -267,3 +271,25 @@ libdcp::empty_or_white_space (string s)
return true;
}
+
+void
+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 library");
+ }
+
+ if (xmlSecCryptoInit() < 0) {
+ throw MiscError ("could not initialise xmlsec-crypto");
+ }
+}
diff --git a/src/util.h b/src/util.h
index 7056db6a..6426eb8d 100644
--- a/src/util.h
+++ b/src/util.h
@@ -53,4 +53,6 @@ extern bool empty_or_white_space (std::string s);
extern opj_image_t* decompress_j2k (uint8_t* data, int64_t size, int reduce);
extern boost::shared_ptr<ARGBFrame> xyz_to_rgb (opj_image_t* xyz_frame);
+extern void init ();
+
}
diff --git a/src/wscript b/src/wscript
index 56a99063..efb31d50 100644
--- a/src/wscript
+++ b/src/wscript
@@ -7,7 +7,7 @@ def build(bld):
obj.name = 'libdcp'
obj.target = 'dcp'
obj.export_includes = ['.']
- obj.uselib = 'BOOST_FILESYSTEM BOOST_SIGNALS2 OPENSSL SIGC++ LIBXML++ OPENJPEG'
+ obj.uselib = 'BOOST_FILESYSTEM BOOST_SIGNALS2 OPENSSL SIGC++ LIBXML++ OPENJPEG XMLSEC1'
obj.use = 'libkumu-libdcp libasdcp-libdcp'
obj.source = """
asset.cc
diff --git a/test/tests.cc b/test/tests.cc
index 71796f72..d27b2ea4 100644
--- a/test/tests.cc
+++ b/test/tests.cc
@@ -56,6 +56,8 @@ wav (libdcp::Channel)
BOOST_AUTO_TEST_CASE (dcp_test)
{
+ libdcp::init ();
+
Kumu::libdcp_test = true;
libdcp::Metadata* t = libdcp::Metadata::instance ();
@@ -598,7 +600,11 @@ BOOST_AUTO_TEST_CASE (encryption)
boost::filesystem::remove_all ("build/test/bar");
boost::filesystem::create_directories ("build/test/bar");
libdcp::DCP d ("build/test/bar");
+ d.set_encrypted (true);
+ d.set_certificates (libdcp::CertificateChain ("test/data/certificate_chain"));
+ d.set_signer_key ("test/data/signer.key");
shared_ptr<libdcp::CPL> cpl (new libdcp::CPL ("build/test/bar", "A Test DCP", libdcp::FEATURE, 24, 24));
+
shared_ptr<libdcp::MonoPictureAsset> mp (new libdcp::MonoPictureAsset (
j2c,
diff --git a/test/wscript b/test/wscript
index 43ca7d73..d22875e9 100644
--- a/test/wscript
+++ b/test/wscript
@@ -18,7 +18,7 @@ def configure(conf):
def build(bld):
obj = bld(features = 'cxx cxxprogram')
obj.name = 'tests'
- obj.uselib = 'BOOST_TEST OPENJPEG'
+ obj.uselib = 'BOOST_TEST OPENJPEG XMLSEC1'
obj.use = 'libdcp'
obj.source = 'tests.cc'
obj.target = 'tests'
diff --git a/wscript b/wscript
index e3d209ae..c119367a 100644
--- a/wscript
+++ b/wscript
@@ -28,6 +28,9 @@ def configure(conf):
conf.check_cfg(package = 'openssl', args = '--cflags --libs', uselib_store = 'OPENSSL', mandatory = True)
conf.check_cfg(package = 'libxml++-2.6', args = '--cflags --libs', uselib_store = 'LIBXML++', mandatory = True)
+ conf.check_cfg(package = 'xmlsec1', args = '--cflags --libs', uselib_store = 'XMLSEC1', mandatory = True)
+ # Remove erroneous escaping of quotes from xmlsec1 defines
+ conf.env.DEFINES_XMLSEC1 = [f.replace('\\', '') for f in conf.env.DEFINES_XMLSEC1]
openjpeg_fragment = """
#include <stdio.h>\n