From f4560f109f4b20810118f7308e20a6845f5ae7a1 Mon Sep 17 00:00:00 2001 From: Jeff Tinker Date: Mon, 29 Jul 2013 17:41:22 -0700 Subject: [PATCH] Squashed commit of the following CDM changes: * Add additional parameters to CDM decryption API https://widevine-internal-review.googlesource.com/#/c/6500/ * Pass Length and Flags Parameters to Decrypt() https://widevine-internal-review.googlesource.com/#/c/6740/ * Remove core files from oemcrypto/mock https://widevine-internal-review.googlesource.com/#/c/6853/ Change-Id: I1c73f5454da20da99130b161543fb990e16e7130 --- libwvdrmengine/cdm/core/include/cdm_engine.h | 11 +- libwvdrmengine/cdm/core/include/cdm_session.h | 6 +- .../cdm/core/include/crypto_session.h | 10 +- .../cdm/core/include/wv_cdm_types.h | 46 +- libwvdrmengine/cdm/core/src/cdm_engine.cpp | 36 +- libwvdrmengine/cdm/core/src/cdm_session.cpp | 27 +- .../cdm/core/src/crypto_session.cpp | 30 +- .../include/wv_content_decryption_module.h | 20 +- .../cdm/src/wv_content_decryption_module.cpp | 44 +- .../cdm/test/request_license_test.cpp | 464 +++++++----------- libwvdrmengine/mediacrypto/Android.mk | 1 + .../mediacrypto/src/WVCryptoPlugin.cpp | 64 ++- libwvdrmengine/mediacrypto/test/Android.mk | 1 + .../mediacrypto/test/WVCryptoPlugin_test.cpp | 211 ++++++-- libwvdrmengine/oemcrypto/mock/Android.mk | 12 +- libwvdrmengine/oemcrypto/mock/src/lock.cpp | 34 -- libwvdrmengine/oemcrypto/mock/src/lock.h | 61 --- libwvdrmengine/oemcrypto/mock/src/log.cpp | 35 -- libwvdrmengine/oemcrypto/mock/src/log.h | 40 -- .../oemcrypto/mock/src/string_conversions.cpp | 91 ---- .../oemcrypto/mock/src/string_conversions.h | 20 - .../oemcrypto/mock/src/wv_cdm_constants.h | 14 - .../oemcrypto/mock/src/wv_cdm_types.h | 49 -- libwvdrmengine/oemcrypto/test/Android.mk | 5 +- 24 files changed, 543 insertions(+), 789 deletions(-) delete mode 100644 libwvdrmengine/oemcrypto/mock/src/lock.cpp delete mode 100644 libwvdrmengine/oemcrypto/mock/src/lock.h delete mode 100644 libwvdrmengine/oemcrypto/mock/src/log.cpp delete mode 100644 libwvdrmengine/oemcrypto/mock/src/log.h delete mode 100644 libwvdrmengine/oemcrypto/mock/src/string_conversions.cpp delete mode 100644 libwvdrmengine/oemcrypto/mock/src/string_conversions.h delete mode 100644 libwvdrmengine/oemcrypto/mock/src/wv_cdm_constants.h delete mode 100644 libwvdrmengine/oemcrypto/mock/src/wv_cdm_types.h diff --git a/libwvdrmengine/cdm/core/include/cdm_engine.h b/libwvdrmengine/cdm/core/include/cdm_engine.h index c4a65757..4319d7bb 100644 --- a/libwvdrmengine/cdm/core/include/cdm_engine.h +++ b/libwvdrmengine/cdm/core/include/cdm_engine.h @@ -85,16 +85,7 @@ class CdmEngine : public TimerHandler { // Decryption and key related methods // Accept encrypted buffer and return decrypted data. virtual CdmResponseType Decrypt(const CdmSessionId& session_id, - bool is_encrypted, - bool is_secure, - const KeyId& key_id, - const uint8_t* encrypt_buffer, - size_t encrypt_length, - const std::vector& iv, - size_t block_offset, - void* decrypt_buffer, - size_t decrypt_buffer_offset, - bool is_video); + const CdmDecryptionParameters& parameters); // Is the key known to any session? virtual bool IsKeyValid(const KeyId& key_id); diff --git a/libwvdrmengine/cdm/core/include/cdm_session.h b/libwvdrmengine/cdm/core/include/cdm_session.h index fd740833..aa4cc57e 100644 --- a/libwvdrmengine/cdm/core/include/cdm_session.h +++ b/libwvdrmengine/cdm/core/include/cdm_session.h @@ -59,11 +59,7 @@ class CdmSession { CdmResponseType QueryKeyControlInfo(CdmQueryMap* key_info); // Decrypt() - Accept encrypted buffer and return decrypted data. - CdmResponseType Decrypt(bool is_encrypted, bool is_secure, - const KeyId& key_id, const uint8_t* encrypt_buffer, - size_t encrypt_length, const std::vector& iv, - size_t block_offset, void* decrypt_buffer, - size_t decrypt_buffer_offset, bool is_video); + CdmResponseType Decrypt(const CdmDecryptionParameters& parameters); // License renewal // GenerateRenewalRequest() - Construct valid renewal request for the current diff --git a/libwvdrmengine/cdm/core/include/crypto_session.h b/libwvdrmengine/cdm/core/include/crypto_session.h index 588f855f..758594e0 100644 --- a/libwvdrmengine/cdm/core/include/crypto_session.h +++ b/libwvdrmengine/cdm/core/include/crypto_session.h @@ -68,15 +68,7 @@ class CryptoSession { // Media data path bool SelectKey(const std::string& key_id); - CdmResponseType Decrypt(bool is_encrypted, - bool is_secure, - const uint8_t* encrypt_buffer, - size_t encrypt_length, - const std::vector& iv, - size_t block_offset, - void* decrypt_buffer, - size_t decrypt_buffer_offset, - bool is_video); + CdmResponseType Decrypt(const CdmDecryptionParameters& parameters); bool GetRandom(uint8_t* random_data, size_t data_length); diff --git a/libwvdrmengine/cdm/core/include/wv_cdm_types.h b/libwvdrmengine/cdm/core/include/wv_cdm_types.h index e2ec0da5..f65b3c16 100644 --- a/libwvdrmengine/cdm/core/include/wv_cdm_types.h +++ b/libwvdrmengine/cdm/core/include/wv_cdm_types.h @@ -41,7 +41,7 @@ enum CdmResponseType { }; #define CORE_DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&); \ + TypeName(const TypeName&); \ void operator=(const TypeName&) enum CdmEventType { @@ -55,6 +55,50 @@ enum CdmLicenseType { kLicenseTypeRelease }; +struct CdmDecryptionParameters { + bool is_encrypted; + bool is_secure; + const KeyId* key_id; + const uint8_t* encrypt_buffer; + size_t encrypt_length; + const std::vector* iv; + size_t block_offset; + void* decrypt_buffer; + size_t decrypt_buffer_length; + size_t decrypt_buffer_offset; + uint8_t subsample_flags; + bool is_video; + CdmDecryptionParameters() + : is_encrypted(true), + is_secure(true), + key_id(NULL), + encrypt_buffer(NULL), + encrypt_length(0), + iv(NULL), + block_offset(0), + decrypt_buffer(NULL), + decrypt_buffer_length(0), + decrypt_buffer_offset(0), + subsample_flags(0), + is_video(true) {} + CdmDecryptionParameters(const KeyId* key, const uint8_t* encrypted_buffer, + size_t encrypted_length, + const std::vector* initialization_vector, + size_t offset, void* decrypted_buffer) + : is_encrypted(true), + is_secure(true), + key_id(key), + encrypt_buffer(encrypted_buffer), + encrypt_length(encrypted_length), + iv(initialization_vector), + block_offset(offset), + decrypt_buffer(decrypted_buffer), + decrypt_buffer_length(encrypted_length), + decrypt_buffer_offset(0), + subsample_flags(0), + is_video(true) {} +}; + // forward class references class KeyMessage; class Request; diff --git a/libwvdrmengine/cdm/core/src/cdm_engine.cpp b/libwvdrmengine/cdm/core/src/cdm_engine.cpp index 9601c53c..9b61ff3c 100644 --- a/libwvdrmengine/cdm/core/src/cdm_engine.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_engine.cpp @@ -458,26 +458,34 @@ CdmResponseType CdmEngine::ReleaseSecureStops( CdmResponseType CdmEngine::Decrypt( const CdmSessionId& session_id, - bool is_encrypted, - bool is_secure, - const KeyId& key_id, - const uint8_t* encrypt_buffer, - size_t encrypt_length, - const std::vector& iv, - size_t block_offset, - void* decrypt_buffer, - size_t decrypt_buffer_offset, - bool is_video) { + const CdmDecryptionParameters& parameters) { + if (parameters.key_id == NULL) { + LOGE("CdmEngine::Decrypt: no key_id"); + return KEY_ERROR; + } + + if (parameters.encrypt_buffer == NULL) { + LOGE("CdmEngine::Decrypt: no src encrypt buffer"); + return KEY_ERROR; + } + + if (parameters.iv == NULL) { + LOGE("CdmEngine::Decrypt: no iv"); + return KEY_ERROR; + } + + if (parameters.decrypt_buffer == NULL) { + LOGE("CdmEngine::Decrypt: no dest decrypt buffer"); + return KEY_ERROR; + } + CdmSessionMap::iterator iter = sessions_.find(session_id); if (iter == sessions_.end()) { LOGW("CdmEngine::Decrypt: session_id not found = %s", session_id.c_str()); return KEY_ERROR; } - return iter->second->Decrypt(is_encrypted, is_secure, key_id, encrypt_buffer, - encrypt_length, iv, block_offset, - decrypt_buffer, decrypt_buffer_offset, - is_video); + return iter->second->Decrypt(parameters); } bool CdmEngine::IsKeyValid(const KeyId& key_id) { diff --git a/libwvdrmengine/cdm/core/src/cdm_session.cpp b/libwvdrmengine/cdm/core/src/cdm_session.cpp index 9f0edf48..225b9a0d 100644 --- a/libwvdrmengine/cdm/core/src/cdm_session.cpp +++ b/libwvdrmengine/cdm/core/src/cdm_session.cpp @@ -217,8 +217,15 @@ CdmResponseType CdmSession::QueryKeyStatus(CdmQueryMap* key_info) { } CdmResponseType CdmSession::QueryKeyControlInfo(CdmQueryMap* key_info) { - if (crypto_session_.get() == NULL || !crypto_session_->IsOpen()) + if (crypto_session_.get() == NULL) { + LOGW("CdmSession::QueryKeyControlInfo: Invalid crypto session"); return UNKNOWN_ERROR; + } + + if (!crypto_session_->IsOpen()) { + LOGW("CdmSession::QueryKeyControlInfo: Crypto session not open"); + return UNKNOWN_ERROR; + } std::stringstream ss; ss << crypto_session_->oec_session_id(); @@ -234,28 +241,22 @@ CdmResponseType CdmSession::CancelKeyRequest() { } // Decrypt() - Accept encrypted buffer and return decrypted data. -CdmResponseType CdmSession::Decrypt( - bool is_encrypted, bool is_secure, const KeyId& key_id, - const uint8_t* encrypt_buffer, size_t encrypt_length, - const std::vector& iv, size_t block_offset, void* decrypt_buffer, - size_t decrypt_buffer_offset, bool is_video) { +CdmResponseType CdmSession::Decrypt(const CdmDecryptionParameters& params) { if (crypto_session_.get() == NULL || !crypto_session_->IsOpen()) return UNKNOWN_ERROR; // Check if key needs to be selected - if (is_encrypted) { - if (key_id_.compare(key_id) != 0) { - if (crypto_session_->SelectKey(key_id)) { - key_id_ = key_id; + if (params.is_encrypted) { + if (key_id_.compare(*params.key_id) != 0) { + if (crypto_session_->SelectKey(*params.key_id)) { + key_id_ = *params.key_id; } else { return NEED_KEY; } } } - return crypto_session_->Decrypt( - is_encrypted, is_secure, encrypt_buffer, encrypt_length, iv, block_offset, - decrypt_buffer, decrypt_buffer_offset, is_video); + return crypto_session_->Decrypt(params); } // License renewal diff --git a/libwvdrmengine/cdm/core/src/crypto_session.cpp b/libwvdrmengine/cdm/core/src/crypto_session.cpp index 83be8476..998ebe18 100755 --- a/libwvdrmengine/cdm/core/src/crypto_session.cpp +++ b/libwvdrmengine/cdm/core/src/crypto_session.cpp @@ -529,39 +529,41 @@ bool CryptoSession::GenerateSignature(const std::string& message, bool use_rsa, return true; } -CdmResponseType CryptoSession::Decrypt( - bool is_encrypted, bool is_secure, const uint8_t* encrypt_buffer, - size_t encrypt_length, const std::vector& iv, size_t block_offset, - void* decrypt_buffer, size_t decrypt_buffer_offset, bool is_video) { +CdmResponseType CryptoSession::Decrypt(const CdmDecryptionParameters& params) { if (!is_destination_buffer_type_valid_) { if (!SetDestinationBufferType()) return UNKNOWN_ERROR; } OEMCrypto_DestBufferDesc buffer_descriptor; buffer_descriptor.type = - is_secure ? destination_buffer_type_ : OEMCrypto_BufferType_Clear; + params.is_secure ? destination_buffer_type_ : OEMCrypto_BufferType_Clear; switch (buffer_descriptor.type) { case OEMCrypto_BufferType_Clear: buffer_descriptor.buffer.clear.address = - static_cast(decrypt_buffer) + decrypt_buffer_offset; - buffer_descriptor.buffer.clear.max_length = encrypt_length; + static_cast(params.decrypt_buffer) + params.decrypt_buffer_offset; + buffer_descriptor.buffer.clear.max_length = params.decrypt_buffer_length; break; case OEMCrypto_BufferType_Secure: - buffer_descriptor.buffer.secure.handle = decrypt_buffer; - buffer_descriptor.buffer.secure.offset = decrypt_buffer_offset; - buffer_descriptor.buffer.secure.max_length = encrypt_length; + buffer_descriptor.buffer.secure.handle = params.decrypt_buffer; + buffer_descriptor.buffer.secure.offset = params.decrypt_buffer_offset; + buffer_descriptor.buffer.secure.max_length = params.decrypt_buffer_length; break; case OEMCrypto_BufferType_Direct: buffer_descriptor.type = OEMCrypto_BufferType_Direct; - buffer_descriptor.buffer.direct.is_video = is_video; + buffer_descriptor.buffer.direct.is_video = params.is_video; break; } OEMCryptoResult sts = OEMCrypto_DecryptCTR( - oec_session_id_, encrypt_buffer, encrypt_length, is_encrypted, &iv[0], - block_offset, &buffer_descriptor, - OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample); + oec_session_id_, + params.encrypt_buffer, + params.encrypt_length, + params.is_encrypted, + &(*params.iv).front(), + params.block_offset, + &buffer_descriptor, + params.subsample_flags); if (OEMCrypto_SUCCESS != sts) { return UNKNOWN_ERROR; diff --git a/libwvdrmengine/cdm/include/wv_content_decryption_module.h b/libwvdrmengine/cdm/include/wv_content_decryption_module.h index 17388ba0..9efd74b6 100644 --- a/libwvdrmengine/cdm/include/wv_content_decryption_module.h +++ b/libwvdrmengine/cdm/include/wv_content_decryption_module.h @@ -56,8 +56,7 @@ class WvContentDecryptionModule { // Provisioning related methods virtual CdmResponseType GetProvisioningRequest( - CdmProvisioningRequest* request, - std::string* default_url); + CdmProvisioningRequest* request, std::string* default_url); virtual CdmResponseType HandleProvisioningResponse( CdmProvisioningResponse& response); @@ -67,23 +66,20 @@ class WvContentDecryptionModule { virtual CdmResponseType ReleaseSecureStops( const CdmSecureStopReleaseMessage& message); - // Accept encrypted buffer and return decrypted data. + // Accept encrypted buffer and decrypt data. + // Decryption parameters that need to be specified are + // is_encrypted, is_secure, key_id, encrypt_buffer, encrypt_length, + // iv, block_offset, decrypt_buffer, decrypt_buffer_length, + // decrypt_buffer_offset and subsample_flags virtual CdmResponseType Decrypt(const CdmSessionId& session_id, - bool is_encrypted, - bool is_secure, - const KeyId& key_id, - const uint8_t* encrypt_buffer, - size_t encrypt_length, - const std::vector& iv, - size_t block_offset, - void* decrypt_buffer, - size_t decrypt_buffer_offset); + const CdmDecryptionParameters& parameters); // Event listener related methods virtual bool AttachEventListener(const CdmSessionId& session_id, WvCdmEventListener* listener); virtual bool DetachEventListener(const CdmSessionId& session_id, WvCdmEventListener* listener); + private: // instance variables diff --git a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp index 814bb931..537f62a5 100644 --- a/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp +++ b/libwvdrmengine/cdm/src/wv_content_decryption_module.cpp @@ -11,16 +11,13 @@ namespace wvcdm { -WvContentDecryptionModule::WvContentDecryptionModule() : - cdm_engine_(new CdmEngine()) { -} +WvContentDecryptionModule::WvContentDecryptionModule() + : cdm_engine_(new CdmEngine()) {} -WvContentDecryptionModule::~WvContentDecryptionModule() { -} +WvContentDecryptionModule::~WvContentDecryptionModule() {} CdmResponseType WvContentDecryptionModule::OpenSession( - const CdmKeySystem& key_system, - CdmSessionId* session_id) { + const CdmKeySystem& key_system, CdmSessionId* session_id) { return cdm_engine_->OpenSession(key_system, session_id); } @@ -75,26 +72,22 @@ CdmResponseType WvContentDecryptionModule::CancelKeyRequest( return cdm_engine_->CancelKeyRequest(session_id); } -CdmResponseType WvContentDecryptionModule::QueryStatus( - CdmQueryMap* key_info) { +CdmResponseType WvContentDecryptionModule::QueryStatus(CdmQueryMap* key_info) { return cdm_engine_->QueryStatus(key_info); } CdmResponseType WvContentDecryptionModule::QueryKeyStatus( - const CdmSessionId& session_id, - CdmQueryMap* key_info) { + const CdmSessionId& session_id, CdmQueryMap* key_info) { return cdm_engine_->QueryKeyStatus(session_id, key_info); } CdmResponseType WvContentDecryptionModule::QueryKeyControlInfo( - const CdmSessionId& session_id, - CdmQueryMap* key_info) { + const CdmSessionId& session_id, CdmQueryMap* key_info) { return cdm_engine_->QueryKeyControlInfo(session_id, key_info); } CdmResponseType WvContentDecryptionModule::GetProvisioningRequest( - CdmProvisioningRequest* request, - std::string* default_url) { + CdmProvisioningRequest* request, std::string* default_url) { return cdm_engine_->GetProvisioningRequest(request, default_url); } @@ -115,30 +108,17 @@ CdmResponseType WvContentDecryptionModule::ReleaseSecureStops( CdmResponseType WvContentDecryptionModule::Decrypt( const CdmSessionId& session_id, - bool is_encrypted, - bool is_secure, - const KeyId& key_id, - const uint8_t* encrypt_buffer, - size_t encrypt_length, - const std::vector& iv, - size_t block_offset, - void* decrypt_buffer, - size_t decrypt_buffer_offset) { - return cdm_engine_->Decrypt(session_id, is_encrypted, is_secure, key_id, - encrypt_buffer, encrypt_length, iv, - block_offset, decrypt_buffer, - decrypt_buffer_offset, true); + const CdmDecryptionParameters& parameters) { + return cdm_engine_->Decrypt(session_id, parameters); } bool WvContentDecryptionModule::AttachEventListener( - const CdmSessionId& session_id, - WvCdmEventListener* listener) { + const CdmSessionId& session_id, WvCdmEventListener* listener) { return cdm_engine_->AttachEventListener(session_id, listener); } bool WvContentDecryptionModule::DetachEventListener( - const CdmSessionId& session_id, - WvCdmEventListener* listener) { + const CdmSessionId& session_id, WvCdmEventListener* listener) { return cdm_engine_->DetachEventListener(session_id, listener); } diff --git a/libwvdrmengine/cdm/test/request_license_test.cpp b/libwvdrmengine/cdm/test/request_license_test.cpp index 26cc1445..af10b093 100644 --- a/libwvdrmengine/cdm/test/request_license_test.cpp +++ b/libwvdrmengine/cdm/test/request_license_test.cpp @@ -8,6 +8,7 @@ #include "gtest/gtest.h" #include "license_request.h" #include "log.h" +#include "OEMCryptoCENC.h" #include "string_conversions.h" #include "url_request.h" #include "wv_cdm_constants.h" @@ -28,15 +29,163 @@ int g_use_full_path = 0; // cannot use boolean in getopt_long namespace wvcdm { -typedef struct DecryptionData { +// TODO(rfrias): refactor to print out the decryption test names +struct SubSampleInfo { + bool retrieve_key; + size_t num_of_subsamples; bool is_encrypted; bool is_secure; wvcdm::KeyId key_id; std::vector encrypt_data; + std::vector decrypt_data; std::vector iv; size_t block_offset; - std::vector decrypt_data; -} DecryptionData; +}; + +SubSampleInfo clear_sub_sample = { + true, 1, false, false, wvcdm::a2bs_hex("E02562E04CD55351B14B3D748D36ED8E"), + wvcdm::a2b_hex( + "9da401105ab8da443e93e6fe089dfc69e00a9a51690d406872f338c5fa7dd3d5" + "abf8dfd660aaff3e327850a56eedf707c03e2d1a00f9f0371e3e19ea32b13267" + "7bc083ccbb83e6d9c03794ee97f50081221a8e5eb123f6dfa895e7a971166483" + "cdadd61cd8d0f859501e750e9d356d57252ecd9f7388459f5470de9d92198c44" + "0b520055b3b9a1c6b2c9d21e78dce99622d9d031fc7dee28a6d1d6dfb81502eb" + "463c4c189555f496d9aa529b3f5522e9f46dcf70b2bfe8df47daf02b6a267f93" + "f80d871786eb4bd7f08f9c52079c034a9534d885ba4c00cbe2234cfbb5205a56" + "41dd760f83d0f09f27881ad490efa8b99b7ab24b34311a2e8416b1a80d736ad7"), + wvcdm::a2b_hex( + "9da401105ab8da443e93e6fe089dfc69e00a9a51690d406872f338c5fa7dd3d5" + "abf8dfd660aaff3e327850a56eedf707c03e2d1a00f9f0371e3e19ea32b13267" + "7bc083ccbb83e6d9c03794ee97f50081221a8e5eb123f6dfa895e7a971166483" + "cdadd61cd8d0f859501e750e9d356d57252ecd9f7388459f5470de9d92198c44" + "0b520055b3b9a1c6b2c9d21e78dce99622d9d031fc7dee28a6d1d6dfb81502eb" + "463c4c189555f496d9aa529b3f5522e9f46dcf70b2bfe8df47daf02b6a267f93" + "f80d871786eb4bd7f08f9c52079c034a9534d885ba4c00cbe2234cfbb5205a56" + "41dd760f83d0f09f27881ad490efa8b99b7ab24b34311a2e8416b1a80d736ad7"), + wvcdm::a2b_hex("50a6c61c3f7c2b37e72b0c047000dd4a"), 0}; + +SubSampleInfo clear_sub_sample_no_key = { + false, 1, false, false, wvcdm::a2bs_hex("77777777777777777777777777777777"), + wvcdm::a2b_hex( + "9da401105ab8da443e93e6fe089dfc69e00a9a51690d406872f338c5fa7dd3d5" + "abf8dfd660aaff3e327850a56eedf707c03e2d1a00f9f0371e3e19ea32b13267" + "7bc083ccbb83e6d9c03794ee97f50081221a8e5eb123f6dfa895e7a971166483" + "cdadd61cd8d0f859501e750e9d356d57252ecd9f7388459f5470de9d92198c44" + "0b520055b3b9a1c6b2c9d21e78dce99622d9d031fc7dee28a6d1d6dfb81502eb" + "463c4c189555f496d9aa529b3f5522e9f46dcf70b2bfe8df47daf02b6a267f93" + "f80d871786eb4bd7f08f9c52079c034a9534d885ba4c00cbe2234cfbb5205a56" + "41dd760f83d0f09f27881ad490efa8b99b7ab24b34311a2e8416b1a80d736ad7"), + wvcdm::a2b_hex( + "9da401105ab8da443e93e6fe089dfc69e00a9a51690d406872f338c5fa7dd3d5" + "abf8dfd660aaff3e327850a56eedf707c03e2d1a00f9f0371e3e19ea32b13267" + "7bc083ccbb83e6d9c03794ee97f50081221a8e5eb123f6dfa895e7a971166483" + "cdadd61cd8d0f859501e750e9d356d57252ecd9f7388459f5470de9d92198c44" + "0b520055b3b9a1c6b2c9d21e78dce99622d9d031fc7dee28a6d1d6dfb81502eb" + "463c4c189555f496d9aa529b3f5522e9f46dcf70b2bfe8df47daf02b6a267f93" + "f80d871786eb4bd7f08f9c52079c034a9534d885ba4c00cbe2234cfbb5205a56" + "41dd760f83d0f09f27881ad490efa8b99b7ab24b34311a2e8416b1a80d736ad7"), + wvcdm::a2b_hex("50a6c61c3f7c2b37e72b0c047000dd4a"), 0}; + +SubSampleInfo single_encrypted_sub_sample = { + // key 1, encrypted, 256b + true, 1, true, false, wvcdm::a2bs_hex("E02562E04CD55351B14B3D748D36ED8E"), + wvcdm::a2b_hex( + "3b2cbde084973539329bd5656da22d20396249bf4a18a51c38c4743360cc9fea" + "a1c78d53de1bd7e14dc5d256fd20a57178a98b83804258c239acd7aa38f2d7d2" + "eca614965b3d22049e19e236fc1800e60965d8b36415677bf2f843d50a6943c4" + "683c07c114a32f5e5fbc9939c483c3a1b2ecd3d82b554d649798866191724283" + "f0ab082eba2da79aaca5c4eaf186f9ee9a0c568f621f705a578f30e4e2ef7b96" + "5e14cc046ce6dbf272ee5558b098f332333e95fc879dea6c29bf34acdb649650" + "f08201b9e649960f2493fd7677cc3abf5ae70e5445845c947ba544456b431646" + "d95a133bff5f57614dda5e4446cd8837901d074149dadf4b775b5b07bb88ca20"), + wvcdm::a2b_hex( + "5a36c0b633b58faf22156d78fdfb608e54a8095788b2b0463ef78d030b4abf82" + "eff34b8d9b7b6352e7d72de991b599662aa475da355033620152e2356ebfadee" + "06172be9e1058fa177e223b9fdd191380cff53c3ea810c6fd852a1df4967b799" + "415179a2276ec388ef763bab89605b9c6952c28dc8d6bf86b03fabbb46b392a3" + "1dad15be602eeeeabb45070b3e25d6bb0217073b1fc44c9fe848594121fd6a91" + "304d605e21f69615e1b57db18312b6b948725724b74e91d8aea7371e99532469" + "1b358bdee873f1936b63efe83d190a53c2d21754d302d63ff285174023473755" + "58b938c2e3ca4c2ce48942da97f9e45797f2c074ac6004734e93784a48af6160"), + wvcdm::a2b_hex("4cca615fc013102892f91efee936639b"), 0}; + +SubSampleInfo switch_key_encrypted_sub_sample[2] = { + // block 0, key 1, encrypted, 256b + {true, 2, true, false, wvcdm::a2bs_hex("E02562E04CD55351B14B3D748D36ED8E"), + wvcdm::a2b_hex( + "3b2cbde084973539329bd5656da22d20396249bf4a18a51c38c4743360cc9fea" + "a1c78d53de1bd7e14dc5d256fd20a57178a98b83804258c239acd7aa38f2d7d2" + "eca614965b3d22049e19e236fc1800e60965d8b36415677bf2f843d50a6943c4" + "683c07c114a32f5e5fbc9939c483c3a1b2ecd3d82b554d649798866191724283" + "f0ab082eba2da79aaca5c4eaf186f9ee9a0c568f621f705a578f30e4e2ef7b96" + "5e14cc046ce6dbf272ee5558b098f332333e95fc879dea6c29bf34acdb649650" + "f08201b9e649960f2493fd7677cc3abf5ae70e5445845c947ba544456b431646" + "d95a133bff5f57614dda5e4446cd8837901d074149dadf4b775b5b07bb88ca20"), + wvcdm::a2b_hex( + "5a36c0b633b58faf22156d78fdfb608e54a8095788b2b0463ef78d030b4abf82" + "eff34b8d9b7b6352e7d72de991b599662aa475da355033620152e2356ebfadee" + "06172be9e1058fa177e223b9fdd191380cff53c3ea810c6fd852a1df4967b799" + "415179a2276ec388ef763bab89605b9c6952c28dc8d6bf86b03fabbb46b392a3" + "1dad15be602eeeeabb45070b3e25d6bb0217073b1fc44c9fe848594121fd6a91" + "304d605e21f69615e1b57db18312b6b948725724b74e91d8aea7371e99532469" + "1b358bdee873f1936b63efe83d190a53c2d21754d302d63ff285174023473755" + "58b938c2e3ca4c2ce48942da97f9e45797f2c074ac6004734e93784a48af6160"), + wvcdm::a2b_hex("4cca615fc013102892f91efee936639b"), 0}, + // block 1, key 3, encrypted, 256b + {true, 2, true, false, wvcdm::a2bs_hex("0065901A64A25899A5193664ABF9AF62"), + wvcdm::a2b_hex( + "337f294addb4c16d1015fd839e80314472432eda503bd0529422318bec7d2b34" + "2b28d24b2c0bf999fd31711901a2b90e03373cb9553ffd4b2e6e655b80a39fe8" + "61718220948f0031a37fe277f943409d09c83ff1c19fe8d601f5b4d139821750" + "47170006db5f38cb84706a9beeaa455fca3b17d8de90c143eb36aaaac3f4670a" + "7194064f4d59996c95992a3e6a848d4da8adddae3ad03c8d28110fda3e5c1d0a" + "35d175c816481275a02d2da96c7fc313864ae076f03887309cdf00ca856bad28" + "2146141964b7f7972e9b253b1fbed6d74ffedcfc51bb91fa78a602479b0b757f" + "53a16cca15c381a4eab3034ee38e12280982d575fe3de23dd65cf8ba240daa88"), + wvcdm::a2b_hex( + "c397c1c9bc6782cd859e92f7158e3ff2a54ee984869582b942b400c22ebb6843" + "7c50f999f73831fa12040f6aab607f57280189ff1db1ab1d0046ffaa55ce1790" + "3baf0f9c983351b2ff15cc4f61f0f8db6922804e74a207e1e5baaeca67b427c7" + "2dd7883ee8232041a9c4e56ccfb8bdc3016602c73fa8944e734ee34c41cf1a17" + "b009b404fd924d23dfee1f494b5e374c9e87c2910de36826044bff89939a70d2" + "47ff1a8a0baa7643026b8d9442fda69dde6802816ddd4b6e3b18f0a95e788d6d" + "166ed7435ef663ef019b4438d3e203734eb95d68758e028f29cd623f35cde4bd" + "edfea33ade378a92a356020bcf3fbba01c9ab16ad448ce6ebe708f768c6676a7"), + wvcdm::a2b_hex("6d4ee851e563b951119cd33c52aadbf5"), 0}}; + +SubSampleInfo partial_single_encrypted_sub_sample = { + // key 3, encrypted, 125b, offset 0 + true, 1, true, false, wvcdm::a2bs_hex("0065901A64A25899A5193664ABF9AF62"), + wvcdm::a2b_hex( + "337f294addb4c16d1015fd839e80314472432eda503bd0529422318bec7d2b34" + "2b28d24b2c0bf999fd31711901a2b90e03373cb9553ffd4b2e6e655b80a39fe8" + "61718220948f0031a37fe277f943409d09c83ff1c19fe8d601f5b4d139821750" + "47170006db5f38cb84706a9beeaa455fca3b17d8de90c143eb36aaaac3"), + wvcdm::a2b_hex( + "c397c1c9bc6782cd859e92f7158e3ff2a54ee984869582b942b400c22ebb6843" + "7c50f999f73831fa12040f6aab607f57280189ff1db1ab1d0046ffaa55ce1790" + "3baf0f9c983351b2ff15cc4f61f0f8db6922804e74a207e1e5baaeca67b427c7" + "2dd7883ee8232041a9c4e56ccfb8bdc3016602c73fa8944e734ee34c41"), + wvcdm::a2b_hex("6d4ee851e563b951119cd33c52aadbf5"), 0}; + +SubSampleInfo partial_offset_single_encrypted_sub_sample = { + // key 3, encrypted, 123b, offset 5 + true, 1, true, false, wvcdm::a2bs_hex("0065901A64A25899A5193664ABF9AF62"), + wvcdm::a2b_hex( + "97f39b919ba56f3c3a51ecdcd7318bc130f054320c74db3990f925" + "054734c03ec79ee0da68938dc4f8c2d91e46ec2342ef24f9328294a9475f7ead" + "8ad3e71db62d6328e826e4ab375f4796aa2bc8b9266551e3007fb3c253780293" + "31fbc32ed29afcb9e7152cf072712c5a22c6b52d60e381eb53eeb58d36528746"), + wvcdm::a2b_hex( + "d36911b44f470ff05d152a7bc69ea6b68aa812cd3676964acb4597" + "b518fe4b7ec0fe44469b1e4f8806922af9ac998d3e23349cea0e68f833564c15" + "e49584f94ef16b7ab6cd2d0b152430f1fb4d7644a0f591980388ac02012d3d42" + "73d6c9604517b1a622b66b8f4e8414e40b00351cc9859061bde810190c7b5df8"), + wvcdm::a2b_hex("43ba341482212c70f79d81c0f4faef8a"), 5}; + +} // namespace + +namespace wvcdm { class TestWvCdmEventListener : public WvCdmEventListener { public: @@ -183,6 +332,10 @@ class WvCdmRequestLicenseTest : public testing::Test { CdmKeySetId key_set_id_; }; +class WvCdmDecryptionTest + : public WvCdmRequestLicenseTest, + public ::testing::WithParamInterface {}; + TEST_F(WvCdmRequestLicenseTest, ProvisioningTest) { decryptor_.OpenSession(g_key_system, &session_id_); std::string provisioning_server_url; @@ -430,294 +583,37 @@ TEST_F(WvCdmRequestLicenseTest, QueryKeyControlInfo) { decryptor_.CloseSession(session_id_); } -TEST_F(WvCdmRequestLicenseTest, ClearDecryptionTest) { +TEST_P(WvCdmDecryptionTest, DecryptionTest) { + SubSampleInfo* data = GetParam(); decryptor_.OpenSession(g_key_system, &session_id_); - GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming); - VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false); + if (data->retrieve_key) { + GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming); + VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false); + } - // key 1, clear, 256b - DecryptionData data; - data.is_encrypted = false; - data.is_secure = false; - data.key_id = wvcdm::a2bs_hex("E02562E04CD55351B14B3D748D36ED8E"); - data.encrypt_data = wvcdm::a2b_hex( - "9da401105ab8da443e93e6fe089dfc69e00a9a51690d406872f338c5fa7dd3d5" - "abf8dfd660aaff3e327850a56eedf707c03e2d1a00f9f0371e3e19ea32b13267" - "7bc083ccbb83e6d9c03794ee97f50081221a8e5eb123f6dfa895e7a971166483" - "cdadd61cd8d0f859501e750e9d356d57252ecd9f7388459f5470de9d92198c44" - "0b520055b3b9a1c6b2c9d21e78dce99622d9d031fc7dee28a6d1d6dfb81502eb" - "463c4c189555f496d9aa529b3f5522e9f46dcf70b2bfe8df47daf02b6a267f93" - "f80d871786eb4bd7f08f9c52079c034a9534d885ba4c00cbe2234cfbb5205a56" - "41dd760f83d0f09f27881ad490efa8b99b7ab24b34311a2e8416b1a80d736ad7"); - data.iv = wvcdm::a2b_hex("50a6c61c3f7c2b37e72b0c047000dd4a"); - data.block_offset = 0; - data.decrypt_data = wvcdm::a2b_hex( - "9da401105ab8da443e93e6fe089dfc69e00a9a51690d406872f338c5fa7dd3d5" - "abf8dfd660aaff3e327850a56eedf707c03e2d1a00f9f0371e3e19ea32b13267" - "7bc083ccbb83e6d9c03794ee97f50081221a8e5eb123f6dfa895e7a971166483" - "cdadd61cd8d0f859501e750e9d356d57252ecd9f7388459f5470de9d92198c44" - "0b520055b3b9a1c6b2c9d21e78dce99622d9d031fc7dee28a6d1d6dfb81502eb" - "463c4c189555f496d9aa529b3f5522e9f46dcf70b2bfe8df47daf02b6a267f93" - "f80d871786eb4bd7f08f9c52079c034a9534d885ba4c00cbe2234cfbb5205a56" - "41dd760f83d0f09f27881ad490efa8b99b7ab24b34311a2e8416b1a80d736ad7"); + for (size_t i = 0; i < data->num_of_subsamples; i++) { + std::vector decrypt_buffer((data + i)->encrypt_data.size()); + CdmDecryptionParameters decryption_parameters( + &(data + i)->key_id, &(data + i)->encrypt_data.front(), + (data + i)->encrypt_data.size(), &(data + i)->iv, + (data + i)->block_offset, &decrypt_buffer[0]); + decryption_parameters.is_encrypted = (data + i)->is_encrypted; + decryption_parameters.is_secure = (data + i)->is_secure; + EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id_, decryption_parameters)); - std::vector decrypt_buffer; - size_t encrypt_length = data.encrypt_data.size(); - decrypt_buffer.resize(encrypt_length); - - EXPECT_EQ(NO_ERROR, - decryptor_.Decrypt(session_id_, data.is_encrypted, data.is_secure, - data.key_id, &data.encrypt_data.front(), - encrypt_length, data.iv, data.block_offset, - &decrypt_buffer.front(), 0)); - - EXPECT_TRUE(std::equal(data.decrypt_data.begin(), data.decrypt_data.end(), - decrypt_buffer.begin())); - decryptor_.CloseSession(session_id_); -} - -TEST_F(WvCdmRequestLicenseTest, ClearDecryptionNoKeyTest) { - decryptor_.OpenSession(g_key_system, &session_id_); - - // key 1, clear, 256b - DecryptionData data; - data.is_encrypted = false; - data.is_secure = false; - data.key_id = wvcdm::a2bs_hex("77777777777777777777777777777777"); - data.encrypt_data = wvcdm::a2b_hex( - "9da401105ab8da443e93e6fe089dfc69e00a9a51690d406872f338c5fa7dd3d5" - "abf8dfd660aaff3e327850a56eedf707c03e2d1a00f9f0371e3e19ea32b13267" - "7bc083ccbb83e6d9c03794ee97f50081221a8e5eb123f6dfa895e7a971166483" - "cdadd61cd8d0f859501e750e9d356d57252ecd9f7388459f5470de9d92198c44" - "0b520055b3b9a1c6b2c9d21e78dce99622d9d031fc7dee28a6d1d6dfb81502eb" - "463c4c189555f496d9aa529b3f5522e9f46dcf70b2bfe8df47daf02b6a267f93" - "f80d871786eb4bd7f08f9c52079c034a9534d885ba4c00cbe2234cfbb5205a56" - "41dd760f83d0f09f27881ad490efa8b99b7ab24b34311a2e8416b1a80d736ad7"); - data.iv = wvcdm::a2b_hex("50a6c61c3f7c2b37e72b0c047000dd4a"); - data.block_offset = 0; - data.decrypt_data = wvcdm::a2b_hex( - "9da401105ab8da443e93e6fe089dfc69e00a9a51690d406872f338c5fa7dd3d5" - "abf8dfd660aaff3e327850a56eedf707c03e2d1a00f9f0371e3e19ea32b13267" - "7bc083ccbb83e6d9c03794ee97f50081221a8e5eb123f6dfa895e7a971166483" - "cdadd61cd8d0f859501e750e9d356d57252ecd9f7388459f5470de9d92198c44" - "0b520055b3b9a1c6b2c9d21e78dce99622d9d031fc7dee28a6d1d6dfb81502eb" - "463c4c189555f496d9aa529b3f5522e9f46dcf70b2bfe8df47daf02b6a267f93" - "f80d871786eb4bd7f08f9c52079c034a9534d885ba4c00cbe2234cfbb5205a56" - "41dd760f83d0f09f27881ad490efa8b99b7ab24b34311a2e8416b1a80d736ad7"); - - std::vector decrypt_buffer; - size_t encrypt_length = data.encrypt_data.size(); - decrypt_buffer.resize(encrypt_length); - - EXPECT_EQ(NO_ERROR, - decryptor_.Decrypt(session_id_, data.is_encrypted, data.is_secure, - data.key_id, &data.encrypt_data.front(), - encrypt_length, data.iv, data.block_offset, - &decrypt_buffer.front(), 0)); - - EXPECT_TRUE(std::equal(data.decrypt_data.begin(), data.decrypt_data.end(), - decrypt_buffer.begin())); - decryptor_.CloseSession(session_id_); -} - -TEST_F(WvCdmRequestLicenseTest, DecryptionTest) { - decryptor_.OpenSession(g_key_system, &session_id_); - GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming); - VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false); - - // key 1, encrypted, 256b - DecryptionData data; - data.is_encrypted = true; - data.is_secure = false; - data.key_id = wvcdm::a2bs_hex("E02562E04CD55351B14B3D748D36ED8E"); - data.encrypt_data = wvcdm::a2b_hex( - "3b2cbde084973539329bd5656da22d20396249bf4a18a51c38c4743360cc9fea" - "a1c78d53de1bd7e14dc5d256fd20a57178a98b83804258c239acd7aa38f2d7d2" - "eca614965b3d22049e19e236fc1800e60965d8b36415677bf2f843d50a6943c4" - "683c07c114a32f5e5fbc9939c483c3a1b2ecd3d82b554d649798866191724283" - "f0ab082eba2da79aaca5c4eaf186f9ee9a0c568f621f705a578f30e4e2ef7b96" - "5e14cc046ce6dbf272ee5558b098f332333e95fc879dea6c29bf34acdb649650" - "f08201b9e649960f2493fd7677cc3abf5ae70e5445845c947ba544456b431646" - "d95a133bff5f57614dda5e4446cd8837901d074149dadf4b775b5b07bb88ca20"); - data.iv = wvcdm::a2b_hex("4cca615fc013102892f91efee936639b"); - data.block_offset = 0; - data.decrypt_data = wvcdm::a2b_hex( - "5a36c0b633b58faf22156d78fdfb608e54a8095788b2b0463ef78d030b4abf82" - "eff34b8d9b7b6352e7d72de991b599662aa475da355033620152e2356ebfadee" - "06172be9e1058fa177e223b9fdd191380cff53c3ea810c6fd852a1df4967b799" - "415179a2276ec388ef763bab89605b9c6952c28dc8d6bf86b03fabbb46b392a3" - "1dad15be602eeeeabb45070b3e25d6bb0217073b1fc44c9fe848594121fd6a91" - "304d605e21f69615e1b57db18312b6b948725724b74e91d8aea7371e99532469" - "1b358bdee873f1936b63efe83d190a53c2d21754d302d63ff285174023473755" - "58b938c2e3ca4c2ce48942da97f9e45797f2c074ac6004734e93784a48af6160"); - - std::vector decrypt_buffer; - size_t encrypt_length = data.encrypt_data.size(); - decrypt_buffer.resize(encrypt_length); - - EXPECT_EQ(NO_ERROR, - decryptor_.Decrypt(session_id_, data.is_encrypted, data.is_secure, - data.key_id, &data.encrypt_data.front(), - encrypt_length, data.iv, data.block_offset, - &decrypt_buffer.front(), 0)); - - EXPECT_TRUE(std::equal(data.decrypt_data.begin(), data.decrypt_data.end(), - decrypt_buffer.begin())); - decryptor_.CloseSession(session_id_); -} - -TEST_F(WvCdmRequestLicenseTest, SwitchKeyDecryptionTest) { - decryptor_.OpenSession(g_key_system, &session_id_); - GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming); - VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false); - - uint8_t data_blocks = 2; - DecryptionData data[data_blocks]; - - // block 0, key 1, encrypted, 256b - data[0].is_encrypted = true; - data[0].is_secure = false; - data[0].key_id = wvcdm::a2bs_hex("E02562E04CD55351B14B3D748D36ED8E"); - data[0].encrypt_data = wvcdm::a2b_hex( - "3b2cbde084973539329bd5656da22d20396249bf4a18a51c38c4743360cc9fea" - "a1c78d53de1bd7e14dc5d256fd20a57178a98b83804258c239acd7aa38f2d7d2" - "eca614965b3d22049e19e236fc1800e60965d8b36415677bf2f843d50a6943c4" - "683c07c114a32f5e5fbc9939c483c3a1b2ecd3d82b554d649798866191724283" - "f0ab082eba2da79aaca5c4eaf186f9ee9a0c568f621f705a578f30e4e2ef7b96" - "5e14cc046ce6dbf272ee5558b098f332333e95fc879dea6c29bf34acdb649650" - "f08201b9e649960f2493fd7677cc3abf5ae70e5445845c947ba544456b431646" - "d95a133bff5f57614dda5e4446cd8837901d074149dadf4b775b5b07bb88ca20"); - data[0].iv = wvcdm::a2b_hex("4cca615fc013102892f91efee936639b"); - data[0].block_offset = 0; - data[0].decrypt_data = wvcdm::a2b_hex( - "5a36c0b633b58faf22156d78fdfb608e54a8095788b2b0463ef78d030b4abf82" - "eff34b8d9b7b6352e7d72de991b599662aa475da355033620152e2356ebfadee" - "06172be9e1058fa177e223b9fdd191380cff53c3ea810c6fd852a1df4967b799" - "415179a2276ec388ef763bab89605b9c6952c28dc8d6bf86b03fabbb46b392a3" - "1dad15be602eeeeabb45070b3e25d6bb0217073b1fc44c9fe848594121fd6a91" - "304d605e21f69615e1b57db18312b6b948725724b74e91d8aea7371e99532469" - "1b358bdee873f1936b63efe83d190a53c2d21754d302d63ff285174023473755" - "58b938c2e3ca4c2ce48942da97f9e45797f2c074ac6004734e93784a48af6160"); - - // block 1, key 3, encrypted, 256b - data[1].is_encrypted = true; - data[1].is_secure = false; - data[1].key_id = wvcdm::a2bs_hex("0065901A64A25899A5193664ABF9AF62"); - data[1].encrypt_data = wvcdm::a2b_hex( - "337f294addb4c16d1015fd839e80314472432eda503bd0529422318bec7d2b34" - "2b28d24b2c0bf999fd31711901a2b90e03373cb9553ffd4b2e6e655b80a39fe8" - "61718220948f0031a37fe277f943409d09c83ff1c19fe8d601f5b4d139821750" - "47170006db5f38cb84706a9beeaa455fca3b17d8de90c143eb36aaaac3f4670a" - "7194064f4d59996c95992a3e6a848d4da8adddae3ad03c8d28110fda3e5c1d0a" - "35d175c816481275a02d2da96c7fc313864ae076f03887309cdf00ca856bad28" - "2146141964b7f7972e9b253b1fbed6d74ffedcfc51bb91fa78a602479b0b757f" - "53a16cca15c381a4eab3034ee38e12280982d575fe3de23dd65cf8ba240daa88"); - data[1].iv = wvcdm::a2b_hex("6d4ee851e563b951119cd33c52aadbf5"); - data[1].block_offset = 0; - data[1].decrypt_data = wvcdm::a2b_hex( - "c397c1c9bc6782cd859e92f7158e3ff2a54ee984869582b942b400c22ebb6843" - "7c50f999f73831fa12040f6aab607f57280189ff1db1ab1d0046ffaa55ce1790" - "3baf0f9c983351b2ff15cc4f61f0f8db6922804e74a207e1e5baaeca67b427c7" - "2dd7883ee8232041a9c4e56ccfb8bdc3016602c73fa8944e734ee34c41cf1a17" - "b009b404fd924d23dfee1f494b5e374c9e87c2910de36826044bff89939a70d2" - "47ff1a8a0baa7643026b8d9442fda69dde6802816ddd4b6e3b18f0a95e788d6d" - "166ed7435ef663ef019b4438d3e203734eb95d68758e028f29cd623f35cde4bd" - "edfea33ade378a92a356020bcf3fbba01c9ab16ad448ce6ebe708f768c6676a7"); - std::vector decrypt_buffer; - - for (int i = 0; i < data_blocks; ++i) { - size_t encrypt_length = data[i].encrypt_data.size(); - decrypt_buffer.resize(encrypt_length); - - EXPECT_EQ( - NO_ERROR, - decryptor_.Decrypt(session_id_, data[i].is_encrypted, data[i].is_secure, - data[i].key_id, &data[i].encrypt_data.front(), - encrypt_length, data[i].iv, data[i].block_offset, - &decrypt_buffer.front(), 0)); - - EXPECT_TRUE(std::equal(data[i].decrypt_data.begin(), - data[i].decrypt_data.end(), decrypt_buffer.begin())); + EXPECT_TRUE(std::equal((data + i)->decrypt_data.begin(), + (data + i)->decrypt_data.end(), + decrypt_buffer.begin())); } decryptor_.CloseSession(session_id_); } -TEST_F(WvCdmRequestLicenseTest, PartialBlockDecryptionTest) { - decryptor_.OpenSession(g_key_system, &session_id_); - GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming); - VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false); - - // key 3, encrypted, 125b, offset 0 - DecryptionData data; - data.is_encrypted = true; - data.is_secure = false; - data.key_id = wvcdm::a2bs_hex("0065901A64A25899A5193664ABF9AF62"); - data.encrypt_data = wvcdm::a2b_hex( - "337f294addb4c16d1015fd839e80314472432eda503bd0529422318bec7d2b34" - "2b28d24b2c0bf999fd31711901a2b90e03373cb9553ffd4b2e6e655b80a39fe8" - "61718220948f0031a37fe277f943409d09c83ff1c19fe8d601f5b4d139821750" - "47170006db5f38cb84706a9beeaa455fca3b17d8de90c143eb36aaaac3"); - data.iv = wvcdm::a2b_hex("6d4ee851e563b951119cd33c52aadbf5"); - data.block_offset = 0; - data.decrypt_data = wvcdm::a2b_hex( - "c397c1c9bc6782cd859e92f7158e3ff2a54ee984869582b942b400c22ebb6843" - "7c50f999f73831fa12040f6aab607f57280189ff1db1ab1d0046ffaa55ce1790" - "3baf0f9c983351b2ff15cc4f61f0f8db6922804e74a207e1e5baaeca67b427c7" - "2dd7883ee8232041a9c4e56ccfb8bdc3016602c73fa8944e734ee34c41"); - - std::vector decrypt_buffer; - size_t encrypt_length = data.encrypt_data.size(); - decrypt_buffer.resize(encrypt_length); - - EXPECT_EQ(NO_ERROR, - decryptor_.Decrypt(session_id_, data.is_encrypted, data.is_secure, - data.key_id, &data.encrypt_data.front(), - encrypt_length, data.iv, data.block_offset, - &decrypt_buffer.front(), 0)); - - EXPECT_TRUE(std::equal(data.decrypt_data.begin(), data.decrypt_data.end(), - decrypt_buffer.begin())); - decryptor_.CloseSession(session_id_); -} - -TEST_F(WvCdmRequestLicenseTest, PartialBlockWithOffsetDecryptionTest) { - decryptor_.OpenSession(g_key_system, &session_id_); - GenerateKeyRequest(g_key_system, g_key_id, kLicenseTypeStreaming); - VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false); - - // key 3, encrypted, 123b, offset 5 - DecryptionData data; - data.is_encrypted = true; - data.is_secure = false; - data.key_id = wvcdm::a2bs_hex("0065901A64A25899A5193664ABF9AF62"); - data.encrypt_data = wvcdm::a2b_hex( - "97f39b919ba56f3c3a51ecdcd7318bc130f054320c74db3990f925" - "054734c03ec79ee0da68938dc4f8c2d91e46ec2342ef24f9328294a9475f7ead" - "8ad3e71db62d6328e826e4ab375f4796aa2bc8b9266551e3007fb3c253780293" - "31fbc32ed29afcb9e7152cf072712c5a22c6b52d60e381eb53eeb58d36528746"); - data.iv = wvcdm::a2b_hex("43ba341482212c70f79d81c0f4faef8a"); - data.block_offset = 5; - data.decrypt_data = wvcdm::a2b_hex( - "d36911b44f470ff05d152a7bc69ea6b68aa812cd3676964acb4597" - "b518fe4b7ec0fe44469b1e4f8806922af9ac998d3e23349cea0e68f833564c15" - "e49584f94ef16b7ab6cd2d0b152430f1fb4d7644a0f591980388ac02012d3d42" - "73d6c9604517b1a622b66b8f4e8414e40b00351cc9859061bde810190c7b5df8"); - - std::vector decrypt_buffer; - size_t encrypt_length = data.encrypt_data.size(); - decrypt_buffer.resize(encrypt_length); - - EXPECT_EQ(NO_ERROR, - decryptor_.Decrypt(session_id_, data.is_encrypted, data.is_secure, - data.key_id, &data.encrypt_data.front(), - encrypt_length, data.iv, data.block_offset, - &decrypt_buffer.front(), 0)); - - EXPECT_TRUE(std::equal(data.decrypt_data.begin(), data.decrypt_data.end(), - decrypt_buffer.begin())); - - decryptor_.CloseSession(session_id_); -} +INSTANTIATE_TEST_CASE_P( + Cdm, WvCdmDecryptionTest, + ::testing::Values(&clear_sub_sample, &clear_sub_sample_no_key, + &single_encrypted_sub_sample, + &switch_key_encrypted_sub_sample[0], + &partial_single_encrypted_sub_sample)); TEST_F(WvCdmRequestLicenseTest, DISABLED_OfflineLicenseDecryptionTest) { decryptor_.OpenSession(g_key_system, &session_id_); diff --git a/libwvdrmengine/mediacrypto/Android.mk b/libwvdrmengine/mediacrypto/Android.mk index 76544000..9b6eb3d0 100644 --- a/libwvdrmengine/mediacrypto/Android.mk +++ b/libwvdrmengine/mediacrypto/Android.mk @@ -14,6 +14,7 @@ LOCAL_C_INCLUDES := \ vendor/widevine/libwvdrmengine/cdm/include \ vendor/widevine/libwvdrmengine/include \ vendor/widevine/libwvdrmengine/mediacrypto/include \ + vendor/widevine/libwvdrmengine/oemcrypto/include \ LOCAL_MODULE := libwvdrmcryptoplugin diff --git a/libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp b/libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp index 6bcc682a..64250671 100644 --- a/libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp +++ b/libwvdrmengine/mediacrypto/src/WVCryptoPlugin.cpp @@ -15,6 +15,7 @@ #include "mapErrors-inl.h" #include "media/stagefright/MediaErrors.h" +#include "OEMCryptoCENC.h" #include "openssl/sha.h" #include "utils/Errors.h" #include "utils/String8.h" @@ -83,6 +84,22 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE], const uint8_t* const source = static_cast(srcPtr); uint8_t* const dest = static_cast(dstPtr); + // Calculate the output buffer size + size_t destSize = 0; + for (size_t i = 0; i < numSubSamples; i++) { + const SubSample &subSample = subSamples[i]; + destSize += subSample.mNumBytesOfClearData; + destSize += subSample.mNumBytesOfEncryptedData; + } + + // Set up the decrypt params that do not vary. + CdmDecryptionParameters params = CdmDecryptionParameters(); + params.is_secure = secure; + params.key_id = &keyId; + params.iv = &ivVector; + params.decrypt_buffer = dest; + params.decrypt_buffer_length = destSize; + // Iterate through subsamples, sending them to the CDM serially. size_t offset = 0; static const size_t kAESBlockSize = 16; @@ -97,13 +114,40 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE], return kErrorExpectedUnencrypted; } + // Calculate any flags that apply to this subsample's parts. + uint8_t clearFlags = 0; + uint8_t encryptedFlags = 0; + + // If this is the first subsample… + if (i == 0) { + // …add OEMCrypto_FirstSubsample to the first part that is present. + if (subSample.mNumBytesOfClearData != 0) { + clearFlags = clearFlags | OEMCrypto_FirstSubsample; + } else { + encryptedFlags = encryptedFlags | OEMCrypto_FirstSubsample; + } + } + // If this is the last subsample… + if (i == numSubSamples - 1) { + // …add OEMCrypto_LastSubsample to the last part that is present + if (subSample.mNumBytesOfEncryptedData != 0) { + encryptedFlags = encryptedFlags | OEMCrypto_LastSubsample; + } else { + clearFlags = clearFlags | OEMCrypto_LastSubsample; + } + } + // "Decrypt" any unencrypted data. Per the ISO-CENC standard, clear data // comes before encrypted data. if (subSample.mNumBytesOfClearData != 0) { - CdmResponseType res = mCDM->Decrypt(mSessionId, false, secure, keyId, - source + offset, - subSample.mNumBytesOfClearData, - ivVector, 0, dest, offset); + params.is_encrypted = false; + params.encrypt_buffer = source + offset; + params.encrypt_length = subSample.mNumBytesOfClearData; + params.block_offset = 0; + params.decrypt_buffer_offset = offset; + params.subsample_flags = clearFlags; + + CdmResponseType res = mCDM->Decrypt(mSessionId, params); if (!isCdmResponseTypeSuccess(res)) { ALOGE("Decrypt error result in session %s during unencrypted block: %d", @@ -118,10 +162,14 @@ ssize_t WVCryptoPlugin::decrypt(bool secure, const uint8_t key[KEY_ID_SIZE], // Decrypt any encrypted data. Per the ISO-CENC standard, encrypted data // comes after clear data. if (subSample.mNumBytesOfEncryptedData != 0) { - CdmResponseType res = mCDM->Decrypt(mSessionId, true, secure, keyId, - source + offset, - subSample.mNumBytesOfEncryptedData, - ivVector, blockOffset, dest, offset); + params.is_encrypted = true; + params.encrypt_buffer = source + offset; + params.encrypt_length = subSample.mNumBytesOfEncryptedData; + params.block_offset = blockOffset; + params.decrypt_buffer_offset = offset; + params.subsample_flags = encryptedFlags; + + CdmResponseType res = mCDM->Decrypt(mSessionId, params); if (!isCdmResponseTypeSuccess(res)) { ALOGE("Decrypt error result in session %s during encrypted block: %d", diff --git a/libwvdrmengine/mediacrypto/test/Android.mk b/libwvdrmengine/mediacrypto/test/Android.mk index edca99f8..67a43d4b 100644 --- a/libwvdrmengine/mediacrypto/test/Android.mk +++ b/libwvdrmengine/mediacrypto/test/Android.mk @@ -13,6 +13,7 @@ LOCAL_C_INCLUDES := \ vendor/widevine/libwvdrmengine/cdm/core/include \ vendor/widevine/libwvdrmengine/cdm/include \ vendor/widevine/libwvdrmengine/mediacrypto/include \ + vendor/widevine/libwvdrmengine/oemcrypto/include \ vendor/widevine/libwvdrmengine/test/gmock/include \ LOCAL_STATIC_LIBRARIES := \ diff --git a/libwvdrmengine/mediacrypto/test/WVCryptoPlugin_test.cpp b/libwvdrmengine/mediacrypto/test/WVCryptoPlugin_test.cpp index a2878641..344ac5f6 100644 --- a/libwvdrmengine/mediacrypto/test/WVCryptoPlugin_test.cpp +++ b/libwvdrmengine/mediacrypto/test/WVCryptoPlugin_test.cpp @@ -10,6 +10,7 @@ #include "gtest/gtest.h" #include "media/stagefright/foundation/ABase.h" #include "media/stagefright/foundation/AString.h" +#include "OEMCryptoCENC.h" #include "wv_cdm_constants.h" #include "wv_cdm_types.h" #include "wv_content_decryption_module.h" @@ -23,10 +24,8 @@ using namespace wvdrm; class MockCDM : public WvContentDecryptionModule { public: - MOCK_METHOD10(Decrypt, CdmResponseType(const CdmSessionId&, bool, bool, - const KeyId&, const uint8_t*, size_t, - const std::vector&, size_t, - void*, size_t)); + MOCK_METHOD2(Decrypt, CdmResponseType(const CdmSessionId&, + const CdmDecryptionParameters&)); MOCK_METHOD1(QueryStatus, CdmResponseType(CdmQueryMap*)); }; @@ -70,6 +69,74 @@ TEST_F(WVCryptoPluginTest, CorrectlyReportsSecureBuffers) { "WVCryptoPlugin incorrectly expects a secure audio decoder"; } +// Factory for matchers that perform deep matching of values against a +// CdmDecryptionParameters struct. For use in the test AttemptsToDecrypt. +class CDPMatcherFactory { + public: + // Some values do not change over the course of the test. To avoid having + // to re-specify them at every call site, we pass them into the factory + // constructor. + CDPMatcherFactory(bool isSecure, uint8_t* keyId, void* out, size_t outLen) + : mIsSecure(isSecure), mKeyId(keyId), mOut(out), mOutLen(outLen) {} + + Matcher operator()(bool isEncrypted, + uint8_t* in, + size_t inLen, + uint8_t* iv, + size_t blockOffset, + size_t outOffset, + uint8_t flags) const { + return Truly(CDPMatcher(mIsSecure, mKeyId, mOut, mOutLen, isEncrypted, + in, inLen, iv, blockOffset, outOffset, flags)); + } + + private: + // Predicate that validates that the fields of a passed-in + // CdmDecryptionParameters match the values it was given at construction + // time. + class CDPMatcher { + public: + CDPMatcher(bool isSecure, uint8_t* keyId, void* out, size_t outLen, + bool isEncrypted, uint8_t* in, size_t inLen, uint8_t* iv, + size_t blockOffset, size_t outOffset, uint8_t flags) + : mIsSecure(isSecure), mKeyId(keyId), mOut(out), mOutLen(outLen), + mIsEncrypted(isEncrypted), mIn(in), mInLen(inLen), mIv(iv), + mBlockOffset(blockOffset), mOutOffset(outOffset), mFlags(flags) {} + + bool operator()(const CdmDecryptionParameters& params) const { + return params.is_secure == mIsSecure && + Value(*params.key_id, ElementsAreArray(mKeyId, KEY_ID_SIZE)) && + params.decrypt_buffer == mOut && + params.decrypt_buffer_length == mOutLen && + params.is_encrypted == mIsEncrypted && + params.encrypt_buffer == mIn && + params.encrypt_length == mInLen && + Value(*params.iv, ElementsAreArray(mIv, KEY_IV_SIZE)) && + params.block_offset == mBlockOffset && + params.decrypt_buffer_offset == mOutOffset && + params.subsample_flags == mFlags; + } + + private: + bool mIsSecure; + uint8_t* mKeyId; + void* mOut; + size_t mOutLen; + bool mIsEncrypted; + uint8_t* mIn; + size_t mInLen; + uint8_t* mIv; + size_t mBlockOffset; + size_t mOutOffset; + uint8_t mFlags; + }; + + bool mIsSecure; + uint8_t* mKeyId; + void* mOut; + size_t mOutLen; +}; + TEST_F(WVCryptoPluginTest, AttemptsToDecrypt) { StrictMock cdm; WVCryptoPlugin plugin(sessionId, kSessionIdSize, &cdm); @@ -111,61 +178,49 @@ TEST_F(WVCryptoPluginTest, AttemptsToDecrypt) { memcpy(iv[4], baseIv, sizeof(baseIv)); iv[4][15] = 7; + CDPMatcherFactory ParamsAre = CDPMatcherFactory(false, keyId, out, kDataSize); + { InSequence calls; // SubSample 0 - EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true, - false, ElementsAreArray(keyId, KEY_ID_SIZE), - in, 16, ElementsAreArray(iv[0], KEY_IV_SIZE), - 0, out, 0)) + EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), + ParamsAre(true, in, 16, iv[0], 0, 0, + OEMCrypto_FirstSubsample))) .Times(1); // SubSample 1 - EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), false, - false, ElementsAreArray(keyId, KEY_ID_SIZE), - in + 16, 16, ElementsAreArray(iv[1], KEY_IV_SIZE), - 0, out, 16)) + EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), + ParamsAre(false, in + 16, 16, iv[1], 0, 16, 0))) .Times(1); - EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true, - false, ElementsAreArray(keyId, KEY_ID_SIZE), - in + 32, 16, ElementsAreArray(iv[1], KEY_IV_SIZE), - 0, out, 32)) + EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), + ParamsAre(true, in + 32, 16, iv[1], 0, 32, 0))) .Times(1); // SubSample 2 - EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true, - false, ElementsAreArray(keyId, KEY_ID_SIZE), - in + 48, 8, ElementsAreArray(iv[2], KEY_IV_SIZE), - 0, out, 48)) + EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), + ParamsAre(true, in + 48, 8, iv[2], 0, 48, 0))) .Times(1); // SubSample 3 - EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), false, - false, ElementsAreArray(keyId, KEY_ID_SIZE), - in + 56, 29, ElementsAreArray(iv[2], KEY_IV_SIZE), - 0, out, 56)) + EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), + ParamsAre(false, in + 56, 29, iv[2], 0, 56, 0))) .Times(1); - EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true, - false, ElementsAreArray(keyId, KEY_ID_SIZE), - in + 85, 24, ElementsAreArray(iv[2], KEY_IV_SIZE), - 8, out, 85)) + EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), + ParamsAre(true, in + 85, 24, iv[2], 8, 85, 0))) .Times(1); // SubSample 4 - EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true, - false, ElementsAreArray(keyId, KEY_ID_SIZE), - in + 109, 60, ElementsAreArray(iv[3], KEY_IV_SIZE), - 0, out, 109)) + EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), + ParamsAre(true, in + 109, 60, iv[3], 0, 109, 0))) .Times(1); // SubSample 5 - EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), true, - false, ElementsAreArray(keyId, KEY_ID_SIZE), - in + 169, 16, ElementsAreArray(iv[4], KEY_IV_SIZE), - 12, out, 169)) + EXPECT_CALL(cdm, Decrypt(ElementsAreArray(sessionId, kSessionIdSize), + ParamsAre(true, in + 169, 16, iv[4], 12, 169, + OEMCrypto_LastSubsample))) .Times(1); } @@ -208,10 +263,12 @@ TEST_F(WVCryptoPluginTest, CommunicatesSecureBufferRequest) { { InSequence calls; - EXPECT_CALL(cdm, Decrypt(_, _, false, _, _, _, _, _, _, _)) + typedef CdmDecryptionParameters CDP; + + EXPECT_CALL(cdm, Decrypt(_, Field(&CDP::is_secure, false))) .Times(2); - EXPECT_CALL(cdm, Decrypt(_, _, true, _, _, _, _, _, _, _)) + EXPECT_CALL(cdm, Decrypt(_, Field(&CDP::is_secure, true))) .Times(2); } @@ -232,3 +289,81 @@ TEST_F(WVCryptoPluginTest, CommunicatesSecureBufferRequest) { EXPECT_EQ(0u, errorDetailMessage.size()) << "WVCryptoPlugin reported a detailed error message."; } + +TEST_F(WVCryptoPluginTest, SetsFlagsForMinimumSubsampleRuns) { + MockCDM cdm; + WVCryptoPlugin plugin(sessionId, kSessionIdSize, &cdm); + + uint8_t keyId[KEY_ID_SIZE]; + uint8_t iv[KEY_IV_SIZE]; + + static const size_t kDataSize = 16; + uint8_t in[kDataSize]; + uint8_t out[kDataSize]; + + FILE* fp = fopen("/dev/urandom", "r"); + fread(keyId, sizeof(uint8_t), KEY_ID_SIZE, fp); + fread(iv, sizeof(uint8_t), KEY_IV_SIZE, fp); + fread(in, sizeof(uint8_t), kDataSize, fp); + fclose(fp); + + static const uint32_t kSubSampleCount = 1; + CryptoPlugin::SubSample clearSubSamples[kSubSampleCount]; + memset(clearSubSamples, 0, sizeof(clearSubSamples)); + clearSubSamples[0].mNumBytesOfClearData = 16; + + CryptoPlugin::SubSample encryptedSubSamples[kSubSampleCount]; + memset(encryptedSubSamples, 0, sizeof(encryptedSubSamples)); + encryptedSubSamples[0].mNumBytesOfEncryptedData = 16; + + CryptoPlugin::SubSample mixedSubSamples[kSubSampleCount]; + memset(mixedSubSamples, 0, sizeof(mixedSubSamples)); + mixedSubSamples[0].mNumBytesOfClearData = 8; + mixedSubSamples[0].mNumBytesOfEncryptedData = 8; + + // Specify the expected calls to Decrypt + { + InSequence calls; + + typedef CdmDecryptionParameters CDP; + + EXPECT_CALL(cdm, Decrypt(_, Field(&CDP::subsample_flags, + OEMCrypto_FirstSubsample | + OEMCrypto_LastSubsample))) + .Times(2); + + EXPECT_CALL(cdm, Decrypt(_, Field(&CDP::subsample_flags, + OEMCrypto_FirstSubsample))) + .Times(1); + + EXPECT_CALL(cdm, Decrypt(_, Field(&CDP::subsample_flags, + OEMCrypto_LastSubsample))) + .Times(1); + } + + AString errorDetailMessage; + + ssize_t res = plugin.decrypt(false, keyId, iv, CryptoPlugin::kMode_AES_CTR, + in, clearSubSamples, kSubSampleCount, out, + &errorDetailMessage); + ASSERT_GE(res, 0) << + "WVCryptoPlugin returned an error"; + EXPECT_EQ(0u, errorDetailMessage.size()) << + "WVCryptoPlugin reported a detailed error message."; + + res = plugin.decrypt(false, keyId, iv, CryptoPlugin::kMode_AES_CTR, in, + encryptedSubSamples, kSubSampleCount, out, + &errorDetailMessage); + ASSERT_GE(res, 0) << + "WVCryptoPlugin returned an error"; + EXPECT_EQ(0u, errorDetailMessage.size()) << + "WVCryptoPlugin reported a detailed error message."; + + res = plugin.decrypt(false, keyId, iv, CryptoPlugin::kMode_AES_CTR, in, + mixedSubSamples, kSubSampleCount, out, + &errorDetailMessage); + ASSERT_GE(res, 0) << + "WVCryptoPlugin returned an error"; + EXPECT_EQ(0u, errorDetailMessage.size()) << + "WVCryptoPlugin reported a detailed error message."; +} diff --git a/libwvdrmengine/oemcrypto/mock/Android.mk b/libwvdrmengine/oemcrypto/mock/Android.mk index 8501f15f..3ea3605a 100644 --- a/libwvdrmengine/oemcrypto/mock/Android.mk +++ b/libwvdrmengine/oemcrypto/mock/Android.mk @@ -2,21 +2,26 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) +CDM_SRC_DIR=../../cdm/src +CORE_SRC_DIR=../../cdm/core/src + LOCAL_SRC_FILES:= \ src/oemcrypto_engine_mock.cpp \ src/oemcrypto_key_mock.cpp \ src/oemcrypto_keybox_mock.cpp \ src/oemcrypto_mock.cpp \ - src/lock.cpp \ - src/log.cpp \ - src/string_conversions.cpp \ src/wvcrc.cpp \ + $(CDM_SRC_DIR)/lock.cpp \ + $(CDM_SRC_DIR)/log.cpp \ + $(CORE_SRC_DIR)/string_conversions.cpp \ LOCAL_MODULE_TAGS := tests LOCAL_C_INCLUDES += \ $(LOCAL_PATH)/../include \ $(LOCAL_PATH)/src \ + vendor/widevine/libwvdrmengine/cdm/core/include \ + vendor/widevine/libwvdrmengine/third_party/stringencoders/src \ bionic \ external/gtest/include \ external/openssl/include \ @@ -32,6 +37,7 @@ LOCAL_SHARED_LIBRARIES := \ libutils \ libz \ +LOCAL_WHOLE_STATIC_LIBRARIES := libmodp_b64 LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR_SHARED_LIBRARIES) LOCAL_MODULE := liboemcrypto diff --git a/libwvdrmengine/oemcrypto/mock/src/lock.cpp b/libwvdrmengine/oemcrypto/mock/src/lock.cpp deleted file mode 100644 index 6deccf8d..00000000 --- a/libwvdrmengine/oemcrypto/mock/src/lock.cpp +++ /dev/null @@ -1,34 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Lock class - provides a simple android specific mutex implementation - -#include "lock.h" -#include "utils/Mutex.h" - -namespace wvcdm { - -class Lock::Impl { - public: - android::Mutex lock_; -}; - -Lock::Lock() : impl_(new Lock::Impl()) { -} - -Lock::~Lock() { - delete impl_; -} - -void Lock::Acquire() { - impl_->lock_.lock(); -} - -void Lock::Release() { - impl_->lock_.unlock(); -} - -bool Lock::Try() { - return (impl_->lock_.tryLock() == 0); -} - -}; // namespace wvcdm diff --git a/libwvdrmengine/oemcrypto/mock/src/lock.h b/libwvdrmengine/oemcrypto/mock/src/lock.h deleted file mode 100644 index 76be6a29..00000000 --- a/libwvdrmengine/oemcrypto/mock/src/lock.h +++ /dev/null @@ -1,61 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Lock - Platform independent interface for a Mutex class -// -#ifndef OEMCRYPTO_LOCK_H_ -#define OEMCRYPTO_LOCK_H_ - -#include "wv_cdm_types.h" - -namespace wvcdm { - -// Simple lock class. The implementation is platform dependent. -// -// The lock must be unlocked by the thread that locked it. -// The lock is also not recursive (ie. cannot be taken multiple times). -class Lock { - public: - Lock(); - ~Lock(); - - void Acquire(); - void Release(); - - // Acquires a lock if not held and returns true. - // Returns false if the lock is held by another thread. - bool Try(); - - friend class AutoLock; - - private: - class Impl; - Impl *impl_; - - CORE_DISALLOW_COPY_AND_ASSIGN(Lock); -}; - -// Manages the lock automatically. It will be locked when AutoLock -// is constructed and release when AutoLock goes out of scope. -class AutoLock { - public: - explicit AutoLock(Lock& lock) : lock_(&lock) { - lock_->Acquire(); - } - - explicit AutoLock(Lock* lock) : lock_(lock) { - lock_->Acquire(); - } - - ~AutoLock() { - lock_->Release(); - } - - private: - Lock *lock_; - - CORE_DISALLOW_COPY_AND_ASSIGN(AutoLock); -}; - -}; // namespace wvcdm - -#endif // OEMCRYPTO_LOCK_H_ diff --git a/libwvdrmengine/oemcrypto/mock/src/log.cpp b/libwvdrmengine/oemcrypto/mock/src/log.cpp deleted file mode 100644 index 0446392a..00000000 --- a/libwvdrmengine/oemcrypto/mock/src/log.cpp +++ /dev/null @@ -1,35 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Log - implemented using the standard Android logging mechanism - -#define LOG_TAG "WVCdm" -#define LOG_BUF_SIZE 1024 - -#include "log.h" -#include "utils/Log.h" - -namespace wvcdm { - -void InitLogging(int argc, const char* const* argv) {} - -void Log(const char* file, int line, LogPriority level, const char* fmt, ...) { - va_list ap; - char buf[LOG_BUF_SIZE]; - va_start(ap, fmt); - vsnprintf(buf, LOG_BUF_SIZE, fmt, ap); - va_end(ap); - - android_LogPriority prio = ANDROID_LOG_VERBOSE; - - switch(level) { - case LOG_ERROR: prio = ANDROID_LOG_ERROR; break; - case LOG_WARN: prio = ANDROID_LOG_WARN; break; - case LOG_INFO: prio = ANDROID_LOG_INFO; break; - case LOG_DEBUG: prio = ANDROID_LOG_DEBUG; break; - case LOG_VERBOSE: prio = ANDROID_LOG_VERBOSE; break; - } - - __android_log_write(prio, LOG_TAG, buf); -} - -}; // namespace wvcdm diff --git a/libwvdrmengine/oemcrypto/mock/src/log.h b/libwvdrmengine/oemcrypto/mock/src/log.h deleted file mode 100644 index e5bbb519..00000000 --- a/libwvdrmengine/oemcrypto/mock/src/log.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. -// -// Log - Platform independent interface for a Logging class -// -#ifndef OEMCRYPTO_LOG_H_ -#define OEMCRYPTO_LOG_H_ - -namespace wvcdm { - -// Simple logging class. The implementation is platform dependent. - -typedef enum { - LOG_ERROR, - LOG_WARN, - LOG_INFO, - LOG_DEBUG, - LOG_VERBOSE -} LogPriority; - -// Required to enable/disable verbose logging (LOGV) in Chromium. In Chromium, -// verbose logging level is controlled using command line switches --v (global) -// or --vmodule (per module). This function calls logging::InitLogging to -// initialize logging, which should have already been included in most Chromium -// based binaries. However, it is typically not included by default in -// unittests, in particular, the unittests in CDM core need to call InitLogging -// to be able to control verbose logging in command line. -void InitLogging(int argc, const char* const* argv); - -void Log(const char* file, int line, LogPriority level, const char* fmt, ...); - -// Log APIs -#define LOGE(...) Log(__FILE__, __LINE__, wvcdm::LOG_ERROR, __VA_ARGS__) -#define LOGW(...) Log(__FILE__, __LINE__, wvcdm::LOG_WARN, __VA_ARGS__) -#define LOGI(...) Log(__FILE__, __LINE__, wvcdm::LOG_INFO, __VA_ARGS__) -#define LOGD(...) Log(__FILE__, __LINE__, wvcdm::LOG_DEBUG, __VA_ARGS__) -#define LOGV(...) Log(__FILE__, __LINE__, wvcdm::LOG_VERBOSE, __VA_ARGS__) - -}; // namespace wvcdm - -#endif // OEMCRYPTO_LOG_H_ diff --git a/libwvdrmengine/oemcrypto/mock/src/string_conversions.cpp b/libwvdrmengine/oemcrypto/mock/src/string_conversions.cpp deleted file mode 100644 index 5df30027..00000000 --- a/libwvdrmengine/oemcrypto/mock/src/string_conversions.cpp +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. - -#include "string_conversions.h" - -#include -#include -#include - -#include "log.h" - -namespace wvcdm { - -static bool CharToDigit(char ch, unsigned char* digit) { - if (ch >= '0' && ch <= '9') { - *digit = ch - '0'; - } else { - ch = tolower(ch); - if ((ch >= 'a') && (ch <= 'f')) { - *digit = ch - 'a' + 10; - } else { - return false; - } - } - return true; -} - -// converts an ascii hex string(2 bytes per digit) into a decimal byte string -std::vector a2b_hex(const std::string& byte) { - std::vector array(0); - unsigned int count = byte.size(); - if (count == 0 || (count % 2) != 0) { - LOGE("Invalid input size %u for string %s", count, byte.c_str()); - return array; - } - - for (unsigned int i = 0; i < count / 2; ++i) { - unsigned char msb = 0; // most significant 4 bits - unsigned char lsb = 0; // least significant 4 bits - if (!CharToDigit(byte[i * 2], &msb) || - !CharToDigit(byte[i * 2 + 1], &lsb)) { - LOGE("Invalid hex value %c%c at index %d", byte[i * 2], byte[i * 2 + 1], i); - return array; - } - array.push_back((msb << 4) | lsb); - } - return array; -} - -std::string b2a_hex(const std::vector& byte) { - return HexEncode(&byte[0], byte.size()); -} - -std::string HexEncode(const uint8_t* in_buffer, unsigned int size) { - static const char kHexChars[] = "0123456789ABCDEF"; - - // Each input byte creates two output hex characters. - std::string out_buffer(size * 2, '\0'); - - for (unsigned int i = 0; i < size; ++i) { - char byte = in_buffer[i]; - out_buffer[(i << 1)] = kHexChars[(byte >> 4) & 0xf]; - out_buffer[(i << 1) + 1] = kHexChars[byte & 0xf]; - } - return out_buffer; -} - -std::string IntToString(int value) { - // log10(2) ~= 0.3 bytes needed per bit or per byte log10(2**8) ~= 2.4. - // So round up to allocate 3 output characters per byte, plus 1 for '-'. - const int kOutputBufSize = 3 * sizeof(int) + 1; - char buffer[kOutputBufSize]; - memset(buffer, 0, kOutputBufSize); - snprintf(buffer, kOutputBufSize, "%d", value); - - std::string out_string(buffer, sizeof(buffer)); - return out_string; -} - -std::string UintToString(unsigned int value) { - // log10(2) ~= 0.3 bytes needed per bit or per byte log10(2**8) ~= 2.4. - // So round up to allocate 3 output characters per byte. - const int kOutputBufSize = 3 * sizeof(unsigned int); - char buffer[kOutputBufSize]; - memset(buffer, 0, kOutputBufSize); - snprintf(buffer, kOutputBufSize, "%u", value); - - std::string out_string(buffer, sizeof(buffer)); - return out_string; -} - -}; // namespace wvcdm diff --git a/libwvdrmengine/oemcrypto/mock/src/string_conversions.h b/libwvdrmengine/oemcrypto/mock/src/string_conversions.h deleted file mode 100644 index bf41eb9d..00000000 --- a/libwvdrmengine/oemcrypto/mock/src/string_conversions.h +++ /dev/null @@ -1,20 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. - -#ifndef OEMCRYPTO_STRING_CONVERSIONS_H_ -#define OEMCRYPTO_STRING_CONVERSIONS_H_ - -#include -#include - -namespace wvcdm { - -std::vector a2b_hex(const std::string& b); -std::string b2a_hex(const std::vector& b); -std::string HexEncode(const uint8_t* bytes, unsigned size); -std::string IntToString(int value); -std::string UintToString(unsigned int value); - - -}; // namespace wvcdm - -#endif // OEMCRYPTO_STRING_CONVERSIONS_H_ diff --git a/libwvdrmengine/oemcrypto/mock/src/wv_cdm_constants.h b/libwvdrmengine/oemcrypto/mock/src/wv_cdm_constants.h deleted file mode 100644 index b47e690a..00000000 --- a/libwvdrmengine/oemcrypto/mock/src/wv_cdm_constants.h +++ /dev/null @@ -1,14 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. - -#ifndef OEMCRYPTO_WV_CDM_CONSTANTS_H_ -#define OEMCRYPTO_WV_CDM_CONSTANTS_H_ - -namespace wvcdm { -static const size_t KEY_CONTROL_SIZE = 16; -static const size_t KEY_IV_SIZE = 16; -static const size_t KEY_PAD_SIZE = 16; -static const size_t KEY_SIZE = 16; -static const size_t MAC_KEY_SIZE = 32; -} // namespace wvcdm - -#endif // OEMCRYPTO_WV_CDM_CONSTANTS_H_ diff --git a/libwvdrmengine/oemcrypto/mock/src/wv_cdm_types.h b/libwvdrmengine/oemcrypto/mock/src/wv_cdm_types.h deleted file mode 100644 index bd3e21d6..00000000 --- a/libwvdrmengine/oemcrypto/mock/src/wv_cdm_types.h +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright 2013 Google Inc. All Rights Reserved. - -#ifndef OEMCRYPTO_WV_CDM_TYPES_H_ -#define OEMCRYPTO_WV_CDM_TYPES_H_ - -#include -#include -#include - -namespace wvcdm { - -typedef std::string CdmKeySystem; -typedef std::string CdmInitData; -typedef std::string CdmKeyMessage; -typedef std::string CdmKeyResponse; -typedef std::string KeyId; -typedef std::string CdmSessionId; -typedef std::string RequestId; -typedef uint32_t CryptoResult; -typedef uint32_t CryptoSessionId; -typedef std::string CryptoKeyId; - -enum CdmResponseType { - NO_ERROR, - UNKNOWN_ERROR, - KEY_ADDED, - KEY_ERROR, - KEY_MESSAGE, - NEED_KEY, - KEY_CANCELED, -}; - -#define CORE_DISALLOW_COPY_AND_ASSIGN(TypeName) \ - TypeName(const TypeName&); \ - void operator=(const TypeName&) - -enum CdmEventType { - LICENSE_EXPIRED, - LICENSE_RENEWAL_NEEDED -}; - -// forward class references -class KeyMessage; -class Request; -class Key; - -} // namespace wvcdm - -#endif // OEMCRYPTO_WV_CDM_TYPES_H_ diff --git a/libwvdrmengine/oemcrypto/test/Android.mk b/libwvdrmengine/oemcrypto/test/Android.mk index 4597888d..0e308d44 100644 --- a/libwvdrmengine/oemcrypto/test/Android.mk +++ b/libwvdrmengine/oemcrypto/test/Android.mk @@ -4,8 +4,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ - oemcrypto_test.cpp \ - ../../cdm/src/log.cpp \ + oemcrypto_test.cpp LOCAL_MODULE_TAGS := tests @@ -19,6 +18,8 @@ LOCAL_C_INCLUDES += \ external/stlport/stlport \ $(LOCAL_PATH)/../include \ $(LOCAL_PATH)/../mock/src \ + vendor/widevine/libwvdrmengine/cdm/core/include \ + vendor/widevine/libwvdrmengine/third_party/stringencoders/src \ # TODO(fredgc): fix order dependencies on libwvlevel3 and libwvwrapper. LOCAL_STATIC_LIBRARIES := \