OEMCrypto v16.1
Merge of http://go/wvgerrit/93404 This CL updates the Widevine CDM to support OEMCrypto v16.1 Test: Tested in 16.2 CL Bug: 141247171 Change-Id: I69bd993500f6fb63bf6010c8b0250dc7acc3d71b
This commit is contained in:
@@ -19,8 +19,8 @@
|
||||
|
||||
#include "file_store.h"
|
||||
#include "log.h"
|
||||
#include "odk.h"
|
||||
#include "oemcrypto_engine_ref.h"
|
||||
#include "oemcrypto_old_usage_table_ref.h"
|
||||
// TODO(fredgc): Setting the device files base bath is currently broken as
|
||||
// wvcdm::Properties is no longer used by the reference code.
|
||||
//#include "properties.h"
|
||||
@@ -71,8 +71,7 @@ OEMCryptoResult UsageTableEntry::SetPST(const uint8_t* pst, size_t pst_length) {
|
||||
data_.pst_length = pst_length;
|
||||
if (!pst || !pst_length) return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
memcpy(data_.pst, pst, pst_length);
|
||||
data_.time_of_license_received =
|
||||
usage_table_->ce_->RollbackCorrectedOfflineTime();
|
||||
data_.time_of_license_received = usage_table_->ce_->SystemTime();
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -101,25 +100,7 @@ bool UsageTableEntry::SetMacKeys(const std::vector<uint8_t>& server,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UsageTableEntry::CheckForUse() {
|
||||
if (Inactive()) return false;
|
||||
recent_decrypt_ = true;
|
||||
if (data_.status == kUnused) {
|
||||
data_.status = kActive;
|
||||
data_.time_of_first_decrypt =
|
||||
usage_table_->ce_->RollbackCorrectedOfflineTime();
|
||||
data_.generation_number++;
|
||||
usage_table_->IncrementGeneration();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void UsageTableEntry::Deactivate(const std::vector<uint8_t>& pst) {
|
||||
if (data_.status == kUnused) {
|
||||
data_.status = kInactiveUnused;
|
||||
} else if (data_.status == kActive) {
|
||||
data_.status = kInactiveUsed;
|
||||
}
|
||||
void UsageTableEntry::ForbidReport() {
|
||||
forbid_report_ = true;
|
||||
data_.generation_number++;
|
||||
usage_table_->IncrementGeneration();
|
||||
@@ -151,7 +132,7 @@ OEMCryptoResult UsageTableEntry::ReportUsage(const std::vector<uint8_t>& pst,
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
wvcdm::Unpacked_PST_Report pst_report(buffer);
|
||||
int64_t now = usage_table_->ce_->RollbackCorrectedOfflineTime();
|
||||
int64_t now = usage_table_->ce_->SystemTime();
|
||||
pst_report.set_seconds_since_license_received(now -
|
||||
data_.time_of_license_received);
|
||||
pst_report.set_seconds_since_first_decrypt(now - data_.time_of_first_decrypt);
|
||||
@@ -170,12 +151,29 @@ OEMCryptoResult UsageTableEntry::ReportUsage(const std::vector<uint8_t>& pst,
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
void UsageTableEntry::UpdateAndIncrement() {
|
||||
void UsageTableEntry::UpdateAndIncrement(ODK_ClockValues* clock_values) {
|
||||
if (recent_decrypt_) {
|
||||
data_.time_of_last_decrypt =
|
||||
usage_table_->ce_->RollbackCorrectedOfflineTime();
|
||||
data_.time_of_last_decrypt = usage_table_->ce_->SystemTime();
|
||||
recent_decrypt_ = false;
|
||||
}
|
||||
data_.time_of_license_received = clock_values->time_of_license_signed;
|
||||
data_.time_of_first_decrypt = clock_values->time_of_first_decrypt;
|
||||
// Use the most recent time_of_last_decrypt.
|
||||
if (static_cast<uint64_t>(data_.time_of_last_decrypt) <
|
||||
clock_values->time_of_last_decrypt) {
|
||||
// For the reference implementation, we update the clock_values on every
|
||||
// decrypt.
|
||||
data_.time_of_last_decrypt = clock_values->time_of_last_decrypt;
|
||||
} else {
|
||||
// For this reference implementation of OEMCrypto, we regularly update
|
||||
// clock_values->time_of_last_decrypt and we could just update
|
||||
// data_.time_of_last_decrypt here. However, I'm including the line below to
|
||||
// make it clear that you could do it the other way around. When this
|
||||
// function is called, the two values should be synced so that the usage
|
||||
// entry can be saved with the correct value.
|
||||
clock_values->time_of_last_decrypt = data_.time_of_last_decrypt;
|
||||
}
|
||||
data_.status = clock_values->status;
|
||||
data_.generation_number++;
|
||||
usage_table_->IncrementGeneration();
|
||||
forbid_report_ = false;
|
||||
@@ -194,7 +192,7 @@ OEMCryptoResult UsageTableEntry::SaveData(CryptoEngine* ce,
|
||||
reinterpret_cast<SignedEntryBlock*>(&clear_buffer[0]);
|
||||
SignedEntryBlock* encrypted =
|
||||
reinterpret_cast<SignedEntryBlock*>(signed_buffer);
|
||||
clear->data = this->data_; // Copy the current data.
|
||||
clear->data = data_; // Copy the current data.
|
||||
memcpy(clear->verification, kEntryVerification, kMagicLength);
|
||||
|
||||
// This should be encrypted and signed with a device specific key.
|
||||
@@ -228,7 +226,8 @@ OEMCryptoResult UsageTableEntry::SaveData(CryptoEngine* ce,
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTableEntry::LoadData(CryptoEngine* ce, uint32_t index,
|
||||
const std::vector<uint8_t>& buffer) {
|
||||
const std::vector<uint8_t>& buffer,
|
||||
ODK_ClockValues* clock_values) {
|
||||
if (buffer.size() < SignedEntrySize()) return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
if (buffer.size() > SignedEntrySize())
|
||||
LOGW("LoadUsageTableEntry: buffer is large. %d > %d", buffer.size(),
|
||||
@@ -295,39 +294,10 @@ OEMCryptoResult UsageTableEntry::LoadData(CryptoEngine* ce, uint32_t index,
|
||||
LOGE("LoadUsageEntry: entry has bad status %d", clear->data.status);
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
this->data_ = clear->data;
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTableEntry::CopyOldUsageEntry(
|
||||
const std::vector<uint8_t>& pst) {
|
||||
OldUsageTableEntry* old_entry = usage_table_->FindOldUsageEntry(pst);
|
||||
if (!old_entry) return OEMCrypto_ERROR_WRONG_PST;
|
||||
data_.time_of_license_received = old_entry->time_of_license_received_;
|
||||
data_.time_of_first_decrypt = old_entry->time_of_first_decrypt_;
|
||||
data_.time_of_last_decrypt = old_entry->time_of_last_decrypt_;
|
||||
data_.status = old_entry->status_;
|
||||
if (old_entry->mac_key_server_.size() != wvoec::MAC_KEY_SIZE) {
|
||||
LOGE("CopyOldEntry: Old entry has bad server mac key.");
|
||||
} else {
|
||||
memcpy(data_.mac_key_server, &(old_entry->mac_key_server_[0]),
|
||||
wvoec::MAC_KEY_SIZE);
|
||||
}
|
||||
if (old_entry->mac_key_client_.size() != wvoec::MAC_KEY_SIZE) {
|
||||
LOGE("CopyOldEntry: Old entry has bad client mac key.");
|
||||
} else {
|
||||
memcpy(data_.mac_key_client, &(old_entry->mac_key_client_[0]),
|
||||
wvoec::MAC_KEY_SIZE);
|
||||
}
|
||||
if (pst.size() > kMaxPSTLength) {
|
||||
LOGE("CopyOldEntry: PST Length was too large. Truncating.");
|
||||
data_.pst_length = kMaxPSTLength;
|
||||
} else {
|
||||
data_.pst_length = pst.size();
|
||||
}
|
||||
memcpy(data_.pst, pst.data(), data_.pst_length);
|
||||
data_.pst[data_.pst_length] = '\0';
|
||||
return OEMCrypto_SUCCESS;
|
||||
data_ = clear->data;
|
||||
return ODK_ReloadClockValues(
|
||||
clock_values, data_.time_of_license_received, data_.time_of_first_decrypt,
|
||||
data_.time_of_last_decrypt, data_.status, ce->SystemTime());
|
||||
}
|
||||
|
||||
size_t UsageTableEntry::SignedEntrySize() {
|
||||
@@ -337,12 +307,7 @@ size_t UsageTableEntry::SignedEntrySize() {
|
||||
return blocks * wvoec::KEY_IV_SIZE;
|
||||
}
|
||||
|
||||
UsageTable::~UsageTable() {
|
||||
if (old_table_) {
|
||||
delete old_table_;
|
||||
old_table_ = NULL;
|
||||
}
|
||||
}
|
||||
UsageTable::~UsageTable() {}
|
||||
|
||||
size_t UsageTable::SignedHeaderSize(size_t count) {
|
||||
size_t base = sizeof(SignedHeaderBlock) + count * sizeof(int64_t);
|
||||
@@ -351,12 +316,10 @@ size_t UsageTable::SignedHeaderSize(size_t count) {
|
||||
return blocks * wvoec::KEY_IV_SIZE;
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTable::UpdateUsageEntry(SessionContext* session,
|
||||
UsageTableEntry* entry,
|
||||
uint8_t* header_buffer,
|
||||
size_t* header_buffer_length,
|
||||
uint8_t* entry_buffer,
|
||||
size_t* entry_buffer_length) {
|
||||
OEMCryptoResult UsageTable::UpdateUsageEntry(
|
||||
SessionContext* session, UsageTableEntry* entry, uint8_t* header_buffer,
|
||||
size_t* header_buffer_length, uint8_t* entry_buffer,
|
||||
size_t* entry_buffer_length, ODK_ClockValues* clock_values) {
|
||||
size_t signed_header_size = SignedHeaderSize(generation_numbers_.size());
|
||||
if (*entry_buffer_length < UsageTableEntry::SignedEntrySize() ||
|
||||
*header_buffer_length < signed_header_size) {
|
||||
@@ -368,7 +331,7 @@ OEMCryptoResult UsageTable::UpdateUsageEntry(SessionContext* session,
|
||||
*header_buffer_length = signed_header_size;
|
||||
if ((!header_buffer) || (!entry_buffer))
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
entry->UpdateAndIncrement();
|
||||
entry->UpdateAndIncrement(clock_values);
|
||||
generation_numbers_[entry->index()] = entry->generation_number();
|
||||
OEMCryptoResult result =
|
||||
entry->SaveData(ce_, session, entry_buffer, *entry_buffer_length);
|
||||
@@ -408,7 +371,8 @@ OEMCryptoResult UsageTable::CreateNewUsageEntry(SessionContext* session,
|
||||
OEMCryptoResult UsageTable::LoadUsageEntry(SessionContext* session,
|
||||
UsageTableEntry** entry,
|
||||
uint32_t index,
|
||||
const std::vector<uint8_t>& buffer) {
|
||||
const std::vector<uint8_t>& buffer,
|
||||
ODK_ClockValues* clock_values) {
|
||||
if (!header_loaded_) {
|
||||
LOGE("CreateNewUsageEntry: Header not loaded.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
@@ -427,7 +391,8 @@ OEMCryptoResult UsageTable::LoadUsageEntry(SessionContext* session,
|
||||
}
|
||||
UsageTableEntry* new_entry = MakeEntry(index);
|
||||
|
||||
OEMCryptoResult status = new_entry->LoadData(ce_, index, buffer);
|
||||
OEMCryptoResult status =
|
||||
new_entry->LoadData(ce_, index, buffer, clock_values);
|
||||
if (status != OEMCrypto_SUCCESS) {
|
||||
delete new_entry;
|
||||
return status;
|
||||
@@ -722,7 +687,7 @@ OEMCryptoResult UsageTable::CreateUsageTableHeader(
|
||||
if (!LoadGenerationNumber(true)) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
// Make sure there are no entries that are currently tied to an open session.
|
||||
for (size_t i = 0; i < sessions_.size(); ++i) {
|
||||
if (sessions_[i] != NULL) {
|
||||
if (sessions_[i] != nullptr) {
|
||||
LOGE("CreateUsageTableHeader: index %d used by session.", i);
|
||||
return OEMCrypto_ERROR_INVALID_SESSION;
|
||||
}
|
||||
@@ -733,41 +698,4 @@ OEMCryptoResult UsageTable::CreateUsageTableHeader(
|
||||
return SaveUsageTableHeader(header_buffer, *header_buffer_length);
|
||||
}
|
||||
|
||||
OldUsageTableEntry* UsageTable::FindOldUsageEntry(
|
||||
const std::vector<uint8_t>& pst) {
|
||||
if (!old_table_) old_table_ = new OldUsageTable(ce_);
|
||||
return old_table_->FindEntry(pst);
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTable::DeleteOldUsageTable() {
|
||||
if (old_table_) {
|
||||
old_table_->Clear();
|
||||
delete old_table_;
|
||||
old_table_ = NULL;
|
||||
}
|
||||
OldUsageTable::DeleteFile(ce_);
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult UsageTable::CreateOldUsageEntry(
|
||||
uint64_t time_since_license_received, uint64_t time_since_first_decrypt,
|
||||
uint64_t time_since_last_decrypt, OEMCrypto_Usage_Entry_Status status,
|
||||
uint8_t* server_mac_key, uint8_t* client_mac_key, const uint8_t* pst,
|
||||
size_t pst_length) {
|
||||
if (!old_table_) old_table_ = new OldUsageTable(ce_);
|
||||
std::vector<uint8_t> pstv(pst, pst + pst_length);
|
||||
OldUsageTableEntry* old_entry = old_table_->CreateEntry(pstv);
|
||||
|
||||
int64_t now = ce_->RollbackCorrectedOfflineTime();
|
||||
old_entry->time_of_license_received_ = now - time_since_license_received;
|
||||
old_entry->time_of_first_decrypt_ = now - time_since_first_decrypt;
|
||||
old_entry->time_of_last_decrypt_ = now - time_since_last_decrypt;
|
||||
old_entry->status_ = status;
|
||||
old_entry->mac_key_server_.assign(server_mac_key,
|
||||
server_mac_key + wvoec::MAC_KEY_SIZE);
|
||||
old_entry->mac_key_client_.assign(client_mac_key,
|
||||
client_mac_key + wvoec::MAC_KEY_SIZE);
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
Reference in New Issue
Block a user