V16.4.2
Changes include: - Let entitled key sessions hold entitlement key id
This commit is contained in:
@@ -69,13 +69,13 @@ void UnlockAndCloseHardwareKeySlot(int fd) {
|
|||||||
|
|
||||||
EntitledKeySession::~EntitledKeySession() { ClearKeySlot(); }
|
EntitledKeySession::~EntitledKeySession() { ClearKeySlot(); }
|
||||||
|
|
||||||
const Key* EntitledKeySession::GetEntitlementKey(
|
KeyId EntitledKeySession::GetEntitlementKeyId(
|
||||||
const KeyId& content_key_id) const {
|
const KeyId& content_key_id) const {
|
||||||
if (content_key_info_map_.find(content_key_id) ==
|
auto content_key_info_iter = content_key_info_map_.find(content_key_id);
|
||||||
content_key_info_map_.end()) {
|
if (content_key_info_iter == content_key_info_map_.end()) {
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
}
|
||||||
return content_key_info_map_.at(content_key_id)->entitlement_key;
|
return content_key_info_iter->second->entitlement_key_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntitledKey* EntitledKeySession::GetContentKey(
|
EntitledKey* EntitledKeySession::GetContentKey(
|
||||||
@@ -88,18 +88,18 @@ EntitledKey* EntitledKeySession::GetContentKey(
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool EntitledKeySession::AddOrUpdateContentKey(
|
bool EntitledKeySession::AddOrUpdateContentKey(
|
||||||
Key* entitlement_key, const KeyId& content_key_id,
|
const KeyId& entitlement_key_id, const KeyId& content_key_id,
|
||||||
std::unique_ptr<EntitledKey> content_key) {
|
std::unique_ptr<EntitledKey> content_key) {
|
||||||
if (entitlement_key == nullptr || content_key_id.empty() ||
|
if (entitlement_key_id.empty() || content_key_id.empty() ||
|
||||||
content_key == nullptr) {
|
content_key == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
// Remove the entry if |entitlement_key| already referenced by a content key
|
// Remove the entry if |entitlement_key_id| is already referenced by a content
|
||||||
// with the same parity. Each entitlement key can only be referred by one
|
// key with the same parity. Each entitlement key can only be referred by one
|
||||||
// even and one odd content key within an entitled key session.
|
// even and one odd content key within an entitled key session.
|
||||||
for (auto const& content_key_entry : content_key_info_map_) {
|
for (auto const& content_key_entry : content_key_info_map_) {
|
||||||
const ContentKeyInfo* const key_info = content_key_entry.second.get();
|
const ContentKeyInfo* const key_info = content_key_entry.second.get();
|
||||||
if (key_info->entitlement_key == entitlement_key &&
|
if (key_info->entitlement_key_id == entitlement_key_id &&
|
||||||
key_info->content_key->is_even_key() == content_key->is_even_key()) {
|
key_info->content_key->is_even_key() == content_key->is_even_key()) {
|
||||||
RemoveContentKey(content_key_entry.first);
|
RemoveContentKey(content_key_entry.first);
|
||||||
break;
|
break;
|
||||||
@@ -114,7 +114,8 @@ bool EntitledKeySession::AddOrUpdateContentKey(
|
|||||||
content_key_info_map_[content_key_id] =
|
content_key_info_map_[content_key_id] =
|
||||||
std::unique_ptr<ContentKeyInfo>(new ContentKeyInfo());
|
std::unique_ptr<ContentKeyInfo>(new ContentKeyInfo());
|
||||||
content_key_info_map_[content_key_id]->content_key = std::move(content_key);
|
content_key_info_map_[content_key_id]->content_key = std::move(content_key);
|
||||||
content_key_info_map_[content_key_id]->entitlement_key = entitlement_key;
|
content_key_info_map_[content_key_id]->entitlement_key_id =
|
||||||
|
entitlement_key_id;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,35 +22,37 @@ typedef uint32_t SessionId;
|
|||||||
|
|
||||||
class EntitledKeySession {
|
class EntitledKeySession {
|
||||||
public:
|
public:
|
||||||
explicit EntitledKeySession(SessionId key_sid)
|
explicit EntitledKeySession(SessionId key_sid) : key_sid_(key_sid){};
|
||||||
: key_sid_(key_sid),
|
|
||||||
current_content_key_(nullptr),
|
|
||||||
current_entitlement_key_(nullptr){};
|
|
||||||
EntitledKeySession(const EntitledKeySession&) = delete;
|
EntitledKeySession(const EntitledKeySession&) = delete;
|
||||||
EntitledKeySession(EntitledKeySession&&) = delete;
|
EntitledKeySession(EntitledKeySession&&) = delete;
|
||||||
~EntitledKeySession();
|
~EntitledKeySession();
|
||||||
|
|
||||||
// Get id of this entitled key session .
|
// Get id of this entitled key session .
|
||||||
SessionId GetSessionId() const { return key_sid_; }
|
SessionId GetSessionId() const { return key_sid_; }
|
||||||
// Get reference of the entitlement key that entitles |content_key_id|.
|
// Get ID of the entitlement key that entitles |content_key_id|. An empty ID
|
||||||
const Key* GetEntitlementKey(const KeyId& content_key_id) const;
|
// will be returned in case of error.
|
||||||
|
KeyId GetEntitlementKeyId(const KeyId& content_key_id) const;
|
||||||
// Get content key whose id is |content_key_id|.
|
// Get content key whose id is |content_key_id|.
|
||||||
EntitledKey* GetContentKey(const KeyId& content_key_id) const;
|
EntitledKey* GetContentKey(const KeyId& content_key_id) const;
|
||||||
|
|
||||||
// Select current content key to |content_key_id|, and current entitlement
|
// Select current content key to |content_key_id|.
|
||||||
// key to its corresponding entitlement key.
|
|
||||||
void SetCurrentKey(const KeyId& content_key_id) {
|
void SetCurrentKey(const KeyId& content_key_id) {
|
||||||
current_content_key_ = GetContentKey(content_key_id);
|
current_content_key_id_ = content_key_id;
|
||||||
current_entitlement_key_ = GetEntitlementKey(content_key_id);
|
|
||||||
}
|
}
|
||||||
// Return the current content key selected, nullptr if none is selected.
|
// Return the current content key selected, nullptr if none is selected.
|
||||||
const EntitledKey* CurrentContentKey() const { return current_content_key_; }
|
const EntitledKey* CurrentContentKey() const {
|
||||||
// Return the current entitlement key selected, nullptr if none is selected.
|
return GetContentKey(current_content_key_id_);
|
||||||
const Key* CurrentEntitlementKey() const { return current_entitlement_key_; }
|
}
|
||||||
|
// Return the current entitlement key id selected, empty if none is selected.
|
||||||
// Update the content key that refers to |entitlement_key| or insert a new
|
KeyId CurrentEntitlementKeyId() const {
|
||||||
// entry that refers to |entitlement_key|. |entitlement_key| must not be null.
|
return GetEntitlementKeyId(current_content_key_id_);
|
||||||
bool AddOrUpdateContentKey(Key* entitlement_key, const KeyId& content_key_id,
|
}
|
||||||
|
// If the specified |entitlement_key_id| has already been referenced by a
|
||||||
|
// content key with the same parity (even/odd), it will replace it with the
|
||||||
|
// new |content key| passed in. Otherwise, insert a new entry that refers to
|
||||||
|
// |entitlement_key_id|.
|
||||||
|
bool AddOrUpdateContentKey(const KeyId& entitlement_key_id,
|
||||||
|
const KeyId& content_key_id,
|
||||||
std::unique_ptr<EntitledKey> content_key);
|
std::unique_ptr<EntitledKey> content_key);
|
||||||
// Remove a content key |content_key_id|.
|
// Remove a content key |content_key_id|.
|
||||||
bool RemoveContentKey(const KeyId& content_key_id);
|
bool RemoveContentKey(const KeyId& content_key_id);
|
||||||
@@ -68,7 +70,7 @@ class EntitledKeySession {
|
|||||||
private:
|
private:
|
||||||
struct ContentKeyInfo {
|
struct ContentKeyInfo {
|
||||||
std::unique_ptr<EntitledKey> content_key;
|
std::unique_ptr<EntitledKey> content_key;
|
||||||
Key* entitlement_key;
|
KeyId entitlement_key_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Must have the same exact definition on the tuner hal side.
|
// Must have the same exact definition on the tuner hal side.
|
||||||
@@ -92,8 +94,7 @@ class EntitledKeySession {
|
|||||||
ContentKeySlot* key_slot) const;
|
ContentKeySlot* key_slot) const;
|
||||||
|
|
||||||
const SessionId key_sid_;
|
const SessionId key_sid_;
|
||||||
EntitledKey* current_content_key_;
|
KeyId current_content_key_id_;
|
||||||
const Key* current_entitlement_key_;
|
|
||||||
// Map from content key id to content key info.
|
// Map from content key id to content key info.
|
||||||
std::map<KeyId, std::unique_ptr<ContentKeyInfo>> content_key_info_map_;
|
std::map<KeyId, std::unique_ptr<ContentKeyInfo>> content_key_info_map_;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -631,18 +631,22 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_QueryKeyControl(
|
|||||||
LOGE("[OEMCrypto_QueryKeyControl(): ERROR_INVALID_SESSION]");
|
LOGE("[OEMCrypto_QueryKeyControl(): ERROR_INVALID_SESSION]");
|
||||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||||
}
|
}
|
||||||
EntitledKeySession* entitled_key_session = nullptr;
|
|
||||||
|
std::vector<uint8_t> key_id_str(key_id, key_id + key_id_length);
|
||||||
|
// |key_id| is the content key id in case of entitlement license. In this
|
||||||
|
// case, get the corresponding entitlement key which holds the key control
|
||||||
|
// block.
|
||||||
if (crypto_engine->SessionTypeBits(session) == kSessionTypeEntitledKey) {
|
if (crypto_engine->SessionTypeBits(session) == kSessionTypeEntitledKey) {
|
||||||
entitled_key_session = crypto_engine->FindEntitledKeySession(session);
|
EntitledKeySession* entitled_key_session =
|
||||||
|
crypto_engine->FindEntitledKeySession(session);
|
||||||
if (entitled_key_session == nullptr) {
|
if (entitled_key_session == nullptr) {
|
||||||
LOGE("OEMCrypto_QueryKeyControl(): can not find the key session.");
|
LOGE("OEMCrypto_QueryKeyControl(): can not find the key session.");
|
||||||
return OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION;
|
return OEMCrypto_ERROR_INVALID_ENTITLED_KEY_SESSION;
|
||||||
}
|
}
|
||||||
|
key_id_str = entitled_key_session->GetEntitlementKeyId(key_id_str);
|
||||||
}
|
}
|
||||||
const std::vector<uint8_t> key_id_str =
|
|
||||||
std::vector<uint8_t>(key_id, key_id + key_id_length);
|
if (!session_ctx->QueryKeyControlBlock(key_id_str, block)) {
|
||||||
if (!session_ctx->QueryKeyControlBlock(entitled_key_session, key_id_str,
|
|
||||||
block)) {
|
|
||||||
LOGE("[OEMCrypto_QueryKeyControl(): FAIL]");
|
LOGE("[OEMCrypto_QueryKeyControl(): FAIL]");
|
||||||
return OEMCrypto_ERROR_NO_CONTENT_KEY;
|
return OEMCrypto_ERROR_NO_CONTENT_KEY;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -830,7 +830,7 @@ OEMCryptoResult SessionContext::LoadEntitledContentKeys(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!key_session->AddOrUpdateContentKey(
|
if (!key_session->AddOrUpdateContentKey(
|
||||||
entitlement_key, content_key_id,
|
entitlement_key_id, content_key_id,
|
||||||
std::unique_ptr<EntitledKey>(new EntitledKey(content_key)))) {
|
std::unique_ptr<EntitledKey>(new EntitledKey(content_key)))) {
|
||||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
}
|
}
|
||||||
@@ -909,7 +909,7 @@ OEMCryptoResult SessionContext::LoadEntitledCasKeys(
|
|||||||
content_key_obj->set_cipher_mode(key_data->cipher_mode);
|
content_key_obj->set_cipher_mode(key_data->cipher_mode);
|
||||||
content_key_obj->set_is_even_key(i % 2 == 0);
|
content_key_obj->set_is_even_key(i % 2 == 0);
|
||||||
|
|
||||||
if (!key_session->AddOrUpdateContentKey(entitlement_key, content_key_id,
|
if (!key_session->AddOrUpdateContentKey(entitlement_key_id, content_key_id,
|
||||||
std::move(content_key_obj))) {
|
std::move(content_key_obj))) {
|
||||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
}
|
}
|
||||||
@@ -1400,22 +1400,11 @@ bool SessionContext::UpdateMacKeys(const std::vector<uint8_t>& enc_mac_keys,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SessionContext::QueryKeyControlBlock(EntitledKeySession* key_session,
|
bool SessionContext::QueryKeyControlBlock(const KeyId& key_id, uint32_t* data) {
|
||||||
const KeyId& key_id, uint32_t* data) {
|
|
||||||
if (session_keys_ == nullptr) {
|
if (session_keys_ == nullptr) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if ((session_keys_->type() == OEMCrypto_EntitlementLicense &&
|
const Key* control_key = session_keys_->Find(key_id);
|
||||||
key_session == nullptr) ||
|
|
||||||
(session_keys_->type() == OEMCrypto_ContentLicense &&
|
|
||||||
key_session != nullptr)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// For entitlement license, |key_id| here refers to the content key id.
|
|
||||||
const Key* control_key = key_session != nullptr
|
|
||||||
? key_session->GetEntitlementKey(key_id)
|
|
||||||
: session_keys_->Find(key_id);
|
|
||||||
if (control_key == nullptr) {
|
if (control_key == nullptr) {
|
||||||
LOGE("[QueryKeyControlBlock(): No key matches key id]");
|
LOGE("[QueryKeyControlBlock(): No key matches key id]");
|
||||||
return false;
|
return false;
|
||||||
@@ -1657,20 +1646,13 @@ OEMCryptoResult SessionContext::DecryptSubsample(
|
|||||||
|
|
||||||
// Compute hash for FDPT.
|
// Compute hash for FDPT.
|
||||||
if (compute_hash_) {
|
if (compute_hash_) {
|
||||||
bool has_key_control = false;
|
const Key* current_control_key =
|
||||||
uint32_t key_control_bits = 0;
|
key_session == nullptr
|
||||||
if (key_session != nullptr &&
|
? current_content_key()
|
||||||
key_session->CurrentEntitlementKey() != nullptr) {
|
: session_keys_->Find(key_session->CurrentEntitlementKeyId());
|
||||||
has_key_control = true;
|
if (current_control_key == nullptr ||
|
||||||
key_control_bits =
|
(current_control_key->control().control_bits() &
|
||||||
key_session->CurrentEntitlementKey()->control().control_bits();
|
wvoec::kControlAllowHashVerification) == 0) {
|
||||||
} else if (key_session == nullptr && current_content_key() != nullptr) {
|
|
||||||
has_key_control = true;
|
|
||||||
key_control_bits = current_content_key()->control().control_bits();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!has_key_control ||
|
|
||||||
(key_control_bits & wvoec::kControlAllowHashVerification) == 0) {
|
|
||||||
LOGE("[DecryptCENC(): OEMCrypto_ERROR_UNKNOWN_FAILURE]");
|
LOGE("[DecryptCENC(): OEMCrypto_ERROR_UNKNOWN_FAILURE]");
|
||||||
hash_error_ = OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
hash_error_ = OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||||
compute_hash_ = false;
|
compute_hash_ = false;
|
||||||
@@ -1714,10 +1696,15 @@ OEMCryptoResult SessionContext::ChooseDecrypt(
|
|||||||
LOGE("[ChooseDecrypt(): OEMCrypto_ERROR_NO_CONTENT_KEY]");
|
LOGE("[ChooseDecrypt(): OEMCrypto_ERROR_NO_CONTENT_KEY]");
|
||||||
return OEMCrypto_ERROR_DECRYPT_FAILED;
|
return OEMCrypto_ERROR_DECRYPT_FAILED;
|
||||||
}
|
}
|
||||||
|
const Key* current_control_key =
|
||||||
const KeyControlBlock& key_control_block =
|
key_session == nullptr
|
||||||
key_session == nullptr ? current_content_key()->control()
|
? current_content_key()
|
||||||
: key_session->CurrentEntitlementKey()->control();
|
: session_keys_->Find(key_session->CurrentEntitlementKeyId());
|
||||||
|
if (current_control_key == nullptr) {
|
||||||
|
LOGE("[ChooseDecrypt(): Can not find key control block.]");
|
||||||
|
return OEMCrypto_ERROR_DECRYPT_FAILED;
|
||||||
|
}
|
||||||
|
const KeyControlBlock& key_control_block = current_control_key->control();
|
||||||
OEMCryptoResult result =
|
OEMCryptoResult result =
|
||||||
CheckKeyControlBlockUse(key_control_block, "DecryptCENC", 0, buffer_type);
|
CheckKeyControlBlockUse(key_control_block, "DecryptCENC", 0, buffer_type);
|
||||||
if (result != OEMCrypto_SUCCESS) return result;
|
if (result != OEMCrypto_SUCCESS) return result;
|
||||||
|
|||||||
@@ -142,8 +142,8 @@ class SessionContext {
|
|||||||
const std::vector<uint8_t>& key_control_iv);
|
const std::vector<uint8_t>& key_control_iv);
|
||||||
virtual bool UpdateMacKeys(const std::vector<uint8_t>& mac_keys,
|
virtual bool UpdateMacKeys(const std::vector<uint8_t>& mac_keys,
|
||||||
const std::vector<uint8_t>& iv);
|
const std::vector<uint8_t>& iv);
|
||||||
virtual bool QueryKeyControlBlock(EntitledKeySession* key_session,
|
// |key_id| must be the key that holds the key control block.
|
||||||
const KeyId& key_id, uint32_t* data);
|
virtual bool QueryKeyControlBlock(const KeyId& key_id, uint32_t* data);
|
||||||
virtual OEMCryptoResult SelectEntitledContentKey(
|
virtual OEMCryptoResult SelectEntitledContentKey(
|
||||||
EntitledKeySession* key_session, const KeyId& key_id,
|
EntitledKeySession* key_session, const KeyId& key_id,
|
||||||
OEMCryptoCipherMode cipher_mode);
|
OEMCryptoCipherMode cipher_mode);
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
// Version format: OEMCrypto_major.OEMCrypto_minor.Plugin_version
|
// Version format: OEMCrypto_major.OEMCrypto_minor.Plugin_version
|
||||||
constexpr char kWvCasPluginVersion[] = "16.4.1";
|
constexpr char kWvCasPluginVersion[] = "16.4.2";
|
||||||
|
|
||||||
bool GetAndroidProperty(const char* key, std::string* value) {
|
bool GetAndroidProperty(const char* key, std::string* value) {
|
||||||
char val[PROPERTY_VALUE_MAX];
|
char val[PROPERTY_VALUE_MAX];
|
||||||
|
|||||||
Reference in New Issue
Block a user