Make some not-so-important CPL read errors non-fatal (DoM #2797).
[libdcp.git] / src / decrypted_kdm.cc
1 /*
2     Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
3
4     This file is part of libdcp.
5
6     libdcp is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 2 of the License, or
9     (at your option) any later version.
10
11     libdcp is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15
16     You should have received a copy of the GNU General Public License
17     along with libdcp.  If not, see <http://www.gnu.org/licenses/>.
18
19     In addition, as a special exception, the copyright holders give
20     permission to link the code of portions of this program with the
21     OpenSSL library under certain conditions as described in each
22     individual source file, and distribute linked combinations
23     including the two.
24
25     You must obey the GNU General Public License in all respects
26     for all of the code used other than OpenSSL.  If you modify
27     file(s) with this exception, you may extend this exception to your
28     version of the file(s), but you are not obligated to do so.  If you
29     do not wish to do so, delete this exception statement from your
30     version.  If you delete this exception statement from all source
31     files in the program, then also delete it here.
32 */
33
34
35 /** @file  src/decrypted_kdm.cc
36  *  @brief DecryptedKDM class
37  */
38
39
40 #include "certificate_chain.h"
41 #include "compose.hpp"
42 #include "cpl.h"
43 #include "dcp_assert.h"
44 #include "decrypted_kdm.h"
45 #include "decrypted_kdm_key.h"
46 #include "encrypted_kdm.h"
47 #include "exceptions.h"
48 #include "reel_asset.h"
49 #include "reel_file_asset.h"
50 #include "util.h"
51 #include <asdcp/AS_DCP.h>
52 #include <asdcp/KM_util.h>
53 #include <openssl/rsa.h>
54 #include <openssl/pem.h>
55 #include <openssl/err.h>
56
57
58 using std::list;
59 using std::vector;
60 using std::string;
61 using std::setw;
62 using std::setfill;
63 using std::hex;
64 using std::pair;
65 using std::map;
66 using std::shared_ptr;
67 using boost::optional;
68 using namespace dcp;
69
70
71 /* Magic value specified by SMPTE S430-1-2006 */
72 static uint8_t smpte_structure_id[] = { 0xf1, 0xdc, 0x12, 0x44, 0x60, 0x16, 0x9a, 0x0e, 0x85, 0xbc, 0x30, 0x06, 0x42, 0xf8, 0x66, 0xab };
73
74
75 static void
76 put (uint8_t ** d, string s)
77 {
78         memcpy (*d, s.c_str(), s.length());
79         (*d) += s.length();
80 }
81
82
83 static void
84 put (uint8_t ** d, uint8_t const * s, int N)
85 {
86         memcpy (*d, s, N);
87         (*d) += N;
88 }
89
90
91 void
92 DecryptedKDM::put_uuid (uint8_t ** d, string id)
93 {
94         /* 32 hex digits plus some hyphens */
95         DCP_ASSERT (id.length() == 36);
96 #ifdef LIBDCP_WINDOWS
97         __mingw_sscanf (
98 #else
99         sscanf (
100 #endif
101                 id.c_str(),
102                 "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
103                 *d + 0, *d + 1, *d + 2, *d + 3, *d + 4, *d + 5, *d + 6, *d + 7,
104                 *d + 8, *d + 9, *d + 10, *d + 11, *d + 12, *d + 13, *d + 14, *d + 15
105                 );
106
107         *d += 16;
108 }
109
110
111 string
112 DecryptedKDM::get_uuid (unsigned char ** p)
113 {
114         char buffer[37];
115 #ifdef LIBDCP_WINDOWS
116         __mingw_snprintf (
117 #else
118         snprintf (
119 #endif
120                 buffer, sizeof(buffer), "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
121                 (*p)[0], (*p)[1], (*p)[2], (*p)[3], (*p)[4], (*p)[5], (*p)[6], (*p)[7],
122                 (*p)[8], (*p)[9], (*p)[10], (*p)[11], (*p)[12], (*p)[13], (*p)[14], (*p)[15]
123                 );
124
125         *p += 16;
126         return buffer;
127 }
128
129
130 static string
131 get (uint8_t ** p, int N)
132 {
133         string g;
134         for (int i = 0; i < N; ++i) {
135                 g += **p;
136                 (*p)++;
137         }
138
139         return g;
140 }
141
142
143 DecryptedKDM::DecryptedKDM (EncryptedKDM const & kdm, string private_key)
144 {
145         /* Read the private key */
146
147         auto bio = BIO_new_mem_buf (const_cast<char *>(private_key.c_str()), -1);
148         if (!bio) {
149                 throw MiscError ("could not create memory BIO");
150         }
151
152         auto rsa = PEM_read_bio_RSAPrivateKey (bio, 0, 0, 0);
153         if (!rsa) {
154                 throw FileError ("could not read RSA private key file", private_key, errno);
155         }
156
157         /* Use the private key to decrypt the keys */
158
159         bool first = true;
160
161         for (auto const& i: kdm.keys()) {
162                 /* Decode the base-64-encoded cipher value from the KDM */
163                 unsigned char cipher_value[256];
164                 int const cipher_value_len = base64_decode (i, cipher_value, sizeof (cipher_value));
165
166                 /* Decrypt it */
167                 auto decrypted = new unsigned char[RSA_size(rsa)];
168                 int const decrypted_len = RSA_private_decrypt (cipher_value_len, cipher_value, decrypted, rsa, RSA_PKCS1_OAEP_PADDING);
169                 if (decrypted_len == -1) {
170                         delete[] decrypted;
171 #if OPENSSL_VERSION_NUMBER > 0x10100000L
172                         throw KDMDecryptionError (ERR_error_string (ERR_get_error(), 0), cipher_value_len, RSA_bits(rsa));
173 #else
174                         throw KDMDecryptionError (ERR_error_string (ERR_get_error(), 0), cipher_value_len, rsa->n->dmax);
175 #endif
176                 }
177
178                 dcp::LocalTime not_valid_before;
179                 dcp::LocalTime not_valid_after;
180
181                 unsigned char* p = decrypted;
182                 switch (decrypted_len) {
183                 case 134:
184                 {
185                         /* Inter-op */
186                         /* 0 is structure id (fixed sequence specified by standard) [16 bytes] */
187                         p += 16;
188                         /* 16 is is signer thumbprint [20 bytes] */
189                         p += 20;
190                         /* 36 is CPL id [16 bytes] */
191                         string const cpl_id = get_uuid (&p);
192                         /* 52 is key id [16 bytes] */
193                         string const key_id = get_uuid (&p);
194                         /* 68 is not-valid-before (a string) [25 bytes] */
195                         not_valid_before = dcp::LocalTime(std::string(reinterpret_cast<char*>(p), 25));
196                         p += 25;
197                         /* 93 is not-valid-after (a string) [25 bytes] */
198                         not_valid_after = dcp::LocalTime(std::string(reinterpret_cast<char*>(p), 25));
199                         p += 25;
200                         /* 118 is the key [ASDCP::KeyLen bytes] */
201                         add_key (optional<string>(), key_id, Key(p), cpl_id, Standard::INTEROP);
202                         break;
203                 }
204                 case 138:
205                 {
206                         /* SMPTE */
207                         /* 0 is structure id (fixed sequence specified by standard) [16 bytes] */
208                         DCP_ASSERT (memcmp (p, smpte_structure_id, 16) == 0);
209                         p += 16;
210                         /* 16 is is signer thumbprint [20 bytes] */
211                         p += 20;
212                         /* 36 is CPL id [16 bytes] */
213                         string const cpl_id = get_uuid (&p);
214                         /* 52 is key type [4 bytes] */
215                         string const key_type = get (&p, 4);
216                         /* 56 is key id [16 bytes] */
217                         string const key_id = get_uuid (&p);
218                         /* 72 is not-valid-before (a string) [25 bytes] */
219                         not_valid_before = dcp::LocalTime(std::string(reinterpret_cast<char*>(p), 25));
220                         p += 25;
221                         /* 97 is not-valid-after (a string) [25 bytes] */
222                         not_valid_after = dcp::LocalTime(std::string(reinterpret_cast<char*>(p), 25));
223                         p += 25;
224                         /* 112 is the key [ASDCP::KeyLen bytes] */
225                         add_key (key_type, key_id, Key(p), cpl_id, Standard::SMPTE);
226                         break;
227                 }
228                 default:
229                         DCP_ASSERT (false);
230                 }
231
232                 delete[] decrypted;
233
234                 if (first) {
235                         _not_valid_before = not_valid_before;
236                         _not_valid_after = not_valid_after;
237                         first = false;
238                 } else {
239                         if (not_valid_before != _not_valid_before || not_valid_after != _not_valid_after) {
240                                 throw InconsistentValidityPeriodError();
241                         }
242                 }
243         }
244
245         RSA_free (rsa);
246         BIO_free (bio);
247
248         _annotation_text = kdm.annotation_text ();
249         _content_title_text = kdm.content_title_text ();
250         _issue_date = kdm.issue_date ();
251 }
252
253
254 DecryptedKDM::DecryptedKDM (
255         LocalTime not_valid_before,
256         LocalTime not_valid_after,
257         string annotation_text,
258         string content_title_text,
259         string issue_date
260         )
261         : _not_valid_before (not_valid_before)
262         , _not_valid_after (not_valid_after)
263         , _annotation_text (annotation_text)
264         , _content_title_text (content_title_text)
265         , _issue_date (issue_date)
266 {
267
268 }
269
270
271 DecryptedKDM::DecryptedKDM (
272         string cpl_id,
273         map<shared_ptr<const ReelFileAsset>, Key> keys,
274         LocalTime not_valid_before,
275         LocalTime not_valid_after,
276         string annotation_text,
277         string content_title_text,
278         string issue_date
279         )
280         : _not_valid_before (not_valid_before)
281         , _not_valid_after (not_valid_after)
282         , _annotation_text (annotation_text)
283         , _content_title_text (content_title_text)
284         , _issue_date (issue_date)
285 {
286         for (auto const& i: keys) {
287                 add_key (i.first->key_type(), i.first->key_id().get(), i.second, cpl_id, Standard::SMPTE);
288         }
289 }
290
291
292 DecryptedKDM::DecryptedKDM (
293         shared_ptr<const CPL> cpl,
294         Key key,
295         LocalTime not_valid_before,
296         LocalTime not_valid_after,
297         string annotation_text,
298         string content_title_text,
299         string issue_date
300         )
301         : _not_valid_before (not_valid_before)
302         , _not_valid_after (not_valid_after)
303         , _annotation_text (annotation_text)
304         , _content_title_text (content_title_text)
305         , _issue_date (issue_date)
306 {
307         /* Create DecryptedKDMKey objects for each encryptable asset */
308         bool did_one = false;
309         for (auto i: cpl->reel_file_assets()) {
310                 if (i->encryptable()) {
311                         add_key (i->key_type().get(), i->key_id().get(), key, cpl->id(), Standard::SMPTE);
312                         did_one = true;
313                 }
314         }
315
316         if (!did_one) {
317                 throw NotEncryptedError (cpl->id ());
318         }
319 }
320
321
322 void
323 DecryptedKDM::add_key (optional<string> type, string key_id, Key key, string cpl_id, Standard standard)
324 {
325         _keys.push_back (DecryptedKDMKey (type, key_id, key, cpl_id, standard));
326 }
327
328
329 void
330 DecryptedKDM::add_key (DecryptedKDMKey key)
331 {
332         _keys.push_back (key);
333 }
334
335
336 EncryptedKDM
337 DecryptedKDM::encrypt (
338         shared_ptr<const CertificateChain> signer,
339         Certificate recipient,
340         vector<string> trusted_devices,
341         Formulation formulation,
342         bool disable_forensic_marking_picture,
343         optional<int> disable_forensic_marking_audio
344         ) const
345 {
346         DCP_ASSERT (!_keys.empty ());
347
348         for (auto i: signer->leaf_to_root()) {
349                 if (day_greater_than_or_equal(i.not_before(), _not_valid_before)) {
350                         throw BadKDMDateError (true);
351                 } else if (day_less_than_or_equal(i.not_after(), _not_valid_after)) {
352                         throw BadKDMDateError (false);
353                 }
354         }
355
356         vector<pair<string, string>> key_ids;
357         vector<string> keys;
358         for (auto const& i: _keys) {
359                 /* We're making SMPTE keys so we must have a type for each one */
360                 DCP_ASSERT (i.type());
361                 key_ids.push_back (make_pair (i.type().get(), i.id ()));
362
363                 /* XXX: SMPTE only */
364                 uint8_t block[138];
365                 uint8_t* p = block;
366
367                 put (&p, smpte_structure_id, 16);
368
369                 base64_decode (signer->leaf().thumbprint (), p, 20);
370                 p += 20;
371
372                 put_uuid (&p, i.cpl_id ());
373                 put (&p, i.type().get());
374                 put_uuid (&p, i.id ());
375                 put (&p, _not_valid_before.as_string ());
376                 put (&p, _not_valid_after.as_string ());
377                 put (&p, i.key().value(), ASDCP::KeyLen);
378
379                 /* Encrypt using the projector's public key */
380                 RSA* rsa = recipient.public_key ();
381                 unsigned char encrypted[RSA_size(rsa)];
382                 int const encrypted_len = RSA_public_encrypt (p - block, block, encrypted, rsa, RSA_PKCS1_OAEP_PADDING);
383                 if (encrypted_len == -1) {
384                         throw MiscError (String::compose ("Could not encrypt KDM (%1)", ERR_error_string (ERR_get_error(), 0)));
385                 }
386
387                 /* Lazy overallocation */
388                 char out[encrypted_len * 2];
389                 Kumu::base64encode (encrypted, encrypted_len, out, encrypted_len * 2);
390                 int const N = strlen (out);
391                 string lines;
392                 for (int i = 0; i < N; ++i) {
393                         if (i > 0 && (i % 64) == 0) {
394                                 lines += "\n";
395                         }
396                         lines += out[i];
397                 }
398
399                 keys.push_back (lines);
400         }
401
402         return EncryptedKDM (
403                 signer,
404                 recipient,
405                 trusted_devices,
406                 _keys.front().cpl_id (),
407                 _content_title_text,
408                 _annotation_text,
409                 _not_valid_before,
410                 _not_valid_after,
411                 formulation,
412                 disable_forensic_marking_picture,
413                 disable_forensic_marking_audio,
414                 key_ids,
415                 keys
416                 );
417 }