LCOV - code coverage report
Current view: top level - source - open_cdm.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 207 207
Test Date: 2025-07-07 09:31:15 Functions: 100.0 % 29 29

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

Generated by: LCOV version 2.0-1