Support reading of encrypted subtitles.
[libdcp.git] / src / decrypted_kdm.cc
index b18d9a900b6c6ce0e5955401fe2941251bdb4de8..05ea73a383b3a34e4192bd0a75af45afbf82d1df 100644 (file)
@@ -1,20 +1,34 @@
 /*
     Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
 
-    This program is free software; you can redistribute it and/or modify
+    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.
 
-    This program is distributed in the hope that it will be useful,
+    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 this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
+    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 "decrypted_kdm.h"
@@ -27,9 +41,9 @@
 #include "cpl.h"
 #include "certificate_chain.h"
 #include "dcp_assert.h"
-#include "AS_DCP.h"
-#include "KM_util.h"
 #include "compose.hpp"
+#include <asdcp/AS_DCP.h>
+#include <asdcp/KM_util.h>
 #include <openssl/rsa.h>
 #include <openssl/pem.h>
 #include <openssl/err.h>
@@ -38,7 +52,6 @@
 using std::list;
 using std::vector;
 using std::string;
-using std::stringstream;
 using std::setw;
 using std::setfill;
 using std::hex;
@@ -60,34 +73,37 @@ put (uint8_t ** d, uint8_t const * s, int N)
         (*d) += N;
 }
 
-static void
-put_uuid (uint8_t ** d, string id)
+void
+DecryptedKDM::put_uuid (uint8_t ** d, string id)
 {
-        id.erase (std::remove (id.begin(), id.end(), '-'));
-        for (int i = 0; i < 32; i += 2) {
-                stringstream s;
-                s << id[i] << id[i + 1];
-                int h;
-                s >> hex >> h;
-                **d = h;
-                (*d)++;
-        }
+       /* 32 hex digits plus some hyphens */
+       DCP_ASSERT (id.length() == 36);
+#ifdef LIBDCP_WINDOWS
+       __mingw_sscanf (
+#else
+       sscanf (
+#endif
+               id.c_str(),
+               "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
+               *d + 0, *d + 1, *d + 2, *d + 3, *d + 4, *d + 5, *d + 6, *d + 7,
+               *d + 8, *d + 9, *d + 10, *d + 11, *d + 12, *d + 13, *d + 14, *d + 15
+               );
+
+       *d += 16;
 }
 
-static string
-get_uuid (unsigned char ** p)
+string
+DecryptedKDM::get_uuid (unsigned char ** p)
 {
-       stringstream g;
-
-       for (int i = 0; i < 16; ++i) {
-               g << setw(2) << setfill('0') << hex << static_cast<int> (**p);
-               (*p)++;
-               if (i == 3 || i == 5 || i == 7 || i == 9) {
-                       g << '-';
-               }
-       }
+       char buffer[37];
+       snprintf (
+               buffer, sizeof(buffer), "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
+               (*p)[0], (*p)[1], (*p)[2], (*p)[3], (*p)[4], (*p)[5], (*p)[6], (*p)[7],
+               (*p)[8], (*p)[9], (*p)[10], (*p)[11], (*p)[12], (*p)[13], (*p)[14], (*p)[15]
+               );
 
-       return g.str ();
+       *p += 16;
+       return buffer;
 }
 
 static string
@@ -287,15 +303,15 @@ DecryptedKDM::encrypt (shared_ptr<const CertificateChain> signer, Certificate re
                char out[encrypted_len * 2];
                Kumu::base64encode (encrypted, encrypted_len, out, encrypted_len * 2);
                int const N = strlen (out);
-               stringstream lines;
+               string lines;
                for (int i = 0; i < N; ++i) {
                        if (i > 0 && (i % 64) == 0) {
-                               lines << "\n";
+                               lines += "\n";
                        }
-                       lines << out[i];
+                       lines += out[i];
                }
 
-               keys.push_back (lines.str ());
+               keys.push_back (lines);
        }
 
        string device_list_description = recipient.subject_common_name ();