LCOV - code coverage report
Current view: top level - source - open_cdm.cpp (source / functions) Coverage Total Hit
Test: coverage.info Lines: 100.0 % 203 203
Test Date: 2026-03-31 11:25:48 Functions: 100.0 % 28 28

            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 : }
        

Generated by: LCOV version 2.0-1