f6d96b39662d3e2544bef96e2b5406a55ed8de33
[libdcp.git] / src / kdm.h
1 /*
2     Copyright (C) 2013 Carl Hetherington <cth@carlh.net>
3
4     This program is free software; you can redistribute it and/or modify
5     it under the terms of the GNU General Public License as published by
6     the Free Software Foundation; either version 2 of the License, or
7     (at your option) any later version.
8
9     This program is distributed in the hope that it will be useful,
10     but WITHOUT ANY WARRANTY; without even the implied warranty of
11     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12     GNU General Public License for more details.
13
14     You should have received a copy of the GNU General Public License
15     along with this program; if not, write to the Free Software
16     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17
18 */
19
20 /** @file  src/kdm.h
21  *  @brief KDM and KDMKey classes.
22  */
23
24 #ifndef LIBDCP_KDM_H
25 #define LIBDCP_KDM_H
26
27 #include <boost/filesystem.hpp>
28 #include <boost/scoped_ptr.hpp>
29 #include <boost/date_time/posix_time/posix_time.hpp>
30 #include "key.h"
31 #include "metadata.h"
32
33 class kdm_key_test;
34
35 namespace dcp {
36
37 namespace xml {
38         class DCinemaSecurityMessage;
39 };
40
41 class Signer;
42 class Certificate;
43 class CPL;
44
45 /** @class KDMKey
46  *  @brief A single key (and associated metadata) for encrypting or decrypting an MXF.
47  *
48  *  One or more of these are delivered (themselves encrypted) in a KDM.  The following
49  *  data is collected into a block:
50  *
51  *  A structure ID (a magic value specified by the standard)
52  *  The thumbprint of the KDM signer's certificate.
53  *  The CPL ID.
54  *  The key ID.
55  *  Validity start and end times.
56  *  The key itself
57  *
58  *  This data block is then encrypted using the projector's public key, so that
59  *  only the target projector can decrypt block.
60  */
61 class KDMKey
62 {
63 public:
64         /** Create a KDMKey from the raw block that is encrypted in the KDM's CipherData.
65          *  @param raw Pointer to data block (134 bytes for interop, 138 bytes for SMPTE).
66          *  @param len Length of the data block in bytes.
67          */
68         KDMKey (uint8_t const * raw, int len);
69
70         /** Create a KDMKey from its constituent parts.
71          *  @param signer Signer for the KDM.
72          *  @param cpl_id ID of the CPL that the KDM is for.
73          *  @param key_type Type of data that this key is for (MDIK for image, MDAK for audio, ...)
74          *  @param key_id ID of this key.
75          *  @param from Valid-from time.
76          *  @param until Valid-until time.
77          *  @param key The key itself.
78          */
79         KDMKey (
80                 boost::shared_ptr<const Signer> signer,
81                 std::string cpl_id, std::string key_type, std::string key_id, boost::posix_time::ptime from, boost::posix_time::ptime until, Key key
82                 );
83         
84         KDMKey (KDMKey const &);
85
86         KDMKey& operator= (KDMKey const &);
87
88         /** @return ID of the CPL that the KDM is for */
89         std::string cpl_id () const {
90                 return _cpl_id;
91         }
92         
93         /** @return ID of the key */
94         std::string key_id () const {
95                 return _key_id;
96         }
97
98         /** @return start of the validity period as a string */
99         std::string not_valid_before () const {
100                 return _not_valid_before;
101         }
102
103         /** @return end of the validity period as a string */
104         std::string not_valid_after () const {
105                 return _not_valid_after;
106         }
107
108         /** @return the key itself */
109         Key key () const {
110                 return _key;
111         }
112
113         /** @param cert Cerfificate.
114          *  @return The data block encrypted with a certificate's public key and converted to base 64.
115          */
116         std::string encrypted_base64 (boost::shared_ptr<const Certificate> cert) const;
117         
118 private:
119         friend class ::kdm_key_test;
120         
121         void get (uint8_t *, uint8_t const **, int) const;
122         std::string get (uint8_t const **, int) const;
123         std::string get_uuid (uint8_t const **) const;
124         void put (uint8_t **, uint8_t const *, int) const;
125         void put (uint8_t **, std::string) const;
126         void put_uuid (uint8_t **, std::string) const;
127
128         friend bool operator== (KDMKey const &, KDMKey const &);
129         
130         uint8_t _signer_thumbprint[20];
131         std::string _cpl_id;
132         std::string _key_type;
133         std::string _key_id;
134         std::string _not_valid_before;
135         std::string _not_valid_after;
136         Key _key;
137 };
138
139 /** @class KDM
140  *  @brief A class representing a Key Delivery Message (KDM).
141  *
142  *  A KDM wraps one or more content keys (which we wrap into KDMKey objects) and various
143  *  other metadata.  This class can read and decrypt existing KDMs (provided you have
144  *  the private key that the KDM was targeted at).  It can also create new KDMs for
145  *  a given CPL.
146  */
147 class KDM
148 {
149 public:
150         /** Load and decrypt a KDM.  After this constructor the KDMKeys can be read
151          *  and used to decrypt MXFs.
152          *
153          *  @param kdm KDM file name.
154          *  @param private_key Private key file name.
155          */
156         KDM (boost::filesystem::path kdm, boost::filesystem::path private_key);
157
158         /** Create a new KDM.
159          *  @param cpl CPL that the KDM is for.
160          *  @param signer Certificate chain to sign the KDM with.
161          *  @param recipient_cert Certificate of the projector that this KDM is targeted at.
162          *  @param not_valid_before Start of validity period.
163          *  @param not_valid_after End of validity period.
164          *  @param annotation_text Text for the &lt;AnnotationText&gt; node.
165          *  @param issue_date Text for the &lt;IssueDate&gt; node.
166          */
167         KDM (
168                 boost::shared_ptr<const CPL> cpl, boost::shared_ptr<const Signer> signer, boost::shared_ptr<const Certificate> recipient_cert,
169                 boost::posix_time::ptime not_valid_before, boost::posix_time::ptime not_valid_after,
170                 std::string annotation_text, std::string issue_date
171                 );
172
173         KDM (KDM const &);
174         KDM & operator= (KDM const &);
175
176         /** @return The unencrypted content keys from this KDM */
177         std::list<KDMKey> keys () const {
178                 return _keys;
179         }
180
181         /** Write this KDM to a file.
182          *  @param file File to write to.
183          */
184         void as_xml (boost::filesystem::path file) const;
185
186         /** Obtain this KDM as an XML string.
187          *  @return XML string.
188          */
189         std::string as_xml () const;
190
191 private:
192         /** Unencrypted MXF content keys */
193         std::list<KDMKey> _keys;
194
195         /** The KDM's contents, mapped 1:1-ish to the XML */
196         boost::shared_ptr<xml::DCinemaSecurityMessage> _xml_kdm;
197 };
198
199
200 }
201
202 #endif