Enable encryption of SMPTE subtitles.
authorCarl Hetherington <cth@carlh.net>
Sat, 13 Aug 2016 22:35:39 +0000 (23:35 +0100)
committerCarl Hetherington <cth@carlh.net>
Sat, 13 Aug 2016 22:35:39 +0000 (23:35 +0100)
Separate out EncryptionContext class to use in SMPTESubtitleAsset::write().

src/asset_writer.cc
src/asset_writer.h
src/encryption_context.cc [new file with mode: 0644]
src/encryption_context.h [new file with mode: 0644]
src/mono_picture_asset_writer.cc
src/smpte_subtitle_asset.cc
src/sound_asset_writer.cc
src/stereo_picture_asset_writer.cc
src/wscript

index 8ce05d5b2b536ec4045c9c6f50961c8aa789a9bd..b9bac1874335cd770c7d371401cc0ae76fee5027 100644 (file)
@@ -38,6 +38,7 @@
 #include "asset_writer.h"
 #include "mxf.h"
 #include "dcp_assert.h"
+#include "encryption_context.h"
 #include <asdcp/AS_DCP.h>
 #include <asdcp/KM_prng.h>
 
@@ -53,41 +54,9 @@ AssetWriter::AssetWriter (MXF* mxf, boost::filesystem::path file, Standard stand
        , _frames_written (0)
        , _finalized (false)
        , _started (false)
-       , _encryption_context (0)
-       , _hmac_context (0)
+       , _encryption_context (new EncryptionContext (mxf->key(), standard))
 {
-       if (mxf->key ()) {
-               _encryption_context = new ASDCP::AESEncContext;
-               if (ASDCP_FAILURE (_encryption_context->InitKey (mxf->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");
-               }
-
-               _hmac_context = new ASDCP::HMACContext;
-
-               ASDCP::LabelSet_t type;
-               if (standard == INTEROP) {
-                       type = ASDCP::LS_MXF_INTEROP;
-               } else {
-                       type = ASDCP::LS_MXF_SMPTE;
-               }
-
-               if (ASDCP_FAILURE (_hmac_context->InitKey (mxf->key()->value(), type))) {
-                       throw MiscError ("could not set up HMAC context");
-               }
-       }
-}
-
-AssetWriter::~AssetWriter ()
-{
-       delete _encryption_context;
-       delete _hmac_context;
 }
 
 /** @return true if anything was written by this writer */
index 80ce82b8719aa5a380a0e4f2c1a6b1a297faf92a..814405d4e77719151d36d977da153233034d9ee9 100644 (file)
 #include "types.h"
 #include <boost/filesystem.hpp>
 
-namespace ASDCP {
-       class AESEncContext;
-       class HMACContext;
-}
-
 namespace dcp {
 
 class MXF;
+class EncryptionContext;
 
 /** @class AssetWriter
  *  @brief Parent class for classes which can write MXF-based assets.
@@ -59,7 +55,7 @@ class MXF;
 class AssetWriter : public boost::noncopyable
 {
 public:
-       virtual ~AssetWriter ();
+       virtual ~AssetWriter () {}
        virtual bool finalize ();
 
        int64_t frames_written () const {
@@ -81,8 +77,7 @@ protected:
        bool _finalized;
        /** true if something has been written to this asset */
        bool _started;
-       ASDCP::AESEncContext* _encryption_context;
-       ASDCP::HMACContext* _hmac_context;
+       boost::shared_ptr<EncryptionContext> _encryption_context;
 };
 
 }
diff --git a/src/encryption_context.cc b/src/encryption_context.cc
new file mode 100644 (file)
index 0000000..7712a25
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+    Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+
+    This file is part of libdcp.
+
+    libdcp 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.
+
+    libdcp 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 libdcp.  If not, see <http://www.gnu.org/licenses/>.
+
+    In addition, as a special exception, the copyright holders give
+    permission to link the code of portions of this program with the
+    OpenSSL library under certain conditions as described in each
+    individual source file, and distribute linked combinations
+    including the two.
+
+    You must obey the GNU General Public License in all respects
+    for all of the code used other than OpenSSL.  If you modify
+    file(s) with this exception, you may extend this exception to your
+    version of the file(s), but you are not obligated to do so.  If you
+    do not wish to do so, delete this exception statement from your
+    version.  If you delete this exception statement from all source
+    files in the program, then also delete it here.
+*/
+
+#include "encryption_context.h"
+#include "exceptions.h"
+#include <asdcp/AS_DCP.h>
+#include <asdcp/KM_prng.h>
+
+using boost::optional;
+using namespace dcp;
+
+EncryptionContext::EncryptionContext (optional<Key> key, Standard standard)
+       : _encryption (0)
+       , _hmac (0)
+{
+       if (!key) {
+               return;
+       }
+
+       _encryption = new ASDCP::AESEncContext;
+       if (ASDCP_FAILURE (_encryption->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->SetIVec (rng.FillRandom (cbc_buffer, ASDCP::CBC_BLOCK_SIZE)))) {
+               throw MiscError ("could not set up CBC initialization vector");
+       }
+
+       _hmac = new ASDCP::HMACContext;
+
+       ASDCP::LabelSet_t type;
+       if (standard == INTEROP) {
+               type = ASDCP::LS_MXF_INTEROP;
+       } else {
+               type = ASDCP::LS_MXF_SMPTE;
+       }
+
+       if (ASDCP_FAILURE (_hmac->InitKey (key->value(), type))) {
+               throw MiscError ("could not set up HMAC context");
+       }
+}
+
+EncryptionContext::~EncryptionContext ()
+{
+       delete _encryption;
+       delete _hmac;
+}
diff --git a/src/encryption_context.h b/src/encryption_context.h
new file mode 100644 (file)
index 0000000..6817395
--- /dev/null
@@ -0,0 +1,64 @@
+/*
+    Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
+
+    This file is part of libdcp.
+
+    libdcp 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.
+
+    libdcp 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 libdcp.  If not, see <http://www.gnu.org/licenses/>.
+
+    In addition, as a special exception, the copyright holders give
+    permission to link the code of portions of this program with the
+    OpenSSL library under certain conditions as described in each
+    individual source file, and distribute linked combinations
+    including the two.
+
+    You must obey the GNU General Public License in all respects
+    for all of the code used other than OpenSSL.  If you modify
+    file(s) with this exception, you may extend this exception to your
+    version of the file(s), but you are not obligated to do so.  If you
+    do not wish to do so, delete this exception statement from your
+    version.  If you delete this exception statement from all source
+    files in the program, then also delete it here.
+*/
+
+#include "key.h"
+#include "types.h"
+#include <boost/optional.hpp>
+
+namespace ASDCP {
+       class AESEncContext;
+       class HMACContext;
+}
+
+namespace dcp {
+
+class EncryptionContext
+{
+public:
+       EncryptionContext (boost::optional<Key> key, Standard standard);
+       ~EncryptionContext ();
+
+       ASDCP::AESEncContext* encryption () const {
+               return _encryption;
+       }
+
+       ASDCP::HMACContext* hmac () const {
+               return _hmac;
+       }
+
+private:
+       ASDCP::AESEncContext* _encryption;
+       ASDCP::HMACContext* _hmac;
+};
+
+}
index 1ef079dcf9fd233373b1d69887be15cfcce6e65e..b6f8cc1b20e3f6b9dae0b29477ed7ea6d6357a45 100644 (file)
@@ -39,6 +39,7 @@
 #include "exceptions.h"
 #include "picture_asset.h"
 #include "dcp_assert.h"
+#include "encryption_context.h"
 #include <asdcp/AS_DCP.h>
 #include <asdcp/KM_fileio.h>
 
@@ -86,7 +87,7 @@ MonoPictureAssetWriter::write (uint8_t* data, int size)
        uint64_t const before_offset = _state->mxf_writer.Tell ();
 
        string hash;
-       ASDCP::Result_t const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _encryption_context, _hmac_context, &hash);
+       ASDCP::Result_t const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _encryption_context->encryption(), _encryption_context->hmac(), &hash);
        if (ASDCP_FAILURE (r)) {
                boost::throw_exception (MXFFileError ("error in writing video MXF", _file.string(), r));
        }
