Unbuilt KDM changes.
authorCarl Hetherington <cth@carlh.net>
Sat, 21 Sep 2013 19:16:11 +0000 (20:16 +0100)
committerCarl Hetherington <cth@carlh.net>
Sat, 21 Sep 2013 19:16:11 +0000 (20:16 +0100)
src/cpl.cc
src/cpl.h
src/kdm.cc
src/kdm.h
test/kdm_test.cc

index a3d2ecfa9fbbaa831f5597ce3a0cd1f5d9b618db..072304b810331db129b03a783a7d9e50cde2b87f 100644 (file)
@@ -348,7 +348,6 @@ shared_ptr<xmlpp::Document>
 CPL::make_kdm (
        shared_ptr<const Signer> signer,
        shared_ptr<const Certificate> 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<shared_ptr<const Asset> > a = assets();
+               for (list<shared_ptr<const Asset> >::iterator i = a.begin(); i != a.end(); ++i) {
+                       /* XXX: non-MXF assets? */
+                       shared_ptr<const MXFAsset> mxf = boost::dynamic_pointer_cast<const MXFAsset> (*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 ());
+               }
        }
        
        {
index da30fdbb8e2c009aa4d4e8f4ea6c3d0ed63933ad..726fdda264d3d8648d3867c0bd8d4f694d5036d0 100644 (file)
--- 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<xmlpp::Document> make_kdm (
                boost::shared_ptr<const Signer> signer,
                boost::shared_ptr<const Certificate> recipient_cert,
-               Key key,
                boost::posix_time::ptime from,
                boost::posix_time::ptime until,
                bool interop,
index bbfd3832ab86cdf9b48cb332e196e27818cb6c5f..b35c34b5483d840972007b495ceb530614955379 100644 (file)
@@ -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<const Signer> 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<int> (**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++;
+       }
+}
index c012c101f810d64410988f5e9991192186d7d665..253589fed63f2dcd906f8d607ea34b23b25987bc 100644 (file)
--- 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;
index a85bada787732751c9cc777f326f3d2176b5415b..d2a80ad2ddfca2263811b03194bc6831fba8c158 100644 (file)
@@ -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");
 }
+