wip check-signatures
authorCarl Hetherington <cth@carlh.net>
Mon, 7 Mar 2022 21:00:06 +0000 (22:00 +0100)
committerCarl Hetherington <cth@carlh.net>
Mon, 7 Mar 2022 21:00:06 +0000 (22:00 +0100)
src/verify.cc
src/verify.h

index a0c329d0cdb862050a74dfe54667ce211a910be8..410d32e8d9edcf98583b4e6b1f75d8a0fbe55633 100644 (file)
@@ -76,6 +76,7 @@
 #include <xercesc/parsers/XercesDOMParser.hpp>
 #include <xercesc/sax/HandlerBase.hpp>
 #include <xercesc/util/PlatformUtils.hpp>
+#include <xmlsec/xmldsig.h>
 #include <boost/algorithm/string.hpp>
 #include <iostream>
 #include <map>
@@ -1256,6 +1257,33 @@ pkl_has_encrypted_assets (shared_ptr<DCP> dcp, shared_ptr<PKL> pkl)
 }
 
 
+static void
+verify_signature (boost::filesystem::path xml_file, vector<VerificationNote>& notes)
+{
+       cxml::Document doc;
+       doc.read_file (xml_file);
+
+       auto signature = doc.optional_node_child("Signature");
+       if (!signature) {
+               return;
+       }
+
+       auto context = xmlSecDSigCtxCreate (0);
+       if (context == nullptr) {
+               throw MiscError ("could not create signature context");
+       }
+
+       context->signKey = xmlSecCryptoAppKeyLoadMemory(
+               reinterpret_cast<const unsigned char *>(_key->c_str()), _key->size(), xmlSecKeyDataFormatPem, 0, 0, 0
+               );
+
+       auto r = xmlSecDSigCtxVerify (context, signature->node()->cobj());
+       if (r < 0) {
+               notes.push_back (dcp::VerificationNote(VerificationNote::Type::ERROR, VerificationNote::Code::INVALID_SIGNATURE, xml_file));
+       }
+}
+
+
 vector<VerificationNote>
 dcp::verify (
        vector<boost::filesystem::path> directories,
@@ -1306,6 +1334,7 @@ dcp::verify (
                for (auto cpl: dcp->cpls()) {
                        stage ("Checking CPL", cpl->file());
                        validate_xml (cpl->file().get(), *xsd_dtd_directory, notes);
+                       verify_signature (cpl->file().get(), notes);
 
                        if (cpl->any_encrypted() && !cpl->all_encrypted()) {
                                notes.push_back ({VerificationNote::Type::BV21_ERROR, VerificationNote::Code::PARTIALLY_ENCRYPTED});
@@ -1553,6 +1582,7 @@ dcp::verify (
                for (auto pkl: dcp->pkls()) {
                        stage ("Checking PKL", pkl->file());
                        validate_xml (pkl->file().get(), *xsd_dtd_directory, notes);
+                       verify_signature (pkl->file().get(), notes);
                        if (pkl_has_encrypted_assets(dcp, pkl)) {
                                cxml::Document doc ("PackingList");
                                doc.read_file (pkl->file().get());
@@ -1763,6 +1793,8 @@ dcp::note_to_string (VerificationNote note)
                return "Some closed <Text> or <Image> nodes have different vertical alignments within a <Subtitle>.";
        case VerificationNote::Code::INCORRECT_CLOSED_CAPTION_ORDERING:
                return "Some closed captions are not listed in the order of their vertical position.";
+       case VerificationNote::Code::INVALID_SIGNATURE:
+               return "An XML file has an invalid signature.";
        }
 
        return "";
@@ -1815,3 +1847,4 @@ dcp::operator<< (std::ostream& s, dcp::VerificationNote const& note)
        return s;
 }
 
+
index 424b29e7ca983387800116931f391fa2b301427a..1fd9f5f45b435bd63c97347fc0f09ac366786cb8 100644 (file)
@@ -392,6 +392,10 @@ public:
                MISMATCHED_CLOSED_CAPTION_VALIGN,
                /** Some closed captions are not listed in the XML in the order of their vertical position */
                INCORRECT_CLOSED_CAPTION_ORDERING,
+               /** An XML file has an invalid signature
+                *  file contains the XML filename
+                */
+               INVALID_SIGNATURE,
        };
 
        VerificationNote (Type type, Code code)