From: Carl Hetherington Date: Sat, 21 Sep 2013 19:16:11 +0000 (+0100) Subject: Unbuilt KDM changes. X-Git-Tag: v0.80~16 X-Git-Url: https://main.carlh.net/gitweb/?a=commitdiff_plain;h=66ef19cdb8ab4e4613762acee98a2bcb999ab65c;p=libdcp.git Unbuilt KDM changes. --- diff --git a/src/cpl.cc b/src/cpl.cc index a3d2ecfa..072304b8 100644 --- a/src/cpl.cc +++ b/src/cpl.cc @@ -348,7 +348,6 @@ shared_ptr CPL::make_kdm ( shared_ptr signer, shared_ptr recipient_cert, - Key key, boost::posix_time::ptime from, boost::posix_time::ptime until, bool interop, @@ -446,12 +445,23 @@ CPL::make_kdm ( authenticated_private->set_attribute ("Id", "ID_AuthenticatedPrivate"); xmlAddID (0, doc->cobj(), (const xmlChar *) "ID_AuthenticatedPrivate", authenticated_private->get_attribute("Id")->cobj()); - xmlpp::Element* encrypted_key = authenticated_private->add_child ("EncryptedKey", "enc"); - xmlpp::Element* encryption_method = encrypted_key->add_child ("EncryptionMethod", "enc"); - encryption_method->set_attribute ("Algorithm", "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"); - encryption_method->add_child("DigestMethod", "ds")->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#sha1"); - xmlpp::Element* cipher_data = authenticated_private->add_child ("CipherData", "enc"); - cipher_data->add_child("CipherValue", "enc")->add_child_text(key.hex()); + list > a = assets(); + for (list >::iterator i = a.begin(); i != a.end(); ++i) { + /* XXX: non-MXF assets? */ + shared_ptr mxf = boost::dynamic_pointer_cast (*i); + if (!mxf) { + continue; + } + + xmlpp::Element* encrypted_key = authenticated_private->add_child ("EncryptedKey", "enc"); + xmlpp::Element* encryption_method = encrypted_key->add_child ("EncryptionMethod", "enc"); + encryption_method->set_attribute ("Algorithm", "http://www.w3.org/2001/04/xmlenc#rsa-oaep-mgf1p"); + encryption_method->add_child("DigestMethod", "ds")->set_attribute("Algorithm", "http://www.w3.org/2000/09/xmldsig#sha1"); + xmlpp::Element* cipher_data = encrypted_key->add_child ("CipherData", "enc"); + + KDMKey kkey (signer, _id, mxf->key_id (), from, until, mxf->key ()); + cipher_data->add_child("CipherValue", "enc")->add_child_text (kkey.base64 ()); + } } { diff --git a/src/cpl.h b/src/cpl.h index da30fdbb..726fdda2 100644 --- a/src/cpl.h +++ b/src/cpl.h @@ -100,7 +100,6 @@ public: * @param signer Details of the certificates and private key to sign the KDM with. * @param recipient_cert The certificate of the projector that this KDM is targeted at. This will contain the * projector's public key which is used to encrypt the content keys. - * @param key Private key used to encrypt the MXFs referenced by this CPL. * @param from Time that the KDM should be valid from. * @param until Time that the KDM should be valid until. * @param interop true to generate an interop KDM, false for SMPTE. @@ -108,7 +107,6 @@ public: boost::shared_ptr make_kdm ( boost::shared_ptr signer, boost::shared_ptr recipient_cert, - Key key, boost::posix_time::ptime from, boost::posix_time::ptime until, bool interop, diff --git a/src/kdm.cc b/src/kdm.cc index bbfd3832..b35c34b5 100644 --- a/src/kdm.cc +++ b/src/kdm.cc @@ -44,13 +44,13 @@ KDM::KDM (boost::filesystem::path kdm, boost::filesystem::path private_key) FILE* private_key_file = fopen (private_key.string().c_str(), "r"); if (!private_key_file) { - throw FileError ("could not find RSA private key file", private_key.string ()); + throw FileError ("could not find RSA private key file", private_key); } RSA* rsa = PEM_read_RSAPrivateKey (private_key_file, 0, 0, 0); fclose (private_key_file); if (!rsa) { - throw FileError ("could not read RSA private key file", private_key.string ()); + throw FileError ("could not read RSA private key file", private_key); } @@ -87,27 +87,41 @@ KDM::KDM (boost::filesystem::path kdm, boost::filesystem::path private_key) RSA_free (rsa); } +KDMKey::KDMKey (shared_ptr signer, string cpl_id, string key_id, boost::posix_time::ptime from, boost::posix_time::ptime until, Key key) + : _cpl_id (cpl_id) + , _key_id (key_id), + , _not_valid_before (ptime_to_string (from)) + , _not_valid_after (ptime_to_string (until)) + , _key (key) +{ + /* Magic value specified by SMPTE S430-1-2006 */ + _structure_id[] = { 0xf1, 0xdc, 0x12, 0x44, 0x60, 0x16, 0x9a, 0x0e, 0x85, 0xbc, 0x30, 0x06, 0x42, 0xf8, 0x66, 0xab }; + + base64_decode (signer->certificates()->leaf()->thumbprint (), _signer_thumbprint, 20); +} -KDMKey::KDMKey (unsigned char const * raw, int len) +KDMKey::KDMKey (uint8_t const * raw, int len) { switch (len) { case 134: /* interop */ - _structure_id = get (&raw, 16); - _signer_thumbprint = get (&raw, 20); - _cpl_id = get_uuid (&raw, 16); - _key_id = get_uuid (&raw, 16); + /* [0-15] is structure id (fixed sequence specified by standard) */ + raw += 16; + get (_signer_thumbprint, &raw, 20); + _cpl_id = get_uuid (&raw); + _key_id = get_uuid (&raw); _not_valid_before = get (&raw, 25); _not_valid_after = get (&raw, 25); _key = Key (raw); break; case 138: /* SMPTE */ - _structure_id = get (&raw, 16); - _signer_thumbprint = get (&raw, 20); - _cpl_id = get_uuid (&raw, 16); + /* [0-15] is structure id (fixed sequence specified by standard) */ + raw += 16; + get (_signer_thumbprint, &raw, 20); + _cpl_id = get_uuid (&raw); _key_type = get (&raw, 4); - _key_id = get_uuid (&raw, 16); + _key_id = get_uuid (&raw); _not_valid_before = get (&raw, 25); _not_valid_after = get (&raw, 25); _key = Key (raw); @@ -117,8 +131,32 @@ KDMKey::KDMKey (unsigned char const * raw, int len) } } + +string +KDMKey::base64 () const +{ + /* XXX: SMPTE only */ + uint8_t block[138]; + uint8_t* p = block; + + /* Magic value specified by SMPTE S430-1-2006 */ + uint8_t structure_id[] = { 0xf1, 0xdc, 0x12, 0x44, 0x60, 0x16, 0x9a, 0x0e, 0x85, 0xbc, 0x30, 0x06, 0x42, 0xf8, 0x66, 0xab }; + put (&p, structure_id, 16); + put (&p, _signer_thumbprint, 20); + put_uuid (&p, _cpl_id); + put (&p, _key_type, 4); + put_uuid (&p, _key_id); + put (&p, _not_valid_before.c_str(), 25); + put (&p, _not_valid_after.c_str(), 25); + put (&p, _key.value(), ASDCP::KeyLen); + + /* Lazy overallocation */ + char string[138 * 2]; + return Kumu::base64encode (block, 138, string, 138 * 2); +} + string -KDMKey::get (unsigned char const ** p, int N) const +KDMKey::get (uint8_t const ** p, int N) const { string g; for (int i = 0; i < N; ++i) { @@ -129,12 +167,19 @@ KDMKey::get (unsigned char const ** p, int N) const return g; } +void +KDMKey::get (uint8_t const * o, uint8_t const ** p, int N) const +{ + memcpy (o, *p, N); + *p += N; +} + string -KDMKey::get_uuid (unsigned char const ** p, int N) const +KDMKey::get_uuid (unsigned char const ** p) const { stringstream g; - for (int i = 0; i < N; ++i) { + for (int i = 0; i < 16; ++i) { g << setw(2) << setfill('0') << hex << static_cast (**p); (*p)++; if (i == 3 || i == 5 || i == 7 || i == 9) { @@ -144,3 +189,21 @@ KDMKey::get_uuid (unsigned char const ** p, int N) const return g.str (); } + +void +KDMKey::put (uint8_t ** d, uint8_t const * s, int N) const +{ + memcpy (*d, s, N); + (*d) += N; +} + +void +KDMKey::put_uuid (uint8_t ** d, string id) const +{ + id.erase (id.remove (id.begin(), id.end(), "-")); + for (int i = 0; i < 32; i += 2) { + stringstream s; + s << id[i] << id[i + 1]; + s >> *d++; + } +} diff --git a/src/kdm.h b/src/kdm.h index c012c101..253589fe 100644 --- a/src/kdm.h +++ b/src/kdm.h @@ -28,49 +28,23 @@ namespace libdcp { /** A single key for encrypting or decrypting an MXF. One or more of these * are delivered in a KDM. */ -class KDMKey +class KDMKey : public boost::noncopyable { public: - KDMKey (unsigned char const *, int); - - std::string structure_id () const { - return _structure_id; - } - - std::string signer_thumbprint () const { - return _signer_thumbprint; - } - - std::string cpl_id () const { - return _cpl_id; - } - - std::string key_type () const { - return _key_type; - } - - std::string key_id () const { - return _key_id; - } - - std::string not_valid_before () const { - return _not_valid_before; - } - - std::string not_valid_after () const { - return _not_valid_after; - } + KDMKey (uint8_t const *, int); Key key () const { return _key; } private: - std::string get (unsigned char const **, int) const; - std::string get_uuid (unsigned char const **, int) const; + void get (uint8_t *, uint8_t const **, int) const; + std::string get (uint8_t const **, int) const; + std::string get_uuid (uint8_t const **) const; + void put (uint8_t **, uint8_t const *, int) const; + void put_uuid (uint8_t **, std::string) const; - std::string _structure_id; - std::string _signer_thumbprint; + uint8_t _signer_thumbprint[20]; std::string _cpl_id; std::string _not_valid_before; std::string _not_valid_after; diff --git a/test/kdm_test.cc b/test/kdm_test.cc index a85bada7..d2a80ad2 100644 --- a/test/kdm_test.cc +++ b/test/kdm_test.cc @@ -42,3 +42,4 @@ BOOST_AUTO_TEST_CASE (kdm_test) BOOST_CHECK_EQUAL (keys.back().not_valid_after(), "2023-07-02T20:04:56+00:00"); BOOST_CHECK_EQUAL (keys.back().key().hex(), "5327fb7ec2e807bd57059615bf8a169d"); } +