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:
Fred Gylys-Colwell
2020-01-18 10:11:24 -08:00
parent 7e2619e379
commit 7665614b2e
132 changed files with 12331 additions and 9341 deletions

View File

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