index 0c0181f42d5c1604252d55d37b4e9b40129fc71b..e0934ab5b71e69a2300f69e559c9d0d3d6844ccf 100644 (file)
@@ -44,6 +44,7 @@
 #include "dcp_assert.h"
 #include "util.h"
 #include "compose.hpp"
+#include "encryption_context.h"
 #include <asdcp/AS_DCP.h>
 #include <asdcp/KM_util.h>
 #include <libxml++/libxml++.h>
@@ -238,6 +239,8 @@ SMPTESubtitleAsset::xml_as_string () const
 void
 SMPTESubtitleAsset::write (boost::filesystem::path p) const
 {
+       EncryptionContext enc (key (), SMPTE);
+
        ASDCP::WriterInfo writer_info;
        fill_writer_info (&writer_info, _id, SMPTE);
 
@@ -271,7 +274,7 @@ SMPTESubtitleAsset::write (boost::filesystem::path p) const
        }
 
        /* XXX: no encryption */
-       r = writer.WriteTimedTextResource (xml_as_string ());
+       r = writer.WriteTimedTextResource (xml_as_string (), enc.encryption(), enc.hmac());
        if (ASDCP_FAILURE (r)) {
                boost::throw_exception (MXFFileError ("could not write XML to timed text resource", p.string(), r));
        }
