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