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

Generated by: LCOV version 2.0-1