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)
105 buffer, sizeof(buffer), "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx",
106 (*p)[0], (*p)[1], (*p)[2], (*p)[3], (*p)[4], (*p)[5], (*p)[6], (*p)[7],
107 (*p)[8], (*p)[9], (*p)[10], (*p)[11], (*p)[12], (*p)[13], (*p)[14], (*p)[15]
115 get (uint8_t ** p, int N)
118 for (int i = 0; i < N; ++i) {
126 DecryptedKDM::DecryptedKDM (EncryptedKDM const & kdm, string private_key)
128 /* Read the private key */
130 BIO* bio = BIO_new_mem_buf (const_cast<char *> (private_key.c_str ()), -1);
132 throw MiscError ("could not create memory BIO");
135 RSA* rsa = PEM_read_bio_RSAPrivateKey (bio, 0, 0, 0);
137 throw FileError ("could not read RSA private key file", private_key, errno);
140 /* Use the private key to decrypt the keys */
142 BOOST_FOREACH (string const & i, kdm.keys ()) {
143 /* Decode the base-64-encoded cipher value from the KDM */
144 unsigned char cipher_value[256];
145 int const cipher_value_len = base64_decode (i, cipher_value, sizeof (cipher_value));
148 unsigned char * decrypted = new unsigned char[RSA_size(rsa)];
149 int const decrypted_len = RSA_private_decrypt (cipher_value_len, cipher_value, decrypted, rsa, RSA_PKCS1_OAEP_PADDING);
150 if (decrypted_len == -1) {
152 throw KDMDecryptionError (ERR_error_string (ERR_get_error(), 0));
155 unsigned char* p = decrypted;
156 switch (decrypted_len) {
160 /* 0 is structure id (fixed sequence specified by standard) [16 bytes] */
162 /* 16 is is signer thumbprint [20 bytes] */
164 /* 36 is CPL id [16 bytes] */
165 string const cpl_id = get_uuid (&p);
166 /* 52 is key id [16 bytes] */
167 string const key_id = get_uuid (&p);
168 /* 68 is not-valid-before (a string) [25 bytes] */
170 /* 93 is not-valid-after (a string) [25 bytes] */
172 /* 118 is the key [ASDCP::KeyLen bytes] */
173 add_key (optional<string>(), key_id, Key (p), cpl_id, INTEROP);
179 /* 0 is structure id (fixed sequence specified by standard) [16 bytes] */
180 DCP_ASSERT (memcmp (p, smpte_structure_id, 16) == 0);
182 /* 16 is is signer thumbprint [20 bytes] */
184 /* 36 is CPL id [16 bytes] */
185 string const cpl_id = get_uuid (&p);
186 /* 52 is key type [4 bytes] */
187 string const key_type = get (&p, 4);
188 /* 56 is key id [16 bytes] */
189 string const key_id = get_uuid (&p);
190 /* 72 is not-valid-before (a string) [25 bytes] */
192 /* 97 is not-valid-after (a string) [25 bytes] */
194 /* 112 is the key [ASDCP::KeyLen bytes] */
195 add_key (key_type, key_id, Key (p), cpl_id, SMPTE);
208 _annotation_text = kdm.annotation_text ();
209 _content_title_text = kdm.content_title_text ();
210 _issue_date = kdm.issue_date ();
213 DecryptedKDM::DecryptedKDM (
214 LocalTime not_valid_before,
215 LocalTime not_valid_after,
216 string annotation_text,
217 string content_title_text,
220 : _not_valid_before (not_valid_before)
221 , _not_valid_after (not_valid_after)
222 , _annotation_text (annotation_text)
223 , _content_title_text (content_title_text)
224 , _issue_date (issue_date)
229 DecryptedKDM::DecryptedKDM (
231 map<shared_ptr<const ReelMXF>, Key> keys,
232 LocalTime not_valid_before,
233 LocalTime not_valid_after,
234 string annotation_text,
235 string content_title_text,
238 : _not_valid_before (not_valid_before)
239 , _not_valid_after (not_valid_after)
240 , _annotation_text (annotation_text)
241 , _content_title_text (content_title_text)
242 , _issue_date (issue_date)
244 for (map<shared_ptr<const ReelMXF>, Key>::const_iterator i = keys.begin(); i != keys.end(); ++i) {
245 add_key (i->first->key_type(), i->first->key_id().get(), i->second, cpl_id, SMPTE);
249 DecryptedKDM::DecryptedKDM (
250 shared_ptr<const CPL> cpl,
252 LocalTime not_valid_before,
253 LocalTime not_valid_after,
254 string annotation_text,
255 string content_title_text,
258 : _not_valid_before (not_valid_before)
259 , _not_valid_after (not_valid_after)
260 , _annotation_text (annotation_text)
261 , _content_title_text (content_title_text)
262 , _issue_date (issue_date)
264 /* Create DecryptedKDMKey objects for each encryptable asset */
265 bool did_one = false;
266 BOOST_FOREACH(shared_ptr<const ReelAsset> i, cpl->reel_assets ()) {
267 shared_ptr<const ReelMXF> mxf = boost::dynamic_pointer_cast<const ReelMXF> (i);
268 if (mxf && mxf->key_id ()) {
269 add_key (mxf->key_type(), mxf->key_id().get(), key, cpl->id(), SMPTE);
275 throw NotEncryptedError (cpl->id ());
279 /** @param type (MDIK, MDAK etc.)
280 * @param key_id Key ID.
281 * @param key The actual symmetric key.
282 * @param cpl_id ID of CPL that the key is for.
285 DecryptedKDM::add_key (optional<string> type, string key_id, Key key, string cpl_id, Standard standard)
287 _keys.push_back (DecryptedKDMKey (type, key_id, key, cpl_id, standard));
291 DecryptedKDM::add_key (DecryptedKDMKey key)
293 _keys.push_back (key);
297 DecryptedKDM::encrypt (
298 shared_ptr<const CertificateChain> signer, Certificate recipient, vector<Certificate> trusted_devices, Formulation formulation
301 list<pair<string, string> > key_ids;
303 BOOST_FOREACH (DecryptedKDMKey const & i, _keys) {
304 /* We're making SMPTE keys so we must have a type for each one */
305 DCP_ASSERT (i.type());
306 key_ids.push_back (make_pair (i.type().get(), i.id ()));
308 /* XXX: SMPTE only */
312 put (&p, smpte_structure_id, 16);
314 base64_decode (signer->leaf().thumbprint (), p, 20);
317 put_uuid (&p, i.cpl_id ());
318 put (&p, i.type().get());
319 put_uuid (&p, i.id ());
320 put (&p, _not_valid_before.as_string ());
321 put (&p, _not_valid_after.as_string ());
322 put (&p, i.key().value(), ASDCP::KeyLen);
324 /* Encrypt using the projector's public key */
325 RSA* rsa = recipient.public_key ();
326 unsigned char encrypted[RSA_size(rsa)];
327 int const encrypted_len = RSA_public_encrypt (p - block, block, encrypted, rsa, RSA_PKCS1_OAEP_PADDING);
328 if (encrypted_len == -1) {
329 throw MiscError (String::compose ("Could not encrypt KDM (%1)", ERR_error_string (ERR_get_error(), 0)));
332 /* Lazy overallocation */
333 char out[encrypted_len * 2];
334 Kumu::base64encode (encrypted, encrypted_len, out, encrypted_len * 2);
335 int const N = strlen (out);
337 for (int i = 0; i < N; ++i) {
338 if (i > 0 && (i % 64) == 0) {
344 keys.push_back (lines);
347 string device_list_description = recipient.subject_common_name ();
348 if (device_list_description.find (".") != string::npos) {
349 device_list_description = device_list_description.substr (device_list_description.find (".") + 1);
352 return EncryptedKDM (
356 _keys.front().cpl_id (),