X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Fdecrypted_kdm.cc;h=99cbca10ff040bd1b87eca376f490e45baaf9e2b;hb=f0a6d7b5b8d16b8b47917cd30b340917f5c62fc5;hp=62162346bf28849a7531d739a293dba3eae4e861;hpb=da228f37426ac999f02e03e558acef5501b22361;p=libdcp.git diff --git a/src/decrypted_kdm.cc b/src/decrypted_kdm.cc index 62162346..99cbca10 100644 --- a/src/decrypted_kdm.cc +++ b/src/decrypted_kdm.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2014 Carl Hetherington + Copyright (C) 2013-2015 Carl Hetherington This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -20,20 +20,23 @@ #include "decrypted_kdm.h" #include "decrypted_kdm_key.h" #include "encrypted_kdm.h" -#include "reel_mxf_asset.h" +#include "reel_mxf.h" +#include "reel_asset.h" #include "util.h" #include "exceptions.h" #include "cpl.h" -#include "mxf.h" -#include "signer.h" +#include "certificate_chain.h" +#include "dcp_assert.h" #include "AS_DCP.h" #include "KM_util.h" #include "compose.hpp" #include #include #include +#include using std::list; +using std::vector; using std::string; using std::stringstream; using std::setw; @@ -75,7 +78,7 @@ static string get_uuid (unsigned char ** p) { stringstream g; - + for (int i = 0; i < 16; ++i) { g << setw(2) << setfill('0') << hex << static_cast (**p); (*p)++; @@ -107,7 +110,7 @@ DecryptedKDM::DecryptedKDM (EncryptedKDM const & kdm, string private_key) if (!bio) { throw MiscError ("could not create memory BIO"); } - + RSA* rsa = PEM_read_bio_RSAPrivateKey (bio, 0, 0, 0); if (!rsa) { throw FileError ("could not read RSA private key file", private_key, errno); @@ -115,12 +118,10 @@ DecryptedKDM::DecryptedKDM (EncryptedKDM const & kdm, string private_key) /* Use the private key to decrypt the keys */ - list const encrypted_keys = kdm.keys (); - for (list::const_iterator i = encrypted_keys.begin(); i != encrypted_keys.end(); ++i) { - + BOOST_FOREACH (string const & i, kdm.keys ()) { /* Decode the base-64-encoded cipher value from the KDM */ unsigned char cipher_value[256]; - int const cipher_value_len = base64_decode (*i, cipher_value, sizeof (cipher_value)); + int const cipher_value_len = base64_decode (i, cipher_value, sizeof (cipher_value)); /* Decrypt it */ unsigned char * decrypted = new unsigned char[RSA_size(rsa)]; @@ -173,14 +174,34 @@ DecryptedKDM::DecryptedKDM (EncryptedKDM const & kdm, string private_key) break; } default: - assert (false); - } - + DCP_ASSERT (false); + } + delete[] decrypted; } RSA_free (rsa); BIO_free (bio); + + _annotation_text = kdm.annotation_text (); + _content_title_text = kdm.content_title_text (); + _issue_date = kdm.issue_date (); +} + +DecryptedKDM::DecryptedKDM ( + LocalTime not_valid_before, + LocalTime not_valid_after, + string annotation_text, + string content_title_text, + string issue_date + ) + : _not_valid_before (not_valid_before) + , _not_valid_after (not_valid_after) + , _annotation_text (annotation_text) + , _content_title_text (content_title_text) + , _issue_date (issue_date) +{ + } DecryptedKDM::DecryptedKDM ( @@ -198,28 +219,43 @@ DecryptedKDM::DecryptedKDM ( , _content_title_text (content_title_text) , _issue_date (issue_date) { - /* Create DecryptedKDMKey objects for each MXF asset */ - list > assets = cpl->reel_assets (); - for (list >::iterator i = assets.begin(); i != assets.end(); ++i) { - /* XXX: do non-MXF assets need keys? */ - shared_ptr mxf = boost::dynamic_pointer_cast (*i); - if (mxf) { - if (mxf->key_id().empty ()) { - throw NotEncryptedError (mxf->id()); + /* Create DecryptedKDMKey objects for each encryptable asset */ + BOOST_FOREACH(shared_ptr i, cpl->reel_assets ()) { + shared_ptr mxf = boost::dynamic_pointer_cast (i); + shared_ptr asset = boost::dynamic_pointer_cast (i); + if (asset && mxf) { + if (!mxf->key_id ()) { + throw NotEncryptedError (asset->id ()); } - _keys.push_back (DecryptedKDMKey (mxf->key_type(), mxf->key_id(), key, cpl->id ())); + _keys.push_back (DecryptedKDMKey (mxf->key_type(), mxf->key_id().get(), key, cpl->id ())); } } } +/** @param type (MDIK, MDAK etc.) + * @param key_id Key ID. + * @param key The actual symmetric key. + * @param cpl_id ID of CPL that the key is for. + */ +void +DecryptedKDM::add_key (string type, string key_id, Key key, string cpl_id) +{ + _keys.push_back (DecryptedKDMKey (type, key_id, key, cpl_id)); +} + +void +DecryptedKDM::add_key (DecryptedKDMKey key) +{ + _keys.push_back (key); +} + EncryptedKDM -DecryptedKDM::encrypt (shared_ptr signer, shared_ptr recipient, Formulation formulation) const +DecryptedKDM::encrypt (shared_ptr signer, Certificate recipient, vector trusted_devices, Formulation formulation) const { list > key_ids; list keys; - for (list::const_iterator i = _keys.begin(); i != _keys.end(); ++i) { - - key_ids.push_back (make_pair (i->type(), i->id ())); + BOOST_FOREACH (DecryptedKDMKey const & i, _keys) { + key_ids.push_back (make_pair (i.type(), i.id ())); /* XXX: SMPTE only */ uint8_t block[138]; @@ -229,24 +265,24 @@ DecryptedKDM::encrypt (shared_ptr signer, shared_ptrcertificates().leaf()->thumbprint (), p, 20); + base64_decode (signer->leaf().thumbprint (), p, 20); p += 20; - - put_uuid (&p, i->cpl_id ()); - put (&p, i->type ()); - put_uuid (&p, i->id ()); + + put_uuid (&p, i.cpl_id ()); + put (&p, i.type ()); + put_uuid (&p, i.id ()); put (&p, _not_valid_before.as_string ()); put (&p, _not_valid_after.as_string ()); - put (&p, i->key().value(), ASDCP::KeyLen); - + put (&p, i.key().value(), ASDCP::KeyLen); + /* Encrypt using the projector's public key */ - RSA* rsa = recipient->public_key (); + RSA* rsa = recipient.public_key (); unsigned char encrypted[RSA_size(rsa)]; int const encrypted_len = RSA_public_encrypt (p - block, block, encrypted, rsa, RSA_PKCS1_OAEP_PADDING); if (encrypted_len == -1) { throw MiscError (String::compose ("Could not encrypt KDM (%1)", ERR_error_string (ERR_get_error(), 0))); } - + /* Lazy overallocation */ char out[encrypted_len * 2]; Kumu::base64encode (encrypted, encrypted_len, out, encrypted_len * 2); @@ -258,11 +294,11 @@ DecryptedKDM::encrypt (shared_ptr signer, shared_ptrcommon_name (); + string device_list_description = recipient.subject_common_name (); if (device_list_description.find (".") != string::npos) { device_list_description = device_list_description.substr (device_list_description.find (".") + 1); } @@ -270,6 +306,7 @@ DecryptedKDM::encrypt (shared_ptr signer, shared_ptr