2 Copyright (C) 2013-2017 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.
34 #include "decrypted_kdm.h"
35 #include "decrypted_kdm_key.h"
36 #include "encrypted_kdm.h"
38 #include "reel_asset.h"
40 #include "exceptions.h"
42 #include "certificate_chain.h"
43 #include "dcp_assert.h"
44 #include "compose.hpp"
45 #include <asdcp/AS_DCP.h>
46 #include <asdcp/KM_util.h>
47 #include <openssl/rsa.h>
48 #include <openssl/pem.h>
49 #include <openssl/err.h>
50 #include <boost/foreach.hpp>
60 using boost::shared_ptr;
61 using boost::optional;
64 /* Magic value specified by SMPTE S430-1-2006 */
65 static uint8_t smpte_structure_id[] = { 0xf1, 0xdc, 0x12, 0x44, 0x60, 0x16, 0x9a, 0x0e, 0x85, 0xbc, 0x30, 0x06, 0x42, 0xf8, 0x66, 0xab };
68 put (uint8_t ** d, string s)
70 memcpy (*d, s.c_str(), s.length());
75 put (uint8_t ** d, uint8_t const * s, int N)
82 DecryptedKDM::put_uuid (uint8_t ** d, string id)
84 /* 32 hex digits plus some hyphens */
85 DCP_ASSERT (id.length() == 36);
92 "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
93 *d + 0, *d + 1, *d + 2, *d + 3, *d + 4, *d + 5, *d + 6, *d + 7,
94 *d + 8, *d + 9, *d + 10, *d + 11, *d + 12, *d + 13, *d + 14, *d + 15
101 DecryptedKDM::get_uuid (unsigned char ** p)
104 #ifdef LIBDCP_WINDOWS
109 buffer, sizeof(buffer), "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
110 (*p)[0], (*p)[1], (*p)[2], (*p)[3], (*p)[4], (*p)[5], (*p)[6], (*p)[7],
111 (*p)[8], (*p)[9], (*p)[10], (*p)[11], (*p)[12], (*p)[13], (*p)[14], (*p)[15]
119 get (uint8_t ** p, int N)
122 for (int i = 0; i < N; ++i) {
130 DecryptedKDM::DecryptedKDM (EncryptedKDM const & kdm, string private_key)
132 /* Read the private key */
134 BIO* bio = BIO_new_mem_buf (const_cast<char *> (private_key.c_str ()), -1);
136 throw MiscError ("could not create memory BIO");
139 RSA* rsa = PEM_read_bio_RSAPrivateKey (bio, 0, 0, 0);
141 throw FileError ("could not read RSA private key file", private_key, errno);
144 /* Use the private key to decrypt the keys */
146 BOOST_FOREACH (string const & i, kdm.keys ()) {
147 /* Decode the base-64-encoded cipher value from the KDM */
148 unsigned char cipher_value[256];
149 int const cipher_value_len = base64_decode (i, cipher_value, sizeof (cipher_value));
152 unsigned char * decrypted = new unsigned char[RSA_size(rsa)];
153 int const decrypted_len = RSA_private_decrypt (cipher_value_len, cipher_value, decrypted, rsa, RSA_PKCS1_OAEP_PADDING);
154 if (decrypted_len == -1) {
156 #if OPENSSL_VERSION_NUMBER > 0x10100000L
157 throw KDMDecryptionError (ERR_error_string (ERR_get_error(), 0), cipher_value_len, RSA_bits(rsa));
159 throw KDMDecryptionError (ERR_error_string (ERR_get_error(), 0), cipher_value_len, rsa->n->dmax);
163 unsigned char* p = decrypted;
164 switch (decrypted_len) {
168 /* 0 is structure id (fixed sequence specified by standard) [16 bytes] */
170 /* 16 is is signer thumbprint [20 bytes] */
172 /* 36 is CPL id [16 bytes] */
173 string const cpl_id = get_uuid (&p);
174 /* 52 is key id [16 bytes] */
175 string const key_id = get_uuid (&p);
176 /* 68 is not-valid-before (a string) [25 bytes] */
178 /* 93 is not-valid-after (a string) [25 bytes] */
180 /* 118 is the key [ASDCP::KeyLen bytes] */
181 add_key (optional<string>(), key_id, Key (p), cpl_id, INTEROP);
187 /* 0 is structure id (fixed sequence specified by standard) [16 bytes] */
188 DCP_ASSERT (memcmp (p, smpte_structure_id, 16) == 0);
190 /* 16 is is signer thumbprint [20 bytes] */
192 /* 36 is CPL id [16 bytes] */
193 string const cpl_id = get_uuid (&p);
194 /* 52 is key type [4 bytes] */
195 string const key_type = get (&p, 4);
196 /* 56 is key id [16 bytes] */
197 string const key_id = get_uuid (&p);
198 /* 72 is not-valid-before (a string) [25 bytes] */
200 /* 97 is not-valid-after (a string) [25 bytes] */
202 /* 112 is the key [ASDCP::KeyLen bytes] */
203 add_key (key_type, key_id, Key (p), cpl_id, SMPTE);
216 _annotation_text = kdm.annotation_text ();
217 _content_title_text = kdm.content_title_text ();
218 _issue_date = kdm.issue_date ();
221 DecryptedKDM::DecryptedKDM (
222 LocalTime not_valid_before,
223 LocalTime not_valid_after,
224 string annotation_text,
225 string content_title_text,
228 : _not_valid_before (not_valid_before)
229 , _not_valid_after (not_valid_after)
230 , _annotation_text (annotation_text)
231 , _content_title_text (content_title_text)
232 , _issue_date (issue_date)
237 DecryptedKDM::DecryptedKDM (
239 map<shared_ptr<const ReelMXF>, Key> keys,
240 LocalTime not_valid_before,
241 LocalTime not_valid_after,
242 string annotation_text,
243 string content_title_text,
246 : _not_valid_before (not_valid_before)
247 , _not_valid_after (not_valid_after)
248 , _annotation_text (annotation_text)
249 , _content_title_text (content_title_text)
250 , _issue_date (issue_date)
252 for (map<shared_ptr<const ReelMXF>, Key>::const_iterator i = keys.begin(); i != keys.end(); ++i) {
253 add_key (i->first->key_type(), i->first->key_id().get(), i->second, cpl_id, SMPTE);
257 DecryptedKDM::DecryptedKDM (
258 shared_ptr<const CPL> cpl,
260 LocalTime not_valid_before,
261 LocalTime not_valid_after,
262 string annotation_text,
263 string content_title_text,
266 : _not_valid_before (not_valid_before)
267 , _not_valid_after (not_valid_after)
268 , _annotation_text (annotation_text)
269 , _content_title_text (content_title_text)
270 , _issue_date (issue_date)
272 /* Create DecryptedKDMKey objects for each encryptable asset */
273 bool did_one = false;
274 BOOST_FOREACH(shared_ptr<const ReelMXF> i, cpl->reel_mxfs()) {
276 add_key (i->key_type(), i->key_id().get(), key, cpl->id(), SMPTE);
282 throw NotEncryptedError (cpl->id ());
286 /** @param type (MDIK, MDAK etc.)
287 * @param key_id Key ID.
288 * @param key The actual symmetric key.
289 * @param cpl_id ID of CPL that the key is for.
292 DecryptedKDM::add_key (optional<string> type, string key_id, Key key, string cpl_id, Standard standard)
294 _keys.push_back (DecryptedKDMKey (type, key_id, key, cpl_id, standard));
298 DecryptedKDM::add_key (DecryptedKDMKey key)
300 _keys.push_back (key);
304 DecryptedKDM::encrypt (
305 shared_ptr<const CertificateChain> signer,
306 Certificate recipient,
307 vector<string> trusted_devices,
308 Formulation formulation,
309 bool disable_forensic_marking_picture,
310 optional<int> disable_forensic_marking_audio
313 DCP_ASSERT (!_keys.empty ());
315 BOOST_FOREACH (dcp::Certificate i, signer->leaf_to_root()) {
316 if (day_greater_than_or_equal(i.not_before(), _not_valid_before)) {
317 throw BadKDMDateError (true);
318 } else if (day_less_than_or_equal(i.not_after(), _not_valid_after)) {
319 throw BadKDMDateError (false);
323 list<pair<string, string> > key_ids;
325 BOOST_FOREACH (DecryptedKDMKey const & i, _keys) {
326 /* We're making SMPTE keys so we must have a type for each one */
327 DCP_ASSERT (i.type());
328 key_ids.push_back (make_pair (i.type().get(), i.id ()));
330 /* XXX: SMPTE only */
334 put (&p, smpte_structure_id, 16);
336 base64_decode (signer->leaf().thumbprint (), p, 20);
339 put_uuid (&p, i.cpl_id ());
340 put (&p, i.type().get());
341 put_uuid (&p, i.id ());
342 put (&p, _not_valid_before.as_string ());
343 put (&p, _not_valid_after.as_string ());
344 put (&p, i.key().value(), ASDCP::KeyLen);
346 /* Encrypt using the projector's public key */
347 RSA* rsa = recipient.public_key ();
348 unsigned char encrypted[RSA_size(rsa)];
349 int const encrypted_len = RSA_public_encrypt (p - block, block, encrypted, rsa, RSA_PKCS1_OAEP_PADDING);
350 if (encrypted_len == -1) {
351 throw MiscError (String::compose ("Could not encrypt KDM (%1)", ERR_error_string (ERR_get_error(), 0)));
354 /* Lazy overallocation */
355 char out[encrypted_len * 2];
356 Kumu::base64encode (encrypted, encrypted_len, out, encrypted_len * 2);
357 int const N = strlen (out);
359 for (int i = 0; i < N; ++i) {
360 if (i > 0 && (i % 64) == 0) {
366 keys.push_back (lines);
369 string device_list_description = recipient.subject_common_name ();
370 if (device_list_description.find (".") != string::npos) {
371 device_list_description = device_list_description.substr (device_list_description.find (".") + 1);
374 return EncryptedKDM (
378 _keys.front().cpl_id (),
384 disable_forensic_marking_picture,
385 disable_forensic_marking_audio,