diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-01-03 20:41:32 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-01-03 20:41:32 +0000 |
| commit | 50b5f8f9df0439d2d8fa9004e0b4af2f3e1eb44c (patch) | |
| tree | 7fd862d261d406a7f93b8531b01b892feb309c8a /src | |
| parent | aef58f7a1caf6a67c2c0b12ba3a6bc632d890f4e (diff) | |
Sort-of generates a signed CPL.
Diffstat (limited to 'src')
| -rw-r--r-- | src/dcp.cc | 54 | ||||
| -rw-r--r-- | src/dcp.h | 15 | ||||
| -rw-r--r-- | src/util.cc | 26 | ||||
| -rw-r--r-- | src/util.h | 2 | ||||
| -rw-r--r-- | src/wscript | 2 |
5 files changed, 91 insertions, 8 deletions
@@ -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"); @@ -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"); + } +} @@ -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 |
