Widevine CENC drm engine update: enable decryption
This import syncs to the widevine git repostiory change commit ab3e1e43642cf36900f55169597a33f222709fdb Change-Id: I3a6f1e2969e5fe7ed1ca12f90b0eb0a3b7899835
This commit is contained in:
@@ -81,11 +81,12 @@ class CdmEngine : public TimerHandler {
|
|||||||
CdmResponseType Decrypt(const CdmSessionId& session_id,
|
CdmResponseType Decrypt(const CdmSessionId& session_id,
|
||||||
bool is_encrypted,
|
bool is_encrypted,
|
||||||
const KeyId& key_id,
|
const KeyId& key_id,
|
||||||
const uint8_t* encrypted_buffer,
|
const uint8_t* encrypt_buffer,
|
||||||
size_t encrypted_size,
|
size_t encrypt_length,
|
||||||
const std::vector<uint8_t>& iv,
|
const std::vector<uint8_t>& iv,
|
||||||
size_t block_offset,
|
size_t block_offset,
|
||||||
uint8_t* decrypted_buffer);
|
void* decrypt_buffer,
|
||||||
|
bool is_video);
|
||||||
|
|
||||||
// Is the key known to any session?
|
// Is the key known to any session?
|
||||||
bool IsKeyValid(const KeyId& key_id);
|
bool IsKeyValid(const KeyId& key_id);
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ namespace wvcdm {
|
|||||||
|
|
||||||
class CdmSession {
|
class CdmSession {
|
||||||
public:
|
public:
|
||||||
CdmSession() : state_(INITIAL), session_id_(GenerateSessionId()) {}
|
CdmSession() : session_id_(GenerateSessionId()),
|
||||||
|
license_received_(false),
|
||||||
|
properties_valid_(false) {}
|
||||||
~CdmSession() {}
|
~CdmSession() {}
|
||||||
|
|
||||||
bool Init();
|
bool Init();
|
||||||
@@ -46,12 +48,14 @@ class CdmSession {
|
|||||||
CdmResponseType QueryKeyStatus(CdmQueryMap* key_info);
|
CdmResponseType QueryKeyStatus(CdmQueryMap* key_info);
|
||||||
|
|
||||||
// Decrypt() - Accept encrypted buffer and return decrypted data.
|
// Decrypt() - Accept encrypted buffer and return decrypted data.
|
||||||
CdmResponseType Decrypt(const uint8_t* encrypted_buffer,
|
CdmResponseType Decrypt(bool is_encrypted,
|
||||||
size_t encrypted_size,
|
|
||||||
size_t block_offset,
|
|
||||||
const std::vector<uint8_t>& iv,
|
|
||||||
const KeyId& key_id,
|
const KeyId& key_id,
|
||||||
uint8_t* decrypted_buffer);
|
const uint8_t* encrypt_buffer,
|
||||||
|
size_t encrypt_length,
|
||||||
|
const std::vector<uint8_t>& iv,
|
||||||
|
size_t block_offset,
|
||||||
|
void* decrypt_buffer,
|
||||||
|
bool is_video);
|
||||||
|
|
||||||
// License renewal
|
// License renewal
|
||||||
// GenerateRenewalRequest() - Construct valid renewal request for the current
|
// GenerateRenewalRequest() - Construct valid renewal request for the current
|
||||||
@@ -73,22 +77,18 @@ class CdmSession {
|
|||||||
// Generate unique ID for each new session.
|
// Generate unique ID for each new session.
|
||||||
CdmSessionId GenerateSessionId();
|
CdmSessionId GenerateSessionId();
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
INITIAL,
|
|
||||||
LICENSE_REQUESTED,
|
|
||||||
LICENSE_RESPONSE_DONE,
|
|
||||||
RENEWAL_ENABLED,
|
|
||||||
RENEWAL_REQUESTED,
|
|
||||||
LICENSE_EXPIRED
|
|
||||||
} CdmSessionState;
|
|
||||||
|
|
||||||
// instance variables
|
// instance variables
|
||||||
CdmSessionState state_;
|
|
||||||
const CdmSessionId session_id_;
|
const CdmSessionId session_id_;
|
||||||
CdmKeySystem key_system_;
|
CdmKeySystem key_system_;
|
||||||
CdmLicense license_parser_;
|
CdmLicense license_parser_;
|
||||||
CryptoSession* crypto_session_;
|
CryptoSession* crypto_session_;
|
||||||
PolicyEngine policy_engine_;
|
PolicyEngine policy_engine_;
|
||||||
|
bool license_received_;
|
||||||
|
|
||||||
|
bool properties_valid_;
|
||||||
|
bool require_explicit_renew_request_;
|
||||||
|
|
||||||
|
KeyId key_id_;
|
||||||
|
|
||||||
std::set<WvCdmEventListener*> listeners_;
|
std::set<WvCdmEventListener*> listeners_;
|
||||||
|
|
||||||
|
|||||||
@@ -38,7 +38,21 @@ class CryptoEngine {
|
|||||||
|
|
||||||
bool GetToken(std::string* token);
|
bool GetToken(std::string* token);
|
||||||
|
|
||||||
CdmResponseType Query(CdmQueryMap* info);
|
typedef enum {
|
||||||
|
kSecurityLevelL1,
|
||||||
|
kSecurityLevelL2,
|
||||||
|
kSecurityLevelL3,
|
||||||
|
kSecurityLevelUnknown
|
||||||
|
} SecurityLevel;
|
||||||
|
|
||||||
|
SecurityLevel GetSecurityLevel();
|
||||||
|
|
||||||
|
bool properties_valid() const { return properties_valid_; }
|
||||||
|
bool oem_crypto_use_secure_buffers() const
|
||||||
|
{ return oem_crypto_use_secure_buffers_; }
|
||||||
|
bool oem_crypto_use_fifo() const { return oem_crypto_use_fifo_; }
|
||||||
|
bool oem_crypto_use_userspace_buffers() const
|
||||||
|
{ return oem_crypto_use_userspace_buffers_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -55,6 +69,11 @@ private:
|
|||||||
mutable Lock sessions_lock_;
|
mutable Lock sessions_lock_;
|
||||||
CryptoSessionMap sessions_;
|
CryptoSessionMap sessions_;
|
||||||
|
|
||||||
|
bool properties_valid_;
|
||||||
|
bool oem_crypto_use_secure_buffers_;
|
||||||
|
bool oem_crypto_use_fifo_;
|
||||||
|
bool oem_crypto_use_userspace_buffers_;
|
||||||
|
|
||||||
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine);
|
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,16 +9,13 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "crypto_key.h"
|
#include "crypto_key.h"
|
||||||
|
#include "OEMCryptoCENC.h"
|
||||||
#include "wv_cdm_types.h"
|
#include "wv_cdm_types.h"
|
||||||
|
|
||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
|
|
||||||
typedef std::map<CryptoKeyId,CryptoKey*> CryptoKeyMap;
|
typedef std::map<CryptoKeyId,CryptoKey*> CryptoKeyMap;
|
||||||
|
|
||||||
// TODO(gmorgan): fill out input and output descriptors
|
|
||||||
typedef void* InputDescriptor;
|
|
||||||
typedef void* OutputDescriptor;
|
|
||||||
|
|
||||||
class CryptoSession {
|
class CryptoSession {
|
||||||
public:
|
public:
|
||||||
CryptoSession();
|
CryptoSession();
|
||||||
@@ -55,12 +52,13 @@ class CryptoSession {
|
|||||||
|
|
||||||
// Media data path
|
// Media data path
|
||||||
bool SelectKey(const std::string& key_id);
|
bool SelectKey(const std::string& key_id);
|
||||||
bool Decrypt(const InputDescriptor input, OutputDescriptor output);
|
CdmResponseType Decrypt(bool is_encrypted,
|
||||||
bool Decrypt(const uint8_t* encrypted_buffer,
|
const uint8_t* encrypt_buffer,
|
||||||
size_t encrypted_size,
|
size_t encrypt_length,
|
||||||
size_t block_offset,
|
const std::vector<uint8_t>& iv,
|
||||||
const std::vector<uint8_t>& iv,
|
size_t block_offset,
|
||||||
uint8_t* decrypted_buffer);
|
void* decrypt_buffer,
|
||||||
|
bool is_video);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
@@ -69,6 +67,7 @@ class CryptoSession {
|
|||||||
void GenerateEncryptContext(const std::string& input_context,
|
void GenerateEncryptContext(const std::string& input_context,
|
||||||
std::string* deriv_context);
|
std::string* deriv_context);
|
||||||
size_t GetOffset(std::string message, std::string field);
|
size_t GetOffset(std::string message, std::string field);
|
||||||
|
bool SetDestinationBufferType();
|
||||||
|
|
||||||
bool valid_;
|
bool valid_;
|
||||||
bool open_;
|
bool open_;
|
||||||
@@ -76,6 +75,9 @@ class CryptoSession {
|
|||||||
CryptoSessionId oec_session_id_;
|
CryptoSessionId oec_session_id_;
|
||||||
CryptoResult session_status_;
|
CryptoResult session_status_;
|
||||||
|
|
||||||
|
OEMCryptoBufferType destination_buffer_type_;
|
||||||
|
bool is_destination_buffer_type_valid_;
|
||||||
|
|
||||||
CryptoKeyMap keys_;
|
CryptoKeyMap keys_;
|
||||||
|
|
||||||
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoSession);
|
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoSession);
|
||||||
|
|||||||
@@ -19,7 +19,20 @@ static const size_t MAC_KEY_SIZE = 32;
|
|||||||
// define boolean property keys here
|
// define boolean property keys here
|
||||||
// If false begin license usage on first playback
|
// If false begin license usage on first playback
|
||||||
static std::string kPropertyKeyBeginLicenseUsageWhenReceived =
|
static std::string kPropertyKeyBeginLicenseUsageWhenReceived =
|
||||||
"WVBeginLicenseUsageWhenReceived";
|
"WVBeginLicenseUsageWhenReceived";
|
||||||
|
// If false, calls to Generate Key request, after the first one,
|
||||||
|
// will result in a renewal request being generated
|
||||||
|
static std::string kPropertyKeyRequireExplicitRenewRequest =
|
||||||
|
"WVRequireExplicitRenewRequest";
|
||||||
|
// Set only one of the three below to true. If secure buffer
|
||||||
|
// is selected, fallback to userspace buffers may occur
|
||||||
|
// if L1/L2 OEMCrypto APIs fail
|
||||||
|
static std::string kPropertyKeyOemCryptoUseSecureBuffers =
|
||||||
|
"WVBeginLicenseOemCryptoUseSecureBuffer";
|
||||||
|
static std::string kPropertyKeyOemCryptoUseFifo =
|
||||||
|
"WVBeginLicenseOemCryptoUseFifo";
|
||||||
|
static std::string kPropertyKeyOemCryptoUseUserSpaceBuffers =
|
||||||
|
"WVBeginLicenseOemCryptoUseUserSpaceBuffers";
|
||||||
|
|
||||||
// define query keys, values here
|
// define query keys, values here
|
||||||
static const std::string QUERY_KEY_LICENSE_TYPE = "LicenseType";
|
static const std::string QUERY_KEY_LICENSE_TYPE = "LicenseType";
|
||||||
@@ -38,6 +51,7 @@ static const std::string QUERY_KEY_RENEWAL_SERVER_URL = "RenewalServerUrl";
|
|||||||
// url
|
// url
|
||||||
static const std::string QUERY_KEY_SECURITY_LEVEL = "SecurityLevel";
|
static const std::string QUERY_KEY_SECURITY_LEVEL = "SecurityLevel";
|
||||||
// "L1", "L3"
|
// "L1", "L3"
|
||||||
|
|
||||||
static const std::string QUERY_VALUE_TRUE = "True";
|
static const std::string QUERY_VALUE_TRUE = "True";
|
||||||
static const std::string QUERY_VALUE_FALSE = "False";
|
static const std::string QUERY_VALUE_FALSE = "False";
|
||||||
static const std::string QUERY_VALUE_STREAMING = "Streaming";
|
static const std::string QUERY_VALUE_STREAMING = "Streaming";
|
||||||
@@ -45,7 +59,7 @@ static const std::string QUERY_VALUE_OFFLINE = "Offline";
|
|||||||
static const std::string QUERY_VALUE_SECURITY_LEVEL_L1 = "L1";
|
static const std::string QUERY_VALUE_SECURITY_LEVEL_L1 = "L1";
|
||||||
static const std::string QUERY_VALUE_SECURITY_LEVEL_L2 = "L2";
|
static const std::string QUERY_VALUE_SECURITY_LEVEL_L2 = "L2";
|
||||||
static const std::string QUERY_VALUE_SECURITY_LEVEL_L3 = "L3";
|
static const std::string QUERY_VALUE_SECURITY_LEVEL_L3 = "L3";
|
||||||
|
static const std::string QUERY_VALUE_SECURITY_LEVEL_Unknown = "Unknown";
|
||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
|
|||||||
@@ -278,10 +278,28 @@ CdmResponseType CdmEngine::RenewKey(
|
|||||||
CdmResponseType CdmEngine::QueryStatus(CdmQueryMap* key_info) {
|
CdmResponseType CdmEngine::QueryStatus(CdmQueryMap* key_info) {
|
||||||
LOGI("CdmEngine::QueryStatus");
|
LOGI("CdmEngine::QueryStatus");
|
||||||
CryptoEngine* crypto_engine = CryptoEngine::GetInstance();
|
CryptoEngine* crypto_engine = CryptoEngine::GetInstance();
|
||||||
if (crypto_engine) {
|
if (!crypto_engine) {
|
||||||
return crypto_engine->Query(key_info);
|
return KEY_ERROR;
|
||||||
}
|
}
|
||||||
return KEY_ERROR;
|
|
||||||
|
switch (crypto_engine->GetSecurityLevel()) {
|
||||||
|
case CryptoEngine::kSecurityLevelL1:
|
||||||
|
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L1;
|
||||||
|
break;
|
||||||
|
case CryptoEngine::kSecurityLevelL2:
|
||||||
|
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L2;
|
||||||
|
break;
|
||||||
|
case CryptoEngine::kSecurityLevelL3:
|
||||||
|
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_L3;
|
||||||
|
break;
|
||||||
|
case CryptoEngine::kSecurityLevelUnknown:
|
||||||
|
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = QUERY_VALUE_SECURITY_LEVEL_Unknown;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return KEY_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType CdmEngine::QueryKeyStatus(
|
CdmResponseType CdmEngine::QueryKeyStatus(
|
||||||
@@ -325,23 +343,21 @@ CdmResponseType CdmEngine::Decrypt(
|
|||||||
const CdmSessionId& session_id,
|
const CdmSessionId& session_id,
|
||||||
bool is_encrypted,
|
bool is_encrypted,
|
||||||
const KeyId& key_id,
|
const KeyId& key_id,
|
||||||
const uint8_t* encrypted_buffer,
|
const uint8_t* encrypt_buffer,
|
||||||
size_t encrypted_size,
|
size_t encrypt_length,
|
||||||
const std::vector<uint8_t>& iv,
|
const std::vector<uint8_t>& iv,
|
||||||
size_t block_offset,
|
size_t block_offset,
|
||||||
uint8_t* decrypted_buffer) {
|
void* decrypt_buffer,
|
||||||
|
bool is_video) {
|
||||||
CdmSessionIter iter = sessions_.find(session_id);
|
CdmSessionIter iter = sessions_.find(session_id);
|
||||||
if (iter == sessions_.end()) {
|
if (iter == sessions_.end()) {
|
||||||
LOGW("CdmEngine::Decrypt: session_id not found = %s", session_id.c_str());
|
LOGW("CdmEngine::Decrypt: session_id not found = %s", session_id.c_str());
|
||||||
return KEY_ERROR;
|
return KEY_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (NO_ERROR != iter->second->Decrypt(encrypted_buffer, encrypted_size,
|
return iter->second->Decrypt(is_encrypted, key_id, encrypt_buffer,
|
||||||
block_offset, iv, key_id,
|
encrypt_length, iv, block_offset,
|
||||||
decrypted_buffer))
|
decrypt_buffer, is_video);
|
||||||
return UNKNOWN_ERROR;
|
|
||||||
|
|
||||||
return NO_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CdmEngine::IsKeyValid(const KeyId& key_id) {
|
bool CdmEngine::IsKeyValid(const KeyId& key_id) {
|
||||||
|
|||||||
@@ -5,10 +5,11 @@
|
|||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
|
||||||
|
#include "clock.h"
|
||||||
#include "crypto_engine.h"
|
#include "crypto_engine.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
#include "properties.h"
|
||||||
#include "string_conversions.h"
|
#include "string_conversions.h"
|
||||||
#include "clock.h"
|
|
||||||
#include "wv_cdm_constants.h"
|
#include "wv_cdm_constants.h"
|
||||||
|
|
||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
@@ -30,6 +31,15 @@ bool CdmSession::Init() {
|
|||||||
std::string token;
|
std::string token;
|
||||||
if (!crypto_engine->GetToken(&token)) return false;
|
if (!crypto_engine->GetToken(&token)) return false;
|
||||||
|
|
||||||
|
if (!Properties::GetInstance()->GetProperty(
|
||||||
|
kPropertyKeyRequireExplicitRenewRequest,
|
||||||
|
require_explicit_renew_request_)) {
|
||||||
|
LOGE("CdmSession::Init: Unable to access property - require explicit renew");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
properties_valid_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
return license_parser_.Init(token, crypto_session_, &policy_engine_);
|
return license_parser_.Init(token, crypto_session_, &policy_engine_);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -50,20 +60,57 @@ bool CdmSession::VerifySession(const CdmKeySystem& key_system,
|
|||||||
|
|
||||||
CdmResponseType CdmSession::GenerateKeyRequest(const CdmInitData& init_data,
|
CdmResponseType CdmSession::GenerateKeyRequest(const CdmInitData& init_data,
|
||||||
CdmKeyMessage* key_request) {
|
CdmKeyMessage* key_request) {
|
||||||
crypto_session_->Open();
|
if (!properties_valid_) {
|
||||||
if(!license_parser_.PrepareKeyRequest(init_data, key_request)) {
|
LOGW("CdmSession::GenerateKeyRequest: Unable to access properties");
|
||||||
return KEY_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
} else {
|
}
|
||||||
return KEY_MESSAGE;
|
|
||||||
|
if (!crypto_session_) {
|
||||||
|
LOGW("CdmSession::GenerateKeyRequest: Invalid crypto session");
|
||||||
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!crypto_session_->IsOpen()) {
|
||||||
|
LOGW("CdmSession::GenerateKeyRequest: Crypto session not open");
|
||||||
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (license_received_) {
|
||||||
|
return require_explicit_renew_request_ ?
|
||||||
|
UNKNOWN_ERROR : GenerateRenewalRequest(key_request);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if(!license_parser_.PrepareKeyRequest(init_data, key_request)) {
|
||||||
|
return KEY_ERROR;
|
||||||
|
} else {
|
||||||
|
return KEY_MESSAGE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddKey() - Accept license response and extract key info.
|
// AddKey() - Accept license response and extract key info.
|
||||||
CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
|
CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
|
||||||
if (!license_parser_.HandleKeyResponse(key_response)) {
|
if (!crypto_session_) {
|
||||||
return KEY_ERROR;
|
LOGW("CdmSession::AddKey: Invalid crypto session");
|
||||||
} else {
|
return UNKNOWN_ERROR;
|
||||||
return KEY_ADDED;
|
}
|
||||||
|
|
||||||
|
if (!crypto_session_->IsOpen()) {
|
||||||
|
LOGW("CdmSession::AddKey: Crypto session not open");
|
||||||
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (license_received_) {
|
||||||
|
return require_explicit_renew_request_ ?
|
||||||
|
UNKNOWN_ERROR : RenewKey(key_response);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!license_parser_.HandleKeyResponse(key_response)) {
|
||||||
|
return KEY_ERROR;
|
||||||
|
} else {
|
||||||
|
license_received_ = true;
|
||||||
|
return KEY_ADDED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -79,23 +126,29 @@ CdmResponseType CdmSession::CancelKeyRequest() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Decrypt() - Accept encrypted buffer and return decrypted data.
|
// Decrypt() - Accept encrypted buffer and return decrypted data.
|
||||||
CdmResponseType CdmSession::Decrypt(const uint8_t* encrypted_buffer,
|
CdmResponseType CdmSession::Decrypt(bool is_encrypted,
|
||||||
size_t encrypted_size,
|
|
||||||
size_t block_offset,
|
|
||||||
const std::vector<uint8_t>& iv,
|
|
||||||
const KeyId& key_id,
|
const KeyId& key_id,
|
||||||
uint8_t* decrypted_buffer) {
|
const uint8_t* encrypt_buffer,
|
||||||
if (!crypto_session_)
|
size_t encrypt_length,
|
||||||
|
const std::vector<uint8_t>& iv,
|
||||||
|
size_t block_offset,
|
||||||
|
void* decrypt_buffer,
|
||||||
|
bool is_video) {
|
||||||
|
if (!crypto_session_ || !crypto_session_->IsOpen())
|
||||||
return UNKNOWN_ERROR;
|
return UNKNOWN_ERROR;
|
||||||
|
|
||||||
if (!crypto_session_->SelectKey(key_id))
|
// Check if key needs to be selected
|
||||||
return UNKNOWN_ERROR;
|
if (key_id_.compare(key_id) != 0) {
|
||||||
|
if (crypto_session_->SelectKey(key_id)) {
|
||||||
|
key_id_ = key_id;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!crypto_session_->Decrypt(encrypted_buffer, encrypted_size,
|
return crypto_session_->Decrypt(is_encrypted, encrypt_buffer, encrypt_length,
|
||||||
block_offset, iv, decrypted_buffer))
|
iv, block_offset, decrypt_buffer, is_video);
|
||||||
return UNKNOWN_ERROR;
|
|
||||||
|
|
||||||
return NO_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// License renewal
|
// License renewal
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "OEMCryptoCENC.h"
|
#include "OEMCryptoCENC.h"
|
||||||
|
#include "properties.h"
|
||||||
#include "wv_cdm_constants.h"
|
#include "wv_cdm_constants.h"
|
||||||
|
|
||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
@@ -23,7 +24,11 @@ Lock CryptoEngine::crypto_engine_lock_;
|
|||||||
|
|
||||||
// CryptoEngine methods
|
// CryptoEngine methods
|
||||||
|
|
||||||
CryptoEngine::CryptoEngine() : initialized_(false) {}
|
CryptoEngine::CryptoEngine() : initialized_(false),
|
||||||
|
properties_valid_(false),
|
||||||
|
oem_crypto_use_secure_buffers_(false),
|
||||||
|
oem_crypto_use_fifo_(false),
|
||||||
|
oem_crypto_use_userspace_buffers_(false) {}
|
||||||
|
|
||||||
CryptoEngine::~CryptoEngine() {
|
CryptoEngine::~CryptoEngine() {
|
||||||
if (initialized_) {
|
if (initialized_) {
|
||||||
@@ -61,6 +66,29 @@ void CryptoEngine::DeleteInstance() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CryptoEngine::Init() {
|
bool CryptoEngine::Init() {
|
||||||
|
properties_valid_ = true;
|
||||||
|
|
||||||
|
if (!Properties::GetInstance()->GetProperty(
|
||||||
|
kPropertyKeyOemCryptoUseSecureBuffers,
|
||||||
|
oem_crypto_use_secure_buffers_)) {
|
||||||
|
LOGW("CryptoEngine::CryptoEngine: Unable to access property - oemcrypto use secure buffers");
|
||||||
|
properties_valid_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Properties::GetInstance()->GetProperty(
|
||||||
|
kPropertyKeyOemCryptoUseFifo,
|
||||||
|
oem_crypto_use_fifo_)) {
|
||||||
|
LOGW("CryptoEngine::CryptoEngine: Unable to access property - oemcrypto use fifos");
|
||||||
|
properties_valid_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Properties::GetInstance()->GetProperty(
|
||||||
|
kPropertyKeyOemCryptoUseUserSpaceBuffers,
|
||||||
|
oem_crypto_use_userspace_buffers_)) {
|
||||||
|
LOGW("CryptoEngine::CryptoEngine: Unable to access property - oemcrypto use userspace buffers");
|
||||||
|
properties_valid_ = false;
|
||||||
|
}
|
||||||
|
|
||||||
LOGV("CryptoEngine::Init: Lock");
|
LOGV("CryptoEngine::Init: Lock");
|
||||||
AutoLock auto_lock(crypto_lock_);
|
AutoLock auto_lock(crypto_lock_);
|
||||||
if (!initialized_) {
|
if (!initialized_) {
|
||||||
@@ -175,10 +203,22 @@ bool CryptoEngine::GetToken(std::string* token) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
CdmResponseType CryptoEngine::Query(CdmQueryMap* key_info) {
|
CryptoEngine::SecurityLevel CryptoEngine::GetSecurityLevel() {
|
||||||
LOGV("CryptoEngine::GetToken: Query");
|
std::string security_level = OEMCrypto_SecurityLevel();
|
||||||
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = OEMCrypto_SecurityLevel();
|
|
||||||
return NO_ERROR;
|
if ((security_level.size() != 2) ||
|
||||||
|
(security_level.at(0) != 'L')) {
|
||||||
|
return kSecurityLevelUnknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (security_level.at(1)) {
|
||||||
|
case '1': return kSecurityLevelL1;
|
||||||
|
case '2': return kSecurityLevelL2;
|
||||||
|
case '3': return kSecurityLevelL3;
|
||||||
|
default : return kSecurityLevelUnknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
return kSecurityLevelUnknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
}; // namespace wvcdm
|
}; // namespace wvcdm
|
||||||
|
|||||||
@@ -35,10 +35,16 @@ namespace wvcdm {
|
|||||||
|
|
||||||
// CryptoSession methods
|
// CryptoSession methods
|
||||||
|
|
||||||
CryptoSession::CryptoSession() : valid_(false), open_(false) {}
|
CryptoSession::CryptoSession() :
|
||||||
|
valid_(false),
|
||||||
|
open_(false),
|
||||||
|
is_destination_buffer_type_valid_(false) {}
|
||||||
|
|
||||||
CryptoSession::CryptoSession(const std::string& sname) : valid_(true),
|
CryptoSession::CryptoSession(const std::string& sname) :
|
||||||
open_(false), cdm_session_id_(sname) {}
|
valid_(true),
|
||||||
|
open_(false),
|
||||||
|
cdm_session_id_(sname),
|
||||||
|
is_destination_buffer_type_valid_(false) {}
|
||||||
|
|
||||||
CryptoSession::~CryptoSession() {
|
CryptoSession::~CryptoSession() {
|
||||||
if (open_) {
|
if (open_) {
|
||||||
@@ -222,7 +228,7 @@ bool CryptoSession::LoadKeys(const std::string& message,
|
|||||||
enc_mac_key = msg + GetOffset(message, mac_key);
|
enc_mac_key = msg + GetOffset(message, mac_key);
|
||||||
enc_mac_key_iv = msg + GetOffset(message, mac_key_iv);
|
enc_mac_key_iv = msg + GetOffset(message, mac_key_iv);
|
||||||
}
|
}
|
||||||
OEMCrypto_KeyObject load_key_array[num_keys];
|
std::vector<OEMCrypto_KeyObject> load_key_array(num_keys);
|
||||||
for (int i=0; i<num_keys; ++i) {
|
for (int i=0; i<num_keys; ++i) {
|
||||||
const CryptoKey* ki = &key_array[i];
|
const CryptoKey* ki = &key_array[i];
|
||||||
OEMCrypto_KeyObject* ko = &load_key_array[i];
|
OEMCrypto_KeyObject* ko = &load_key_array[i];
|
||||||
@@ -246,7 +252,7 @@ bool CryptoSession::LoadKeys(const std::string& message,
|
|||||||
oec_session_id_, msg, message.size(),
|
oec_session_id_, msg, message.size(),
|
||||||
reinterpret_cast<const uint8_t*>(signature.data()),
|
reinterpret_cast<const uint8_t*>(signature.data()),
|
||||||
signature.size(), enc_mac_key_iv, enc_mac_key,
|
signature.size(), enc_mac_key_iv, enc_mac_key,
|
||||||
num_keys, load_key_array));
|
num_keys, &load_key_array[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CryptoSession::RefreshKeys(const std::string& message,
|
bool CryptoSession::RefreshKeys(const std::string& message,
|
||||||
@@ -258,7 +264,7 @@ bool CryptoSession::RefreshKeys(const std::string& message,
|
|||||||
AutoLock auto_lock(crypto_engine->crypto_lock_);
|
AutoLock auto_lock(crypto_engine->crypto_lock_);
|
||||||
|
|
||||||
const uint8_t* msg = reinterpret_cast<const uint8_t*>(message.data());
|
const uint8_t* msg = reinterpret_cast<const uint8_t*>(message.data());
|
||||||
OEMCrypto_KeyRefreshObject load_key_array[num_keys];
|
std::vector<OEMCrypto_KeyRefreshObject> load_key_array(num_keys);
|
||||||
for (int i=0; i<num_keys; ++i) {
|
for (int i=0; i<num_keys; ++i) {
|
||||||
const CryptoKey* ki = &key_array[i];
|
const CryptoKey* ki = &key_array[i];
|
||||||
OEMCrypto_KeyRefreshObject* ko = &load_key_array[i];
|
OEMCrypto_KeyRefreshObject* ko = &load_key_array[i];
|
||||||
@@ -285,7 +291,7 @@ bool CryptoSession::RefreshKeys(const std::string& message,
|
|||||||
oec_session_id_, msg, message.size(),
|
oec_session_id_, msg, message.size(),
|
||||||
reinterpret_cast<const uint8_t*>(signature.data()),
|
reinterpret_cast<const uint8_t*>(signature.data()),
|
||||||
signature.size(),
|
signature.size(),
|
||||||
num_keys, load_key_array));
|
num_keys, &load_key_array[0]));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CryptoSession::SelectKey(const std::string& key_id) {
|
bool CryptoSession::SelectKey(const std::string& key_id) {
|
||||||
@@ -304,55 +310,49 @@ bool CryptoSession::SelectKey(const std::string& key_id) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CryptoSession::Decrypt(const InputDescriptor input,
|
CdmResponseType CryptoSession::Decrypt(bool is_encrypted,
|
||||||
const OutputDescriptor output) {
|
const uint8_t* encrypt_buffer,
|
||||||
LOGV("CryptoSession::Decrypt: Lock");
|
size_t encrypt_length,
|
||||||
CryptoEngine* crypto_engine = CryptoEngine::GetInstance();
|
const std::vector<uint8_t>& iv,
|
||||||
AutoLock auto_lock(crypto_engine->crypto_lock_);
|
size_t block_offset,
|
||||||
// TODO(gmorgan): handle inputs and outputs to decrypt call
|
void* decrypt_buffer,
|
||||||
const uint8_t* data_addr = NULL;
|
bool is_video) {
|
||||||
uint32_t data_length = 0;
|
if (!is_destination_buffer_type_valid_) {
|
||||||
bool is_encrypted = false;
|
if (!SetDestinationBufferType())
|
||||||
uint8_t* iv = NULL;
|
return UNKNOWN_ERROR;
|
||||||
uint32_t offset = 0;
|
|
||||||
const OEMCrypto_DestBufferDesc* out_buffer = NULL;
|
|
||||||
OEMCryptoResult sts = OEMCrypto_DecryptCTR(oec_session_id_, data_addr,
|
|
||||||
data_length, is_encrypted, iv,
|
|
||||||
offset, out_buffer);
|
|
||||||
if (OEMCrypto_SUCCESS != sts) {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(jfore): Define InputDescriptor and OutputDecriptor and
|
OEMCrypto_DestBufferDesc buffer_descriptor;
|
||||||
// remove this method. For now this is a level 3 decrypt.
|
buffer_descriptor.type = destination_buffer_type_;
|
||||||
bool CryptoSession::Decrypt(const uint8_t* encrypted_buffer,
|
|
||||||
size_t encrypted_size,
|
|
||||||
size_t block_offset,
|
|
||||||
const std::vector<uint8_t>& iv,
|
|
||||||
uint8_t* decrypted_buffer) {
|
|
||||||
LOGV("CryptoSession::Decrypt: Lock");
|
|
||||||
CryptoEngine* crypto_engine = CryptoEngine::GetInstance();
|
|
||||||
AutoLock auto_lock(crypto_engine->crypto_lock_);
|
|
||||||
// TODO(gmorgan): handle inputs and outputs to decrypt call
|
|
||||||
const uint8_t* data_addr = NULL;
|
|
||||||
uint32_t data_length = 0;
|
|
||||||
bool is_encrypted = false;
|
|
||||||
uint32_t offset = block_offset;
|
|
||||||
OEMCrypto_DestBufferDesc out_buffer;
|
|
||||||
|
|
||||||
out_buffer.type = OEMCrypto_BufferType_Clear;
|
if (!is_encrypted)
|
||||||
out_buffer.buffer.clear.address = decrypted_buffer;
|
buffer_descriptor.type = OEMCrypto_BufferType_Clear;
|
||||||
out_buffer.buffer.clear.max_length = encrypted_size;
|
|
||||||
|
|
||||||
OEMCryptoResult sts = OEMCrypto_DecryptCTR(oec_session_id_, encrypted_buffer,
|
switch (buffer_descriptor.type) {
|
||||||
encrypted_size, true, &iv[0],
|
case OEMCrypto_BufferType_Clear:
|
||||||
offset, &out_buffer);
|
buffer_descriptor.buffer.clear.address =
|
||||||
if (OEMCrypto_SUCCESS != sts) {
|
static_cast<uint8_t*>(decrypt_buffer);
|
||||||
return false;
|
buffer_descriptor.buffer.clear.max_length = encrypt_length;
|
||||||
|
break;
|
||||||
|
case OEMCrypto_BufferType_Secure:
|
||||||
|
buffer_descriptor.buffer.secure.handle = decrypt_buffer;
|
||||||
|
buffer_descriptor.buffer.secure.max_length = encrypt_length;
|
||||||
|
break;
|
||||||
|
case OEMCrypto_BufferType_Direct:
|
||||||
|
buffer_descriptor.type = OEMCrypto_BufferType_Direct;
|
||||||
|
buffer_descriptor.buffer.direct.is_video = is_video;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
OEMCryptoResult sts = OEMCrypto_DecryptCTR(oec_session_id_, encrypt_buffer,
|
||||||
|
encrypt_length, is_encrypted,
|
||||||
|
&iv[0], block_offset,
|
||||||
|
&buffer_descriptor);
|
||||||
|
|
||||||
|
if (OEMCrypto_SUCCESS != sts) {
|
||||||
|
return UNKNOWN_ERROR;
|
||||||
|
}
|
||||||
|
return NO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CryptoSession::GenerateNonce(uint32_t* nonce) {
|
bool CryptoSession::GenerateNonce(uint32_t* nonce) {
|
||||||
@@ -366,4 +366,33 @@ bool CryptoSession::GenerateNonce(uint32_t* nonce) {
|
|||||||
AutoLock auto_lock(crypto_engine->crypto_lock_);
|
AutoLock auto_lock(crypto_engine->crypto_lock_);
|
||||||
return(OEMCrypto_SUCCESS == OEMCrypto_GenerateNonce(oec_session_id_, nonce));
|
return(OEMCrypto_SUCCESS == OEMCrypto_GenerateNonce(oec_session_id_, nonce));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CryptoSession::SetDestinationBufferType() {
|
||||||
|
CryptoEngine* crypto_engine = CryptoEngine::GetInstance();
|
||||||
|
|
||||||
|
if (!crypto_engine->properties_valid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (crypto_engine->oem_crypto_use_secure_buffers()) {
|
||||||
|
if (crypto_engine->GetSecurityLevel() == CryptoEngine::kSecurityLevelL1) {
|
||||||
|
destination_buffer_type_ = OEMCrypto_BufferType_Secure;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
destination_buffer_type_ = OEMCrypto_BufferType_Clear;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (crypto_engine->oem_crypto_use_fifo()) {
|
||||||
|
destination_buffer_type_ = OEMCrypto_BufferType_Direct;
|
||||||
|
}
|
||||||
|
else if (crypto_engine->oem_crypto_use_userspace_buffers()) {
|
||||||
|
destination_buffer_type_ = OEMCrypto_BufferType_Clear;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
is_destination_buffer_type_valid_ = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}; // namespace wvcdm
|
}; // namespace wvcdm
|
||||||
|
|||||||
@@ -10,7 +10,11 @@ namespace wvcdm {
|
|||||||
|
|
||||||
// set property values below
|
// set property values below
|
||||||
static CdmBooleanProperties kCdmBooleanProperties[] = {
|
static CdmBooleanProperties kCdmBooleanProperties[] = {
|
||||||
{ .name = kPropertyKeyBeginLicenseUsageWhenReceived, .value = false }
|
{ kPropertyKeyBeginLicenseUsageWhenReceived, false },
|
||||||
|
{ kPropertyKeyRequireExplicitRenewRequest, false },
|
||||||
|
{ kPropertyKeyOemCryptoUseSecureBuffers, true },
|
||||||
|
{ kPropertyKeyOemCryptoUseFifo, false },
|
||||||
|
{ kPropertyKeyOemCryptoUseUserSpaceBuffers, false },
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|||||||
@@ -60,11 +60,11 @@ class WvContentDecryptionModule {
|
|||||||
virtual CdmResponseType Decrypt(const CdmSessionId& session_id,
|
virtual CdmResponseType Decrypt(const CdmSessionId& session_id,
|
||||||
bool is_encrypted,
|
bool is_encrypted,
|
||||||
const KeyId& key_id,
|
const KeyId& key_id,
|
||||||
const uint8_t* encrypted_buffer,
|
const uint8_t* encrypt_buffer,
|
||||||
size_t encrypted_size,
|
size_t encrypt_length,
|
||||||
const std::vector<uint8_t>& iv,
|
const std::vector<uint8_t>& iv,
|
||||||
size_t block_offset,
|
size_t block_offset,
|
||||||
uint8_t* decrypted_buffer);
|
void* decrypt_buffer);
|
||||||
|
|
||||||
// Event listener related methods
|
// Event listener related methods
|
||||||
virtual bool AttachEventListener(CdmSessionId& session_id,
|
virtual bool AttachEventListener(CdmSessionId& session_id,
|
||||||
|
|||||||
@@ -92,14 +92,14 @@ CdmResponseType WvContentDecryptionModule::Decrypt(
|
|||||||
const CdmSessionId& session_id,
|
const CdmSessionId& session_id,
|
||||||
bool is_encrypted,
|
bool is_encrypted,
|
||||||
const KeyId& key_id,
|
const KeyId& key_id,
|
||||||
const uint8_t* encrypted_buffer,
|
const uint8_t* encrypt_buffer,
|
||||||
size_t encrypted_size,
|
size_t encrypt_length,
|
||||||
const std::vector<uint8_t>& iv,
|
const std::vector<uint8_t>& iv,
|
||||||
size_t block_offset,
|
size_t block_offset,
|
||||||
uint8_t* decrypted_buffer) {
|
void* decrypt_buffer) {
|
||||||
return cdm_engine_->Decrypt(session_id, is_encrypted, key_id,
|
return cdm_engine_->Decrypt(session_id, is_encrypted, key_id,
|
||||||
encrypted_buffer, encrypted_size, iv,
|
encrypt_buffer, encrypt_length, iv,
|
||||||
block_offset, decrypted_buffer);
|
block_offset, decrypt_buffer, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool WvContentDecryptionModule::AttachEventListener(
|
bool WvContentDecryptionModule::AttachEventListener(
|
||||||
|
|||||||
@@ -26,6 +26,15 @@ int g_use_full_path = 0; // cannot use boolean in getopt_long
|
|||||||
|
|
||||||
namespace wvcdm {
|
namespace wvcdm {
|
||||||
|
|
||||||
|
typedef struct DecryptionData {
|
||||||
|
bool is_encrypted;
|
||||||
|
wvcdm::KeyId key_id;
|
||||||
|
std::vector<uint8_t> encrypt_data;
|
||||||
|
std::vector<uint8_t> iv;
|
||||||
|
size_t block_offset;
|
||||||
|
std::vector<uint8_t> decrypt_data;
|
||||||
|
} DecryptionData;
|
||||||
|
|
||||||
class WvCdmRequestLicenseTest : public testing::Test {
|
class WvCdmRequestLicenseTest : public testing::Test {
|
||||||
public:
|
public:
|
||||||
WvCdmRequestLicenseTest() {}
|
WvCdmRequestLicenseTest() {}
|
||||||
@@ -101,12 +110,7 @@ class WvCdmRequestLicenseTest : public testing::Test {
|
|||||||
if (is_renewal) {
|
if (is_renewal) {
|
||||||
// TODO application makes a license request, CDM will renew the license
|
// TODO application makes a license request, CDM will renew the license
|
||||||
// when appropriate
|
// when appropriate
|
||||||
wvcdm::CdmAppParameterMap app_parameters;
|
EXPECT_EQ(decryptor_.AddKey(session_id_, resp), wvcdm::KEY_ADDED);
|
||||||
EXPECT_EQ(decryptor_.GenerateKeyRequest(session_id_,
|
|
||||||
init_data,
|
|
||||||
kLicenseTypeStreaming,
|
|
||||||
app_parameters,
|
|
||||||
&key_msg_), wvcdm::KEY_ADDED);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
EXPECT_EQ(decryptor_.AddKey(session_id_, resp), wvcdm::KEY_ADDED);
|
EXPECT_EQ(decryptor_.AddKey(session_id_, resp), wvcdm::KEY_ADDED);
|
||||||
@@ -134,15 +138,13 @@ TEST_F(WvCdmRequestLicenseTest, WrongMessageTest) {
|
|||||||
decryptor_.CloseSession(session_id_);
|
decryptor_.CloseSession(session_id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, NormalDecryption) {
|
TEST_F(WvCdmRequestLicenseTest, AddKeyTest) {
|
||||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||||
GenerateKeyRequest(g_key_system, g_key_id);
|
GenerateKeyRequest(g_key_system, g_key_id);
|
||||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||||
decryptor_.CloseSession(session_id_);
|
decryptor_.CloseSession(session_id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 0
|
|
||||||
// TODO License renewal is not yet implented
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, LicenseRenewal) {
|
TEST_F(WvCdmRequestLicenseTest, LicenseRenewal) {
|
||||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||||
GenerateKeyRequest(g_key_system, g_key_id);
|
GenerateKeyRequest(g_key_system, g_key_id);
|
||||||
@@ -152,7 +154,6 @@ TEST_F(WvCdmRequestLicenseTest, LicenseRenewal) {
|
|||||||
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, true);
|
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, true);
|
||||||
decryptor_.CloseSession(session_id_);
|
decryptor_.CloseSession(session_id_);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
TEST_F(WvCdmRequestLicenseTest, QueryKeyStatus) {
|
TEST_F(WvCdmRequestLicenseTest, QueryKeyStatus) {
|
||||||
decryptor_.OpenSession(g_key_system, &session_id_);
|
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||||
@@ -198,6 +199,313 @@ TEST_F(WvCdmRequestLicenseTest, QueryStatus) {
|
|||||||
decryptor_.CloseSession(session_id_);
|
decryptor_.CloseSession(session_id_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_F(WvCdmRequestLicenseTest, ClearDecryptionTest) {
|
||||||
|
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||||
|
GenerateKeyRequest(g_key_system, g_key_id);
|
||||||
|
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||||
|
|
||||||
|
// key 1, clear, 256b
|
||||||
|
DecryptionData data;
|
||||||
|
data.is_encrypted = 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");
|
||||||
|
|
||||||
|
std::vector<uint8_t> 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.key_id,
|
||||||
|
&data.encrypt_data.front(),
|
||||||
|
encrypt_length,
|
||||||
|
data.iv,
|
||||||
|
data.block_offset,
|
||||||
|
&decrypt_buffer.front()));
|
||||||
|
|
||||||
|
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);
|
||||||
|
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||||
|
|
||||||
|
// key 1, encrypted, 256b
|
||||||
|
DecryptionData data;
|
||||||
|
data.is_encrypted = true;
|
||||||
|
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<uint8_t> 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.key_id,
|
||||||
|
&data.encrypt_data.front(),
|
||||||
|
encrypt_length,
|
||||||
|
data.iv,
|
||||||
|
data.block_offset,
|
||||||
|
&decrypt_buffer.front()));
|
||||||
|
|
||||||
|
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);
|
||||||
|
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].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].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<uint8_t> 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].key_id,
|
||||||
|
&data[i].encrypt_data.front(),
|
||||||
|
encrypt_length,
|
||||||
|
data[i].iv,
|
||||||
|
data[i].block_offset,
|
||||||
|
&decrypt_buffer.front()));
|
||||||
|
|
||||||
|
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);
|
||||||
|
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||||
|
|
||||||
|
// key 3, encrypted, 125b, offset 0
|
||||||
|
DecryptionData data;
|
||||||
|
data.is_encrypted = true;
|
||||||
|
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<uint8_t> 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.key_id,
|
||||||
|
&data.encrypt_data.front(),
|
||||||
|
encrypt_length,
|
||||||
|
data.iv,
|
||||||
|
data.block_offset,
|
||||||
|
&decrypt_buffer.front()));
|
||||||
|
|
||||||
|
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);
|
||||||
|
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||||
|
|
||||||
|
// key 3, encrypted, 123b, offset 5
|
||||||
|
DecryptionData data;
|
||||||
|
data.is_encrypted = true;
|
||||||
|
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<uint8_t> 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.key_id,
|
||||||
|
&data.encrypt_data.front(),
|
||||||
|
encrypt_length,
|
||||||
|
data.iv,
|
||||||
|
data.block_offset,
|
||||||
|
&decrypt_buffer.front()));
|
||||||
|
|
||||||
|
EXPECT_TRUE(std::equal(data.decrypt_data.begin(), data.decrypt_data.end(),
|
||||||
|
decrypt_buffer.begin()));
|
||||||
|
|
||||||
|
decryptor_.CloseSession(session_id_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(rfrias, edwinwong): pending L1 OEMCrypto due to key block handling
|
||||||
|
/*
|
||||||
|
TEST_F(WvCdmRequestLicenseTest, KeyControlBlockDecryptionTest) {
|
||||||
|
decryptor_.OpenSession(g_key_system, &session_id_);
|
||||||
|
GenerateKeyRequest(g_key_system, g_key_id);
|
||||||
|
VerifyKeyRequestResponse(g_license_server, g_client_auth, g_key_id, false);
|
||||||
|
|
||||||
|
DecryptionData data;
|
||||||
|
|
||||||
|
// block 4, key 2, encrypted
|
||||||
|
data.is_encrypted = true;
|
||||||
|
data.key_id = wvcdm::a2bs_hex("0915007CAA9B5931B76A3A85F046523E");
|
||||||
|
data.encrypt_data = wvcdm::a2b_hex(
|
||||||
|
"6758ac1c6ccf5d08479e3bfc62bbc0fd154aff4415aa7ed53d89e3983248d117"
|
||||||
|
"ab5137ae7cedd9f9d7321d4cf35a7013237afbcc2d893d1d928efa94e9f7e2ed"
|
||||||
|
"1855463cf75ff07ecc0246b90d0734f42d98aeea6a0a6d2618a8339bd0aca368"
|
||||||
|
"4fb4a4670c0385e5bd5de9e2d8b9226851b8f8955adfbab968793b46fd152f5e"
|
||||||
|
"e608467bb2695836f8f76c32731f5e208176d05e4b07020d58f6282c477f3840"
|
||||||
|
"b8079c02e8bd1d03191d190cc505ddfbb2e9bacc794534c91fe409d62f5389b9"
|
||||||
|
"35ed66134bd30f09f8da9dbfe6b8cf53d13cae34dae6e89109216e3a02233d5c"
|
||||||
|
"2f66aef74313aae4a99b654b485b5cc207b2dc8d44a8b99a4dc196a9820eccef");
|
||||||
|
data.iv = wvcdm::a2b_hex("c8f2d133ec357fe727cd233b3bfa755f");
|
||||||
|
data.block_offset = 0;
|
||||||
|
data.decrypt_data = wvcdm::a2b_hex(
|
||||||
|
"34bab89185f1be990dfc454410c7c9093d008bc783908838b02a65b26db28759"
|
||||||
|
"dca9dc5f117b3c8c3898358722d1b4c490e5a5d168ba0f9f8a3d4371b8fd1057"
|
||||||
|
"2d6dd65f3f9d1850de8d76dc71bd6dc6c23da4e1223fcc3e47162033a6f82890"
|
||||||
|
"e2bd6e9d6ddbe453830afc89064ed18078c786f8f746fcbafd88e83e7160cce5"
|
||||||
|
"62fa7a7d699ef8421bda020d242ae4f61a786213b707c3b17b83d77510f9a07e"
|
||||||
|
"d9d7e47d8f8fa2aff86eb26d61ddf384a27513e3facf6b1f5fe6c0d063b8856c"
|
||||||
|
"c486d930393ea79ba73ba293eda39059e2ce9ee7bd5d31ab11f35e55dc35dfe0"
|
||||||
|
"ea5e2ec684014852add6e29ce7d88a1595641ae4c0dd10155526b5a87560ec9d");
|
||||||
|
|
||||||
|
std::vector<uint8_t> decrypt_buffer;
|
||||||
|
size_t encrypt_length = data[i].encrypt_data.size();
|
||||||
|
decrypt_buffer.resize(encrypt_length);
|
||||||
|
|
||||||
|
EXPECT_EQ(NO_ERROR, decryptor_.Decrypt(session_id_,
|
||||||
|
data.is_encrypted,
|
||||||
|
data.key_id,
|
||||||
|
&data.encrypt_data.front(),
|
||||||
|
encrypt_length,
|
||||||
|
data.iv,
|
||||||
|
data.block_offset,
|
||||||
|
&decrypt_buffer.front()));
|
||||||
|
|
||||||
|
EXPECT_TRUE(std::equal(data.decrypt_data.begin(),
|
||||||
|
data.decrypt_data.end(),
|
||||||
|
decrypt_buffer.begin()));
|
||||||
|
}
|
||||||
|
decryptor_.CloseSession(session_id_);
|
||||||
|
}
|
||||||
|
*/
|
||||||
} // namespace wvcdm
|
} // namespace wvcdm
|
||||||
|
|
||||||
int main(int argc, char **argv) {
|
int main(int argc, char **argv) {
|
||||||
|
|||||||
@@ -24,7 +24,8 @@ LOCAL_C_INCLUDES := \
|
|||||||
vendor/widevine/libwvdrmengine/test/gmock/include \
|
vendor/widevine/libwvdrmengine/test/gmock/include \
|
||||||
vendor/widevine/libwvdrmengine/cdm/core/include \
|
vendor/widevine/libwvdrmengine/cdm/core/include \
|
||||||
vendor/widevine/libwvdrmengine/cdm/core/test \
|
vendor/widevine/libwvdrmengine/cdm/core/test \
|
||||||
vendor/widevine/libwvdrmengine/cdm/include
|
vendor/widevine/libwvdrmengine/cdm/include \
|
||||||
|
vendor/widevine/libwvdrmengine/oemcrypto/include
|
||||||
|
|
||||||
LOCAL_C_INCLUDES += \
|
LOCAL_C_INCLUDES += \
|
||||||
external/protobuf/src
|
external/protobuf/src
|
||||||
|
|||||||
Reference in New Issue
Block a user