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,
|
||||
bool is_encrypted,
|
||||
const KeyId& key_id,
|
||||
const uint8_t* encrypted_buffer,
|
||||
size_t encrypted_size,
|
||||
const uint8_t* encrypt_buffer,
|
||||
size_t encrypt_length,
|
||||
const std::vector<uint8_t>& iv,
|
||||
size_t block_offset,
|
||||
uint8_t* decrypted_buffer);
|
||||
void* decrypt_buffer,
|
||||
bool is_video);
|
||||
|
||||
// Is the key known to any session?
|
||||
bool IsKeyValid(const KeyId& key_id);
|
||||
|
||||
@@ -18,7 +18,9 @@ namespace wvcdm {
|
||||
|
||||
class CdmSession {
|
||||
public:
|
||||
CdmSession() : state_(INITIAL), session_id_(GenerateSessionId()) {}
|
||||
CdmSession() : session_id_(GenerateSessionId()),
|
||||
license_received_(false),
|
||||
properties_valid_(false) {}
|
||||
~CdmSession() {}
|
||||
|
||||
bool Init();
|
||||
@@ -46,12 +48,14 @@ class CdmSession {
|
||||
CdmResponseType QueryKeyStatus(CdmQueryMap* key_info);
|
||||
|
||||
// Decrypt() - Accept encrypted buffer and return decrypted data.
|
||||
CdmResponseType Decrypt(const uint8_t* encrypted_buffer,
|
||||
size_t encrypted_size,
|
||||
size_t block_offset,
|
||||
const std::vector<uint8_t>& iv,
|
||||
CdmResponseType Decrypt(bool is_encrypted,
|
||||
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
|
||||
// GenerateRenewalRequest() - Construct valid renewal request for the current
|
||||
@@ -73,22 +77,18 @@ class CdmSession {
|
||||
// Generate unique ID for each new session.
|
||||
CdmSessionId GenerateSessionId();
|
||||
|
||||
typedef enum {
|
||||
INITIAL,
|
||||
LICENSE_REQUESTED,
|
||||
LICENSE_RESPONSE_DONE,
|
||||
RENEWAL_ENABLED,
|
||||
RENEWAL_REQUESTED,
|
||||
LICENSE_EXPIRED
|
||||
} CdmSessionState;
|
||||
|
||||
// instance variables
|
||||
CdmSessionState state_;
|
||||
const CdmSessionId session_id_;
|
||||
CdmKeySystem key_system_;
|
||||
CdmLicense license_parser_;
|
||||
CryptoSession* crypto_session_;
|
||||
PolicyEngine policy_engine_;
|
||||
bool license_received_;
|
||||
|
||||
bool properties_valid_;
|
||||
bool require_explicit_renew_request_;
|
||||
|
||||
KeyId key_id_;
|
||||
|
||||
std::set<WvCdmEventListener*> listeners_;
|
||||
|
||||
|
||||
@@ -38,7 +38,21 @@ class CryptoEngine {
|
||||
|
||||
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:
|
||||
|
||||
@@ -55,6 +69,11 @@ private:
|
||||
mutable Lock sessions_lock_;
|
||||
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);
|
||||
};
|
||||
|
||||
|
||||
@@ -9,16 +9,13 @@
|
||||
#include <map>
|
||||
|
||||
#include "crypto_key.h"
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "wv_cdm_types.h"
|
||||
|
||||
namespace wvcdm {
|
||||
|
||||
typedef std::map<CryptoKeyId,CryptoKey*> CryptoKeyMap;
|
||||
|
||||
// TODO(gmorgan): fill out input and output descriptors
|
||||
typedef void* InputDescriptor;
|
||||
typedef void* OutputDescriptor;
|
||||
|
||||
class CryptoSession {
|
||||
public:
|
||||
CryptoSession();
|
||||
@@ -55,12 +52,13 @@ class CryptoSession {
|
||||
|
||||
// Media data path
|
||||
bool SelectKey(const std::string& key_id);
|
||||
bool Decrypt(const InputDescriptor input, OutputDescriptor output);
|
||||
bool Decrypt(const uint8_t* encrypted_buffer,
|
||||
size_t encrypted_size,
|
||||
size_t block_offset,
|
||||
const std::vector<uint8_t>& iv,
|
||||
uint8_t* decrypted_buffer);
|
||||
CdmResponseType Decrypt(bool is_encrypted,
|
||||
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);
|
||||
|
||||
private:
|
||||
|
||||
@@ -69,6 +67,7 @@ class CryptoSession {
|
||||
void GenerateEncryptContext(const std::string& input_context,
|
||||
std::string* deriv_context);
|
||||
size_t GetOffset(std::string message, std::string field);
|
||||
bool SetDestinationBufferType();
|
||||
|
||||
bool valid_;
|
||||
bool open_;
|
||||
@@ -76,6 +75,9 @@ class CryptoSession {
|
||||
CryptoSessionId oec_session_id_;
|
||||
CryptoResult session_status_;
|
||||
|
||||
OEMCryptoBufferType destination_buffer_type_;
|
||||
bool is_destination_buffer_type_valid_;
|
||||
|
||||
CryptoKeyMap keys_;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoSession);
|
||||
|
||||
@@ -19,7 +19,20 @@ static const size_t MAC_KEY_SIZE = 32;
|
||||
// define boolean property keys here
|
||||
// If false begin license usage on first playback
|
||||
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
|
||||
static const std::string QUERY_KEY_LICENSE_TYPE = "LicenseType";
|
||||
@@ -38,6 +51,7 @@ static const std::string QUERY_KEY_RENEWAL_SERVER_URL = "RenewalServerUrl";
|
||||
// url
|
||||
static const std::string QUERY_KEY_SECURITY_LEVEL = "SecurityLevel";
|
||||
// "L1", "L3"
|
||||
|
||||
static const std::string QUERY_VALUE_TRUE = "True";
|
||||
static const std::string QUERY_VALUE_FALSE = "False";
|
||||
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_L2 = "L2";
|
||||
static const std::string QUERY_VALUE_SECURITY_LEVEL_L3 = "L3";
|
||||
|
||||
static const std::string QUERY_VALUE_SECURITY_LEVEL_Unknown = "Unknown";
|
||||
|
||||
} // namespace wvcdm
|
||||
|
||||
|
||||
@@ -278,10 +278,28 @@ CdmResponseType CdmEngine::RenewKey(
|
||||
CdmResponseType CdmEngine::QueryStatus(CdmQueryMap* key_info) {
|
||||
LOGI("CdmEngine::QueryStatus");
|
||||
CryptoEngine* crypto_engine = CryptoEngine::GetInstance();
|
||||
if (crypto_engine) {
|
||||
return crypto_engine->Query(key_info);
|
||||
if (!crypto_engine) {
|
||||
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(
|
||||
@@ -325,23 +343,21 @@ CdmResponseType CdmEngine::Decrypt(
|
||||
const CdmSessionId& session_id,
|
||||
bool is_encrypted,
|
||||
const KeyId& key_id,
|
||||
const uint8_t* encrypted_buffer,
|
||||
size_t encrypted_size,
|
||||
const uint8_t* encrypt_buffer,
|
||||
size_t encrypt_length,
|
||||
const std::vector<uint8_t>& iv,
|
||||
size_t block_offset,
|
||||
uint8_t* decrypted_buffer) {
|
||||
void* decrypt_buffer,
|
||||
bool is_video) {
|
||||
CdmSessionIter iter = sessions_.find(session_id);
|
||||
if (iter == sessions_.end()) {
|
||||
LOGW("CdmEngine::Decrypt: session_id not found = %s", session_id.c_str());
|
||||
return KEY_ERROR;
|
||||
}
|
||||
|
||||
if (NO_ERROR != iter->second->Decrypt(encrypted_buffer, encrypted_size,
|
||||
block_offset, iv, key_id,
|
||||
decrypted_buffer))
|
||||
return UNKNOWN_ERROR;
|
||||
|
||||
return NO_ERROR;
|
||||
return iter->second->Decrypt(is_encrypted, key_id, encrypt_buffer,
|
||||
encrypt_length, iv, block_offset,
|
||||
decrypt_buffer, is_video);
|
||||
}
|
||||
|
||||
bool CdmEngine::IsKeyValid(const KeyId& key_id) {
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "clock.h"
|
||||
#include "crypto_engine.h"
|
||||
#include "log.h"
|
||||
#include "properties.h"
|
||||
#include "string_conversions.h"
|
||||
#include "clock.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
|
||||
namespace wvcdm {
|
||||
@@ -30,6 +31,15 @@ bool CdmSession::Init() {
|
||||
std::string token;
|
||||
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_);
|
||||
}
|
||||
|
||||
@@ -50,20 +60,57 @@ bool CdmSession::VerifySession(const CdmKeySystem& key_system,
|
||||
|
||||
CdmResponseType CdmSession::GenerateKeyRequest(const CdmInitData& init_data,
|
||||
CdmKeyMessage* key_request) {
|
||||
crypto_session_->Open();
|
||||
if(!license_parser_.PrepareKeyRequest(init_data, key_request)) {
|
||||
return KEY_ERROR;
|
||||
} else {
|
||||
return KEY_MESSAGE;
|
||||
if (!properties_valid_) {
|
||||
LOGW("CdmSession::GenerateKeyRequest: Unable to access properties");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
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.
|
||||
CdmResponseType CdmSession::AddKey(const CdmKeyResponse& key_response) {
|
||||
if (!license_parser_.HandleKeyResponse(key_response)) {
|
||||
return KEY_ERROR;
|
||||
} else {
|
||||
return KEY_ADDED;
|
||||
if (!crypto_session_) {
|
||||
LOGW("CdmSession::AddKey: Invalid crypto session");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
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.
|
||||
CdmResponseType CdmSession::Decrypt(const uint8_t* encrypted_buffer,
|
||||
size_t encrypted_size,
|
||||
size_t block_offset,
|
||||
const std::vector<uint8_t>& iv,
|
||||
CdmResponseType CdmSession::Decrypt(bool is_encrypted,
|
||||
const KeyId& key_id,
|
||||
uint8_t* decrypted_buffer) {
|
||||
if (!crypto_session_)
|
||||
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) {
|
||||
if (!crypto_session_ || !crypto_session_->IsOpen())
|
||||
return UNKNOWN_ERROR;
|
||||
|
||||
if (!crypto_session_->SelectKey(key_id))
|
||||
return UNKNOWN_ERROR;
|
||||
// Check if key needs to be selected
|
||||
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,
|
||||
block_offset, iv, decrypted_buffer))
|
||||
return UNKNOWN_ERROR;
|
||||
|
||||
return NO_ERROR;
|
||||
return crypto_session_->Decrypt(is_encrypted, encrypt_buffer, encrypt_length,
|
||||
iv, block_offset, decrypt_buffer, is_video);
|
||||
}
|
||||
|
||||
// License renewal
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include "log.h"
|
||||
#include "OEMCryptoCENC.h"
|
||||
#include "properties.h"
|
||||
#include "wv_cdm_constants.h"
|
||||
|
||||
namespace wvcdm {
|
||||
@@ -23,7 +24,11 @@ Lock CryptoEngine::crypto_engine_lock_;
|
||||
|
||||
// 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() {
|
||||
if (initialized_) {
|
||||
@@ -61,6 +66,29 @@ void CryptoEngine::DeleteInstance() {
|
||||
}
|
||||
|
||||
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");
|
||||
AutoLock auto_lock(crypto_lock_);
|
||||
if (!initialized_) {
|
||||
@@ -175,10 +203,22 @@ bool CryptoEngine::GetToken(std::string* token) {
|
||||
return true;
|
||||
}
|
||||
|
||||
CdmResponseType CryptoEngine::Query(CdmQueryMap* key_info) {
|
||||
LOGV("CryptoEngine::GetToken: Query");
|
||||
(*key_info)[QUERY_KEY_SECURITY_LEVEL] = OEMCrypto_SecurityLevel();
|
||||
return NO_ERROR;
|
||||
CryptoEngine::SecurityLevel CryptoEngine::GetSecurityLevel() {
|
||||
std::string security_level = OEMCrypto_SecurityLevel();
|
||||
|
||||
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
|
||||
|
||||
@@ -35,10 +35,16 @@ namespace wvcdm {
|
||||
|
||||
// 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),
|
||||
open_(false), cdm_session_id_(sname) {}
|
||||
CryptoSession::CryptoSession(const std::string& sname) :
|
||||
valid_(true),
|
||||
open_(false),
|
||||
cdm_session_id_(sname),
|
||||
is_destination_buffer_type_valid_(false) {}
|
||||
|
||||
CryptoSession::~CryptoSession() {
|
||||
if (open_) {
|
||||
@@ -222,7 +228,7 @@ bool CryptoSession::LoadKeys(const std::string& message,
|
||||
enc_mac_key = msg + GetOffset(message, mac_key);
|
||||
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) {
|
||||
const CryptoKey* ki = &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(),
|
||||
reinterpret_cast<const uint8_t*>(signature.data()),
|
||||
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,
|
||||
@@ -258,7 +264,7 @@ bool CryptoSession::RefreshKeys(const std::string& message,
|
||||
AutoLock auto_lock(crypto_engine->crypto_lock_);
|
||||
|
||||
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) {
|
||||
const CryptoKey* ki = &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(),
|
||||
reinterpret_cast<const uint8_t*>(signature.data()),
|
||||
signature.size(),
|
||||
num_keys, load_key_array));
|
||||
num_keys, &load_key_array[0]));
|
||||
}
|
||||
|
||||
bool CryptoSession::SelectKey(const std::string& key_id) {
|
||||
@@ -304,55 +310,49 @@ bool CryptoSession::SelectKey(const std::string& key_id) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CryptoSession::Decrypt(const InputDescriptor input,
|
||||
const OutputDescriptor output) {
|
||||
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;
|
||||
uint8_t* iv = NULL;
|
||||
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;
|
||||
CdmResponseType CryptoSession::Decrypt(bool is_encrypted,
|
||||
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) {
|
||||
if (!is_destination_buffer_type_valid_) {
|
||||
if (!SetDestinationBufferType())
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// TODO(jfore): Define InputDescriptor and OutputDecriptor and
|
||||
// remove this method. For now this is a level 3 decrypt.
|
||||
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;
|
||||
OEMCrypto_DestBufferDesc buffer_descriptor;
|
||||
buffer_descriptor.type = destination_buffer_type_;
|
||||
|
||||
out_buffer.type = OEMCrypto_BufferType_Clear;
|
||||
out_buffer.buffer.clear.address = decrypted_buffer;
|
||||
out_buffer.buffer.clear.max_length = encrypted_size;
|
||||
if (!is_encrypted)
|
||||
buffer_descriptor.type = OEMCrypto_BufferType_Clear;
|
||||
|
||||
OEMCryptoResult sts = OEMCrypto_DecryptCTR(oec_session_id_, encrypted_buffer,
|
||||
encrypted_size, true, &iv[0],
|
||||
offset, &out_buffer);
|
||||
if (OEMCrypto_SUCCESS != sts) {
|
||||
return false;
|
||||
switch (buffer_descriptor.type) {
|
||||
case OEMCrypto_BufferType_Clear:
|
||||
buffer_descriptor.buffer.clear.address =
|
||||
static_cast<uint8_t*>(decrypt_buffer);
|
||||
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) {
|
||||
@@ -366,4 +366,33 @@ bool CryptoSession::GenerateNonce(uint32_t* nonce) {
|
||||
AutoLock auto_lock(crypto_engine->crypto_lock_);
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user