From bb6c2aef9befb77bf14775abfedf8a2c9b7f8d53 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 3 Jan 2013 22:00:04 +0000 Subject: Write PKL using libxml++ and sign them. --- src/asset.cc | 17 ++--- src/asset.h | 6 +- src/dcp.cc | 229 +++++++++++++++++++++++++++++++---------------------------- src/dcp.h | 6 +- 4 files changed, 137 insertions(+), 121 deletions(-) (limited to 'src') diff --git a/src/asset.cc b/src/asset.cc index 5ecc2e9f..ac8f8b8e 100644 --- a/src/asset.cc +++ b/src/asset.cc @@ -24,6 +24,8 @@ #include #include #include +#include +#include #include "AS_DCP.h" #include "KM_util.h" #include "asset.h" @@ -45,15 +47,14 @@ Asset::Asset (string directory, string file_name) } void -Asset::write_to_pkl (ostream& s) const +Asset::write_to_pkl (xmlpp::Element* p) const { - s << " \n" - << " urn:uuid:" << _uuid << "\n" - << " " << _file_name << "\n" - << " " << digest() << "\n" - << " " << filesystem::file_size(path()) << "\n" - << " application/mxf\n" - << " \n"; + xmlpp::Element* asset = p->add_child("Asset"); + asset->add_child("Id")->add_child_text("urn:uuid:" + _uuid); + asset->add_child("AnnotationText")->add_child_text (_file_name); + asset->add_child("Hash")->add_child_text (digest()); + asset->add_child("Size")->add_child_text (boost::lexical_cast (filesystem::file_size(path()))); + asset->add_child("Type")->add_child_text ("application/mxf"); } void diff --git a/src/asset.h b/src/asset.h index 4a52e819..5436e05c 100644 --- a/src/asset.h +++ b/src/asset.h @@ -60,10 +60,10 @@ public: */ virtual void write_to_cpl (xmlpp::Element* p) const = 0; - /** Write details of the asset to a PKL stream. - * @param s Stream. + /** Write details of the asset to a PKL AssetList node. + * @param p Parent node. */ - void write_to_pkl (std::ostream& s) const; + void write_to_pkl (xmlpp::Element* p) const; /** Write details of the asset to a ASSETMAP stream. * @param s Stream. diff --git a/src/dcp.cc b/src/dcp.cc index aa7bb46a..2ece0eac 100644 --- a/src/dcp.cc +++ b/src/dcp.cc @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -82,29 +83,37 @@ DCP::write_pkl (string pkl_uuid) const stringstream s; s << pkl_uuid << "_pkl.xml"; p /= s.str(); - ofstream pkl (p.string().c_str()); - - pkl << "\n" - << "\n" - << " urn:uuid:" << pkl_uuid << "\n" - /* XXX: this is a bit of a hack */ - << " " << _cpls.front()->name() << "\n" - << " " << Metadata::instance()->issue_date << "\n" - << " " << Metadata::instance()->issuer << "\n" - << " " << Metadata::instance()->creator << "\n" - << " \n"; - list > a = assets (); - for (list >::const_iterator i = a.begin(); i != a.end(); ++i) { - (*i)->write_to_pkl (pkl); + xmlpp::Document doc; + xmlpp::Element* pkl = doc.create_root_node("PackingList", "http://www.smpte-ra.org/schemas/429-8/2007/PKL"); + if (_encrypted) { + pkl->set_namespace_declaration ("http://www.w3.org/2000/09/xmldsig#", "dsig"); } - for (list >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { - (*i)->write_to_pkl (pkl); + pkl->add_child("Id")->add_child_text ("urn:uuid:" + pkl_uuid); + /* XXX: this is a bit of a hack */ + pkl->add_child("AnnotationText")->add_child_text(_cpls.front()->name()); + pkl->add_child("IssueDate")->add_child_text (Metadata::instance()->issue_date); + pkl->add_child("Issuer")->add_child_text (Metadata::instance()->issuer); + pkl->add_child("Creator")->add_child_text (Metadata::instance()->creator); + + { + xmlpp::Element* asset_list = pkl->add_child("AssetList"); + list > a = assets (); + for (list >::const_iterator i = a.begin(); i != a.end(); ++i) { + (*i)->write_to_pkl (asset_list); + } + + for (list >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) { + (*i)->write_to_pkl (asset_list); + } } - pkl << " \n" - << "\n"; + if (_encrypted) { + sign (pkl, _certificates, _signer_key); + } + + doc.write_to_file_formatted (p.string(), "UTF-8"); return p.string (); } @@ -462,111 +471,115 @@ CPL::write_xml (bool encrypted, CertificateChain const & certificates, string co } if (encrypted) { - xmlpp::Element* signer = cpl->add_child("Signer"); - { - xmlpp::Element* data = signer->add_child("X509Data", "dsig"); - { - xmlpp::Element* serial = data->add_child("X509IssuerSerial", "dsig"); - serial->add_child("X509IssuerName", "dsig")->add_child_text ( - Certificate::name_for_xml (certificates.leaf()->issuer()) - ); - serial->add_child("X509SerialNumber", "dsig")->add_child_text ( - certificates.leaf()->serial() - ); - } - data->add_child("X509SubjectName", "dsig")->add_child_text ( - Certificate::name_for_xml (certificates.leaf()->subject()) - ); - } + DCP::sign (cpl, certificates, signer_key); + } - 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 = signed_info->add_child("Reference", "dsig"); - reference->set_attribute ("URI", ""); - { - xmlpp::Element* transforms = reference->add_child("Transforms", "dsig"); - transforms->add_child("Transform", "dsig")->set_attribute ( - "Algorithm", "http://www.w3.org/2000/09/xmldsig#enveloped-signature" - ); - } - 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"); - } - } + doc.write_to_file_formatted (p.string(), "UTF-8"); - signature->add_child("SignatureValue", "dsig"); + _digest = make_digest (p.string (), 0); + _length = boost::filesystem::file_size (p.string ()); +} - xmlpp::Element* key_info = signature->add_child("KeyInfo", "dsig"); - list > c = certificates.leaf_to_root (); - for (list >::iterator i = c.begin(); i != c.end(); ++i) { - xmlpp::Element* data = key_info->add_child("X509Data", "dsig"); +void +DCP::sign (xmlpp::Element* parent, CertificateChain const & certificates, string const & signer_key) +{ + xmlpp::Element* signer = parent->add_child("Signer"); + { + xmlpp::Element* data = signer->add_child("X509Data", "dsig"); + { + xmlpp::Element* serial = data->add_child("X509IssuerSerial", "dsig"); + serial->add_child("X509IssuerName", "dsig")->add_child_text ( + Certificate::name_for_xml (certificates.leaf()->issuer()) + ); + serial->add_child("X509SerialNumber", "dsig")->add_child_text ( + certificates.leaf()->serial() + ); + } + data->add_child("X509SubjectName", "dsig")->add_child_text ( + Certificate::name_for_xml (certificates.leaf()->subject()) + ); + } + + xmlpp::Element* signature = parent->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 = signed_info->add_child("Reference", "dsig"); + reference->set_attribute ("URI", ""); { - xmlpp::Element* serial = data->add_child("X509IssuerSerial", "dsig"); - serial->add_child("X509IssuerName", "dsig")->add_child_text( - Certificate::name_for_xml ((*i)->issuer()) + xmlpp::Element* transforms = reference->add_child("Transforms", "dsig"); + transforms->add_child("Transform", "dsig")->set_attribute ( + "Algorithm", "http://www.w3.org/2000/09/xmldsig#enveloped-signature" ); - serial->add_child("X509SerialNumber", "dsig")->add_child_text((*i)->serial()); } - - data->add_child("X509Certificate", "dsig")->add_child_text((*i)->certificate()); - } - - doc.write_to_file_formatted ("/home/carl/fuckwit.xml", "UTF-8"); - - 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"); + 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"); } - - 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"); + } + + signature->add_child("SignatureValue", "dsig"); + + xmlpp::Element* key_info = signature->add_child("KeyInfo", "dsig"); + list > c = certificates.leaf_to_root (); + for (list >::iterator i = c.begin(); i != c.end(); ++i) { + xmlpp::Element* data = key_info->add_child("X509Data", "dsig"); + + { + 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()); } - - if (xmlSecDSigCtxSign (&signature_context, signature->cobj()) < 0) { - throw MiscError ("could not sign CPL"); + + data->add_child("X509Certificate", "dsig")->add_child_text((*i)->certificate()); + } + + 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"); } - - xmlSecDSigCtxFinalize (&signature_context); - xmlSecKeysMngrDestroy (keys_manager); + + if (xmlSecCryptoAppDefaultKeysMngrAdoptKey (keys_manager, key) < 0) { + xmlSecKeyDestroy (key); + throw MiscError ("could not use signer key"); } - - doc.write_to_file_formatted (p.string(), "UTF-8"); - - _digest = make_digest (p.string (), 0); - _length = boost::filesystem::file_size (p.string ()); + + 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); } void -CPL::write_to_pkl (ostream& s) const +CPL::write_to_pkl (xmlpp::Element* p) const { - s << " \n" - << " urn:uuid:" << _uuid << "\n" - << " " << _digest << "\n" - << " " << _length << "\n" - << " text/xml\n" - << " \n"; + xmlpp::Element* asset = p->add_child("Asset"); + asset->add_child("Id")->add_child_text("urn:uuid:" + _uuid); + asset->add_child("Hash")->add_child_text(_digest); + asset->add_child("Size")->add_child_text(boost::lexical_cast (_length)); + asset->add_child("Type")->add_child_text("text/xml"); } list > diff --git a/src/dcp.h b/src/dcp.h index e2e2314f..0ee4a8fc 100644 --- a/src/dcp.h +++ b/src/dcp.h @@ -32,7 +32,7 @@ #include "certificates.h" namespace xmlpp { - class Node; + class Element; } /** @brief Namespace for everything in libdcp */ @@ -88,7 +88,7 @@ public: 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; + void write_to_pkl (xmlpp::Element* p) const; private: std::string _directory; @@ -168,6 +168,8 @@ public: */ boost::signals2::signal Progress; + static void sign (xmlpp::Element* parent, CertificateChain const & certificates, std::string const & signer_key); + private: /** Write the PKL file. -- cgit v1.2.3