From a36e6a696a3636f7855a714ab9724de4de395eb5 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 12 Dec 2024 05:26:18 +0000 Subject: [PATCH 01/37] Feat: Making common OCDM-PR implementation. Reason for change: *removed soc dependancy. *Added playready packages. Risks: High. Signed-off-by: fasil kv --- CMakeLists.txt | 29 ++++++++++++++++++----------- cmake/FindPlayReady.cmake | 12 ++++++++++++ 2 files changed, 30 insertions(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ffec84..f04eb20 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -15,7 +15,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -cmake_minimum_required(VERSION 2.8) +cmake_minimum_required(VERSION 3.3) project(DRMPlayready) if (DEFINED MAKE_VERBOSE) @@ -24,9 +24,9 @@ endif() set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") -set(DRM_PLUGIN_NAME "PlayReady4") +set(DRM_PLUGIN_NAME "PlayReady") -set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") +set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -w -Wno-psabi ") if(NOT CMAKE_CROSSCOMPILING) set(STAGING_DIR "${CMAKE_INSTALL_PREFIX}") @@ -37,7 +37,7 @@ endif() file(GLOB DRM_PLUGIN_INCLUDES *.h) set(DRM_PLUGIN_LIBS - ${PLAYREADY4_LIBRARIES}) + ${PLAYREADY_LIBRARIES}) set(DRM_PLUGIN_SOURCES MediaSession.cpp @@ -46,14 +46,21 @@ set(DRM_PLUGIN_SOURCES # add the library add_library(${DRM_PLUGIN_NAME} SHARED ${DRM_PLUGIN_SOURCES}) -target_compile_definitions(${DRM_PLUGIN_NAME} PRIVATE ${PLAYREADY4_FLAGS}) -target_include_directories(${DRM_PLUGIN_NAME} PRIVATE ${PLAYREADY4_INCLUDE_DIRS}) -target_include_directories(${DRM_PLUGIN_NAME} PRIVATE source/curl_prebuilt/include/curl source/inc source/modules/contentspecific/h264/real source/oem/ansi/inc source/oem/common/broker/pkImpl source/oem/common/crypto/aes source/oem/common/inc source/oem/common/trustedexec source/results source/securecore/trustedexec/base source/tools/devicedevcert/bcertdump source/tools/pseudotee/dll source/tools/shared/common source/tools/shared/netio source/tools/shared/oem source/tools/shared/remoteprovisioningmock source/trustedexec/base source/trustedexec/debug source/trustedexec/decrypt source/trustedexec/inc source/trustedexec/licprep source/trustedexec/rprov source/trustedexec/teeproxystub/common source/trustedexec/teeproxystub/proxy/common source/trustedexec/teeproxystub/stub/common) -add_compile_definitions(DRM_BUILD_PROFILE=900) -target_link_libraries(${DRM_PLUGIN_NAME} PRIVATE libplayreadypk.so) +target_compile_definitions(${DRM_PLUGIN_NAME} PRIVATE ${PLAYREADY_FLAGS}) + set_target_properties(${DRM_PLUGIN_NAME} PROPERTIES SUFFIX ".drm") set_target_properties(${DRM_PLUGIN_NAME} PROPERTIES PREFIX "") +find_package(PlayReady REQUIRED) +if(PLAYREADY_FOUND) + message(STATUS "PlayReady found!") + # message(STATUS "${PLAYREADY_INCLUDE_DIRS}") + include_directories(${PLAYREADY_INCLUDE_DIRS}) + target_link_libraries(${DRM_PLUGIN_NAME} PlayReady::PlayReady) +else() + message(FATAL_ERROR "PlayReady not found. Please install the required libraries.") +endif() + find_package(OpenSSL REQUIRED) target_link_libraries(${DRM_PLUGIN_NAME} OpenSSL::SSL) @@ -64,8 +71,8 @@ target_link_libraries(${DRM_PLUGIN_NAME} OpenSSL::SSL) target_include_directories(${DRM_PLUGIN_NAME} PRIVATE ${CMAKE_SYSROOT}/usr/include/gstreamer-1.0) target_include_directories(${DRM_PLUGIN_NAME} PRIVATE ${CMAKE_SYSROOT}/usr/include/glib-2.0) target_include_directories(${DRM_PLUGIN_NAME} PRIVATE ${CMAKE_SYSROOT}/usr/lib/glib-2.0/include) - target_include_directories(${DRM_PLUGIN_NAME} PRIVATE ${CMAKE_SYSROOT}/usr/include/realtek/genericLinux/include) - target_link_libraries(${DRM_PLUGIN_NAME} gstsvpext) + #target_link_libraries(${DRM_PLUGIN_NAME} gstsvpext) + target_link_libraries(${DRM_PLUGIN_NAME} gstamlsvpext) #endif() if("${DYNAMIC_SVP_DECRYPTION}" STREQUAL "ON") diff --git a/cmake/FindPlayReady.cmake b/cmake/FindPlayReady.cmake index b577318..9d278d8 100644 --- a/cmake/FindPlayReady.cmake +++ b/cmake/FindPlayReady.cmake @@ -47,6 +47,18 @@ if(PC_PLAYREADY_FOUND) set(PLAYREADY_LIBRARIES ${PC_PLAYREADY_LIBRARIES}) set(PLAYREADY_LIBRARY_DIRS ${PC_PLAYREADY_LIBRARY_DIRS}) endif() + + if(PC_PLAYREADY_FOUND) + find_path (PLAYREADY_INCLUDE NAME "drmmanager.h" PATHS "usr/include/" PATH_SUFFIXES "playready") + # Define the path to be removed + set(PLAYREADY_LIBRARY_REMOVE_DIRS + "${PLAYREADY_INCLUDE}/inc" + "${PLAYREADY_INCLUDE}/results" + ) + list(REMOVE_ITEM PLAYREADY_INCLUDE_DIRS ${PLAYREADY_LIBRARY_REMOVE_DIRS}) + # message(STATUS "Updated PLAYREADY_LIBRARY_DIRS: ${PLAYREADY_INCLUDE_DIRS}") + endif() + endif() include(FindPackageHandleStandardArgs) From e188c474948e33fdc5c1570fbabb0de394349bbc Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 12 Dec 2024 05:58:07 +0000 Subject: [PATCH 02/37] Fix: Fixed compilation issue in aml. Reason for change: *replaced code. *added pure virtual functions that have not been implemented. Risks: High. Signed-off-by: fasil kv --- MediaSession.cpp | 20 ++++++++++---------- MediaSystem.cpp | 30 ++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index 56f858c..7c2893c 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -27,16 +27,16 @@ #ifdef USE_SVP #include "gst_svp_meta.h" -typedef struct Sec_OpaqueBufferHandle_struct -{ - uint32_t dataBufSize; - //TEEC_Session *sess; - uint32_t align; - int ion_fd; - int map_fd; - //TEEC_SharedMemory register_shm; - void *rtkmem_handle; -} Sec_OpaqueBufferHandle; +// typedef struct Sec_OpaqueBufferHandle_struct +// { +// uint32_t dataBufSize; +// //TEEC_Session *sess; +// uint32_t align; +// int ion_fd; +// int map_fd; +// //TEEC_SharedMemory register_shm; +// void *rtkmem_handle; +// } Sec_OpaqueBufferHandle; typedef struct SecureBufferInfo_struct { diff --git a/MediaSystem.cpp b/MediaSystem.cpp index efb5fd0..e83d196 100644 --- a/MediaSystem.cpp +++ b/MediaSystem.cpp @@ -45,6 +45,30 @@ extern DRM_CONST_STRING g_dstrDrmPath; WPEFramework::Core::CriticalSection drmAppContextMutex_; +// static DRM_WCHAR* createDrmWchar(std::string const& s) { +// DRM_WCHAR* w = new DRM_WCHAR[s.length() + 1]; +// for (size_t i = 0; i < s.length(); ++i) +// w[i] = ONE_WCHAR(s[i], '\0'); +// w[s.length()] = ONE_WCHAR('\0', '\0'); +// return w; +// } + +// static void PackedCharsToNative(DRM_CHAR *f_pPackedString, DRM_DWORD f_cch) { +// DRM_DWORD ich = 0; + +// if( f_pPackedString == nullptr +// || f_cch == 0 ) +// { +// return; +// } +// for( ich = 1; ich <= f_cch; ich++ ) +// { +// f_pPackedString[f_cch - ich] = ((DRM_BYTE*)f_pPackedString)[ f_cch - ich ]; +// } +// } + +namespace CDMi { + static DRM_WCHAR* createDrmWchar(std::string const& s) { DRM_WCHAR* w = new DRM_WCHAR[s.length() + 1]; for (size_t i = 0; i < s.length(); ++i) @@ -67,8 +91,6 @@ static void PackedCharsToNative(DRM_CHAR *f_pPackedString, DRM_DWORD f_cch) { } } -namespace CDMi { - class PlayReady : public IMediaKeys, public IMediaKeysExt { private: class Config : public WPEFramework::Core::JSON::Container { @@ -171,6 +193,10 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { return CDMi_SUCCESS; } + virtual CDMi_RESULT GetMetrics(std::string& metrics){ + return CDMi_S_FALSE; + } + CDMi_RESULT SetServerCertificate( const uint8_t *f_pbServerCertificate, uint32_t f_cbServerCertificate) { CDMi_RESULT cr = CDMi_SUCCESS; From e63200c17b666916dfec00a687e776ade668f7ef Mon Sep 17 00:00:00 2001 From: kvfasil Date: Wed, 18 Dec 2024 06:29:47 +0000 Subject: [PATCH 03/37] fix: fixed runtime issue --- CMakeLists.txt | 5 +++-- MediaSystem.cpp | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f04eb20..5f94936 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -24,7 +24,7 @@ endif() set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") -set(DRM_PLUGIN_NAME "PlayReady") +set(DRM_PLUGIN_NAME "Playready") set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -w -Wno-psabi ") @@ -56,7 +56,8 @@ if(PLAYREADY_FOUND) message(STATUS "PlayReady found!") # message(STATUS "${PLAYREADY_INCLUDE_DIRS}") include_directories(${PLAYREADY_INCLUDE_DIRS}) - target_link_libraries(${DRM_PLUGIN_NAME} PlayReady::PlayReady) + include_directories(${PLAYREADY_LIBRARIES}) + target_link_libraries(${DRM_PLUGIN_NAME} playready-4.4) else() message(FATAL_ERROR "PlayReady not found. Please install the required libraries.") endif() diff --git a/MediaSystem.cpp b/MediaSystem.cpp index e83d196..13ef6d1 100644 --- a/MediaSystem.cpp +++ b/MediaSystem.cpp @@ -737,6 +737,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { void Initialize(const WPEFramework::PluginHost::IShell * service, const std::string& configline) { + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); OnSystemConfigurationAvailable(configline); } @@ -760,6 +761,6 @@ static SystemFactoryType g_instance({"video/x-h264", "audio/mpeg"}); } // namespace CDMi CDMi::ISystemFactory* GetSystemFactory() { - + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); return (&CDMi::g_instance); } From d1fce070231e80a2a47af7ae13baddab59c6ba18 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Wed, 18 Dec 2024 06:33:38 +0000 Subject: [PATCH 04/37] Update: updated CMakelists. --- CMakeLists.txt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5f94936..62ac688 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -98,3 +98,10 @@ else() endif() install(TARGETS ${DRM_PLUGIN_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/WPEFramework/OCDM) + +if(NOT "${CMAKE_FIND_ROOT_PATH}" STREQUAL "") + install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink /etc/playready ${CMAKE_CURRENT_BINARY_DIR}/playready)") + install(DIRECTORY DESTINATION ${CMAKE_INSTALL_PREFIX}/../${PERSISTENT_PATH}/OCDM) + install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/playready DESTINATION ${CMAKE_INSTALL_PREFIX}/../${PERSISTENT_PATH}/OCDM/) +endif() + From db50e988b031f68b1a6e58453518df65b55c33cc Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 19 Dec 2024 05:46:26 +0000 Subject: [PATCH 05/37] feat: adding macro for compilations. --- CMakeLists.txt | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 62ac688..f696b5b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -34,6 +34,9 @@ else() set(STAGING_DIR "${CMAKE_FIND_ROOT_PATH}") endif() +add_definitions(-DAML_SVP_PR) +add_definitions(-DPR_4_4) + file(GLOB DRM_PLUGIN_INCLUDES *.h) set(DRM_PLUGIN_LIBS From fe31916161640b9a5538b1f222af365988516909 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 19 Dec 2024 08:33:38 +0000 Subject: [PATCH 06/37] fix: fixed runtime issue. aligned code from rdkcentral. --- MediaSession.cpp | 2397 +++++++++---------------------------------- MediaSession.h | 187 +++- MediaSessionExt.cpp | 401 +++++--- MediaSystem.cpp | 381 ++++--- 4 files changed, 1086 insertions(+), 2280 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index 7c2893c..7106325 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -14,6 +14,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #include "MediaSession.h" #include #include @@ -22,36 +23,15 @@ #include #include #include -#include - -#ifdef USE_SVP +//#include #include "gst_svp_meta.h" -// typedef struct Sec_OpaqueBufferHandle_struct -// { -// uint32_t dataBufSize; -// //TEEC_Session *sess; -// uint32_t align; -// int ion_fd; -// int map_fd; -// //TEEC_SharedMemory register_shm; -// void *rtkmem_handle; -// } Sec_OpaqueBufferHandle; - -typedef struct SecureBufferInfo_struct -{ - uint32_t secureBufSize; - void *pSecBufHandle; - void *pPhysAddr; - void *pVirtualAddr; - uint32_t align; - int ion_fd; - int map_fd; -} SecureBufferInfo; - -#endif +using namespace WPEFramework; +using SafeCriticalSection = Core::SafeSyncType; +MODULE_NAME_DECLARATION(BUILD_REFERENCE); -extern WPEFramework::Core::CriticalSection drmAppContextMutex_; +extern Core::CriticalSection drmAppContextMutex_; +extern DRM_CONST_STRING g_dstrCDMDrmStoreName; #define NYI_KEYSYSTEM "keysystem-placeholder" @@ -71,180 +51,20 @@ extern WPEFramework::Core::CriticalSection drmAppContextMutex_; #define NO_OF DRM_NO_OF #endif -#define DEVCERT_WAIT_SECS 30 -#define DEVCERT_RETRY_MAX 4 - -#define EXPECTED_AES_CTR_IVDATA_SIZE (8) -#define EXPECTED_AES_CBC_IVDATA_SIZE (16) using namespace std; -KeyId::KeyId( const DRM_BYTE *f_pBytes , KeyIdOrder keyOrder) -{ - m_hexStr.clear(); - m_base64Str.clear(); - ZEROMEM( m_bytes, DRM_ID_SIZE ); - keyIdOrder = KEYID_ORDER_UNKNOWN; - memcpy( m_bytes, f_pBytes, DRM_ID_SIZE ); - keyIdOrder = keyOrder; -} - -DRM_RESULT KeyId::keyDecode( const DRM_CONST_STRING &f_pdstrB64 ){ - - DRM_DWORD cBytes = DRM_ID_SIZE; - DRM_RESULT dr = DRM_B64_DecodeW( &f_pdstrB64, &cBytes, getmBytes(), 0 ); - if ( dr != DRM_SUCCESS ) - { - fprintf(stderr, "\n[keyDecode] DRM_B64_DecodeW Failed"); - } - return dr; -} - -void KeyId::setKeyIdOrder(KeyIdOrder keyOrder) -{ - keyIdOrder = keyOrder; -} - -KeyId::KeyIdOrder KeyId::getKeyIdOrder() -{ - return keyIdOrder; -} - -const DRM_BYTE* KeyId::getmBytes() -{ - return m_bytes; -} - -KeyId& KeyId::ToggleFormat() -{ - DRM_BYTE tmp; - - if ( keyIdOrder != KEYID_ORDER_UNKNOWN ) - { - tmp = m_bytes[3]; - m_bytes[3] = m_bytes[0]; - m_bytes[0] = tmp; - tmp = m_bytes[2]; - m_bytes[2] = m_bytes[1]; - m_bytes[1] = tmp; - tmp = m_bytes[5]; - m_bytes[5] = m_bytes[4]; - m_bytes[4] = tmp; - tmp = m_bytes[7]; - m_bytes[7] = m_bytes[6]; - m_bytes[6] = tmp; - - if ( keyIdOrder == KEYID_ORDER_GUID_LE ) - keyIdOrder = KEYID_ORDER_UUID_BE; - else - keyIdOrder = KEYID_ORDER_GUID_LE; - } - m_hexStr.clear(); - m_base64Str.clear(); - - return *this; -} - -bool KeyId::operator< ( const KeyId &keyId ) const -{ - if ( memcmp(keyId.m_bytes, m_bytes, DRM_ID_SIZE) < 0 ) - return true; - return false; -} - -bool KeyId::operator== ( const KeyId &keyId ) -{ - bool areEqual = false; - - if ( memcmp(&m_bytes[8], &(keyId.m_bytes[8]), 8) == 0 ) - { - if ( memcmp(keyId.m_bytes, m_bytes, 8) == 0 ) - { - areEqual = true; - } - else - { - ToggleFormat(); - areEqual = ( memcmp(keyId.m_bytes, m_bytes, DRM_ID_SIZE ) == 0 ); - ToggleFormat(); - } - } - - return areEqual; -} - -const char* KeyId::HexStr() -{ - if ( m_hexStr.empty() ) - { - char hex[64]; - ::memset(hex, 0, 64); - for (int i = 0; i < DRM_ID_SIZE; i++) - { - hex[i * 2] = "0123456789abcdef"[m_bytes[i] >> 4]; - hex[i * 2 + 1] = "0123456789abcdef"[m_bytes[i] & 0x0F]; - } - m_hexStr = hex; - } - - return m_hexStr.c_str(); -} - -const char* KeyId::B64Str() -{ - DRM_RESULT dr = DRM_SUCCESS; - if ( m_base64Str.empty() ) - { - char b64[64]; - DRM_DWORD cbB64 = 64; - ::memset( b64, 0, 64 ); - PR4ChkDR( DRM_B64_EncodeA( m_bytes, DRM_ID_SIZE, b64, &cbB64, 0 ) ); - - m_base64Str = b64; - } - - ErrorExit: - - return m_base64Str.c_str(); -} - namespace CDMi { -namespace { - -void Swap(uint8_t& lhs, uint8_t& rhs) -{ - uint8_t tmp =lhs; - lhs = rhs; - rhs = tmp; -} - -} - -DRM_INIT_CONTEXT g_oDrmInitContext = { "/opt/drm", "/opt/drm/sample.hds" }; - -const DRM_WCHAR g_rgwchCDMDrmStoreName[] = {WCHAR_CAST('/'), WCHAR_CAST('o'), WCHAR_CAST('p'), WCHAR_CAST('t'), WCHAR_CAST('/'), - WCHAR_CAST('d'), WCHAR_CAST('r'), WCHAR_CAST('m'), WCHAR_CAST('/'), WCHAR_CAST('s'), - WCHAR_CAST('a'), WCHAR_CAST('m'), WCHAR_CAST('p'), WCHAR_CAST('l'), WCHAR_CAST('e'), - WCHAR_CAST('.'), WCHAR_CAST('h'), WCHAR_CAST('d'), WCHAR_CAST('s'), WCHAR_CAST('\0')}; - -const DRM_WCHAR g_rgwchCDMDrmPath[] = {WCHAR_CAST('/'), WCHAR_CAST('o'), WCHAR_CAST('p'), WCHAR_CAST('t'), WCHAR_CAST('/'), - WCHAR_CAST('d'), WCHAR_CAST('r'), WCHAR_CAST('m'), WCHAR_CAST('\0')}; - -const DRM_CONST_STRING g_dstrCDMDrmStoreName = CREATE_DRM_STRING(g_rgwchCDMDrmStoreName); -const DRM_CONST_STRING g_dstrCDMDrmPath = CREATE_DRM_STRING(g_rgwchCDMDrmPath); - -DRM_BOOL MediaKeySession::m_bPrintOPLError = true; - const DRM_CONST_STRING *g_rgpdstrRights[1] = {&g_dstrDRM_RIGHT_PLAYBACK}; -uint64_t MediaKeySession::mMaxResDecodePixels = 0; -bool MediaKeySession::mMaxResDecodeSet = false; +void * MediaKeySession::sess = NULL; +uint32_t MediaKeySession::m_secCount = 0; -WPEFramework::Core::CriticalSection prPlatformMutex_; -WPEFramework::Core::CriticalSection prSessionMutex_; -DRM_DWORD CPRDrmPlatform::m_dwInitRefCount = 0; - -/*Parsing the first playready init header from _initData_. In success case the header will be stored in _output_*/ +// Parse out the first PlayReady initialization header found in the concatenated +// block of headers in _initData_. +// If a PlayReady header is found, this function returns true and the header +// contents are stored in _output_. +// Otherwise, returns false and _output_ is not touched. bool parsePlayreadyInitializationData(const std::string& initData, std::string* output) { BufferReader input(reinterpret_cast(initData.data()), initData.length()); @@ -252,12 +72,23 @@ bool parsePlayreadyInitializationData(const std::string& initData, std::string* static const uint8_t playreadySystemId[] = { 0x9A, 0x04, 0xF0, 0x79, 0x98, 0x40, 0x42, 0x86, 0xAB, 0x92, 0xE6, 0x5B, 0xE0, 0x88, 0x5F, 0x95, - }; + // one PSSH box consists of: + // 4 byte size of the atom, inclusive. (0 means the rest of the buffer.) + // 4 byte atom type, "pssh". + // (optional, if size == 1) 8 byte size of the atom, inclusive. + // 1 byte version, value 0 or 1. (skip if larger.) + // 3 byte flags, value 0. (ignored.) + // 16 byte system id. + // (optional, if version == 1) 4 byte key ID count. (K) + // (optional, if version == 1) K * 16 byte key ID. + // 4 byte size of PSSH data, exclusive. (N) + // N byte PSSH data. while (!input.IsEOF()) { size_t startPosition = input.pos(); + // The atom size, used for skipping. uint64_t atomSize; if (!input.Read4Into8(&atomSize)) { @@ -291,22 +122,26 @@ bool parsePlayreadyInitializationData(const std::string& initData, std::string* if (version > 1) { + // unrecognized version - skip. if (!input.SkipBytes(atomSize - (input.pos() - startPosition))) { return false; } continue; } + // flags if (!input.SkipBytes(3)) { return false; } + // system id std::vector systemId; if (!input.ReadVec(&systemId, sizeof(playreadySystemId))) { return false; } if (memcmp(&systemId[0], playreadySystemId, sizeof(playreadySystemId))) { + // skip non-Playready PSSH boxes. if (!input.SkipBytes(atomSize - (input.pos() - startPosition))) { return false; } @@ -314,6 +149,7 @@ bool parsePlayreadyInitializationData(const std::string& initData, std::string* } if (version == 1) { + // v1 has additional fields for key IDs. We can skip them. uint32_t numKeyIds; if (!input.Read4(&numKeyIds)) { return false; @@ -324,6 +160,7 @@ bool parsePlayreadyInitializationData(const std::string& initData, std::string* } } + // size of PSSH data uint32_t dataLength; if (!input.Read4(&dataLength)) { return false; @@ -337,324 +174,144 @@ bool parsePlayreadyInitializationData(const std::string& initData, std::string* return true; } + // we did not find a matching record return false; } -DRM_RESULT CPRDrmPlatform::DrmPlatformInitialize( DRM_INIT_CONTEXT *f_pContext ) -{ - DRM_RESULT dr = DRM_SUCCESS; - SafeCriticalSection systemLock(prPlatformMutex_); - - if ( ++m_dwInitRefCount == 1 ) - { - DRM_RESULT dr = DRM_SUCCESS; - DRM_DWORD cAttempts = 0; - - while( ( dr=Drm_Platform_Initialize( f_pContext ) ) == DRM_E_DEPRECATED_DEVCERT_READ_ERROR) { - Drm_Platform_Uninitialize( (void *)nullptr ); - - if ( cAttempts >= DEVCERT_RETRY_MAX ){ - ChkDR( DRM_E_DEPRECATED_DEVCERT_READ_ERROR); - } - sleep( DEVCERT_WAIT_SECS ); - ++cAttempts; - } - } - - ErrorExit: - - if ( DRM_FAILED( dr ) ) - { - --m_dwInitRefCount; - fprintf(stderr, "[%s:%d] failed. 0x%X - app_dir=%s, global_dir=%s",__FUNCTION__,__LINE__,dr,f_pContext->pszApplicationDir,f_pContext->pszGlobalDir); - } - - return dr; -} - -DRM_RESULT CPRDrmPlatform::DrmPlatformInitialize() -{ - return DrmPlatformInitialize( &g_oDrmInitContext ); -} - -DRM_RESULT CPRDrmPlatform::DrmPlatformUninitialize() -{ - DRM_RESULT dr = DRM_SUCCESS; - - SafeCriticalSection systemLock(prPlatformMutex_); - - if ( m_dwInitRefCount == 0 ) - { - fprintf(stderr, "[%s:%d] ref count is already 0",__FUNCTION__,__LINE__); - ChkDR( DRM_E_FAIL ); - } - else if ( --m_dwInitRefCount == 0 ) - { - if ( DRM_FAILED( (dr=Drm_Platform_Uninitialize( (void *)nullptr ) ) ) ) - { - fprintf(stderr, "[%s:%d] Drm_Platform_Uninitialize failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); - goto ErrorExit; - } - } - - ErrorExit: - - if ( DRM_FAILED( dr ) ) - { - fprintf(stderr, "[%s:%d] failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); - } - - return dr; - -} - -/*Get the version and list of keyids from the header*/ -DRM_RESULT Header_GetInfo( - const DRM_CONST_STRING *f_pdstrWRMHEADER, - eDRM_HEADER_VERSION *f_pHeaderVersion, - DRM_CONST_STRING **f_ppdstrKIDs, - DRM_DWORD *f_pcbKIDs) -{ - DRM_RESULT dr = DRM_SUCCESS; - DRM_DWORD cKIDs = 0; - DRM_CONST_STRING *pdstrKIDs = NULL; - - PR4ChkDR( DRM_HDR_GetHeaderVersion( f_pdstrWRMHEADER, f_pHeaderVersion ) ); - - PR4ChkDR( DRM_HDR_GetAttribute( - f_pdstrWRMHEADER, - NULL, - DRM_HEADER_ATTRIB_KIDS, - NULL, - &cKIDs, - &pdstrKIDs, - 0 ) ); - - *f_ppdstrKIDs = pdstrKIDs; - *f_pcbKIDs = cKIDs; - -ErrorExit: - return dr; -} - -PlayreadySession::PlayreadySession() - : m_poAppContext(nullptr) - , m_pbPROpaqueBuf(nullptr) - , m_cbPROpaqueBuf(0) - , m_bInitCalled(false) -{ - - if ( DRM_FAILED( CPRDrmPlatform::DrmPlatformInitialize( &g_oDrmInitContext ) ) ) - { - fprintf(stderr, "[%s:%d] DrmPlatformInitialize failed.",__FUNCTION__,__LINE__); - } -} - -PlayreadySession::~PlayreadySession() -{ - SafeCriticalSection systemLock(prSessionMutex_); - - if ( IsPlayreadySessionInit() ) - { - SAFE_OEM_FREE(m_pbPROpaqueBuf); - m_cbPROpaqueBuf = 0; - - if (m_poAppContext != nullptr) - { - Drm_Uninitialize(m_poAppContext); - SAFE_OEM_FREE(m_poAppContext); - m_poAppContext = nullptr; - } - } - - if (DRM_FAILED(CPRDrmPlatform::DrmPlatformUninitialize())) - { - fprintf(stderr, "[%s:%d] DrmPlatformUninitialize failed.",__FUNCTION__,__LINE__); - } - -} - -DRM_APP_CONTEXT * PlayreadySession::InitializeDRM(const DRM_CONST_STRING * pDRMStoreName) -{ - DRM_RESULT dr = DRM_SUCCESS; - - SafeCriticalSection systemLock(prSessionMutex_); - - m_bInitCalled = true; - - if (m_poAppContext == nullptr) - { - ChkMem( m_pbPROpaqueBuf = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE) ); - ZEROMEM(m_pbPROpaqueBuf, MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE); - m_cbPROpaqueBuf = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; - - ChkMem( m_poAppContext = (DRM_APP_CONTEXT * )Oem_MemAlloc( sizeof(DRM_APP_CONTEXT) ) ); - ZEROMEM( m_poAppContext, sizeof(DRM_APP_CONTEXT) ); - - dr = Drm_Initialize(m_poAppContext, nullptr, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName); - if (dr != DRM_SUCCESS) - { - ChkDR(Drm_Initialize(m_poAppContext, nullptr, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName)); - } - } - else - { - DRM_RESULT err = Drm_Reinitialize(m_poAppContext); - if (DRM_FAILED(err)) - { - fprintf(stderr, "[%s:%d] Drm_Reinitialize failed. 0x%lX - %s",__FUNCTION__,__LINE__,(long )err,DRM_ERR_NAME(err)); - } - } - - return m_poAppContext; - -ErrorExit: - if (DRM_FAILED(dr)) { - fprintf(stderr, "[%s:%d] failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); - } - return nullptr; -} - MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitData, const uint8_t *f_pbCDMData, uint32_t f_cbCDMData, DRM_APP_CONTEXT * poAppContext, bool initiateChallengeGeneration /* = false */) - : m_pbRevocationBuffer(nullptr) - , m_eKeyState(KEY_CLOSED) + : m_pbOpaqueBuffer(nullptr) + , m_cbOpaqueBuffer(0) + , m_pbRevocationBuffer(nullptr) + , m_eKeyState(KEY_INIT) , m_pbChallenge(nullptr) , m_cbChallenge(0) - , m_pchSilentURL(nullptr) + , m_pchSilentURL(nullptr) , m_customData(reinterpret_cast(f_pbCDMData), f_cbCDMData) , m_piCallback(nullptr) , mSessionId(0) - , mInitiateChallengeGeneration(initiateChallengeGeneration) - , m_cHeaderKIDs(0) - , m_pdstrHeaderKIDs( nullptr ) - , m_eHeaderVersion( DRM_HEADER_VERSION_UNKNOWN ) - , m_oBatchID( DRM_ID_EMPTY ) - , m_currentDecryptContext( nullptr ) -#ifdef USE_SVP - , m_pSVPContext(nullptr) - , m_rpcID(0) -#endif , m_fCommit(FALSE) + , mInitiateChallengeGeneration(initiateChallengeGeneration) , m_poAppContext(poAppContext) + , m_oDecryptContext(nullptr) + , m_oDecryptContext2(nullptr) , m_decryptInited(false) - , m_bDRMInitializedLocally(false) + , m_pSVPContext(NULL) + , m_rpcID(0) { - DRM_RESULT dr = DRM_SUCCESS; - DRM_ID oSessionID = DRM_ID_EMPTY; - DRM_CONST_STRING dstrWRMHEADER = DRM_EMPTY_DRM_STRING; - - DRM_DWORD cchEncodedSessionID = SIZEOF(m_rgchSessionID); + memset(&levels_, 0, sizeof(levels_)); + DRM_RESULT dr = DRM_SUCCESS; + + ocdm_log("Initializing SVP context for client side\n"); + gst_svp_ext_get_context(&m_pSVPContext, Client, m_rpcID); + + if (!initiateChallengeGeneration) { + mLicenseResponse = std::unique_ptr(new LicenseResponse()); + mSecureStopId.clear(); + + // TODO: can we do this nicer? + mDrmHeader.resize(f_cbCDMData); + memcpy(&mDrmHeader[0], f_pbCDMData, f_cbCDMData); + m_secCount++; + } else { + m_oDecryptContext = new DRM_DECRYPT_CONTEXT; + memset(m_oDecryptContext, 0, sizeof(DRM_DECRYPT_CONTEXT)); + m_oDecryptContext2 = new DRM_DECRYPT_CONTEXT; + memset(m_oDecryptContext2, 0, sizeof(DRM_DECRYPT_CONTEXT)); + + DRM_ID oSessionID; + + DRM_DWORD cchEncodedSessionID = SIZEOF(m_rgchSessionID); + + // FIXME: Change the interface of this method? Not sure why the win32 bondage is still so popular. + std::string initData(reinterpret_cast(f_pbInitData), f_cbInitData); + std::string playreadyInitData; + + ocdm_log("Constructing PlayReady Session [%p]\n", this); + + ChkMem(m_pbOpaqueBuffer = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE)); + m_cbOpaqueBuffer = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; +#ifndef REUSE_APPCONTEXT + ChkMem(m_poAppContext = (DRM_APP_CONTEXT *)Oem_MemAlloc(SIZEOF(DRM_APP_CONTEXT))); + + // Initialize DRM app context. + dr = Drm_Initialize(m_poAppContext, + nullptr, + m_pbOpaqueBuffer, + m_cbOpaqueBuffer, + &g_dstrCDMDrmStoreName); + if ((dr == DRM_E_SECURESTOP_STORE_CORRUPT) || \ + (dr == DRM_E_SECURESTORE_CORRUPT) || \ + (dr == DRM_E_DST_CORRUPTED)){ + + ocdm_log( "%s:%d drmstore corrrupt, delete it !!!!\n", __FUNCTION__, __LINE__); + //if drmstore file is corrupted, remove it and init again, playready will create a new one + remove(GetDrmStorePath().c_str()); + + dr = Drm_Initialize(m_poAppContext, + nullptr, + m_pbOpaqueBuffer, + m_cbOpaqueBuffer, + &g_dstrCDMDrmStoreName); + } + ChkDR(dr); + if (DRM_REVOCATION_IsRevocationSupported()) { + ChkMem(m_pbRevocationBuffer = (DRM_BYTE *)Oem_MemAlloc(REVOCATION_BUFFER_SIZE)); -#ifdef USE_SVP - gst_svp_ext_get_context(&m_pSVPContext, Client, 0); + ChkDR(Drm_Revocation_SetBuffer(m_poAppContext, + m_pbRevocationBuffer, + REVOCATION_BUFFER_SIZE)); + } #endif - std::string initData(reinterpret_cast(f_pbInitData), f_cbInitData); - std::string playreadyInitData; - - ChkBOOL(m_eKeyState == KEY_CLOSED, DRM_E_INVALIDARG); - - mMaxResDecodePixels = 0; - mMaxResDecodeSet = false; - - g_dstrDrmPath = g_dstrCDMDrmPath; - - if (m_poAppContext == nullptr) { - m_poAppContext = InitializeDRM(&g_dstrCDMDrmStoreName); - } - - if (DRM_REVOCATION_IsRevocationSupported()) { - ChkMem(m_pbRevocationBuffer = (DRM_BYTE *)Oem_MemAlloc(REVOCATION_BUFFER_SIZE)); - - ChkDR(Drm_Revocation_SetBuffer(m_poAppContext, - m_pbRevocationBuffer, - REVOCATION_BUFFER_SIZE)); - } - - m_bPrintOPLError = true; - - ChkDR(Oem_Random_GetBytes(nullptr, (DRM_BYTE *)&oSessionID, SIZEOF(oSessionID))); - ZEROMEM(m_rgchSessionID, SIZEOF(m_rgchSessionID)); - - ChkDR(DRM_B64_EncodeA((DRM_BYTE *)&oSessionID, - SIZEOF(oSessionID), - m_rgchSessionID, - &cchEncodedSessionID, - 0)); - - if (!parsePlayreadyInitializationData(initData, &playreadyInitData)) { - playreadyInitData = initData; - } - - mDrmHeader.resize( playreadyInitData.size() ); - ::memcpy( &mDrmHeader[ 0 ], - reinterpret_cast(playreadyInitData.data()), - playreadyInitData.size() ); +#ifdef PR_4_4 + //temporary hack to allow time based licenses + ( DRM_REINTERPRET_CAST( DRM_APP_CONTEXT_INTERNAL, m_poAppContext ) )->fClockSet = TRUE; +#endif - ChkDR(Drm_Content_SetProperty(m_poAppContext, - DRM_CSP_AUTODETECT_HEADER, - &mDrmHeader[ 0 ], - mDrmHeader.size()) ); + // Generate a random media session ID. + ChkDR(Oem_Random_GetBytes(nullptr, (DRM_BYTE *)&oSessionID, SIZEOF(oSessionID))); + ZEROMEM(m_rgchSessionID, SIZEOF(m_rgchSessionID)); - DRM_CONST_DSTR_FROM_PB( &dstrWRMHEADER, &mDrmHeader[ 0 ], mDrmHeader.size() ); + // Store the generated media session ID in base64 encoded form. + ChkDR(DRM_B64_EncodeA((DRM_BYTE *)&oSessionID, + SIZEOF(oSessionID), + m_rgchSessionID, + &cchEncodedSessionID, + 0)); - ChkDR( Header_GetInfo( &dstrWRMHEADER, - &m_eHeaderVersion, - &m_pdstrHeaderKIDs, - &m_cHeaderKIDs ) ); + // The current state MUST be KEY_INIT otherwise error out. + ChkBOOL(m_eKeyState == KEY_INIT, DRM_E_INVALIDARG); - for( DRM_DWORD idx = 0; idx < m_cHeaderKIDs; idx++ ) - { - KeyId kid , kid2; - DRM_DWORD cBytes = DRM_ID_SIZE; - DRM_DWORD cBytes2 = DRM_ID_SIZE; - - DRM_RESULT dr = DRM_B64_DecodeW( &m_pdstrHeaderKIDs[ idx ], &cBytes, kid.getmBytes(), 0 ); - if ( dr == DRM_SUCCESS ) - { - kid.setKeyIdOrder(KeyId::KEYID_ORDER_GUID_LE); - } - - DRM_RESULT dr2 = DRM_B64_DecodeW( &m_pdstrHeaderKIDs[ idx ], &cBytes2, kid2.getmBytes(), 0 ); - if ( dr2 == DRM_SUCCESS ) - { - kid2.setKeyIdOrder(KeyId::KEYID_ORDER_GUID_LE); - } + if (!parsePlayreadyInitializationData(initData, &playreadyInitData)) { + playreadyInitData = initData; } + ChkDR(Drm_Content_SetProperty(m_poAppContext, + DRM_CSP_AUTODETECT_HEADER, + reinterpret_cast(playreadyInitData.data()), + playreadyInitData.size())); - m_eKeyState = KEY_INIT; + // The current state MUST be KEY_INIT otherwise error out. + ChkBOOL(m_eKeyState == KEY_INIT, DRM_E_INVALIDARG); + m_secCount++; + return; + } ErrorExit: - - if (DRM_FAILED(dr)) - { - m_eKeyState = KEY_ERROR; - fprintf(stderr, "[%s:%d] Playready initialization error: 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); - } - - return; -} - -MediaKeySession::~MediaKeySession(void) -{ - mMaxResDecodePixels = 0; - mMaxResDecodeSet = false; - Close(); - -} - -const char* MediaKeySession::printGuid(KeyId &keyId) -{ - if (keyId.getKeyIdOrder() == KeyId::KEYID_ORDER_UUID_BE) - keyId.ToggleFormat(); - return keyId.B64Str(); + if (DRM_FAILED(dr)) { + const DRM_CHAR* description; + DRM_ERR_GetErrorNameFromCode(dr, &description); + ocdm_log("playready error1: %s\n", description); + } } -const char* MediaKeySession::printUuid(KeyId &keyId) -{ - if (keyId.getKeyIdOrder() == KeyId::KEYID_ORDER_GUID_LE) - keyId.ToggleFormat(); - return keyId.B64Str(); +MediaKeySession::~MediaKeySession(void) { + gst_svp_ext_free_context(m_pSVPContext); + Close(); + if (--m_secCount == 0) { + svp_release_secure_buffers(m_pSVPContext, sess, nullptr, nullptr, 0); // Secure_V2_SessionDestroy(&sess); + } + sess = NULL; + ocdm_log("Destructing PlayReady Session [%p]\n", this); } const char *MediaKeySession::GetSessionId(void) const { @@ -662,63 +319,27 @@ const char *MediaKeySession::GetSessionId(void) const { } const char *MediaKeySession::GetKeySystem(void) const { - return NYI_KEYSYSTEM; + return NYI_KEYSYSTEM; // FIXME : replace with keysystem and test. } DRM_RESULT DRM_CALL MediaKeySession::_PolicyCallback( - const DRM_VOID *f_pvOutputLevelsData, + const DRM_VOID *f_pvOutputLevelsData, DRM_POLICY_CALLBACK_TYPE f_dwCallbackType, +#ifdef PR_4_4 const DRM_KID *f_pKID, const DRM_LID *f_pLID, +#endif const DRM_VOID *f_pv) { - DRM_RESULT res = DRM_SUCCESS; - - switch (f_dwCallbackType) - { - case DRM_PLAY_OPL_CALLBACK: - { - const DRM_PLAY_OPL_LATEST * const opl = static_cast(f_pvOutputLevelsData); - assert(opl->dwVersion == VER_DRM_PLAY_OPL_LATEST); - - /* MaxResDecode */ - const DRM_DIGITAL_VIDEO_OUTPUT_PROTECTION_IDS_LATEST &dvopi = opl->dvopi; - assert(dvopi.dwVersion == VER_DRM_DIGITAL_VIDEO_OUTPUT_PROTECTION_IDS_LATEST); - for (size_t i = 0; i < dvopi.cEntries; ++i) - { - const DRM_OUTPUT_PROTECTION_LATEST &entry = dvopi.rgVop[i]; - if (DRM_IDENTICAL_GUIDS(&entry.guidId, &g_guidMaxResDecode)) - { - assert(entry.dwVersion == VER_DRM_DIGITAL_VIDEO_OUTPUT_PROTECTION_LATEST); - - uint32_t mrdWidth = (uint32_t)(entry.rgbConfigData[0] << 24 | entry.rgbConfigData[1] << 16 | entry.rgbConfigData[2] << 8 | entry.rgbConfigData[3]); - uint32_t mrdHeight = (uint32_t)(entry.rgbConfigData[4] << 24 | entry.rgbConfigData[5] << 16 | entry.rgbConfigData[6] << 8 | entry.rgbConfigData[7]); - - - mMaxResDecodePixels = mrdWidth*mrdHeight; - mMaxResDecodeSet = true; - res = DRM_SUCCESS; - break; - } - } - break; - } - default: - // ignored - res = DRM_SUCCESS; - break; - } - - return res; + return DRM_SUCCESS; } void MediaKeySession::Run(const IMediaKeySessionCallback *f_piMediaKeySessionCallback) { + if (f_piMediaKeySessionCallback) { m_piCallback = const_cast(f_piMediaKeySessionCallback); if (mInitiateChallengeGeneration) { - if ( CDMi_SUCCESS != PersistentLicenseCheck() ) { - playreadyGenerateKeyRequest(); - } + playreadyGenerateKeyRequest(); } } else { m_piCallback = nullptr; @@ -729,1503 +350,461 @@ bool MediaKeySession::playreadyGenerateKeyRequest() { DRM_RESULT dr = DRM_SUCCESS; DRM_DWORD cchSilentURL = 0; - - SAFE_OEM_FREE( m_pbChallenge ); - SAFE_OEM_FREE( m_pchSilentURL ); - m_cbChallenge = 0; - - ChkDR(Drm_Content_SetProperty(m_poAppContext, - DRM_CSP_AUTODETECT_HEADER, - &mDrmHeader[ 0 ], - mDrmHeader.size()) ); +#ifdef PR_4_4 + dr = Drm_Reader_Bind(m_poAppContext, + g_rgpdstrRights, + DRM_NO_OF(g_rgpdstrRights), + _PolicyCallback, + nullptr, + m_oDecryptContext); +#endif + // FIXME : Check add case Play rights already acquired + // Try to figure out the size of the license acquisition + // challenge to be returned. dr = Drm_LicenseAcq_GenerateChallenge(m_poAppContext, g_rgpdstrRights, sizeof(g_rgpdstrRights) / sizeof(DRM_CONST_STRING *), - nullptr, + NULL, !m_customData.empty() ? m_customData.c_str() : nullptr, m_customData.size(), - nullptr, + NULL, &cchSilentURL, - nullptr, - nullptr, + NULL, + NULL, +#ifdef PR_4_4 m_pbChallenge, &m_cbChallenge, - &m_oBatchID ); - - if ( dr == DRM_E_NO_URL ) - { + NULL); +#else + NULL, + &m_cbChallenge); +#endif + if (dr == DRM_E_NO_URL) { + cchSilentURL = 0; dr = Drm_LicenseAcq_GenerateChallenge(m_poAppContext, g_rgpdstrRights, sizeof(g_rgpdstrRights) / sizeof(DRM_CONST_STRING *), - nullptr, + NULL, !m_customData.empty() ? m_customData.c_str() : nullptr, - m_customData.size() , - nullptr, - nullptr, // null pointer to buffer size - nullptr, - nullptr, + m_customData.size(), + NULL, + NULL, + NULL, + NULL, +#ifdef PR_4_4 m_pbChallenge, &m_cbChallenge, - &m_oBatchID ); + NULL); +#else + NULL, + &m_cbChallenge); +#endif } + if (dr == DRM_E_BUFFERTOOSMALL) { + SAFE_OEM_FREE(m_pchSilentURL); + ChkMem(m_pchSilentURL = (DRM_CHAR *)Oem_MemAlloc(cchSilentURL + 1)); + ZEROMEM(m_pchSilentURL, cchSilentURL + 1); - if (dr == DRM_E_BUFFERTOOSMALL) - { - if (cchSilentURL > 0) - { - ChkMem( m_pchSilentURL = (DRM_CHAR * )Oem_MemAlloc(cchSilentURL + 1)); - ZEROMEM( m_pchSilentURL, cchSilentURL + 1 ); - } - - if ( m_cbChallenge > 0 ) - { - ChkMem( m_pbChallenge = (DRM_BYTE * )Oem_MemAlloc( m_cbChallenge + 1 ) ); - ZEROMEM( m_pbChallenge, m_cbChallenge + 1 ); - } + // Allocate buffer that is sufficient to store the license acquisition + // challenge. + if (m_cbChallenge > 0) + ChkMem(m_pbChallenge = (DRM_BYTE *)Oem_MemAlloc(m_cbChallenge)); dr = DRM_SUCCESS; - } - else - { + } else { ChkDR(dr); } + ocdm_log("%s\n", m_customData.empty() ? m_customData.c_str() : nullptr); + // Supply a buffer to receive the license acquisition challenge. ChkDR(Drm_LicenseAcq_GenerateChallenge(m_poAppContext, g_rgpdstrRights, sizeof(g_rgpdstrRights) / sizeof(DRM_CONST_STRING *), NULL, !m_customData.empty() ? m_customData.c_str() : nullptr, m_customData.size(), - m_pchSilentURL, - cchSilentURL ? &cchSilentURL : nullptr, + cchSilentURL > 0 ? m_pchSilentURL : NULL, + cchSilentURL > 0 ? &cchSilentURL: NULL, nullptr, nullptr, m_pbChallenge, +#ifdef PR_4_4 &m_cbChallenge, - &m_oBatchID ) ); + nullptr)); +#else + &m_cbChallenge)); +#endif m_eKeyState = KEY_PENDING; - if (m_piCallback) - m_piCallback->OnKeyMessage((const uint8_t *) m_pbChallenge, m_cbChallenge, - m_pchSilentURL != NULL ? (char *)m_pchSilentURL : "" ); + m_piCallback->OnKeyMessage((const uint8_t *) m_pbChallenge, m_cbChallenge, (char *)m_pchSilentURL); + return true; ErrorExit: if (DRM_FAILED(dr)) { - fprintf(stderr, "[%s:%d] failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); - - if(m_piCallback) - { - m_piCallback->OnError( 0, CDMi_S_FALSE, "KeyError" ); - m_piCallback->OnKeyStatusUpdate(MapDrToKeyMessage(dr), nullptr, 0); - m_piCallback->OnKeyStatusesUpdated(); - } - m_eKeyState = KEY_ERROR; + const DRM_CHAR* description; + DRM_ERR_GetErrorNameFromCode(dr, &description); + ocdm_log("playready error2: %s\n", description); + if (m_piCallback) + m_piCallback->OnKeyMessage((const uint8_t *) "", 0, ""); } - - return ( dr == DRM_SUCCESS ); + return false; } CDMi_RESULT MediaKeySession::Load(void) { return CDMi_S_FALSE; } -/*Set KeyId property which will be used by the Reader_Bind during license searching*/ -CDMi_RESULT MediaKeySession::SetKeyIdProperty( const DRM_WCHAR *f_rgwchEncodedKid, DRM_DWORD f_cchEncodedKid ){ +void MediaKeySession::SetParameter(const uint8_t * data, const uint32_t length) { + //ocdm_log("set cbcs parameter\n"); +} - DRM_RESULT err = Drm_Content_SetProperty( - m_poAppContext, - DRM_CSP_AUTODETECT_HEADER, - (DRM_BYTE*)f_rgwchEncodedKid, - f_cchEncodedKid * sizeof( DRM_WCHAR ) ); +void MediaKeySession::Update(const uint8_t *m_pbKeyMessageResponse, uint32_t m_cbKeyMessageResponse) { - if (DRM_FAILED(err)) { - fprintf(stderr, "[%s:%d] Drm_Content_SetProperty DRM_CSP_AUTODETECT_HEADER failed. 0x%08X - %s",__FUNCTION__,__LINE__,static_cast(err),DRM_ERR_NAME(err)); - return CDMi_FAIL; + DRM_RESULT dr = DRM_SUCCESS; + DRM_DWORD decryptionMode; + DRM_LICENSE_RESPONSE oLicenseResponse = {eUnknownProtocol, 0}; + ChkArg(m_pbKeyMessageResponse && m_cbKeyMessageResponse > 0); + + ChkDR(Drm_LicenseAcq_ProcessResponse(m_poAppContext, + DRM_PROCESS_LIC_RESPONSE_SIGNATURE_NOT_REQUIRED, +#ifndef PR_4_4 + nullptr, + nullptr, +#endif + const_cast(m_pbKeyMessageResponse), + m_cbKeyMessageResponse, + &oLicenseResponse)); + decryptionMode = OEM_TEE_DECRYPTION_MODE_HANDLE; + dr = Drm_Content_SetProperty(m_poAppContext, + DRM_CSP_DECRYPTION_OUTPUT_MODE, + (const DRM_BYTE*)&decryptionMode, + sizeof decryptionMode); + if (!DRM_SUCCEEDED(dr)) { + ocdm_log("Drm_Content_SetProperty() failed with %lx", dr); + goto ErrorExit; + } + + dr = Drm_Reader_Bind(m_poAppContext, + g_rgpdstrRights, + DRM_NO_OF(g_rgpdstrRights), + _PolicyCallback, + nullptr, + m_oDecryptContext); + if (!DRM_SUCCEEDED(dr)) { + ocdm_log("Drm_Reader_Bind() MODE_HANDLE failed with %lx", dr); + goto ErrorExit; + } + + decryptionMode = OEM_TEE_DECRYPTION_MODE_NOT_SECURE; + dr = Drm_Content_SetProperty(m_poAppContext, + DRM_CSP_DECRYPTION_OUTPUT_MODE, + (const DRM_BYTE*)&decryptionMode, + sizeof decryptionMode); + if (!DRM_SUCCEEDED(dr)) { + ocdm_log("Drm_Content_SetProperty() failed with %lx", dr); + goto ErrorExit; + } + + dr = Drm_Reader_Bind(m_poAppContext, + g_rgpdstrRights, + DRM_NO_OF(g_rgpdstrRights), + _PolicyCallback, + nullptr, + m_oDecryptContext2); + if (!DRM_SUCCEEDED(dr)) { + ocdm_log("Drm_Reader_Bind() MODE_NOT_SECURE failed with %lx, ignore", dr); + } + + m_eKeyState = KEY_READY; + + if (m_eKeyState == KEY_READY) { + if (m_piCallback) { + for (DRM_DWORD i = 0; i < oLicenseResponse.m_cAcks; ++i) { + if (DRM_SUCCEEDED(oLicenseResponse.m_rgoAcks[i].m_dwResult)) { + m_piCallback->OnKeyStatusUpdate("KeyUsable", oLicenseResponse.m_rgoAcks[i].m_oKID.rgb, DRM_ID_SIZE); + } + } + m_piCallback->OnKeyStatusesUpdated(); } + } - return CDMi_SUCCESS; -} - -/*Converting KeyId into base64-encoded format*/ -CDMi_RESULT MediaKeySession::SetKeyIdProperty( KeyId & f_rKeyId ){ - - DRM_WCHAR rgwchEncodedKid[CCH_BASE64_EQUIV(DRM_ID_SIZE)]= {0}; - DRM_DWORD cchEncodedKid = CCH_BASE64_EQUIV(DRM_ID_SIZE); + return; - if ( f_rKeyId.getKeyIdOrder() == KeyId::KEYID_ORDER_UUID_BE ) - { - f_rKeyId.ToggleFormat(); - } +ErrorExit: + if (DRM_FAILED(dr)) { + const DRM_CHAR* description; + DRM_ERR_GetErrorNameFromCode(dr, &description); + ocdm_log("playready error3: %s\n", description); - DRM_RESULT err = DRM_B64_EncodeW( f_rKeyId.getmBytes(), DRM_ID_SIZE, - rgwchEncodedKid, &cchEncodedKid, 0); + m_eKeyState = KEY_ERROR; - if (DRM_FAILED(err)) { - fprintf(stderr, "[%s:%d] DRM_B64_EncodeW failed. 0x%08X - %s",__FUNCTION__,__LINE__,static_cast(err),DRM_ERR_NAME(err)); - return CDMi_FAIL; + // The upper layer is blocked waiting for an update, let's wake it. + if (m_piCallback) { + for (DRM_DWORD i = 0; i < oLicenseResponse.m_cAcks; ++i) { + m_piCallback->OnKeyStatusUpdate("KeyError", oLicenseResponse.m_rgoAcks[i].m_oKID.rgb, DRM_ID_SIZE); + } + m_piCallback->OnKeyStatusesUpdated(); } - return SetKeyIdProperty( rgwchEncodedKid, cchEncodedKid ); + } + return; } -/*handles all the licenses in the response using Drm_LicenseAcq_ProcessResponse().*/ -DRM_RESULT MediaKeySession::ProcessLicenseResponse( - DRM_PROCESS_LIC_RESPONSE_FLAG f_eResponseFlag, - const DRM_BYTE *f_pbResponse, - DRM_DWORD f_cbResponse, - DRM_LICENSE_RESPONSE *f_pLiceneResponse ) { - DRM_RESULT dr = DRM_SUCCESS; - - dr = Drm_LicenseAcq_ProcessResponse( - m_poAppContext, - f_eResponseFlag, - f_pbResponse, - f_cbResponse, - f_pLiceneResponse ); - - if ( dr == DRM_E_LICACQ_TOO_MANY_LICENSES ) - { - DRM_DWORD cLicenses = f_pLiceneResponse->m_cAcks; - f_pLiceneResponse->m_pAcks = ( DRM_LICENSE_ACK * )Oem_MemAlloc( cLicenses * sizeof( DRM_LICENSE_ACK ) ); - f_pLiceneResponse->m_cMaxAcks = cLicenses; - - dr = Drm_LicenseAcq_ProcessResponse( - m_poAppContext, - f_eResponseFlag, - f_pbResponse, - f_cbResponse, - f_pLiceneResponse ); - } - return dr; +CDMi_RESULT MediaKeySession::Remove(void) { + return CDMi_S_FALSE; } -/*Wrapper function for Drm_Reader_Bind()*/ -DRM_RESULT MediaKeySession::ReaderBind( - const DRM_CONST_STRING *f_rgpdstrRights[], - DRM_DWORD f_cRights, - DRMPFNPOLICYCALLBACK f_pfnPolicyCallback, - const DRM_VOID *f_pv, - DRM_DECRYPT_CONTEXT *f_pDecryptContext ) { - - - DRM_RESULT dr = DRM_SUCCESS; - DRM_BYTE *newOpaqueBuffer = nullptr; - - while( (dr=Drm_Reader_Bind( - m_poAppContext, - f_rgpdstrRights, - f_cRights, - f_pfnPolicyCallback, - f_pv, - f_pDecryptContext ) ) == DRM_E_BUFFERTOOSMALL ){ - - - DRM_BYTE *pbOldBuf = nullptr; - DRM_DWORD cbOldBuf = 0; - - if ( m_cbPROpaqueBuf == 0 ) - m_cbPROpaqueBuf = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; - - m_cbPROpaqueBuf *= 2; - - if ( m_cbPROpaqueBuf > MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE * 64 ){ - ChkDR( DRM_E_OUTOFMEMORY ); - } +CDMi_RESULT MediaKeySession::Close(void) { + m_eKeyState = KEY_CLOSED; - ChkMem( newOpaqueBuffer = ( DRM_BYTE* )Oem_MemAlloc( m_cbPROpaqueBuf ) ); + if (mInitiateChallengeGeneration == true) { + if (DRM_REVOCATION_IsRevocationSupported() && m_pbRevocationBuffer != nullptr) { + SAFE_OEM_FREE(m_pbRevocationBuffer); + m_pbRevocationBuffer = nullptr; + } +#ifndef REUSE_APPCONTEXT + if (m_poAppContext != nullptr) { + Drm_Uninitialize(m_poAppContext); + SAFE_OEM_FREE(m_poAppContext); + m_poAppContext = nullptr; + } +#endif + if (m_pbOpaqueBuffer != nullptr) { + SAFE_OEM_FREE(m_pbOpaqueBuffer); + m_pbOpaqueBuffer = nullptr; + } - dr = Drm_GetOpaqueBuffer( m_poAppContext, &pbOldBuf, &cbOldBuf ); - if ( DRM_FAILED( dr ) ){ - fprintf(stderr, "[%s:%d] Drm_GetOpaqueBuffer failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); - SAFE_OEM_FREE( newOpaqueBuffer ); - ChkDR( dr ); + if (m_oDecryptContext != nullptr) { + Drm_Reader_Close(m_oDecryptContext); + delete m_oDecryptContext; + m_oDecryptContext = nullptr; } - dr = Drm_ResizeOpaqueBuffer( m_poAppContext, newOpaqueBuffer, m_cbPROpaqueBuf ); - if ( DRM_FAILED( dr ) ){ - fprintf(stderr, "[%s:%d] Drm_ResizeOpaqueBuffer failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); - SAFE_OEM_FREE( newOpaqueBuffer ); - ChkDR( dr ); + if (m_oDecryptContext2 != nullptr) { + Drm_Reader_Close(m_oDecryptContext2); + delete m_oDecryptContext2; + m_oDecryptContext2 = nullptr; } - if ( m_pbPROpaqueBuf != nullptr && m_pbPROpaqueBuf == pbOldBuf ){ - SAFE_OEM_FREE( pbOldBuf ); - m_pbPROpaqueBuf = newOpaqueBuffer; - }else{ - SAFE_OEM_FREE( pbOldBuf ); + if (m_pbChallenge != nullptr) { + SAFE_OEM_FREE(m_pbChallenge); + m_pbChallenge = nullptr; } - } - ErrorExit: - if ( DRM_FAILED( dr ) ){ - fprintf(stderr, "[%s:%d] failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + if (m_pchSilentURL != nullptr) { + SAFE_OEM_FREE(m_pchSilentURL); + m_pchSilentURL = nullptr; + } } - return dr; + return CDMi_SUCCESS; } -CDMi_RESULT MediaKeySession::PersistentLicenseCheck() { -#ifdef NO_PERSISTENT_LICENSE_CHECK - // DELIA-51437: The Webkit EME implementation used by OTT apps - // such as Amazon and YouTube fails when the key is usable from - // just the init data. Webkit is expecting a license request - // message and the lack of this message prevents the session from - // loading correctly. - // - // The EME concept of a persistent session uses the Session Id to - // reload a session, not the raw Key ID. We do not current - // support that type of session in the OCDM. Apps wishing to use - // persistent keys should directly link to PR4 or the OCDM should - // be rewritten to use PR4's CDMI API - // (modules/cdmi/real/drmcdmireal.c). - fprintf(stderr, "\n PersistentLicenseCheck: skipping persistent check"); - return CDMi_S_FALSE; -#else - DRM_RESULT dr = DRM_SUCCESS; - DRM_CONTENT_SET_PROPERTY eContentPropertyType = DRM_CSP_HEADER_NOT_SET; + CDMi_RESULT MediaKeySession::Decrypt( + uint8_t* inData, + const uint32_t inDataLength, + uint8_t** outData, + uint32_t* outDataLength, + const SampleInfo* sampleInfo, + const IStreamProperties* properties) +{ + DRM_UINT64 iv_vector[2] = { 0 }; + void* pSecureToken = nullptr; + void *decryptedData = nullptr; + bool bGstSvpStatus = false; - if ( !mDrmHeader.size() ) { - fprintf(stderr, "[%s:%d] mDrmHeader not set",__FUNCTION__,__LINE__); - return CDMi_FAIL; - } - if ( m_pdstrHeaderKIDs == NULL || m_cHeaderKIDs == 0 ){ - fprintf(stderr, "[%s:%d] key ids not set",__FUNCTION__,__LINE__); - return CDMi_FAIL; + SafeCriticalSection systemLock(drmAppContextMutex_); + assert(sampleInfo->ivLength > 0); + if (inDataLength == 0) { + return CDMi_SUCCESS; } - if ( m_eHeaderVersion == DRM_HEADER_VERSION_4_2 ) - eContentPropertyType = DRM_CSP_V4_2_HEADER; - else if ( m_eHeaderVersion == DRM_HEADER_VERSION_4_3 ) - eContentPropertyType = DRM_CSP_V4_3_HEADER; - else{ - eContentPropertyType = DRM_CSP_AUTODETECT_HEADER; + if (!m_oDecryptContext) { + ocdm_log("Error: no decrypt context (yet?)\n"); + return CDMi_S_FALSE; } - for( DRM_DWORD idx = 0; idx < m_cHeaderKIDs; idx++ ){ + DRM_RESULT err = DRM_SUCCESS; + DRM_DWORD rgdwMappings[2]; + bool bUseSVP = true; - KeyId keyId; - keyId.keyDecode(m_pdstrHeaderKIDs[ idx ]); - keyId.setKeyIdOrder(KeyId::KEYID_ORDER_GUID_LE); - - DECRYPT_CONTEXT decryptContext; + if ( (outDataLength == NULL) || (outData == NULL) + || (sampleInfo->iv == NULL || sampleInfo->ivLength == 0) || (m_eKeyState != KEY_READY) ) { + ocdm_log("Error: Decrypt - Invalid argument\n"); + return CDMi_S_FALSE; + } - if ( CDMi_SUCCESS != SetKeyIdProperty( m_pdstrHeaderKIDs[idx].pwszString, - m_pdstrHeaderKIDs[idx].cchString ) ) { - fprintf(stderr, "[%s:%d] SetKeyIdProperty failed. %s",__FUNCTION__,__LINE__,printGuid(keyId)); - ChkDR( DRM_E_FAIL ); - } + *outDataLength = 0; + *outData = NULL; - decryptContext = NEW_DECRYPT_CONTEXT(); - dr = ReaderBind( - g_rgpdstrRights, - NO_OF(g_rgpdstrRights), - _PolicyCallback, - &m_playreadyLevels, - &(decryptContext->oDrmDecryptContext) ); - if ( DRM_FAILED( dr ) ){ - ChkDR( dr ); +#ifndef PR_4_4 + if (!properties->InitLength()) { + err = Drm_Reader_InitDecrypt(m_oDecryptContext, nullptr, 0); + } else { + // Initialize the decryption context for Cocktail packaged + // content. This is a no-op for AES packaged content. + if (inDataLength <= 15) { + err = Drm_Reader_InitDecrypt(m_oDecryptContext, (DRM_BYTE*)inData, inDataLength); + } else { + err = Drm_Reader_InitDecrypt(m_oDecryptContext, (DRM_BYTE*)(inData + inDataLength - 15), inDataLength); } - - decryptContext->keyId = keyId; - m_DecryptContextVector.push_back(decryptContext); } - -ErrorExit: - - if ( DRM_FAILED( dr ) ){ - CloseDecryptContexts(); - return CDMi_FAIL; + if (DRM_FAILED(err)) { + ocdm_log("Failed to init decrypt\n"); + return CDMi_S_FALSE; } +#endif - if ( m_piCallback ) - { - for (DECRYPT_CONTEXT &p : m_DecryptContextVector) - { - m_piCallback->OnKeyStatusUpdate(MapDrToKeyMessage( dr ), p->keyId.getmBytes(), DRM_ID_SIZE); - } - m_piCallback->OnKeyStatusesUpdated(); + // TODO: can be done in another way (now abusing "initWithLast15" variable) + if (properties->InitLength()) { + memcpy(iv_vector, sampleInfo->iv, sizeof(iv_vector)); + } else { + unsigned char * ivDataNonConst = const_cast(sampleInfo->iv); // TODO: this is ugly + for (uint32_t i = 0; i < 2; i++) { + if (i << 3 >= sampleInfo->ivLength) + break; + NETWORKBYTES_TO_QWORD(iv_vector[i], &ivDataNonConst[i << 3], 0); + } } - m_eKeyState = KEY_READY; - - return CDMi_SUCCESS; -#endif -} + CDMi::MediaType mediaType = CDMi::Unknown; -// Allow persistent PlayReady licenses to be used in a temporary -// session. -// -// Ideally, the license server would only return temporary licenses -// and would could block all persistent license with the -// `DRM_PROCESS_LIC_RESPONSE_FLAG` value of -// `DRM_PROCESS_LIC_RESPONSE_BLOCK_PERSISTENT_LICENSES`. -// -// Instead, we allow persistent licenses to be used but attempt to -// clean them up when the session closes. -void MediaKeySession::SaveTemporaryPersistentLicenses(const DRM_LICENSE_RESPONSE* f_poLicenseResponse) { - fprintf(stderr, "\n SaveTemporaryPersistentLicenses: response has persistent licenses: %s", - f_poLicenseResponse->m_fHasPersistentLicenses ? "true" : "false"); - - if (!f_poLicenseResponse->m_fHasPersistentLicenses) { - return; - } - - // We know there are persistent license but not which ones. Save - // them all for deletion when we close a session. - for (DRM_DWORD i = 0; i < f_poLicenseResponse->m_cAcks; ++i) { - const DRM_LICENSE_ACK *pLicenseAck = nullptr; - - pLicenseAck = f_poLicenseResponse->m_pAcks != nullptr - ? &f_poLicenseResponse->m_pAcks[ i ] : &f_poLicenseResponse->m_rgoAcks[ i ]; - - if ( DRM_SUCCEEDED( pLicenseAck->m_dwResult ) ) { - m_oPersistentLicenses.emplace_back(pLicenseAck->m_oKID, pLicenseAck->m_oLID); - } - } -} - -void MediaKeySession::DeleteTemporaryPersistentLicenses() { - DRM_RESULT dr = DRM_SUCCESS; - DRM_CONST_STRING dstrKID = DRM_EMPTY_DRM_STRING; - DRM_CONST_STRING dstrLID = DRM_EMPTY_DRM_STRING; - DRM_DWORD cbstrKID = 0; - DRM_DWORD cLicDeleted = 0; - - fprintf(stderr, "\n DeleteTemporaryPersistentLicenses: deleting %zd possibly persistent licenses", - m_oPersistentLicenses.size()); - - /* Allocate strKID buffer */ - cbstrKID = CCH_BASE64_EQUIV( sizeof( DRM_ID ) ) * sizeof( DRM_WCHAR ); - ChkMem( dstrKID.pwszString = (DRM_WCHAR *) Oem_MemAlloc( cbstrKID ) ); - dstrKID.cchString = CCH_BASE64_EQUIV( sizeof( DRM_ID ) ); - - ChkMem( dstrLID.pwszString = (DRM_WCHAR *) Oem_MemAlloc( cbstrKID ) ); - dstrLID.cchString = CCH_BASE64_EQUIV( sizeof( DRM_ID ) ); - - for (const auto& pair: m_oPersistentLicenses) { - - /* Convert KID to string */ - dr = DRM_B64_EncodeW( - (DRM_BYTE*)&pair.first, - sizeof( DRM_ID ), - (DRM_WCHAR*)dstrKID.pwszString, - &dstrKID.cchString, - DRM_BASE64_ENCODE_NO_FLAGS ); - - if (DRM_FAILED(dr)) { - fprintf(stderr, "\n DeleteTemporaryPersistentLicenses: DRM_B64_EncodeW failed for KID: 0x%08X", dr); - continue; - } - - /* Convert LID to string */ - dr = DRM_B64_EncodeW( - (DRM_BYTE*)&pair.second, - sizeof( DRM_ID ), - (DRM_WCHAR*)dstrLID.pwszString, - &dstrKID.cchString, - DRM_BASE64_ENCODE_NO_FLAGS ); - - if (DRM_FAILED(dr)) { - fprintf(stderr, "\n DeleteTemporaryPersistentLicenses: DRM_B64_EncodeW failed for LID: 0x%08X", dr); - continue; - } - - dr = Drm_StoreMgmt_DeleteLicenses( - m_poAppContext, - &dstrKID, - &dstrLID, - &cLicDeleted); - - } - -ErrorExit: - SAFE_OEM_FREE( dstrKID.pwszString ); - SAFE_OEM_FREE( dstrLID.pwszString ); - - return; -} - -/*processes the license response and creates decryptor for each valid ack available in the response*/ -void MediaKeySession::Update(const uint8_t *m_pbKeyMessageResponse, uint32_t m_cbKeyMessageResponse) { - - DRM_RESULT dr = DRM_SUCCESS; - DRM_LICENSE_RESPONSE oLicenseResponse = { eUnknownProtocol, 0 }; - DRM_LICENSE_ACK *pLicenseAck = nullptr; - - ChkBOOL(m_eKeyState == KEY_PENDING, DRM_E_INVALIDARG); - - ChkArg(m_pbKeyMessageResponse && m_cbKeyMessageResponse > 0); - - ChkDR( ProcessLicenseResponse( - DRM_PROCESS_LIC_RESPONSE_NO_FLAGS, - const_cast(m_pbKeyMessageResponse), - m_cbKeyMessageResponse, - &oLicenseResponse ) ); - - SaveTemporaryPersistentLicenses(&oLicenseResponse); - - for (DRM_DWORD i = 0; i < oLicenseResponse.m_cAcks; ++i) { - - pLicenseAck = oLicenseResponse.m_pAcks != nullptr - ? &oLicenseResponse.m_pAcks[ i ] : &oLicenseResponse.m_rgoAcks[ i ]; - - KeyId keyId(&pLicenseAck->m_oKID.rgb[0],KeyId::KEYID_ORDER_GUID_LE); - - dr = pLicenseAck->m_dwResult; - if ( DRM_SUCCEEDED( dr ) ) { - - DECRYPT_CONTEXT decryptContext; - - if ( CDMi_SUCCESS != SetKeyIdProperty( keyId ) ) - { - dr = DRM_E_FAIL; - goto LoopEnd; - } - - decryptContext = NEW_DECRYPT_CONTEXT(); - - dr = ReaderBind( - g_rgpdstrRights, - NO_OF(g_rgpdstrRights), - _PolicyCallback, - &m_playreadyLevels, - &(decryptContext->oDrmDecryptContext) ); - - if ( DRM_FAILED( dr ) ){ - fprintf(stderr, "[%s:%d] ReaderBind failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); - goto LoopEnd; - } - - decryptContext->keyId = keyId; - - if ( oLicenseResponse.m_cAcks == 1 ){ - m_currentDecryptContext = decryptContext; - } - - m_DecryptContextVector.push_back(decryptContext); - - m_eKeyState = KEY_READY; - } - LoopEnd: - if ( m_piCallback ){ - m_piCallback->OnKeyStatusUpdate( MapDrToKeyMessage( dr ), keyId.getmBytes(), DRM_ID_SIZE); - } - } - - if ( m_eKeyState == KEY_READY ){ - dr = DRM_SUCCESS; - }else{ - fprintf(stderr, "[%s:%d] Could not bind to any licenses",__FUNCTION__,__LINE__); - dr = DRM_E_FAIL; - } - -ErrorExit: - - if (DRM_FAILED(dr)) { - fprintf(stderr, "[%s:%d] failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); - m_eKeyState = KEY_ERROR; - } - if (m_piCallback){ - m_piCallback->OnKeyStatusesUpdated(); - } - SAFE_OEM_FREE( oLicenseResponse.m_pAcks ); - return; -} - -CDMi_RESULT MediaKeySession::Remove(void) { - fprintf(stderr, "[%s:%d] returning false ",__FUNCTION__,__LINE__); - return CDMi_S_FALSE; -} - -/*Closes each DRM_DECRYPT_CONTEXT using Drm_Reader_Close()*/ -void MediaKeySession::CloseDecryptContexts(void) { - m_currentDecryptContext = nullptr; - - for (DECRYPT_CONTEXT &p : m_DecryptContextVector) - { - Drm_Reader_Close(&(p->oDrmDecryptContext)); - } - m_DecryptContextVector.clear(); -} - -void MediaKeySession::DeleteInMemoryLicenses() { - DRM_ID emptyId = DRM_ID_EMPTY; - - if (memcmp(&m_oBatchID, &emptyId, sizeof(DRM_ID)) == 0) { - return; - } - KeyId batchId(&m_oBatchID.rgb[0],KeyId::KEYID_ORDER_GUID_LE); - - DRM_RESULT dr = Drm_StoreMgmt_DeleteInMemoryLicenses(m_poAppContext, &m_oBatchID); - if (DRM_FAILED(dr) && dr != DRM_E_NOMORE) { - fprintf(stderr, "[%s:%d] Drm_StoreMgmt_DeleteInMemoryLicenses failed for batchId:%s. 0x%X - %s",__FUNCTION__,__LINE__,printUuid(batchId),dr,DRM_ERR_NAME(dr)); - } -} - -CDMi_RESULT MediaKeySession::Close(void) { - - if ( m_eKeyState != KEY_CLOSED ) { -#ifdef USE_SVP - gst_svp_ext_free_context(m_pSVPContext); -#endif - - SAFE_OEM_FREE(m_pbChallenge); - - SAFE_OEM_FREE(m_pchSilentURL); - - CloseDecryptContexts(); - - DeleteInMemoryLicenses(); - - DeleteTemporaryPersistentLicenses(); - - mDrmHeader.clear(); - - SAFE_OEM_FREE(m_pbRevocationBuffer); - - SAFE_OEM_FREE(m_pdstrHeaderKIDs); - - m_eKeyState = KEY_CLOSED; - } - - return CDMi_SUCCESS; -} - -CDMi_RESULT MediaKeySession::PlaybackStopped(void) { - return CDMi_SUCCESS; -} - -const char* MediaKeySession::MapDrToKeyMessage( DRM_RESULT dr ) -{ - switch (dr) - { - case DRM_SUCCESS: - return "KeyUsable"; - case DRM_E_TEE_OUTPUT_PROTECTION_REQUIREMENTS_NOT_MET: - case DRM_E_TEST_OPL_MISMATCH: - return "KeyOutputRestricted"; - case DRM_E_TEE_OUTPUT_PROTECTION_INSUFFICIENT_HDCP: - return "KeyOutputRestrictedHDCP"; - case DRM_E_TEE_OUTPUT_PROTECTION_INSUFFICIENT_HDCP22: - case DRM_E_TEST_INVALID_OPL_CALLBACK: - return "KeyOutputRestrictedHDCP22"; - default: - return "KeyInternalError"; - } -} - -CDMi_RESULT MediaKeySession::DRM_DecryptFailure(DRM_RESULT dr, const uint8_t *payloadData, uint32_t *f_pcbOpaqueClearContent, uint8_t **f_ppbOpaqueClearContent) -{ - fprintf(stderr, "[%s:%d] playready decrypt() failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); - - if(f_pcbOpaqueClearContent != nullptr) - { - *f_pcbOpaqueClearContent = 0; + if(properties != NULL) { + mediaType = properties->GetMediaType(); + if(mediaType == CDMi::Audio) { + // Audio does not use the secure path (SAP) so + // use the inplace decryption technique. + bUseSVP = false; } - if(f_ppbOpaqueClearContent != nullptr && payloadData != nullptr) - { - *f_ppbOpaqueClearContent = (uint8_t *)payloadData; + } else { + ocdm_log("DYNAMIC_SVP_DECRYPTION parser not set! "); + } + + DRM_DWORD regionCount[1] = { 0 }; + DRM_DWORD regionSkip[2] = { 0 }; + uint32_t opaque_buffer_size = 0; + uint8_t *opaque_buffer = NULL; + uint32_t subSampleCount = sampleInfo->subSampleCount; + std::vector encryptedRegions; + uint32_t inputLen = inDataLength - svp_token_size() - gst_svp_header_size(NULL); + decryptedData = reinterpret_cast(gst_svp_header_get_start_of_data( NULL, inData )); + + regionSkip[0] = sampleInfo->pattern.encrypted_blocks; + regionSkip[1] = sampleInfo->pattern.clear_blocks; + if (subSampleCount > 0) { + for (int i = 0; i < subSampleCount; i++) { + encryptedRegions.push_back(sampleInfo->subSample[i].clear_bytes); + encryptedRegions.push_back(sampleInfo->subSample[i].encrypted_bytes); } - - if(m_piCallback){ - char errStr[50]; - uint64_t errCode = (0xFFFFFFFF00000000)|(dr); - sprintf(errStr,"0x%llx-DecryptError",errCode); - m_piCallback->OnError(0, CDMi_S_FALSE, errStr); - m_piCallback->OnKeyStatusUpdate(MapDrToKeyMessage( dr ), nullptr, 0); - m_piCallback->OnKeyStatusesUpdated(); + } else { + encryptedRegions.push_back(0); + encryptedRegions.push_back(inputLen); } - return CDMi_S_FALSE; -} - -DECRYPT_CONTEXT MediaKeySession::GetDecryptCtx( KeyId &f_rKeyId ) -{ - for (DECRYPT_CONTEXT &ctx : m_DecryptContextVector) - { - if (ctx->keyId == f_rKeyId) - { - return ctx; - } - } - return nullptr; -} - -CDMi_RESULT MediaKeySession::SetParameter(const std::string& name, const std::string& value) -{ - CDMi_RESULT retVal = CDMi_S_FALSE; - - if(name.find("rpcId") != std::string::npos) { - // Got the RPC ID for gst-svp-ext communication - unsigned int nID = 0; - nID = (unsigned int)std::stoul(value.c_str(), nullptr, 16); - if(nID != 0) { -#ifdef USE_SVP - //fprintf(stderr, "Initializing SVP context for client side ID = %X\n", nID); - gst_svp_ext_get_context(&m_pSVPContext, Client, nID); -#endif - } - } - return retVal; -} - -CDMi_RESULT MediaKeySession::Decrypt( - uint8_t* inData, - const uint32_t inDataLength, - uint8_t** outData, - uint32_t* outDataLength, - const SampleInfo* sampleInfo, - const IStreamProperties* properties) -{ - CDMi_RESULT ret = CDMi_S_FALSE; - bool useSVP = false; - -#if defined (RESOLUTION_CHECK_ENABLED) - uint64_t mCurrentPixels; - if (properties->GetMediaType() == Video) { - mCurrentPixels = properties->GetHeight() * properties->GetWidth(); - } - - /* MaxResDecode */ - if (mMaxResDecodeSet) { - if ((mCurrentPixels > mMaxResDecodePixels)) { - fprintf(stderr, "[%s:%d] video resolution:%llu exceeds maximum resolution:%lu",__FUNCTION__,__LINE__,mCurrentPixels,mMaxResDecodePixels); - return CDMi_S_FALSE; - } - } -#endif /* RESOLUTION_CHECK_ENABLED */ - -#if defined (DYNAMIC_SVP_DECRYPTION) - if (properties->GetMediaType() == Video) { - useSVP = true; - } -#endif /* DYNAMIC_SVP_DECRYPTION */ - - if (sampleInfo->scheme == AesCbc_Cbc1 || sampleInfo->scheme == AesCbc_Cbcs) { //CBC - ret = DecryptAesCBC1(sampleInfo->subSample, sampleInfo->subSampleCount, - sampleInfo->iv, sampleInfo->ivLength, - inData, inDataLength, - outDataLength, outData, - sampleInfo->keyIdLength, sampleInfo->keyId, - properties->InitLength(), - sampleInfo->pattern.encrypted_blocks, sampleInfo->pattern.clear_blocks, - useSVP); - } else { //AesCtr_Cenc, AesCtr_Cens - ret = DecryptAesCTR1(sampleInfo->subSample, sampleInfo->subSampleCount, - sampleInfo->iv, sampleInfo->ivLength, - inData, inDataLength, - outDataLength, outData, - sampleInfo->keyIdLength, sampleInfo->keyId, - properties->InitLength(), - useSVP); - } - return ret; -} - -CDMi_RESULT MediaKeySession::DecryptAesCBC1( - SubSampleInfo* subSample, - uint8_t subSampleCount, - const uint8_t *f_pbIV, - uint32_t f_cbIV, - const uint8_t *payloadData, - uint32_t payloadDataSize, - uint32_t *f_pcbOpaqueClearContent, - uint8_t **f_ppbOpaqueClearContent, - const uint8_t keyIdLength, - const uint8_t* f_keyId, - uint8_t initWithLast15, - uint32_t cryptoBlocks, - uint32_t clearBlocks, - bool useSVP) -{ - void *decryptedData = nullptr; - uint32_t *f_pdwSubSampleMapping; - uint32_t f_cdwSubSampleMapping; - DRM_RESULT dr = DRM_SUCCESS; - DRM_RESULT err = DRM_SUCCESS; - uint32_t actualDataLength = 0; - void *pSecureMemory = NULL; - SecureBufferInfo *pstSecBufInfo = NULL; - uint32_t encryptedDataSize = 0; - void* header = NULL; - - assert(f_cbIV == EXPECTED_AES_CBC_IVDATA_SIZE); - - if ( f_keyId != nullptr ){ - KeyId keyId(&f_keyId[0],KeyId::KEYID_ORDER_UUID_BE); - - if (m_currentDecryptContext == nullptr - || m_currentDecryptContext->keyId != keyId) - { - m_currentDecryptContext = GetDecryptCtx( keyId ); - } - } - if ( m_currentDecryptContext == nullptr ){ - fprintf(stderr, "[%s:%d] m_currentDecryptContext is Nullptr",__FUNCTION__,__LINE__); - return CDMi_S_FALSE; - } - - SafeCriticalSection systemLock(drmAppContextMutex_); - - assert(f_cbIV > 0); - if(payloadDataSize == 0){ - return CDMi_SUCCESS; - } - - uint8_t *iv = malloc(f_cbIV * sizeof(uint8_t)); - - if (initWithLast15) { - // Netflix case - memcpy(iv, f_pbIV, f_cbIV * sizeof(uint8_t)); - - } else { - // Regular case - uint8_t buf[ f_cbIV ]; - for (uint32_t i = 0; i < f_cbIV / 2; i++) { - buf[i] = f_pbIV[f_cbIV - i - 1]; - buf[f_cbIV - i - 1] = f_pbIV[i]; - } - memcpy(iv, buf, f_cbIV * sizeof(uint8_t)); - } - - if (gst_svp_has_header(m_pSVPContext, payloadData)) - { - header = (void*)payloadData; - decryptedData = reinterpret_cast(gst_svp_header_get_start_of_data(m_pSVPContext, header)); - gst_svp_header_get_field(m_pSVPContext, header, SvpHeaderFieldName::DataSize, &actualDataLength); - } - -#ifdef USE_SVP - if (useSVP) - { - // Allocate secure buffer for decryption. - pstSecBufInfo = (SecureBufferInfo*)malloc(sizeof(SecureBufferInfo)); - svp_allocate_secure_buffers(m_pSVPContext, &pstSecBufInfo, &pSecureMemory, nullptr, actualDataLength); - } -#endif - - DRM_DWORD encryptedRegionIvCounts = 1; - DRM_DWORD encryptedRegionCounts; - std::vector encryptedRegion; - std::vector encryptedRegionMapping; - std::vector iv_high; - std::vector iv_low; - DRM_UINT64 iv64; - - NETWORKBYTES_TO_QWORD(iv64, &iv[0], 0); - iv_high.push_back(iv64); - - NETWORKBYTES_TO_QWORD(iv64, &iv[8], 0); - iv_low.push_back(iv64); - - if (subSampleCount > 0) { - for (unsigned int position = 0; position < subSampleCount; position++) { - encryptedRegionMapping.push_back(static_cast (subSample[position].clear_bytes)); - encryptedRegionMapping.push_back(static_cast (subSample[position].encrypted_bytes)); - } - } else { - encryptedRegionMapping.push_back(0); - encryptedRegionMapping.push_back(actualDataLength); - } - - encryptedRegionCounts = encryptedRegionMapping.size()/2; - - encryptedRegion.push_back(cryptoBlocks); - encryptedRegion.push_back(clearBlocks); - - DRM_DWORD* decryptedLength = 0; - DRM_BYTE** decryptedContent = NULL; - if (useSVP) - { - decryptedLength = reinterpret_cast(actualDataLength); - decryptedContent = reinterpret_cast(pstSecBufInfo->pPhysAddr); - } - - err = Drm_Reader_DecryptMultipleOpaque(&(m_currentDecryptContext->oDrmDecryptContext), - encryptedRegionIvCounts, - &iv_high[0], &iv_low[0], - &encryptedRegionCounts, - encryptedRegionMapping.size(), &encryptedRegionMapping[0], - encryptedRegion.size(), &encryptedRegion[0], - (DRM_DWORD) actualDataLength, - (DRM_BYTE *) decryptedData, - reinterpret_cast(&decryptedLength), reinterpret_cast(&decryptedContent)); - free(iv); - iv = NULL; - - if (DRM_FAILED(err)) - { - fprintf(stderr, "[%s:%d] Drm_Reader_DecryptMultipleOpaque failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); - DRM_DecryptFailure(err, nullptr, nullptr, nullptr); -#ifdef USE_SVP - if (useSVP) - { - // Free decrypted secure buffer. - svp_release_secure_buffers(m_pSVPContext, nullptr, pSecureMemory, nullptr, 0); - } -#endif - return err; - } - - if (!m_fCommit) { - err = Drm_Reader_Commit(m_poAppContext, _PolicyCallback, &m_playreadyLevels); - m_fCommit = TRUE; - } - - if (useSVP){ - void* secToken = NULL; - svp_buffer_alloc_token(&secToken); - svp_buffer_to_token(m_pSVPContext, (void *)pstSecBufInfo, secToken); - - // Add a header to the output buffer. - if (header) - { - gst_svp_header_set_field(m_pSVPContext, header, SvpHeaderFieldName::Type, TokenType::Handle); - } - memcpy((uint8_t *)decryptedData, secToken, svp_token_size()); - svp_buffer_free_token(secToken); - //TODO: note the return token data and size - } else{ - if (header) - { - gst_svp_header_set_field(m_pSVPContext, header, SvpHeaderFieldName::Type, TokenType::InPlace); - } - - } - - // Return clear content. - *f_pcbOpaqueClearContent = actualDataLength; - *f_ppbOpaqueClearContent = (uint8_t *)payloadData; - - if(useSVP && pstSecBufInfo) - { - free(pstSecBufInfo); - pstSecBufInfo = NULL; - } - - return CDMi_SUCCESS; -} + regionCount[0] = encryptedRegions.size()/2; -CDMi_RESULT MediaKeySession::DecryptAesCTR1( - SubSampleInfo* subSample, - uint8_t subSampleCount, - const uint8_t *f_pbIV, - uint32_t f_cbIV, - const uint8_t *payloadData, - uint32_t payloadDataSize, - uint32_t *f_pcbOpaqueClearContent, - uint8_t **f_ppbOpaqueClearContent, - const uint8_t keyIdLength, - const uint8_t* f_keyId, - uint8_t initWithLast15, - bool useSVP) -{ - void *decryptedData = nullptr; - uint32_t *f_pdwSubSampleMapping = NULL; - uint32_t f_cdwSubSampleMapping = 0; - DRM_RESULT err = DRM_SUCCESS; - uint32_t actualDataLength = 0; - void *DstPhys = NULL; - void *pSecureMemory = NULL; - SecureBufferInfo *pstSecBufInfo = NULL; - uint32_t encryptedDataSize = 0; - void* header = NULL; - - if ( f_keyId != nullptr ){ - KeyId keyId(&f_keyId[0],KeyId::KEYID_ORDER_UUID_BE); - - if (m_currentDecryptContext == nullptr - || m_currentDecryptContext->keyId != keyId) - { - m_currentDecryptContext = GetDecryptCtx( keyId ); + if (bUseSVP) { + uint32_t e; + Sec_OpaqueBufferHandle* secbuf_out = NULL; + // err = SecBuffer_Malloc(inDataLength, &secbuf_out); + e = svp_allocate_secure_buffers(m_pSVPContext, (void **)&secbuf_out, &sess, nullptr, inputLen); + if (DRM_FAILED(e)) { + ocdm_log("Failed to run SecBuffer_Malloc\n"); + return CDMi_S_FALSE; } - } - if ( m_currentDecryptContext == nullptr ){ - fprintf(stderr, "[%s:%d] m_currentDecryptContext is Nullptr",__FUNCTION__,__LINE__); - return CDMi_S_FALSE; - } - - SafeCriticalSection systemLock(drmAppContextMutex_); - assert(f_cbIV > 0); - if(payloadDataSize == 0){ - return CDMi_SUCCESS; - } - - DRM_AES_COUNTER_MODE_CONTEXT ctrContext = { 0 }; - - if (initWithLast15) { - // Netflix case - memcpy(&ctrContext, f_pbIV, DRM_MIN(f_cbIV, sizeof(ctrContext)) ); - } else { - // Regular case - uint8_t buf[ f_cbIV ]; - for (uint32_t i = 0; i < f_cbIV / 2; i++) { - buf[i] = f_pbIV[f_cbIV - i - 1]; - buf[f_cbIV - i - 1] = f_pbIV[i]; + OEM_OPTEE_SetHandle(secbuf_out->secmem_handle); + err = Drm_Reader_DecryptMultipleOpaque(m_oDecryptContext, + 1, iv_vector, iv_vector + 1, regionCount, + encryptedRegions.size(), &encryptedRegions[0], + 2, regionSkip, + inputLen, (const DRM_BYTE*)decryptedData, + &opaque_buffer_size, + &opaque_buffer); + if (DRM_FAILED(err)) { + ocdm_log("Failed to run Drm_Reader_DecryptMultipleOpaque1\n"); + return CDMi_S_FALSE; } - MEMCPY(&ctrContext.qwInitializationVector, buf, f_cbIV); - } - - if (gst_svp_has_header(m_pSVPContext, payloadData)) - { - header = (void*)payloadData; - decryptedData = reinterpret_cast(gst_svp_header_get_start_of_data(m_pSVPContext, header)); - gst_svp_header_get_field(m_pSVPContext, header, SvpHeaderFieldName::DataSize, &actualDataLength); - } - -#ifdef USE_SVP - if (useSVP) - { - // Allocate secure buffer for decryption. - pstSecBufInfo = (SecureBufferInfo*)malloc(sizeof(SecureBufferInfo)); - svp_allocate_secure_buffers(m_pSVPContext, &pstSecBufInfo, &pSecureMemory, nullptr, actualDataLength); - } -#endif - - DRM_DWORD rgdwMappings[ 2* subSampleCount ]; - DRM_DWORD rgdwMappings1[ 2 ]; - - if ( subSampleCount != 0) { - for (unsigned int position = 0,i=0; position < subSampleCount; position++,i=i+1) { - rgdwMappings[i] = subSample[position].clear_bytes; - rgdwMappings[++i] = subSample[position].encrypted_bytes; - } - - f_pdwSubSampleMapping = reinterpret_cast(rgdwMappings); - f_cdwSubSampleMapping = NO_OF(rgdwMappings); - } else { - rgdwMappings1[0] = 0; - rgdwMappings1[1] = actualDataLength; - f_pdwSubSampleMapping = reinterpret_cast(rgdwMappings1); - f_cdwSubSampleMapping = NO_OF(rgdwMappings1); - } - - DRM_DWORD* decryptedLength = 0; - DRM_BYTE** decryptedContent = NULL; - if (useSVP) - { - decryptedLength = reinterpret_cast(actualDataLength); - decryptedContent = reinterpret_cast(pstSecBufInfo->pPhysAddr); - } - - err = Drm_Reader_DecryptOpaque( - &(m_currentDecryptContext->oDrmDecryptContext), - f_cdwSubSampleMapping, - reinterpret_cast(f_pdwSubSampleMapping), - ctrContext.qwInitializationVector, - actualDataLength, - (DRM_BYTE *) decryptedData, - reinterpret_cast(&decryptedLength), - reinterpret_cast(&decryptedContent)); - - if (DRM_FAILED(err)) - { - fprintf(stderr, "[%s:%d] Drm_Reader_DecryptOpaque failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); - DRM_DecryptFailure(err, nullptr, nullptr, nullptr); -#ifdef USE_SVP - if (useSVP) { - // Free decrypted secure buffer. - svp_release_secure_buffers(m_pSVPContext, nullptr, pSecureMemory, nullptr, 0); + if (opaque_buffer) { + free(opaque_buffer); + opaque_buffer = NULL; } -#endif - return CDMi_S_FALSE; - } - - if (!m_fCommit) { - err = Drm_Reader_Commit(m_poAppContext, _PolicyCallback, &m_playreadyLevels); - m_fCommit = TRUE; - } - - if (useSVP){ - void* secToken = NULL; - svp_buffer_alloc_token(&secToken); - svp_buffer_to_token(m_pSVPContext, (void*)pstSecBufInfo, secToken); + // ocdm_log("Drm_Reader_DecryptOpaque video ---- %p\n", secbuf_out); - // Add a header to the output buffer. - if (header) - { - gst_svp_header_set_field(m_pSVPContext, header, SvpHeaderFieldName::Type, TokenType::Handle); - } - - memcpy((uint8_t *)decryptedData, secToken, svp_token_size()); - svp_buffer_free_token(secToken); - //TODO: note the return token data and size - } else{ - if (header) - { - gst_svp_header_set_field(m_pSVPContext, header, SvpHeaderFieldName::Type, TokenType::InPlace); - } - } - - // Return clear content. - *f_pcbOpaqueClearContent = actualDataLength; - *f_ppbOpaqueClearContent = (uint8_t *)payloadData; - - if(useSVP && pstSecBufInfo) - { - free(pstSecBufInfo); - pstSecBufInfo = NULL; - } - return CDMi_SUCCESS; -} - -#if 0 -CDMi_RESULT MediaKeySession::Decrypt( - const uint8_t *f_pbSessionKey, - uint32_t f_cbSessionKey, - const EncryptionScheme encryptionScheme, - const EncryptionPattern& pattern, - const uint8_t *f_pbIV, - uint32_t f_cbIV, - uint8_t* payloadData, - uint32_t payloadDataSize, - uint32_t *f_pcbOpaqueClearContent, - uint8_t **f_ppbOpaqueClearContent, - const uint8_t keyIdLength, - const uint8_t* f_keyId, - bool initWithLast15 - ) -{ - CDMi_RESULT ret = CDMi_S_FALSE; - uint32_t *f_pdwSubSampleMapping; - uint32_t f_cdwSubSampleMapping; - - printf("anto mediasession: old decrypt called\n"); - -#if 0 - if (encryptionScheme == 1) { //CBC - ret = DecryptAesCBC(f_pdwSubSampleMapping, f_cdwSubSampleMapping, - f_pbIV, f_cbIV, - payloadData, payloadDataSize, - f_pcbOpaqueClearContent, f_ppbOpaqueClearContent, - keyIdLength, f_keyId, - initWithLast15, - pattern.encrypted_blocks, pattern.clear_blocks); - } else { - ret = DecryptAesCTR(f_pdwSubSampleMapping, f_cdwSubSampleMapping, - f_pbIV, f_cbIV, - payloadData, payloadDataSize, - f_pcbOpaqueClearContent, f_ppbOpaqueClearContent, - keyIdLength, f_keyId, - initWithLast15); - } -#endif - return ret; -} - -CDMi_RESULT MediaKeySession::DecryptAesCBC( - const uint32_t *f_pdwSubSampleMapping, - uint32_t f_cdwSubSampleMapping, - const uint8_t *f_pbIV, - uint32_t f_cbIV, - const uint8_t *payloadData, - uint32_t payloadDataSize, - uint32_t *f_pcbOpaqueClearContent, - uint8_t **f_ppbOpaqueClearContent, - const uint8_t keyIdLength, - const uint8_t* f_keyId, - bool initWithLast15, - uint32_t cryptoBlocks, - uint32_t clearBlocks - ) -{ - DRM_RESULT dr = DRM_SUCCESS; - DRM_RESULT err = DRM_SUCCESS; - uint32_t actualDataLength = 0; - void *DstPhys = NULL; - bool useSVP = true; -#ifdef USE_SVP - RtkSecureMemory *rtkmem = NULL; -#endif - - assert(f_cbIV == EXPECTED_AES_CBC_IVDATA_SIZE); - - if ( f_keyId != nullptr ){ - KeyId keyId(&f_keyId[0],KeyId::KEYID_ORDER_UUID_BE); - - if (m_currentDecryptContext == nullptr - || m_currentDecryptContext->keyId != keyId) - { - m_currentDecryptContext = GetDecryptCtx( keyId ); + bGstSvpStatus = svp_buffer_alloc_token(&pSecureToken); + if (!bGstSvpStatus) { + ocdm_log("Memory alloc for token is failure\n"); + return CDMi_S_FALSE; } - } - if ( m_currentDecryptContext == nullptr ){ - fprintf(stderr, "[%s:%d] m_currentDecryptContext is Nullptr",__FUNCTION__,__LINE__); - return CDMi_S_FALSE; - - } - - - SafeCriticalSection systemLock(drmAppContextMutex_); - - - assert(f_cbIV > 0); - if(payloadDataSize == 0){ - return CDMi_SUCCESS; - } - - uint8_t *iv = malloc(f_cbIV * sizeof(uint8_t)); - - if (initWithLast15) { - // Netflix case - memcpy(iv, f_pbIV, f_cbIV * sizeof(uint8_t)); - - } else { - // Regular case - uint8_t buf[ f_cbIV ]; - for (uint32_t i = 0; i < f_cbIV / 2; i++) { - buf[i] = f_pbIV[f_cbIV - i - 1]; - buf[f_cbIV - i - 1] = f_pbIV[i]; + /* first byte will be used for encyption type - inPlace or handle */ + bGstSvpStatus = svp_buffer_to_token(m_pSVPContext, (void *)secbuf_out, pSecureToken + sizeof(uint8_t)); + if (!bGstSvpStatus) { + ocdm_log("Buffer to Token creation is failure"); + return CDMi_S_FALSE; } - memcpy(iv, buf, f_cbIV * sizeof(uint8_t)); - } - DRM_DWORD rgdwMappings[2]; - if ( NULL == f_pdwSubSampleMapping ) - { - rgdwMappings[0] = 0; - rgdwMappings[1] = payloadDataSize; - f_pdwSubSampleMapping = reinterpret_cast(rgdwMappings); - f_cdwSubSampleMapping = NO_OF(rgdwMappings); - } - uint8_t *data = const_cast(payloadData); - uint32_t subSampleCount = 0; - uint16_t inClear = 0; - uint32_t inEncrypted = 0; - uint8_t *dataItr = data; - DRM_DWORD encryptedRegionIvCounts = 1; - std::vector encryptedRegionCounts; - std::vector encryptedRegion; - std::vector encryptedRegionMapping; - std::vector iv_high; - std::vector iv_low; - DRM_UINT64 iv64; - - NETWORKBYTES_TO_QWORD(iv64, &iv[0], 0); - iv_high.push_back(iv64); - - NETWORKBYTES_TO_QWORD(iv64, &iv[8], 0); - iv_low.push_back(iv64); - - memcpy(&subSampleCount, data, sizeof(subSampleCount)); - dataItr += sizeof(subSampleCount); - - encryptedRegionCounts.push_back(subSampleCount); - -#ifdef USE_SVP - if (useSVP) - { - actualDataLength = payloadDataSize - svp_token_size(); - - // Allocate secure buffer for decryption. - rtkmem = rtk_secure_mem_new(actualDataLength, RTKMEM_VIDEO); - DstPhys = rtkmem->phys_addr; - } - else -#endif - { - actualDataLength = payloadDataSize; - } + *outDataLength = svp_token_size(); + *outData = (uint8_t *)inData; - payloadDataSize = actualDataLength; - - for (unsigned int position = 0; position < subSampleCount; position++) { - inClear = 0; - inEncrypted = 0; - memcpy(&inClear, dataItr, sizeof(inClear)); - dataItr += sizeof(inClear); - inClear = htons(inClear); - encryptedRegionMapping.push_back(static_cast (inClear)); - memcpy(&inEncrypted, dataItr, sizeof(inEncrypted)); - dataItr += sizeof(inEncrypted); - encryptedRegionMapping.push_back(htonl(inEncrypted)); - } - encryptedRegion.push_back(cryptoBlocks); - encryptedRegion.push_back(clearBlocks); - - DRM_DWORD* decryptedLength = 0; - DRM_BYTE** decryptedContent = NULL; - if (useSVP) { - decryptedLength = reinterpret_cast(&payloadDataSize); - decryptedContent = reinterpret_cast(&DstPhys); - } + memcpy((void *)(uint8_t*)decryptedData, pSecureToken, *outDataLength); + // Add a header to the output buffer. + ((DRM_BYTE*)decryptedData)[0] = 1; // 0 = inPlace, 1 = handle - int numBytesInMapping = 0; - for (auto it : encryptedRegionMapping) { - numBytesInMapping += it; - } + svp_buffer_free_token(pSecureToken); + pSecureToken = NULL; - if (useSVP) - { - err = Drm_Reader_DecryptMultipleOpaque(&(m_currentDecryptContext->oDrmDecryptContext), - encryptedRegionIvCounts, - &iv_high[0], &iv_low[0], - &encryptedRegionCounts[0], - encryptedRegionMapping.size(), &encryptedRegionMapping[0], - encryptedRegion.size(), &encryptedRegion[0], - (DRM_DWORD) actualDataLength, (DRM_BYTE *) dataItr, - decryptedLength, decryptedContent); - } - else - { - err = Drm_Reader_DecryptMultipleOpaque(&(m_currentDecryptContext->oDrmDecryptContext), - encryptedRegionIvCounts, - &iv_high[0], &iv_low[0], - &encryptedRegionCounts[0], - encryptedRegionMapping.size(), &encryptedRegionMapping[0], - encryptedRegion.size(), &encryptedRegion[0], - (DRM_DWORD) actualDataLength, (DRM_BYTE *) dataItr, - reinterpret_cast(&decryptedLength), reinterpret_cast(&decryptedContent)); - } - - free(iv); - iv = NULL; - - if (DRM_FAILED(err)) - { - fprintf(stderr, "[%s:%d] Drm_Reader_DecryptMultipleOpaque failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); -#ifdef USE_SVP - if (useSVP) + } else { + err = Drm_Reader_DecryptMultipleOpaque(m_oDecryptContext2, + 1, iv_vector, iv_vector + 1, regionCount, + encryptedRegions.size(), &encryptedRegions[0], + 2, regionSkip, + inputLen, (const DRM_BYTE*)decryptedData, + &opaque_buffer_size, + &opaque_buffer); + if (DRM_FAILED(err)) { - // Free decrypted secure buffer. - rtk_secure_mem_free(rtkmem); + ocdm_log("Failed to run Drm_Reader_DecryptMultipleOpaque2 %x\n", err); + return CDMi_S_FALSE; } -#endif - return err; - } - -#ifdef USE_SVP - if (useSVP) - { - Sec_OpaqueBufferHandle *desc = NULL; - desc = (Sec_OpaqueBufferHandle*)calloc(sizeof(Sec_OpaqueBufferHandle), 1); - desc->dataBufSize = actualDataLength; - desc->ion_fd = rtkmem->ion_fd; - desc->map_fd = rtkmem->ion_sharefd; - desc->rtkmem_handle = (void *)rtkmem->handle; - - void* secToken = NULL; - svp_buffer_alloc_token(&secToken); - svp_buffer_to_token(m_pSVPContext, (void *)desc, secToken); - memcpy((void *)payloadData, secToken, svp_token_size()); - svp_buffer_free_token(secToken); - //TODO: note the return token data and size - } -#endif - - if (!m_fCommit) { - err = Drm_Reader_Commit(m_poAppContext, _PolicyCallback, &m_playreadyLevels); - m_fCommit = TRUE; - } - - if (useSVP) - { - // Return clear content. - *f_pcbOpaqueClearContent = payloadDataSize; - *f_ppbOpaqueClearContent = (uint8_t *)payloadData; - } - else - { - *f_pcbOpaqueClearContent = actualDataLength; - *f_ppbOpaqueClearContent = (uint8_t *)dataItr; - } - - return CDMi_SUCCESS; -} - -CDMi_RESULT MediaKeySession::DecryptAesCTR( - const uint32_t *f_pdwSubSampleMapping, - uint32_t f_cdwSubSampleMapping, - const uint8_t *f_pbIV, - uint32_t f_cbIV, - const uint8_t *payloadData, - uint32_t payloadDataSize, - uint32_t *f_pcbOpaqueClearContent, - uint8_t **f_ppbOpaqueClearContent, - const uint8_t keyIdLength, - const uint8_t* f_keyId, - bool initWithLast15 - ) -{ - DRM_RESULT dr = DRM_SUCCESS; - DRM_RESULT err = DRM_SUCCESS; - void *DstPhys = NULL; - bool useSVP = true; -#ifdef USE_SVP - RtkSecureMemory *rtkmem = NULL; -#endif - - if ( f_keyId != nullptr ){ - KeyId keyId(&f_keyId[0],KeyId::KEYID_ORDER_UUID_BE); - - if (m_currentDecryptContext == nullptr - || m_currentDecryptContext->keyId != keyId) - { - m_currentDecryptContext = GetDecryptCtx( keyId ); + if (opaque_buffer) { + memcpy((uint8_t *)decryptedData, opaque_buffer, opaque_buffer_size); + free(opaque_buffer); + opaque_buffer = NULL; } - } - if ( m_currentDecryptContext == nullptr ){ - fprintf(stderr, "[%s:%d] m_currentDecryptContext is Nullptr",__FUNCTION__,__LINE__); - return CDMi_S_FALSE; - } - - SafeCriticalSection systemLock(drmAppContextMutex_); - - assert(f_cbIV > 0); - if(payloadDataSize == 0){ - return CDMi_SUCCESS; - } - - DRM_AES_COUNTER_MODE_CONTEXT ctrContext = { 0 }; - - if (initWithLast15) { - // Netflix case - memcpy(&ctrContext, f_pbIV, DRM_MIN(f_cbIV, sizeof(ctrContext)) ); + memmove((DRM_BYTE*)decryptedData + sizeof(uint8_t), decryptedData, inputLen); + // Add a header to the output buffer. + ((DRM_BYTE*)decryptedData)[0] = 0; // 0 = inPlace, 1 = handle - } else { - // Regular case - uint8_t buf[ f_cbIV ]; - for (uint32_t i = 0; i < f_cbIV / 2; i++) { - buf[i] = f_pbIV[f_cbIV - i - 1]; - buf[f_cbIV - i - 1] = f_pbIV[i]; - } - MEMCPY(&ctrContext.qwInitializationVector, buf, f_cbIV); - } - - uint8_t *data = const_cast(payloadData); - uint16_t inClear = 0; - uint32_t inEncrypted = 0; - uint32_t subSampleCount = 0; - uint8_t *dataItr = data; - uint32_t actualDataLength = 0; - - // 1. read the subsample count - memcpy(&subSampleCount, data, sizeof(subSampleCount)); - f_cdwSubSampleMapping = subSampleCount; - dataItr += sizeof(subSampleCount); - -#ifdef USE_SVP - if (useSVP) - { - actualDataLength = payloadDataSize - svp_token_size(); - - // Allocate secure buffer for decryption. - rtkmem = rtk_secure_mem_new(actualDataLength, RTKMEM_VIDEO); - DstPhys = rtkmem->phys_addr; - } - else -#endif - { - actualDataLength = payloadDataSize; + *outDataLength = inDataLength; + *outData = (uint8_t *)inData; } - // 2. read the subsample buffer - DRM_DWORD rgdwMappings[subSampleCount*2]; - for (unsigned int position = 0; position < (subSampleCount*2); position+=2) { - inClear = 0; - inEncrypted = 0; - - memcpy(&inClear, dataItr, sizeof(inClear)); - dataItr += sizeof(inClear); - memcpy(&inEncrypted, dataItr, sizeof(inEncrypted)); - dataItr += sizeof(inEncrypted); - - rgdwMappings[position] = ntohs(inClear); - rgdwMappings[position+1] = ntohl(inEncrypted); - } - f_pdwSubSampleMapping = reinterpret_cast(rgdwMappings); - - // 3. dataItr is the encrypted data now - if (useSVP) - { - err = Drm_Reader_DecryptOpaque( - &(m_currentDecryptContext->oDrmDecryptContext), - f_cdwSubSampleMapping*2, - reinterpret_cast(f_pdwSubSampleMapping), - ctrContext.qwInitializationVector, - actualDataLength, - (DRM_BYTE *) dataItr, - reinterpret_cast(&actualDataLength), - reinterpret_cast(&DstPhys)); - } - else - { - DRM_DWORD* decryptedLength = 0; - DRM_BYTE** decryptedContent = NULL; - err = Drm_Reader_DecryptOpaque( - &(m_currentDecryptContext->oDrmDecryptContext), - f_cdwSubSampleMapping*2, - reinterpret_cast(f_pdwSubSampleMapping), - ctrContext.qwInitializationVector, - actualDataLength, - (DRM_BYTE *) dataItr, - reinterpret_cast(&decryptedLength), - reinterpret_cast(&decryptedContent)); + // Call commit during the decryption of the first sample. + if (!m_fCommit) { + //err = Drm_Reader_Commit(m_poAppContext, &opencdm_output_levels_callback, &levels_); + err = Drm_Reader_Commit(m_poAppContext, _PolicyCallback, nullptr); // TODO: pass along user data + if (DRM_FAILED(err)) { + ocdm_log("Failed to do Reader Commit\n"); + return CDMi_S_FALSE; + } + m_fCommit = TRUE; } - - if (DRM_FAILED(err)) - { - fprintf(stderr, "[%s:%d] Drm_Reader_DecryptOpaque failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); -#ifdef USE_SVP - if (useSVP) { - // Free decrypted secure buffer. - rtk_secure_mem_free(rtkmem); - } -#endif - return CDMi_S_FALSE; - } - -#ifdef USE_SVP - if (useSVP) - { - Sec_OpaqueBufferHandle *desc = NULL; - desc = (Sec_OpaqueBufferHandle*)calloc(sizeof(Sec_OpaqueBufferHandle), 1); - desc->dataBufSize = actualDataLength; - desc->ion_fd = rtkmem->ion_fd; - desc->map_fd = rtkmem->ion_sharefd; - desc->rtkmem_handle = (void *)rtkmem->handle; - - void* secToken = NULL; - svp_buffer_alloc_token(&secToken); - svp_buffer_to_token(m_pSVPContext, (void*)desc, secToken); - memcpy((void *)payloadData, secToken, svp_token_size()); - svp_buffer_free_token(secToken); - //TODO: note the return token data and size - } -#endif - - if (!m_fCommit) { - err = Drm_Reader_Commit(m_poAppContext, _PolicyCallback, &m_playreadyLevels); - m_fCommit = TRUE; - } - - if (useSVP) - { - // Return clear content. - *f_pcbOpaqueClearContent = payloadDataSize; - *f_ppbOpaqueClearContent = (uint8_t *)payloadData; - } - else - { - *f_pcbOpaqueClearContent = actualDataLength; - *f_ppbOpaqueClearContent = (uint8_t *)dataItr; - } - - return CDMi_SUCCESS; + + return CDMi_SUCCESS; } -#endif CDMi_RESULT MediaKeySession::ReleaseClearContent( const uint8_t *f_pbSessionKey, uint32_t f_cbSessionKey, const uint32_t f_cbClearContentOpaque, uint8_t *f_pbClearContentOpaque ) { + return CDMi_SUCCESS; + } } // namespace CDMi diff --git a/MediaSession.h b/MediaSession.h index 4120b81..22597a5 100644 --- a/MediaSession.h +++ b/MediaSession.h @@ -14,18 +14,24 @@ * See the License for the specific language governing permissions and * limitations under the License. */ + #pragma once +//#include +#include -#include #include #include #include #include #include -#include -#include +#include #include #include + +#include +#include +#include + #undef min #undef max #undef __in @@ -35,13 +41,36 @@ #include #include #include -#include -#include +//#include + +#ifndef MODULE_NAME +#define MODULE_NAME Playready +#endif #ifndef SIZEOF #define SIZEOF sizeof +#include +#else +#include +#endif + +#include +#include + + +#ifdef USE_SYSTEMD_JOURNAL_PRINT +#include +#else +#include #endif +#ifdef USE_SYSTEMD_JOURNAL_PRINT +#define ocdm_log(fmt,args...) sd_journal_print(LOG_NOTICE, "[OCDM][Playready]" fmt, ##args) +#else +#define ocdm_log(fmt,args...) syslog(LOG_NOTICE, "[OCDM][Playready][sys]" fmt, ##args) +#endif + + #ifdef DRM_ONE_CHAR #define ONE_CHAR DRM_ONE_CHAR #endif @@ -134,6 +163,7 @@ typedef std::shared_ptr<__DECRYPT_CONTEXT> DECRYPT_CONTEXT; #define NEW_DECRYPT_CONTEXT() std::make_shared<__DECRYPT_CONTEXT>() ////////////////////////////////////////////////////////////////// +/* class SafeCriticalSection { public: @@ -169,8 +199,27 @@ class SafeCriticalSection WPEFramework::Core::CriticalSection& mLock; bool mLocked; }; +*/ + +/////////////////////////////////////////////////////////// namespace CDMi { +#define CHECK_EXACT(call, value, label) \ + if ((call) != value) \ + { \ + goto label; \ + } +typedef uint32_t secmem_handle_t; +struct Sec_OpaqueBufferHandle_struct +{ + secmem_handle_t secmem_handle; + uint32_t dataBufSize; +}; +typedef struct Sec_OpaqueBufferHandle_struct Sec_OpaqueBufferHandle; + +DRM_WCHAR* createDrmWchar(std::string const& s); +void PackedCharsToNative(DRM_CHAR *f_pPackedString, DRM_DWORD f_cch); +std::string GetDrmStorePath(); struct PlayreadyOutProtLevels { @@ -181,11 +230,21 @@ struct PlayreadyOutProtLevels struct PlayLevels { - uint16_t compressedDigitalVideoLevel_; - uint16_t uncompressedDigitalVideoLevel_; - uint16_t analogVideoLevel_; - uint16_t compressedDigitalAudioLevel_; - uint16_t uncompressedDigitalAudioLevel_; + uint16_t compressedDigitalVideoLevel_; //!< Compressed digital video output protection level. + uint16_t uncompressedDigitalVideoLevel_; //!< Uncompressed digital video output protection level. + uint16_t analogVideoLevel_; //!< Analog video output protection level. + uint16_t compressedDigitalAudioLevel_; //!< Compressed digital audio output protection level. + uint16_t uncompressedDigitalAudioLevel_; //!< Uncompressed digital audio output protection level. +}; + +class LicenseResponse { +public: + LicenseResponse() : dlr(new DRM_LICENSE_RESPONSE) {} + ~LicenseResponse() { delete dlr; } + DRM_LICENSE_RESPONSE * get() { return dlr; } + void clear() { memset(dlr, 0, sizeof(DRM_LICENSE_RESPONSE)); } +private: + DRM_LICENSE_RESPONSE * const dlr; }; class PlayreadySession @@ -206,7 +265,7 @@ class PlayreadySession bool m_bInitCalled; }; -class MediaKeySession : public PlayreadySession , public IMediaKeySession , public IMediaKeySessionExt { +class MediaKeySession : public IMediaKeySession, public IMediaKeySessionExt { private: enum KeyState { // Has been initialized. @@ -227,11 +286,11 @@ class MediaKeySession : public PlayreadySession , public IMediaKeySession , publ IndividualizationRequest = 3 }; public: - - MediaKeySession( - const uint8_t drmHeader[], - uint32_t drmHeaderLength, - DRM_APP_CONTEXT * poAppContext, bool initiateChallengeGeneration = false); + //static const std::vector m_mimeTypes; + // MediaKeySession( + // const uint8_t drmHeader[], + // uint32_t drmHeaderLength, + // DRM_APP_CONTEXT * poAppContext, bool initiateChallengeGeneration = false); MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitData, const uint8_t *f_pbCDMData, uint32_t f_cbCDMData, DRM_APP_CONTEXT * poAppContext, bool initiateChallengeGeneration = false); ~MediaKeySession(); @@ -239,6 +298,7 @@ class MediaKeySession : public PlayreadySession , public IMediaKeySession , publ bool playreadyGenerateKeyRequest(); bool ready() const { return m_eKeyState == KEY_READY; } + // MediaKeySession overrides virtual void Run( const IMediaKeySessionCallback *f_piMediaKeySessionCallback); @@ -251,11 +311,40 @@ class MediaKeySession : public PlayreadySession , public IMediaKeySession , publ virtual CDMi_RESULT Remove(); virtual CDMi_RESULT Close(void); - virtual CDMi_RESULT PlaybackStopped(void); - virtual CDMi_RESULT SetParameter(const std::string& name, const std::string& value); + virtual void SetParameter(const uint8_t * data, const uint32_t length); virtual const char *GetSessionId(void) const; virtual const char *GetKeySystem(void) const; +////////////////////// Decrypt /////////////////////////////////// +#ifdef AML_SVP_PR + + virtual CDMi_RESULT Decrypt( + const uint8_t *f_pbSessionKey, + uint32_t f_cbSessionKey, + const EncryptionScheme encryptionScheme, + const EncryptionPattern& pattern, + const uint8_t *f_pbIV, + uint32_t f_cbIV, + const uint8_t *f_pbData, + uint32_t f_cbData, + uint32_t *f_pcbOpaqueClearContent, + uint8_t **f_ppbOpaqueClearContent, + const uint8_t keyIdLength, + const uint8_t* keyId, + bool initWithLast15) { + + return (CDMi_METHOD_NOT_IMPLEMENTED); + } + virtual CDMi_RESULT Decrypt( + uint8_t* inData, + const uint32_t inDataLength, + uint8_t** outData, + uint32_t* outDataLength, + const SampleInfo* sampleInfo, + const IStreamProperties* properties); + +///////////////////////////////////////////////////////////////////// +#else virtual CDMi_RESULT MediaKeySession::Decrypt( uint8_t* inData, @@ -343,6 +432,9 @@ class MediaKeySession : public PlayreadySession , public IMediaKeySession , publ bool initWithLast15); #endif +#endif +////////////////////// Decrypt /////////////////////////////////// + virtual CDMi_RESULT ReleaseClearContent( const uint8_t *f_pbSessionKey, uint32_t f_cbSessionKey, @@ -350,43 +442,49 @@ class MediaKeySession : public PlayreadySession , public IMediaKeySession , publ uint8_t *f_pbClearContentOpaque ); static DRM_BOOL m_bPrintOPLError; + uint32_t GetSessionIdExt(void) const override; - uint32_t GetSessionIdExt(void) const; - - virtual CDMi_RESULT SetDrmHeader(const uint8_t drmHeader[], uint32_t drmHeaderLength); - virtual CDMi_RESULT GetChallengeDataExt(uint8_t * challenge, uint32_t & challengeSize, uint32_t isLDL); - virtual CDMi_RESULT CancelChallengeDataExt(); - virtual CDMi_RESULT StoreLicenseData(const uint8_t licenseData[], uint32_t licenseDataSize, unsigned char * secureStopId); - virtual CDMi_RESULT SelectKeyId(const uint8_t keyLength, const uint8_t keyId[]); - virtual CDMi_RESULT CleanDecryptContext(); - - + virtual CDMi_RESULT SetDrmHeader(const uint8_t drmHeader[], uint32_t drmHeaderLength) override; + virtual CDMi_RESULT GetChallengeDataExt(uint8_t * challenge, uint32_t & challengeSize, uint32_t isLDL) override; + virtual CDMi_RESULT CancelChallengeDataExt() override; + virtual CDMi_RESULT StoreLicenseData(const uint8_t licenseData[], uint32_t licenseDataSize, unsigned char * secureStopId) override; + virtual CDMi_RESULT SelectKeyId(const uint8_t keyLength, const uint8_t keyId[]) override; + virtual CDMi_RESULT CleanDecryptContext() override; private: - std::vector< DECRYPT_CONTEXT > m_DecryptContextVector; + CDMi_RESULT SetKeyId(DRM_APP_CONTEXT *pDrmAppCtx, const uint8_t keyLength, const uint8_t keyId[]); + CDMi_RESULT SelectDrmHeader(DRM_APP_CONTEXT *pDrmAppCtx, const uint32_t headerLength, const uint8_t header[]); + CDMi_RESULT SetOutputMode(DRM_APP_CONTEXT *pDrmAppCtx, DRM_DWORD dwDecryptionMode); - static bool mMaxResDecodeSet; - static uint64_t mMaxResDecodePixels; + // std::vector< DECRYPT_CONTEXT > m_DecryptContextVector; - virtual CDMi_RESULT DRM_DecryptFailure(DRM_RESULT dr, const uint8_t *payloadData, uint32_t *f_pcbOpaqueClearContent, uint8_t **f_ppbOpaqueClearContent); + // static bool mMaxResDecodeSet; + // static uint64_t mMaxResDecodePixels; - struct PlayreadyOutProtLevels m_playreadyLevels; + // virtual CDMi_RESULT DRM_DecryptFailure(DRM_RESULT dr, const uint8_t *payloadData, uint32_t *f_pcbOpaqueClearContent, uint8_t **f_ppbOpaqueClearContent); - static DRM_RESULT DRM_CALL _PolicyCallback(const DRM_VOID *, - DRM_POLICY_CALLBACK_TYPE f_dwCallbackType, const DRM_KID *, - const DRM_LID *, const DRM_VOID *); + // struct PlayreadyOutProtLevels m_playreadyLevels; + + static DRM_RESULT DRM_CALL _PolicyCallback(const DRM_VOID *, DRM_POLICY_CALLBACK_TYPE f_dwCallbackType, + const DRM_KID *, const DRM_LID *, const DRM_VOID *); + + DRM_BYTE *m_pbOpaqueBuffer; + DRM_DWORD m_cbOpaqueBuffer; - DRM_BYTE *m_pbRevocationBuffer; KeyState m_eKeyState; DRM_CHAR m_rgchSessionID[CCH_BASE64_EQUIV(SIZEOF(DRM_ID)) + 1]; - + DRM_BYTE *m_pbChallenge; DRM_DWORD m_cbChallenge; - DRM_CHAR *m_pchSilentURL; + DRM_CHAR *m_pchSilentURL; std::string m_customData; IMediaKeySessionCallback *m_piCallback; +private: + std::unique_ptr mLicenseResponse; + std::vector mSecureStopId; + std::vector mNounce; std::vector mDrmHeader; uint32_t mSessionId; PlayLevels levels_; @@ -397,10 +495,8 @@ class MediaKeySession : public PlayreadySession , public IMediaKeySession , publ DRM_ID m_oBatchID; std::vector> m_oPersistentLicenses; DECRYPT_CONTEXT m_currentDecryptContext; -#ifdef USE_SVP void* m_pSVPContext; unsigned int m_rpcID; -#endif CDMi_RESULT PersistentLicenseCheck(); DRM_RESULT ProcessLicenseResponse( DRM_PROCESS_LIC_RESPONSE_FLAG f_eResponseFlag, @@ -427,13 +523,18 @@ class MediaKeySession : public PlayreadySession , public IMediaKeySession , publ void SaveTemporaryPersistentLicenses(const DRM_LICENSE_RESPONSE* f_poLicenseResponse); void DeleteTemporaryPersistentLicenses(); const char* printGuid(KeyId &keyId); - const char* printUuid(KeyId &keyId); + const char* printUuid(KeyId &keyId); protected: DRM_BOOL m_fCommit; DRM_APP_CONTEXT *m_poAppContext; bool m_decryptInited; bool m_bDRMInitializedLocally; + + static void *sess; + static uint32_t m_secCount; + DRM_DECRYPT_CONTEXT *m_oDecryptContext; + DRM_DECRYPT_CONTEXT *m_oDecryptContext2; }; class CPRDrmPlatform @@ -449,4 +550,4 @@ class CPRDrmPlatform extern DRM_INIT_CONTEXT g_oDrmInitContext; -} // namespace CDMi +} // namespace CDMi \ No newline at end of file diff --git a/MediaSessionExt.cpp b/MediaSessionExt.cpp index 8836f16..2247376 100644 --- a/MediaSessionExt.cpp +++ b/MediaSessionExt.cpp @@ -1,16 +1,34 @@ +/* + * If not stated otherwise in this file or this component's LICENSE file the + * following copyright and licenses apply: + * + * Copyright 2020 RDK Management + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + #include "MediaSession.h" #include #include #include -#ifdef USE_SVP -#include "gst_svp_meta.h" -#endif - using namespace std; +#include -extern WPEFramework::Core::CriticalSection drmAppContextMutex_; +using namespace WPEFramework; +using SafeCriticalSection = Core::SafeSyncType; +extern Core::CriticalSection drmAppContextMutex_; const DRM_WCHAR PLAY[] = { ONE_WCHAR('P', '\0'), ONE_WCHAR('l', '\0'), @@ -19,7 +37,7 @@ const DRM_WCHAR PLAY[] = { ONE_WCHAR('P', '\0'), ONE_WCHAR('\0', '\0') }; const DRM_CONST_STRING PLAY_RIGHT = CREATE_DRM_STRING(PLAY); - +static const DRM_CONST_STRING* RIGHTS[] = { &g_dstrDRM_RIGHT_PLAYBACK }; const KeyId KeyId::EmptyKeyId; namespace CDMi { @@ -27,108 +45,20 @@ namespace CDMi { std::map mBindMap; static const DRM_CONST_STRING* RIGHTS[] = { &PLAY_RIGHT }; -MediaKeySession::MediaKeySession(const uint8_t drmHeader[], uint32_t drmHeaderLength, DRM_APP_CONTEXT * poAppContext, bool initiateChallengeGeneration /* = false */) - : m_pbRevocationBuffer(nullptr) - , m_eKeyState(KEY_CLOSED) - , m_pbChallenge(nullptr) - , m_cbChallenge(0) - , m_pchSilentURL(nullptr) - , m_piCallback(nullptr) - , mSessionId(0) - , mInitiateChallengeGeneration(initiateChallengeGeneration) - , m_cHeaderKIDs(0) - , m_pdstrHeaderKIDs( nullptr ) - , m_eHeaderVersion( DRM_HEADER_VERSION_UNKNOWN ) - , m_oBatchID( DRM_ID_EMPTY ) - , m_currentDecryptContext( nullptr ) -#ifdef USE_SVP - , m_pSVPContext(nullptr) - , m_rpcID(0) -#endif - , m_fCommit(false) - , m_poAppContext(poAppContext) - , m_decryptInited(false) - , m_bDRMInitializedLocally(false) -{ -#ifdef USE_SVP - gst_svp_ext_get_context(&m_pSVPContext, Client, m_rpcID); -#endif - - mDrmHeader.resize(drmHeaderLength); - memcpy(&mDrmHeader[0], drmHeader, drmHeaderLength); - - m_eKeyState = KEY_INIT; -} - uint32_t MediaKeySession::GetSessionIdExt() const { + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); return mSessionId; } CDMi_RESULT MediaKeySession::SetDrmHeader(const uint8_t drmHeader[], uint32_t drmHeaderLength) { + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); mDrmHeader.resize(drmHeaderLength); memcpy(&mDrmHeader[0], drmHeader, drmHeaderLength); return CDMi_SUCCESS; } -CDMi_RESULT MediaKeySession::BindKeyNow(DECRYPT_CONTEXT decryptContext) -{ - - DRM_VOID * pvData = nullptr; - DRMPFNPOLICYCALLBACK pfnOPLCallback = nullptr; - DECRYPT_CONTEXT tmpDecryptContext; - DRM_RESULT dr; - - if ( CDMi_SUCCESS != SetKeyIdProperty( decryptContext->keyId ) ) - { - return CDMi_S_FALSE; - } - - dr = ReaderBind( - RIGHTS, - sizeof(RIGHTS) / sizeof(DRM_CONST_STRING*), - _PolicyCallback, - pvData, - &(decryptContext->oDrmDecryptContext) ); - - if ( DRM_FAILED( dr ) ){ - fprintf(stderr, "[%s:%d] ReaderBind failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); - return CDMi_S_FALSE; - } else { - dr = Drm_Reader_Commit(m_poAppContext, _PolicyCallback, pvData); - if (DRM_FAILED(dr)) - { - fprintf(stderr, "[%s:%d] Drm_Reader_Commit failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); - return CDMi_S_FALSE; - } - } - if ( nullptr == ( tmpDecryptContext = GetDecryptCtx( decryptContext->keyId ) ) ){ - m_DecryptContextVector.push_back(decryptContext); - } - return CDMi_SUCCESS; -} - -CDMi_RESULT MediaKeySession::BindKey(KeyId keyId) -{ - DECRYPT_CONTEXT decryptContext; - decryptContext = NEW_DECRYPT_CONTEXT(); - decryptContext->keyId = keyId; - - auto it = mBindMap.find(keyId); - if (it != mBindMap.end()) - { - it->second = decryptContext; - return CDMi_SUCCESS; - } - else - { - BindKeyNow(decryptContext); - mBindMap.insert(std::make_pair(decryptContext->keyId, std::shared_ptr<__DECRYPT_CONTEXT>())); - } - return CDMi_SUCCESS; -} - CDMi_RESULT MediaKeySession::StoreLicenseData(const uint8_t f_rgbLicenseData[], uint32_t f_cbLicenseDataSize, uint8_t * f_pSecureStopId) { DRM_RESULT err = DRM_SUCCESS; @@ -213,66 +143,6 @@ CDMi_RESULT MediaKeySession::StoreLicenseData(const uint8_t f_rgbLicenseData[], return CDMi_SUCCESS; } -CDMi_RESULT MediaKeySession::SelectKeyId( const uint8_t f_keyLength, const uint8_t f_keyId[] ) -{ - SafeCriticalSection systemLock(drmAppContextMutex_); - DRM_RESULT err; - DRMPFNPOLICYCALLBACK pfnOPLCallback = nullptr; - DRM_VOID * pvData = nullptr; - - pfnOPLCallback = _PolicyCallback; - - if ( f_keyId == nullptr || f_keyLength != DRM_ID_SIZE ) - { - fprintf(stderr, "[%s:%d] Bad value for keyId arg ",__FUNCTION__,__LINE__); - return CDMi_S_FALSE; - } - - KeyId keyId(&f_keyId[0],KeyId::KEYID_ORDER_UUID_BE); - std::string keyIdHex(keyId.HexStr()); - - if ( nullptr != ( m_currentDecryptContext = GetDecryptCtx( keyId ) ) ){ - return CDMi_SUCCESS; - } - - if ( CDMi_SUCCESS != SetKeyIdProperty( keyId ) ) - { - fprintf(stderr, "[%s:%d] SetKeyIdProperty failed",__FUNCTION__,__LINE__); - return CDMi_S_FALSE; - } - - CDMi_RESULT result = CDMi_SUCCESS; - - DECRYPT_CONTEXT decryptContext = NEW_DECRYPT_CONTEXT(); - err = ReaderBind( - RIGHTS, - sizeof(RIGHTS) / sizeof(DRM_CONST_STRING*), - pfnOPLCallback, - pvData, - &(decryptContext->oDrmDecryptContext ) ); - - if (DRM_FAILED(err)) - { - fprintf(stderr, "[%s:%d] ReaderBind failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); - result = CDMi_S_FALSE; - } else { - err = Drm_Reader_Commit(m_poAppContext, pfnOPLCallback, pvData); - if (DRM_FAILED(err)) - { - fprintf(stderr, "[%s:%d] Drm_Reader_Commit failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); - result = CDMi_S_FALSE; - } - } - if (result == CDMi_SUCCESS) { - m_fCommit = TRUE; - m_decryptInited = true; - decryptContext->keyId = keyId; - m_DecryptContextVector.push_back(decryptContext); - m_currentDecryptContext = decryptContext; - } - return result; -} - CDMi_RESULT MediaKeySession::GetChallengeDataExt(uint8_t * f_pChallenge, uint32_t & f_ChallengeSize, uint32_t f_isLDL) { DRM_RESULT err; @@ -375,10 +245,10 @@ CDMi_RESULT MediaKeySession::CleanDecryptContext() ASSERT(m_poAppContext != nullptr); - for (DECRYPT_CONTEXT &ctx : m_DecryptContextVector) - { - Unbind(ctx->keyId); - } + // for (DECRYPT_CONTEXT &ctx : m_DecryptContextVector) + // { + // Unbind(ctx->keyId); + // } CloseDecryptContexts(); @@ -395,5 +265,216 @@ CDMi_RESULT MediaKeySession::CleanDecryptContext() m_decryptInited = false; return CDMi_SUCCESS; } + + + + + + + +CDMi_RESULT MediaKeySession::SetKeyId(DRM_APP_CONTEXT *pDrmAppCtx, const uint8_t keyLength, const uint8_t keyId[]){ + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); + return CDMi_SUCCESS; } + +CDMi_RESULT MediaKeySession::BindKeyNow(DECRYPT_CONTEXT decryptContext) +{ + + DRM_VOID * pvData = nullptr; + DRMPFNPOLICYCALLBACK pfnOPLCallback = nullptr; + DECRYPT_CONTEXT tmpDecryptContext; + DRM_RESULT dr; + + if ( CDMi_SUCCESS != SetKeyIdProperty( decryptContext->keyId ) ) + { + return CDMi_S_FALSE; + } + + dr = ReaderBind( + RIGHTS, + sizeof(RIGHTS) / sizeof(DRM_CONST_STRING*), + _PolicyCallback, + pvData, + &(decryptContext->oDrmDecryptContext) ); + + if ( DRM_FAILED( dr ) ){ + fprintf(stderr, "[%s:%d] ReaderBind failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + return CDMi_S_FALSE; + } else { + dr = Drm_Reader_Commit(m_poAppContext, _PolicyCallback, pvData); + if (DRM_FAILED(dr)) + { + fprintf(stderr, "[%s:%d] Drm_Reader_Commit failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + return CDMi_S_FALSE; + } + } + if ( nullptr == ( tmpDecryptContext = GetDecryptCtx( decryptContext->keyId ) ) ){ + // m_DecryptContextVector.push_back(decryptContext); + } + return CDMi_SUCCESS; +} + +CDMi_RESULT MediaKeySession::BindKey(KeyId keyId) +{ + DECRYPT_CONTEXT decryptContext; + decryptContext = NEW_DECRYPT_CONTEXT(); + decryptContext->keyId = keyId; + + auto it = mBindMap.find(keyId); + if (it != mBindMap.end()) + { + it->second = decryptContext; + return CDMi_SUCCESS; + } + else + { + BindKeyNow(decryptContext); + mBindMap.insert(std::make_pair(decryptContext->keyId, std::shared_ptr<__DECRYPT_CONTEXT>())); + } + return CDMi_SUCCESS; +} + + + +CDMi_RESULT MediaKeySession::SelectKeyId( const uint8_t f_keyLength, const uint8_t f_keyId[] ) +{ + SafeCriticalSection systemLock(drmAppContextMutex_); + DRM_RESULT err; + DRMPFNPOLICYCALLBACK pfnOPLCallback = nullptr; + DRM_VOID * pvData = nullptr; + + pfnOPLCallback = _PolicyCallback; + + if ( f_keyId == nullptr || f_keyLength != DRM_ID_SIZE ) + { + fprintf(stderr, "[%s:%d] Bad value for keyId arg ",__FUNCTION__,__LINE__); + return CDMi_S_FALSE; + } + + KeyId keyId(&f_keyId[0],KeyId::KEYID_ORDER_UUID_BE); + std::string keyIdHex(keyId.HexStr()); + + if ( nullptr != ( m_currentDecryptContext = GetDecryptCtx( keyId ) ) ){ + return CDMi_SUCCESS; + } + + if ( CDMi_SUCCESS != SetKeyIdProperty( keyId ) ) + { + fprintf(stderr, "[%s:%d] SetKeyIdProperty failed",__FUNCTION__,__LINE__); + return CDMi_S_FALSE; + } + + CDMi_RESULT result = CDMi_SUCCESS; + + DECRYPT_CONTEXT decryptContext = NEW_DECRYPT_CONTEXT(); + err = ReaderBind( + RIGHTS, + sizeof(RIGHTS) / sizeof(DRM_CONST_STRING*), + pfnOPLCallback, + pvData, + &(decryptContext->oDrmDecryptContext ) ); + + if (DRM_FAILED(err)) + { + fprintf(stderr, "[%s:%d] ReaderBind failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); + result = CDMi_S_FALSE; + } else { + err = Drm_Reader_Commit(m_poAppContext, pfnOPLCallback, pvData); + if (DRM_FAILED(err)) + { + fprintf(stderr, "[%s:%d] Drm_Reader_Commit failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); + result = CDMi_S_FALSE; + } + } + if (result == CDMi_SUCCESS) { + m_fCommit = TRUE; + m_decryptInited = true; + decryptContext->keyId = keyId; + // m_DecryptContextVector.push_back(decryptContext); + m_currentDecryptContext = decryptContext; + } + return result; +} + +CDMi_RESULT MediaKeySession::SelectDrmHeader(DRM_APP_CONTEXT *pDrmAppCtx, + const uint32_t headerLength, const uint8_t header[]) +{ + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); + // Make the current app context contain the DRM header for this session. + ocdm_log("Drm_Content_SetProperty DRM_CSP_AUTODETECT_HEADER\n"); + + return CDMi_SUCCESS; +} + +CDMi_RESULT MediaKeySession::SetOutputMode(DRM_APP_CONTEXT *pDrmAppCtx, DRM_DWORD dwDecryptionMode) +{ + + return CDMi_SUCCESS; + +} + +struct CallbackInfo +{ + IMediaKeySessionCallback * _callback; + uint16_t _compressedVideo; + uint16_t _uncompressedVideo; + uint16_t _analogVideo; + uint16_t _compressedAudio; + uint16_t _uncompressedAudio; +}; + +static void * PlayLevelUpdateCallback(void * data) +{ + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); + CallbackInfo * callbackInfo = static_cast(data); + + stringstream keyMessage; + keyMessage << "{"; + keyMessage << "\"compressed-video\": " << callbackInfo->_compressedVideo << ","; + keyMessage << "\"uncompressed-video\": " << callbackInfo->_uncompressedVideo << ","; + keyMessage << "\"analog-video\": " << callbackInfo->_analogVideo << ","; + keyMessage << "\"compressed-audio\": " << callbackInfo->_compressedAudio << ","; + keyMessage << "\"uncompressed-audio\": " << callbackInfo->_uncompressedAudio; + keyMessage << "}"; + + string keyMessageStr = keyMessage.str(); + const uint8_t * messageBytes = reinterpret_cast(keyMessageStr.c_str()); + + char urlBuffer[64]; + strcpy(urlBuffer, "properties"); + callbackInfo->_callback->OnKeyMessage(messageBytes, keyMessageStr.length() + 1, urlBuffer); + + delete callbackInfo; + return nullptr; +} + +static DRM_RESULT opencdm_output_levels_callback(const DRM_VOID *outputLevels, DRM_POLICY_CALLBACK_TYPE callbackType, const DRM_VOID *data) { + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); + // We only care about the play callback. + if (callbackType != DRM_PLAY_OPL_CALLBACK) + return DRM_SUCCESS; + return DRM_SUCCESS; + const IMediaKeySessionCallback * constSessionCallback = reinterpret_cast(data); + if (constSessionCallback != nullptr) { + CallbackInfo * callbackInfo = new CallbackInfo; + callbackInfo->_callback = const_cast(constSessionCallback); + + // Pull out the protection levels. + const DRM_PLAY_OPL_EX2* playLevels = static_cast(outputLevels); + callbackInfo->_compressedVideo = playLevels->minOPL.wCompressedDigitalVideo; + callbackInfo->_uncompressedVideo = playLevels->minOPL.wUncompressedDigitalVideo; + callbackInfo->_analogVideo = playLevels->minOPL.wAnalogVideo; + callbackInfo->_compressedAudio = playLevels->minOPL.wCompressedDigitalAudio; + callbackInfo->_uncompressedAudio = playLevels->minOPL.wUncompressedDigitalAudio; + + // Run on a new thread, so we don't go too deep in the IPC callstack. + pthread_t threadId; + pthread_create(&threadId, nullptr, PlayLevelUpdateCallback, callbackInfo); + + } + // All done. + return DRM_SUCCESS; +} + +} diff --git a/MediaSystem.cpp b/MediaSystem.cpp index 13ef6d1..590decf 100644 --- a/MediaSystem.cpp +++ b/MediaSystem.cpp @@ -15,22 +15,20 @@ * limitations under the License. */ #include "MediaSession.h" +#include +//#include +#include + + #include #include #include #include -#include -#include -#include -#include -#include - -#include -#define CLEAN_ON_INIT 1 - -#define DEVICESTORE_DIGEST_BYTES_SIZE OEM_SHA256_DIGEST_SIZE_IN_BYTES +// has its own TRACING mechanism. We do not want to use those, undefine it here to avoid a warning. +// with the TRACE macro of the PLAYREADY software. +#undef TRACE #define ErrCheckCert() do { \ if ( m_pbPublisherCert == NULL || m_cbPublisherCert == 0 ) { \ @@ -40,52 +38,33 @@ }while( 0 ) using namespace std; - +using namespace WPEFramework; extern DRM_CONST_STRING g_dstrDrmPath; -WPEFramework::Core::CriticalSection drmAppContextMutex_; - -// static DRM_WCHAR* createDrmWchar(std::string const& s) { -// DRM_WCHAR* w = new DRM_WCHAR[s.length() + 1]; -// for (size_t i = 0; i < s.length(); ++i) -// w[i] = ONE_WCHAR(s[i], '\0'); -// w[s.length()] = ONE_WCHAR('\0', '\0'); -// return w; -// } - -// static void PackedCharsToNative(DRM_CHAR *f_pPackedString, DRM_DWORD f_cch) { -// DRM_DWORD ich = 0; - -// if( f_pPackedString == nullptr -// || f_cch == 0 ) -// { -// return; -// } -// for( ich = 1; ich <= f_cch; ich++ ) -// { -// f_pPackedString[f_cch - ich] = ((DRM_BYTE*)f_pPackedString)[ f_cch - ich ]; -// } -// } +using SafeCriticalSection = Core::SafeSyncType; + +Core::CriticalSection drmAppContextMutex_; +DRM_CONST_STRING g_dstrCDMDrmStoreName; + namespace CDMi { -static DRM_WCHAR* createDrmWchar(std::string const& s) { +DRM_WCHAR* createDrmWchar(std::string const& s) { DRM_WCHAR* w = new DRM_WCHAR[s.length() + 1]; for (size_t i = 0; i < s.length(); ++i) - w[i] = ONE_WCHAR(s[i], '\0'); - w[s.length()] = ONE_WCHAR('\0', '\0'); + w[i] = DRM_ONE_WCHAR(s[i], '\0'); + w[s.length()] = DRM_ONE_WCHAR('\0', '\0'); return w; } -static void PackedCharsToNative(DRM_CHAR *f_pPackedString, DRM_DWORD f_cch) { +void PackedCharsToNative(DRM_CHAR *f_pPackedString, DRM_DWORD f_cch) { DRM_DWORD ich = 0; - if( f_pPackedString == nullptr - || f_cch == 0 ) + if ( f_pPackedString == nullptr || f_cch == 0 ) { return; } - for( ich = 1; ich <= f_cch; ich++ ) + for ( ich = 1; ich <= f_cch; ich++ ) { f_pPackedString[f_cch - ich] = ((DRM_BYTE*)f_pPackedString)[ f_cch - ich ]; } @@ -124,6 +103,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { CDMi_RESULT SetSecureStopPublisherCert( const DRM_BYTE*, DRM_DWORD ); }; + private: PlayReady (const PlayReady&) = delete; PlayReady& operator= (const PlayReady&) = delete; @@ -137,13 +117,13 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { } public: - PlayReady() : m_poAppContext(nullptr) { } ~PlayReady(void) { - SAFE_OEM_FREE( m_pbPublisherCert ); + if (m_poAppContext) + Drm_Uninitialize(m_poAppContext.get()); } CDMi_RESULT CreateMediaKeySession( @@ -151,22 +131,24 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { int32_t licenseType, const char *f_pwszInitDataType, const uint8_t *f_pbInitData, - uint32_t f_cbInitData, + uint32_t f_cbInitData, const uint8_t *f_pbCDMData, - uint32_t f_cbCDMData, - IMediaKeySession **f_ppiMediaKeySession) { - bool isNetflixPlayready = (strstr(keySystem.c_str(), "netflix") != nullptr); + uint32_t f_cbCDMData, + IMediaKeySession **f_ppiMediaKeySession) { + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); + bool isNetflixPlayready = (strstr(keySystem.c_str(), "netflix") != nullptr); if (isNetflixPlayready) { + // TODO: why is the order different when dealing with netflix? if(!m_isAppCtxInitialized) { InitializeAppCtx(); - } - *f_ppiMediaKeySession = new CDMi::MediaKeySession(f_pbInitData, f_cbInitData, m_poAppContext.get(), !isNetflixPlayready); - } else { - *f_ppiMediaKeySession = new CDMi::MediaKeySession(f_pbInitData, f_cbInitData, f_pbCDMData, f_cbCDMData, m_poAppContext.get(), !isNetflixPlayready); - } - return CDMi_SUCCESS; + } + *f_ppiMediaKeySession = new CDMi::MediaKeySession(f_pbCDMData, f_cbCDMData, f_pbInitData, f_cbInitData, m_poAppContext.get(), !isNetflixPlayready); + } else { + *f_ppiMediaKeySession = new CDMi::MediaKeySession(f_pbInitData, f_cbInitData, f_pbCDMData, f_cbCDMData, m_poAppContext.get(), !isNetflixPlayready); + } + return CDMi_SUCCESS; } CDMi_RESULT SetSecureStopPublisherCert( const DRM_BYTE *f_pbPublisherCert, DRM_DWORD f_cbPublisherCert ) @@ -199,13 +181,13 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { CDMi_RESULT SetServerCertificate( const uint8_t *f_pbServerCertificate, uint32_t f_cbServerCertificate) { - CDMi_RESULT cr = CDMi_SUCCESS; - - if ( CDMi_FAILED( ( cr=SetSecureStopPublisherCert( f_pbServerCertificate, f_cbServerCertificate ) ) ) ) - { - fprintf(stderr, "[%s:%d] SetSecureStopPublisherCert failed",__FUNCTION__,__LINE__); - } - return cr; + // CDMi_RESULT cr = CDMi_SUCCESS; + // if ( CDMi_FAILED( ( cr=SetSecureStopPublisherCert( f_pbServerCertificate, f_cbServerCertificate ) ) ) ) + // { + // fprintf(stderr, "[%s:%d] SetSecureStopPublisherCert failed",__FUNCTION__,__LINE__); + // } + // return cr; + return CDMi_S_FALSE; } virtual CDMi_RESULT Metrics(uint32_t length, const uint8_t* buffer) @@ -214,6 +196,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { } CDMi_RESULT DestroyMediaKeySession(IMediaKeySession *f_piMediaKeySession) { + SafeCriticalSection systemLock(drmAppContextMutex_); MediaKeySession * mediaKeySession = dynamic_cast(f_piMediaKeySession); if ( mediaKeySession != nullptr ) @@ -226,9 +209,11 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { } return CDMi_SUCCESS; } - - uint64_t GetDrmSystemTime() const /* override */ + + uint64_t GetDrmSystemTime() const override { + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); + ocdm_log("%s:%d: PR is asked for system time\n", __FILE__, __LINE__); DRM_RESULT dr = DRM_SUCCESS; DRM_SECURETIME_CLOCK_TYPE eClockType = DRM_SECURETIME_CLOCK_TYPE_INVALID; DRMFILETIME oftSystemTime = { 0 }; @@ -238,10 +223,9 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { dr = Drm_SecureTime_GetValue( ( DRM_APP_CONTEXT* ) m_poAppContext.get(), &oftSystemTime, &eClockType ); - if ( dr != DRM_SUCCESS ) { - fprintf(stderr, "[%s:%d] Drm_SecureTime_GetValue failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + fprintf(stderr, "[%s:%d] Drm_SecureTime_GetValue failed. 0x%X ",__FUNCTION__,__LINE__,dr); } else if ( eClockType == DRM_SECURETIME_CLOCK_TYPE_INVALID ) { @@ -266,7 +250,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { { bool isNetflixPlayready = (strstr(keySystem.c_str(), "netflix") != nullptr); printf("\n [TEL ELXSI] isNetflixPlayready is %d",&isNetflixPlayready); - *session = new CDMi::MediaKeySession(drmHeader, drmHeaderLength, m_poAppContext.get(), !isNetflixPlayready); + // *session = new CDMi::MediaKeySession(drmHeader, drmHeaderLength, m_poAppContext.get(), !isNetflixPlayready); return CDMi_SUCCESS; } @@ -278,7 +262,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { return CDMi_SUCCESS; } - std::string GetVersionExt() const /* override */ + std::string GetVersionExt() const override { const uint32_t MAXLEN = 64; char versionStr[MAXLEN]; @@ -291,27 +275,26 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { return string(versionStr); } - uint32_t GetLdlSessionLimit() const /* override */ + uint32_t GetLdlSessionLimit() const override { return ( uint32_t )DRM_MAX_NONCE_COUNT_PER_SESSION; } - bool IsSecureStopEnabled() /* override */ + bool IsSecureStopEnabled() override { return true; } - CDMi_RESULT EnableSecureStop(bool enable) /* override */ + CDMi_RESULT EnableSecureStop(bool enable) override { return CDMi_SUCCESS; } - uint32_t ResetSecureStops() /* override */ + uint32_t ResetSecureStops() override { return 0; } - /*Return a list of the current SecureStop sessions.*/ CDMi_RESULT GetSecureStopIds(uint8_t ids[], uint16_t idsLength, uint32_t & count) { SafeCriticalSection lock(drmAppContextMutex_); @@ -356,9 +339,8 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { SAFE_OEM_FREE( pidSessions ); return cr; - } + } - /*Generate a SecureStop challenge to send to the server.*/ CDMi_RESULT GetSecureStop( const uint8_t sessionID[], uint32_t sessionIDLength, @@ -401,7 +383,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { if ( err != DRM_SUCCESS ) { f_cbChallenge = 0; - fprintf(stderr, "[%s:%d] Drm_SecureStop_GenerateChallenge failed. 0x%X - %s",__FUNCTION__,__LINE__,(long)err,DRM_ERR_NAME(err)); + fprintf(stderr, "[%s:%d] Drm_SecureStop_GenerateChallenge failed. 0x%X ",__FUNCTION__,__LINE__,(long)err); cr = CDMi_S_FALSE; } else if ( f_cbChallenge < cbChallenge ) @@ -421,7 +403,6 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { return cr; } - /*Process the response from the SecureStop server.*/ CDMi_RESULT CommitSecureStop( const uint8_t f_sessionID[], uint32_t f_sessionIDLength, @@ -461,39 +442,17 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { } else { - fprintf(stderr, "[%s:%d] Drm_SecureStop_ProcessResponse failed. 0x%X - %s",__FUNCTION__,__LINE__,(long)err,DRM_ERR_NAME(err)); + fprintf(stderr, "[%s:%d] Drm_SecureStop_ProcessResponse failed. 0x%X ",__FUNCTION__,__LINE__,(long)err); cr = CDMi_S_FALSE; } SAFE_OEM_FREE( pcchCustomData ); return cr; } - CDMi_RESULT CreateSystemExt() /* override */ - { - if (m_poAppContext.get() != nullptr) { - m_poAppContext.reset(); - } - - std::string rdir(m_readDir); - - drmdir_ = createDrmWchar(rdir); - - g_dstrDrmPath.pwszString = drmdir_; - g_dstrDrmPath.cchString = rdir.length(); - - std::string store(m_storeLocation); - - drmStore_.pwszString = createDrmWchar(store); - drmStore_.cchString = store.length(); - - pbRevocationBuffer_ = new DRM_BYTE[REVOCATION_BUFFER_SIZE]; - - return CDMi_SUCCESS; - } - /*Initialize the PlayReady application context*/ CDMi_RESULT InitializeAppCtx() { + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); DRM_BYTE *appOpaqueBuffer = nullptr; if (m_poAppContext.get() != nullptr) { @@ -504,6 +463,8 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { appOpaqueBuffer = new DRM_BYTE[MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE]; + appContextOpaqueBuffer_ = appOpaqueBuffer; + ::memset(m_poAppContext.get(), 0, sizeof(DRM_APP_CONTEXT)); DRM_RESULT err = Drm_Initialize(m_poAppContext.get(), nullptr, appOpaqueBuffer, @@ -517,8 +478,8 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { &drmStore_ ); if ( err != DRM_SUCCESS ) { - fprintf(stderr, "[%s:%d] Drm_Initialize failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); - int status = remove ("/opt/drm/sample.hds"); + fprintf(stderr, "[%s:%d] Drm_Initialize failed. 0x%X - %s",__FUNCTION__,__LINE__,err,"DRM_ERR_NAME"); + int status = remove(GetDrmStorePath().c_str()); if(status == 0) fprintf(stderr," sample.hds File removal successful"); else @@ -535,7 +496,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { { delete [] appOpaqueBuffer; m_poAppContext.reset(); - fprintf(stderr, "[%s:%d] Drm_Revocation_SetBuffer failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); + fprintf(stderr, "[%s:%d] Drm_Revocation_SetBuffer failed. 0x%X - %s",__FUNCTION__,__LINE__,err,"DRM_ERR_NAME"); return CDMi_S_FALSE; } @@ -543,6 +504,8 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { return CDMi_SUCCESS; } + + /*Unitialize the playready context and opaque buffer*/ CDMi_RESULT UninitializeAppCtx() { @@ -559,7 +522,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { DRM_RESULT err = Drm_GetOpaqueBuffer( m_poAppContext.get(), &pbOldBuf, &cbOldBuf ); if(DRM_FAILED(err)) { - fprintf(stderr, "[%s:%d] Drm_GetOpaqueBuffer failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); + fprintf(stderr, "[%s:%d] Drm_GetOpaqueBuffer failed. 0x%X - %s",__FUNCTION__,__LINE__,err,"DRM_ERR_NAME"); } Drm_Uninitialize(m_poAppContext.get()); @@ -572,39 +535,6 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { return CDMi_SUCCESS; } - CDMi_RESULT InitSystemExt() /* override */ - { - SafeCriticalSection lock(drmAppContextMutex_); - - DRM_BYTE *appOpaqueBuffer = nullptr; - - DRM_RESULT err = CPRDrmPlatform::DrmPlatformInitialize(); - - if(DRM_FAILED(err)) - { - if (m_poAppContext.get() != nullptr) { - m_poAppContext.reset(); - } - fprintf(stderr, "[%s:%d] DrmPlatformInitialize failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); - return CDMi_S_FALSE; - } - - if (CDMi_SUCCESS != InitializeAppCtx()) - { - fprintf(stderr, "[%s:%d] InitializeAppCtx failed.",__FUNCTION__,__LINE__); - return CDMi_S_FALSE; - } - -#ifdef CLEAN_ON_INIT - err = CleanLicenseStore(); - if(DRM_FAILED(err)) - { - fprintf(stderr, "[%s:%d] CleanLicenseStore failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); - } -#endif - return CDMi_SUCCESS; - } - void Deinitialize(const WPEFramework::PluginHost::IShell * shell) { TeardownSystemExt(); @@ -622,7 +552,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { DRM_RESULT err = CleanLicenseStore(); if(DRM_FAILED(err)) { - fprintf(stderr, "[%s:%d] CleanLicenseStore failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); + fprintf(stderr, "[%s:%d] CleanLicenseStore failed. 0x%X - %s",__FUNCTION__,__LINE__,err,"DRM_ERR_NAME"); } if (CDMi_SUCCESS != UninitializeAppCtx() ) @@ -635,10 +565,10 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { delete [] drmdir_; delete [] drmStore_.pwszString; - err = CPRDrmPlatform::DrmPlatformUninitialize(); + // err = CPRDrmPlatform::DrmPlatformUninitialize(); if(DRM_FAILED(err)) { - fprintf(stderr, "[%s:%d] DrmPlatformUninitialize failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); + fprintf(stderr, "[%s:%d] DrmPlatformUninitialize failed. 0x%X - %s",__FUNCTION__,__LINE__,err,"DRM_ERR_NAME"); return CDMi_S_FALSE; } @@ -656,10 +586,10 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { struct stat buf; CDMi_RESULT cr = CDMi_SUCCESS; - if (CDMi_SUCCESS != UninitializeAppCtx() ) - { - fprintf(stderr, "[%s:%d] UninitializeAppCtx failed.",__FUNCTION__,__LINE__); - } + // if (CDMi_SUCCESS != UninitializeAppCtx() ) + // { + // fprintf(stderr, "[%s:%d] UninitializeAppCtx failed.",__FUNCTION__,__LINE__); + // } if (stat(m_storeLocation.c_str(), &buf) != -1) { @@ -694,42 +624,155 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { SafeCriticalSection lock(drmAppContextMutex_); CDMi_RESULT ret = CDMi_SUCCESS; - FILE* const file = fopen(m_storeLocation.c_str(), "rb"); - if (!file) - return CDMi_S_FALSE; - - SHA256_CTX sha256; - SHA256_Init(&sha256); - const int BUFSIZE = 32768; - std::vector buffer(BUFSIZE, 0); - size_t bytesRead = 0; - while ((bytesRead = fread(&buffer[0], 1, BUFSIZE, file))) { - if (!SHA256_Update(&sha256, &buffer[0], bytesRead)) { - ret = CDMi_S_FALSE; - break; + // FILE* const file = fopen(m_storeLocation.c_str(), "rb"); + // if (!file) + // return CDMi_S_FALSE; + + // SHA256_CTX sha256; + // SHA256_Init(&sha256); + // const int BUFSIZE = 32768; + // std::vector buffer(BUFSIZE, 0); + // size_t bytesRead = 0; + // while ((bytesRead = fread(&buffer[0], 1, BUFSIZE, file))) { + // if (!SHA256_Update(&sha256, &buffer[0], bytesRead)) { + // ret = CDMi_S_FALSE; + // break; + // } + // } + // fclose(file); + // SHA256_Final(secureStoreHash, &sha256); + + // return ret; + +#ifdef NETFLIX + if (secureStoreHashLength < 256) + { + ocdm_log("Error: opencdm_get_secure_store_hash needs an array of size 256\n"); + return CDMi_S_FALSE; + } + + DRM_RESULT err = Drm_GetSecureStoreHash(&drmStore_, secureStoreHash); + if (err != DRM_SUCCESS) + { + ocdm_log("Error: Drm_GetSecureStoreHash returned 0x%lX\n", (long)err); + return CDMi_S_FALSE; + } +#endif + + return CDMi_SUCCESS; + + } + + std::string GetDrmStorePath() + { + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); + const uint32_t MAXLEN = 256; + char pathStr[MAXLEN]; + if (drmStore_.cchString >= MAXLEN) + return ""; + DRM_UTL_DemoteUNICODEtoASCII(drmStore_.pwszString, + pathStr, MAXLEN); + ((DRM_BYTE*)pathStr)[drmStore_.cchString] = 0; + PackedCharsToNative(pathStr, drmStore_.cchString + 1); + + return string(pathStr); + } + + CDMi_RESULT InitSystemExt() /* override */ + { + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); + + SafeCriticalSection lock(drmAppContextMutex_); + + DRM_RESULT err = Drm_Platform_Initialize(nullptr); + + if(DRM_FAILED(err)) + { + if (m_poAppContext.get() != nullptr) { + m_poAppContext.reset(); } + fprintf(stderr, "[%s:%d] DrmPlatformInitialize failed. 0x%X - %s",__FUNCTION__,__LINE__,err,"DRM_ERR_NAME"); + return CDMi_S_FALSE; + } + + if (CDMi_SUCCESS != InitializeAppCtx()) + { + fprintf(stderr, "[%s:%d] InitializeAppCtx failed.",__FUNCTION__,__LINE__); + return CDMi_S_FALSE; + } + +#ifdef CLEAN_ON_INIT + err = CleanLicenseStore(); + if(DRM_FAILED(err)) + { + fprintf(stderr, "[%s:%d] CleanLicenseStore failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); } - fclose(file); - SHA256_Final(secureStoreHash, &sha256); +#endif + return CDMi_SUCCESS; + } + + CDMi_RESULT CreateSystemExt() /* override */ + { + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); + if (m_poAppContext.get() != nullptr) { + m_poAppContext.reset(); + } + + std::string rdir(m_readDir); + + drmdir_ = createDrmWchar(rdir); + + g_dstrDrmPath.pwszString = drmdir_; + g_dstrDrmPath.cchString = rdir.length(); + + std::string store(m_storeLocation); + + drmStore_.pwszString = createDrmWchar(store); + drmStore_.cchString = store.length(); + +#ifdef AML_SVP_PR + g_dstrCDMDrmStoreName.pwszString = createDrmWchar(store); + g_dstrCDMDrmStoreName.cchString = store.length(); +#endif + + pbRevocationBuffer_ = new DRM_BYTE[REVOCATION_BUFFER_SIZE]; - return ret; + return CDMi_SUCCESS; } - void OnSystemConfigurationAvailable(const std::string& configline) + + void OnSystemConfigurationAvailable(const WPEFramework::PluginHost::IShell * shell, const std::string& configline) { +#ifdef AML_SVP_PR + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); + string persistentPath = shell->PersistentPath(); + string statePath = persistentPath + "state"; // To store rollback clock state etc + string storePath = persistentPath + "playready/storage"; + m_readDir = persistentPath + "playready"; + m_storeLocation = persistentPath + "playready/storage/drmstore"; + + Core::Directory storeDir(storePath.c_str()); + storeDir.CreatePath(); + Core::Directory stateDir(statePath.c_str()); + stateDir.Create(); +#else + + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); Config config; config.FromString(configline); m_readDir = config.ReadDir.Value(); m_storeLocation = config.StoreLocation.Value(); m_storeLocation = "/opt/drm/sample.hds"; + string statePath = config.HomePath.Value().c_str(); +#endif + fprintf(stderr,"#FASIL# %s: %s: %d\n", statePath.c_str(),storePath.c_str(),__LINE__); + fprintf(stderr,"#FASIL# %s: %s: %d\n", m_readDir.c_str(),m_storeLocation.c_str(),__LINE__); - string homePath = config.HomePath.Value(); - if(!homePath.empty()) { - WPEFramework::Core::SystemInfo::SetEnvironment(_T("HOME"), homePath.c_str()); + if(!statePath.empty()) { + WPEFramework::Core::SystemInfo::SetEnvironment(_T("HOME"), statePath); } else { fprintf(stderr, "[%s:%d] Error: could not set HOME variable. SecureStop functionality may not work!",__FUNCTION__,__LINE__); } - CreateSystemExt(); InitSystemExt(); @@ -737,8 +780,8 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { void Initialize(const WPEFramework::PluginHost::IShell * service, const std::string& configline) { - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); - OnSystemConfigurationAvailable(configline); + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); + OnSystemConfigurationAvailable(service, configline); } private: @@ -746,7 +789,8 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { DRM_CONST_STRING drmStore_; DRM_BYTE *pbRevocationBuffer_ = nullptr; - std::shared_ptr m_poAppContext; + std::unique_ptr m_poAppContext; + DRM_BYTE *appContextOpaqueBuffer_ = nullptr; //AML_ONLY string m_readDir; string m_storeLocation; @@ -762,5 +806,6 @@ static SystemFactoryType g_instance({"video/x-h264", "audio/mpeg"}); CDMi::ISystemFactory* GetSystemFactory() { fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); - return (&CDMi::g_instance); + fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); + return (&CDMi::g_instance); } From 633af2c36758f213099f103e76820e6d944ce59a Mon Sep 17 00:00:00 2001 From: kvfasil Date: Tue, 31 Dec 2024 08:24:05 +0000 Subject: [PATCH 07/37] fix: fixed SafeCriticalSection error. --- MediaSystem.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/MediaSystem.cpp b/MediaSystem.cpp index 590decf..40110fe 100644 --- a/MediaSystem.cpp +++ b/MediaSystem.cpp @@ -41,11 +41,10 @@ using namespace std; using namespace WPEFramework; extern DRM_CONST_STRING g_dstrDrmPath; -using SafeCriticalSection = Core::SafeSyncType; - -Core::CriticalSection drmAppContextMutex_; -DRM_CONST_STRING g_dstrCDMDrmStoreName; +using SafeCriticalSection = WPEFramework::Core::SafeSyncType; +WPEFramework::Core::CriticalSection drmAppContextMutex_; +extern DRM_CONST_STRING g_dstrDrmPath; namespace CDMi { From ef17a29d69dd5b90d27cd7f8f62f3046f3536370 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Tue, 31 Dec 2024 08:25:26 +0000 Subject: [PATCH 08/37] fix: * realigned code. * fixed undefined error code. --- MediaSession.h | 4 +- MediaSystem.cpp | 331 +++++++++++++++++++++++------------------------- 2 files changed, 163 insertions(+), 172 deletions(-) diff --git a/MediaSession.h b/MediaSession.h index 22597a5..afbe022 100644 --- a/MediaSession.h +++ b/MediaSession.h @@ -217,8 +217,8 @@ struct Sec_OpaqueBufferHandle_struct }; typedef struct Sec_OpaqueBufferHandle_struct Sec_OpaqueBufferHandle; -DRM_WCHAR* createDrmWchar(std::string const& s); -void PackedCharsToNative(DRM_CHAR *f_pPackedString, DRM_DWORD f_cch); +// DRM_WCHAR* createDrmWchar(std::string const& s); +// void PackedCharsToNative(DRM_CHAR *f_pPackedString, DRM_DWORD f_cch); std::string GetDrmStorePath(); struct PlayreadyOutProtLevels diff --git a/MediaSystem.cpp b/MediaSystem.cpp index 40110fe..57b9e46 100644 --- a/MediaSystem.cpp +++ b/MediaSystem.cpp @@ -15,20 +15,28 @@ * limitations under the License. */ #include "MediaSession.h" -#include -//#include -#include - - #include #include #include #include +#include +#include +#include -// has its own TRACING mechanism. We do not want to use those, undefine it here to avoid a warning. -// with the TRACE macro of the PLAYREADY software. -#undef TRACE +#ifdef AML_SVP_PR +#include +#else +#include +#endif + +#include +#include +#include + +#define CLEAN_ON_INIT 1 + +#define DEVICESTORE_DIGEST_BYTES_SIZE OEM_SHA256_DIGEST_SIZE_IN_BYTES #define ErrCheckCert() do { \ if ( m_pbPublisherCert == NULL || m_cbPublisherCert == 0 ) { \ @@ -38,17 +46,15 @@ }while( 0 ) using namespace std; -using namespace WPEFramework; + extern DRM_CONST_STRING g_dstrDrmPath; +DRM_CONST_STRING g_dstrCDMDrmStoreName; //AML using SafeCriticalSection = WPEFramework::Core::SafeSyncType; WPEFramework::Core::CriticalSection drmAppContextMutex_; -extern DRM_CONST_STRING g_dstrDrmPath; - -namespace CDMi { -DRM_WCHAR* createDrmWchar(std::string const& s) { +static DRM_WCHAR* createDrmWchar(std::string const& s) { DRM_WCHAR* w = new DRM_WCHAR[s.length() + 1]; for (size_t i = 0; i < s.length(); ++i) w[i] = DRM_ONE_WCHAR(s[i], '\0'); @@ -56,7 +62,7 @@ DRM_WCHAR* createDrmWchar(std::string const& s) { return w; } -void PackedCharsToNative(DRM_CHAR *f_pPackedString, DRM_DWORD f_cch) { +static void PackedCharsToNative(DRM_CHAR *f_pPackedString, DRM_DWORD f_cch) { DRM_DWORD ich = 0; if ( f_pPackedString == nullptr || f_cch == 0 ) @@ -69,6 +75,8 @@ void PackedCharsToNative(DRM_CHAR *f_pPackedString, DRM_DWORD f_cch) { } } +namespace CDMi { + class PlayReady : public IMediaKeys, public IMediaKeysExt { private: class Config : public WPEFramework::Core::JSON::Container { @@ -121,8 +129,12 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { } ~PlayReady(void) { +#ifdef AML_SVP_PR if (m_poAppContext) Drm_Uninitialize(m_poAppContext.get()); +#else + SAFE_OEM_FREE( m_pbPublisherCert ); +#endif } CDMi_RESULT CreateMediaKeySession( @@ -133,8 +145,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { uint32_t f_cbInitData, const uint8_t *f_pbCDMData, uint32_t f_cbCDMData, - IMediaKeySession **f_ppiMediaKeySession) { - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); + IMediaKeySession **f_ppiMediaKeySession) { bool isNetflixPlayready = (strstr(keySystem.c_str(), "netflix") != nullptr); if (isNetflixPlayready) { @@ -142,8 +153,12 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { if(!m_isAppCtxInitialized) { InitializeAppCtx(); - } + } +#ifdef AML_SVP_PR *f_ppiMediaKeySession = new CDMi::MediaKeySession(f_pbCDMData, f_cbCDMData, f_pbInitData, f_cbInitData, m_poAppContext.get(), !isNetflixPlayready); +#else + *f_ppiMediaKeySession = new CDMi::MediaKeySession(f_pbInitData, f_cbInitData, m_poAppContext.get(), !isNetflixPlayready); +#endif } else { *f_ppiMediaKeySession = new CDMi::MediaKeySession(f_pbInitData, f_cbInitData, f_pbCDMData, f_cbCDMData, m_poAppContext.get(), !isNetflixPlayready); } @@ -180,13 +195,12 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { CDMi_RESULT SetServerCertificate( const uint8_t *f_pbServerCertificate, uint32_t f_cbServerCertificate) { - // CDMi_RESULT cr = CDMi_SUCCESS; - // if ( CDMi_FAILED( ( cr=SetSecureStopPublisherCert( f_pbServerCertificate, f_cbServerCertificate ) ) ) ) - // { - // fprintf(stderr, "[%s:%d] SetSecureStopPublisherCert failed",__FUNCTION__,__LINE__); - // } - // return cr; - return CDMi_S_FALSE; + CDMi_RESULT cr = CDMi_SUCCESS; + if ( CDMi_FAILED( ( cr=SetSecureStopPublisherCert( f_pbServerCertificate, f_cbServerCertificate ) ) ) ) + { + fprintf(stderr, "[%s:%d] SetSecureStopPublisherCert failed",__FUNCTION__,__LINE__); + } + return cr; } virtual CDMi_RESULT Metrics(uint32_t length, const uint8_t* buffer) @@ -209,10 +223,9 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { return CDMi_SUCCESS; } - uint64_t GetDrmSystemTime() const override +// uint64_t GetDrmSystemTime() const override + uint64_t GetDrmSystemTime() const /* override */ { - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); - ocdm_log("%s:%d: PR is asked for system time\n", __FILE__, __LINE__); DRM_RESULT dr = DRM_SUCCESS; DRM_SECURETIME_CLOCK_TYPE eClockType = DRM_SECURETIME_CLOCK_TYPE_INVALID; DRMFILETIME oftSystemTime = { 0 }; @@ -224,7 +237,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { &oftSystemTime, &eClockType ); if ( dr != DRM_SUCCESS ) { - fprintf(stderr, "[%s:%d] Drm_SecureTime_GetValue failed. 0x%X ",__FUNCTION__,__LINE__,dr); + fprintf(stderr, "[%s:%d] Drm_SecureTime_GetValue failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); } else if ( eClockType == DRM_SECURETIME_CLOCK_TYPE_INVALID ) { @@ -261,7 +274,8 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { return CDMi_SUCCESS; } - std::string GetVersionExt() const override +// std::string GetVersionExt() const override + std::string GetVersionExt() const /* override */ { const uint32_t MAXLEN = 64; char versionStr[MAXLEN]; @@ -274,22 +288,40 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { return string(versionStr); } - uint32_t GetLdlSessionLimit() const override + std::string GetDrmStorePath() + { + const uint32_t MAXLEN = 256; + char pathStr[MAXLEN]; + if (drmStore_.cchString >= MAXLEN) + return ""; + DRM_UTL_DemoteUNICODEtoASCII(drmStore_.pwszString, + pathStr, MAXLEN); + ((DRM_BYTE*)pathStr)[drmStore_.cchString] = 0; + PackedCharsToNative(pathStr, drmStore_.cchString + 1); + + return string(pathStr); + } + +// uint32_t GetLdlSessionLimit() const override + uint32_t GetLdlSessionLimit() const /* override */ { return ( uint32_t )DRM_MAX_NONCE_COUNT_PER_SESSION; } - bool IsSecureStopEnabled() override +// bool IsSecureStopEnabled() override + bool IsSecureStopEnabled() /* override */ { return true; } - CDMi_RESULT EnableSecureStop(bool enable) override +// CDMi_RESULT EnableSecureStop(bool enable) override + CDMi_RESULT EnableSecureStop(bool enable) /* override */ { return CDMi_SUCCESS; } - uint32_t ResetSecureStops() override +// uint32_t ResetSecureStops() override + uint32_t ResetSecureStops() /* override */ { return 0; } @@ -340,6 +372,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { return cr; } + /*Generate a SecureStop challenge to send to the server.*/ CDMi_RESULT GetSecureStop( const uint8_t sessionID[], uint32_t sessionIDLength, @@ -382,7 +415,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { if ( err != DRM_SUCCESS ) { f_cbChallenge = 0; - fprintf(stderr, "[%s:%d] Drm_SecureStop_GenerateChallenge failed. 0x%X ",__FUNCTION__,__LINE__,(long)err); + fprintf(stderr, "[%s:%d] Drm_SecureStop_GenerateChallenge failed. 0x%X - %s",__FUNCTION__,__LINE__,(long)err,DRM_ERR_NAME(err)); cr = CDMi_S_FALSE; } else if ( f_cbChallenge < cbChallenge ) @@ -402,6 +435,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { return cr; } + /*Process the response from the SecureStop server.*/ CDMi_RESULT CommitSecureStop( const uint8_t f_sessionID[], uint32_t f_sessionIDLength, @@ -441,17 +475,44 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { } else { - fprintf(stderr, "[%s:%d] Drm_SecureStop_ProcessResponse failed. 0x%X ",__FUNCTION__,__LINE__,(long)err); + fprintf(stderr, "[%s:%d] Drm_SecureStop_ProcessResponse failed. 0x%X - %s",__FUNCTION__,__LINE__,(long)err,DRM_ERR_NAME(err)); cr = CDMi_S_FALSE; } SAFE_OEM_FREE( pcchCustomData ); return cr; } + CDMi_RESULT CreateSystemExt() /* override */ + { + if (m_poAppContext.get() != nullptr) { + m_poAppContext.reset(); + } + + std::string rdir(m_readDir); + + drmdir_ = createDrmWchar(rdir); + + g_dstrDrmPath.pwszString = drmdir_; + g_dstrDrmPath.cchString = rdir.length(); + + std::string store(m_storeLocation); + + drmStore_.pwszString = createDrmWchar(store); + drmStore_.cchString = store.length(); + +#ifdef AML_SVP_PR + g_dstrCDMDrmStoreName.pwszString = createDrmWchar(store); + g_dstrCDMDrmStoreName.cchString = store.length(); +#endif + + pbRevocationBuffer_ = new DRM_BYTE[REVOCATION_BUFFER_SIZE]; + + return CDMi_SUCCESS; + } + /*Initialize the PlayReady application context*/ CDMi_RESULT InitializeAppCtx() { - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); DRM_BYTE *appOpaqueBuffer = nullptr; if (m_poAppContext.get() != nullptr) { @@ -477,7 +538,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { &drmStore_ ); if ( err != DRM_SUCCESS ) { - fprintf(stderr, "[%s:%d] Drm_Initialize failed. 0x%X - %s",__FUNCTION__,__LINE__,err,"DRM_ERR_NAME"); + fprintf(stderr, "[%s:%d] Drm_Initialize failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); int status = remove(GetDrmStorePath().c_str()); if(status == 0) fprintf(stderr," sample.hds File removal successful"); @@ -495,7 +556,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { { delete [] appOpaqueBuffer; m_poAppContext.reset(); - fprintf(stderr, "[%s:%d] Drm_Revocation_SetBuffer failed. 0x%X - %s",__FUNCTION__,__LINE__,err,"DRM_ERR_NAME"); + fprintf(stderr, "[%s:%d] Drm_Revocation_SetBuffer failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); return CDMi_S_FALSE; } @@ -503,8 +564,6 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { return CDMi_SUCCESS; } - - /*Unitialize the playready context and opaque buffer*/ CDMi_RESULT UninitializeAppCtx() { @@ -521,7 +580,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { DRM_RESULT err = Drm_GetOpaqueBuffer( m_poAppContext.get(), &pbOldBuf, &cbOldBuf ); if(DRM_FAILED(err)) { - fprintf(stderr, "[%s:%d] Drm_GetOpaqueBuffer failed. 0x%X - %s",__FUNCTION__,__LINE__,err,"DRM_ERR_NAME"); + fprintf(stderr, "[%s:%d] Drm_GetOpaqueBuffer failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); } Drm_Uninitialize(m_poAppContext.get()); @@ -534,6 +593,37 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { return CDMi_SUCCESS; } + CDMi_RESULT InitSystemExt() /* override */ + { + SafeCriticalSection lock(drmAppContextMutex_); + + DRM_RESULT err = Drm_Platform_Initialize(nullptr); + + if(DRM_FAILED(err)) + { + if (m_poAppContext.get() != nullptr) { + m_poAppContext.reset(); + } + fprintf(stderr, "[%s:%d] DrmPlatformInitialize failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); + return CDMi_S_FALSE; + } + + if (CDMi_SUCCESS != InitializeAppCtx()) + { + fprintf(stderr, "[%s:%d] InitializeAppCtx failed.",__FUNCTION__,__LINE__); + return CDMi_S_FALSE; + } + +#ifdef CLEAN_ON_INIT + err = CleanLicenseStore(); + if(DRM_FAILED(err)) + { + fprintf(stderr, "[%s:%d] CleanLicenseStore failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); + } +#endif + return CDMi_SUCCESS; + } + void Deinitialize(const WPEFramework::PluginHost::IShell * shell) { TeardownSystemExt(); @@ -551,7 +641,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { DRM_RESULT err = CleanLicenseStore(); if(DRM_FAILED(err)) { - fprintf(stderr, "[%s:%d] CleanLicenseStore failed. 0x%X - %s",__FUNCTION__,__LINE__,err,"DRM_ERR_NAME"); + fprintf(stderr, "[%s:%d] CleanLicenseStore failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); } if (CDMi_SUCCESS != UninitializeAppCtx() ) @@ -564,10 +654,10 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { delete [] drmdir_; delete [] drmStore_.pwszString; - // err = CPRDrmPlatform::DrmPlatformUninitialize(); + err = CPRDrmPlatform::DrmPlatformUninitialize(); if(DRM_FAILED(err)) { - fprintf(stderr, "[%s:%d] DrmPlatformUninitialize failed. 0x%X - %s",__FUNCTION__,__LINE__,err,"DRM_ERR_NAME"); + fprintf(stderr, "[%s:%d] DrmPlatformUninitialize failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); return CDMi_S_FALSE; } @@ -585,10 +675,10 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { struct stat buf; CDMi_RESULT cr = CDMi_SUCCESS; - // if (CDMi_SUCCESS != UninitializeAppCtx() ) - // { - // fprintf(stderr, "[%s:%d] UninitializeAppCtx failed.",__FUNCTION__,__LINE__); - // } + if (CDMi_SUCCESS != UninitializeAppCtx() ) + { + fprintf(stderr, "[%s:%d] UninitializeAppCtx failed.",__FUNCTION__,__LINE__); + } if (stat(m_storeLocation.c_str(), &buf) != -1) { @@ -623,140 +713,42 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { SafeCriticalSection lock(drmAppContextMutex_); CDMi_RESULT ret = CDMi_SUCCESS; - // FILE* const file = fopen(m_storeLocation.c_str(), "rb"); - // if (!file) - // return CDMi_S_FALSE; - - // SHA256_CTX sha256; - // SHA256_Init(&sha256); - // const int BUFSIZE = 32768; - // std::vector buffer(BUFSIZE, 0); - // size_t bytesRead = 0; - // while ((bytesRead = fread(&buffer[0], 1, BUFSIZE, file))) { - // if (!SHA256_Update(&sha256, &buffer[0], bytesRead)) { - // ret = CDMi_S_FALSE; - // break; - // } - // } - // fclose(file); - // SHA256_Final(secureStoreHash, &sha256); - - // return ret; - -#ifdef NETFLIX - if (secureStoreHashLength < 256) - { - ocdm_log("Error: opencdm_get_secure_store_hash needs an array of size 256\n"); - return CDMi_S_FALSE; - } - - DRM_RESULT err = Drm_GetSecureStoreHash(&drmStore_, secureStoreHash); - if (err != DRM_SUCCESS) - { - ocdm_log("Error: Drm_GetSecureStoreHash returned 0x%lX\n", (long)err); - return CDMi_S_FALSE; - } -#endif - - return CDMi_SUCCESS; - - } - - std::string GetDrmStorePath() - { - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); - const uint32_t MAXLEN = 256; - char pathStr[MAXLEN]; - if (drmStore_.cchString >= MAXLEN) - return ""; - DRM_UTL_DemoteUNICODEtoASCII(drmStore_.pwszString, - pathStr, MAXLEN); - ((DRM_BYTE*)pathStr)[drmStore_.cchString] = 0; - PackedCharsToNative(pathStr, drmStore_.cchString + 1); - - return string(pathStr); - } - - CDMi_RESULT InitSystemExt() /* override */ - { - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); - - SafeCriticalSection lock(drmAppContextMutex_); - - DRM_RESULT err = Drm_Platform_Initialize(nullptr); - - if(DRM_FAILED(err)) - { - if (m_poAppContext.get() != nullptr) { - m_poAppContext.reset(); + FILE* const file = fopen(m_storeLocation.c_str(), "rb"); + if (!file) + return CDMi_S_FALSE; + + SHA256_CTX sha256; + SHA256_Init(&sha256); + const int BUFSIZE = 32768; + std::vector buffer(BUFSIZE, 0); + size_t bytesRead = 0; + while ((bytesRead = fread(&buffer[0], 1, BUFSIZE, file))) { + if (!SHA256_Update(&sha256, &buffer[0], bytesRead)) { + ret = CDMi_S_FALSE; + break; } - fprintf(stderr, "[%s:%d] DrmPlatformInitialize failed. 0x%X - %s",__FUNCTION__,__LINE__,err,"DRM_ERR_NAME"); - return CDMi_S_FALSE; - } - - if (CDMi_SUCCESS != InitializeAppCtx()) - { - fprintf(stderr, "[%s:%d] InitializeAppCtx failed.",__FUNCTION__,__LINE__); - return CDMi_S_FALSE; - } - -#ifdef CLEAN_ON_INIT - err = CleanLicenseStore(); - if(DRM_FAILED(err)) - { - fprintf(stderr, "[%s:%d] CleanLicenseStore failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); - } -#endif - return CDMi_SUCCESS; - } - - CDMi_RESULT CreateSystemExt() /* override */ - { - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); - if (m_poAppContext.get() != nullptr) { - m_poAppContext.reset(); } + fclose(file); + SHA256_Final(secureStoreHash, &sha256); - std::string rdir(m_readDir); - - drmdir_ = createDrmWchar(rdir); - - g_dstrDrmPath.pwszString = drmdir_; - g_dstrDrmPath.cchString = rdir.length(); - - std::string store(m_storeLocation); - - drmStore_.pwszString = createDrmWchar(store); - drmStore_.cchString = store.length(); - -#ifdef AML_SVP_PR - g_dstrCDMDrmStoreName.pwszString = createDrmWchar(store); - g_dstrCDMDrmStoreName.cchString = store.length(); -#endif - - pbRevocationBuffer_ = new DRM_BYTE[REVOCATION_BUFFER_SIZE]; - - return CDMi_SUCCESS; + return ret; } - - + void OnSystemConfigurationAvailable(const WPEFramework::PluginHost::IShell * shell, const std::string& configline) { #ifdef AML_SVP_PR - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); string persistentPath = shell->PersistentPath(); string statePath = persistentPath + "state"; // To store rollback clock state etc string storePath = persistentPath + "playready/storage"; m_readDir = persistentPath + "playready"; m_storeLocation = persistentPath + "playready/storage/drmstore"; - Core::Directory storeDir(storePath.c_str()); + WPEFramework::Core::Directory storeDir(storePath.c_str()); storeDir.CreatePath(); - Core::Directory stateDir(statePath.c_str()); + WPEFramework::Core::Directory stateDir(statePath.c_str()); stateDir.Create(); #else - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); Config config; config.FromString(configline); m_readDir = config.ReadDir.Value(); @@ -764,8 +756,8 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { m_storeLocation = "/opt/drm/sample.hds"; string statePath = config.HomePath.Value().c_str(); #endif - fprintf(stderr,"#FASIL# %s: %s: %d\n", statePath.c_str(),storePath.c_str(),__LINE__); - fprintf(stderr,"#FASIL# %s: %s: %d\n", m_readDir.c_str(),m_storeLocation.c_str(),__LINE__); + fprintf(stderr,"#COMMON-OCDM# %s: %s: %d\n", statePath.c_str(),storePath.c_str(),__LINE__); + fprintf(stderr,"#COMMON-OCDM# %s: %s: %d\n", m_readDir.c_str(),m_storeLocation.c_str(),__LINE__); if(!statePath.empty()) { WPEFramework::Core::SystemInfo::SetEnvironment(_T("HOME"), statePath); @@ -779,7 +771,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { void Initialize(const WPEFramework::PluginHost::IShell * service, const std::string& configline) { - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); + fprintf(stderr,"#COMMON-OCDM# : %s: %d\n",__func__,__LINE__); OnSystemConfigurationAvailable(service, configline); } @@ -804,7 +796,6 @@ static SystemFactoryType g_instance({"video/x-h264", "audio/mpeg"}); } // namespace CDMi CDMi::ISystemFactory* GetSystemFactory() { - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); + fprintf(stderr,"#COMMON-OCDM# : %s: %d\n",__func__,__LINE__); return (&CDMi::g_instance); } From 18e506f17dc3fe8eb38412a96a68853acec6ec64 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Tue, 31 Dec 2024 09:49:39 +0000 Subject: [PATCH 09/37] update: updated MediaSessionExt.cpp and removed unused code. --- MediaSessionExt.cpp | 396 ++++++++++++++++++-------------------------- 1 file changed, 159 insertions(+), 237 deletions(-) diff --git a/MediaSessionExt.cpp b/MediaSessionExt.cpp index 2247376..12961ce 100644 --- a/MediaSessionExt.cpp +++ b/MediaSessionExt.cpp @@ -1,34 +1,18 @@ -/* - * If not stated otherwise in this file or this component's LICENSE file the - * following copyright and licenses apply: - * - * Copyright 2020 RDK Management - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - #include "MediaSession.h" #include #include #include +#ifdef USE_SVP +#include "gst_svp_meta.h" +#endif + using namespace std; #include -using namespace WPEFramework; -using SafeCriticalSection = Core::SafeSyncType; -extern Core::CriticalSection drmAppContextMutex_; +using SafeCriticalSection = WPEFramework::Core::SafeSyncType; +extern WPEFramework::Core::CriticalSection drmAppContextMutex_; const DRM_WCHAR PLAY[] = { ONE_WCHAR('P', '\0'), ONE_WCHAR('l', '\0'), @@ -45,20 +29,110 @@ namespace CDMi { std::map mBindMap; static const DRM_CONST_STRING* RIGHTS[] = { &PLAY_RIGHT }; +/* +MediaKeySession::MediaKeySession(const uint8_t drmHeader[], uint32_t drmHeaderLength, DRM_APP_CONTEXT * poAppContext, bool initiateChallengeGeneration = false ) + : m_pbRevocationBuffer(nullptr) + , m_eKeyState(KEY_CLOSED) + , m_pbChallenge(nullptr) + , m_cbChallenge(0) + , m_pchSilentURL(nullptr) + , m_piCallback(nullptr) + , mSessionId(0) + , mInitiateChallengeGeneration(initiateChallengeGeneration) + , m_cHeaderKIDs(0) + , m_pdstrHeaderKIDs( nullptr ) + , m_eHeaderVersion( DRM_HEADER_VERSION_UNKNOWN ) + , m_oBatchID( DRM_ID_EMPTY ) + , m_currentDecryptContext( nullptr ) +#ifdef USE_SVP + , m_pSVPContext(nullptr) + , m_rpcID(0) +#endif + , m_fCommit(false) + , m_poAppContext(poAppContext) + , m_decryptInited(false) + , m_bDRMInitializedLocally(false) +{ +#ifdef USE_SVP + gst_svp_ext_get_context(&m_pSVPContext, Client, m_rpcID); +#endif + + mDrmHeader.resize(drmHeaderLength); + memcpy(&mDrmHeader[0], drmHeader, drmHeaderLength); + + m_eKeyState = KEY_INIT; +} +*/ + uint32_t MediaKeySession::GetSessionIdExt() const { - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); return mSessionId; } CDMi_RESULT MediaKeySession::SetDrmHeader(const uint8_t drmHeader[], uint32_t drmHeaderLength) { - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); mDrmHeader.resize(drmHeaderLength); memcpy(&mDrmHeader[0], drmHeader, drmHeaderLength); return CDMi_SUCCESS; } +CDMi_RESULT MediaKeySession::BindKeyNow(DECRYPT_CONTEXT decryptContext) +{ + + DRM_VOID * pvData = nullptr; + DRMPFNPOLICYCALLBACK pfnOPLCallback = nullptr; + DECRYPT_CONTEXT tmpDecryptContext; + DRM_RESULT dr; + + if ( CDMi_SUCCESS != SetKeyIdProperty( decryptContext->keyId ) ) + { + return CDMi_S_FALSE; + } + + dr = ReaderBind( + RIGHTS, + sizeof(RIGHTS) / sizeof(DRM_CONST_STRING*), + _PolicyCallback, + pvData, + &(decryptContext->oDrmDecryptContext) ); + + if ( DRM_FAILED( dr ) ){ + fprintf(stderr, "[%s:%d] ReaderBind failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + return CDMi_S_FALSE; + } else { + dr = Drm_Reader_Commit(m_poAppContext, _PolicyCallback, pvData); + if (DRM_FAILED(dr)) + { + fprintf(stderr, "[%s:%d] Drm_Reader_Commit failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + return CDMi_S_FALSE; + } + } + if ( nullptr == ( tmpDecryptContext = GetDecryptCtx( decryptContext->keyId ) ) ){ + // m_DecryptContextVector.push_back(decryptContext); + } + return CDMi_SUCCESS; +} + +CDMi_RESULT MediaKeySession::BindKey(KeyId keyId) +{ + DECRYPT_CONTEXT decryptContext; + decryptContext = NEW_DECRYPT_CONTEXT(); + decryptContext->keyId = keyId; + + auto it = mBindMap.find(keyId); + if (it != mBindMap.end()) + { + it->second = decryptContext; + return CDMi_SUCCESS; + } + else + { + BindKeyNow(decryptContext); + mBindMap.insert(std::make_pair(decryptContext->keyId, std::shared_ptr<__DECRYPT_CONTEXT>())); + } + return CDMi_SUCCESS; +} + CDMi_RESULT MediaKeySession::StoreLicenseData(const uint8_t f_rgbLicenseData[], uint32_t f_cbLicenseDataSize, uint8_t * f_pSecureStopId) { DRM_RESULT err = DRM_SUCCESS; @@ -143,6 +217,66 @@ CDMi_RESULT MediaKeySession::StoreLicenseData(const uint8_t f_rgbLicenseData[], return CDMi_SUCCESS; } +CDMi_RESULT MediaKeySession::SelectKeyId( const uint8_t f_keyLength, const uint8_t f_keyId[] ) +{ + SafeCriticalSection systemLock(drmAppContextMutex_); + DRM_RESULT err; + DRMPFNPOLICYCALLBACK pfnOPLCallback = nullptr; + DRM_VOID * pvData = nullptr; + + pfnOPLCallback = _PolicyCallback; + + if ( f_keyId == nullptr || f_keyLength != DRM_ID_SIZE ) + { + fprintf(stderr, "[%s:%d] Bad value for keyId arg ",__FUNCTION__,__LINE__); + return CDMi_S_FALSE; + } + + KeyId keyId(&f_keyId[0],KeyId::KEYID_ORDER_UUID_BE); + std::string keyIdHex(keyId.HexStr()); + + if ( nullptr != ( m_currentDecryptContext = GetDecryptCtx( keyId ) ) ){ + return CDMi_SUCCESS; + } + + if ( CDMi_SUCCESS != SetKeyIdProperty( keyId ) ) + { + fprintf(stderr, "[%s:%d] SetKeyIdProperty failed",__FUNCTION__,__LINE__); + return CDMi_S_FALSE; + } + + CDMi_RESULT result = CDMi_SUCCESS; + + DECRYPT_CONTEXT decryptContext = NEW_DECRYPT_CONTEXT(); + err = ReaderBind( + RIGHTS, + sizeof(RIGHTS) / sizeof(DRM_CONST_STRING*), + pfnOPLCallback, + pvData, + &(decryptContext->oDrmDecryptContext ) ); + + if (DRM_FAILED(err)) + { + fprintf(stderr, "[%s:%d] ReaderBind failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); + result = CDMi_S_FALSE; + } else { + err = Drm_Reader_Commit(m_poAppContext, pfnOPLCallback, pvData); + if (DRM_FAILED(err)) + { + fprintf(stderr, "[%s:%d] Drm_Reader_Commit failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); + result = CDMi_S_FALSE; + } + } + if (result == CDMi_SUCCESS) { + m_fCommit = TRUE; + m_decryptInited = true; + decryptContext->keyId = keyId; + // m_DecryptContextVector.push_back(decryptContext); + m_currentDecryptContext = decryptContext; + } + return result; +} + CDMi_RESULT MediaKeySession::GetChallengeDataExt(uint8_t * f_pChallenge, uint32_t & f_ChallengeSize, uint32_t f_isLDL) { DRM_RESULT err; @@ -265,216 +399,4 @@ CDMi_RESULT MediaKeySession::CleanDecryptContext() m_decryptInited = false; return CDMi_SUCCESS; } - - - - - - - -CDMi_RESULT MediaKeySession::SetKeyId(DRM_APP_CONTEXT *pDrmAppCtx, const uint8_t keyLength, const uint8_t keyId[]){ - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); - return CDMi_SUCCESS; -} - - -CDMi_RESULT MediaKeySession::BindKeyNow(DECRYPT_CONTEXT decryptContext) -{ - - DRM_VOID * pvData = nullptr; - DRMPFNPOLICYCALLBACK pfnOPLCallback = nullptr; - DECRYPT_CONTEXT tmpDecryptContext; - DRM_RESULT dr; - - if ( CDMi_SUCCESS != SetKeyIdProperty( decryptContext->keyId ) ) - { - return CDMi_S_FALSE; - } - - dr = ReaderBind( - RIGHTS, - sizeof(RIGHTS) / sizeof(DRM_CONST_STRING*), - _PolicyCallback, - pvData, - &(decryptContext->oDrmDecryptContext) ); - - if ( DRM_FAILED( dr ) ){ - fprintf(stderr, "[%s:%d] ReaderBind failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); - return CDMi_S_FALSE; - } else { - dr = Drm_Reader_Commit(m_poAppContext, _PolicyCallback, pvData); - if (DRM_FAILED(dr)) - { - fprintf(stderr, "[%s:%d] Drm_Reader_Commit failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); - return CDMi_S_FALSE; - } - } - if ( nullptr == ( tmpDecryptContext = GetDecryptCtx( decryptContext->keyId ) ) ){ - // m_DecryptContextVector.push_back(decryptContext); - } - return CDMi_SUCCESS; -} - -CDMi_RESULT MediaKeySession::BindKey(KeyId keyId) -{ - DECRYPT_CONTEXT decryptContext; - decryptContext = NEW_DECRYPT_CONTEXT(); - decryptContext->keyId = keyId; - - auto it = mBindMap.find(keyId); - if (it != mBindMap.end()) - { - it->second = decryptContext; - return CDMi_SUCCESS; - } - else - { - BindKeyNow(decryptContext); - mBindMap.insert(std::make_pair(decryptContext->keyId, std::shared_ptr<__DECRYPT_CONTEXT>())); - } - return CDMi_SUCCESS; -} - - - -CDMi_RESULT MediaKeySession::SelectKeyId( const uint8_t f_keyLength, const uint8_t f_keyId[] ) -{ - SafeCriticalSection systemLock(drmAppContextMutex_); - DRM_RESULT err; - DRMPFNPOLICYCALLBACK pfnOPLCallback = nullptr; - DRM_VOID * pvData = nullptr; - - pfnOPLCallback = _PolicyCallback; - - if ( f_keyId == nullptr || f_keyLength != DRM_ID_SIZE ) - { - fprintf(stderr, "[%s:%d] Bad value for keyId arg ",__FUNCTION__,__LINE__); - return CDMi_S_FALSE; - } - - KeyId keyId(&f_keyId[0],KeyId::KEYID_ORDER_UUID_BE); - std::string keyIdHex(keyId.HexStr()); - - if ( nullptr != ( m_currentDecryptContext = GetDecryptCtx( keyId ) ) ){ - return CDMi_SUCCESS; - } - - if ( CDMi_SUCCESS != SetKeyIdProperty( keyId ) ) - { - fprintf(stderr, "[%s:%d] SetKeyIdProperty failed",__FUNCTION__,__LINE__); - return CDMi_S_FALSE; - } - - CDMi_RESULT result = CDMi_SUCCESS; - - DECRYPT_CONTEXT decryptContext = NEW_DECRYPT_CONTEXT(); - err = ReaderBind( - RIGHTS, - sizeof(RIGHTS) / sizeof(DRM_CONST_STRING*), - pfnOPLCallback, - pvData, - &(decryptContext->oDrmDecryptContext ) ); - - if (DRM_FAILED(err)) - { - fprintf(stderr, "[%s:%d] ReaderBind failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); - result = CDMi_S_FALSE; - } else { - err = Drm_Reader_Commit(m_poAppContext, pfnOPLCallback, pvData); - if (DRM_FAILED(err)) - { - fprintf(stderr, "[%s:%d] Drm_Reader_Commit failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); - result = CDMi_S_FALSE; - } - } - if (result == CDMi_SUCCESS) { - m_fCommit = TRUE; - m_decryptInited = true; - decryptContext->keyId = keyId; - // m_DecryptContextVector.push_back(decryptContext); - m_currentDecryptContext = decryptContext; - } - return result; -} - -CDMi_RESULT MediaKeySession::SelectDrmHeader(DRM_APP_CONTEXT *pDrmAppCtx, - const uint32_t headerLength, const uint8_t header[]) -{ - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); - // Make the current app context contain the DRM header for this session. - ocdm_log("Drm_Content_SetProperty DRM_CSP_AUTODETECT_HEADER\n"); - - return CDMi_SUCCESS; -} - -CDMi_RESULT MediaKeySession::SetOutputMode(DRM_APP_CONTEXT *pDrmAppCtx, DRM_DWORD dwDecryptionMode) -{ - - return CDMi_SUCCESS; - -} - -struct CallbackInfo -{ - IMediaKeySessionCallback * _callback; - uint16_t _compressedVideo; - uint16_t _uncompressedVideo; - uint16_t _analogVideo; - uint16_t _compressedAudio; - uint16_t _uncompressedAudio; -}; - -static void * PlayLevelUpdateCallback(void * data) -{ - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); - CallbackInfo * callbackInfo = static_cast(data); - - stringstream keyMessage; - keyMessage << "{"; - keyMessage << "\"compressed-video\": " << callbackInfo->_compressedVideo << ","; - keyMessage << "\"uncompressed-video\": " << callbackInfo->_uncompressedVideo << ","; - keyMessage << "\"analog-video\": " << callbackInfo->_analogVideo << ","; - keyMessage << "\"compressed-audio\": " << callbackInfo->_compressedAudio << ","; - keyMessage << "\"uncompressed-audio\": " << callbackInfo->_uncompressedAudio; - keyMessage << "}"; - - string keyMessageStr = keyMessage.str(); - const uint8_t * messageBytes = reinterpret_cast(keyMessageStr.c_str()); - - char urlBuffer[64]; - strcpy(urlBuffer, "properties"); - callbackInfo->_callback->OnKeyMessage(messageBytes, keyMessageStr.length() + 1, urlBuffer); - - delete callbackInfo; - return nullptr; -} - -static DRM_RESULT opencdm_output_levels_callback(const DRM_VOID *outputLevels, DRM_POLICY_CALLBACK_TYPE callbackType, const DRM_VOID *data) { - fprintf(stderr,"#FASIL# %s: %s: %d\n", __FILE__,__func__,__LINE__); - // We only care about the play callback. - if (callbackType != DRM_PLAY_OPL_CALLBACK) - return DRM_SUCCESS; - return DRM_SUCCESS; - const IMediaKeySessionCallback * constSessionCallback = reinterpret_cast(data); - if (constSessionCallback != nullptr) { - CallbackInfo * callbackInfo = new CallbackInfo; - callbackInfo->_callback = const_cast(constSessionCallback); - - // Pull out the protection levels. - const DRM_PLAY_OPL_EX2* playLevels = static_cast(outputLevels); - callbackInfo->_compressedVideo = playLevels->minOPL.wCompressedDigitalVideo; - callbackInfo->_uncompressedVideo = playLevels->minOPL.wUncompressedDigitalVideo; - callbackInfo->_analogVideo = playLevels->minOPL.wAnalogVideo; - callbackInfo->_compressedAudio = playLevels->minOPL.wCompressedDigitalAudio; - callbackInfo->_uncompressedAudio = playLevels->minOPL.wUncompressedDigitalAudio; - - // Run on a new thread, so we don't go too deep in the IPC callstack. - pthread_t threadId; - pthread_create(&threadId, nullptr, PlayLevelUpdateCallback, callbackInfo); - - } - // All done. - return DRM_SUCCESS; -} - -} +} \ No newline at end of file From f3eb8f68ac0b359db3efb15b1737cabf78d9a58c Mon Sep 17 00:00:00 2001 From: kvfasil Date: Tue, 31 Dec 2024 17:13:12 +0000 Subject: [PATCH 10/37] fix: modifiying MediaKeySession(),inherit PlayreadySession(). --- MediaSession.cpp | 150 ++++++++++++++++++++++++++++++++++++++++++----- MediaSession.h | 2 +- 2 files changed, 137 insertions(+), 15 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index 7106325..418de80 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -23,14 +23,19 @@ #include #include #include -//#include +#include + +#ifdef USE_SVP #include "gst_svp_meta.h" +#endif using namespace WPEFramework; using SafeCriticalSection = Core::SafeSyncType; MODULE_NAME_DECLARATION(BUILD_REFERENCE); extern Core::CriticalSection drmAppContextMutex_; +WPEFramework::Core::CriticalSection prSessionMutex_; + extern DRM_CONST_STRING g_dstrCDMDrmStoreName; #define NYI_KEYSYSTEM "keysystem-placeholder" @@ -178,6 +183,99 @@ bool parsePlayreadyInitializationData(const std::string& initData, std::string* return false; } +PlayreadySession::PlayreadySession() + : m_poAppContext(nullptr) + , m_pbPROpaqueBuf(nullptr) + , m_cbPROpaqueBuf(0) + , m_bInitCalled(false) +{ + void *pPlatformInitData = NULL; + // // void svpGetDrmPlatformInitData( void ** ppPlatformInitData) + // // svpGetDrmPlatformInitData( &pPlatformInitData); + + //TODO + // if ( DRM_FAILED( CPRDrmPlatform::DrmPlatformInitialize( pPlatformInitData ) ) ) + // { + // fprintf(stderr, "[%s:%d] DrmPlatformInitialize failed.",__FUNCTION__,__LINE__); + // } +} + +PlayreadySession::~PlayreadySession() +{ + SafeCriticalSection systemLock(prSessionMutex_); + + if ( IsPlayreadySessionInit() ) + { + SAFE_OEM_FREE(m_pbPROpaqueBuf); + m_cbPROpaqueBuf = 0; + + if (m_poAppContext != nullptr) + { + Drm_Uninitialize(m_poAppContext); + SAFE_OEM_FREE(m_poAppContext); + m_poAppContext = nullptr; + } + } + + // TODO + // if (DRM_FAILED(CPRDrmPlatform::DrmPlatformUninitialize())) + // { + // fprintf(stderr, "[%s:%d] DrmPlatformUninitialize failed.",__FUNCTION__,__LINE__); + // } +} + +DRM_APP_CONTEXT * PlayreadySession::InitializeDRM(const DRM_CONST_STRING * pDRMStoreName) +{ + DRM_RESULT dr = DRM_SUCCESS; + DRM_VOID *pdrmOemContext = nullptr; + + SafeCriticalSection systemLock(prSessionMutex_); + + m_bInitCalled = true; + + if (m_poAppContext == nullptr) + { + + +// ChkMem( m_pbOpaqueBuffer = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE)); //aml + ChkMem( m_pbPROpaqueBuf = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE) ); + ZEROMEM(m_pbPROpaqueBuf, MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE); +// m_cbOpaqueBuffer = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; //aml + m_cbPROpaqueBuf = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; + +// ChkMem( m_poAppContext = (DRM_APP_CONTEXT *)Oem_MemAlloc(SIZEOF(DRM_APP_CONTEXT))); //aml + ChkMem( m_poAppContext = (DRM_APP_CONTEXT * )Oem_MemAlloc( sizeof(DRM_APP_CONTEXT) ) ); + ZEROMEM( m_poAppContext, sizeof(DRM_APP_CONTEXT) ); + + /* pdrmOemContext this should be valid for BRCM , others it could be null */ + // svpGetDrmOEMContext(&pdrmOemContext); + // Initialize DRM app context. +// dr = Drm_Initialize(m_poAppContext, nullptr, m_pbOpaqueBuffer, m_cbOpaqueBuffer, &g_dstrCDMDrmStoreName); //aml + dr = Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName); + if (dr != DRM_SUCCESS) + { + ChkDR(Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName)); + } + } + else + { + DRM_RESULT err = Drm_Reinitialize(m_poAppContext); + if (DRM_FAILED(err)) + { + fprintf(stderr, "[%s:%d] Drm_Reinitialize failed. 0x%lX - %s",__FUNCTION__,__LINE__,(long )err,DRM_ERR_NAME(err)); + } + } + + return m_poAppContext; + +ErrorExit: + if (DRM_FAILED(dr)) { + fprintf(stderr, "[%s:%d] failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + } + return nullptr; +} + + MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitData, const uint8_t *f_pbCDMData, uint32_t f_cbCDMData, DRM_APP_CONTEXT * poAppContext, bool initiateChallengeGeneration /* = false */) : m_pbOpaqueBuffer(nullptr) , m_cbOpaqueBuffer(0) @@ -198,13 +296,20 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD , m_pSVPContext(NULL) , m_rpcID(0) { - memset(&levels_, 0, sizeof(levels_)); + memset(&levels_, 0, sizeof(levels_)); //need to comment later. + DRM_RESULT dr = DRM_SUCCESS; + DRM_ID oSessionID; + DRM_CONST_STRING dstrWRMHEADER = DRM_EMPTY_DRM_STRING; + + DRM_DWORD cchEncodedSessionID = SIZEOF(m_rgchSessionID); + ocdm_log("Initializing SVP context for client side\n"); gst_svp_ext_get_context(&m_pSVPContext, Client, m_rpcID); if (!initiateChallengeGeneration) { + fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); mLicenseResponse = std::unique_ptr(new LicenseResponse()); mSecureStopId.clear(); @@ -213,25 +318,30 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD memcpy(&mDrmHeader[0], f_pbCDMData, f_cbCDMData); m_secCount++; } else { + fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); m_oDecryptContext = new DRM_DECRYPT_CONTEXT; memset(m_oDecryptContext, 0, sizeof(DRM_DECRYPT_CONTEXT)); m_oDecryptContext2 = new DRM_DECRYPT_CONTEXT; memset(m_oDecryptContext2, 0, sizeof(DRM_DECRYPT_CONTEXT)); - DRM_ID oSessionID; - - DRM_DWORD cchEncodedSessionID = SIZEOF(m_rgchSessionID); - // FIXME: Change the interface of this method? Not sure why the win32 bondage is still so popular. std::string initData(reinterpret_cast(f_pbInitData), f_cbInitData); std::string playreadyInitData; +// ChkBOOL(m_eKeyState == KEY_CLOSED, DRM_E_INVALIDARG); + + // mMaxResDecodePixels = 0; + // mMaxResDecodeSet = false; + +////////////////////////////////////////////////////////////////////////////////////////////// ocdm_log("Constructing PlayReady Session [%p]\n", this); - ChkMem(m_pbOpaqueBuffer = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE)); - m_cbOpaqueBuffer = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; + ChkMem(m_pbOpaqueBuffer = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE)); //aml + m_cbOpaqueBuffer = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; //aml + #ifndef REUSE_APPCONTEXT - ChkMem(m_poAppContext = (DRM_APP_CONTEXT *)Oem_MemAlloc(SIZEOF(DRM_APP_CONTEXT))); + fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); + ChkMem(m_poAppContext = (DRM_APP_CONTEXT *)Oem_MemAlloc(SIZEOF(DRM_APP_CONTEXT))); //aml // Initialize DRM app context. dr = Drm_Initialize(m_poAppContext, @@ -254,6 +364,12 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD &g_dstrCDMDrmStoreName); } ChkDR(dr); +///////////////////////////////////////////////////////////////////////////////////////// + + // if (m_poAppContext == nullptr) { + // m_poAppContext = InitializeDRM(&g_dstrCDMDrmStoreName); + // } + if (DRM_REVOCATION_IsRevocationSupported()) { ChkMem(m_pbRevocationBuffer = (DRM_BYTE *)Oem_MemAlloc(REVOCATION_BUFFER_SIZE)); @@ -263,11 +379,6 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD } #endif -#ifdef PR_4_4 - //temporary hack to allow time based licenses - ( DRM_REINTERPRET_CAST( DRM_APP_CONTEXT_INTERNAL, m_poAppContext ) )->fClockSet = TRUE; -#endif - // Generate a random media session ID. ChkDR(Oem_Random_GetBytes(nullptr, (DRM_BYTE *)&oSessionID, SIZEOF(oSessionID))); ZEROMEM(m_rgchSessionID, SIZEOF(m_rgchSessionID)); @@ -285,11 +396,20 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD if (!parsePlayreadyInitializationData(initData, &playreadyInitData)) { playreadyInitData = initData; } + + ChkDR(Drm_Content_SetProperty(m_poAppContext, DRM_CSP_AUTODETECT_HEADER, reinterpret_cast(playreadyInitData.data()), playreadyInitData.size())); + + +#ifdef PR_4_4 + //temporary hack to allow time based licenses + ( DRM_REINTERPRET_CAST( DRM_APP_CONTEXT_INTERNAL, m_poAppContext ) )->fClockSet = TRUE; +#endif + // The current state MUST be KEY_INIT otherwise error out. ChkBOOL(m_eKeyState == KEY_INIT, DRM_E_INVALIDARG); m_secCount++; @@ -304,6 +424,8 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD } } + + MediaKeySession::~MediaKeySession(void) { gst_svp_ext_free_context(m_pSVPContext); Close(); diff --git a/MediaSession.h b/MediaSession.h index afbe022..247ee80 100644 --- a/MediaSession.h +++ b/MediaSession.h @@ -265,7 +265,7 @@ class PlayreadySession bool m_bInitCalled; }; -class MediaKeySession : public IMediaKeySession, public IMediaKeySessionExt { +class MediaKeySession : public PlayreadySession, public IMediaKeySession, public IMediaKeySessionExt { private: enum KeyState { // Has been initialized. From e7257780b87ba33d386f5cd6780f89af41584ef1 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Tue, 31 Dec 2024 18:15:30 +0000 Subject: [PATCH 11/37] feat: implementing InitializeDRM(). --- MediaSession.cpp | 118 ++++++++++++++++++++++++++++++----------------- 1 file changed, 76 insertions(+), 42 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index 418de80..c368b7f 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -236,26 +236,66 @@ DRM_APP_CONTEXT * PlayreadySession::InitializeDRM(const DRM_CONST_STRING * pDRMS if (m_poAppContext == nullptr) { + fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); + // ChkMem( m_pbOpaqueBuffer = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE)); //aml + // ZEROMEM(m_pbOpaqueBuffer, MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE); + // m_cbOpaqueBuffer = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; //aml + + ChkMem( m_pbPROpaqueBuf = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE) ); + ZEROMEM(m_pbPROpaqueBuf, MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE); + m_cbPROpaqueBuf = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; -// ChkMem( m_pbOpaqueBuffer = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE)); //aml - ChkMem( m_pbPROpaqueBuf = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE) ); - ZEROMEM(m_pbPROpaqueBuf, MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE); -// m_cbOpaqueBuffer = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; //aml - m_cbPROpaqueBuf = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; + // ChkMem( m_poAppContext = (DRM_APP_CONTEXT *)Oem_MemAlloc(SIZEOF(DRM_APP_CONTEXT))); //aml + // ZEROMEM( m_poAppContext, sizeof(DRM_APP_CONTEXT) ); -// ChkMem( m_poAppContext = (DRM_APP_CONTEXT *)Oem_MemAlloc(SIZEOF(DRM_APP_CONTEXT))); //aml ChkMem( m_poAppContext = (DRM_APP_CONTEXT * )Oem_MemAlloc( sizeof(DRM_APP_CONTEXT) ) ); ZEROMEM( m_poAppContext, sizeof(DRM_APP_CONTEXT) ); /* pdrmOemContext this should be valid for BRCM , others it could be null */ // svpGetDrmOEMContext(&pdrmOemContext); // Initialize DRM app context. -// dr = Drm_Initialize(m_poAppContext, nullptr, m_pbOpaqueBuffer, m_cbOpaqueBuffer, &g_dstrCDMDrmStoreName); //aml + fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); dr = Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName); if (dr != DRM_SUCCESS) { + ocdm_log( "%s:%d drmstore corrrupt, delete it !!!!\n", __FUNCTION__, __LINE__); + //if drmstore file is corrupted, remove it and init again, playready will create a new one + remove(GetDrmStorePath().c_str()); ChkDR(Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName)); } + + // dr = Drm_Initialize(m_poAppContext, nullptr, m_pbOpaqueBuffer, m_cbOpaqueBuffer, &g_dstrCDMDrmStoreName); //aml + // if (dr != DRM_SUCCESS) + // { + // ocdm_log( "%s:%d drmstore corrrupt, delete it !!!!\n", __FUNCTION__, __LINE__); + // //if drmstore file is corrupted, remove it and init again, playready will create a new one + // remove(GetDrmStorePath().c_str()); + // ChkDR(Drm_Initialize(m_poAppContext, nullptr, m_pbOpaqueBuffer, m_cbOpaqueBuffer, &g_dstrCDMDrmStoreName)); + // } + + fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); + +///////////////////////////////////////////////////////////////////////////////////// + +// // ChkMem( m_pbOpaqueBuffer = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE)); //aml +// ChkMem( m_pbPROpaqueBuf = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE) ); +// ZEROMEM(m_pbPROpaqueBuf, MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE); +// // m_cbOpaqueBuffer = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; //aml +// m_cbPROpaqueBuf = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; + +// // ChkMem( m_poAppContext = (DRM_APP_CONTEXT *)Oem_MemAlloc(SIZEOF(DRM_APP_CONTEXT))); //aml +// ChkMem( m_poAppContext = (DRM_APP_CONTEXT * )Oem_MemAlloc( sizeof(DRM_APP_CONTEXT) ) ); +// ZEROMEM( m_poAppContext, sizeof(DRM_APP_CONTEXT) ); + +// /* pdrmOemContext this should be valid for BRCM , others it could be null */ +// // svpGetDrmOEMContext(&pdrmOemContext); +// // Initialize DRM app context. +// // dr = Drm_Initialize(m_poAppContext, nullptr, m_pbOpaqueBuffer, m_cbOpaqueBuffer, &g_dstrCDMDrmStoreName); //aml +// dr = Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName); +// if (dr != DRM_SUCCESS) +// { +// ChkDR(Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName)); +// } } else { @@ -333,43 +373,38 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD // mMaxResDecodePixels = 0; // mMaxResDecodeSet = false; -////////////////////////////////////////////////////////////////////////////////////////////// - ocdm_log("Constructing PlayReady Session [%p]\n", this); - - ChkMem(m_pbOpaqueBuffer = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE)); //aml - m_cbOpaqueBuffer = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; //aml - -#ifndef REUSE_APPCONTEXT - fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); - ChkMem(m_poAppContext = (DRM_APP_CONTEXT *)Oem_MemAlloc(SIZEOF(DRM_APP_CONTEXT))); //aml - - // Initialize DRM app context. - dr = Drm_Initialize(m_poAppContext, - nullptr, - m_pbOpaqueBuffer, - m_cbOpaqueBuffer, - &g_dstrCDMDrmStoreName); - if ((dr == DRM_E_SECURESTOP_STORE_CORRUPT) || \ - (dr == DRM_E_SECURESTORE_CORRUPT) || \ - (dr == DRM_E_DST_CORRUPTED)){ - - ocdm_log( "%s:%d drmstore corrrupt, delete it !!!!\n", __FUNCTION__, __LINE__); - //if drmstore file is corrupted, remove it and init again, playready will create a new one - remove(GetDrmStorePath().c_str()); - - dr = Drm_Initialize(m_poAppContext, - nullptr, - m_pbOpaqueBuffer, - m_cbOpaqueBuffer, - &g_dstrCDMDrmStoreName); - } - ChkDR(dr); +///////////////////////////////////////////////////////////////////////////////////////// + // fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); + // ChkMem( m_pbOpaqueBuffer = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE)); //aml + // ZEROMEM(m_pbOpaqueBuffer, MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE); + // m_cbOpaqueBuffer = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; //aml + + // ChkMem( m_poAppContext = (DRM_APP_CONTEXT *)Oem_MemAlloc(SIZEOF(DRM_APP_CONTEXT))); //aml + // ZEROMEM( m_poAppContext, sizeof(DRM_APP_CONTEXT) ); + + // /* pdrmOemContext this should be valid for BRCM , others it could be null */ + // // svpGetDrmOEMContext(&pdrmOemContext); + // // Initialize DRM app context. + // dr = Drm_Initialize(m_poAppContext, nullptr, m_pbOpaqueBuffer, m_cbOpaqueBuffer, &g_dstrCDMDrmStoreName); //aml + // fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); + // if (dr != DRM_SUCCESS) + // { + // ocdm_log( "%s:%d drmstore corrrupt, delete it !!!!\n", __FUNCTION__, __LINE__); + // //if drmstore file is corrupted, remove it and init again, playready will create a new one + // remove(GetDrmStorePath().c_str()); + // ChkDR(Drm_Initialize(m_poAppContext, nullptr, m_pbOpaqueBuffer, m_cbOpaqueBuffer, &g_dstrCDMDrmStoreName)); + // } + + // fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); ///////////////////////////////////////////////////////////////////////////////////////// - // if (m_poAppContext == nullptr) { - // m_poAppContext = InitializeDRM(&g_dstrCDMDrmStoreName); - // } +// if (m_poAppContext == nullptr) { + if (m_poAppContext) { + fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); + m_poAppContext = InitializeDRM(&g_dstrCDMDrmStoreName); + } +/////////////////////////////////////////////////////////////////////////////////////////// if (DRM_REVOCATION_IsRevocationSupported()) { ChkMem(m_pbRevocationBuffer = (DRM_BYTE *)Oem_MemAlloc(REVOCATION_BUFFER_SIZE)); @@ -377,7 +412,6 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD m_pbRevocationBuffer, REVOCATION_BUFFER_SIZE)); } -#endif // Generate a random media session ID. ChkDR(Oem_Random_GetBytes(nullptr, (DRM_BYTE *)&oSessionID, SIZEOF(oSessionID))); From 676d4eec9f2bd6d99ecc543e6af487181052b03a Mon Sep 17 00:00:00 2001 From: kvfasil Date: Wed, 1 Jan 2025 05:24:48 +0000 Subject: [PATCH 12/37] feat: code clean up. --- MediaSession.cpp | 87 ++++++++++-------------------------------------- 1 file changed, 18 insertions(+), 69 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index c368b7f..8523da5 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -190,8 +190,8 @@ PlayreadySession::PlayreadySession() , m_bInitCalled(false) { void *pPlatformInitData = NULL; - // // void svpGetDrmPlatformInitData( void ** ppPlatformInitData) - // // svpGetDrmPlatformInitData( &pPlatformInitData); + // void svpGetDrmPlatformInitData( void ** ppPlatformInitData) + // svpGetDrmPlatformInitData( &pPlatformInitData); //TODO // if ( DRM_FAILED( CPRDrmPlatform::DrmPlatformInitialize( pPlatformInitData ) ) ) @@ -235,67 +235,26 @@ DRM_APP_CONTEXT * PlayreadySession::InitializeDRM(const DRM_CONST_STRING * pDRMS if (m_poAppContext == nullptr) { - fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); - // ChkMem( m_pbOpaqueBuffer = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE)); //aml - // ZEROMEM(m_pbOpaqueBuffer, MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE); - // m_cbOpaqueBuffer = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; //aml - ChkMem( m_pbPROpaqueBuf = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE) ); ZEROMEM(m_pbPROpaqueBuf, MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE); m_cbPROpaqueBuf = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; - // ChkMem( m_poAppContext = (DRM_APP_CONTEXT *)Oem_MemAlloc(SIZEOF(DRM_APP_CONTEXT))); //aml - // ZEROMEM( m_poAppContext, sizeof(DRM_APP_CONTEXT) ); - - ChkMem( m_poAppContext = (DRM_APP_CONTEXT * )Oem_MemAlloc( sizeof(DRM_APP_CONTEXT) ) ); - ZEROMEM( m_poAppContext, sizeof(DRM_APP_CONTEXT) ); - - /* pdrmOemContext this should be valid for BRCM , others it could be null */ - // svpGetDrmOEMContext(&pdrmOemContext); - // Initialize DRM app context. - fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); - dr = Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName); - if (dr != DRM_SUCCESS) - { - ocdm_log( "%s:%d drmstore corrrupt, delete it !!!!\n", __FUNCTION__, __LINE__); - //if drmstore file is corrupted, remove it and init again, playready will create a new one - remove(GetDrmStorePath().c_str()); - ChkDR(Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName)); - } - - // dr = Drm_Initialize(m_poAppContext, nullptr, m_pbOpaqueBuffer, m_cbOpaqueBuffer, &g_dstrCDMDrmStoreName); //aml - // if (dr != DRM_SUCCESS) - // { - // ocdm_log( "%s:%d drmstore corrrupt, delete it !!!!\n", __FUNCTION__, __LINE__); - // //if drmstore file is corrupted, remove it and init again, playready will create a new one - // remove(GetDrmStorePath().c_str()); - // ChkDR(Drm_Initialize(m_poAppContext, nullptr, m_pbOpaqueBuffer, m_cbOpaqueBuffer, &g_dstrCDMDrmStoreName)); - // } + ChkMem( m_poAppContext = (DRM_APP_CONTEXT * )Oem_MemAlloc( sizeof(DRM_APP_CONTEXT) ) ); + ZEROMEM( m_poAppContext, sizeof(DRM_APP_CONTEXT) ); + /* pdrmOemContext this should be valid for BRCM , others it could be null */ + // svpGetDrmOEMContext(&pdrmOemContext); + // Initialize DRM app context. + dr = Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName); + if (dr != DRM_SUCCESS) + { + ocdm_log( "%s:%d drmstore corrrupt, delete it !!!!\n", __FUNCTION__, __LINE__); + //if drmstore file is corrupted, remove it and init again, playready will create a new one + remove(GetDrmStorePath().c_str()); + ChkDR(Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName)); + } fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); - -///////////////////////////////////////////////////////////////////////////////////// - -// // ChkMem( m_pbOpaqueBuffer = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE)); //aml -// ChkMem( m_pbPROpaqueBuf = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE) ); -// ZEROMEM(m_pbPROpaqueBuf, MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE); -// // m_cbOpaqueBuffer = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; //aml -// m_cbPROpaqueBuf = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; - -// // ChkMem( m_poAppContext = (DRM_APP_CONTEXT *)Oem_MemAlloc(SIZEOF(DRM_APP_CONTEXT))); //aml -// ChkMem( m_poAppContext = (DRM_APP_CONTEXT * )Oem_MemAlloc( sizeof(DRM_APP_CONTEXT) ) ); -// ZEROMEM( m_poAppContext, sizeof(DRM_APP_CONTEXT) ); - -// /* pdrmOemContext this should be valid for BRCM , others it could be null */ -// // svpGetDrmOEMContext(&pdrmOemContext); -// // Initialize DRM app context. -// // dr = Drm_Initialize(m_poAppContext, nullptr, m_pbOpaqueBuffer, m_cbOpaqueBuffer, &g_dstrCDMDrmStoreName); //aml -// dr = Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName); -// if (dr != DRM_SUCCESS) -// { -// ChkDR(Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName)); -// } } else { @@ -315,7 +274,6 @@ DRM_APP_CONTEXT * PlayreadySession::InitializeDRM(const DRM_CONST_STRING * pDRMS return nullptr; } - MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitData, const uint8_t *f_pbCDMData, uint32_t f_cbCDMData, DRM_APP_CONTEXT * poAppContext, bool initiateChallengeGeneration /* = false */) : m_pbOpaqueBuffer(nullptr) , m_cbOpaqueBuffer(0) @@ -344,7 +302,6 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD DRM_DWORD cchEncodedSessionID = SIZEOF(m_rgchSessionID); - ocdm_log("Initializing SVP context for client side\n"); gst_svp_ext_get_context(&m_pSVPContext, Client, m_rpcID); @@ -370,11 +327,10 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD // ChkBOOL(m_eKeyState == KEY_CLOSED, DRM_E_INVALIDARG); - // mMaxResDecodePixels = 0; - // mMaxResDecodeSet = false; +// mMaxResDecodePixels = 0; +// mMaxResDecodeSet = false; ///////////////////////////////////////////////////////////////////////////////////////// - // fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); // ChkMem( m_pbOpaqueBuffer = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE)); //aml // ZEROMEM(m_pbOpaqueBuffer, MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE); // m_cbOpaqueBuffer = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; //aml @@ -386,7 +342,6 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD // // svpGetDrmOEMContext(&pdrmOemContext); // // Initialize DRM app context. // dr = Drm_Initialize(m_poAppContext, nullptr, m_pbOpaqueBuffer, m_cbOpaqueBuffer, &g_dstrCDMDrmStoreName); //aml - // fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); // if (dr != DRM_SUCCESS) // { // ocdm_log( "%s:%d drmstore corrrupt, delete it !!!!\n", __FUNCTION__, __LINE__); @@ -395,10 +350,7 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD // ChkDR(Drm_Initialize(m_poAppContext, nullptr, m_pbOpaqueBuffer, m_cbOpaqueBuffer, &g_dstrCDMDrmStoreName)); // } - // fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); -///////////////////////////////////////////////////////////////////////////////////////// - -// if (m_poAppContext == nullptr) { +// if (m_poAppContext == nullptr) { //RTK if (m_poAppContext) { fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); m_poAppContext = InitializeDRM(&g_dstrCDMDrmStoreName); @@ -431,14 +383,11 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD playreadyInitData = initData; } - ChkDR(Drm_Content_SetProperty(m_poAppContext, DRM_CSP_AUTODETECT_HEADER, reinterpret_cast(playreadyInitData.data()), playreadyInitData.size())); - - #ifdef PR_4_4 //temporary hack to allow time based licenses ( DRM_REINTERPRET_CAST( DRM_APP_CONTEXT_INTERNAL, m_poAppContext ) )->fClockSet = TRUE; From bb9aa68dfc3b04a5b946e088c6e8ce3951e4d1af Mon Sep 17 00:00:00 2001 From: kvfasil Date: Wed, 1 Jan 2025 11:54:27 +0000 Subject: [PATCH 13/37] feat: CPRDrmPlatform class implemented. --- MediaSession.cpp | 121 +++++++++++++++++++++++++++++++++++++++++++++++ MediaSession.h | 2 +- MediaSystem.cpp | 4 +- 3 files changed, 125 insertions(+), 2 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index 8523da5..3501ed3 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -33,10 +33,12 @@ using namespace WPEFramework; using SafeCriticalSection = Core::SafeSyncType; MODULE_NAME_DECLARATION(BUILD_REFERENCE); +WPEFramework::Core::CriticalSection prPlatformMutex_; extern Core::CriticalSection drmAppContextMutex_; WPEFramework::Core::CriticalSection prSessionMutex_; extern DRM_CONST_STRING g_dstrCDMDrmStoreName; +extern DRM_VOID *m_drmOemContext; #define NYI_KEYSYSTEM "keysystem-placeholder" @@ -56,12 +58,19 @@ extern DRM_CONST_STRING g_dstrCDMDrmStoreName; #define NO_OF DRM_NO_OF #endif +#define DEVCERT_WAIT_SECS 30 +#define DEVCERT_RETRY_MAX 4 + +#define EXPECTED_AES_CTR_IVDATA_SIZE (8) +#define EXPECTED_AES_CBC_IVDATA_SIZE (16) using namespace std; namespace CDMi { const DRM_CONST_STRING *g_rgpdstrRights[1] = {&g_dstrDRM_RIGHT_PLAYBACK}; +DRM_DWORD CPRDrmPlatform::m_dwInitRefCount = 0; + void * MediaKeySession::sess = NULL; uint32_t MediaKeySession::m_secCount = 0; @@ -183,6 +192,118 @@ bool parsePlayreadyInitializationData(const std::string& initData, std::string* return false; } +/* + * f_pContext(input) : It could be NULL or Valid pointer + */ +DRM_RESULT CPRDrmPlatform::DrmPlatformInitialize( void *f_pContext ) +{ + DRM_RESULT dr = DRM_SUCCESS; + SafeCriticalSection systemLock(prPlatformMutex_); + + if ( ++m_dwInitRefCount == 1 ) + { + DRM_RESULT dr = DRM_SUCCESS; + DRM_DWORD cAttempts = 0; + + while( ( dr=Drm_Platform_Initialize( f_pContext ) ) == DRM_E_DEPRECATED_DEVCERT_READ_ERROR) { + + Drm_Platform_Uninitialize( (void *)nullptr ); + + if ( cAttempts >= DEVCERT_RETRY_MAX ){ + ChkDR( DRM_E_DEPRECATED_DEVCERT_READ_ERROR); + } + sleep( DEVCERT_WAIT_SECS ); + ++cAttempts; + } + } + + ErrorExit: + + if ( DRM_FAILED( dr ) ) + { + --m_dwInitRefCount; + fprintf(stderr, "[%s:%d] failed. 0x%X",__FUNCTION__,__LINE__,dr); + } + + return dr; +} + +DRM_RESULT CPRDrmPlatform::DrmPlatformInitialize() +{ + void *pPlatformInitData = NULL; + /* realtek, it returns DRM_INIT_CONTEXT as pPlatformInitData, + * Amlogic, it would be NULL + * BRCM, it returns OEM_Settings as pPlatformInitData + */ + // void svpGetDrmPlatformInitData( void ** ppPlatformInitData) + // svpGetDrmPlatformInitData( &pPlatformInitData); + return DrmPlatformInitialize( (void *)pPlatformInitData ); +} + +DRM_RESULT CPRDrmPlatform::DrmPlatformUninitialize() +{ + DRM_RESULT dr = DRM_SUCCESS; + + SafeCriticalSection systemLock(prPlatformMutex_); + + if ( m_dwInitRefCount == 0 ) + { + fprintf(stderr, "[%s:%d] ref count is already 0",__FUNCTION__,__LINE__); + ChkDR( DRM_E_FAIL ); + } + else if ( --m_dwInitRefCount == 0 ) + { + /* m_drmOemContext currently used by BRCM. AML & RTK it could be stub */ + //void svpGetDrmOEMContext(void ** ppdrmOemContext) + // svpGetDrmOEMContext(&m_drmOemContext); + + if ( DRM_FAILED( (dr=Drm_Platform_Uninitialize( (void *)m_drmOemContext ) ) ) ) + { + fprintf(stderr, "[%s:%d] Drm_Platform_Uninitialize failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + goto ErrorExit; + } + } + + ErrorExit: + + if ( DRM_FAILED( dr ) ) + { + fprintf(stderr, "[%s:%d] failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + } + + return dr; + +} + +/*Get the version and list of keyids from the header*/ +DRM_RESULT Header_GetInfo( + const DRM_CONST_STRING *f_pdstrWRMHEADER, + eDRM_HEADER_VERSION *f_pHeaderVersion, + DRM_CONST_STRING **f_ppdstrKIDs, + DRM_DWORD *f_pcbKIDs) +{ + DRM_RESULT dr = DRM_SUCCESS; + DRM_DWORD cKIDs = 0; + DRM_CONST_STRING *pdstrKIDs = NULL; + + PR4ChkDR( DRM_HDR_GetHeaderVersion( f_pdstrWRMHEADER, f_pHeaderVersion ) ); + + PR4ChkDR( DRM_HDR_GetAttribute( + f_pdstrWRMHEADER, + NULL, + DRM_HEADER_ATTRIB_KIDS, + NULL, + &cKIDs, + &pdstrKIDs, + 0 ) ); + + *f_ppdstrKIDs = pdstrKIDs; + *f_pcbKIDs = cKIDs; + +ErrorExit: + return dr; +} + PlayreadySession::PlayreadySession() : m_poAppContext(nullptr) , m_pbPROpaqueBuf(nullptr) diff --git a/MediaSession.h b/MediaSession.h index 247ee80..b00dd6e 100644 --- a/MediaSession.h +++ b/MediaSession.h @@ -541,7 +541,7 @@ class CPRDrmPlatform { public: static DRM_RESULT DrmPlatformInitialize(); - static DRM_RESULT DrmPlatformInitialize( DRM_INIT_CONTEXT * ); + static DRM_RESULT DrmPlatformInitialize( void * ); static DRM_RESULT DrmPlatformUninitialize(); private: static DRM_DWORD m_dwInitRefCount; diff --git a/MediaSystem.cpp b/MediaSystem.cpp index 57b9e46..45d2ab4 100644 --- a/MediaSystem.cpp +++ b/MediaSystem.cpp @@ -49,6 +49,7 @@ using namespace std; extern DRM_CONST_STRING g_dstrDrmPath; DRM_CONST_STRING g_dstrCDMDrmStoreName; //AML +DRM_VOID *m_drmOemContext; using SafeCriticalSection = WPEFramework::Core::SafeSyncType; @@ -597,7 +598,8 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { { SafeCriticalSection lock(drmAppContextMutex_); - DRM_RESULT err = Drm_Platform_Initialize(nullptr); +// DRM_RESULT err = Drm_Platform_Initialize(nullptr); + DRM_RESULT err = CPRDrmPlatform::DrmPlatformInitialize(); if(DRM_FAILED(err)) { From a140b11a3e1b7fefb3aff2e432a3cc223cedca06 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Wed, 1 Jan 2025 12:50:21 +0000 Subject: [PATCH 14/37] feat: KeyId class added. --- MediaSession.cpp | 129 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) diff --git a/MediaSession.cpp b/MediaSession.cpp index 3501ed3..3edeb71 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -65,6 +65,135 @@ extern DRM_VOID *m_drmOemContext; #define EXPECTED_AES_CBC_IVDATA_SIZE (16) using namespace std; +KeyId::KeyId( const DRM_BYTE *f_pBytes , KeyIdOrder keyOrder) +{ + m_hexStr.clear(); + m_base64Str.clear(); + ZEROMEM( m_bytes, DRM_ID_SIZE ); + keyIdOrder = KEYID_ORDER_UNKNOWN; + memcpy( m_bytes, f_pBytes, DRM_ID_SIZE ); + keyIdOrder = keyOrder; +} + +DRM_RESULT KeyId::keyDecode( const DRM_CONST_STRING &f_pdstrB64 ){ + + DRM_DWORD cBytes = DRM_ID_SIZE; + DRM_RESULT dr = DRM_B64_DecodeW( &f_pdstrB64, &cBytes, getmBytes(), 0 ); + if ( dr != DRM_SUCCESS ) + { + fprintf(stderr, "\n[keyDecode] DRM_B64_DecodeW Failed"); + } + return dr; +} + +void KeyId::setKeyIdOrder(KeyIdOrder keyOrder) +{ + keyIdOrder = keyOrder; +} + +KeyId::KeyIdOrder KeyId::getKeyIdOrder() +{ + return keyIdOrder; +} + +const DRM_BYTE* KeyId::getmBytes() +{ + return m_bytes; +} + +KeyId& KeyId::ToggleFormat() +{ + DRM_BYTE tmp; + + if ( keyIdOrder != KEYID_ORDER_UNKNOWN ) + { + tmp = m_bytes[3]; + m_bytes[3] = m_bytes[0]; + m_bytes[0] = tmp; + tmp = m_bytes[2]; + m_bytes[2] = m_bytes[1]; + m_bytes[1] = tmp; + tmp = m_bytes[5]; + m_bytes[5] = m_bytes[4]; + m_bytes[4] = tmp; + tmp = m_bytes[7]; + m_bytes[7] = m_bytes[6]; + m_bytes[6] = tmp; + + if ( keyIdOrder == KEYID_ORDER_GUID_LE ) + keyIdOrder = KEYID_ORDER_UUID_BE; + else + keyIdOrder = KEYID_ORDER_GUID_LE; + } + m_hexStr.clear(); + m_base64Str.clear(); + + return *this; +} + +bool KeyId::operator< ( const KeyId &keyId ) const +{ + if ( memcmp(keyId.m_bytes, m_bytes, DRM_ID_SIZE) < 0 ) + return true; + return false; +} + +bool KeyId::operator== ( const KeyId &keyId ) +{ + bool areEqual = false; + + if ( memcmp(&m_bytes[8], &(keyId.m_bytes[8]), 8) == 0 ) + { + if ( memcmp(keyId.m_bytes, m_bytes, 8) == 0 ) + { + areEqual = true; + } + else + { + ToggleFormat(); + areEqual = ( memcmp(keyId.m_bytes, m_bytes, DRM_ID_SIZE ) == 0 ); + ToggleFormat(); + } + } + + return areEqual; +} + +const char* KeyId::HexStr() +{ + if ( m_hexStr.empty() ) + { + char hex[64]; + ::memset(hex, 0, 64); + for (int i = 0; i < DRM_ID_SIZE; i++) + { + hex[i * 2] = "0123456789abcdef"[m_bytes[i] >> 4]; + hex[i * 2 + 1] = "0123456789abcdef"[m_bytes[i] & 0x0F]; + } + m_hexStr = hex; + } + + return m_hexStr.c_str(); +} + +const char* KeyId::B64Str() +{ + DRM_RESULT dr = DRM_SUCCESS; + if ( m_base64Str.empty() ) + { + char b64[64]; + DRM_DWORD cbB64 = 64; + ::memset( b64, 0, 64 ); + PR4ChkDR( DRM_B64_EncodeA( m_bytes, DRM_ID_SIZE, b64, &cbB64, 0 ) ); + + m_base64Str = b64; + } + + ErrorExit: + + return m_base64Str.c_str(); +} + namespace CDMi { const DRM_CONST_STRING *g_rgpdstrRights[1] = {&g_dstrDRM_RIGHT_PLAYBACK}; From 9f6a5025a5c8dfd94241a2e735832a86d3a8c0e9 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 2 Jan 2025 05:20:20 +0000 Subject: [PATCH 15/37] fix: commented unused init variable. --- MediaSession.cpp | 56 ++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 54 insertions(+), 2 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index 3edeb71..d0d1eea 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -196,6 +196,30 @@ const char* KeyId::B64Str() namespace CDMi { +namespace { +void Swap(uint8_t& lhs, uint8_t& rhs) +{ + uint8_t tmp =lhs; + lhs = rhs; + rhs = tmp; +} +} + +/* +DRM_INIT_CONTEXT g_oDrmInitContext = { "/opt/drm", "/opt/drm/sample.hds" }; + +const DRM_WCHAR g_rgwchCDMDrmStoreName[] = {WCHAR_CAST('/'), WCHAR_CAST('o'), WCHAR_CAST('p'), WCHAR_CAST('t'), WCHAR_CAST('/'), + WCHAR_CAST('d'), WCHAR_CAST('r'), WCHAR_CAST('m'), WCHAR_CAST('/'), WCHAR_CAST('s'), + WCHAR_CAST('a'), WCHAR_CAST('m'), WCHAR_CAST('p'), WCHAR_CAST('l'), WCHAR_CAST('e'), + WCHAR_CAST('.'), WCHAR_CAST('h'), WCHAR_CAST('d'), WCHAR_CAST('s'), WCHAR_CAST('\0')}; + +const DRM_WCHAR g_rgwchCDMDrmPath[] = {WCHAR_CAST('/'), WCHAR_CAST('o'), WCHAR_CAST('p'), WCHAR_CAST('t'), WCHAR_CAST('/'), + WCHAR_CAST('d'), WCHAR_CAST('r'), WCHAR_CAST('m'), WCHAR_CAST('\0')}; + +const DRM_CONST_STRING g_dstrCDMDrmStoreName = CREATE_DRM_STRING(g_rgwchCDMDrmStoreName); +const DRM_CONST_STRING g_dstrCDMDrmPath = CREATE_DRM_STRING(g_rgwchCDMDrmPath); +*/ + const DRM_CONST_STRING *g_rgpdstrRights[1] = {&g_dstrDRM_RIGHT_PLAYBACK}; DRM_DWORD CPRDrmPlatform::m_dwInitRefCount = 0; @@ -525,9 +549,9 @@ DRM_APP_CONTEXT * PlayreadySession::InitializeDRM(const DRM_CONST_STRING * pDRMS } MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitData, const uint8_t *f_pbCDMData, uint32_t f_cbCDMData, DRM_APP_CONTEXT * poAppContext, bool initiateChallengeGeneration /* = false */) - : m_pbOpaqueBuffer(nullptr) + : /* m_pbOpaqueBuffer(nullptr) , m_cbOpaqueBuffer(0) - , m_pbRevocationBuffer(nullptr) + , */ m_pbRevocationBuffer(nullptr) , m_eKeyState(KEY_INIT) , m_pbChallenge(nullptr) , m_cbChallenge(0) @@ -643,6 +667,34 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD ( DRM_REINTERPRET_CAST( DRM_APP_CONTEXT_INTERNAL, m_poAppContext ) )->fClockSet = TRUE; #endif + DRM_CONST_DSTR_FROM_PB( &dstrWRMHEADER, &mDrmHeader[ 0 ], mDrmHeader.size() ); + + ChkDR( Header_GetInfo( &dstrWRMHEADER, + &m_eHeaderVersion, + &m_pdstrHeaderKIDs, + &m_cHeaderKIDs ) ); + + for( DRM_DWORD idx = 0; idx < m_cHeaderKIDs; idx++ ) + { + KeyId kid , kid2; + DRM_DWORD cBytes = DRM_ID_SIZE; + DRM_DWORD cBytes2 = DRM_ID_SIZE; + + DRM_RESULT dr = DRM_B64_DecodeW( &m_pdstrHeaderKIDs[ idx ], &cBytes, kid.getmBytes(), 0 ); + if ( dr == DRM_SUCCESS ) + { + kid.setKeyIdOrder(KeyId::KEYID_ORDER_GUID_LE); + } + + DRM_RESULT dr2 = DRM_B64_DecodeW( &m_pdstrHeaderKIDs[ idx ], &cBytes2, kid2.getmBytes(), 0 ); + if ( dr2 == DRM_SUCCESS ) + { + kid2.setKeyIdOrder(KeyId::KEYID_ORDER_GUID_LE); + } + } + + m_eKeyState = KEY_INIT; + // The current state MUST be KEY_INIT otherwise error out. ChkBOOL(m_eKeyState == KEY_INIT, DRM_E_INVALIDARG); m_secCount++; From 75c33a2a1b2a7aeb67ec9591cb5dc23fa4afe2e7 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 2 Jan 2025 05:55:56 +0000 Subject: [PATCH 16/37] fix: aligned and cleanup MediaKeySession() init variable. --- MediaSession.cpp | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index d0d1eea..db0db44 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -549,9 +549,7 @@ DRM_APP_CONTEXT * PlayreadySession::InitializeDRM(const DRM_CONST_STRING * pDRMS } MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitData, const uint8_t *f_pbCDMData, uint32_t f_cbCDMData, DRM_APP_CONTEXT * poAppContext, bool initiateChallengeGeneration /* = false */) - : /* m_pbOpaqueBuffer(nullptr) - , m_cbOpaqueBuffer(0) - , */ m_pbRevocationBuffer(nullptr) + : m_pbRevocationBuffer(nullptr) , m_eKeyState(KEY_INIT) , m_pbChallenge(nullptr) , m_cbChallenge(0) @@ -559,14 +557,22 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD , m_customData(reinterpret_cast(f_pbCDMData), f_cbCDMData) , m_piCallback(nullptr) , mSessionId(0) - , m_fCommit(FALSE) , mInitiateChallengeGeneration(initiateChallengeGeneration) - , m_poAppContext(poAppContext) + , m_cHeaderKIDs(0) + , m_pdstrHeaderKIDs( nullptr ) + , m_eHeaderVersion( DRM_HEADER_VERSION_UNKNOWN ) + , m_oBatchID( DRM_ID_EMPTY ) +// , m_currentDecryptContext( nullptr ) //RTK , m_oDecryptContext(nullptr) , m_oDecryptContext2(nullptr) - , m_decryptInited(false) - , m_pSVPContext(NULL) +#ifdef USE_SVP + , m_pSVPContext(nullptr) , m_rpcID(0) +#endif + , m_fCommit(FALSE) + , m_poAppContext(poAppContext) + , m_decryptInited(false) + , m_bDRMInitializedLocally(false) { memset(&levels_, 0, sizeof(levels_)); //need to comment later. From 86121e8051ca72cec682c942856c9670230a5c8f Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 2 Jan 2025 08:42:55 +0000 Subject: [PATCH 17/37] fix: code refacterd. --- MediaSession.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index db0db44..cc4d467 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -553,7 +553,7 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD , m_eKeyState(KEY_INIT) , m_pbChallenge(nullptr) , m_cbChallenge(0) - , m_pchSilentURL(nullptr) + , m_pchSilentURL(nullptr) , m_customData(reinterpret_cast(f_pbCDMData), f_cbCDMData) , m_piCallback(nullptr) , mSessionId(0) @@ -585,16 +585,6 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD ocdm_log("Initializing SVP context for client side\n"); gst_svp_ext_get_context(&m_pSVPContext, Client, m_rpcID); - if (!initiateChallengeGeneration) { - fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); - mLicenseResponse = std::unique_ptr(new LicenseResponse()); - mSecureStopId.clear(); - - // TODO: can we do this nicer? - mDrmHeader.resize(f_cbCDMData); - memcpy(&mDrmHeader[0], f_pbCDMData, f_cbCDMData); - m_secCount++; - } else { fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); m_oDecryptContext = new DRM_DECRYPT_CONTEXT; memset(m_oDecryptContext, 0, sizeof(DRM_DECRYPT_CONTEXT)); @@ -705,7 +695,6 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD ChkBOOL(m_eKeyState == KEY_INIT, DRM_E_INVALIDARG); m_secCount++; return; - } ErrorExit: if (DRM_FAILED(dr)) { From faa497ff4900b84b4de6af9a03dddce98e82cfca Mon Sep 17 00:00:00 2001 From: kvfasil Date: Tue, 14 Jan 2025 06:30:47 +0000 Subject: [PATCH 18/37] fix: CMakelists updated. --- CMakeLists.txt | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index f696b5b..54395ff 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,7 +57,6 @@ set_target_properties(${DRM_PLUGIN_NAME} PROPERTIES PREFIX "") find_package(PlayReady REQUIRED) if(PLAYREADY_FOUND) message(STATUS "PlayReady found!") - # message(STATUS "${PLAYREADY_INCLUDE_DIRS}") include_directories(${PLAYREADY_INCLUDE_DIRS}) include_directories(${PLAYREADY_LIBRARIES}) target_link_libraries(${DRM_PLUGIN_NAME} playready-4.4) @@ -69,15 +68,12 @@ find_package(OpenSSL REQUIRED) target_link_libraries(${DRM_PLUGIN_NAME} OpenSSL::SSL) # Enable SVP. -#if("${RDK_SVP}" STREQUAL "ENABLED") message(STATUS "Using RDK_SVP") add_definitions (-DUSE_SVP) target_include_directories(${DRM_PLUGIN_NAME} PRIVATE ${CMAKE_SYSROOT}/usr/include/gstreamer-1.0) target_include_directories(${DRM_PLUGIN_NAME} PRIVATE ${CMAKE_SYSROOT}/usr/include/glib-2.0) target_include_directories(${DRM_PLUGIN_NAME} PRIVATE ${CMAKE_SYSROOT}/usr/lib/glib-2.0/include) - #target_link_libraries(${DRM_PLUGIN_NAME} gstsvpext) - target_link_libraries(${DRM_PLUGIN_NAME} gstamlsvpext) -#endif() + target_link_libraries(${DRM_PLUGIN_NAME} gstsvpext) if("${DYNAMIC_SVP_DECRYPTION}" STREQUAL "ON") add_definitions( -DDYNAMIC_SVP_DECRYPTION ) @@ -102,9 +98,3 @@ endif() install(TARGETS ${DRM_PLUGIN_NAME} DESTINATION ${CMAKE_INSTALL_PREFIX}/share/WPEFramework/OCDM) -if(NOT "${CMAKE_FIND_ROOT_PATH}" STREQUAL "") - install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink /etc/playready ${CMAKE_CURRENT_BINARY_DIR}/playready)") - install(DIRECTORY DESTINATION ${CMAKE_INSTALL_PREFIX}/../${PERSISTENT_PATH}/OCDM) - install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/playready DESTINATION ${CMAKE_INSTALL_PREFIX}/../${PERSISTENT_PATH}/OCDM/) -endif() - From a061b392174c10574bbf20b353ad6da086fb312f Mon Sep 17 00:00:00 2001 From: kvfasil Date: Wed, 15 Jan 2025 09:44:25 +0000 Subject: [PATCH 19/37] fix: fixing runtime issue due to latest change. --- MediaSession.cpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index cc4d467..efc6729 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -967,19 +967,8 @@ CDMi_RESULT MediaKeySession::Close(void) { SAFE_OEM_FREE(m_pbRevocationBuffer); m_pbRevocationBuffer = nullptr; } -#ifndef REUSE_APPCONTEXT - if (m_poAppContext != nullptr) { - Drm_Uninitialize(m_poAppContext); - SAFE_OEM_FREE(m_poAppContext); - m_poAppContext = nullptr; - } -#endif - if (m_pbOpaqueBuffer != nullptr) { - SAFE_OEM_FREE(m_pbOpaqueBuffer); - m_pbOpaqueBuffer = nullptr; - } - if (m_oDecryptContext != nullptr) { + if (m_oDecryptContext != nullptr) { Drm_Reader_Close(m_oDecryptContext); delete m_oDecryptContext; m_oDecryptContext = nullptr; From 2b23d8780ec0313540c4987d338453824d4099b0 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Wed, 15 Jan 2025 20:23:07 +0000 Subject: [PATCH 20/37] fix: fixing runtime issue. --- MediaSession.cpp | 54 ++++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index efc6729..47e93aa 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -663,33 +663,33 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD ( DRM_REINTERPRET_CAST( DRM_APP_CONTEXT_INTERNAL, m_poAppContext ) )->fClockSet = TRUE; #endif - DRM_CONST_DSTR_FROM_PB( &dstrWRMHEADER, &mDrmHeader[ 0 ], mDrmHeader.size() ); - - ChkDR( Header_GetInfo( &dstrWRMHEADER, - &m_eHeaderVersion, - &m_pdstrHeaderKIDs, - &m_cHeaderKIDs ) ); - - for( DRM_DWORD idx = 0; idx < m_cHeaderKIDs; idx++ ) - { - KeyId kid , kid2; - DRM_DWORD cBytes = DRM_ID_SIZE; - DRM_DWORD cBytes2 = DRM_ID_SIZE; - - DRM_RESULT dr = DRM_B64_DecodeW( &m_pdstrHeaderKIDs[ idx ], &cBytes, kid.getmBytes(), 0 ); - if ( dr == DRM_SUCCESS ) - { - kid.setKeyIdOrder(KeyId::KEYID_ORDER_GUID_LE); - } - - DRM_RESULT dr2 = DRM_B64_DecodeW( &m_pdstrHeaderKIDs[ idx ], &cBytes2, kid2.getmBytes(), 0 ); - if ( dr2 == DRM_SUCCESS ) - { - kid2.setKeyIdOrder(KeyId::KEYID_ORDER_GUID_LE); - } - } - - m_eKeyState = KEY_INIT; + // DRM_CONST_DSTR_FROM_PB( &dstrWRMHEADER, &mDrmHeader[ 0 ], mDrmHeader.size() ); + + // ChkDR( Header_GetInfo( &dstrWRMHEADER, + // &m_eHeaderVersion, + // &m_pdstrHeaderKIDs, + // &m_cHeaderKIDs ) ); + + // for( DRM_DWORD idx = 0; idx < m_cHeaderKIDs; idx++ ) + // { + // KeyId kid , kid2; + // DRM_DWORD cBytes = DRM_ID_SIZE; + // DRM_DWORD cBytes2 = DRM_ID_SIZE; + + // DRM_RESULT dr = DRM_B64_DecodeW( &m_pdstrHeaderKIDs[ idx ], &cBytes, kid.getmBytes(), 0 ); + // if ( dr == DRM_SUCCESS ) + // { + // kid.setKeyIdOrder(KeyId::KEYID_ORDER_GUID_LE); + // } + + // DRM_RESULT dr2 = DRM_B64_DecodeW( &m_pdstrHeaderKIDs[ idx ], &cBytes2, kid2.getmBytes(), 0 ); + // if ( dr2 == DRM_SUCCESS ) + // { + // kid2.setKeyIdOrder(KeyId::KEYID_ORDER_GUID_LE); + // } + // } + + // m_eKeyState = KEY_INIT; // The current state MUST be KEY_INIT otherwise error out. ChkBOOL(m_eKeyState == KEY_INIT, DRM_E_INVALIDARG); From 8f9c322e6cc43cfb840afd4b3082a4a327aa3766 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Wed, 15 Jan 2025 20:35:25 +0000 Subject: [PATCH 21/37] fix: cleanup. --- MediaSession.cpp | 48 ++++++------------------------------------------ 1 file changed, 6 insertions(+), 42 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index 47e93aa..e11fbdb 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -14,7 +14,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - #include "MediaSession.h" #include #include @@ -36,9 +35,9 @@ MODULE_NAME_DECLARATION(BUILD_REFERENCE); WPEFramework::Core::CriticalSection prPlatformMutex_; extern Core::CriticalSection drmAppContextMutex_; WPEFramework::Core::CriticalSection prSessionMutex_; +extern DRM_VOID *m_drmOemContext; extern DRM_CONST_STRING g_dstrCDMDrmStoreName; -extern DRM_VOID *m_drmOemContext; #define NYI_KEYSYSTEM "keysystem-placeholder" @@ -197,28 +196,15 @@ const char* KeyId::B64Str() namespace CDMi { namespace { + void Swap(uint8_t& lhs, uint8_t& rhs) { uint8_t tmp =lhs; lhs = rhs; rhs = tmp; } -} -/* -DRM_INIT_CONTEXT g_oDrmInitContext = { "/opt/drm", "/opt/drm/sample.hds" }; - -const DRM_WCHAR g_rgwchCDMDrmStoreName[] = {WCHAR_CAST('/'), WCHAR_CAST('o'), WCHAR_CAST('p'), WCHAR_CAST('t'), WCHAR_CAST('/'), - WCHAR_CAST('d'), WCHAR_CAST('r'), WCHAR_CAST('m'), WCHAR_CAST('/'), WCHAR_CAST('s'), - WCHAR_CAST('a'), WCHAR_CAST('m'), WCHAR_CAST('p'), WCHAR_CAST('l'), WCHAR_CAST('e'), - WCHAR_CAST('.'), WCHAR_CAST('h'), WCHAR_CAST('d'), WCHAR_CAST('s'), WCHAR_CAST('\0')}; - -const DRM_WCHAR g_rgwchCDMDrmPath[] = {WCHAR_CAST('/'), WCHAR_CAST('o'), WCHAR_CAST('p'), WCHAR_CAST('t'), WCHAR_CAST('/'), - WCHAR_CAST('d'), WCHAR_CAST('r'), WCHAR_CAST('m'), WCHAR_CAST('\0')}; - -const DRM_CONST_STRING g_dstrCDMDrmStoreName = CREATE_DRM_STRING(g_rgwchCDMDrmStoreName); -const DRM_CONST_STRING g_dstrCDMDrmPath = CREATE_DRM_STRING(g_rgwchCDMDrmPath); -*/ +} const DRM_CONST_STRING *g_rgpdstrRights[1] = {&g_dstrDRM_RIGHT_PLAYBACK}; @@ -227,11 +213,7 @@ DRM_DWORD CPRDrmPlatform::m_dwInitRefCount = 0; void * MediaKeySession::sess = NULL; uint32_t MediaKeySession::m_secCount = 0; -// Parse out the first PlayReady initialization header found in the concatenated -// block of headers in _initData_. -// If a PlayReady header is found, this function returns true and the header -// contents are stored in _output_. -// Otherwise, returns false and _output_ is not touched. +/*Parsing the first playready init header from _initData_. In success case the header will be stored in _output_*/ bool parsePlayreadyInitializationData(const std::string& initData, std::string* output) { BufferReader input(reinterpret_cast(initData.data()), initData.length()); @@ -239,23 +221,12 @@ bool parsePlayreadyInitializationData(const std::string& initData, std::string* static const uint8_t playreadySystemId[] = { 0x9A, 0x04, 0xF0, 0x79, 0x98, 0x40, 0x42, 0x86, 0xAB, 0x92, 0xE6, 0x5B, 0xE0, 0x88, 0x5F, 0x95, + }; - // one PSSH box consists of: - // 4 byte size of the atom, inclusive. (0 means the rest of the buffer.) - // 4 byte atom type, "pssh". - // (optional, if size == 1) 8 byte size of the atom, inclusive. - // 1 byte version, value 0 or 1. (skip if larger.) - // 3 byte flags, value 0. (ignored.) - // 16 byte system id. - // (optional, if version == 1) 4 byte key ID count. (K) - // (optional, if version == 1) K * 16 byte key ID. - // 4 byte size of PSSH data, exclusive. (N) - // N byte PSSH data. while (!input.IsEOF()) { size_t startPosition = input.pos(); - // The atom size, used for skipping. uint64_t atomSize; if (!input.Read4Into8(&atomSize)) { @@ -289,26 +260,22 @@ bool parsePlayreadyInitializationData(const std::string& initData, std::string* if (version > 1) { - // unrecognized version - skip. if (!input.SkipBytes(atomSize - (input.pos() - startPosition))) { return false; } continue; } - // flags if (!input.SkipBytes(3)) { return false; } - // system id std::vector systemId; if (!input.ReadVec(&systemId, sizeof(playreadySystemId))) { return false; } if (memcmp(&systemId[0], playreadySystemId, sizeof(playreadySystemId))) { - // skip non-Playready PSSH boxes. if (!input.SkipBytes(atomSize - (input.pos() - startPosition))) { return false; } @@ -316,7 +283,6 @@ bool parsePlayreadyInitializationData(const std::string& initData, std::string* } if (version == 1) { - // v1 has additional fields for key IDs. We can skip them. uint32_t numKeyIds; if (!input.Read4(&numKeyIds)) { return false; @@ -327,7 +293,6 @@ bool parsePlayreadyInitializationData(const std::string& initData, std::string* } } - // size of PSSH data uint32_t dataLength; if (!input.Read4(&dataLength)) { return false; @@ -341,12 +306,11 @@ bool parsePlayreadyInitializationData(const std::string& initData, std::string* return true; } - // we did not find a matching record return false; } /* - * f_pContext(input) : It could be NULL or Valid pointer + * f_pContext(input) : It could be NULL or Valid pointer */ DRM_RESULT CPRDrmPlatform::DrmPlatformInitialize( void *f_pContext ) { From b246f22339d8d7686acc5a99458f31b91c50e05e Mon Sep 17 00:00:00 2001 From: kvfasil Date: Wed, 15 Jan 2025 20:52:59 +0000 Subject: [PATCH 22/37] fix: cleanup. --- MediaSystem.cpp | 73 +++++++++++++++++++++++++------------------------ 1 file changed, 37 insertions(+), 36 deletions(-) diff --git a/MediaSystem.cpp b/MediaSystem.cpp index 45d2ab4..61318b3 100644 --- a/MediaSystem.cpp +++ b/MediaSystem.cpp @@ -26,13 +26,14 @@ #ifdef AML_SVP_PR #include +#include #else #include #endif #include + #include -#include #define CLEAN_ON_INIT 1 @@ -49,8 +50,8 @@ using namespace std; extern DRM_CONST_STRING g_dstrDrmPath; DRM_CONST_STRING g_dstrCDMDrmStoreName; //AML -DRM_VOID *m_drmOemContext; +DRM_VOID *m_drmOemContext; using SafeCriticalSection = WPEFramework::Core::SafeSyncType; WPEFramework::Core::CriticalSection drmAppContextMutex_; @@ -65,12 +66,12 @@ static DRM_WCHAR* createDrmWchar(std::string const& s) { static void PackedCharsToNative(DRM_CHAR *f_pPackedString, DRM_DWORD f_cch) { DRM_DWORD ich = 0; - - if ( f_pPackedString == nullptr || f_cch == 0 ) + if( f_pPackedString == nullptr + || f_cch == 0 ) { return; } - for ( ich = 1; ich <= f_cch; ich++ ) + for( ich = 1; ich <= f_cch; ich++ ) { f_pPackedString[f_cch - ich] = ((DRM_BYTE*)f_pPackedString)[ f_cch - ich ]; } @@ -111,7 +112,6 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { CDMi_RESULT SetSecureStopPublisherCert( const DRM_BYTE*, DRM_DWORD ); }; - private: PlayReady (const PlayReady&) = delete; PlayReady& operator= (const PlayReady&) = delete; @@ -125,6 +125,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { } public: + PlayReady() : m_poAppContext(nullptr) { } @@ -143,14 +144,12 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { int32_t licenseType, const char *f_pwszInitDataType, const uint8_t *f_pbInitData, - uint32_t f_cbInitData, + uint32_t f_cbInitData, const uint8_t *f_pbCDMData, - uint32_t f_cbCDMData, + uint32_t f_cbCDMData, IMediaKeySession **f_ppiMediaKeySession) { - bool isNetflixPlayready = (strstr(keySystem.c_str(), "netflix") != nullptr); if (isNetflixPlayready) { - // TODO: why is the order different when dealing with netflix? if(!m_isAppCtxInitialized) { InitializeAppCtx(); @@ -161,9 +160,9 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { *f_ppiMediaKeySession = new CDMi::MediaKeySession(f_pbInitData, f_cbInitData, m_poAppContext.get(), !isNetflixPlayready); #endif } else { - *f_ppiMediaKeySession = new CDMi::MediaKeySession(f_pbInitData, f_cbInitData, f_pbCDMData, f_cbCDMData, m_poAppContext.get(), !isNetflixPlayready); + *f_ppiMediaKeySession = new CDMi::MediaKeySession(f_pbInitData, f_cbInitData, f_pbCDMData, f_cbCDMData, m_poAppContext.get(), !isNetflixPlayready); } - return CDMi_SUCCESS; + return CDMi_SUCCESS; } CDMi_RESULT SetSecureStopPublisherCert( const DRM_BYTE *f_pbPublisherCert, DRM_DWORD f_cbPublisherCert ) @@ -194,6 +193,21 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { return CDMi_S_FALSE; } + std::string GetDrmStorePath() + { + const uint32_t MAXLEN = 256; + char pathStr[MAXLEN]; + if (drmStore_.cchString >= MAXLEN) + return ""; + DRM_UTL_DemoteUNICODEtoASCII(drmStore_.pwszString, + pathStr, MAXLEN); + ((DRM_BYTE*)pathStr)[drmStore_.cchString] = 0; + PackedCharsToNative(pathStr, drmStore_.cchString + 1); + + return string(pathStr); + } + + CDMi_RESULT SetServerCertificate( const uint8_t *f_pbServerCertificate, uint32_t f_cbServerCertificate) { CDMi_RESULT cr = CDMi_SUCCESS; @@ -212,7 +226,6 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { CDMi_RESULT DestroyMediaKeySession(IMediaKeySession *f_piMediaKeySession) { SafeCriticalSection systemLock(drmAppContextMutex_); MediaKeySession * mediaKeySession = dynamic_cast(f_piMediaKeySession); - if ( mediaKeySession != nullptr ) { delete f_piMediaKeySession; @@ -223,8 +236,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { } return CDMi_SUCCESS; } - -// uint64_t GetDrmSystemTime() const override + uint64_t GetDrmSystemTime() const /* override */ { DRM_RESULT dr = DRM_SUCCESS; @@ -236,6 +248,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { dr = Drm_SecureTime_GetValue( ( DRM_APP_CONTEXT* ) m_poAppContext.get(), &oftSystemTime, &eClockType ); + if ( dr != DRM_SUCCESS ) { fprintf(stderr, "[%s:%d] Drm_SecureTime_GetValue failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); @@ -275,7 +288,6 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { return CDMi_SUCCESS; } -// std::string GetVersionExt() const override std::string GetVersionExt() const /* override */ { const uint32_t MAXLEN = 64; @@ -289,44 +301,27 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { return string(versionStr); } - std::string GetDrmStorePath() - { - const uint32_t MAXLEN = 256; - char pathStr[MAXLEN]; - if (drmStore_.cchString >= MAXLEN) - return ""; - DRM_UTL_DemoteUNICODEtoASCII(drmStore_.pwszString, - pathStr, MAXLEN); - ((DRM_BYTE*)pathStr)[drmStore_.cchString] = 0; - PackedCharsToNative(pathStr, drmStore_.cchString + 1); - - return string(pathStr); - } - -// uint32_t GetLdlSessionLimit() const override uint32_t GetLdlSessionLimit() const /* override */ { return ( uint32_t )DRM_MAX_NONCE_COUNT_PER_SESSION; } -// bool IsSecureStopEnabled() override bool IsSecureStopEnabled() /* override */ { return true; } -// CDMi_RESULT EnableSecureStop(bool enable) override CDMi_RESULT EnableSecureStop(bool enable) /* override */ { return CDMi_SUCCESS; } -// uint32_t ResetSecureStops() override uint32_t ResetSecureStops() /* override */ { return 0; } + /*Return a list of the current SecureStop sessions.*/ CDMi_RESULT GetSecureStopIds(uint8_t ids[], uint16_t idsLength, uint32_t & count) { SafeCriticalSection lock(drmAppContextMutex_); @@ -371,7 +366,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { SAFE_OEM_FREE( pidSessions ); return cr; - } + } /*Generate a SecureStop challenge to send to the server.*/ CDMi_RESULT GetSecureStop( @@ -496,6 +491,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { g_dstrDrmPath.pwszString = drmdir_; g_dstrDrmPath.cchString = rdir.length(); + // Store store location std::string store(m_storeLocation); drmStore_.pwszString = createDrmWchar(store); @@ -506,6 +502,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { g_dstrCDMDrmStoreName.cchString = store.length(); #endif + // Init revocation buffer. pbRevocationBuffer_ = new DRM_BYTE[REVOCATION_BUFFER_SIZE]; return CDMi_SUCCESS; @@ -522,6 +519,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { m_poAppContext.reset(new DRM_APP_CONTEXT); + // Init opaque buffer. appOpaqueBuffer = new DRM_BYTE[MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE]; appContextOpaqueBuffer_ = appOpaqueBuffer; @@ -599,6 +597,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { SafeCriticalSection lock(drmAppContextMutex_); // DRM_RESULT err = Drm_Platform_Initialize(nullptr); + DRM_RESULT err = CPRDrmPlatform::DrmPlatformInitialize(); if(DRM_FAILED(err)) @@ -738,6 +737,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { void OnSystemConfigurationAvailable(const WPEFramework::PluginHost::IShell * shell, const std::string& configline) { + #ifdef AML_SVP_PR string persistentPath = shell->PersistentPath(); string statePath = persistentPath + "state"; // To store rollback clock state etc @@ -766,6 +766,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { } else { fprintf(stderr, "[%s:%d] Error: could not set HOME variable. SecureStop functionality may not work!",__FUNCTION__,__LINE__); } + CreateSystemExt(); InitSystemExt(); @@ -800,4 +801,4 @@ static SystemFactoryType g_instance({"video/x-h264", "audio/mpeg"}); CDMi::ISystemFactory* GetSystemFactory() { fprintf(stderr,"#COMMON-OCDM# : %s: %d\n",__func__,__LINE__); return (&CDMi::g_instance); -} +} \ No newline at end of file From 50e3a6a28bafcb252ca1901892c8f5ddbacc1480 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Wed, 15 Jan 2025 21:11:11 +0000 Subject: [PATCH 23/37] update: OnSystemConfigurationAvailable() changes verified. --- MediaSystem.cpp | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/MediaSystem.cpp b/MediaSystem.cpp index 61318b3..504f6a2 100644 --- a/MediaSystem.cpp +++ b/MediaSystem.cpp @@ -738,35 +738,26 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { void OnSystemConfigurationAvailable(const WPEFramework::PluginHost::IShell * shell, const std::string& configline) { -#ifdef AML_SVP_PR - string persistentPath = shell->PersistentPath(); - string statePath = persistentPath + "state"; // To store rollback clock state etc - string storePath = persistentPath + "playready/storage"; - m_readDir = persistentPath + "playready"; - m_storeLocation = persistentPath + "playready/storage/drmstore"; - - WPEFramework::Core::Directory storeDir(storePath.c_str()); - storeDir.CreatePath(); - WPEFramework::Core::Directory stateDir(statePath.c_str()); - stateDir.Create(); -#else - Config config; config.FromString(configline); m_readDir = config.ReadDir.Value(); m_storeLocation = config.StoreLocation.Value(); - m_storeLocation = "/opt/drm/sample.hds"; - string statePath = config.HomePath.Value().c_str(); -#endif - fprintf(stderr,"#COMMON-OCDM# %s: %s: %d\n", statePath.c_str(),storePath.c_str(),__LINE__); - fprintf(stderr,"#COMMON-OCDM# %s: %s: %d\n", m_readDir.c_str(),m_storeLocation.c_str(),__LINE__); - if(!statePath.empty()) { - WPEFramework::Core::SystemInfo::SetEnvironment(_T("HOME"), statePath); + // svpGetDrmStoragePath(m_readDir, m_storeLocation); + m_readDir = "/opt/persistent/rdkservices/OCDM/playready/"; + m_storeLocation = "/opt/persistent/rdkservices/OCDM/playready/storage/drmstore"; + + WPEFramework::Core::Directory(m_readDir.c_str()).CreatePath(); + + string homePath = config.HomePath.Value(); + if(!homePath.empty()) { + WPEFramework::Core::SystemInfo::SetEnvironment(_T("HOME"), homePath.c_str()); } else { - fprintf(stderr, "[%s:%d] Error: could not set HOME variable. SecureStop functionality may not work!",__FUNCTION__,__LINE__); + fprintf(stderr, "[%s:%d] Error: could not set HOME variable. SecureStop functionality may not work!\n",__FUNCTION__,__LINE__); } + fprintf(stderr,"#COMMON-OCDM# %s: %s: %d\n", m_readDir.c_str(),m_storeLocation.c_str(),__LINE__); + CreateSystemExt(); InitSystemExt(); From b3bf102705e1e2acbe520b774fffc1a6629b120b Mon Sep 17 00:00:00 2001 From: kvfasil Date: Wed, 15 Jan 2025 21:40:44 +0000 Subject: [PATCH 24/37] update: cleanup. --- MediaSystem.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/MediaSystem.cpp b/MediaSystem.cpp index 504f6a2..4fc825a 100644 --- a/MediaSystem.cpp +++ b/MediaSystem.cpp @@ -49,7 +49,7 @@ using namespace std; extern DRM_CONST_STRING g_dstrDrmPath; -DRM_CONST_STRING g_dstrCDMDrmStoreName; //AML +DRM_CONST_STRING g_dstrCDMDrmStoreName; DRM_VOID *m_drmOemContext; using SafeCriticalSection = WPEFramework::Core::SafeSyncType; @@ -494,13 +494,11 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { // Store store location std::string store(m_storeLocation); - drmStore_.pwszString = createDrmWchar(store); - drmStore_.cchString = store.length(); + drmStore_.pwszString = createDrmWchar(store); //AML + drmStore_.cchString = store.length(); //AML -#ifdef AML_SVP_PR g_dstrCDMDrmStoreName.pwszString = createDrmWchar(store); g_dstrCDMDrmStoreName.cchString = store.length(); -#endif // Init revocation buffer. pbRevocationBuffer_ = new DRM_BYTE[REVOCATION_BUFFER_SIZE]; @@ -653,6 +651,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { delete [] pbRevocationBuffer_; delete [] drmdir_; + delete [] g_dstrCDMDrmStoreName.pwszString; delete [] drmStore_.pwszString; err = CPRDrmPlatform::DrmPlatformUninitialize(); From 2f75fd6ac213f0b0359412d0d2e322014f4d6388 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Wed, 15 Jan 2025 21:54:59 +0000 Subject: [PATCH 25/37] update: aligned and tested. --- MediaSystem.cpp | 37 ++++++++++++++++++++----------------- 1 file changed, 20 insertions(+), 17 deletions(-) diff --git a/MediaSystem.cpp b/MediaSystem.cpp index 4fc825a..2897544 100644 --- a/MediaSystem.cpp +++ b/MediaSystem.cpp @@ -510,6 +510,7 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { CDMi_RESULT InitializeAppCtx() { DRM_BYTE *appOpaqueBuffer = nullptr; + DRM_VOID *pDrmOemContext = NULL; if (m_poAppContext.get() != nullptr) { m_poAppContext.reset(); @@ -523,28 +524,30 @@ class PlayReady : public IMediaKeys, public IMediaKeysExt { appContextOpaqueBuffer_ = appOpaqueBuffer; ::memset(m_poAppContext.get(), 0, sizeof(DRM_APP_CONTEXT)); - DRM_RESULT err = Drm_Initialize(m_poAppContext.get(), nullptr, + + // svpGetDrmOEMContext(&pDrmOemContext); + DRM_RESULT err = Drm_Initialize(m_poAppContext.get(), pDrmOemContext, appOpaqueBuffer, MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE, - &drmStore_); + &g_dstrCDMDrmStoreName); + + if((err == DRM_E_SECURESTOP_STORE_CORRUPT) || \ + (err == DRM_E_SECURESTORE_CORRUPT) || \ + (err == DRM_E_DST_CORRUPTED)) { + + //if drmstore file is corrupted, remove it and init again, playready will create a new one + remove(GetDrmStorePath().c_str()); - if(err != DRM_SUCCESS) { - err = Drm_Initialize(m_poAppContext.get(), nullptr, + err = Drm_Initialize(m_poAppContext.get(), pDrmOemContext, appOpaqueBuffer, MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE, - &drmStore_ ); - if ( err != DRM_SUCCESS ) - { - fprintf(stderr, "[%s:%d] Drm_Initialize failed. 0x%X - %s",__FUNCTION__,__LINE__,err,DRM_ERR_NAME(err)); - int status = remove(GetDrmStorePath().c_str()); - if(status == 0) - fprintf(stderr," sample.hds File removal successful"); - else - fprintf(stderr,"sample.hds File removal not successful"); - m_poAppContext.reset(); - delete [] appOpaqueBuffer; - return CDMi_S_FALSE; - } + &g_dstrCDMDrmStoreName ); + } + + if (DRM_FAILED(err)) { + delete [] appOpaqueBuffer; + m_poAppContext.reset(); + return CDMi_S_FALSE; } ::memset(pbRevocationBuffer_, 0, REVOCATION_BUFFER_SIZE); From 18edd028ca30bb946af5dec1e005cef718e08b82 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Wed, 15 Jan 2025 22:37:57 +0000 Subject: [PATCH 26/37] update: tested. --- MediaSession.cpp | 99 +++++++++++++++++------------------------------- 1 file changed, 35 insertions(+), 64 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index e11fbdb..d84d7f7 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -32,9 +32,8 @@ using namespace WPEFramework; using SafeCriticalSection = Core::SafeSyncType; MODULE_NAME_DECLARATION(BUILD_REFERENCE); -WPEFramework::Core::CriticalSection prPlatformMutex_; + extern Core::CriticalSection drmAppContextMutex_; -WPEFramework::Core::CriticalSection prSessionMutex_; extern DRM_VOID *m_drmOemContext; extern DRM_CONST_STRING g_dstrCDMDrmStoreName; @@ -208,6 +207,11 @@ void Swap(uint8_t& lhs, uint8_t& rhs) const DRM_CONST_STRING *g_rgpdstrRights[1] = {&g_dstrDRM_RIGHT_PLAYBACK}; +// uint64_t MediaKeySession::mMaxResDecodePixels = 0; +// bool MediaKeySession::mMaxResDecodeSet = false; + +WPEFramework::Core::CriticalSection prPlatformMutex_; +WPEFramework::Core::CriticalSection prSessionMutex_; DRM_DWORD CPRDrmPlatform::m_dwInitRefCount = 0; void * MediaKeySession::sess = NULL; @@ -473,26 +477,21 @@ DRM_APP_CONTEXT * PlayreadySession::InitializeDRM(const DRM_CONST_STRING * pDRMS if (m_poAppContext == nullptr) { - fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); - ChkMem( m_pbPROpaqueBuf = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE) ); - ZEROMEM(m_pbPROpaqueBuf, MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE); - m_cbPROpaqueBuf = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; + ChkMem( m_pbPROpaqueBuf = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE) ); + ZEROMEM(m_pbPROpaqueBuf, MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE); + m_cbPROpaqueBuf = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; - ChkMem( m_poAppContext = (DRM_APP_CONTEXT * )Oem_MemAlloc( sizeof(DRM_APP_CONTEXT) ) ); - ZEROMEM( m_poAppContext, sizeof(DRM_APP_CONTEXT) ); + ChkMem( m_poAppContext = (DRM_APP_CONTEXT * )Oem_MemAlloc( sizeof(DRM_APP_CONTEXT) ) ); + ZEROMEM( m_poAppContext, sizeof(DRM_APP_CONTEXT) ); /* pdrmOemContext this should be valid for BRCM , others it could be null */ // svpGetDrmOEMContext(&pdrmOemContext); - // Initialize DRM app context. - dr = Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName); - if (dr != DRM_SUCCESS) - { - ocdm_log( "%s:%d drmstore corrrupt, delete it !!!!\n", __FUNCTION__, __LINE__); - //if drmstore file is corrupted, remove it and init again, playready will create a new one + dr = Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName); + if (dr != DRM_SUCCESS) + { remove(GetDrmStorePath().c_str()); - ChkDR(Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName)); - } - fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); + ChkDR(Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName)); + } } else { @@ -559,56 +558,28 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD std::string initData(reinterpret_cast(f_pbInitData), f_cbInitData); std::string playreadyInitData; -// ChkBOOL(m_eKeyState == KEY_CLOSED, DRM_E_INVALIDARG); - -// mMaxResDecodePixels = 0; -// mMaxResDecodeSet = false; - -///////////////////////////////////////////////////////////////////////////////////////// - // ChkMem( m_pbOpaqueBuffer = (DRM_BYTE *)Oem_MemAlloc(MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE)); //aml - // ZEROMEM(m_pbOpaqueBuffer, MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE); - // m_cbOpaqueBuffer = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; //aml - - // ChkMem( m_poAppContext = (DRM_APP_CONTEXT *)Oem_MemAlloc(SIZEOF(DRM_APP_CONTEXT))); //aml - // ZEROMEM( m_poAppContext, sizeof(DRM_APP_CONTEXT) ); - - // /* pdrmOemContext this should be valid for BRCM , others it could be null */ - // // svpGetDrmOEMContext(&pdrmOemContext); - // // Initialize DRM app context. - // dr = Drm_Initialize(m_poAppContext, nullptr, m_pbOpaqueBuffer, m_cbOpaqueBuffer, &g_dstrCDMDrmStoreName); //aml - // if (dr != DRM_SUCCESS) - // { - // ocdm_log( "%s:%d drmstore corrrupt, delete it !!!!\n", __FUNCTION__, __LINE__); - // //if drmstore file is corrupted, remove it and init again, playready will create a new one - // remove(GetDrmStorePath().c_str()); - // ChkDR(Drm_Initialize(m_poAppContext, nullptr, m_pbOpaqueBuffer, m_cbOpaqueBuffer, &g_dstrCDMDrmStoreName)); - // } - // if (m_poAppContext == nullptr) { //RTK if (m_poAppContext) { fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); m_poAppContext = InitializeDRM(&g_dstrCDMDrmStoreName); } -/////////////////////////////////////////////////////////////////////////////////////////// - if (DRM_REVOCATION_IsRevocationSupported()) { - ChkMem(m_pbRevocationBuffer = (DRM_BYTE *)Oem_MemAlloc(REVOCATION_BUFFER_SIZE)); - - ChkDR(Drm_Revocation_SetBuffer(m_poAppContext, - m_pbRevocationBuffer, - REVOCATION_BUFFER_SIZE)); - } + if (DRM_REVOCATION_IsRevocationSupported()) { + ChkMem(m_pbRevocationBuffer = (DRM_BYTE *)Oem_MemAlloc(REVOCATION_BUFFER_SIZE)); - // Generate a random media session ID. - ChkDR(Oem_Random_GetBytes(nullptr, (DRM_BYTE *)&oSessionID, SIZEOF(oSessionID))); - ZEROMEM(m_rgchSessionID, SIZEOF(m_rgchSessionID)); + ChkDR(Drm_Revocation_SetBuffer(m_poAppContext, + m_pbRevocationBuffer, + REVOCATION_BUFFER_SIZE)); + } + + ChkDR(Oem_Random_GetBytes(nullptr, (DRM_BYTE *)&oSessionID, SIZEOF(oSessionID))); + ZEROMEM(m_rgchSessionID, SIZEOF(m_rgchSessionID)); - // Store the generated media session ID in base64 encoded form. - ChkDR(DRM_B64_EncodeA((DRM_BYTE *)&oSessionID, - SIZEOF(oSessionID), - m_rgchSessionID, - &cchEncodedSessionID, - 0)); + ChkDR(DRM_B64_EncodeA((DRM_BYTE *)&oSessionID, + SIZEOF(oSessionID), + m_rgchSessionID, + &cchEncodedSessionID, + 0)); // The current state MUST be KEY_INIT otherwise error out. ChkBOOL(m_eKeyState == KEY_INIT, DRM_E_INVALIDARG); @@ -617,10 +588,10 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD playreadyInitData = initData; } - ChkDR(Drm_Content_SetProperty(m_poAppContext, - DRM_CSP_AUTODETECT_HEADER, - reinterpret_cast(playreadyInitData.data()), - playreadyInitData.size())); + ChkDR(Drm_Content_SetProperty(m_poAppContext, + DRM_CSP_AUTODETECT_HEADER, + reinterpret_cast(playreadyInitData.data()), + playreadyInitData.size())); #ifdef PR_4_4 //temporary hack to allow time based licenses @@ -1162,4 +1133,4 @@ CDMi_RESULT MediaKeySession::ReleaseClearContent( } -} // namespace CDMi +} // namespace CDMi \ No newline at end of file From 1833851f80e123246726a6f876e775d22e17b471 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 16 Jan 2025 05:39:16 +0000 Subject: [PATCH 27/37] update: tested. --- MediaSession.cpp | 50 +++++++++++++++++++++++++++++++----------------- 1 file changed, 32 insertions(+), 18 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index d84d7f7..e174ccd 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -537,26 +537,36 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD , m_decryptInited(false) , m_bDRMInitializedLocally(false) { + fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); memset(&levels_, 0, sizeof(levels_)); //need to comment later. - DRM_RESULT dr = DRM_SUCCESS; - DRM_ID oSessionID; - DRM_CONST_STRING dstrWRMHEADER = DRM_EMPTY_DRM_STRING; - - DRM_DWORD cchEncodedSessionID = SIZEOF(m_rgchSessionID); + DRM_RESULT dr = DRM_SUCCESS; + DRM_ID oSessionID = DRM_ID_EMPTY; + DRM_CONST_STRING dstrWRMHEADER = DRM_EMPTY_DRM_STRING; - ocdm_log("Initializing SVP context for client side\n"); - gst_svp_ext_get_context(&m_pSVPContext, Client, m_rpcID); + DRM_DWORD cchEncodedSessionID = SIZEOF(m_rgchSessionID); + +#ifdef USE_SVP + gst_svp_ext_get_context(&m_pSVPContext, Client, 0); + +// m_stSecureBuffInfo.bCreateSecureMemRegion = true; +// m_stSecureBuffInfo.SecureMemRegionSize = 512 * 1024; +// +// if( 0 != svp_allocate_secure_buffers(m_pSVPContext, (void**)&m_stSecureBuffInfo, nullptr, nullptr, m_stSecureBuffInfo.SecureMemRegionSize)) +// { +// fprintf(stderr, "[%s:%d] secure memory, allocate failed [%d]",__FUNCTION__,__LINE__, m_stSecureBuffInfo.SecureMemRegionSize); +// m_stSecureBuffInfo.SecureMemRegionSize = 0; +// } +#endif - fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); m_oDecryptContext = new DRM_DECRYPT_CONTEXT; memset(m_oDecryptContext, 0, sizeof(DRM_DECRYPT_CONTEXT)); m_oDecryptContext2 = new DRM_DECRYPT_CONTEXT; memset(m_oDecryptContext2, 0, sizeof(DRM_DECRYPT_CONTEXT)); - // FIXME: Change the interface of this method? Not sure why the win32 bondage is still so popular. - std::string initData(reinterpret_cast(f_pbInitData), f_cbInitData); - std::string playreadyInitData; + + std::string initData(reinterpret_cast(f_pbInitData), f_cbInitData); + std::string playreadyInitData; // if (m_poAppContext == nullptr) { //RTK if (m_poAppContext) { @@ -581,17 +591,21 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD &cchEncodedSessionID, 0)); - // The current state MUST be KEY_INIT otherwise error out. - ChkBOOL(m_eKeyState == KEY_INIT, DRM_E_INVALIDARG); + if (!parsePlayreadyInitializationData(initData, &playreadyInitData)) { + playreadyInitData = initData; + } - if (!parsePlayreadyInitializationData(initData, &playreadyInitData)) { - playreadyInitData = initData; - } + mDrmHeader.resize( playreadyInitData.size() ); + ::memcpy( &mDrmHeader[ 0 ], + reinterpret_cast(playreadyInitData.data()), + playreadyInitData.size() ); ChkDR(Drm_Content_SetProperty(m_poAppContext, DRM_CSP_AUTODETECT_HEADER, - reinterpret_cast(playreadyInitData.data()), - playreadyInitData.size())); + &mDrmHeader[ 0 ], + mDrmHeader.size()) ); + + DRM_CONST_DSTR_FROM_PB( &dstrWRMHEADER, &mDrmHeader[ 0 ], mDrmHeader.size() ); #ifdef PR_4_4 //temporary hack to allow time based licenses From df31b12c7ba8b0df10b3773ebf414d2579543698 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 16 Jan 2025 06:29:41 +0000 Subject: [PATCH 28/37] update: playreadyGenerateKeyRequest() changes verified. --- MediaSession.cpp | 210 +++++++++++++++++++++++++---------------------- 1 file changed, 114 insertions(+), 96 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index e174ccd..8985d95 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -513,7 +513,7 @@ DRM_APP_CONTEXT * PlayreadySession::InitializeDRM(const DRM_CONST_STRING * pDRMS MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitData, const uint8_t *f_pbCDMData, uint32_t f_cbCDMData, DRM_APP_CONTEXT * poAppContext, bool initiateChallengeGeneration /* = false */) : m_pbRevocationBuffer(nullptr) - , m_eKeyState(KEY_INIT) + , m_eKeyState(KEY_CLOSED) , m_pbChallenge(nullptr) , m_cbChallenge(0) , m_pchSilentURL(nullptr) @@ -540,6 +540,11 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); memset(&levels_, 0, sizeof(levels_)); //need to comment later. + m_oDecryptContext = new DRM_DECRYPT_CONTEXT; + memset(m_oDecryptContext, 0, sizeof(DRM_DECRYPT_CONTEXT)); + m_oDecryptContext2 = new DRM_DECRYPT_CONTEXT; + memset(m_oDecryptContext2, 0, sizeof(DRM_DECRYPT_CONTEXT)); + DRM_RESULT dr = DRM_SUCCESS; DRM_ID oSessionID = DRM_ID_EMPTY; DRM_CONST_STRING dstrWRMHEADER = DRM_EMPTY_DRM_STRING; @@ -548,29 +553,28 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD #ifdef USE_SVP gst_svp_ext_get_context(&m_pSVPContext, Client, 0); +/* + m_stSecureBuffInfo.bCreateSecureMemRegion = true; + m_stSecureBuffInfo.SecureMemRegionSize = 512 * 1024; -// m_stSecureBuffInfo.bCreateSecureMemRegion = true; -// m_stSecureBuffInfo.SecureMemRegionSize = 512 * 1024; -// -// if( 0 != svp_allocate_secure_buffers(m_pSVPContext, (void**)&m_stSecureBuffInfo, nullptr, nullptr, m_stSecureBuffInfo.SecureMemRegionSize)) -// { -// fprintf(stderr, "[%s:%d] secure memory, allocate failed [%d]",__FUNCTION__,__LINE__, m_stSecureBuffInfo.SecureMemRegionSize); -// m_stSecureBuffInfo.SecureMemRegionSize = 0; -// } + if( 0 != svp_allocate_secure_buffers(m_pSVPContext, (void**)&m_stSecureBuffInfo, nullptr, nullptr, m_stSecureBuffInfo.SecureMemRegionSize)) + { + fprintf(stderr, "[%s:%d] secure memory, allocate failed [%d]",__FUNCTION__,__LINE__, m_stSecureBuffInfo.SecureMemRegionSize); + m_stSecureBuffInfo.SecureMemRegionSize = 0; + } +*/ #endif - m_oDecryptContext = new DRM_DECRYPT_CONTEXT; - memset(m_oDecryptContext, 0, sizeof(DRM_DECRYPT_CONTEXT)); - m_oDecryptContext2 = new DRM_DECRYPT_CONTEXT; - memset(m_oDecryptContext2, 0, sizeof(DRM_DECRYPT_CONTEXT)); - - std::string initData(reinterpret_cast(f_pbInitData), f_cbInitData); std::string playreadyInitData; + ChkBOOL(m_eKeyState == KEY_CLOSED, DRM_E_INVALIDARG); + +// mMaxResDecodePixels = 0; +// mMaxResDecodeSet = false; + // if (m_poAppContext == nullptr) { //RTK if (m_poAppContext) { - fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); m_poAppContext = InitializeDRM(&g_dstrCDMDrmStoreName); } @@ -612,45 +616,44 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD ( DRM_REINTERPRET_CAST( DRM_APP_CONTEXT_INTERNAL, m_poAppContext ) )->fClockSet = TRUE; #endif - // DRM_CONST_DSTR_FROM_PB( &dstrWRMHEADER, &mDrmHeader[ 0 ], mDrmHeader.size() ); - - // ChkDR( Header_GetInfo( &dstrWRMHEADER, - // &m_eHeaderVersion, - // &m_pdstrHeaderKIDs, - // &m_cHeaderKIDs ) ); + DRM_CONST_DSTR_FROM_PB( &dstrWRMHEADER, &mDrmHeader[ 0 ], mDrmHeader.size() ); - // for( DRM_DWORD idx = 0; idx < m_cHeaderKIDs; idx++ ) - // { - // KeyId kid , kid2; - // DRM_DWORD cBytes = DRM_ID_SIZE; - // DRM_DWORD cBytes2 = DRM_ID_SIZE; + ChkDR( Header_GetInfo( &dstrWRMHEADER, + &m_eHeaderVersion, + &m_pdstrHeaderKIDs, + &m_cHeaderKIDs ) ); - // DRM_RESULT dr = DRM_B64_DecodeW( &m_pdstrHeaderKIDs[ idx ], &cBytes, kid.getmBytes(), 0 ); - // if ( dr == DRM_SUCCESS ) - // { - // kid.setKeyIdOrder(KeyId::KEYID_ORDER_GUID_LE); - // } + for( DRM_DWORD idx = 0; idx < m_cHeaderKIDs; idx++ ) + { + KeyId kid , kid2; + DRM_DWORD cBytes = DRM_ID_SIZE; + DRM_DWORD cBytes2 = DRM_ID_SIZE; + + DRM_RESULT dr = DRM_B64_DecodeW( &m_pdstrHeaderKIDs[ idx ], &cBytes, kid.getmBytes(), 0 ); + if ( dr == DRM_SUCCESS ) + { + kid.setKeyIdOrder(KeyId::KEYID_ORDER_GUID_LE); + } + + DRM_RESULT dr2 = DRM_B64_DecodeW( &m_pdstrHeaderKIDs[ idx ], &cBytes2, kid2.getmBytes(), 0 ); + if ( dr2 == DRM_SUCCESS ) + { + kid2.setKeyIdOrder(KeyId::KEYID_ORDER_GUID_LE); + } + } - // DRM_RESULT dr2 = DRM_B64_DecodeW( &m_pdstrHeaderKIDs[ idx ], &cBytes2, kid2.getmBytes(), 0 ); - // if ( dr2 == DRM_SUCCESS ) - // { - // kid2.setKeyIdOrder(KeyId::KEYID_ORDER_GUID_LE); - // } - // } + m_eKeyState = KEY_INIT; - // m_eKeyState = KEY_INIT; +ErrorExit: - // The current state MUST be KEY_INIT otherwise error out. - ChkBOOL(m_eKeyState == KEY_INIT, DRM_E_INVALIDARG); - m_secCount++; - return; + if (DRM_FAILED(dr)) + { + m_eKeyState = KEY_ERROR; + fprintf(stderr, "[%s:%d] Playready initialization error: 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + } -ErrorExit: - if (DRM_FAILED(dr)) { - const DRM_CHAR* description; - DRM_ERR_GetErrorNameFromCode(dr, &description); - ocdm_log("playready error1: %s\n", description); - } + m_secCount++; + return; } @@ -665,12 +668,26 @@ MediaKeySession::~MediaKeySession(void) { ocdm_log("Destructing PlayReady Session [%p]\n", this); } +const char* MediaKeySession::printGuid(KeyId &keyId) +{ + if (keyId.getKeyIdOrder() == KeyId::KEYID_ORDER_UUID_BE) + keyId.ToggleFormat(); + return keyId.B64Str(); +} + +const char* MediaKeySession::printUuid(KeyId &keyId) +{ + if (keyId.getKeyIdOrder() == KeyId::KEYID_ORDER_GUID_LE) + keyId.ToggleFormat(); + return keyId.B64Str(); +} + const char *MediaKeySession::GetSessionId(void) const { return m_rgchSessionID; } const char *MediaKeySession::GetKeySystem(void) const { - return NYI_KEYSYSTEM; // FIXME : replace with keysystem and test. + return NYI_KEYSYSTEM; } DRM_RESULT DRM_CALL MediaKeySession::_PolicyCallback( @@ -701,6 +718,10 @@ bool MediaKeySession::playreadyGenerateKeyRequest() { DRM_RESULT dr = DRM_SUCCESS; DRM_DWORD cchSilentURL = 0; + SAFE_OEM_FREE( m_pbChallenge ); + SAFE_OEM_FREE( m_pchSilentURL ); + + m_cbChallenge = 0; #ifdef PR_4_4 dr = Drm_Reader_Bind(m_poAppContext, @@ -711,49 +732,44 @@ bool MediaKeySession::playreadyGenerateKeyRequest() { m_oDecryptContext); #endif - // FIXME : Check add case Play rights already acquired - // Try to figure out the size of the license acquisition - // challenge to be returned. + + ChkDR(Drm_Content_SetProperty(m_poAppContext, + DRM_CSP_AUTODETECT_HEADER, + &mDrmHeader[ 0 ], + mDrmHeader.size()) ); + dr = Drm_LicenseAcq_GenerateChallenge(m_poAppContext, g_rgpdstrRights, sizeof(g_rgpdstrRights) / sizeof(DRM_CONST_STRING *), - NULL, + nullptr, !m_customData.empty() ? m_customData.c_str() : nullptr, m_customData.size(), - NULL, + nullptr, &cchSilentURL, - NULL, - NULL, -#ifdef PR_4_4 + nullptr, + nullptr, m_pbChallenge, &m_cbChallenge, - NULL); -#else - NULL, - &m_cbChallenge); -#endif - if (dr == DRM_E_NO_URL) { - cchSilentURL = 0; + &m_oBatchID ); + + if ( dr == DRM_E_NO_URL ) + { dr = Drm_LicenseAcq_GenerateChallenge(m_poAppContext, g_rgpdstrRights, sizeof(g_rgpdstrRights) / sizeof(DRM_CONST_STRING *), - NULL, + nullptr, !m_customData.empty() ? m_customData.c_str() : nullptr, - m_customData.size(), - NULL, - NULL, - NULL, - NULL, -#ifdef PR_4_4 + m_customData.size() , + nullptr, + nullptr, // null pointer to buffer size + nullptr, + nullptr, m_pbChallenge, &m_cbChallenge, - NULL); -#else - NULL, - &m_cbChallenge); -#endif + &m_oBatchID ); } - if (dr == DRM_E_BUFFERTOOSMALL) { + + if (dr == DRM_E_BUFFERTOOSMALL) { SAFE_OEM_FREE(m_pchSilentURL); ChkMem(m_pchSilentURL = (DRM_CHAR *)Oem_MemAlloc(cchSilentURL + 1)); ZEROMEM(m_pchSilentURL, cchSilentURL + 1); @@ -764,45 +780,47 @@ bool MediaKeySession::playreadyGenerateKeyRequest() { ChkMem(m_pbChallenge = (DRM_BYTE *)Oem_MemAlloc(m_cbChallenge)); dr = DRM_SUCCESS; - } else { + } + else + { ChkDR(dr); } - ocdm_log("%s\n", m_customData.empty() ? m_customData.c_str() : nullptr); - // Supply a buffer to receive the license acquisition challenge. ChkDR(Drm_LicenseAcq_GenerateChallenge(m_poAppContext, g_rgpdstrRights, sizeof(g_rgpdstrRights) / sizeof(DRM_CONST_STRING *), NULL, !m_customData.empty() ? m_customData.c_str() : nullptr, m_customData.size(), - cchSilentURL > 0 ? m_pchSilentURL : NULL, - cchSilentURL > 0 ? &cchSilentURL: NULL, + m_pchSilentURL, + cchSilentURL ? &cchSilentURL : nullptr, nullptr, nullptr, m_pbChallenge, -#ifdef PR_4_4 &m_cbChallenge, - nullptr)); -#else - &m_cbChallenge)); -#endif + &m_oBatchID ) ); m_eKeyState = KEY_PENDING; + fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); if (m_piCallback) - m_piCallback->OnKeyMessage((const uint8_t *) m_pbChallenge, m_cbChallenge, (char *)m_pchSilentURL); - return true; + m_piCallback->OnKeyMessage((const uint8_t *) m_pbChallenge, m_cbChallenge, + m_pchSilentURL != NULL ? (char *)m_pchSilentURL : "" ); ErrorExit: if (DRM_FAILED(dr)) { - const DRM_CHAR* description; - DRM_ERR_GetErrorNameFromCode(dr, &description); - ocdm_log("playready error2: %s\n", description); - if (m_piCallback) - m_piCallback->OnKeyMessage((const uint8_t *) "", 0, ""); + fprintf(stderr, "[%s:%d] failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + + if(m_piCallback) + { + m_piCallback->OnError( 0, CDMi_S_FALSE, "KeyError" ); + m_piCallback->OnKeyStatusUpdate(MapDrToKeyMessage(dr), nullptr, 0); + m_piCallback->OnKeyStatusesUpdated(); + } + m_eKeyState = KEY_ERROR; } - return false; + + return ( dr == DRM_SUCCESS ); } CDMi_RESULT MediaKeySession::Load(void) { From acdb87210b16b8ed4259f75e88ce1ba5fea59cba Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 16 Jan 2025 06:39:31 +0000 Subject: [PATCH 29/37] update: aligned and tested. --- MediaSession.cpp | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index 8985d95..1aef796 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -769,15 +769,19 @@ bool MediaKeySession::playreadyGenerateKeyRequest() { &m_oBatchID ); } - if (dr == DRM_E_BUFFERTOOSMALL) { - SAFE_OEM_FREE(m_pchSilentURL); - ChkMem(m_pchSilentURL = (DRM_CHAR *)Oem_MemAlloc(cchSilentURL + 1)); - ZEROMEM(m_pchSilentURL, cchSilentURL + 1); - - // Allocate buffer that is sufficient to store the license acquisition - // challenge. - if (m_cbChallenge > 0) - ChkMem(m_pbChallenge = (DRM_BYTE *)Oem_MemAlloc(m_cbChallenge)); + if (dr == DRM_E_BUFFERTOOSMALL) + { + if (cchSilentURL > 0) + { + ChkMem( m_pchSilentURL = (DRM_CHAR * )Oem_MemAlloc(cchSilentURL + 1)); + ZEROMEM( m_pchSilentURL, cchSilentURL + 1 ); + } + + if ( m_cbChallenge > 0 ) + { + ChkMem( m_pbChallenge = (DRM_BYTE * )Oem_MemAlloc( m_cbChallenge + 1 ) ); + ZEROMEM( m_pbChallenge, m_cbChallenge + 1 ); + } dr = DRM_SUCCESS; } From 8fca67afac3e76c7d7ebf3700a5c098982465b2b Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 16 Jan 2025 07:00:15 +0000 Subject: [PATCH 30/37] update: PersistentLicenseCheck() added. --- MediaSession.cpp | 162 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 159 insertions(+), 3 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index 1aef796..65a890d 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -702,12 +702,13 @@ DRM_RESULT DRM_CALL MediaKeySession::_PolicyCallback( } void MediaKeySession::Run(const IMediaKeySessionCallback *f_piMediaKeySessionCallback) { - if (f_piMediaKeySessionCallback) { m_piCallback = const_cast(f_piMediaKeySessionCallback); if (mInitiateChallengeGeneration) { - playreadyGenerateKeyRequest(); + if ( CDMi_SUCCESS != PersistentLicenseCheck() ) { + playreadyGenerateKeyRequest(); + } } } else { m_piCallback = nullptr; @@ -732,7 +733,6 @@ bool MediaKeySession::playreadyGenerateKeyRequest() { m_oDecryptContext); #endif - ChkDR(Drm_Content_SetProperty(m_poAppContext, DRM_CSP_AUTODETECT_HEADER, &mDrmHeader[ 0 ], @@ -831,6 +831,162 @@ CDMi_RESULT MediaKeySession::Load(void) { return CDMi_S_FALSE; } +/*Set KeyId property which will be used by the Reader_Bind during license searching*/ +CDMi_RESULT MediaKeySession::SetKeyIdProperty( const DRM_WCHAR *f_rgwchEncodedKid, DRM_DWORD f_cchEncodedKid ){ + DRM_RESULT err = Drm_Content_SetProperty( + m_poAppContext, + DRM_CSP_AUTODETECT_HEADER, + (DRM_BYTE*)f_rgwchEncodedKid, + f_cchEncodedKid * sizeof( DRM_WCHAR ) ); + + if (DRM_FAILED(err)) { + fprintf(stderr, "[%s:%d] Drm_Content_SetProperty DRM_CSP_AUTODETECT_HEADER failed. 0x%08X - %s",__FUNCTION__,__LINE__,static_cast(err),DRM_ERR_NAME(err)); + return CDMi_FAIL; + } + + return CDMi_SUCCESS; +} + +/*Converting KeyId into base64-encoded format*/ +CDMi_RESULT MediaKeySession::SetKeyIdProperty( KeyId & f_rKeyId ){ + DRM_WCHAR rgwchEncodedKid[CCH_BASE64_EQUIV(DRM_ID_SIZE)]= {0}; + DRM_DWORD cchEncodedKid = CCH_BASE64_EQUIV(DRM_ID_SIZE); + + if ( f_rKeyId.getKeyIdOrder() == KeyId::KEYID_ORDER_UUID_BE ) + { + f_rKeyId.ToggleFormat(); + } + + DRM_RESULT err = DRM_B64_EncodeW( f_rKeyId.getmBytes(), DRM_ID_SIZE, + rgwchEncodedKid, &cchEncodedKid, 0); + + if (DRM_FAILED(err)) { + fprintf(stderr, "[%s:%d] DRM_B64_EncodeW failed. 0x%08X - %s",__FUNCTION__,__LINE__,static_cast(err),DRM_ERR_NAME(err)); + return CDMi_FAIL; + } + return SetKeyIdProperty( rgwchEncodedKid, cchEncodedKid ); +} + +/*handles all the licenses in the response using Drm_LicenseAcq_ProcessResponse().*/ +DRM_RESULT MediaKeySession::ProcessLicenseResponse( + DRM_PROCESS_LIC_RESPONSE_FLAG f_eResponseFlag, + const DRM_BYTE *f_pbResponse, + DRM_DWORD f_cbResponse, + DRM_LICENSE_RESPONSE *f_pLiceneResponse ) { + DRM_RESULT dr = DRM_SUCCESS; + + dr = Drm_LicenseAcq_ProcessResponse( + m_poAppContext, + f_eResponseFlag, + f_pbResponse, + f_cbResponse, + f_pLiceneResponse ); + + if ( dr == DRM_E_LICACQ_TOO_MANY_LICENSES ) + { + DRM_DWORD cLicenses = f_pLiceneResponse->m_cAcks; + f_pLiceneResponse->m_pAcks = ( DRM_LICENSE_ACK * )Oem_MemAlloc( cLicenses * sizeof( DRM_LICENSE_ACK ) ); + f_pLiceneResponse->m_cMaxAcks = cLicenses; + + dr = Drm_LicenseAcq_ProcessResponse( + m_poAppContext, + f_eResponseFlag, + f_pbResponse, + f_cbResponse, + f_pLiceneResponse ); + } + return dr; +} + +CDMi_RESULT MediaKeySession::PersistentLicenseCheck() { +#ifdef NO_PERSISTENT_LICENSE_CHECK + // DELIA-51437: The Webkit EME implementation used by OTT apps + // such as Amazon and YouTube fails when the key is usable from + // just the init data. Webkit is expecting a license request + // message and the lack of this message prevents the session from + // loading correctly. + // + // The EME concept of a persistent session uses the Session Id to + // reload a session, not the raw Key ID. We do not current + // support that type of session in the OCDM. Apps wishing to use + // persistent keys should directly link to PR4 or the OCDM should + // be rewritten to use PR4's CDMI API + // (modules/cdmi/real/drmcdmireal.c). + fprintf(stderr, "\n PersistentLicenseCheck: skipping persistent check\n"); + return CDMi_S_FALSE; +#else + DRM_RESULT dr = DRM_SUCCESS; + DRM_CONTENT_SET_PROPERTY eContentPropertyType = DRM_CSP_HEADER_NOT_SET; + + if ( !mDrmHeader.size() ) { + fprintf(stderr, "[%s:%d] mDrmHeader not set",__FUNCTION__,__LINE__); + return CDMi_FAIL; + } + if ( m_pdstrHeaderKIDs == NULL || m_cHeaderKIDs == 0 ){ + fprintf(stderr, "[%s:%d] key ids not set",__FUNCTION__,__LINE__); + return CDMi_FAIL; + } + + if ( m_eHeaderVersion == DRM_HEADER_VERSION_4_2 ) + eContentPropertyType = DRM_CSP_V4_2_HEADER; + else if ( m_eHeaderVersion == DRM_HEADER_VERSION_4_3 ) + eContentPropertyType = DRM_CSP_V4_3_HEADER; + else{ + eContentPropertyType = DRM_CSP_AUTODETECT_HEADER; + } + + for( DRM_DWORD idx = 0; idx < m_cHeaderKIDs; idx++ ){ + + KeyId keyId; + keyId.keyDecode(m_pdstrHeaderKIDs[ idx ]); + keyId.setKeyIdOrder(KeyId::KEYID_ORDER_GUID_LE); + + DECRYPT_CONTEXT decryptContext; + + if ( CDMi_SUCCESS != SetKeyIdProperty( m_pdstrHeaderKIDs[idx].pwszString, + m_pdstrHeaderKIDs[idx].cchString ) ) { + fprintf(stderr, "[%s:%d] SetKeyIdProperty failed. %s",__FUNCTION__,__LINE__,printGuid(keyId)); + ChkDR( DRM_E_FAIL ); + } + + decryptContext = NEW_DECRYPT_CONTEXT(); + + dr = ReaderBind( + g_rgpdstrRights, + NO_OF(g_rgpdstrRights), + _PolicyCallback, + &m_playreadyLevels, + &(decryptContext->oDrmDecryptContext) ); + if ( DRM_FAILED( dr ) ){ + ChkDR( dr ); + } + + decryptContext->keyId = keyId; + m_DecryptContextVector.push_back(decryptContext); + } + +ErrorExit: + + if ( DRM_FAILED( dr ) ){ + CloseDecryptContexts(); + return CDMi_FAIL; + } + + if ( m_piCallback ) + { + for (DECRYPT_CONTEXT &p : m_DecryptContextVector) + { + m_piCallback->OnKeyStatusUpdate(MapDrToKeyMessage( dr ), p->keyId.getmBytes(), DRM_ID_SIZE); + } + m_piCallback->OnKeyStatusesUpdated(); + } + + m_eKeyState = KEY_READY; + + return CDMi_SUCCESS; +#endif +} + void MediaKeySession::SetParameter(const uint8_t * data, const uint32_t length) { //ocdm_log("set cbcs parameter\n"); } From cfc45f757f7009246b4c4fb2b36b2b69907e74c4 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 16 Jan 2025 07:12:45 +0000 Subject: [PATCH 31/37] update: tested. --- MediaSession.cpp | 94 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/MediaSession.cpp b/MediaSession.cpp index 65a890d..b73189c 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -987,6 +987,100 @@ CDMi_RESULT MediaKeySession::PersistentLicenseCheck() { #endif } +// Allow persistent PlayReady licenses to be used in a temporary +// session. +// +// Ideally, the license server would only return temporary licenses +// and would could block all persistent license with the +// `DRM_PROCESS_LIC_RESPONSE_FLAG` value of +// `DRM_PROCESS_LIC_RESPONSE_BLOCK_PERSISTENT_LICENSES`. +// +// Instead, we allow persistent licenses to be used but attempt to +// clean them up when the session closes. +void MediaKeySession::SaveTemporaryPersistentLicenses(const DRM_LICENSE_RESPONSE* f_poLicenseResponse) { + + fprintf(stderr, "\n SaveTemporaryPersistentLicenses: response has persistent licenses: %s", + f_poLicenseResponse->m_fHasPersistentLicenses ? "true" : "false"); + + if (!f_poLicenseResponse->m_fHasPersistentLicenses) { + return; + } + + // We know there are persistent license but not which ones. Save + // them all for deletion when we close a session. + for (DRM_DWORD i = 0; i < f_poLicenseResponse->m_cAcks; ++i) { + const DRM_LICENSE_ACK *pLicenseAck = nullptr; + + pLicenseAck = f_poLicenseResponse->m_pAcks != nullptr + ? &f_poLicenseResponse->m_pAcks[ i ] : &f_poLicenseResponse->m_rgoAcks[ i ]; + + if ( DRM_SUCCEEDED( pLicenseAck->m_dwResult ) ) { + m_oPersistentLicenses.emplace_back(pLicenseAck->m_oKID, pLicenseAck->m_oLID); + } + } +} + +void MediaKeySession::DeleteTemporaryPersistentLicenses() { + DRM_RESULT dr = DRM_SUCCESS; + DRM_CONST_STRING dstrKID = DRM_EMPTY_DRM_STRING; + DRM_CONST_STRING dstrLID = DRM_EMPTY_DRM_STRING; + DRM_DWORD cbstrKID = 0; + DRM_DWORD cLicDeleted = 0; + + fprintf(stderr, "\n DeleteTemporaryPersistentLicenses: deleting %zd possibly persistent licenses", + m_oPersistentLicenses.size()); + + /* Allocate strKID buffer */ + cbstrKID = CCH_BASE64_EQUIV( sizeof( DRM_ID ) ) * sizeof( DRM_WCHAR ); + ChkMem( dstrKID.pwszString = (DRM_WCHAR *) Oem_MemAlloc( cbstrKID ) ); + dstrKID.cchString = CCH_BASE64_EQUIV( sizeof( DRM_ID ) ); + + ChkMem( dstrLID.pwszString = (DRM_WCHAR *) Oem_MemAlloc( cbstrKID ) ); + dstrLID.cchString = CCH_BASE64_EQUIV( sizeof( DRM_ID ) ); + + for (const auto& pair: m_oPersistentLicenses) { + + /* Convert KID to string */ + dr = DRM_B64_EncodeW( + (DRM_BYTE*)&pair.first, + sizeof( DRM_ID ), + (DRM_WCHAR*)dstrKID.pwszString, + &dstrKID.cchString, + DRM_BASE64_ENCODE_NO_FLAGS ); + + if (DRM_FAILED(dr)) { + fprintf(stderr, "\n DeleteTemporaryPersistentLicenses: DRM_B64_EncodeW failed for KID: 0x%08X", dr); + continue; + } + + /* Convert LID to string */ + dr = DRM_B64_EncodeW( + (DRM_BYTE*)&pair.second, + sizeof( DRM_ID ), + (DRM_WCHAR*)dstrLID.pwszString, + &dstrKID.cchString, + DRM_BASE64_ENCODE_NO_FLAGS ); + + if (DRM_FAILED(dr)) { + fprintf(stderr, "\n DeleteTemporaryPersistentLicenses: DRM_B64_EncodeW failed for LID: 0x%08X", dr); + continue; + } + + dr = Drm_StoreMgmt_DeleteLicenses( + m_poAppContext, + &dstrKID, + &dstrLID, + &cLicDeleted); + + } + +ErrorExit: + SAFE_OEM_FREE( dstrKID.pwszString ); + SAFE_OEM_FREE( dstrLID.pwszString ); + + return; +} + void MediaKeySession::SetParameter(const uint8_t * data, const uint32_t length) { //ocdm_log("set cbcs parameter\n"); } From dfc627d79dd386785a9494ce761479ff918c6b07 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 16 Jan 2025 07:40:24 +0000 Subject: [PATCH 32/37] update: aligned and tested. --- MediaSession.cpp | 159 +++++++++++++++++++++++++++++++++++++++++++++-- MediaSession.h | 9 +-- 2 files changed, 160 insertions(+), 8 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index b73189c..422ee79 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -898,6 +898,69 @@ DRM_RESULT MediaKeySession::ProcessLicenseResponse( return dr; } +/*Wrapper function for Drm_Reader_Bind()*/ +DRM_RESULT MediaKeySession::ReaderBind( + const DRM_CONST_STRING *f_rgpdstrRights[], + DRM_DWORD f_cRights, + DRMPFNPOLICYCALLBACK f_pfnPolicyCallback, + const DRM_VOID *f_pv, + DRM_DECRYPT_CONTEXT *f_pDecryptContext ) { + DRM_RESULT dr = DRM_SUCCESS; + DRM_BYTE *newOpaqueBuffer = nullptr; + + while( (dr=Drm_Reader_Bind( + m_poAppContext, + f_rgpdstrRights, + f_cRights, + f_pfnPolicyCallback, + f_pv, + f_pDecryptContext ) ) == DRM_E_BUFFERTOOSMALL ){ + + + DRM_BYTE *pbOldBuf = nullptr; + DRM_DWORD cbOldBuf = 0; + + if ( m_cbPROpaqueBuf == 0 ) + m_cbPROpaqueBuf = MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE; + + m_cbPROpaqueBuf *= 2; + + if ( m_cbPROpaqueBuf > MINIMUM_APPCONTEXT_OPAQUE_BUFFER_SIZE * 64 ){ + ChkDR( DRM_E_OUTOFMEMORY ); + } + + ChkMem( newOpaqueBuffer = ( DRM_BYTE* )Oem_MemAlloc( m_cbPROpaqueBuf ) ); + + dr = Drm_GetOpaqueBuffer( m_poAppContext, &pbOldBuf, &cbOldBuf ); + if ( DRM_FAILED( dr ) ){ + fprintf(stderr, "[%s:%d] Drm_GetOpaqueBuffer failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + SAFE_OEM_FREE( newOpaqueBuffer ); + ChkDR( dr ); + } + + dr = Drm_ResizeOpaqueBuffer( m_poAppContext, newOpaqueBuffer, m_cbPROpaqueBuf ); + if ( DRM_FAILED( dr ) ){ + fprintf(stderr, "[%s:%d] Drm_ResizeOpaqueBuffer failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + SAFE_OEM_FREE( newOpaqueBuffer ); + ChkDR( dr ); + } + + if ( m_pbPROpaqueBuf != nullptr && m_pbPROpaqueBuf == pbOldBuf ){ + SAFE_OEM_FREE( pbOldBuf ); + m_pbPROpaqueBuf = newOpaqueBuffer; + }else{ + SAFE_OEM_FREE( pbOldBuf ); + } + } + + ErrorExit: + if ( DRM_FAILED( dr ) ){ + fprintf(stderr, "[%s:%d] failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + } + + return dr; +} + CDMi_RESULT MediaKeySession::PersistentLicenseCheck() { #ifdef NO_PERSISTENT_LICENSE_CHECK // DELIA-51437: The Webkit EME implementation used by OTT apps @@ -1081,10 +1144,6 @@ void MediaKeySession::DeleteTemporaryPersistentLicenses() { return; } -void MediaKeySession::SetParameter(const uint8_t * data, const uint32_t length) { - //ocdm_log("set cbcs parameter\n"); -} - void MediaKeySession::Update(const uint8_t *m_pbKeyMessageResponse, uint32_t m_cbKeyMessageResponse) { DRM_RESULT dr = DRM_SUCCESS; @@ -1180,6 +1239,31 @@ CDMi_RESULT MediaKeySession::Remove(void) { return CDMi_S_FALSE; } +/*Closes each DRM_DECRYPT_CONTEXT using Drm_Reader_Close()*/ +void MediaKeySession::CloseDecryptContexts(void) { + m_currentDecryptContext = nullptr; + for (DECRYPT_CONTEXT &p : m_DecryptContextVector) + { + Drm_Reader_Close(&(p->oDrmDecryptContext)); + // Drm_Reader_Close(&(p->oDrmDecryptAudioContext)); + } + m_DecryptContextVector.clear(); +} + +void MediaKeySession::DeleteInMemoryLicenses() { + DRM_ID emptyId = DRM_ID_EMPTY; + + if (memcmp(&m_oBatchID, &emptyId, sizeof(DRM_ID)) == 0) { + return; + } + KeyId batchId(&m_oBatchID.rgb[0],KeyId::KEYID_ORDER_GUID_LE); + + DRM_RESULT dr = Drm_StoreMgmt_DeleteInMemoryLicenses(m_poAppContext, &m_oBatchID); + if (DRM_FAILED(dr) && dr != DRM_E_NOMORE) { + fprintf(stderr, "[%s:%d] Drm_StoreMgmt_DeleteInMemoryLicenses failed for batchId:%s. 0x%X - %s",__FUNCTION__,__LINE__,printUuid(batchId),dr,DRM_ERR_NAME(dr)); + } +} + CDMi_RESULT MediaKeySession::Close(void) { m_eKeyState = KEY_CLOSED; @@ -1215,6 +1299,73 @@ CDMi_RESULT MediaKeySession::Close(void) { return CDMi_SUCCESS; } +CDMi_RESULT MediaKeySession::PlaybackStopped(void) { + return CDMi_SUCCESS; +} + +const char* MediaKeySession::MapDrToKeyMessage( DRM_RESULT dr ) +{ + switch (dr) + { + case DRM_SUCCESS: + return "KeyUsable"; + case DRM_E_TEE_OUTPUT_PROTECTION_REQUIREMENTS_NOT_MET: + case DRM_E_TEST_OPL_MISMATCH: + return "KeyOutputRestricted"; + case DRM_E_TEE_OUTPUT_PROTECTION_INSUFFICIENT_HDCP: + return "KeyOutputRestrictedHDCP"; + case DRM_E_TEE_OUTPUT_PROTECTION_INSUFFICIENT_HDCP22: + case DRM_E_TEST_INVALID_OPL_CALLBACK: + return "KeyOutputRestrictedHDCP22"; + case DRM_E_LICENSE_NOT_FOUND: + return "LicenseNotFound"; + case DRM_E_LICENSE_EXPIRED: + return "LicenseExpired"; + default: + return "KeyInternalError"; + } +} + +CDMi_RESULT MediaKeySession::DRM_DecryptFailure(DRM_RESULT dr, const uint8_t *payloadData, uint32_t *f_pcbOpaqueClearContent, uint8_t **f_ppbOpaqueClearContent) +{ + fprintf(stderr, "[%s:%d] playready decrypt() failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + + if(f_pcbOpaqueClearContent != nullptr) + { + *f_pcbOpaqueClearContent = 0; + } + if(f_ppbOpaqueClearContent != nullptr && payloadData != nullptr) + { + *f_ppbOpaqueClearContent = (uint8_t *)payloadData; + } + + if(m_piCallback){ + char errStr[50]; + uint64_t errCode = (0xFFFFFFFF00000000)|(dr); + sprintf(errStr,"0x%llx-DecryptError",errCode); + m_piCallback->OnError(0, CDMi_S_FALSE, errStr); + m_piCallback->OnKeyStatusUpdate(MapDrToKeyMessage( dr ), nullptr, 0); + m_piCallback->OnKeyStatusesUpdated(); + } + return CDMi_S_FALSE; +} + +DECRYPT_CONTEXT MediaKeySession::GetDecryptCtx( KeyId &f_rKeyId ) +{ + for (DECRYPT_CONTEXT &ctx : m_DecryptContextVector) + { + if (ctx->keyId == f_rKeyId) + { + return ctx; + } + } + return nullptr; +} + +void MediaKeySession::SetParameter(const uint8_t * data, const uint32_t length) { + //ocdm_log("set cbcs parameter\n"); +} + CDMi_RESULT MediaKeySession::Decrypt( uint8_t* inData, const uint32_t inDataLength, diff --git a/MediaSession.h b/MediaSession.h index b00dd6e..82a9ef5 100644 --- a/MediaSession.h +++ b/MediaSession.h @@ -311,6 +311,7 @@ class MediaKeySession : public PlayreadySession, public IMediaKeySession, public virtual CDMi_RESULT Remove(); virtual CDMi_RESULT Close(void); + virtual CDMi_RESULT PlaybackStopped(void); virtual void SetParameter(const uint8_t * data, const uint32_t length); virtual const char *GetSessionId(void) const; @@ -456,12 +457,12 @@ class MediaKeySession : public PlayreadySession, public IMediaKeySession, public CDMi_RESULT SelectDrmHeader(DRM_APP_CONTEXT *pDrmAppCtx, const uint32_t headerLength, const uint8_t header[]); CDMi_RESULT SetOutputMode(DRM_APP_CONTEXT *pDrmAppCtx, DRM_DWORD dwDecryptionMode); - // std::vector< DECRYPT_CONTEXT > m_DecryptContextVector; + std::vector< DECRYPT_CONTEXT > m_DecryptContextVector; - // static bool mMaxResDecodeSet; - // static uint64_t mMaxResDecodePixels; + static bool mMaxResDecodeSet; + static uint64_t mMaxResDecodePixels; - // virtual CDMi_RESULT DRM_DecryptFailure(DRM_RESULT dr, const uint8_t *payloadData, uint32_t *f_pcbOpaqueClearContent, uint8_t **f_ppbOpaqueClearContent); + virtual CDMi_RESULT DRM_DecryptFailure(DRM_RESULT dr, const uint8_t *payloadData, uint32_t *f_pcbOpaqueClearContent, uint8_t **f_ppbOpaqueClearContent); // struct PlayreadyOutProtLevels m_playreadyLevels; From d72ec8085322cd927ed0ceb16d1e5d687c37d265 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 16 Jan 2025 07:58:35 +0000 Subject: [PATCH 33/37] update: SetParameter() updated. --- MediaSession.cpp | 21 +++++++++-- MediaSession.h | 93 +----------------------------------------------- 2 files changed, 19 insertions(+), 95 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index 422ee79..e5bf9d7 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -1362,8 +1362,22 @@ DECRYPT_CONTEXT MediaKeySession::GetDecryptCtx( KeyId &f_rKeyId ) return nullptr; } -void MediaKeySession::SetParameter(const uint8_t * data, const uint32_t length) { - //ocdm_log("set cbcs parameter\n"); +CDMi_RESULT MediaKeySession::SetParameter(const std::string& name, const std::string& value) +{ + CDMi_RESULT retVal = CDMi_S_FALSE; + + if(name.find("rpcId") != std::string::npos) { + // Got the RPC ID for gst-svp-ext communication + unsigned int nID = 0; + nID = (unsigned int)std::stoul(value.c_str(), nullptr, 16); + if(nID != 0) { +#ifdef USE_SVP + //fprintf(stderr, "Initializing SVP context for client side ID = %X\n", nID); + gst_svp_ext_get_context(&m_pSVPContext, Client, nID); +#endif + } + } + return retVal; } CDMi_RESULT MediaKeySession::Decrypt( @@ -1374,6 +1388,7 @@ void MediaKeySession::SetParameter(const uint8_t * data, const uint32_t length) const SampleInfo* sampleInfo, const IStreamProperties* properties) { + fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); DRM_UINT64 iv_vector[2] = { 0 }; void* pSecureToken = nullptr; void *decryptedData = nullptr; @@ -1565,7 +1580,7 @@ CDMi_RESULT MediaKeySession::ReleaseClearContent( uint32_t f_cbSessionKey, const uint32_t f_cbClearContentOpaque, uint8_t *f_pbClearContentOpaque ) { - + fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); return CDMi_SUCCESS; } diff --git a/MediaSession.h b/MediaSession.h index 82a9ef5..7062020 100644 --- a/MediaSession.h +++ b/MediaSession.h @@ -313,11 +313,10 @@ class MediaKeySession : public PlayreadySession, public IMediaKeySession, public virtual CDMi_RESULT Close(void); virtual CDMi_RESULT PlaybackStopped(void); - virtual void SetParameter(const uint8_t * data, const uint32_t length); + virtual CDMi_RESULT SetParameter(const std::string& name, const std::string& value); virtual const char *GetSessionId(void) const; virtual const char *GetKeySystem(void) const; ////////////////////// Decrypt /////////////////////////////////// -#ifdef AML_SVP_PR virtual CDMi_RESULT Decrypt( const uint8_t *f_pbSessionKey, @@ -344,96 +343,6 @@ class MediaKeySession : public PlayreadySession, public IMediaKeySession, public const SampleInfo* sampleInfo, const IStreamProperties* properties); -///////////////////////////////////////////////////////////////////// -#else - - virtual CDMi_RESULT MediaKeySession::Decrypt( - uint8_t* inData, - const uint32_t inDataLength, - uint8_t** outData, - uint32_t* outDataLength, - const SampleInfo* sampleInfo, - const IStreamProperties* properties); -#if 0 - virtual CDMi_RESULT MediaKeySession::Decrypt( - const uint8_t *f_pbSessionKey, - uint32_t f_cbSessionKey, - const EncryptionScheme encryptionScheme, - const EncryptionPattern& pattern, - const uint8_t *f_pbIV, - uint32_t f_cbIV, - uint8_t* payloadData, - uint32_t payloadDataSize, - uint32_t *f_pcbOpaqueClearContent, - uint8_t **f_ppbOpaqueClearContent, - const uint8_t keyIdLength, - const uint8_t* f_keyId, - bool initWithLast15); -#endif - - virtual CDMi_RESULT MediaKeySession::DecryptAesCBC1( - SubSampleInfo* subSample, - uint8_t subSampleCount, - const uint8_t *f_pbIV, - uint32_t f_cbIV, - const uint8_t *payloadData, - uint32_t payloadDataSize, - uint32_t *f_pcbOpaqueClearContent, - uint8_t **f_ppbOpaqueClearContent, - const uint8_t keyIdLength, - const uint8_t* f_keyId, - uint8_t initWithLast15, - uint32_t cryptoBlocks, - uint32_t clearBlocks, - bool useSVP); - -#if 0 - virtual CDMi_RESULT MediaKeySession::DecryptAesCBC( - const uint32_t *f_pdwSubSampleMapping, - uint32_t f_cdwSubSampleMapping, - const uint8_t *f_pbIV, - uint32_t f_cbIV, - const uint8_t *payloadData, - uint32_t payloadDataSize, - uint32_t *f_pcbOpaqueClearContent, - uint8_t **f_ppbOpaqueClearContent, - const uint8_t keyIdLength, - const uint8_t* f_keyId, - bool initWithLast15, - uint32_t cryptoBlocks, - uint32_t clearBlocks); -#endif - - virtual CDMi_RESULT MediaKeySession::DecryptAesCTR1( - SubSampleInfo* subSample, - uint8_t subSampleCount, - const uint8_t *f_pbIV, - uint32_t f_cbIV, - const uint8_t *payloadData, - uint32_t payloadDataSize, - uint32_t *f_pcbOpaqueClearContent, - uint8_t **f_ppbOpaqueClearContent, - const uint8_t keyIdLength, - const uint8_t* f_keyId, - uint8_t initWithLast15, - bool useSVP); - -#if 0 - virtual CDMi_RESULT MediaKeySession::DecryptAesCTR( - const uint32_t *f_pdwSubSampleMapping, - uint32_t f_cdwSubSampleMapping, - const uint8_t *f_pbIV, - uint32_t f_cbIV, - const uint8_t *payloadData, - uint32_t payloadDataSize, - uint32_t *f_pcbOpaqueClearContent, - uint8_t **f_ppbOpaqueClearContent, - const uint8_t keyIdLength, - const uint8_t* f_keyId, - bool initWithLast15); -#endif - -#endif ////////////////////// Decrypt /////////////////////////////////// virtual CDMi_RESULT ReleaseClearContent( From 3546109fe2c14479b049ef6f6b1cb5cc81513710 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 16 Jan 2025 18:35:20 +0000 Subject: [PATCH 34/37] update: aligned updated. --- MediaSession.cpp | 187 ++++++++++++++++++++++++++++------------------- MediaSession.h | 4 +- 2 files changed, 116 insertions(+), 75 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index e5bf9d7..2061f72 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -1145,93 +1145,132 @@ void MediaKeySession::DeleteTemporaryPersistentLicenses() { } void MediaKeySession::Update(const uint8_t *m_pbKeyMessageResponse, uint32_t m_cbKeyMessageResponse) { + fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); + DRM_RESULT dr = DRM_SUCCESS; + DRM_LICENSE_RESPONSE oLicenseResponse = { eUnknownProtocol, 0 }; + DRM_LICENSE_ACK *pLicenseAck = nullptr; + DRM_DWORD decryptionMode; + bool bIsAudioNeedNonSVPContext; - DRM_RESULT dr = DRM_SUCCESS; - DRM_DWORD decryptionMode; - DRM_LICENSE_RESPONSE oLicenseResponse = {eUnknownProtocol, 0}; - ChkArg(m_pbKeyMessageResponse && m_cbKeyMessageResponse > 0); + ChkBOOL(m_eKeyState == KEY_PENDING, DRM_E_INVALIDARG); - ChkDR(Drm_LicenseAcq_ProcessResponse(m_poAppContext, - DRM_PROCESS_LIC_RESPONSE_SIGNATURE_NOT_REQUIRED, -#ifndef PR_4_4 - nullptr, - nullptr, -#endif - const_cast(m_pbKeyMessageResponse), - m_cbKeyMessageResponse, - &oLicenseResponse)); - decryptionMode = OEM_TEE_DECRYPTION_MODE_HANDLE; - dr = Drm_Content_SetProperty(m_poAppContext, - DRM_CSP_DECRYPTION_OUTPUT_MODE, - (const DRM_BYTE*)&decryptionMode, - sizeof decryptionMode); - if (!DRM_SUCCEEDED(dr)) { - ocdm_log("Drm_Content_SetProperty() failed with %lx", dr); - goto ErrorExit; - } + ChkArg(m_pbKeyMessageResponse && m_cbKeyMessageResponse > 0); - dr = Drm_Reader_Bind(m_poAppContext, - g_rgpdstrRights, - DRM_NO_OF(g_rgpdstrRights), - _PolicyCallback, - nullptr, - m_oDecryptContext); - if (!DRM_SUCCEEDED(dr)) { - ocdm_log("Drm_Reader_Bind() MODE_HANDLE failed with %lx", dr); - goto ErrorExit; - } + ChkDR( ProcessLicenseResponse( + DRM_PROCESS_LIC_RESPONSE_NO_FLAGS, + const_cast(m_pbKeyMessageResponse), + m_cbKeyMessageResponse, + &oLicenseResponse ) ); - decryptionMode = OEM_TEE_DECRYPTION_MODE_NOT_SECURE; - dr = Drm_Content_SetProperty(m_poAppContext, - DRM_CSP_DECRYPTION_OUTPUT_MODE, - (const DRM_BYTE*)&decryptionMode, - sizeof decryptionMode); - if (!DRM_SUCCEEDED(dr)) { - ocdm_log("Drm_Content_SetProperty() failed with %lx", dr); - goto ErrorExit; - } + SaveTemporaryPersistentLicenses(&oLicenseResponse); - dr = Drm_Reader_Bind(m_poAppContext, - g_rgpdstrRights, - DRM_NO_OF(g_rgpdstrRights), - _PolicyCallback, - nullptr, - m_oDecryptContext2); - if (!DRM_SUCCEEDED(dr)) { - ocdm_log("Drm_Reader_Bind() MODE_NOT_SECURE failed with %lx, ignore", dr); - } + fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); + + for (DRM_DWORD i = 0; i < oLicenseResponse.m_cAcks; ++i) { + + fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); + + pLicenseAck = oLicenseResponse.m_pAcks != nullptr + ? &oLicenseResponse.m_pAcks[ i ] : &oLicenseResponse.m_rgoAcks[ i ]; + + KeyId keyId(&pLicenseAck->m_oKID.rgb[0],KeyId::KEYID_ORDER_GUID_LE); + + dr = pLicenseAck->m_dwResult; + if ( DRM_SUCCEEDED( dr ) ) { + + DECRYPT_CONTEXT decryptContext; + + if ( CDMi_SUCCESS != SetKeyIdProperty( keyId ) ) + { + dr = DRM_E_FAIL; + goto LoopEnd; + } + + decryptContext = NEW_DECRYPT_CONTEXT(); - m_eKeyState = KEY_READY; + decryptionMode = OEM_TEE_DECRYPTION_MODE_HANDLE; + dr = Drm_Content_SetProperty(m_poAppContext, + DRM_CSP_DECRYPTION_OUTPUT_MODE, + (const DRM_BYTE*)&decryptionMode, + sizeof decryptionMode); + if (!DRM_SUCCEEDED(dr)) { + fprintf(stderr, "[%s:%d] Drm_Content_SetProperty() failed with %lx - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + goto ErrorExit; + } + + dr = ReaderBind( + g_rgpdstrRights, + NO_OF(g_rgpdstrRights), + _PolicyCallback, + &m_playreadyLevels, + m_oDecryptContext); + + if ( DRM_FAILED( dr ) ){ + fprintf(stderr, "[%s:%d] ReaderBind failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + goto LoopEnd; + } - if (m_eKeyState == KEY_READY) { - if (m_piCallback) { - for (DRM_DWORD i = 0; i < oLicenseResponse.m_cAcks; ++i) { - if (DRM_SUCCEEDED(oLicenseResponse.m_rgoAcks[i].m_dwResult)) { - m_piCallback->OnKeyStatusUpdate("KeyUsable", oLicenseResponse.m_rgoAcks[i].m_oKID.rgb, DRM_ID_SIZE); + bIsAudioNeedNonSVPContext = true; + + if(bIsAudioNeedNonSVPContext) + { + fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); + decryptionMode = OEM_TEE_DECRYPTION_MODE_NOT_SECURE; + dr = Drm_Content_SetProperty(m_poAppContext, + DRM_CSP_DECRYPTION_OUTPUT_MODE, + (const DRM_BYTE*)&decryptionMode, + sizeof decryptionMode); + if (!DRM_SUCCEEDED(dr)) { + fprintf(stderr, "[%s:%d] Drm_Content_SetProperty() failed with %lx - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + goto ErrorExit; + } + + dr = ReaderBind( + g_rgpdstrRights, + NO_OF(g_rgpdstrRights), + _PolicyCallback, + &m_playreadyLevels, + m_oDecryptContext2); + + if ( DRM_FAILED( dr ) ){ + fprintf(stderr, "[%s:%d] ReaderBind failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + goto LoopEnd; + } + } + + decryptContext->keyId = keyId; + + if ( oLicenseResponse.m_cAcks == 1 ){ + m_currentDecryptContext = decryptContext; + } + + m_DecryptContextVector.push_back(decryptContext); + + m_eKeyState = KEY_READY; } - } - m_piCallback->OnKeyStatusesUpdated(); - } - } + LoopEnd: + if ( m_piCallback ){ + m_piCallback->OnKeyStatusUpdate( MapDrToKeyMessage( dr ), keyId.getmBytes(), DRM_ID_SIZE); + } + } - return; + if ( m_eKeyState == KEY_READY ){ + dr = DRM_SUCCESS; + }else{ + fprintf(stderr, "[%s:%d] Could not bind to any licenses",__FUNCTION__,__LINE__); + dr = DRM_E_FAIL; + } ErrorExit: - if (DRM_FAILED(dr)) { - const DRM_CHAR* description; - DRM_ERR_GetErrorNameFromCode(dr, &description); - ocdm_log("playready error3: %s\n", description); - m_eKeyState = KEY_ERROR; - - // The upper layer is blocked waiting for an update, let's wake it. - if (m_piCallback) { - for (DRM_DWORD i = 0; i < oLicenseResponse.m_cAcks; ++i) { - m_piCallback->OnKeyStatusUpdate("KeyError", oLicenseResponse.m_rgoAcks[i].m_oKID.rgb, DRM_ID_SIZE); - } - m_piCallback->OnKeyStatusesUpdated(); + if (DRM_FAILED(dr)) { + fprintf(stderr, "[%s:%d] failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); + m_eKeyState = KEY_ERROR; } - } + if (m_piCallback){ + m_piCallback->OnKeyStatusesUpdated(); + } + SAFE_OEM_FREE( oLicenseResponse.m_pAcks ); return; } diff --git a/MediaSession.h b/MediaSession.h index 7062020..5e798c1 100644 --- a/MediaSession.h +++ b/MediaSession.h @@ -151,10 +151,12 @@ struct __DECRYPT_CONTEXT { KeyId keyId; DRM_DECRYPT_CONTEXT oDrmDecryptContext; + DRM_DECRYPT_CONTEXT oDrmDecryptAudioContext; __DECRYPT_CONTEXT() { memset( &oDrmDecryptContext, 0, sizeof( DRM_DECRYPT_CONTEXT ) ); + memset( &oDrmDecryptAudioContext, 0, sizeof( DRM_DECRYPT_CONTEXT ) ); } }; @@ -373,7 +375,7 @@ class MediaKeySession : public PlayreadySession, public IMediaKeySession, public virtual CDMi_RESULT DRM_DecryptFailure(DRM_RESULT dr, const uint8_t *payloadData, uint32_t *f_pcbOpaqueClearContent, uint8_t **f_ppbOpaqueClearContent); - // struct PlayreadyOutProtLevels m_playreadyLevels; + struct PlayreadyOutProtLevels m_playreadyLevels; static DRM_RESULT DRM_CALL _PolicyCallback(const DRM_VOID *, DRM_POLICY_CALLBACK_TYPE f_dwCallbackType, const DRM_KID *, const DRM_LID *, const DRM_VOID *); From 78d39f8abdc04f8dcf0332a5196a7fabdaf096f1 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 16 Jan 2025 18:49:29 +0000 Subject: [PATCH 35/37] update: aligned updated. --- MediaSession.cpp | 54 ++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 45 insertions(+), 9 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index 2061f72..703970e 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -207,8 +207,8 @@ void Swap(uint8_t& lhs, uint8_t& rhs) const DRM_CONST_STRING *g_rgpdstrRights[1] = {&g_dstrDRM_RIGHT_PLAYBACK}; -// uint64_t MediaKeySession::mMaxResDecodePixels = 0; -// bool MediaKeySession::mMaxResDecodeSet = false; +uint64_t MediaKeySession::mMaxResDecodePixels = 0; +bool MediaKeySession::mMaxResDecodeSet = false; WPEFramework::Core::CriticalSection prPlatformMutex_; WPEFramework::Core::CriticalSection prSessionMutex_; @@ -570,8 +570,8 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD ChkBOOL(m_eKeyState == KEY_CLOSED, DRM_E_INVALIDARG); -// mMaxResDecodePixels = 0; -// mMaxResDecodeSet = false; +mMaxResDecodePixels = 0; +mMaxResDecodeSet = false; // if (m_poAppContext == nullptr) { //RTK if (m_poAppContext) { @@ -691,16 +691,52 @@ const char *MediaKeySession::GetKeySystem(void) const { } DRM_RESULT DRM_CALL MediaKeySession::_PolicyCallback( - const DRM_VOID *f_pvOutputLevelsData, + const DRM_VOID *f_pvOutputLevelsData, DRM_POLICY_CALLBACK_TYPE f_dwCallbackType, -#ifdef PR_4_4 const DRM_KID *f_pKID, const DRM_LID *f_pLID, -#endif const DRM_VOID *f_pv) { - return DRM_SUCCESS; + DRM_RESULT res = DRM_SUCCESS; + + switch (f_dwCallbackType) + { + case DRM_PLAY_OPL_CALLBACK: + { + const DRM_PLAY_OPL_LATEST * const opl = static_cast(f_pvOutputLevelsData); + assert(opl->dwVersion == VER_DRM_PLAY_OPL_LATEST); + + /* MaxResDecode */ + const DRM_DIGITAL_VIDEO_OUTPUT_PROTECTION_IDS_LATEST &dvopi = opl->dvopi; + assert(dvopi.dwVersion == VER_DRM_DIGITAL_VIDEO_OUTPUT_PROTECTION_IDS_LATEST); + for (size_t i = 0; i < dvopi.cEntries; ++i) + { + const DRM_OUTPUT_PROTECTION_LATEST &entry = dvopi.rgVop[i]; + if (DRM_IDENTICAL_GUIDS(&entry.guidId, &g_guidMaxResDecode)) + { + assert(entry.dwVersion == VER_DRM_DIGITAL_VIDEO_OUTPUT_PROTECTION_LATEST); + + uint32_t mrdWidth = (uint32_t)(entry.rgbConfigData[0] << 24 | entry.rgbConfigData[1] << 16 | entry.rgbConfigData[2] << 8 | entry.rgbConfigData[3]); + uint32_t mrdHeight = (uint32_t)(entry.rgbConfigData[4] << 24 | entry.rgbConfigData[5] << 16 | entry.rgbConfigData[6] << 8 | entry.rgbConfigData[7]); + + + mMaxResDecodePixels = mrdWidth*mrdHeight; + mMaxResDecodeSet = true; + res = DRM_SUCCESS; + break; + } + } + break; + } + default: + // ignored + res = DRM_SUCCESS; + break; + } + + return res; } + void MediaKeySession::Run(const IMediaKeySessionCallback *f_piMediaKeySessionCallback) { if (f_piMediaKeySessionCallback) { m_piCallback = const_cast(f_piMediaKeySessionCallback); @@ -1062,7 +1098,7 @@ CDMi_RESULT MediaKeySession::PersistentLicenseCheck() { // clean them up when the session closes. void MediaKeySession::SaveTemporaryPersistentLicenses(const DRM_LICENSE_RESPONSE* f_poLicenseResponse) { - fprintf(stderr, "\n SaveTemporaryPersistentLicenses: response has persistent licenses: %s", + fprintf(stderr, "\n SaveTemporaryPersistentLicenses: response has persistent licenses: %s\n", f_poLicenseResponse->m_fHasPersistentLicenses ? "true" : "false"); if (!f_poLicenseResponse->m_fHasPersistentLicenses) { From a943ed6c1faafe66f0277f50057e34e2773f0d04 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 16 Jan 2025 20:04:20 +0000 Subject: [PATCH 36/37] update: removing DecryptContext init values. --- MediaSession.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index 703970e..b60d334 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -525,7 +525,7 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD , m_pdstrHeaderKIDs( nullptr ) , m_eHeaderVersion( DRM_HEADER_VERSION_UNKNOWN ) , m_oBatchID( DRM_ID_EMPTY ) -// , m_currentDecryptContext( nullptr ) //RTK + , m_currentDecryptContext( nullptr ) //RTK , m_oDecryptContext(nullptr) , m_oDecryptContext2(nullptr) #ifdef USE_SVP @@ -540,10 +540,16 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); memset(&levels_, 0, sizeof(levels_)); //need to comment later. - m_oDecryptContext = new DRM_DECRYPT_CONTEXT; - memset(m_oDecryptContext, 0, sizeof(DRM_DECRYPT_CONTEXT)); - m_oDecryptContext2 = new DRM_DECRYPT_CONTEXT; - memset(m_oDecryptContext2, 0, sizeof(DRM_DECRYPT_CONTEXT)); +// m_oDecryptContext = new DRM_DECRYPT_CONTEXT; +// memset(m_oDecryptContext, 0, sizeof(DRM_DECRYPT_CONTEXT)); +// m_oDecryptContext2 = new DRM_DECRYPT_CONTEXT; +// memset(m_oDecryptContext2, 0, sizeof(DRM_DECRYPT_CONTEXT)); + +m_currentDecryptContext = NEW_DECRYPT_CONTEXT(); +m_DecryptContextVector.push_back(m_currentDecryptContext); + +m_oDecryptContext = &(m_currentDecryptContext->oDrmDecryptContext); +m_oDecryptContext2 = &(m_currentDecryptContext->oDrmDecryptAudioContext); DRM_RESULT dr = DRM_SUCCESS; DRM_ID oSessionID = DRM_ID_EMPTY; @@ -1320,7 +1326,7 @@ void MediaKeySession::CloseDecryptContexts(void) { for (DECRYPT_CONTEXT &p : m_DecryptContextVector) { Drm_Reader_Close(&(p->oDrmDecryptContext)); - // Drm_Reader_Close(&(p->oDrmDecryptAudioContext)); + Drm_Reader_Close(&(p->oDrmDecryptAudioContext)); } m_DecryptContextVector.clear(); } @@ -1350,13 +1356,13 @@ CDMi_RESULT MediaKeySession::Close(void) { if (m_oDecryptContext != nullptr) { Drm_Reader_Close(m_oDecryptContext); - delete m_oDecryptContext; +// delete m_oDecryptContext; m_oDecryptContext = nullptr; } if (m_oDecryptContext2 != nullptr) { Drm_Reader_Close(m_oDecryptContext2); - delete m_oDecryptContext2; +// delete m_oDecryptContext2; m_oDecryptContext2 = nullptr; } From 7d3f4871150408eb7b17aa7f101d292ebbd9fe45 Mon Sep 17 00:00:00 2001 From: kvfasil Date: Thu, 16 Jan 2025 21:54:45 +0000 Subject: [PATCH 37/37] update: code updated and tested. --- MediaSession.cpp | 101 ++++++++++++----------------------------------- 1 file changed, 26 insertions(+), 75 deletions(-) diff --git a/MediaSession.cpp b/MediaSession.cpp index b60d334..8bacb6c 100644 --- a/MediaSession.cpp +++ b/MediaSession.cpp @@ -352,11 +352,6 @@ DRM_RESULT CPRDrmPlatform::DrmPlatformInitialize( void *f_pContext ) DRM_RESULT CPRDrmPlatform::DrmPlatformInitialize() { void *pPlatformInitData = NULL; - /* realtek, it returns DRM_INIT_CONTEXT as pPlatformInitData, - * Amlogic, it would be NULL - * BRCM, it returns OEM_Settings as pPlatformInitData - */ - // void svpGetDrmPlatformInitData( void ** ppPlatformInitData) // svpGetDrmPlatformInitData( &pPlatformInitData); return DrmPlatformInitialize( (void *)pPlatformInitData ); } @@ -374,8 +369,6 @@ DRM_RESULT CPRDrmPlatform::DrmPlatformUninitialize() } else if ( --m_dwInitRefCount == 0 ) { - /* m_drmOemContext currently used by BRCM. AML & RTK it could be stub */ - //void svpGetDrmOEMContext(void ** ppdrmOemContext) // svpGetDrmOEMContext(&m_drmOemContext); if ( DRM_FAILED( (dr=Drm_Platform_Uninitialize( (void *)m_drmOemContext ) ) ) ) @@ -431,11 +424,9 @@ PlayreadySession::PlayreadySession() , m_cbPROpaqueBuf(0) , m_bInitCalled(false) { - void *pPlatformInitData = NULL; - // void svpGetDrmPlatformInitData( void ** ppPlatformInitData) + void *pPlatformInitData = NULL; // svpGetDrmPlatformInitData( &pPlatformInitData); - //TODO // if ( DRM_FAILED( CPRDrmPlatform::DrmPlatformInitialize( pPlatformInitData ) ) ) // { // fprintf(stderr, "[%s:%d] DrmPlatformInitialize failed.",__FUNCTION__,__LINE__); @@ -459,7 +450,6 @@ PlayreadySession::~PlayreadySession() } } - // TODO // if (DRM_FAILED(CPRDrmPlatform::DrmPlatformUninitialize())) // { // fprintf(stderr, "[%s:%d] DrmPlatformUninitialize failed.",__FUNCTION__,__LINE__); @@ -484,13 +474,12 @@ DRM_APP_CONTEXT * PlayreadySession::InitializeDRM(const DRM_CONST_STRING * pDRMS ChkMem( m_poAppContext = (DRM_APP_CONTEXT * )Oem_MemAlloc( sizeof(DRM_APP_CONTEXT) ) ); ZEROMEM( m_poAppContext, sizeof(DRM_APP_CONTEXT) ); - /* pdrmOemContext this should be valid for BRCM , others it could be null */ // svpGetDrmOEMContext(&pdrmOemContext); dr = Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName); if (dr != DRM_SUCCESS) { remove(GetDrmStorePath().c_str()); - ChkDR(Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName)); + ChkDR(Drm_Initialize(m_poAppContext, pdrmOemContext, m_pbPROpaqueBuf, m_cbPROpaqueBuf, pDRMStoreName)); } } else @@ -525,9 +514,7 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD , m_pdstrHeaderKIDs( nullptr ) , m_eHeaderVersion( DRM_HEADER_VERSION_UNKNOWN ) , m_oBatchID( DRM_ID_EMPTY ) - , m_currentDecryptContext( nullptr ) //RTK - , m_oDecryptContext(nullptr) - , m_oDecryptContext2(nullptr) + , m_currentDecryptContext( nullptr ) #ifdef USE_SVP , m_pSVPContext(nullptr) , m_rpcID(0) @@ -540,17 +527,6 @@ MediaKeySession::MediaKeySession(const uint8_t *f_pbInitData, uint32_t f_cbInitD fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); memset(&levels_, 0, sizeof(levels_)); //need to comment later. -// m_oDecryptContext = new DRM_DECRYPT_CONTEXT; -// memset(m_oDecryptContext, 0, sizeof(DRM_DECRYPT_CONTEXT)); -// m_oDecryptContext2 = new DRM_DECRYPT_CONTEXT; -// memset(m_oDecryptContext2, 0, sizeof(DRM_DECRYPT_CONTEXT)); - -m_currentDecryptContext = NEW_DECRYPT_CONTEXT(); -m_DecryptContextVector.push_back(m_currentDecryptContext); - -m_oDecryptContext = &(m_currentDecryptContext->oDrmDecryptContext); -m_oDecryptContext2 = &(m_currentDecryptContext->oDrmDecryptAudioContext); - DRM_RESULT dr = DRM_SUCCESS; DRM_ID oSessionID = DRM_ID_EMPTY; DRM_CONST_STRING dstrWRMHEADER = DRM_EMPTY_DRM_STRING; @@ -576,8 +552,8 @@ m_oDecryptContext2 = &(m_currentDecryptContext->oDrmDecryptAudioContext); ChkBOOL(m_eKeyState == KEY_CLOSED, DRM_E_INVALIDARG); -mMaxResDecodePixels = 0; -mMaxResDecodeSet = false; + mMaxResDecodePixels = 0; + mMaxResDecodeSet = false; // if (m_poAppContext == nullptr) { //RTK if (m_poAppContext) { @@ -622,8 +598,6 @@ mMaxResDecodeSet = false; ( DRM_REINTERPRET_CAST( DRM_APP_CONTEXT_INTERNAL, m_poAppContext ) )->fClockSet = TRUE; #endif - DRM_CONST_DSTR_FROM_PB( &dstrWRMHEADER, &mDrmHeader[ 0 ], mDrmHeader.size() ); - ChkDR( Header_GetInfo( &dstrWRMHEADER, &m_eHeaderVersion, &m_pdstrHeaderKIDs, @@ -662,9 +636,9 @@ mMaxResDecodeSet = false; return; } - - MediaKeySession::~MediaKeySession(void) { + mMaxResDecodePixels = 0; + mMaxResDecodeSet = false; gst_svp_ext_free_context(m_pSVPContext); Close(); if (--m_secCount == 0) { @@ -742,7 +716,6 @@ DRM_RESULT DRM_CALL MediaKeySession::_PolicyCallback( return res; } - void MediaKeySession::Run(const IMediaKeySessionCallback *f_piMediaKeySessionCallback) { if (f_piMediaKeySessionCallback) { m_piCallback = const_cast(f_piMediaKeySessionCallback); @@ -766,15 +739,6 @@ bool MediaKeySession::playreadyGenerateKeyRequest() { m_cbChallenge = 0; -#ifdef PR_4_4 - dr = Drm_Reader_Bind(m_poAppContext, - g_rgpdstrRights, - DRM_NO_OF(g_rgpdstrRights), - _PolicyCallback, - nullptr, - m_oDecryptContext); -#endif - ChkDR(Drm_Content_SetProperty(m_poAppContext, DRM_CSP_AUTODETECT_HEADER, &mDrmHeader[ 0 ], @@ -848,7 +812,7 @@ bool MediaKeySession::playreadyGenerateKeyRequest() { m_eKeyState = KEY_PENDING; - fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); + if (m_piCallback) m_piCallback->OnKeyMessage((const uint8_t *) m_pbChallenge, m_cbChallenge, m_pchSilentURL != NULL ? (char *)m_pchSilentURL : "" ); @@ -1017,7 +981,7 @@ CDMi_RESULT MediaKeySession::PersistentLicenseCheck() { // persistent keys should directly link to PR4 or the OCDM should // be rewritten to use PR4's CDMI API // (modules/cdmi/real/drmcdmireal.c). - fprintf(stderr, "\n PersistentLicenseCheck: skipping persistent check\n"); + fprintf(stderr, "\n PersistentLicenseCheck: skipping persistent check"); return CDMi_S_FALSE; #else DRM_RESULT dr = DRM_SUCCESS; @@ -1104,7 +1068,7 @@ CDMi_RESULT MediaKeySession::PersistentLicenseCheck() { // clean them up when the session closes. void MediaKeySession::SaveTemporaryPersistentLicenses(const DRM_LICENSE_RESPONSE* f_poLicenseResponse) { - fprintf(stderr, "\n SaveTemporaryPersistentLicenses: response has persistent licenses: %s\n", + fprintf(stderr, "\n SaveTemporaryPersistentLicenses: response has persistent licenses: %s", f_poLicenseResponse->m_fHasPersistentLicenses ? "true" : "false"); if (!f_poLicenseResponse->m_fHasPersistentLicenses) { @@ -1186,8 +1150,10 @@ void MediaKeySession::DeleteTemporaryPersistentLicenses() { return; } +/*processes the license response and creates decryptor for each valid ack available in the response*/ void MediaKeySession::Update(const uint8_t *m_pbKeyMessageResponse, uint32_t m_cbKeyMessageResponse) { - fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); + + DRM_RESULT dr = DRM_SUCCESS; DRM_LICENSE_RESPONSE oLicenseResponse = { eUnknownProtocol, 0 }; DRM_LICENSE_ACK *pLicenseAck = nullptr; @@ -1206,12 +1172,8 @@ void MediaKeySession::Update(const uint8_t *m_pbKeyMessageResponse, uint32_t m_ SaveTemporaryPersistentLicenses(&oLicenseResponse); - fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); - for (DRM_DWORD i = 0; i < oLicenseResponse.m_cAcks; ++i) { - fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); - pLicenseAck = oLicenseResponse.m_pAcks != nullptr ? &oLicenseResponse.m_pAcks[ i ] : &oLicenseResponse.m_rgoAcks[ i ]; @@ -1245,18 +1207,18 @@ void MediaKeySession::Update(const uint8_t *m_pbKeyMessageResponse, uint32_t m_ NO_OF(g_rgpdstrRights), _PolicyCallback, &m_playreadyLevels, - m_oDecryptContext); + &(decryptContext->oDrmDecryptContext) ); if ( DRM_FAILED( dr ) ){ fprintf(stderr, "[%s:%d] ReaderBind failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); goto LoopEnd; } + // bIsAudioNeedNonSVPContext = svpIsAudioNeedNonSVPContext(); bIsAudioNeedNonSVPContext = true; if(bIsAudioNeedNonSVPContext) { - fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); decryptionMode = OEM_TEE_DECRYPTION_MODE_NOT_SECURE; dr = Drm_Content_SetProperty(m_poAppContext, DRM_CSP_DECRYPTION_OUTPUT_MODE, @@ -1272,7 +1234,7 @@ void MediaKeySession::Update(const uint8_t *m_pbKeyMessageResponse, uint32_t m_ NO_OF(g_rgpdstrRights), _PolicyCallback, &m_playreadyLevels, - m_oDecryptContext2); + &(decryptContext->oDrmDecryptAudioContext) ); if ( DRM_FAILED( dr ) ){ fprintf(stderr, "[%s:%d] ReaderBind failed. 0x%X - %s",__FUNCTION__,__LINE__,dr,DRM_ERR_NAME(dr)); @@ -1317,7 +1279,8 @@ void MediaKeySession::Update(const uint8_t *m_pbKeyMessageResponse, uint32_t m_ } CDMi_RESULT MediaKeySession::Remove(void) { - return CDMi_S_FALSE; + fprintf(stderr, "[%s:%d] returning false ",__FUNCTION__,__LINE__); + return CDMi_S_FALSE; } /*Closes each DRM_DECRYPT_CONTEXT using Drm_Reader_Close()*/ @@ -1354,18 +1317,6 @@ CDMi_RESULT MediaKeySession::Close(void) { m_pbRevocationBuffer = nullptr; } - if (m_oDecryptContext != nullptr) { - Drm_Reader_Close(m_oDecryptContext); -// delete m_oDecryptContext; - m_oDecryptContext = nullptr; - } - - if (m_oDecryptContext2 != nullptr) { - Drm_Reader_Close(m_oDecryptContext2); -// delete m_oDecryptContext2; - m_oDecryptContext2 = nullptr; - } - if (m_pbChallenge != nullptr) { SAFE_OEM_FREE(m_pbChallenge); m_pbChallenge = nullptr; @@ -1470,6 +1421,7 @@ CDMi_RESULT MediaKeySession::SetParameter(const std::string& name, const std::st const IStreamProperties* properties) { fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); + DRM_UINT64 iv_vector[2] = { 0 }; void* pSecureToken = nullptr; void *decryptedData = nullptr; @@ -1481,7 +1433,7 @@ CDMi_RESULT MediaKeySession::SetParameter(const std::string& name, const std::st return CDMi_SUCCESS; } - if (!m_oDecryptContext) { + if (!&(m_currentDecryptContext->oDrmDecryptContext)) { ocdm_log("Error: no decrypt context (yet?)\n"); return CDMi_S_FALSE; } @@ -1501,14 +1453,14 @@ CDMi_RESULT MediaKeySession::SetParameter(const std::string& name, const std::st #ifndef PR_4_4 if (!properties->InitLength()) { - err = Drm_Reader_InitDecrypt(m_oDecryptContext, nullptr, 0); + err = Drm_Reader_InitDecrypt(&(m_currentDecryptContext->oDrmDecryptContext), nullptr, 0); } else { // Initialize the decryption context for Cocktail packaged // content. This is a no-op for AES packaged content. if (inDataLength <= 15) { - err = Drm_Reader_InitDecrypt(m_oDecryptContext, (DRM_BYTE*)inData, inDataLength); + err = Drm_Reader_InitDecrypt(&(m_currentDecryptContext->oDrmDecryptContext), (DRM_BYTE*)inData, inDataLength); } else { - err = Drm_Reader_InitDecrypt(m_oDecryptContext, (DRM_BYTE*)(inData + inDataLength - 15), inDataLength); + err = Drm_Reader_InitDecrypt(&(m_currentDecryptContext->oDrmDecryptContext), (DRM_BYTE*)(inData + inDataLength - 15), inDataLength); } } if (DRM_FAILED(err)) { @@ -1576,7 +1528,8 @@ CDMi_RESULT MediaKeySession::SetParameter(const std::string& name, const std::st } OEM_OPTEE_SetHandle(secbuf_out->secmem_handle); - err = Drm_Reader_DecryptMultipleOpaque(m_oDecryptContext, + err = Drm_Reader_DecryptMultipleOpaque( + &(m_currentDecryptContext->oDrmDecryptContext), 1, iv_vector, iv_vector + 1, regionCount, encryptedRegions.size(), &encryptedRegions[0], 2, regionSkip, @@ -1616,7 +1569,7 @@ CDMi_RESULT MediaKeySession::SetParameter(const std::string& name, const std::st pSecureToken = NULL; } else { - err = Drm_Reader_DecryptMultipleOpaque(m_oDecryptContext2, + err = Drm_Reader_DecryptMultipleOpaque(&(m_currentDecryptContext->oDrmDecryptAudioContext), 1, iv_vector, iv_vector + 1, regionCount, encryptedRegions.size(), &encryptedRegions[0], 2, regionSkip, @@ -1661,9 +1614,7 @@ CDMi_RESULT MediaKeySession::ReleaseClearContent( uint32_t f_cbSessionKey, const uint32_t f_cbClearContentOpaque, uint8_t *f_pbClearContentOpaque ) { - fprintf(stderr,"##FASIL## %s : %d : \n",__func__,__LINE__); return CDMi_SUCCESS; - } } // namespace CDMi \ No newline at end of file