summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/certificates.cc8
-rw-r--r--src/certificates.h1
-rw-r--r--src/dcp.cc4
-rw-r--r--src/dcp.h4
-rw-r--r--src/kdm.cc95
-rw-r--r--src/kdm.h11
-rw-r--r--src/signer.cc2
-rw-r--r--src/sound_asset.h4
-rw-r--r--src/util.cc1
-rw-r--r--src/wscript2
-rw-r--r--src/xml/kdm_smpte.h23
11 files changed, 123 insertions, 32 deletions
diff --git a/src/certificates.cc b/src/certificates.cc
index 4c41ebba..f23dbc5d 100644
--- a/src/certificates.cc
+++ b/src/certificates.cc
@@ -194,6 +194,14 @@ Certificate::subject () const
}
string
+Certificate::common_name () const
+{
+ assert (_certificate);
+
+ return get_name_part (X509_get_subject_name (_certificate), NID_commonName);
+}
+
+string
Certificate::serial () const
{
assert (_certificate);
diff --git a/src/certificates.h b/src/certificates.h
index 198773f1..2bf8d0db 100644
--- a/src/certificates.h
+++ b/src/certificates.h
@@ -58,6 +58,7 @@ public:
std::string issuer () const;
std::string serial () const;
std::string subject () const;
+ std::string common_name () const;
/** @return RSA public key from this Certificate. Caller must not free the returned value. */
RSA* public_key () const;
diff --git a/src/dcp.cc b/src/dcp.cc
index 03d1598d..48ee7c56 100644
--- a/src/dcp.cc
+++ b/src/dcp.cc
@@ -67,7 +67,7 @@ DCP::DCP (boost::filesystem::path directory)
}
void
-DCP::write_xml (bool interop, XMLMetadata const & metadata, shared_ptr<Signer> signer) const
+DCP::write_xml (bool interop, XMLMetadata const & metadata, shared_ptr<const Signer> signer) const
{
for (list<shared_ptr<CPL> >::const_iterator i = _cpls.begin(); i != _cpls.end(); ++i) {
(*i)->write_xml (interop, metadata, signer);
@@ -81,7 +81,7 @@ DCP::write_xml (bool interop, XMLMetadata const & metadata, shared_ptr<Signer> s
}
std::string
-DCP::write_pkl (string pkl_uuid, bool interop, XMLMetadata const & metadata, shared_ptr<Signer> signer) const
+DCP::write_pkl (string pkl_uuid, bool interop, XMLMetadata const & metadata, shared_ptr<const Signer> signer) const
{
assert (!_cpls.empty ());
diff --git a/src/dcp.h b/src/dcp.h
index f2a261cd..635a972d 100644
--- a/src/dcp.h
+++ b/src/dcp.h
@@ -83,7 +83,7 @@ public:
/** Write the required XML files to the directory that was
* passed into the constructor.
*/
- void write_xml (bool interop, XMLMetadata const &, boost::shared_ptr<Signer> signer = boost::shared_ptr<Signer> ()) const;
+ void write_xml (bool interop, XMLMetadata const &, boost::shared_ptr<const Signer> signer = boost::shared_ptr<const Signer> ()) const;
/** Compare this DCP with another, according to various options.
* @param other DCP to compare this one to.
@@ -126,7 +126,7 @@ private:
/** Write the PKL file.
* @param pkl_uuid UUID to use.
*/
- std::string write_pkl (std::string pkl_uuid, bool, XMLMetadata const &, boost::shared_ptr<Signer>) const;
+ std::string write_pkl (std::string pkl_uuid, bool, XMLMetadata const &, boost::shared_ptr<const Signer>) const;
/** Write the VOLINDEX file */
void write_volindex () const;
diff --git a/src/kdm.cc b/src/kdm.cc
index fc0aaa75..80d64441 100644
--- a/src/kdm.cc
+++ b/src/kdm.cc
@@ -46,7 +46,7 @@ using boost::shared_ptr;
using namespace libdcp;
KDM::KDM (boost::filesystem::path kdm, boost::filesystem::path private_key)
- : xml_kdm (new xml::DCinemaSecurityMessage (kdm))
+ : _xml_kdm (new xml::DCinemaSecurityMessage (kdm))
{
/* Read the private key */
@@ -63,7 +63,7 @@ KDM::KDM (boost::filesystem::path kdm, boost::filesystem::path private_key)
/* Use it to decrypt the keys */
- list<string> encrypted_keys = xml_kdm->authenticated_private.encrypted_keys;
+ list<string> encrypted_keys = _xml_kdm->authenticated_private.encrypted_keys;
for (list<string>::iterator i = encrypted_keys.begin(); i != encrypted_keys.end(); ++i) {
@@ -91,9 +91,9 @@ KDM::KDM (
boost::posix_time::ptime not_valid_before, boost::posix_time::ptime not_valid_after,
string annotation_text, string issue_date
)
- : xml_kdm (new xml::DCinemaSecurityMessage)
+ : _xml_kdm (new xml::DCinemaSecurityMessage)
{
- xml::AuthenticatedPublic& apu = xml_kdm->authenticated_public;
+ xml::AuthenticatedPublic& apu = _xml_kdm->authenticated_public;
/* AuthenticatedPublic */
@@ -107,13 +107,18 @@ KDM::KDM (
apu.recipient.x509_issuer_serial.x509_serial_number = recipient_cert->serial ();
apu.recipient.x509_subject_name = recipient_cert->subject ();
apu.composition_playlist_id = "urn:uuid:" + cpl->id ();
+// apu.content_authenticator = signer->certificates().leaf()->thumbprint ();
apu.content_title_text = cpl->name ();
apu.content_keys_not_valid_before = ptime_to_string (not_valid_before);
apu.content_keys_not_valid_after = ptime_to_string (not_valid_after);
apu.authorized_device_info.device_list_identifier = "urn:uuid:" + make_uuid ();
- apu.authorized_device_info.device_list_description = recipient_cert->subject ();
+ string n = recipient_cert->common_name ();
+ if (n.find (".") != string::npos) {
+ n = n.substr (n.find (".") + 1);
+ }
+ apu.authorized_device_info.device_list_description = n;
apu.authorized_device_info.device_list.push_back (recipient_cert->thumbprint ());
-
+
list<shared_ptr<const Asset> > assets = cpl->assets ();
for (list<shared_ptr<const Asset> >::iterator i = assets.begin(); i != assets.end(); ++i) {
/* XXX: non-MXF assets? */
@@ -132,36 +137,63 @@ KDM::KDM (
/* XXX: non-MXF assets? */
shared_ptr<const MXFAsset> mxf = boost::dynamic_pointer_cast<const MXFAsset> (*i);
if (mxf) {
- xml_kdm->authenticated_private.encrypted_keys.push_back (
- KDMKey (
+ KDMKey kkey (
signer, cpl->id (), mxf->key_type (), mxf->key_id (),
not_valid_before, not_valid_after, mxf->key().get()
- ).encrypted_base64 (recipient_cert)
);
+
+ _keys.push_back (kkey);
+ _xml_kdm->authenticated_private.encrypted_keys.push_back (kkey.encrypted_base64 (recipient_cert));
}
}
/* Signature */
- shared_ptr<xmlpp::Document> doc = xml_kdm->as_xml ();
+ shared_ptr<xmlpp::Document> doc = _xml_kdm->as_xml ();
shared_ptr<cxml::Node> root (new cxml::Node (doc->get_root_node ()));
xmlpp::Node* signature = root->node_child("Signature")->node();
signer->add_signature_value (signature, "ds");
- xml_kdm->signature = xml::Signature (shared_ptr<cxml::Node> (new cxml::Node (signature)));
+ _xml_kdm->signature = xml::Signature (shared_ptr<cxml::Node> (new cxml::Node (signature)));
}
+KDM::KDM (KDM const & other)
+ : _keys (other._keys)
+ , _xml_kdm (new xml::DCinemaSecurityMessage (*other._xml_kdm.get()))
+{
+
+}
+
+KDM &
+KDM::operator= (KDM const & other)
+{
+ if (this == &other) {
+ return *this;
+ }
+
+ _keys = other._keys;
+ _xml_kdm.reset (new xml::DCinemaSecurityMessage (*other._xml_kdm.get ()));
+
+ return *this;
+}
+
void
KDM::as_xml (boost::filesystem::path path) const
{
- shared_ptr<xmlpp::Document> doc = xml_kdm->as_xml ();
- doc->write_to_file_formatted (path.string(), "UTF-8");
+ shared_ptr<xmlpp::Document> doc = _xml_kdm->as_xml ();
+ /* This must *not* be the _formatted version, otherwise the signature
+ will be wrong.
+ */
+ doc->write_to_file (path.string(), "UTF-8");
}
string
KDM::as_xml () const
{
- shared_ptr<xmlpp::Document> doc = xml_kdm->as_xml ();
- return doc->write_to_string_formatted ("UTF-8");
+ shared_ptr<xmlpp::Document> doc = _xml_kdm->as_xml ();
+ /* This must *not* be the _formatted version, otherwise the signature
+ will be wrong.
+ */
+ return doc->write_to_string ("UTF-8");
}
KDMKey::KDMKey (
@@ -225,7 +257,7 @@ KDMKey::operator= (KDMKey const & other)
if (&other == this) {
return *this;
}
-
+
_cpl_id = other._cpl_id;
_key_type = other._key_type;
_key_id = other._key_id;
@@ -269,7 +301,17 @@ KDMKey::encrypted_base64 (shared_ptr<const Certificate> recipient_cert) const
/* Lazy overallocation */
char out[encrypted_len * 2];
- return Kumu::base64encode (encrypted, encrypted_len, out, encrypted_len * 2);
+ Kumu::base64encode (encrypted, encrypted_len, out, encrypted_len * 2);
+ int const N = strlen (out);
+ stringstream lines;
+ for (int i = 0; i < N; ++i) {
+ if (i > 0 && (i % 64) == 0) {
+ lines << "\n";
+ }
+ lines << out[i];
+ }
+
+ return lines.str ();
}
string
@@ -329,8 +371,25 @@ KDMKey::put_uuid (uint8_t ** d, string id) const
stringstream s;
s << id[i] << id[i + 1];
int h;
- s >> h;
+ s >> hex >> h;
**d = h;
(*d)++;
}
}
+
+bool
+libdcp::operator== (libdcp::KDMKey const & a, libdcp::KDMKey const & b)
+{
+ if (memcmp (a._signer_thumbprint, b._signer_thumbprint, 20) != 0) {
+ return false;
+ }
+
+ return (
+ a._cpl_id == b._cpl_id &&
+ a._key_type == b._key_type &&
+ a._key_id == b._key_id &&
+ a._not_valid_before == b._not_valid_before &&
+ a._not_valid_after == b._not_valid_after &&
+ a._key == b._key
+ );
+}
diff --git a/src/kdm.h b/src/kdm.h
index 597088ed..4e897ca8 100644
--- a/src/kdm.h
+++ b/src/kdm.h
@@ -30,6 +30,8 @@
#include "key.h"
#include "metadata.h"
+class kdm_key_test;
+
namespace libdcp {
namespace xml {
@@ -114,12 +116,16 @@ public:
std::string encrypted_base64 (boost::shared_ptr<const Certificate> cert) const;
private:
+ friend class ::kdm_key_test;
+
void get (uint8_t *, uint8_t const **, int) const;
std::string get (uint8_t const **, int) const;
std::string get_uuid (uint8_t const **) const;
void put (uint8_t **, uint8_t const *, int) const;
void put (uint8_t **, std::string) const;
void put_uuid (uint8_t **, std::string) const;
+
+ friend bool operator== (KDMKey const &, KDMKey const &);
uint8_t _signer_thumbprint[20];
std::string _cpl_id;
@@ -164,6 +170,9 @@ public:
std::string annotation_text, std::string issue_date
);
+ KDM (KDM const &);
+ KDM & operator= (KDM const &);
+
/** @return The unencrypted content keys from this KDM */
std::list<KDMKey> keys () const {
return _keys;
@@ -184,7 +193,7 @@ private:
std::list<KDMKey> _keys;
/** The KDM's contents, mapped 1:1-ish to the XML */
- boost::shared_ptr<xml::DCinemaSecurityMessage> xml_kdm;
+ boost::shared_ptr<xml::DCinemaSecurityMessage> _xml_kdm;
};
diff --git a/src/signer.cc b/src/signer.cc
index 9aebd39d..f15f5325 100644
--- a/src/signer.cc
+++ b/src/signer.cc
@@ -21,12 +21,14 @@
#include <xmlsec/xmldsig.h>
#include <xmlsec/dl.h>
#include <xmlsec/app.h>
+#include <xmlsec/crypto.h>
#include <libcxml/cxml.h>
#include "signer.h"
#include "exceptions.h"
using std::string;
using std::list;
+using std::cout;
using boost::shared_ptr;
using namespace libdcp;
diff --git a/src/sound_asset.h b/src/sound_asset.h
index d41b72d5..67d3e445 100644
--- a/src/sound_asset.h
+++ b/src/sound_asset.h
@@ -88,6 +88,10 @@ public:
return _channels;
}
+ void set_sampling_rate (int s) {
+ _sampling_rate = s;
+ }
+
int sampling_rate () const {
return _sampling_rate;
}
diff --git a/src/util.cc b/src/util.cc
index 4bcc61fb..11052df6 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -33,6 +33,7 @@
#include <xmlsec/xmldsig.h>
#include <xmlsec/dl.h>
#include <xmlsec/app.h>
+#include <xmlsec/crypto.h>
#include "KM_util.h"
#include "KM_fileio.h"
#include "AS_DCP.h"
diff --git a/src/wscript b/src/wscript
index d7e118c7..1d694ec3 100644
--- a/src/wscript
+++ b/src/wscript
@@ -67,6 +67,7 @@ def build(bld):
lut.h
lut_cache.h
metadata.h
+ mono_picture_asset.h
mono_picture_frame.h
mxf_asset.h
picture_asset.h
@@ -80,6 +81,7 @@ def build(bld):
sound_asset.h
sound_frame.h
srgb_linearised_gamma_lut.h
+ stereo_picture_asset.h
stereo_picture_frame.h
subtitle_asset.h
types.h
diff --git a/src/xml/kdm_smpte.h b/src/xml/kdm_smpte.h
index 0139876f..32a297f8 100644
--- a/src/xml/kdm_smpte.h
+++ b/src/xml/kdm_smpte.h
@@ -170,6 +170,7 @@ public:
c = c->node_child ("KDMRequiredExtensions");
recipient = Recipient (c->node_child ("Recipient"));
composition_playlist_id = c->string_child ("CompositionPlaylistId");
+ content_authenticator = c->optional_string_child ("ContentAuthenticator");
content_title_text = c->string_child ("ContentTitleText");
content_keys_not_valid_before = c->string_child ("ContentKeysNotValidBefore");
content_keys_not_valid_after = c->string_child ("ContentKeysNotValidAfter");
@@ -209,6 +210,9 @@ public:
recipient.as_xml (kdm_required_extensions->add_child ("Recipient"));
kdm_required_extensions->add_child("CompositionPlaylistId")->add_child_text (composition_playlist_id);
+ if (content_authenticator) {
+ kdm_required_extensions->add_child("ContentAuthenticator")->add_child_text (content_authenticator.get ());
+ }
kdm_required_extensions->add_child("ContentTitleText")->add_child_text (content_title_text);
kdm_required_extensions->add_child("ContentKeysNotValidBefore")->add_child_text (content_keys_not_valid_before);
kdm_required_extensions->add_child("ContentKeysNotValidAfter")->add_child_text (content_keys_not_valid_after);
@@ -234,6 +238,7 @@ public:
Signer signer;
Recipient recipient;
std::string composition_playlist_id;
+ boost::optional<std::string> content_authenticator;
std::string content_title_text;
std::string content_keys_not_valid_before;
std::string content_keys_not_valid_after;
@@ -312,16 +317,12 @@ public:
node->done ();
}
- void as_xml (Writer& writer, xmlpp::Element* node) const
+ void as_xml (xmlpp::Element* node) const
{
xmlpp::Element* reference = node->add_child ("Reference", "ds");
reference->set_attribute ("URI", uri);
reference->add_child("DigestMethod", "ds")->set_attribute ("Algorithm", "http://www.w3.org/2001/04/xmlenc#sha256");
reference->add_child("DigestValue", "ds")->add_child_text (digest_value);
-
- if (!uri.empty ()) {
- xmlAddID (0, writer.document->cobj(), (const xmlChar *) uri.substr(1).c_str(), writer.references[uri.substr(1)]->cobj ());
- }
}
std::string uri;
@@ -359,14 +360,14 @@ public:
node->done ();
}
- void as_xml (Writer& writer, xmlpp::Element* node) const
+ void as_xml (xmlpp::Element* node) const
{
xmlpp::Element* si = node->add_child ("SignedInfo", "ds");
si->add_child ("CanonicalizationMethod", "ds")->set_attribute ("Algorithm", "http://www.w3.org/TR/2001/REC-xml-c14n-20010315#WithComments");
si->add_child ("SignatureMethod", "ds")->set_attribute ("Algorithm", "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
- authenticated_public.as_xml (writer, si);
- authenticated_private.as_xml (writer, si);
+ authenticated_public.as_xml (si);
+ authenticated_private.as_xml (si);
node->add_child("SignatureValue", "ds")->add_child_text (signature_value);
@@ -408,7 +409,11 @@ public:
authenticated_public.as_xml (writer, root->add_child ("AuthenticatedPublic"));
authenticated_private.as_xml (writer, root->add_child ("AuthenticatedPrivate"));
- signature.as_xml (writer, root->add_child ("Signature", "ds"));
+ signature.as_xml (root->add_child ("Signature", "ds"));
+
+ for (std::map<std::string, xmlpp::Attribute*>::const_iterator i = writer.references.begin(); i != writer.references.end(); ++i) {
+ xmlAddID (0, writer.document->cobj(), (const xmlChar *) i->first.c_str(), i->second->cobj ());
+ }
return writer.document;
}