OEMCrypto Backwards Compatible Usage Table

Merge from widevine of http://go/wvgerrit/23283

This CL adds the backwards compatiblity functions to the new usage
tables in the oemcrypto mock reference code.

b/31458046
b/32554171

Change-Id: I04901d95aceb8910406f7c514c26c29c2c575322
This commit is contained in:
Fred Gylys-Colwell
2017-01-27 15:22:55 -08:00
parent d06fa606c7
commit 9e153438db
14 changed files with 1151 additions and 350 deletions

View File

@@ -13,6 +13,7 @@ LOCAL_SRC_FILES:= \
src/oemcrypto_logging.cpp \
src/oemcrypto_mock.cpp \
src/oemcrypto_nonce_table.cpp \
src/oemcrypto_old_usage_table_mock.cpp \
src/oemcrypto_rsa_key_shared.cpp \
src/oemcrypto_session.cpp \
src/oemcrypto_session_key_table.cpp \

View File

@@ -1417,15 +1417,6 @@ extern "C" uint32_t OEMCrypto_SupportedCertificates() {
}
return OEMCrypto_Supports_RSA_2048bit | OEMCrypto_Supports_RSA_3072bit |
OEMCrypto_Supports_RSA_CAST;
if (!crypto_engine) {
LOGE("OEMCrypto_GetProvisioningMethod: OEMCrypto Not Initialized.");
return 0;
}
if (crypto_engine->config_provisioning_method() == OEMCrypto_DrmCertificate) {
return 0;
}
return OEMCrypto_Supports_RSA_2048bit | OEMCrypto_Supports_RSA_3072bit |
OEMCrypto_Supports_RSA_CAST;
}
extern "C" OEMCryptoResult OEMCrypto_Generic_Encrypt(
@@ -1827,10 +1818,6 @@ extern "C" OEMCryptoResult OEMCrypto_ShrinkUsageTableHeader(
if (!crypto_engine->config_supports_usage_table()) {
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
if (!header_buffer) {
LOGE("OEMCrypto_ShrinkUsageTableHeader: buffer null.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
return crypto_engine->usage_table().ShrinkUsageTableHeader(
new_table_size, header_buffer, header_buffer_length);
}
@@ -1876,4 +1863,29 @@ extern "C" OEMCryptoResult OEMCrypto_CopyOldUsageEntry(
return session_ctx->CopyOldUsageEntry(pstv);
}
extern "C"
OEMCryptoResult OEMCrypto_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 (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
LOGI("-- OEMCryptoResult OEMCrypto_CreateOldUsageEntry()\n");
}
if (!crypto_engine) {
LOGE("OEMCrypto_CreateOldUsageEntry: OEMCrypto Not Initialized.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (!crypto_engine->config_supports_usage_table()) {
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
}
return crypto_engine->usage_table().CreateOldUsageEntry(
time_since_license_received, time_since_first_decrypt,
time_since_last_decrypt, status, server_mac_key, client_mac_key, pst,
pst_length);
}
} // namespace wvoec_mock

View File

@@ -0,0 +1,237 @@
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Mock implementation of OEMCrypto APIs
//
#include "oemcrypto_old_usage_table_mock.h"
#include <string.h>
#include <time.h>
#include <string>
#include <vector>
#include <openssl/aes.h>
#include <openssl/hmac.h>
#include <openssl/rand.h>
#include <openssl/sha.h>
#include "file_store.h"
#include "log.h"
#include "oemcrypto_engine_mock.h"
#include "oemcrypto_logging.h"
#include "properties.h"
#include "pst_report.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h"
namespace wvoec_mock {
OldUsageTableEntry::OldUsageTableEntry(const std::vector<uint8_t> &pst_hash)
: pst_hash_(pst_hash),
time_of_license_received_(time(NULL)),
time_of_first_decrypt_(0),
time_of_last_decrypt_(0),
status_(kUnused) {}
OldUsageTableEntry::~OldUsageTableEntry() {}
OldUsageTableEntry::OldUsageTableEntry(const OldStoredUsageEntry *buffer) {
pst_hash_.assign(buffer->pst_hash, buffer->pst_hash + SHA256_DIGEST_LENGTH);
time_of_license_received_ = buffer->time_of_license_received;
time_of_first_decrypt_ = buffer->time_of_first_decrypt;
time_of_last_decrypt_ = buffer->time_of_last_decrypt;
status_ = buffer->status;
mac_key_server_.assign(buffer->mac_key_server,
buffer->mac_key_server + wvcdm::MAC_KEY_SIZE);
mac_key_client_.assign(buffer->mac_key_client,
buffer->mac_key_client + wvcdm::MAC_KEY_SIZE);
}
OldUsageTable::OldUsageTable(CryptoEngine *ce) {
ce_ = ce;
generation_ = 0;
table_.clear();
// Load saved table.
wvcdm::FileSystem *file_system = ce->file_system();
wvcdm::File *file;
std::string path;
// Note: this path is OK for a real implementation, but using security level 1
// would be better.
if (!wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3,
&path)) {
LOGE("OldUsageTable: Unable to get base path");
return;
}
std::string filename = path + "UsageTable.dat";
if (!file_system->Exists(filename)) {
if (LogCategoryEnabled(kLoggingTraceUsageTable)) {
LOGI("OldUsageTable: No saved usage table. Creating new table.");
}
return;
}
size_t file_size = file_system->FileSize(filename);
std::vector<uint8_t> encrypted_buffer(file_size);
std::vector<uint8_t> buffer(file_size);
OldStoredUsageTable *stored_table =
reinterpret_cast<OldStoredUsageTable *>(&buffer[0]);
OldStoredUsageTable *encrypted_table =
reinterpret_cast<OldStoredUsageTable *>(&encrypted_buffer[0]);
file = file_system->Open(filename, wvcdm::FileSystem::kReadOnly);
if (!file) {
LOGE("OldUsageTable: File open failed: %s", path.c_str());
return;
}
file->Read(reinterpret_cast<char *>(&encrypted_buffer[0]), file_size);
file->Close();
// Verify the signature of the usage table file.
// This should be encrypted and signed with a device specific key.
// For the reference implementation, I'm just going to use the keybox key.
const bool override_to_real = true;
const std::vector<uint8_t> &key = ce_->DeviceRootKey(override_to_real);
uint8_t computed_signature[SHA256_DIGEST_LENGTH];
unsigned int sig_length = sizeof(computed_signature);
if (!HMAC(EVP_sha256(), &key[0], key.size(),
&encrypted_buffer[SHA256_DIGEST_LENGTH],
file_size - SHA256_DIGEST_LENGTH, computed_signature,
&sig_length)) {
LOGE("OldUsageTable: Could not recreate signature.");
table_.clear();
return;
}
if (memcmp(encrypted_table->signature, computed_signature, sig_length)) {
LOGE("OldUsageTable: Invalid signature given: %s",
wvcdm::HexEncode(&encrypted_buffer[0], sig_length).c_str());
LOGE("OldUsageTable: Invalid signature computed: %s",
wvcdm::HexEncode(computed_signature, sig_length).c_str());
table_.clear();
return;
}
// Next, decrypt the table.
uint8_t iv_buffer[wvcdm::KEY_IV_SIZE];
memcpy(iv_buffer, encrypted_table->iv, wvcdm::KEY_IV_SIZE);
AES_KEY aes_key;
AES_set_decrypt_key(&key[0], 128, &aes_key);
AES_cbc_encrypt(&encrypted_buffer[SHA256_DIGEST_LENGTH + wvcdm::KEY_IV_SIZE],
&buffer[SHA256_DIGEST_LENGTH + wvcdm::KEY_IV_SIZE],
file_size - SHA256_DIGEST_LENGTH - wvcdm::KEY_IV_SIZE,
&aes_key, iv_buffer, AES_DECRYPT);
// Next, read the generation number from a different location.
// On a real implementation, you should NOT put the generation number in
// a file in user space. It should be stored in secure memory. For the
// reference implementation, we'll just pretend this is secure.
std::string filename2 = path + "GenerationNumber.dat";
file = file_system->Open(filename2, wvcdm::FileSystem::kReadOnly);
if (!file) {
LOGE("OldUsageTable: File open failed: %s (clearing table)", path.c_str());
generation_ = 0;
table_.clear();
return;
}
file->Read(reinterpret_cast<char *>(&generation_), sizeof(int64_t));
file->Close();
if (stored_table->generation == generation_ + 1) {
if (LogCategoryEnabled(kLoggingTraceUsageTable)) {
LOGW("OldUsageTable: File is one generation old. Acceptable rollback.");
}
} else if (stored_table->generation == generation_ - 1) {
if (LogCategoryEnabled(kLoggingTraceUsageTable)) {
LOGW("OldUsageTable: File is one generation new. Acceptable rollback.");
}
// This might happen if the generation number was rolled back?
} else if (stored_table->generation != generation_) {
LOGE("OldUsageTable: Rollback detected. Clearing Usage Table. %lx -> %lx",
generation_, stored_table->generation);
table_.clear();
generation_ = 0;
return;
}
// At this point, the stored table looks valid. We can load in all the
// entries.
for (uint64_t i = 0; i < stored_table->count; i++) {
OldUsageTableEntry *entry =
new OldUsageTableEntry(&stored_table->entries[i].entry);
table_[entry->pst_hash()] = entry;
}
if (LogCategoryEnabled(kLoggingTraceUsageTable)) {
LOGI("OldUsageTable: loaded %d entries.", stored_table->count);
}
}
OldUsageTableEntry *OldUsageTable::FindEntry(const std::vector<uint8_t> &pst) {
wvcdm::AutoLock lock(lock_);
return FindEntryLocked(pst);
}
OldUsageTableEntry *OldUsageTable::FindEntryLocked(const std::vector<uint8_t> &pst) {
std::vector<uint8_t> pst_hash;
if (!ComputeHash(pst, pst_hash)) {
LOGE("OldUsageTable: Could not compute hash of pst.");
return NULL;
}
EntryMap::iterator it = table_.find(pst_hash);
if (it == table_.end()) {
return NULL;
}
return it->second;
}
OldUsageTableEntry *OldUsageTable::CreateEntry(const std::vector<uint8_t> &pst) {
std::vector<uint8_t> pst_hash;
if (!ComputeHash(pst, pst_hash)) {
LOGE("OldUsageTable: Could not compute hash of pst.");
return NULL;
}
OldUsageTableEntry *entry = new OldUsageTableEntry(pst_hash);
wvcdm::AutoLock lock(lock_);
table_[pst_hash] = entry;
return entry;
}
void OldUsageTable::Clear() {
wvcdm::AutoLock lock(lock_);
for (EntryMap::iterator i = table_.begin(); i != table_.end(); ++i) {
if (i->second) delete i->second;
}
table_.clear();
}
void OldUsageTable::DeleteFile(CryptoEngine *ce) {
wvcdm::FileSystem *file_system = ce->file_system();
std::string path;
// Note: this path is OK for a real implementation, but using security level 1
// would be better.
if (!wvcdm::Properties::GetDeviceFilesBasePath(wvcdm::kSecurityLevelL3,
&path)) {
LOGE("OldUsageTable: Unable to get base path");
return;
}
std::string filename = path + "UsageTable.dat";
if (file_system->Exists(filename)) {
if (!file_system->Remove(filename)) {
LOGE("DeleteOldUsageTable: error removing file.");
}
}
}
bool OldUsageTable::ComputeHash(const std::vector<uint8_t> &pst,
std::vector<uint8_t> &pst_hash) {
// The PST is not fixed size, and we have no promises that it is reasonbly
// sized, so we compute a hash of it, and store that instead.
pst_hash.resize(SHA256_DIGEST_LENGTH);
SHA256_CTX context;
if (!SHA256_Init(&context)) return false;
if (!SHA256_Update(&context, &pst[0], pst.size())) return false;
if (!SHA256_Final(&pst_hash[0], &context)) return false;
return true;
}
} // namespace wvoec_mock

View File

@@ -0,0 +1,93 @@
// Copyright 2013 Google Inc. All Rights Reserved.
//
// Mock implementation of OEMCrypto APIs
//
// This is from the v12 version of oemcrypto usage tables. It is used for
// devices that upgrade from v12 to v13 in the field, and need to convert from
// the old type of usage table to the new.
#ifndef OEMCRYPTO_OLD_USAGE_TABLE_MOCK_H_
#define OEMCRYPTO_OLD_USAGE_TABLE_MOCK_H_
#include <stdint.h>
#include <map>
#include <string>
#include <vector>
#include "lock.h"
#include "OEMCryptoCENC.h"
#include "openssl/sha.h"
#include "wv_cdm_constants.h"
namespace wvoec_mock {
class CryptoEngine;
class UsagetTableEntry;
struct OldStoredUsageEntry {
// To save disk space, we only store a hash of the pst.
uint8_t pst_hash[SHA256_DIGEST_LENGTH];
int64_t time_of_license_received;
int64_t time_of_first_decrypt;
int64_t time_of_last_decrypt;
enum OEMCrypto_Usage_Entry_Status status;
uint8_t mac_key_server[wvcdm::MAC_KEY_SIZE];
uint8_t mac_key_client[wvcdm::MAC_KEY_SIZE];
};
typedef union {
struct OldStoredUsageEntry entry;
uint8_t padding[128]; // multiple of block size and bigger than entry size.
} AlignedOldStoredUsageEntry;
struct OldStoredUsageTable {
uint8_t signature[SHA256_DIGEST_LENGTH];
uint8_t iv[wvcdm::KEY_IV_SIZE];
int64_t generation;
uint64_t count;
AlignedOldStoredUsageEntry entries[];
};
class OldUsageTableEntry {
public:
OldUsageTableEntry(const std::vector<uint8_t> &pst_hash);
OldUsageTableEntry(const OldStoredUsageEntry *buffer);
~OldUsageTableEntry();
const std::vector<uint8_t> &pst_hash() const { return pst_hash_; }
private:
std::vector<uint8_t> pst_hash_;
int64_t time_of_license_received_;
int64_t time_of_first_decrypt_;
int64_t time_of_last_decrypt_;
enum OEMCrypto_Usage_Entry_Status status_;
std::vector<uint8_t> mac_key_server_;
std::vector<uint8_t> mac_key_client_;
friend class UsageTableEntry;
friend class UsageTable;
};
class OldUsageTable {
public:
OldUsageTable(CryptoEngine *ce);
~OldUsageTable() { Clear(); }
OldUsageTableEntry *FindEntry(const std::vector<uint8_t> &pst);
OldUsageTableEntry *CreateEntry(const std::vector<uint8_t> &pst);
void Clear();
static void DeleteFile(CryptoEngine *ce);
private:
OldUsageTableEntry *FindEntryLocked(const std::vector<uint8_t> &pst);
bool ComputeHash(const std::vector<uint8_t> &pst,
std::vector<uint8_t> &pst_hash);
typedef std::map<std::vector<uint8_t>, OldUsageTableEntry *> EntryMap;
EntryMap table_;
wvcdm::Lock lock_;
int64_t generation_;
CryptoEngine *ce_;
};
} // namespace wvoec_mock
#endif // OEMCRYPTO_OLD_USAGE_TABLE_MOCK_H_

View File

@@ -1015,7 +1015,10 @@ OEMCryptoResult SessionContext::UpdateUsageEntry(uint8_t* header_buffer,
size_t* header_buffer_length,
uint8_t* entry_buffer,
size_t* entry_buffer_length) {
if (!usage_entry_) return OEMCrypto_ERROR_INVALID_CONTEXT;
if (!usage_entry_) {
LOGE("UpdateUsageEntry: Session has no entry.");
return OEMCrypto_ERROR_INVALID_CONTEXT;
}
return ce_->usage_table().UpdateUsageEntry(this, usage_entry_, header_buffer,
header_buffer_length, entry_buffer,
entry_buffer_length);
@@ -1043,7 +1046,7 @@ OEMCryptoResult SessionContext::MoveEntry(uint32_t new_index) {
OEMCryptoResult SessionContext::CopyOldUsageEntry(
const std::vector<uint8_t>& pst) {
if (!usage_entry_) return OEMCrypto_ERROR_INVALID_CONTEXT;
return ce_->usage_table().CopyOldUsageEntry(usage_entry_, pst);
return usage_entry_->CopyOldUsageEntry(pst);
}

View File

@@ -19,11 +19,13 @@
#include "log.h"
#include "oemcrypto_engine_mock.h"
#include "oemcrypto_logging.h"
#include "oemcrypto_old_usage_table_mock.h"
#include "properties.h"
#include "pst_report.h"
#include "string_conversions.h"
#include "wv_cdm_constants.h"
namespace wvoec_mock {
namespace {
const size_t kMagicLength = 8;
const char* kEntryVerification = "USEENTRY";
@@ -31,13 +33,15 @@ const char* kHeaderVerification = "USEHEADR";
// Offset into a signed block where we start encrypting. We need to
// skip the signature and the iv.
const size_t kEncryptionOffset = SHA256_DIGEST_LENGTH + SHA256_DIGEST_LENGTH;
// A structure that holds an usage entry and its signature.
struct SignedEntryBlock {
uint8_t signature[SHA256_DIGEST_LENGTH];
uint8_t iv[SHA256_DIGEST_LENGTH];
uint8_t verification[kMagicLength];
wvoec_mock::StoredUsageEntry data;
StoredUsageEntry data;
};
// This has the data in the header of constant size. There is also an array
// of generation numbers.
struct SignedHeaderBlock {
@@ -50,8 +54,6 @@ struct SignedHeaderBlock {
} // namespace
namespace wvoec_mock {
UsageTableEntry::UsageTableEntry(UsageTable* table, uint32_t index,
int64_t generation)
: usage_table_(table), recent_decrypt_(false), forbid_report_(true) {
@@ -286,6 +288,37 @@ OEMCryptoResult UsageTableEntry::LoadData(CryptoEngine* ce, uint32_t index,
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() != wvcdm::MAC_KEY_SIZE) {
LOGE("CopyOldEntry: Old entry has bad server mac key.");
} else {
memcpy(data_.mac_key_server, &(old_entry->mac_key_server_[0]),
wvcdm::MAC_KEY_SIZE);
}
if (old_entry->mac_key_client_.size() != wvcdm::MAC_KEY_SIZE) {
LOGE("CopyOldEntry: Old entry has bad client mac key.");
} else {
memcpy(data_.mac_key_client, &(old_entry->mac_key_client_[0]),
wvcdm::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[0], wvcdm::MAC_KEY_SIZE);
return OEMCrypto_SUCCESS;
}
size_t UsageTableEntry::SignedEntrySize() {
size_t base = sizeof(SignedEntryBlock);
// round up to make even number of blocks:
@@ -293,6 +326,13 @@ size_t UsageTableEntry::SignedEntrySize() {
return blocks * wvcdm::KEY_IV_SIZE;
}
UsageTable::~UsageTable() {
if (old_table_) {
delete old_table_;
old_table_ = NULL;
}
}
size_t UsageTable::SignedHeaderSize(size_t count) {
size_t base = sizeof(SignedHeaderBlock) + count * sizeof(int64_t);
// round up to make even number of blocks:
@@ -329,7 +369,10 @@ OEMCryptoResult UsageTable::UpdateUsageEntry(SessionContext* session,
OEMCryptoResult UsageTable::CreateNewUsageEntry(SessionContext* session,
UsageTableEntry** entry,
uint32_t* usage_entry_number) {
if (!header_loaded_) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
if (!header_loaded_) {
LOGE("CreateNewUsageEntry: Header not loaded.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (!entry) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
if (!usage_entry_number) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
uint32_t index = generation_numbers_.size();
@@ -347,7 +390,10 @@ OEMCryptoResult UsageTable::LoadUsageEntry(SessionContext* session,
UsageTableEntry** entry,
uint32_t index,
const std::vector<uint8_t>& buffer) {
if (!header_loaded_) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
if (!header_loaded_) {
LOGE("CreateNewUsageEntry: Header not loaded.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
if (!entry) return OEMCrypto_ERROR_UNKNOWN_FAILURE;
if (index >= generation_numbers_.size())
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
@@ -389,6 +435,10 @@ OEMCryptoResult UsageTable::ShrinkUsageTableHeader(
return OEMCrypto_ERROR_SHORT_BUFFER;
}
*header_buffer_length = signed_header_size;
if (!header_buffer) {
LOGE("OEMCrypto_ShrinkUsageTableHeader: buffer null.");
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
}
for (size_t i = new_table_size; i < sessions_.size(); i++) {
if (sessions_[i]) {
LOGE("ShrinkUsageTableHeader: session open for %d", i);
@@ -544,7 +594,7 @@ OEMCryptoResult UsageTable::MoveEntry(UsageTableEntry* entry,
}
if (sessions_[new_index]) {
LOGE("MoveEntry: session open for %d", new_index);
return OEMCrypto_ERROR_INVALID_CONTEXT;
return OEMCrypto_ERROR_INVALID_SESSION;
}
if (!entry) {
LOGE("MoveEntry: null entry");
@@ -636,15 +686,41 @@ OEMCryptoResult UsageTable::CreateUsageTableHeader(
return SaveUsageTableHeader(header_buffer, *header_buffer_length);
}
OEMCryptoResult UsageTable::CopyOldUsageEntry(UsageTableEntry* entry,
const std::vector<uint8_t>& pst) {
// TODO(fredgc): add this.
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
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() {
// TODO(fredgc): add this.
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
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 = time(NULL);
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 + wvcdm::MAC_KEY_SIZE);
old_entry->mac_key_client_.assign(client_mac_key,
client_mac_key + wvcdm::MAC_KEY_SIZE);
return OEMCrypto_SUCCESS;
}
} // namespace wvoec_mock

View File

@@ -21,6 +21,8 @@ namespace wvoec_mock {
class SessionContext;
class CryptoEngine;
class UsageTable;
class OldUsageTable;
class OldUsageTableEntry;
const size_t kMaxPSTLength = 255;
// This is the data we store offline.
@@ -61,6 +63,7 @@ class UsageTableEntry {
uint8_t* signed_buffer, size_t buffer_size);
OEMCryptoResult LoadData(CryptoEngine* ce, uint32_t index,
const std::vector<uint8_t>& buffer);
OEMCryptoResult CopyOldUsageEntry(const std::vector<uint8_t>& pst);
int64_t generation_number() { return data_.generation_number; }
void set_generation_number(int64_t value) { data_.generation_number = value; }
void set_index(int32_t index) { data_.index = index; }
@@ -77,7 +80,9 @@ class UsageTableEntry {
class UsageTable {
public:
UsageTable(CryptoEngine* ce, wvcdm::FileSystem* file_system)
: ce_(ce), file_system_(file_system), header_loaded_(false){};
: ce_(ce), file_system_(file_system), header_loaded_(false),
old_table_(NULL){};
~UsageTable();
OEMCryptoResult CreateNewUsageEntry(SessionContext* session,
UsageTableEntry** entry,
@@ -92,19 +97,25 @@ class UsageTable {
uint8_t* entry_buffer,
size_t* entry_buffer_length);
OEMCryptoResult MoveEntry(UsageTableEntry* entry, uint32_t new_index);
OEMCryptoResult CopyOldUsageEntry(UsageTableEntry* entry,
const std::vector<uint8_t>& pst);
OEMCryptoResult DeleteOldUsageTable();
OEMCryptoResult CreateUsageTableHeader(uint8_t* header_buffer,
size_t* header_buffer_length);
OEMCryptoResult LoadUsageTableHeader(const std::vector<uint8_t>& buffer);
OEMCryptoResult ShrinkUsageTableHeader(uint32_t new_table_size,
uint8_t* header_buffer,
size_t* header_buffer_length);
// Diassociates this entry with it's session.
void ReleaseEntry(uint32_t index) { sessions_[index] = 0; }
void IncrementGeneration();
static size_t SignedHeaderSize(size_t count);
OldUsageTableEntry* FindOldUsageEntry(const std::vector<uint8_t>& pst);
OEMCryptoResult DeleteOldUsageTable();
OEMCryptoResult 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);
private:
OEMCryptoResult SaveUsageTableHeader(uint8_t* signed_buffer,
@@ -118,6 +129,7 @@ class UsageTable {
int64_t master_generation_number_;
std::vector<int64_t> generation_numbers_;
std::vector<SessionContext*> sessions_;
OldUsageTable *old_table_;
};
} // namespace wvoec_mock