Check SMPTE structure ID when reading KDMs.
[libdcp.git] / src / decrypted_kdm.cc
index 96049aa2871100a133e983868a30f716a13d2860..7113afb8ab512b3ff3d0a6e359abd29f333e7de6 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013-2016 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2017 Carl Hetherington <cth@carlh.net>
 
     This file is part of libdcp.
 
@@ -56,9 +56,14 @@ using std::setw;
 using std::setfill;
 using std::hex;
 using std::pair;
+using std::map;
 using boost::shared_ptr;
+using boost::optional;
 using namespace dcp;
 
+/* Magic value specified by SMPTE S430-1-2006 */
+static uint8_t smpte_structure_id[] = { 0xf1, 0xdc, 0x12, 0x44, 0x60, 0x16, 0x9a, 0x0e, 0x85, 0xbc, 0x30, 0x06, 0x42, 0xf8, 0x66, 0xab };
+
 static void
 put (uint8_t ** d, string s)
 {
@@ -165,13 +170,14 @@ DecryptedKDM::DecryptedKDM (EncryptedKDM const & kdm, string private_key)
                        /* 93 is not-valid-after (a string) [25 bytes] */
                        p += 25;
                        /* 118 is the key [ASDCP::KeyLen bytes] */
-                       _keys.push_back (DecryptedKDMKey ("", key_id, Key (p), cpl_id));
+                       add_key (optional<string>(), key_id, Key (p), cpl_id);
                        break;
                }
                case 138:
                {
                        /* SMPTE */
                        /* 0 is structure id (fixed sequence specified by standard) [16 bytes] */
+                       DCP_ASSERT (memcmp (p, smpte_structure_id, 16) == 0);
                        p += 16;
                        /* 16 is is signer thumbprint [20 bytes] */
                        p += 20;
@@ -186,7 +192,7 @@ DecryptedKDM::DecryptedKDM (EncryptedKDM const & kdm, string private_key)
                        /* 97 is not-valid-after (a string) [25 bytes] */
                        p += 25;
                        /* 112 is the key [ASDCP::KeyLen bytes] */
-                       _keys.push_back (DecryptedKDMKey (key_type, key_id, Key (p), cpl_id));
+                       add_key (key_type, key_id, Key (p), cpl_id);
                        break;
                }
                default:
@@ -221,7 +227,27 @@ DecryptedKDM::DecryptedKDM (
 }
 
 DecryptedKDM::DecryptedKDM (
-       boost::shared_ptr<const CPL> cpl,
+       string cpl_id,
+       map<shared_ptr<const ReelMXF>, Key> keys,
+       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)
+{
+       for (map<shared_ptr<const ReelMXF>, Key>::const_iterator i = keys.begin(); i != keys.end(); ++i) {
+               add_key (i->first->key_type(), i->first->key_id().get(), i->second, cpl_id);
+       }
+}
+
+DecryptedKDM::DecryptedKDM (
+       shared_ptr<const CPL> cpl,
        Key key,
        LocalTime not_valid_before,
        LocalTime not_valid_after,
@@ -239,9 +265,8 @@ DecryptedKDM::DecryptedKDM (
        bool did_one = false;
        BOOST_FOREACH(shared_ptr<const ReelAsset> i, cpl->reel_assets ()) {
                shared_ptr<const ReelMXF> mxf = boost::dynamic_pointer_cast<const ReelMXF> (i);
-               shared_ptr<const ReelAsset> asset = boost::dynamic_pointer_cast<const ReelAsset> (i);
-               if (asset && mxf && mxf->key_id ()) {
-                       _keys.push_back (DecryptedKDMKey (mxf->key_type(), mxf->key_id().get(), key, cpl->id ()));
+               if (mxf && mxf->key_id ()) {
+                       add_key (mxf->key_type(), mxf->key_id().get(), key, cpl->id ());
                        did_one = true;
                }
        }
@@ -257,7 +282,7 @@ DecryptedKDM::DecryptedKDM (
  *  @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)
+DecryptedKDM::add_key (optional<string> type, string key_id, Key key, string cpl_id)
 {
        _keys.push_back (DecryptedKDMKey (type, key_id, key, cpl_id));
 }
@@ -274,21 +299,21 @@ DecryptedKDM::encrypt (shared_ptr<const CertificateChain> signer, Certificate re
        list<pair<string, string> > key_ids;
        list<string> keys;
        BOOST_FOREACH (DecryptedKDMKey const & i, _keys) {
-               key_ids.push_back (make_pair (i.type(), i.id ()));
+               /* We're making SMPTE keys so we must have a type for each one */
+               DCP_ASSERT (i.type());
+               key_ids.push_back (make_pair (i.type().get(), i.id ()));
 
                /* 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, smpte_structure_id, 16);
 
                base64_decode (signer->leaf().thumbprint (), p, 20);
                p += 20;
 
                put_uuid (&p, i.cpl_id ());
-               put (&p, i.type ());
+               put (&p, i.type().get());
                put_uuid (&p, i.id ());
                put (&p, _not_valid_before.as_string ());
                put (&p, _not_valid_after.as_string ());
@@ -326,7 +351,6 @@ DecryptedKDM::encrypt (shared_ptr<const CertificateChain> signer, Certificate re
                signer,
                recipient,
                trusted_devices,
-               device_list_description,
                _keys.front().cpl_id (),
                _content_title_text,
                _annotation_text,