@@ -285,7 +288,7 @@ SMPTESubtitleAsset::write (boost::filesystem::path p) const
                        ASDCP::TimedText::FrameBuffer buffer;
                        buffer.SetData (j->data.data().get(), j->data.size());
                        buffer.Size (j->data.size());
-                       r = writer.WriteAncillaryResource (buffer);
+                       r = writer.WriteAncillaryResource (buffer, enc.encryption(), enc.hmac());
                        if (ASDCP_FAILURE (r)) {
                                boost::throw_exception (MXFFileError ("could not write font to timed text resource", p.string(), r));
                        }
index b0d7bc7d98e9492f97ce3393ec4df9db77b03074..84ed778756e44af2ad1719d0b7a95a3205048d4f 100644 (file)
@@ -36,6 +36,7 @@
 #include "exceptions.h"
 #include "dcp_assert.h"
 #include "compose.hpp"
+#include "encryption_context.h"
 #include <asdcp/AS_DCP.h>
 
 using std::min;
@@ -127,7 +128,7 @@ SoundAssetWriter::write (float const * const * data, int frames)
 void
 SoundAssetWriter::write_current_frame ()
 {
-       ASDCP::Result_t const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _encryption_context, _hmac_context);
+       ASDCP::Result_t const r = _state->mxf_writer.WriteFrame (_state->frame_buffer, _encryption_context->encryption(), _encryption_context->hmac());
        if (ASDCP_FAILURE (r)) {
                boost::throw_exception (MiscError (String::compose ("could not write audio MXF frame (%1)", int (r))));
        }
index 6e43de100e95ac939af2372d3fd69ea21469c3f9..00a738de2f58442b23239dcf0f69a89c44a1676b 100644 (file)
@@ -35,6 +35,7 @@
 #include "exceptions.h"
 #include "dcp_assert.h"
 #include "picture_asset.h"
+#include "encryption_context.h"
 #include <asdcp/AS_DCP.h>
 #include <asdcp/KM_fileio.h>
 
@@ -87,8 +88,8 @@ StereoPictureAssetWriter::write (uint8_t* data, int size)
        Kumu::Result_t r = _state->mxf_writer.WriteFrame (
                _state->frame_buffer,
                _next_eye == EYE_LEFT ? ASDCP::JP2K::SP_LEFT : ASDCP::JP2K::SP_RIGHT,
-               _encryption_context,
-               _hmac_context,
+               _encryption_context->encryption(),
+               _encryption_context->hmac(),
                &hash
                );
 
index 247f4626ecd7cf0e31204b3bb9ef4b85216f98da..d76b1a5085eae557dbe47419140b8c2a90eed957 100644 (file)
@@ -49,6 +49,7 @@ def build(bld):
              decrypted_kdm.cc
              decrypted_kdm_key.cc
              encrypted_kdm.cc
+             encryption_context.cc
              exceptions.cc
              file.cc
              font_asset.cc
@@ -121,6 +122,7 @@ def build(bld):
               decrypted_kdm.h
               decrypted_kdm_key.h
               encrypted_kdm.h
+              encryption_context.h
               exceptions.h
               font_asset.h
               gamma_transfer_function.h