X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fencrypted_kdm.cc;h=23052f8a2c438bd358acb3e0b8f63628a68c5b30;hb=201b6fdf572c04424d870ac4d07d1d1a8725b24c;hp=b6a992fb659f58c3b6634d04fe1bfea0d1aa6322;hpb=e758024e07b64098dfdb67dcd54c828e374ca7b6;p=libdcp.git diff --git a/src/encrypted_kdm.cc b/src/encrypted_kdm.cc index b6a992fb..23052f8a 100644 --- a/src/encrypted_kdm.cc +++ b/src/encrypted_kdm.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2016 Carl Hetherington + Copyright (C) 2013-2018 Carl Hetherington This file is part of libdcp. @@ -34,12 +34,16 @@ #include "encrypted_kdm.h" #include "util.h" #include "certificate_chain.h" +#include "exceptions.h" +#include "compose.hpp" #include #include #include #include +#include #include #include +#include using std::list; using std::vector; @@ -48,6 +52,7 @@ using std::map; using std::pair; using boost::shared_ptr; using boost::optional; +using boost::starts_with; using namespace dcp; namespace dcp { @@ -380,7 +385,25 @@ public: , authorized_device_info (node->node_child ("AuthorizedDeviceInfo")) , key_id_list (node->node_child ("KeyIdList")) { - + disable_forensic_marking_picture = false; + disable_forensic_marking_audio = optional(); + if (node->optional_node_child("ForensicMarkFlagList")) { + BOOST_FOREACH (cxml::ConstNodePtr i, node->node_child("ForensicMarkFlagList")->node_children("ForensicMarkFlag")) { + if (i->content() == picture_disable) { + disable_forensic_marking_picture = true; + } else if (starts_with(i->content(), audio_disable)) { + disable_forensic_marking_audio = 0; + string const above = audio_disable + "-above-channel-"; + if (starts_with(i->content(), above)) { + string above_number = i->content().substr(above.length()); + if (above_number == "") { + throw KDMFormatError("Badly-formatted ForensicMarkFlag"); + } + disable_forensic_marking_audio = atoi(above_number.c_str()); + } + } + } + } } void as_xml (xmlpp::Element* node) const @@ -400,9 +423,19 @@ public: } key_id_list.as_xml (node->add_child ("KeyIdList")); - xmlpp::Element* forensic_mark_flag_list = node->add_child ("ForensicMarkFlagList"); - forensic_mark_flag_list->add_child("ForensicMarkFlag")->add_child_text ("http://www.smpte-ra.org/430-1/2006/KDM#mrkflg-picture-disable"); - forensic_mark_flag_list->add_child("ForensicMarkFlag")->add_child_text ("http://www.smpte-ra.org/430-1/2006/KDM#mrkflg-audio-disable"); + if (disable_forensic_marking_picture || disable_forensic_marking_audio) { + xmlpp::Element* forensic_mark_flag_list = node->add_child ("ForensicMarkFlagList"); + if (disable_forensic_marking_picture) { + forensic_mark_flag_list->add_child("ForensicMarkFlag")->add_child_text(picture_disable); + } + if (disable_forensic_marking_audio) { + string mrkflg = audio_disable; + if (*disable_forensic_marking_audio > 0) { + mrkflg += String::compose ("-above-channel-%1", *disable_forensic_marking_audio); + } + forensic_mark_flag_list->add_child("ForensicMarkFlag")->add_child_text (mrkflg); + } + } } Recipient recipient; @@ -411,10 +444,19 @@ public: string content_title_text; LocalTime not_valid_before; LocalTime not_valid_after; + bool disable_forensic_marking_picture; + optional disable_forensic_marking_audio; boost::optional authorized_device_info; KeyIdList key_id_list; + +private: + static const string picture_disable; + static const string audio_disable; }; +const string KDMRequiredExtensions::picture_disable = "http://www.smpte-ra.org/430-1/2006/KDM#mrkflg-picture-disable"; +const string KDMRequiredExtensions::audio_disable = "http://www.smpte-ra.org/430-1/2006/KDM#mrkflg-audio-disable"; + class RequiredExtensions { public: @@ -525,21 +567,28 @@ public: EncryptedKDM::EncryptedKDM (string s) { - shared_ptr doc (new cxml::Document ("DCinemaSecurityMessage")); - doc->read_string (s); - _data = new data::EncryptedKDMData (doc); + try { + shared_ptr doc (new cxml::Document ("DCinemaSecurityMessage")); + doc->read_string (s); + _data = new data::EncryptedKDMData (doc); + } catch (xmlpp::parse_error& e) { + throw KDMFormatError (e.what ()); + } } +/** @param trusted_devices Trusted device thumbprints */ EncryptedKDM::EncryptedKDM ( shared_ptr signer, Certificate recipient, - vector trusted_devices, + vector trusted_devices, string cpl_id, string content_title_text, optional annotation_text, LocalTime not_valid_before, LocalTime not_valid_after, Formulation formulation, + bool disable_forensic_marking_picture, + optional disable_forensic_marking_audio, list > key_ids, list keys ) @@ -547,12 +596,13 @@ EncryptedKDM::EncryptedKDM ( { /* Fill our XML-ish description in with the juicy bits that the caller has given */ - /* Our ideas about the KDM types are: + /* Our ideas, based on http://isdcf.com/papers/ISDCF-Doc5-kdm-certs.pdf, about the KDM types are: * - * Type Trusted-device thumb ContentAuthenticator - * MODIFIED_TRANSITIONAL_1 assume-trust No - * DCI_ANY assume-trust Yes - * DCI_SPECIFIC as specified Yes + * Type Trusted-device thumb ContentAuthenticator + * MODIFIED_TRANSITIONAL_1 assume-trust No + * MULTIPLE_MODIFIED_TRANSITIONAL_1 as specified No + * DCI_ANY assume-trust Yes + * DCI_SPECIFIC as specified Yes */ data::AuthenticatedPublic& aup = _data->authenticated_public; @@ -571,6 +621,8 @@ EncryptedKDM::EncryptedKDM ( kre.content_title_text = content_title_text; kre.not_valid_before = not_valid_before; kre.not_valid_after = not_valid_after; + kre.disable_forensic_marking_picture = disable_forensic_marking_picture; + kre.disable_forensic_marking_audio = disable_forensic_marking_audio; if (formulation != MODIFIED_TRANSITIONAL_TEST) { kre.authorized_device_info = data::AuthorizedDeviceInfo (); @@ -584,16 +636,25 @@ EncryptedKDM::EncryptedKDM ( if (formulation == MODIFIED_TRANSITIONAL_1 || formulation == DCI_ANY) { /* Use the "assume trust" thumbprint */ kre.authorized_device_info->certificate_thumbprints.push_back ("2jmj7l5rSw0yVb/vlWAYkK/YBwk="); - } else if (formulation == DCI_SPECIFIC) { - /* As I read the standard we should use the recipient - /and/ other trusted device thumbprints here. MJD - reports that this doesn't work with his setup; - a working KDM does not include the recipient's - thumbprint (recipient.thumbprint()). - Waimea uses only the trusted devices here, too. - */ - BOOST_FOREACH (Certificate const & i, trusted_devices) { - kre.authorized_device_info->certificate_thumbprints.push_back (i.thumbprint ()); + } else if (formulation == MULTIPLE_MODIFIED_TRANSITIONAL_1 || formulation == DCI_SPECIFIC) { + if (trusted_devices.empty ()) { + /* Fall back on the "assume trust" thumbprint so we + can generate "modified-transitional-1" KDMs + together with "multiple-modified-transitional-1" + KDMs in one go, and similarly for "dci-any" etc. + */ + kre.authorized_device_info->certificate_thumbprints.push_back ("2jmj7l5rSw0yVb/vlWAYkK/YBwk="); + } else { + /* As I read the standard we should use the + recipient /and/ other trusted device thumbprints + here. MJD reports that this doesn't work with + his setup; a working KDM does not include the + recipient's thumbprint (recipient.thumbprint()). + Waimea uses only the trusted devices here, too. + */ + BOOST_FOREACH (string i, trusted_devices) { + kre.authorized_device_info->certificate_thumbprints.push_back (i); + } } } } @@ -662,6 +723,12 @@ EncryptedKDM::keys () const return _data->authenticated_private.encrypted_key; } +string +EncryptedKDM::id () const +{ + return _data->authenticated_public.message_id; +} + optional EncryptedKDM::annotation_text () const {