Changes include:
- Let entitled key sessions hold entitlement key id
This commit is contained in:
Lu Chen
2021-06-29 15:28:34 -07:00
parent 065ca035c9
commit 8eb2d07c5f
7 changed files with 66 additions and 73 deletions

View File

@@ -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;
} }

View File

@@ -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_;
}; };

View File

@@ -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;
} }

View File

@@ -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;

View File

@@ -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);

View File

@@ -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];