Line data Source code
1 : /*
2 : * If not stated otherwise in this file or this component's LICENSE file the
3 : * following copyright and licenses apply:
4 : *
5 : * Copyright 2022 Sky UK
6 : *
7 : * Licensed under the Apache License, Version 2.0 (the "License");
8 : * you may not use this file except in compliance with the License.
9 : * You may obtain a copy of the License at
10 : *
11 : * http://www.apache.org/licenses/LICENSE-2.0
12 : *
13 : * Unless required by applicable law or agreed to in writing, software
14 : * distributed under the License is distributed on an "AS IS" BASIS,
15 : * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 : * See the License for the specific language governing permissions and
17 : * limitations under the License.
18 : */
19 :
20 : #include <opencdm/open_cdm.h>
21 :
22 : #include "ActiveSessions.h"
23 : #include "Logger.h"
24 : #include "MediaKeysCapabilitiesBackend.h"
25 : #include "OpenCDMSession.h"
26 : #include "OpenCDMSystemPrivate.h"
27 : #include <cassert>
28 : #include <cstring>
29 :
30 : namespace
31 : {
32 : const Logger kLog{"open_cdm"};
33 : } // namespace
34 :
35 1 : OpenCDMSystem *opencdm_create_system(const char keySystem[])
36 : {
37 1 : kLog << debug << __func__;
38 :
39 1 : const char kSrcRev[] = SRCREV;
40 1 : const char kTags[] = TAGS;
41 :
42 : if (std::strlen(kSrcRev) > 0)
43 : {
44 : if (std::strlen(kTags) > 0)
45 : {
46 : kLog << mil << "Release Tag(s): " << kTags << " (Commit ID: " << kSrcRev << ")";
47 : }
48 : else
49 : {
50 1 : kLog << mil << "Release Tag(s): No Release Tags!" << " (Commit ID: " << kSrcRev << ")";
51 : }
52 : }
53 : else
54 : {
55 : kLog << warn << "Failed to get git commit ID!";
56 : }
57 :
58 1 : OpenCDMSystem *result = nullptr;
59 1 : opencdm_create_system_extended(keySystem, &result);
60 :
61 1 : return result;
62 : }
63 :
64 1 : OpenCDMError opencdm_create_system_extended(const char keySystem[], struct OpenCDMSystem **system)
65 : {
66 1 : kLog << debug << __func__;
67 1 : assert(system != nullptr);
68 :
69 1 : *system = createSystem(keySystem, "");
70 :
71 1 : return ERROR_NONE;
72 : }
73 :
74 1 : OpenCDMError opencdm_destruct_system(struct OpenCDMSystem *system)
75 : {
76 1 : kLog << debug << __func__;
77 1 : if (system)
78 : {
79 1 : delete system;
80 : }
81 :
82 1 : return ERROR_NONE;
83 : }
84 :
85 1 : OpenCDMError opencdm_is_type_supported(const char keySystem[], const char mimeType[])
86 : {
87 1 : kLog << debug << __func__;
88 3 : return MediaKeysCapabilitiesBackend::instance().supportsKeySystem(std::string(keySystem));
89 : }
90 :
91 3 : OpenCDMError opencdm_system_get_metadata(struct OpenCDMSystem *system, char metadata[], uint16_t *metadataSize)
92 : {
93 3 : kLog << debug << __func__;
94 3 : if (!system || !metadataSize)
95 : {
96 2 : kLog << error << __func__ << ": System or metadataSize is NULL";
97 2 : return ERROR_FAIL;
98 : }
99 1 : *metadataSize = 0;
100 1 : return ERROR_NONE;
101 : }
102 :
103 4 : OpenCDMError opencdm_system_get_version(struct OpenCDMSystem *system, char versionStr[])
104 : {
105 4 : kLog << debug << __func__;
106 4 : if (!system || !versionStr)
107 : {
108 2 : kLog << error << __func__ << ": System or versionStr is NULL";
109 2 : return ERROR_FAIL;
110 : }
111 2 : std::string version;
112 2 : if (!MediaKeysCapabilitiesBackend::instance().getSupportedKeySystemVersion(system->keySystem(), version))
113 : {
114 1 : return ERROR_FAIL;
115 : }
116 :
117 1 : const size_t MAX_LEN = 64;
118 1 : snprintf(versionStr, MAX_LEN, "%s", version.c_str());
119 :
120 1 : return ERROR_NONE;
121 2 : }
122 :
123 4 : OpenCDMError opencdm_system_get_drm_time(struct OpenCDMSystem *system, uint64_t *time)
124 : {
125 4 : kLog << debug << __func__;
126 4 : if (!time || !system)
127 : {
128 2 : kLog << error << "Ptr is null";
129 2 : return ERROR_FAIL;
130 : }
131 2 : if (!system->getDrmTime(*time))
132 : {
133 1 : kLog << error << "Failed to get DRM Time";
134 1 : return ERROR_FAIL;
135 : }
136 1 : return ERROR_NONE;
137 : }
138 :
139 2 : struct OpenCDMSession *opencdm_get_system_session(struct OpenCDMSystem *system, const uint8_t keyId[],
140 : const uint8_t length, const uint32_t waitTime)
141 : {
142 2 : kLog << debug << __func__;
143 6 : return ActiveSessions::instance().get(std::vector<uint8_t>(keyId, keyId + length));
144 : }
145 :
146 1 : OpenCDMError opencdm_system_set_server_certificate(struct OpenCDMSystem *system, const uint8_t serverCertificate[],
147 : const uint16_t serverCertificateLength)
148 : {
149 1 : kLog << debug << __func__;
150 1 : return ERROR_NONE;
151 : }
152 :
153 1 : struct OpenCDMSession *opencdm_get_session(const uint8_t keyId[], const uint8_t length, const uint32_t waitTime)
154 : {
155 1 : kLog << debug << __func__;
156 1 : return opencdm_get_system_session(nullptr, keyId, length, waitTime);
157 : }
158 :
159 5 : OpenCDMError opencdm_construct_session(struct OpenCDMSystem *system, const LicenseType licenseType,
160 : const char initDataType[], const uint8_t initData[],
161 : const uint16_t initDataLength, const uint8_t CDMData[],
162 : const uint16_t CDMDataLength, OpenCDMSessionCallbacks *callbacks, void *userData,
163 : struct OpenCDMSession **session)
164 : {
165 5 : kLog << debug << __func__;
166 5 : if (!system)
167 : {
168 1 : kLog << error << "System is NULL or not initialized";
169 1 : return ERROR_FAIL;
170 : }
171 8 : std::string initializationDataType(initDataType);
172 : std::vector<uint8_t> initDataVec(reinterpret_cast<const uint8_t *>(initData),
173 4 : reinterpret_cast<const uint8_t *>(initData) + initDataLength);
174 :
175 : OpenCDMSession *newSession =
176 4 : system->createSession(licenseType, callbacks, userData, initializationDataType, initDataVec);
177 :
178 4 : if (!newSession)
179 : {
180 1 : return ERROR_INVALID_SESSION;
181 : }
182 :
183 3 : if (!newSession->initialize())
184 : {
185 1 : kLog << error << "Failed to create session";
186 1 : ActiveSessions::instance().remove(newSession);
187 1 : return ERROR_FAIL;
188 : }
189 : std::vector<uint8_t> cdmDataVec(reinterpret_cast<const uint8_t *>(CDMData),
190 2 : reinterpret_cast<const uint8_t *>(CDMData) + CDMDataLength);
191 :
192 2 : if (!newSession->generateRequest(initializationDataType, initDataVec, cdmDataVec /*not used yet*/))
193 : {
194 1 : kLog << error << "Failed to generate request";
195 :
196 1 : opencdm_session_close(newSession);
197 1 : opencdm_destruct_session(newSession);
198 1 : return ERROR_FAIL;
199 : }
200 :
201 1 : *session = newSession;
202 :
203 1 : return ERROR_NONE;
204 4 : }
205 :
206 3 : OpenCDMError opencdm_destruct_session(struct OpenCDMSession *session)
207 : {
208 3 : kLog << debug << __func__;
209 3 : if (session)
210 : {
211 2 : ActiveSessions::instance().remove(session);
212 2 : return ERROR_NONE;
213 : }
214 1 : return ERROR_INVALID_SESSION;
215 : }
216 :
217 3 : OpenCDMError opencdm_session_load(struct OpenCDMSession *session)
218 : {
219 3 : kLog << debug << __func__;
220 3 : OpenCDMError result = ERROR_INVALID_SESSION;
221 3 : if (session)
222 : {
223 2 : if (session->loadSession())
224 : {
225 1 : result = ERROR_NONE;
226 : }
227 : else
228 : {
229 1 : kLog << error << "Failed to load the session";
230 1 : result = ERROR_FAIL;
231 : }
232 : }
233 :
234 3 : return result;
235 : }
236 :
237 3 : OpenCDMError opencdm_session_metadata(const struct OpenCDMSession *session, char metadata[], uint16_t *metadataSize)
238 : {
239 3 : kLog << debug << __func__;
240 3 : if (!session || !metadataSize)
241 : {
242 2 : kLog << error << __func__ << ": session or metadata size is null";
243 2 : return ERROR_FAIL;
244 : }
245 1 : *metadataSize = 0;
246 1 : return ERROR_NONE;
247 : }
248 :
249 2 : const char *opencdm_session_id(const struct OpenCDMSession *session)
250 : {
251 2 : kLog << debug << __func__;
252 2 : if (!session)
253 : {
254 1 : return nullptr;
255 : }
256 1 : return session->getSessionId().c_str();
257 : }
258 :
259 1 : const char *opencdm_session_buffer_id(const struct OpenCDMSession *session)
260 : {
261 1 : kLog << debug << __func__;
262 1 : return nullptr;
263 : }
264 :
265 2 : uint32_t opencdm_session_has_key_id(struct OpenCDMSession *session, const uint8_t length, const uint8_t keyId[])
266 : {
267 2 : kLog << debug << __func__;
268 2 : if (!session)
269 : {
270 1 : kLog << error << "Failed to check key id";
271 1 : return 0;
272 : }
273 1 : std::vector<uint8_t> key(keyId, keyId + length);
274 1 : return static_cast<uint32_t>(session->containsKey(key));
275 : }
276 :
277 3 : KeyStatus opencdm_session_status(const struct OpenCDMSession *session, const uint8_t keyId[], uint8_t length)
278 : {
279 3 : kLog << debug << __func__;
280 3 : if (session && keyId && 0 != length)
281 : {
282 1 : std::vector<uint8_t> key(keyId, keyId + length);
283 1 : return session->status(key);
284 : }
285 :
286 2 : return InternalError;
287 : }
288 :
289 1 : uint32_t opencdm_session_error(const struct OpenCDMSession *session, const uint8_t keyId[], uint8_t length)
290 : {
291 1 : kLog << warn << __func__ << " NOT IMPLEMENTED YET";
292 1 : return 0;
293 : }
294 :
295 2 : OpenCDMError opencdm_session_system_error(const struct OpenCDMSession *session)
296 : {
297 2 : kLog << debug << __func__;
298 2 : if (!session)
299 : {
300 1 : kLog << error << __func__ << ": Failed to get session system error - session is null";
301 1 : return ERROR_FAIL;
302 : }
303 1 : uint32_t err = session->getLastDrmError();
304 : // Rialto doesn't implement it yet
305 : switch (err)
306 : {
307 : default:
308 1 : return ERROR_NONE;
309 : }
310 : }
311 :
312 4 : OpenCDMError opencdm_session_update(struct OpenCDMSession *session, const uint8_t keyMessage[], uint16_t keyLength)
313 : {
314 4 : kLog << debug << __func__;
315 4 : if (!session)
316 : {
317 1 : kLog << error << __func__ << ": Session is NULL";
318 1 : return ERROR_INVALID_SESSION;
319 : }
320 3 : if (!keyMessage || keyLength == 0)
321 : {
322 1 : kLog << error << __func__ << ": keyMessage is empty";
323 1 : return ERROR_FAIL;
324 : }
325 2 : std::vector<uint8_t> license(keyMessage, keyMessage + keyLength);
326 2 : if (!session->updateSession(license))
327 : {
328 1 : kLog << error << "Failed to update the session";
329 1 : return ERROR_FAIL;
330 : }
331 :
332 1 : return ERROR_NONE;
333 2 : }
334 :
335 3 : OpenCDMError opencdm_session_remove(struct OpenCDMSession *session)
336 : {
337 3 : kLog << debug << __func__;
338 3 : OpenCDMError result = ERROR_INVALID_SESSION;
339 3 : if (session)
340 : {
341 2 : if (session->removeSession())
342 : {
343 1 : result = ERROR_NONE;
344 : }
345 : else
346 : {
347 1 : kLog << error << "Failed to remove the key session";
348 1 : result = ERROR_FAIL;
349 : }
350 : }
351 :
352 3 : return result;
353 : }
354 :
355 1 : OpenCDMError opencdm_session_resetoutputprotection(struct OpenCDMSession *session)
356 : {
357 1 : kLog << warn << __func__ << " NOT IMPLEMENTED YET";
358 1 : return ERROR_NONE;
359 : }
360 :
361 1 : OpenCDMError opencdm_session_set_parameter(struct OpenCDMSession *session, const std::string &name,
362 : const std::string &value)
363 : {
364 1 : kLog << warn << __func__ << " NOT IMPLEMENTED YET";
365 1 : return ERROR_NONE;
366 : }
367 :
368 4 : OpenCDMError opencdm_session_close(struct OpenCDMSession *session)
369 : {
370 4 : kLog << debug << __func__;
371 4 : OpenCDMError result = ERROR_INVALID_SESSION;
372 4 : if (session)
373 : {
374 3 : if (session->closeSession())
375 : {
376 2 : result = ERROR_NONE;
377 : }
378 : else
379 : {
380 1 : kLog << error << "Failed to close the key session";
381 1 : result = ERROR_FAIL;
382 : }
383 : }
384 :
385 4 : return result;
386 : }
387 :
388 2 : OpenCDMBool opencdm_system_supports_server_certificate(struct OpenCDMSystem *system)
389 : {
390 2 : kLog << debug << __func__;
391 2 : if (MediaKeysCapabilitiesBackend::instance().isServerCertificateSupported(system->keySystem()))
392 : {
393 1 : return OpenCDMBool::OPENCDM_BOOL_TRUE;
394 : }
395 1 : return OpenCDMBool::OPENCDM_BOOL_FALSE;
396 : }
397 :
398 1 : OpenCDMError opencdm_session_decrypt(struct OpenCDMSession *session, uint8_t encrypted[],
399 : const uint32_t encryptedLength, const EncryptionScheme encScheme,
400 : const EncryptionPattern pattern, const uint8_t *IV, uint16_t IVLength,
401 : const uint8_t *keyId, const uint16_t keyIdLength, uint32_t initWithLast15)
402 : {
403 1 : kLog << warn << __func__ << " not implemented";
404 1 : return ERROR_FAIL;
405 : }
406 :
407 6 : OpenCDMError opencdm_get_metric_system_data(struct OpenCDMSystem *system, uint32_t *bufferLength, uint8_t *buffer)
408 : {
409 6 : kLog << debug << __func__;
410 6 : if (!system)
411 : {
412 1 : kLog << error << "System ptr is null";
413 1 : return ERROR_FAIL;
414 : }
415 :
416 5 : if (!bufferLength)
417 : {
418 1 : kLog << error << "Buffer length ptr is null";
419 1 : return ERROR_FAIL;
420 : }
421 :
422 4 : if (!buffer)
423 : {
424 1 : kLog << error << "Buffer ptr is null";
425 1 : return ERROR_FAIL;
426 : }
427 :
428 3 : std::vector<uint8_t> bufferVec;
429 3 : if (!system->getMetricSystemData(bufferVec))
430 : {
431 1 : kLog << error << "Failed to get metric system data";
432 1 : return ERROR_FAIL;
433 : }
434 :
435 2 : if (*bufferLength < bufferVec.size())
436 : {
437 2 : kLog << error << "Buffer is too small - return size " << bufferVec.size() << " does not fit in buffer of size "
438 1 : << *bufferLength;
439 1 : return ERROR_BUFFER_TOO_SMALL;
440 : }
441 :
442 1 : std::memcpy(buffer, bufferVec.data(), bufferVec.size());
443 1 : *bufferLength = bufferVec.size();
444 1 : return ERROR_NONE;
445 3 : }
|