summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2019-01-20 20:26:41 +0000
committerCarl Hetherington <cth@carlh.net>2019-01-24 02:03:05 +0000
commita266fc223ecb7a696fa9dc35422ef0264b1c3c40 (patch)
tree27273528c69e91c7461d9349f9f1467886ddf977
parent49f9ec23d00bec2f284118fed3d48d10a6cc8537 (diff)
Attempt to fix Sony digest validation by indenting the <Signer>
and <Signature> before signing. This is in the belief that, perhaps, the Sony software "reformats" the XML before checking that the signature is correct (or something).
-rw-r--r--src/certificate_chain.cc35
-rw-r--r--src/certificate_chain.h2
-rw-r--r--src/cpl.cc7
-rw-r--r--src/dcp.cc5
-rw-r--r--src/encrypted_kdm.cc2
-rw-r--r--src/pkl.cc2
-rw-r--r--tools/wscript2
7 files changed, 45 insertions, 10 deletions
diff --git a/src/certificate_chain.cc b/src/certificate_chain.cc
index 6b4216b5..ebc3cc7f 100644
--- a/src/certificate_chain.cc
+++ b/src/certificate_chain.cc
@@ -552,6 +552,33 @@ CertificateChain::root_to_leaf () const
throw CertificateChainError ("certificate chain is not consistent");
}
+static string
+spaces (int n)
+{
+ string s = "";
+ for (int i = 0; i < n; ++i) {
+ s += " ";
+ }
+ return s;
+}
+
+static void
+indent (xmlpp::Element* element, int initial)
+{
+ xmlpp::Node* last = 0;
+ BOOST_FOREACH (xmlpp::Node * n, element->get_children()) {
+ xmlpp::Element* e = dynamic_cast<xmlpp::Element*>(n);
+ if (e) {
+ element->add_child_text_before (e, "\n" + spaces(initial + 2));
+ indent (e, initial + 2);
+ last = n;
+ }
+ }
+ if (last) {
+ element->add_child_text (last, "\n" + spaces(initial));
+ }
+}
+
/** Add a &lt;Signer&gt; and &lt;ds:Signature&gt; nodes to an XML node.
* @param parent XML node to add to.
* @param standard INTEROP or SMPTE.
@@ -561,6 +588,7 @@ CertificateChain::sign (xmlpp::Element* parent, Standard standard) const
{
/* <Signer> */
+ parent->add_child_text(" ");
xmlpp::Element* signer = parent->add_child("Signer");
signer->set_namespace_declaration ("http://www.w3.org/2000/09/xmldsig#", "dsig");
xmlpp::Element* data = signer->add_child("X509Data", "dsig");
@@ -569,11 +597,15 @@ CertificateChain::sign (xmlpp::Element* parent, Standard standard) const
serial_element->add_child("X509SerialNumber", "dsig")->add_child_text (leaf().serial());
data->add_child("X509SubjectName", "dsig")->add_child_text (leaf().subject());
+ indent (signer, 2);
+
/* <Signature> */
+ parent->add_child_text("\n ");
xmlpp::Element* signature = parent->add_child("Signature");
signature->set_namespace_declaration ("http://www.w3.org/2000/09/xmldsig#", "dsig");
signature->set_namespace ("dsig");
+ parent->add_child_text("\n");
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");
@@ -608,7 +640,7 @@ CertificateChain::sign (xmlpp::Element* parent, Standard standard) const
* @param ns Namespace to use for the signature XML nodes.
*/
void
-CertificateChain::add_signature_value (xmlpp::Node* parent, string ns) const
+CertificateChain::add_signature_value (xmlpp::Element* parent, string ns) const
{
cxml::Node cp (parent);
xmlpp::Node* key_info = cp.node_child("KeyInfo")->node ();
@@ -639,6 +671,7 @@ CertificateChain::add_signature_value (xmlpp::Node* parent, string ns) const
throw runtime_error ("could not read private key");
}
+ indent (parent, 2);
int const r = xmlSecDSigCtxSign (signature_context, parent->cobj ());
if (r < 0) {
throw MiscError (String::compose ("could not sign (%1)", r));
diff --git a/src/certificate_chain.h b/src/certificate_chain.h
index 365632fe..8b54604d 100644
--- a/src/certificate_chain.h
+++ b/src/certificate_chain.h
@@ -103,7 +103,7 @@ public:
bool private_key_valid () const;
void sign (xmlpp::Element* parent, Standard standard) const;
- void add_signature_value (xmlpp::Node* parent, std::string ns) const;
+ void add_signature_value (xmlpp::Element* parent, std::string ns) const;
boost::optional<std::string> key () const {
return _key;
diff --git a/src/cpl.cc b/src/cpl.cc
index 726d69b7..4a594b5a 100644
--- a/src/cpl.cc
+++ b/src/cpl.cc
@@ -140,6 +140,10 @@ CPL::write_xml (boost::filesystem::path file, Standard standard, shared_ptr<cons
root = doc.create_root_node ("CompositionPlaylist", cpl_smpte_ns);
}
+ if (signer) {
+ root->set_namespace_declaration ("http://www.w3.org/2000/09/xmldsig#", "dsig");
+ }
+
root->add_child("Id")->add_child_text ("urn:uuid:" + _id);
root->add_child("AnnotationText")->add_child_text (_metadata.annotation_text);
root->add_child("IssueDate")->add_child_text (_metadata.issue_date);
@@ -164,8 +168,7 @@ CPL::write_xml (boost::filesystem::path file, Standard standard, shared_ptr<cons
signer->sign (root, standard);
}
- /* This must not be the _formatted version otherwise signature digests will be wrong */
- doc.write_to_file (file.string (), "UTF-8");
+ doc.write_to_file_formatted (file.string(), "UTF-8");
set_file (file);
}
diff --git a/src/dcp.cc b/src/dcp.cc
index 8bf2f02f..5d908530 100644
--- a/src/dcp.cc
+++ b/src/dcp.cc
@@ -348,7 +348,7 @@ DCP::write_volindex (Standard standard) const
}
root->add_child("Index")->add_child_text ("1");
- doc.write_to_file (p.string (), "UTF-8");
+ doc.write_to_file_formatted (p.string (), "UTF-8");
}
void
@@ -417,8 +417,7 @@ DCP::write_assetmap (Standard standard, string pkl_uuid, boost::filesystem::path
i->write_to_assetmap (asset_list, _directory);
}
- /* This must not be the _formatted version otherwise signature digests will be wrong */
- doc.write_to_file (p.string (), "UTF-8");
+ doc.write_to_file_formatted (p.string (), "UTF-8");
}
/** Write all the XML files for this DCP.
diff --git a/src/encrypted_kdm.cc b/src/encrypted_kdm.cc
index 23052f8a..9d581451 100644
--- a/src/encrypted_kdm.cc
+++ b/src/encrypted_kdm.cc
@@ -670,7 +670,7 @@ EncryptedKDM::EncryptedKDM (
xmlpp::Node::NodeList children = doc->get_root_node()->get_children ();
for (xmlpp::Node::NodeList::const_iterator i = children.begin(); i != children.end(); ++i) {
if ((*i)->get_name() == "Signature") {
- signer->add_signature_value (*i, "ds");
+ signer->add_signature_value (dynamic_cast<xmlpp::Element*>(*i), "ds");
}
}
diff --git a/src/pkl.cc b/src/pkl.cc
index 43c7d092..9910b190 100644
--- a/src/pkl.cc
+++ b/src/pkl.cc
@@ -113,7 +113,7 @@ PKL::write (boost::filesystem::path file, shared_ptr<const CertificateChain> sig
signer->sign (pkl, _standard);
}
- doc.write_to_file (file.string(), "UTF-8");
+ doc.write_to_file_formatted (file.string(), "UTF-8");
}
optional<string>
diff --git a/tools/wscript b/tools/wscript
index 73c58f30..98eb0df0 100644
--- a/tools/wscript
+++ b/tools/wscript
@@ -44,7 +44,7 @@ def build(bld):
obj.source = 'dcpinfo.cc common.cc'
obj.target = 'dcpinfo'
- for f in ['dumpsub', 'decryptmxf', 'kdm', 'thumb', 'recover', 'verify']:
+ for f in ['dumpsub', 'decryptmxf', 'kdm', 'thumb', 'recover', 'verify', 'sign']:
obj = bld(features='cxx cxxprogram')
obj.use = ['libdcp%s' % bld.env.API_VERSION]
obj.uselib = 'OPENJPEG CXML OPENMP ASDCPLIB_CTH BOOST_FILESYSTEM LIBXML++ XMLSEC1 OPENSSL'