2 Copyright (C) 2013-2021 Carl Hetherington <cth@carlh.net>
4 This file is part of libdcp.
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.
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.
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/>.
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
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.
35 /** @file src/decrypted_kdm.cc
36 * @brief DecryptedKDM class
40 #include "decrypted_kdm.h"
41 #include "decrypted_kdm_key.h"
42 #include "encrypted_kdm.h"
44 #include "reel_asset.h"
46 #include "exceptions.h"
48 #include "certificate_chain.h"
49 #include "dcp_assert.h"
50 #include "compose.hpp"
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>
66 using std::shared_ptr;
67 using boost::optional;
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 };
76 put (uint8_t ** d, string s)
78 memcpy (*d, s.c_str(), s.length());
84 put (uint8_t ** d, uint8_t const * s, int N)
92 DecryptedKDM::put_uuid (uint8_t ** d, string id)
94 /* 32 hex digits plus some hyphens */
95 DCP_ASSERT (id.length() == 36);
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
112 DecryptedKDM::get_uuid (unsigned char ** p)
115 #ifdef LIBDCP_WINDOWS
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]
131 get (uint8_t ** p, int N)
134 for (int i = 0; i < N; ++i) {
143 DecryptedKDM::DecryptedKDM (EncryptedKDM const & kdm, string private_key)
145 /* Read the private key */
147 auto bio = BIO_new_mem_buf (const_cast<char *>(private_key.c_str()), -1);
149 throw MiscError ("could not create memory BIO");
152 auto rsa = PEM_read_bio_RSAPrivateKey (bio, 0, 0, 0);
154 throw FileError ("could not read RSA private key file", private_key, errno);
157 /* Use the private key to decrypt the keys */
159 for (auto const& i: kdm.keys()) {
160 /* Decode the base-64-encoded cipher value from the KDM */
161 unsigned char cipher_value[256];
162 int const cipher_value_len = base64_decode (i, cipher_value, sizeof (cipher_value));
165 auto decrypted = new unsigned char[RSA_size(rsa)];
166 int const decrypted_len = RSA_private_decrypt (cipher_value_len, cipher_value, decrypted, rsa, RSA_PKCS1_OAEP_PADDING);
167 if (decrypted_len == -1) {
169 #if OPENSSL_VERSION_NUMBER > 0x10100000L
170 throw KDMDecryptionError (ERR_error_string (ERR_get_error(), 0), cipher_value_len, RSA_bits(rsa));
172 throw KDMDecryptionError (ERR_error_string (ERR_get_error(), 0), cipher_value_len, rsa->n->dmax);
176 unsigned char* p = decrypted;
177 switch (decrypted_len) {
181 /* 0 is structure id (fixed sequence specified by standard) [16 bytes] */
183 /* 16 is is signer thumbprint [20 bytes] */
185 /* 36 is CPL id [16 bytes] */
186 string const cpl_id = get_uuid (&p);
187 /* 52 is key id [16 bytes] */
188 string const key_id = get_uuid (&p);
189 /* 68 is not-valid-before (a string) [25 bytes] */
191 /* 93 is not-valid-after (a string) [25 bytes] */
193 /* 118 is the key [ASDCP::KeyLen bytes] */
194 add_key (optional<string>(), key_id, Key(p), cpl_id, Standard::INTEROP);
200 /* 0 is structure id (fixed sequence specified by standard) [16 bytes] */
201 DCP_ASSERT (memcmp (p, smpte_structure_id, 16) == 0);
203 /* 16 is is signer thumbprint [20 bytes] */
205 /* 36 is CPL id [16 bytes] */
206 string const cpl_id = get_uuid (&p);
207 /* 52 is key type [4 bytes] */
208 string const key_type = get (&p, 4);
209 /* 56 is key id [16 bytes] */
210 string const key_id = get_uuid (&p);
211 /* 72 is not-valid-before (a string) [25 bytes] */
213 /* 97 is not-valid-after (a string) [25 bytes] */
215 /* 112 is the key [ASDCP::KeyLen bytes] */
216 add_key (key_type, key_id, Key(p), cpl_id, Standard::SMPTE);
229 _annotation_text = kdm.annotation_text ();
230 _content_title_text = kdm.content_title_text ();
231 _issue_date = kdm.issue_date ();
235 DecryptedKDM::DecryptedKDM (
236 LocalTime not_valid_before,
237 LocalTime not_valid_after,
238 string annotation_text,
239 string content_title_text,
242 : _not_valid_before (not_valid_before)
243 , _not_valid_after (not_valid_after)
244 , _annotation_text (annotation_text)
245 , _content_title_text (content_title_text)
246 , _issue_date (issue_date)
252 DecryptedKDM::DecryptedKDM (
254 map<shared_ptr<const ReelMXF>, Key> keys,
255 LocalTime not_valid_before,
256 LocalTime not_valid_after,
257 string annotation_text,
258 string content_title_text,
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)
267 for (map<shared_ptr<const ReelMXF>, Key>::const_iterator i = keys.begin(); i != keys.end(); ++i) {
268 add_key (i->first->key_type(), i->first->key_id().get(), i->second, cpl_id, Standard::SMPTE);
273 DecryptedKDM::DecryptedKDM (
274 shared_ptr<const CPL> cpl,
276 LocalTime not_valid_before,
277 LocalTime not_valid_after,
278 string annotation_text,
279 string content_title_text,
282 : _not_valid_before (not_valid_before)
283 , _not_valid_after (not_valid_after)
284 , _annotation_text (annotation_text)
285 , _content_title_text (content_title_text)
286 , _issue_date (issue_date)
288 /* Create DecryptedKDMKey objects for each encryptable asset */
289 bool did_one = false;
290 for (auto i: cpl->reel_mxfs()) {
292 add_key (i->key_type(), i->key_id().get(), key, cpl->id(), Standard::SMPTE);
298 throw NotEncryptedError (cpl->id ());
304 DecryptedKDM::add_key (optional<string> type, string key_id, Key key, string cpl_id, Standard standard)
306 _keys.push_back (DecryptedKDMKey (type, key_id, key, cpl_id, standard));
311 DecryptedKDM::add_key (DecryptedKDMKey key)
313 _keys.push_back (key);
318 DecryptedKDM::encrypt (
319 shared_ptr<const CertificateChain> signer,
320 Certificate recipient,
321 vector<string> trusted_devices,
322 Formulation formulation,
323 bool disable_forensic_marking_picture,
324 optional<int> disable_forensic_marking_audio
327 DCP_ASSERT (!_keys.empty ());
329 for (auto i: signer->leaf_to_root()) {
330 if (day_greater_than_or_equal(dcp::LocalTime(i.not_before()), _not_valid_before)) {
331 throw BadKDMDateError (true);
332 } else if (day_less_than_or_equal(dcp::LocalTime(i.not_after()), _not_valid_after)) {
333 throw BadKDMDateError (false);
337 vector<pair<string, string>> key_ids;
339 for (auto const& i: _keys) {
340 /* We're making SMPTE keys so we must have a type for each one */
341 DCP_ASSERT (i.type());
342 key_ids.push_back (make_pair (i.type().get(), i.id ()));
344 /* XXX: SMPTE only */
348 put (&p, smpte_structure_id, 16);
350 base64_decode (signer->leaf().thumbprint (), p, 20);
353 put_uuid (&p, i.cpl_id ());
354 put (&p, i.type().get());
355 put_uuid (&p, i.id ());
356 put (&p, _not_valid_before.as_string ());
357 put (&p, _not_valid_after.as_string ());
358 put (&p, i.key().value(), ASDCP::KeyLen);
360 /* Encrypt using the projector's public key */
361 RSA* rsa = recipient.public_key ();
362 unsigned char encrypted[RSA_size(rsa)];
363 int const encrypted_len = RSA_public_encrypt (p - block, block, encrypted, rsa, RSA_PKCS1_OAEP_PADDING);
364 if (encrypted_len == -1) {
365 throw MiscError (String::compose ("Could not encrypt KDM (%1)", ERR_error_string (ERR_get_error(), 0)));
368 /* Lazy overallocation */
369 char out[encrypted_len * 2];
370 Kumu::base64encode (encrypted, encrypted_len, out, encrypted_len * 2);
371 int const N = strlen (out);
373 for (int i = 0; i < N; ++i) {
374 if (i > 0 && (i % 64) == 0) {
380 keys.push_back (lines);
383 string device_list_description = recipient.subject_common_name ();
384 if (device_list_description.find (".") != string::npos) {
385 device_list_description = device_list_description.substr (device_list_description.find (".") + 1);
388 return EncryptedKDM (
392 _keys.front().cpl_id (),
398 disable_forensic_marking_picture,
399 disable_forensic_marking_audio,