diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-09-19 20:44:42 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-09-19 20:44:42 +0100 |
| commit | 8d6c3c9ae554430582dcb016897e87f6d04d5d78 (patch) | |
| tree | 5b329eeb60fe7372cc89740d4cf8fa1d5fe51614 | |
| parent | 827901db3d834465b1121c9f8041b9faf4923ec9 (diff) | |
Various encryption-related stuff.
| -rw-r--r-- | examples/make_dcp.cc | 4 | ||||
| -rw-r--r-- | src/certificates.cc | 50 | ||||
| -rw-r--r-- | src/certificates.h | 16 | ||||
| -rw-r--r-- | src/cpl.cc | 28 | ||||
| -rw-r--r-- | src/dcp.cc | 4 | ||||
| -rw-r--r-- | src/kdm.cc | 27 | ||||
| -rw-r--r-- | src/kdm.h | 35 | ||||
| -rw-r--r-- | src/key.cc | 99 | ||||
| -rw-r--r-- | src/key.h | 61 | ||||
| -rw-r--r-- | src/mxf_asset.cc | 54 | ||||
| -rw-r--r-- | src/mxf_asset.h | 35 | ||||
| -rw-r--r-- | src/picture_asset.cc | 20 | ||||
| -rw-r--r-- | src/picture_asset.h | 9 | ||||
| -rw-r--r-- | src/reel.cc | 8 | ||||
| -rw-r--r-- | src/sound_asset.cc | 10 | ||||
| -rw-r--r-- | src/sound_asset.h | 7 | ||||
| -rw-r--r-- | src/wscript | 2 | ||||
| -rw-r--r-- | test/certificates_test.cc | 9 | ||||
| -rw-r--r-- | test/dcp_test.cc | 2 | ||||
| -rw-r--r-- | test/encryption_test.cc | 12 | ||||
| -rw-r--r-- | test/error_test.cc | 4 | ||||
| -rw-r--r-- | test/kdm_test.cc | 28 | ||||
| -rw-r--r-- | test/recovery_test.cc | 4 |
23 files changed, 361 insertions, 167 deletions
diff --git a/examples/make_dcp.cc b/examples/make_dcp.cc index 6da9cf20..9222caaa 100644 --- a/examples/make_dcp.cc +++ b/examples/make_dcp.cc @@ -75,7 +75,7 @@ main () for 2K projectors. */ boost::shared_ptr<libdcp::MonoPictureAsset> picture_asset ( - new libdcp::MonoPictureAsset (video_frame, "My Film DCP", "video.mxf", 0, 24, 48, false, libdcp::Size (1998, 1080), false) + new libdcp::MonoPictureAsset (video_frame, "My Film DCP", "video.mxf", 0, 24, 48, libdcp::Size (1998, 1080), false) ); /* Now we will create a `sound asset', which is made up of a WAV file for each channel of audio. Here we're using @@ -95,7 +95,7 @@ main () /* Now we can create the sound asset using these files */ boost::shared_ptr<libdcp::SoundAsset> sound_asset ( - new libdcp::SoundAsset (sound_files, "My Film DCP", "audio.mxf", 0, 24, 48, false, false) + new libdcp::SoundAsset (sound_files, "My Film DCP", "audio.mxf", 0, 24, 48, false) ); /* Now that we have the assets, we can create a Reel to put them in and add it to the CPL */ diff --git a/src/certificates.cc b/src/certificates.cc index 3566fba0..6d9c449d 100644 --- a/src/certificates.cc +++ b/src/certificates.cc @@ -43,7 +43,7 @@ Certificate::Certificate (X509* c) } -Certificate::Certificate (string const & filename) +Certificate::Certificate (boost::filesystem::path filename) : _certificate (0) { FILE* f = fopen (filename.c_str(), "r"); @@ -56,13 +56,52 @@ Certificate::Certificate (string const & filename) } } +Certificate::Certificate (string cert) +{ + read_string (cert); +} + +Certificate::Certificate (Certificate const & other) +{ + read_string (other.certificate (true)); +} + +void +Certificate::read_string (string cert) +{ + BIO* bio = BIO_new_mem_buf (const_cast<char *> (cert.c_str ()), -1); + if (!bio) { + throw MiscError ("could not create memory BIO"); + } + + _certificate = PEM_read_bio_X509 (bio, 0, 0, 0); + if (!_certificate) { + throw MiscError ("could not read X509 certificate from memory BIO"); + } + + BIO_free (bio); +} + Certificate::~Certificate () { X509_free (_certificate); } +Certificate & +Certificate::operator= (Certificate const & other) +{ + if (this == &other) { + return *this; + } + + X509_free (_certificate); + read_string (other.certificate ()); + + return *this; +} + string -Certificate::certificate () const +Certificate::certificate (bool with_begin_end) const { assert (_certificate); @@ -82,8 +121,11 @@ Certificate::certificate () const BIO_free (bio); - boost::replace_all (s, "-----BEGIN CERTIFICATE-----\n", ""); - boost::replace_all (s, "\n-----END CERTIFICATE-----\n", ""); + if (!with_begin_end) { + boost::replace_all (s, "-----BEGIN CERTIFICATE-----\n", ""); + boost::replace_all (s, "\n-----END CERTIFICATE-----\n", ""); + } + return s; } diff --git a/src/certificates.h b/src/certificates.h index 9caea5a7..ef2e63b4 100644 --- a/src/certificates.h +++ b/src/certificates.h @@ -24,6 +24,7 @@ #include <list> #include <boost/noncopyable.hpp> #include <boost/shared_ptr.hpp> +#include <boost/filesystem.hpp> #undef X509_NAME #include <openssl/x509.h> @@ -35,18 +36,25 @@ namespace xmlpp { namespace libdcp { -class Certificate : public boost::noncopyable +class Certificate { public: Certificate () : _certificate (0) {} - Certificate (std::string const &); + Certificate (boost::filesystem::path); + Certificate (std::string); Certificate (X509 *); + Certificate (Certificate const &); ~Certificate (); - std::string certificate () const; + Certificate& operator= (Certificate const &); + + /** @param with_begin_end true to include BEGIN CERTIFICATE / END CERTIFICATE markers + * @return the whole certificate as a string. + */ + std::string certificate (bool with_begin_end = false) const; std::string issuer () const; std::string serial () const; std::string subject () const; @@ -54,6 +62,8 @@ public: std::string thumbprint () const; private: + void read_string (std::string); + static std::string name_for_xml (X509_NAME *); static std::string asn_to_utf8 (ASN1_STRING *); static std::string get_name_part (X509_NAME *, int); @@ -444,21 +444,29 @@ CPL::make_kdm ( xmlpp::Element* authenticated_private = root->add_child("AuthenticatedPrivate"); authenticated_private->set_attribute ("Id", "ID_AuthenticatedPrivate"); xmlAddID (0, doc->cobj(), (const xmlChar *) "ID_AuthenticatedPrivate", authenticated_private->get_attribute("Id")->cobj()); - { - xmlpp::Element* encrypted_key = authenticated_private->add_child ("EncryptedKey", "enc"); - { - xmlpp::Element* encryption_method = encrypted_key->add_child ("EncryptionMethod", "enc"); - encryption_method->set_attribute ("Algorithm", "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"); - encryption_method->add_child("DigestMethod", "ds")->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#sha1"); - } + /* Hex keys that we have already written into the node */ + list<Key> written_keys; + + list<shared_ptr<const Asset> > a = assets(); + for (list<shared_ptr<const Asset> >::iterator i = a.begin(); i != a.end(); ++i) { + /* XXX: non-MXF assets? */ + shared_ptr<const MXFAsset> mxf = boost::dynamic_pointer_cast<const MXFAsset> (*i); + if (!mxf || find (written_keys.begin(), written_keys.end(), mxf->key ()) != written_keys.end ()) { + continue; + } + + xmlpp::Element* encrypted_key = authenticated_private->add_child ("EncryptedKey", "enc"); + xmlpp::Element* encryption_method = encrypted_key->add_child ("EncryptionMethod", "enc"); + encryption_method->set_attribute ("Algorithm", "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"); + encryption_method->add_child("DigestMethod", "ds")->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#sha1"); xmlpp::Element* cipher_data = authenticated_private->add_child ("CipherData", "enc"); - cipher_data->add_child("CipherValue", "enc")->add_child_text("XXX"); + cipher_data->add_child("CipherValue", "enc")->add_child_text(mxf->key()->hex()); + + written_keys.push_back (mxf->key().get()); } } - /* XXX: x2 one for each mxf? */ - { xmlpp::Element* signature = root->add_child("Signature", "ds"); @@ -349,10 +349,10 @@ DCP::encrypted () const void DCP::add_kdm (KDM const & kdm) { - list<KDMCipher> ciphers = kdm.ciphers (); + list<KDMKey> keys = kdm.keys (); for (list<shared_ptr<CPL> >::iterator i = _cpls.begin(); i != _cpls.end(); ++i) { - for (list<KDMCipher>::iterator j = ciphers.begin(); j != ciphers.end(); ++j) { + for (list<KDMKey>::iterator j = keys.begin(); j != keys.end(); ++j) { if (j->cpl_id() == (*i)->id()) { (*i)->add_kdm (kdm); } @@ -80,7 +80,7 @@ KDM::KDM (boost::filesystem::path kdm, boost::filesystem::path private_key) throw MiscError (String::compose ("Could not decrypt KDM (%1)", ERR_error_string (ERR_get_error(), 0))); } - _ciphers.push_back (KDMCipher (decrypted, decrypted_len)); + _keys.push_back (KDMKey (decrypted, decrypted_len)); delete[] decrypted; } @@ -88,7 +88,7 @@ KDM::KDM (boost::filesystem::path kdm, boost::filesystem::path private_key) } -KDMCipher::KDMCipher (unsigned char const * raw, int len) +KDMKey::KDMKey (unsigned char const * raw, int len) { switch (len) { case 134: @@ -99,8 +99,7 @@ KDMCipher::KDMCipher (unsigned char const * raw, int len) _key_id = get_uuid (&raw, 16); _not_valid_before = get (&raw, 25); _not_valid_after = get (&raw, 25); - memcpy (_key_raw, raw, 16); - _key_string = get_hex (&raw, 16); + _key = Key (raw); break; case 138: /* SMPTE */ @@ -111,8 +110,7 @@ KDMCipher::KDMCipher (unsigned char const * raw, int len) _key_id = get_uuid (&raw, 16); _not_valid_before = get (&raw, 25); _not_valid_after = get (&raw, 25); - memcpy (_key_raw, raw, 16); - _key_string = get_hex (&raw, 16); + _key = Key (raw); break; default: assert (false); @@ -120,7 +118,7 @@ KDMCipher::KDMCipher (unsigned char const * raw, int len) } string -KDMCipher::get (unsigned char const ** p, int N) const +KDMKey::get (unsigned char const ** p, int N) const { string g; for (int i = 0; i < N; ++i) { @@ -132,7 +130,7 @@ KDMCipher::get (unsigned char const ** p, int N) const } string -KDMCipher::get_uuid (unsigned char const ** p, int N) const +KDMKey::get_uuid (unsigned char const ** p, int N) const { stringstream g; @@ -146,16 +144,3 @@ KDMCipher::get_uuid (unsigned char const ** p, int N) const return g.str (); } - -string -KDMCipher::get_hex (unsigned char const ** p, int N) const -{ - stringstream g; - - for (int i = 0; i < N; ++i) { - g << setw(2) << setfill('0') << hex << static_cast<int> (**p); - (*p)++; - } - - return g.str (); -} @@ -21,16 +21,17 @@ #define LIBDCP_KDM_H #include <boost/filesystem.hpp> +#include "key.h" namespace libdcp { -/** A single cipher for encrypting or decrypting an MXF. One or more of these +/** A single key for encrypting or decrypting an MXF. One or more of these * are delivered in a KDM. */ -class KDMCipher +class KDMKey { public: - KDMCipher (unsigned char const *, int); + KDMKey (unsigned char const *, int); std::string structure_id () const { return _structure_id; @@ -47,11 +48,11 @@ public: std::string key_type () const { return _key_type; } - + std::string key_id () const { return _key_id; } - + std::string not_valid_before () const { return _not_valid_before; } @@ -60,30 +61,22 @@ public: return _not_valid_after; } - /** The key as a hex string */ - std::string key_string () const { - return _key_string; - } - - /** The key as 16 raw bytes */ - unsigned char const * key_raw () const { - return _key_raw; + Key key () const { + return _key; } private: std::string get (unsigned char const **, int) const; std::string get_uuid (unsigned char const **, int) const; - std::string get_hex (unsigned char const **, int) const; std::string _structure_id; std::string _signer_thumbprint; std::string _cpl_id; - std::string _key_type; - std::string _key_id; std::string _not_valid_before; std::string _not_valid_after; - std::string _key_string; - unsigned char _key_raw[16]; + std::string _key_type; + std::string _key_id; + Key _key; }; class KDM @@ -91,12 +84,12 @@ class KDM public: KDM (boost::filesystem::path, boost::filesystem::path); - std::list<KDMCipher> ciphers () const { - return _ciphers; + std::list<KDMKey> keys () const { + return _keys; } private: - std::list<KDMCipher> _ciphers; + std::list<KDMKey> _keys; }; diff --git a/src/key.cc b/src/key.cc new file mode 100644 index 00000000..8cac04a3 --- /dev/null +++ b/src/key.cc @@ -0,0 +1,99 @@ +/* + Copyright (C) 2013 Carl Hetherington <cth@carlh.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#include <sstream> +#include <string> +#include <iomanip> +#include "AS_DCP.h" +#include "KM_prng.h" +#include "KM_util.h" +#include "key.h" + +using std::string; +using std::stringstream; +using std::setw; +using std::setfill; +using namespace libdcp; + +Key::Key () + : _value (new uint8_t[ASDCP::KeyLen]) +{ + Kumu::FortunaRNG rng; + rng.FillRandom (_value, ASDCP::KeyLen); +} + +Key::Key (uint8_t const * value) + : _value (new uint8_t[ASDCP::KeyLen]) +{ + memcpy (_value, value, ASDCP::KeyLen); +} + +Key::Key (string value) + : _value (new uint8_t[ASDCP::KeyLen]) +{ + unsigned int length; + Kumu::hex2bin (value.c_str(), _value, ASDCP::KeyLen, &length); +} + +Key::Key (Key const & other) + : _value (new uint8_t[ASDCP::KeyLen]) +{ + memcpy (_value, other._value, ASDCP::KeyLen); +} + +Key::~Key () +{ + delete[] _value; +} + +Key & +Key::operator= (Key const & other) +{ + if (this == &other) { + return *this; + } + + memcpy (_value, other._value, ASDCP::KeyLen); + return *this; +} + +string +Key::hex () const +{ + stringstream g; + + for (unsigned int i = 0; i < ASDCP::KeyLen; ++i) { + g << setw(2) << setfill('0') << std::hex << static_cast<int> (_value[i]); + } + + return g.str (); +} + +bool +libdcp::operator== (Key const & a, Key const & b) +{ + return memcmp (a.value(), b.value(), ASDCP::KeyLen) == 0; +} + +bool +libdcp::operator!= (Key const & a, Key const & b) +{ + return !(a == b); +} + diff --git a/src/key.h b/src/key.h new file mode 100644 index 00000000..fbadfd33 --- /dev/null +++ b/src/key.h @@ -0,0 +1,61 @@ +/* + Copyright (C) 2013 Carl Hetherington <cth@carlh.net> + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef LIBDCP_KEY_H +#define LIBDCP_KEY_H + +#include <stdint.h> + +namespace libdcp { + +/** A key for encrypting MXFs */ +class Key +{ +public: + /** Create a new, random key */ + Key (); + + /** Create a Key from a raw key value */ + Key (uint8_t const *); + + /** Create a Key from a hex key value */ + Key (std::string); + + Key (Key const &); + ~Key (); + + Key& operator= (Key const &); + + uint8_t* value () const { + return _value; + } + + std::string hex () const; + +private: + /** Raw key value */ + uint8_t* _value; +}; + +extern bool operator== (Key const & a, Key const & b); +extern bool operator!= (Key const & a, Key const & b); + +} + +#endif diff --git a/src/mxf_asset.cc b/src/mxf_asset.cc index 54c204e7..bcfe6085 100644 --- a/src/mxf_asset.cc +++ b/src/mxf_asset.cc @@ -46,46 +46,25 @@ using namespace libdcp; MXFAsset::MXFAsset (string directory, string file_name) : Asset (directory, file_name) , _progress (0) - , _encrypted (false) , _encryption_context (0) , _decryption_context (0) { } -MXFAsset::MXFAsset (string directory, string file_name, boost::signals2::signal<void (float)>* progress, int edit_rate, int intrinsic_duration, bool encrypted) +MXFAsset::MXFAsset (string directory, string file_name, boost::signals2::signal<void (float)>* progress, int edit_rate, int intrinsic_duration) : Asset (directory, file_name, edit_rate, intrinsic_duration) , _progress (progress) - , _encrypted (encrypted) , _encryption_context (0) , _decryption_context (0) { - if (_encrypted) { - /* Generate an encryption key and a UUID for it */ - _key_id = make_uuid (); - uint8_t key_buffer[ASDCP::KeyLen]; - Kumu::FortunaRNG rng; - rng.FillRandom (key_buffer, ASDCP::KeyLen); - char key_string[ASDCP::KeyLen * 4]; - Kumu::bin2hex (key_buffer, ASDCP::KeyLen, key_string, ASDCP::KeyLen * 4); - _key_value = key_string; - - _encryption_context = new ASDCP::AESEncContext; - if (ASDCP_FAILURE (_encryption_context->InitKey (key_buffer))) { - throw MiscError ("could not set up encryption context"); - } - - uint8_t cbc_buffer[ASDCP::CBC_BLOCK_SIZE]; - - if (ASDCP_FAILURE (_encryption_context->SetIVec (rng.FillRandom (cbc_buffer, ASDCP::CBC_BLOCK_SIZE)))) { - throw MiscError ("could not set up CBC initialization vector"); - } - } + } MXFAsset::~MXFAsset () { delete _encryption_context; + delete _decryption_context; } void @@ -104,7 +83,7 @@ MXFAsset::fill_writer_info (ASDCP::WriterInfo* writer_info, string uuid, bool in Kumu::hex2bin (uuid.c_str(), writer_info->AssetUUID, Kumu::UUID_Length, &c); assert (c == Kumu::UUID_Length); - if (_encrypted) { + if (_key) { Kumu::GenRandomUUID (writer_info->ContextID); writer_info->EncryptedEssence = true; @@ -159,16 +138,35 @@ MXFAsset::write_to_cpl (xmlpp::Element* node, bool interop) const a->add_child ("IntrinsicDuration")->add_child_text (lexical_cast<string> (_intrinsic_duration)); a->add_child ("EntryPoint")->add_child_text (lexical_cast<string> (_entry_point)); a->add_child ("Duration")->add_child_text (lexical_cast<string> (_duration)); - if (_encrypted) { + if (!_key_id.empty ()) { a->add_child("KeyId")->add_child_text ("urn:uuid:" + _key_id); } } void -MXFAsset::set_kdm_cipher (KDMCipher cipher) +MXFAsset::set_key (Key key) { + _key = key; + + if (_key_id.empty ()) { + /* No key ID so far; we now need one */ + _key_id = make_uuid (); + } + _decryption_context = new ASDCP::AESDecContext; - if (ASDCP_FAILURE (_decryption_context->InitKey (cipher.key_raw ()))) { + if (ASDCP_FAILURE (_decryption_context->InitKey (_key->value ()))) { throw MiscError ("could not set up decryption context"); } + + _encryption_context = new ASDCP::AESEncContext; + if (ASDCP_FAILURE (_encryption_context->InitKey (_key->value ()))) { + throw MiscError ("could not set up encryption context"); + } + + uint8_t cbc_buffer[ASDCP::CBC_BLOCK_SIZE]; + + Kumu::FortunaRNG rng; + if (ASDCP_FAILURE (_encryption_context->SetIVec (rng.FillRandom (cbc_buffer, ASDCP::CBC_BLOCK_SIZE)))) { + throw MiscError ("could not set up CBC initialization vector"); + } } diff --git a/src/mxf_asset.h b/src/mxf_asset.h index 3f6ecc59..d681970e 100644 --- a/src/mxf_asset.h +++ b/src/mxf_asset.h @@ -22,6 +22,7 @@ #include <boost/signals2.hpp> #include "asset.h" +#include "key.h" namespace ASDCP { class AESEncContext; @@ -32,7 +33,6 @@ namespace libdcp { class MXFMetadata; -class KDMCipher; /** @brief Parent class for assets which have MXF files */ class MXFAsset : public Asset @@ -55,7 +55,13 @@ public: * @param edit_rate Edit rate in frames per second (usually equal to the video frame rate). * @param intrinsic_duration Duration of the whole asset in frames. */ - MXFAsset (std::string directory, std::string file_name, boost::signals2::signal<void (float)>* progress, int edit_rate, int intrinsic_duration, bool encrypted); + MXFAsset ( + std::string directory, + std::string file_name, + boost::signals2::signal<void (float)>* progress, + int edit_rate, + int intrinsic_duration + ); ~MXFAsset (); @@ -72,19 +78,23 @@ public: void add_typed_key_id (xmlpp::Element *) const; - std::string key_id () const { - return _key_id; + bool encrypted () const { + return !_key_id.empty (); } - void set_key_id (std::string k) { - _key_id = k; + void set_key_id (std::string i) { + _key_id = i; } - bool encrypted () const { - return !_key_id.empty (); + std::string key_id () const { + return _key_id; } + + void set_key (Key); - void set_kdm_cipher (KDMCipher); + boost::optional<Key> key () const { + return _key; + } protected: virtual std::string key_type () const = 0; @@ -95,13 +105,10 @@ protected: /** Signal to emit to report progress, or 0 */ boost::signals2::signal<void (float)>* _progress; - bool _encrypted; ASDCP::AESEncContext* _encryption_context; - /** Key used to encrypt, or empty if _encryption is false */ - std::string _key_value; - /** UUID of encryption key */ - std::string _key_id; ASDCP::AESDecContext* _decryption_context; + std::string _key_id; + boost::optional<Key> _key; }; } diff --git a/src/picture_asset.cc b/src/picture_asset.cc index 1c480348..5903b394 100644 --- a/src/picture_asset.cc +++ b/src/picture_asset.cc @@ -54,8 +54,8 @@ using boost::dynamic_pointer_cast; using boost::lexical_cast; using namespace libdcp; -PictureAsset::PictureAsset (string directory, string mxf_name, boost::signals2::signal<void (float)>* progress, int fps, int intrinsic_duration, bool encrypted, Size size) - : MXFAsset (directory, mxf_name, progress, fps, intrinsic_duration, encrypted) +PictureAsset::PictureAsset (string directory, string mxf_name, boost::signals2::signal<void (float)>* progress, int fps, int intrinsic_duration, Size size) + : MXFAsset (directory, mxf_name, progress, fps, intrinsic_duration) , _size (size) { @@ -195,12 +195,11 @@ MonoPictureAsset::MonoPictureAsset ( boost::signals2::signal<void (float)>* progress, int fps, int intrinsic_duration, - bool encrypted, Size size, bool interop, MXFMetadata const & metadata ) - : PictureAsset (directory, mxf_name, progress, fps, intrinsic_duration, encrypted, size) + : PictureAsset (directory, mxf_name, progress, fps, intrinsic_duration, size) { construct (get_path, interop, metadata); } @@ -212,18 +211,17 @@ MonoPictureAsset::MonoPictureAsset ( boost::signals2::signal<void (float)>* progress, int fps, int intrinsic_duration, - bool encrypted, Size size, bool interop, MXFMetadata const & metadata ) - : PictureAsset (directory, mxf_name, progress, fps, intrinsic_duration, encrypted, size) + : PictureAsset (directory, mxf_name, progress, fps, intrinsic_duration, size) { construct (boost::bind (&MonoPictureAsset::path_from_list, this, _1, files), interop, metadata); } -MonoPictureAsset::MonoPictureAsset (string directory, string mxf_name, int fps, Size size, bool encrypted) - : PictureAsset (directory, mxf_name, 0, fps, 0, encrypted, size) +MonoPictureAsset::MonoPictureAsset (string directory, string mxf_name, int fps, Size size) + : PictureAsset (directory, mxf_name, 0, fps, 0, size) { } @@ -437,7 +435,7 @@ PictureAsset::frame_buffer_equals ( StereoPictureAsset::StereoPictureAsset (string directory, string mxf_name, int fps, int intrinsic_duration) - : PictureAsset (directory, mxf_name, 0, fps, intrinsic_duration, false, Size (0, 0)) + : PictureAsset (directory, mxf_name, 0, fps, intrinsic_duration, Size (0, 0)) { ASDCP::JP2K::MXFSReader reader; if (ASDCP_FAILURE (reader.OpenRead (path().string().c_str()))) { @@ -472,8 +470,8 @@ PictureAsset::key_type () const return "MDIK"; } -StereoPictureAsset::StereoPictureAsset (string directory, string mxf_name, int fps, Size size, bool encrypted) - : PictureAsset (directory, mxf_name, 0, fps, 0, encrypted, size) +StereoPictureAsset::StereoPictureAsset (string directory, string mxf_name, int fps, Size size) + : PictureAsset (directory, mxf_name, 0, fps, 0, size) { } diff --git a/src/picture_asset.h b/src/picture_asset.h index 7fcc2efb..398f8868 100644 --- a/src/picture_asset.h +++ b/src/picture_asset.h @@ -64,7 +64,6 @@ public: boost::signals2::signal<void (float)>* progress, int fps, int intrinsic_duration, - bool encrypted, Size ); @@ -112,7 +111,6 @@ public: * @param fps Video frames per second. * @param intrinsic_duration Total number of frames in the asset. * @param size Size of images in pixels. - * @param encrypted true if asset should be encrypted. */ MonoPictureAsset ( std::vector<std::string> const & files, @@ -121,7 +119,6 @@ public: boost::signals2::signal<void (float)>* progress, int fps, int intrinsic_duration, - bool encrypted, Size size, bool interop, MXFMetadata const & metadata = MXFMetadata () @@ -137,7 +134,6 @@ public: * @param fps Video frames per second. * @param intrinsic_duration Total number of frames in the asset. * @param size Size of images in pixels. - * @param encrypted true if asset should be encrypted. */ MonoPictureAsset ( boost::function<std::string (int)> get_path, @@ -146,7 +142,6 @@ public: boost::signals2::signal<void (float)>* progress, int fps, int intrinsic_duration, - bool encrypted, Size size, bool interop, MXFMetadata const & metadata = MXFMetadata () @@ -166,7 +161,7 @@ public: * @param fps Video frames per second. * @param size Size in pixels that the picture frames will be. */ - MonoPictureAsset (std::string directory, std::string mxf_name, int fps, Size size, bool encrypted); + MonoPictureAsset (std::string directory, std::string mxf_name, int fps, Size size); /** Start a progressive write to a MonoPictureAsset */ boost::shared_ptr<PictureAssetWriter> start_write (bool, bool, MXFMetadata const & metadata = MXFMetadata ()); @@ -195,7 +190,7 @@ public: * @param fps Video frames per second. * @param size Size in pixels that the picture frames will be. */ - StereoPictureAsset (std::string directory, std::string mxf_name, int fps, Size size, bool encrypted); + StereoPictureAsset (std::string directory, std::string mxf_name, int fps, Size size); /** Start a progressive write to a StereoPictureAsset */ boost::shared_ptr<PictureAssetWriter> start_write (bool, bool, MXFMetadata const & metadata = MXFMetadata ()); diff --git a/src/reel.cc b/src/reel.cc index 43c934ea..ffb184ab 100644 --- a/src/reel.cc +++ b/src/reel.cc @@ -93,14 +93,14 @@ Reel::encrypted () const void Reel::add_kdm (KDM const & kdm) { - list<KDMCipher> ciphers = kdm.ciphers (); + list<KDMKey> keys = kdm.keys (); - for (list<KDMCipher>::iterator i = ciphers.begin(); i != ciphers.end(); ++i) { + for (list<KDMKey>::iterator i = keys.begin(); i != keys.end(); ++i) { if (i->key_id() == _main_picture->key_id()) { - _main_picture->set_kdm_cipher (*i); + _main_picture->set_key (i->key ()); } if (i->key_id() == _main_sound->key_id()) { - _main_sound->set_kdm_cipher (*i); + _main_sound->set_key (i->key ()); } } } diff --git a/src/sound_asset.cc b/src/sound_asset.cc index 29fbc0d7..6f74e54a 100644 --- a/src/sound_asset.cc +++ b/src/sound_asset.cc @@ -49,11 +49,10 @@ SoundAsset::SoundAsset ( boost::signals2::signal<void (float)>* progress, int fps, int intrinsic_duration, - bool encrypted, bool interop, MXFMetadata const & metadata ) - : MXFAsset (directory, mxf_name, progress, fps, intrinsic_duration, encrypted) + : MXFAsset (directory, mxf_name, progress, fps, intrinsic_duration) , _channels (files.size ()) , _sampling_rate (0) { @@ -70,11 +69,10 @@ SoundAsset::SoundAsset ( int fps, int intrinsic_duration, int channels, - bool encrypted, bool interop, MXFMetadata const & metadata ) - : MXFAsset (directory, mxf_name, progress, fps, intrinsic_duration, encrypted) + : MXFAsset (directory, mxf_name, progress, fps, intrinsic_duration) , _channels (channels) , _sampling_rate (0) { @@ -104,8 +102,8 @@ SoundAsset::SoundAsset (string directory, string mxf_name) _intrinsic_duration = desc.ContainerDuration; } -SoundAsset::SoundAsset (string directory, string mxf_name, int fps, int channels, int sampling_rate, bool encrypted) - : MXFAsset (directory, mxf_name, 0, fps, 0, encrypted) +SoundAsset::SoundAsset (string directory, string mxf_name, int fps, int channels, int sampling_rate) + : MXFAsset (directory, mxf_name, 0, fps, 0) , _channels (channels) , _sampling_rate (sampling_rate) { diff --git a/src/sound_asset.h b/src/sound_asset.h index cf015c30..339e67f8 100644 --- a/src/sound_asset.h +++ b/src/sound_asset.h @@ -79,7 +79,6 @@ public: * @param length Length in frames. * @param start_frame Frame in the source to start writing from. * @param intrinsic_duration Length of the whole asset in frames. - * @param encrypted true if asset should be encrypted. * Note that this is different to entry_point in that the asset will contain no data before start_frame. */ SoundAsset ( @@ -89,7 +88,6 @@ public: boost::signals2::signal<void (float)>* progress, int fps, int intrinsic_duration, - bool encrypted, bool interop, MXFMetadata const & metadata = MXFMetadata () ); @@ -103,7 +101,6 @@ public: * @param fps Frames per second. * @param intrinsic_duration Length of the whole asset in frames. * @param channels Number of audio channels. - * @param encrypted true if asset should be encrypted. */ SoundAsset ( boost::function<std::string (Channel)> get_path, @@ -113,7 +110,6 @@ public: int fps, int intrinsic_duration, int channels, - bool encrypted, bool interop, MXFMetadata const & metadata = MXFMetadata () ); @@ -128,8 +124,7 @@ public: std::string mxf_name, int fps, int channels, - int sampling_rate, - bool encrypted + int sampling_rate ); boost::shared_ptr<SoundAssetWriter> start_write (bool, MXFMetadata const & metadata = MXFMetadata ()); diff --git a/src/wscript b/src/wscript index 904b367d..8634125c 100644 --- a/src/wscript +++ b/src/wscript @@ -20,6 +20,7 @@ def build(bld): gamma_lut.cc image.cc kdm.cc + key.cc metadata.cc mxf_asset.cc picture_asset.cc @@ -55,6 +56,7 @@ def build(bld): gamma_lut.h image.h kdm.h + key.h lut.h lut_cache.h metadata.h diff --git a/test/certificates_test.cc b/test/certificates_test.cc index 40e550cb..ba29549b 100644 --- a/test/certificates_test.cc +++ b/test/certificates_test.cc @@ -21,9 +21,9 @@ BOOST_AUTO_TEST_CASE (certificates) { libdcp::CertificateChain c; - c.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate ("test/ref/crypt/ca.self-signed.pem"))); - c.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate ("test/ref/crypt/intermediate.signed.pem"))); - c.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate ("test/ref/crypt/leaf.signed.pem"))); + c.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (boost::filesystem::path ("test/ref/crypt/ca.self-signed.pem")))); + c.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (boost::filesystem::path ("test/ref/crypt/intermediate.signed.pem")))); + c.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (boost::filesystem::path ("test/ref/crypt/leaf.signed.pem")))); list<shared_ptr<libdcp::Certificate> > leaf_to_root = c.leaf_to_root (); @@ -71,4 +71,7 @@ BOOST_AUTO_TEST_CASE (certificates) "dnQualifier=ndND9A/cODo2rTdrbLVmfQnoaSc=,CN=.smpte-430-2.ROOT.NOT_FOR_PRODUCTION,OU=example.org,O=example.org" ); + /* Check that reconstruction from a string works */ + libdcp::Certificate test (c.root()->certificate (true)); + BOOST_CHECK_EQUAL (test.certificate(), c.root()->certificate()); } diff --git a/test/dcp_test.cc b/test/dcp_test.cc index 1b943694..d4207d5a 100644 --- a/test/dcp_test.cc +++ b/test/dcp_test.cc @@ -45,7 +45,6 @@ BOOST_AUTO_TEST_CASE (dcp_test) &d.Progress, 24, 24, - false, libdcp::Size (32, 32), false, mxf_meta @@ -60,7 +59,6 @@ BOOST_AUTO_TEST_CASE (dcp_test) 24, 2, false, - false, mxf_meta )); diff --git a/test/encryption_test.cc b/test/encryption_test.cc index 1b0de19a..3501befc 100644 --- a/test/encryption_test.cc +++ b/test/encryption_test.cc @@ -39,9 +39,9 @@ BOOST_AUTO_TEST_CASE (encryption) libdcp::DCP d ("build/test/DCP/bar"); libdcp::CertificateChain chain; - chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate ("build/test/signer/ca.self-signed.pem"))); - chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate ("build/test/signer/intermediate.signed.pem"))); - chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate ("build/test/signer/leaf.signed.pem"))); + chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (boost::filesystem::path ("build/test/signer/ca.self-signed.pem")))); + chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (boost::filesystem::path ("build/test/signer/intermediate.signed.pem")))); + chain.add (shared_ptr<libdcp::Certificate> (new libdcp::Certificate (boost::filesystem::path ("build/test/signer/leaf.signed.pem")))); shared_ptr<libdcp::Signer> signer ( new libdcp::Signer ( @@ -59,12 +59,13 @@ BOOST_AUTO_TEST_CASE (encryption) &d.Progress, 24, 24, - true, libdcp::Size (32, 32), false, mxf_metadata )); + mp->set_key (libdcp::Key ()); + shared_ptr<libdcp::SoundAsset> ms (new libdcp::SoundAsset ( wav, "build/test/bar", @@ -73,10 +74,11 @@ BOOST_AUTO_TEST_CASE (encryption) 24, 24, 2, - true, false, mxf_metadata )); + + ms->set_key (libdcp::Key ()); cpl->add_reel (shared_ptr<libdcp::Reel> (new libdcp::Reel (mp, ms, shared_ptr<libdcp::SubtitleAsset> ()))); d.add_cpl (cpl); diff --git a/test/error_test.cc b/test/error_test.cc index 380363b4..5477ca5a 100644 --- a/test/error_test.cc +++ b/test/error_test.cc @@ -29,12 +29,12 @@ BOOST_AUTO_TEST_CASE (error_test) /* Trying to create video/audio MXFs using a non-existant file should throw an exception */ BOOST_CHECK_THROW ( - new libdcp::MonoPictureAsset (p, "build/test/fred", "video.mxf", &d.Progress, 24, 24, false, libdcp::Size (32, 32), false), + new libdcp::MonoPictureAsset (p, "build/test/fred", "video.mxf", &d.Progress, 24, 24, libdcp::Size (32, 32), false), libdcp::FileError ); BOOST_CHECK_THROW ( - new libdcp::SoundAsset (p, "build/test/fred", "audio.mxf", &d.Progress, 24, 24, false, false), + new libdcp::SoundAsset (p, "build/test/fred", "audio.mxf", &d.Progress, 24, 24, false), libdcp::FileError ); } diff --git a/test/kdm_test.cc b/test/kdm_test.cc index f536e189..a85bada7 100644 --- a/test/kdm_test.cc +++ b/test/kdm_test.cc @@ -26,19 +26,19 @@ BOOST_AUTO_TEST_CASE (kdm_test) "test/data/private.key" ); - list<libdcp::KDMCipher> ciphers = kdm.ciphers (); + list<libdcp::KDMKey> keys = kdm.keys (); - BOOST_CHECK_EQUAL (ciphers.size(), 2); - - BOOST_CHECK_EQUAL (ciphers.front().cpl_id(), "eece17de-77e8-4a55-9347-b6bab5724b9f"); - BOOST_CHECK_EQUAL (ciphers.front().key_id(), "4ac4f922-8239-4831-b23b-31426d0542c4"); - BOOST_CHECK_EQUAL (ciphers.front().not_valid_before(), "2013-07-06T20:04:58+00:00"); - BOOST_CHECK_EQUAL (ciphers.front().not_valid_after(), "2023-07-02T20:04:56+00:00"); - BOOST_CHECK_EQUAL (ciphers.front().key_string(), "8a2729c3e5b65c45d78305462104c3fb"); - - BOOST_CHECK_EQUAL (ciphers.back().cpl_id(), "eece17de-77e8-4a55-9347-b6bab5724b9f"); - BOOST_CHECK_EQUAL (ciphers.back().key_id(), "73baf5de-e195-4542-ab28-8a465f7d4079"); - BOOST_CHECK_EQUAL (ciphers.back().not_valid_before(), "2013-07-06T20:04:58+00:00"); - BOOST_CHECK_EQUAL (ciphers.back().not_valid_after(), "2023-07-02T20:04:56+00:00"); - BOOST_CHECK_EQUAL (ciphers.back().key_string(), "5327fb7ec2e807bd57059615bf8a169d"); + BOOST_CHECK_EQUAL (keys.size(), 2); + + BOOST_CHECK_EQUAL (keys.front().cpl_id(), "eece17de-77e8-4a55-9347-b6bab5724b9f"); + BOOST_CHECK_EQUAL (keys.front().key_id(), "4ac4f922-8239-4831-b23b-31426d0542c4"); + BOOST_CHECK_EQUAL (keys.front().not_valid_before(), "2013-07-06T20:04:58+00:00"); + BOOST_CHECK_EQUAL (keys.front().not_valid_after(), "2023-07-02T20:04:56+00:00"); + BOOST_CHECK_EQUAL (keys.front().key().hex(), "8a2729c3e5b65c45d78305462104c3fb"); + + BOOST_CHECK_EQUAL (keys.back().cpl_id(), "eece17de-77e8-4a55-9347-b6bab5724b9f"); + BOOST_CHECK_EQUAL (keys.back().key_id(), "73baf5de-e195-4542-ab28-8a465f7d4079"); + BOOST_CHECK_EQUAL (keys.back().not_valid_before(), "2013-07-06T20:04:58+00:00"); + BOOST_CHECK_EQUAL (keys.back().not_valid_after(), "2023-07-02T20:04:56+00:00"); + BOOST_CHECK_EQUAL (keys.back().key().hex(), "5327fb7ec2e807bd57059615bf8a169d"); } diff --git a/test/recovery_test.cc b/test/recovery_test.cc index 277ea678..d8ffea6a 100644 --- a/test/recovery_test.cc +++ b/test/recovery_test.cc @@ -41,7 +41,7 @@ BOOST_AUTO_TEST_CASE (recovery) boost::filesystem::remove_all ("build/test/baz"); boost::filesystem::create_directories ("build/test/baz"); - shared_ptr<libdcp::MonoPictureAsset> mp (new libdcp::MonoPictureAsset ("build/test/baz", "video1.mxf", 24, libdcp::Size (32, 32), false)); + shared_ptr<libdcp::MonoPictureAsset> mp (new libdcp::MonoPictureAsset ("build/test/baz", "video1.mxf", 24, libdcp::Size (32, 32))); shared_ptr<libdcp::PictureAssetWriter> writer = mp->start_write (false, false); int written_size = 0; @@ -69,7 +69,7 @@ BOOST_AUTO_TEST_CASE (recovery) Kumu::ResetTestRNG (); #endif - mp.reset (new libdcp::MonoPictureAsset ("build/test/baz", "video2.mxf", 24, libdcp::Size (32, 32), false)); + mp.reset (new libdcp::MonoPictureAsset ("build/test/baz", "video2.mxf", 24, libdcp::Size (32, 32))); writer = mp->start_write (true, false); writer->write (data, size); |
