Merge OEMCrypto changes from CDM to android repository
This is a merge of the following CLs: Style clean up in oemcrypto/mock https://widevine-internal-review.googlesource.com/#/c/10660 Split off default keybox. https://widevine-internal-review.googlesource.com/#/c/10661/ Split off several properties from CryptoEngine. https://widevine-internal-review.googlesource.com/#/c/10662/ Split off Keybox installation. https://widevine-internal-review.googlesource.com/#/c/10680/ Wii-U build compatibility fixes. https://widevine-internal-review.googlesource.com/#/c/10720/ Fix style issues in oemcrypto_logging_test. https://widevine-internal-review.googlesource.com/#/c/10824/ Correct OEMCrypto error codes in the mock. https://widevine-internal-review.googlesource.com/#/c/10821/ Enable logging during OEMCrypto unit tests. https://widevine-internal-review.googlesource.com/#/c/10833/ Wait to create usage table path until needed. https://widevine-internal-review.googlesource.com/#/c/10831/ Allow keybox installation to be unimplemented. https://widevine-internal-review.googlesource.com/#/c/10850/ Minor clean up in the OEMCrypto header. https://widevine-internal-review.googlesource.com/#/c/10921/ Add usage table device property to the mock oemcrypto https://widevine-internal-review.googlesource.com/#/c/11092/ Change-Id: I02a818a620bcd4bd2291f1b3c0ac9308ae444319
This commit is contained in:
@@ -0,0 +1,36 @@
|
||||
// Copyright 2014 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Mock implementation of OEMCrypto APIs
|
||||
//
|
||||
#include "oemcrypto_engine_mock.h"
|
||||
|
||||
namespace wvoec_mock {
|
||||
|
||||
// If local_display() returns true, we pretend we are using a built-in display,
|
||||
// instead of HDMI or WiFi output.
|
||||
bool CryptoEngine::local_display() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// A closed platform is permitted to use clear buffers.
|
||||
bool CryptoEngine::closed_platform() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns the HDCP version currently in use.
|
||||
OEMCrypto_HDCP_Capability CryptoEngine::current_hdcp_capability() {
|
||||
return local_display() ? 0xFF : 0x01;
|
||||
}
|
||||
|
||||
// Returns the max HDCP version supported.
|
||||
OEMCrypto_HDCP_Capability CryptoEngine::maximum_hdcp_capability() {
|
||||
return 0x02;
|
||||
}
|
||||
|
||||
// Returns true if the client supports persistent storage of
|
||||
// offline usage table information.
|
||||
bool CryptoEngine::supports_storage() {
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace wvoec_mock
|
||||
@@ -343,14 +343,15 @@ bool SessionContext::CheckNonceOrEntry(const KeyControlBlock& key_control_block,
|
||||
const std::vector<uint8_t>& pst) {
|
||||
switch (key_control_block.control_bits() & kControlReplayMask) {
|
||||
case kControlNonceRequired: // Online license. Nonce always required.
|
||||
if (!CheckNonce(key_control_block.nonce())) return false;
|
||||
if (pst.size() == 0) {
|
||||
LOGE("KCB: PST null for kControlNonceRequired.");
|
||||
return false;
|
||||
}
|
||||
if (!(key_control_block.control_bits() & kControlNonceEnabled)) {
|
||||
LOGE("KCB: Server provided Nonce_Required but Nonce_Enabled = 0.");
|
||||
// Server error. Continue, and assume nonce required.
|
||||
}
|
||||
if (!CheckNonce(key_control_block.nonce())) return false;
|
||||
if (!usage_entry_) {
|
||||
if (ce_->usage_table()->FindEntry(pst)) {
|
||||
LOGE("KCB: Cannot create duplicate entries in usage table.");
|
||||
@@ -362,6 +363,7 @@ bool SessionContext::CheckNonceOrEntry(const KeyControlBlock& key_control_block,
|
||||
case kControlNonceOrEntry:
|
||||
if (key_control_block.control_bits() & kControlNonceEnabled) {
|
||||
LOGE("KCB: Server provided NonceOrEntry but Nonce_Enabled = 1.");
|
||||
// Server error. Continue, and assume nonce required.
|
||||
}
|
||||
if (pst.size() == 0) {
|
||||
LOGE("KCB: PST null for kControlNonceOrEntry.");
|
||||
@@ -773,8 +775,10 @@ OEMCryptoResult SessionContext::Generic_Decrypt(const uint8_t* in_buffer,
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
if (control.control_bits() & kControlDataPathSecure) {
|
||||
LOGE("[Generic_Decrypt(): control bit says secure path only.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
if (!ce_->closed_platform()) {
|
||||
LOGE("[Generic_Decrypt(): control bit says secure path only.");
|
||||
return OEMCrypto_ERROR_UNKNOWN_FAILURE;
|
||||
}
|
||||
}
|
||||
if (control.duration() > 0) {
|
||||
if (control.duration() < CurrentTimer()) {
|
||||
@@ -966,17 +970,9 @@ bool SessionContext::IsUsageEntryValid() {
|
||||
|
||||
void SessionContext::ReleaseUsageEntry() { usage_entry_ = NULL; }
|
||||
|
||||
CryptoEngine::CryptoEngine() :
|
||||
ce_state_(CE_INITIALIZED), current_session_(NULL) {
|
||||
valid_ = true;
|
||||
CryptoEngine::CryptoEngine()
|
||||
: current_session_(NULL), usage_table_(new UsageTable(this)) {
|
||||
ERR_load_crypto_strings();
|
||||
// These are made up numbers, just for illustration.
|
||||
current_hdcp_capability_ = 0x1;
|
||||
maximum_hdcp_capability_ = 0x2;
|
||||
// If local_display_ is true, we pretend we are using a built-in display,
|
||||
// instead of HDMI or WiFi output.
|
||||
local_display_ = false;
|
||||
usage_table_ = new UsageTable(this);
|
||||
}
|
||||
|
||||
CryptoEngine::~CryptoEngine() {
|
||||
@@ -1061,7 +1057,7 @@ OEMCryptoResult SessionContext::DecryptCTR(
|
||||
}
|
||||
const KeyControlBlock& control = current_content_key()->control();
|
||||
if (control.control_bits() & kControlDataPathSecure) {
|
||||
if (buffer_type == kBufferTypeClear) {
|
||||
if (!ce_->closed_platform() && buffer_type == kBufferTypeClear) {
|
||||
LOGE("[DecryptCTR(): Secure key with insecure buffer]");
|
||||
return OEMCrypto_ERROR_DECRYPT_FAILED;
|
||||
}
|
||||
@@ -1198,4 +1194,4 @@ void NonceTable::Flush() {
|
||||
}
|
||||
}
|
||||
|
||||
}; // namespace wvoec_mock
|
||||
} // namespace wvoec_mock
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
//
|
||||
// Mock implementation of OEMCrypto APIs
|
||||
//
|
||||
#ifndef WVOEC_MOCK_OEMCRYPTO_ENGINE_MOCK_H_
|
||||
#define WVOEC_MOCK_OEMCRYPTO_ENGINE_MOCK_H_
|
||||
#ifndef OEMCRYPTO_ENGINE_MOCK_H_
|
||||
#define OEMCRYPTO_ENGINE_MOCK_H_
|
||||
|
||||
#include <openssl/rsa.h>
|
||||
#include <stdint.h>
|
||||
@@ -220,26 +220,14 @@ class SessionContext {
|
||||
};
|
||||
|
||||
class CryptoEngine {
|
||||
|
||||
private:
|
||||
enum CryptoEngineState {
|
||||
CE_ILLEGAL,
|
||||
CE_INITIALIZED,
|
||||
CE_HAS_KEYBOX,
|
||||
CE_HAS_SESSIONS,
|
||||
CE_ERROR
|
||||
};
|
||||
|
||||
public:
|
||||
CryptoEngine();
|
||||
~CryptoEngine();
|
||||
|
||||
bool Initialized() { return (ce_state_ != CE_ILLEGAL); }
|
||||
bool Initialized() { return true; }
|
||||
|
||||
void Terminate();
|
||||
|
||||
bool isValid() { return valid_; }
|
||||
|
||||
KeyboxError ValidateKeybox();
|
||||
WvKeybox& keybox() { return keybox_; }
|
||||
|
||||
@@ -253,32 +241,24 @@ class CryptoEngine {
|
||||
current_session_ = current;
|
||||
}
|
||||
|
||||
OEMCrypto_HDCP_Capability current_hdcp_capability() const {
|
||||
return local_display_ ? 0xFF : current_hdcp_capability_;
|
||||
}
|
||||
|
||||
OEMCrypto_HDCP_Capability maximum_hdcp_capability() const {
|
||||
return maximum_hdcp_capability_;
|
||||
}
|
||||
OEMCrypto_HDCP_Capability current_hdcp_capability();
|
||||
OEMCrypto_HDCP_Capability maximum_hdcp_capability();
|
||||
|
||||
UsageTable* usage_table() { return usage_table_; }
|
||||
bool local_display() { return local_display_; }
|
||||
bool local_display();
|
||||
bool closed_platform();
|
||||
bool supports_storage();
|
||||
|
||||
private:
|
||||
bool valid_;
|
||||
CryptoEngineState ce_state_;
|
||||
SessionContext* current_session_;
|
||||
ActiveSessions sessions_;
|
||||
WvKeybox keybox_;
|
||||
wvcdm::Lock session_table_lock_;
|
||||
OEMCrypto_HDCP_Capability current_hdcp_capability_;
|
||||
OEMCrypto_HDCP_Capability maximum_hdcp_capability_;
|
||||
bool local_display_;
|
||||
UsageTable* usage_table_;
|
||||
|
||||
CORE_DISALLOW_COPY_AND_ASSIGN(CryptoEngine);
|
||||
};
|
||||
|
||||
}; // namespace wvoec_eng
|
||||
} // namespace wvoec_mock
|
||||
|
||||
#endif // WVOEC_MOCK_OEMCRYPTO_ENGINE_MOCK_H_
|
||||
#endif // OEMCRYPTO_ENGINE_MOCK_H_
|
||||
|
||||
@@ -107,4 +107,4 @@ void Key::UpdateDuration(const KeyControlBlock& control) {
|
||||
control_.set_duration(control.duration());
|
||||
}
|
||||
|
||||
}; // namespace wvoec_mock
|
||||
} // namespace wvoec_mock
|
||||
|
||||
@@ -72,6 +72,6 @@ class Key {
|
||||
KeyControlBlock control_;
|
||||
};
|
||||
|
||||
}; // namespace wvoec_eng
|
||||
} // namespace wvoec_mock
|
||||
|
||||
#endif
|
||||
#endif // OEMCRYPTO_KEY_MOCK_H_
|
||||
|
||||
@@ -14,47 +14,8 @@
|
||||
|
||||
namespace wvoec_mock {
|
||||
|
||||
const WidevineKeybox kDefaultKeybox = {
|
||||
// Sample keybox used for test vectors
|
||||
{
|
||||
// deviceID
|
||||
0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x30, // TestKey01
|
||||
0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
}, {
|
||||
// key
|
||||
0xfb, 0xda, 0x04, 0x89, 0xa1, 0x58, 0x16, 0x0e,
|
||||
0xa4, 0x02, 0xe9, 0x29, 0xe3, 0xb6, 0x8f, 0x04,
|
||||
}, {
|
||||
// data
|
||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x19,
|
||||
0x07, 0xd9, 0xff, 0xde, 0x13, 0xaa, 0x95, 0xc1,
|
||||
0x22, 0x67, 0x80, 0x53, 0x36, 0x21, 0x36, 0xbd,
|
||||
0xf8, 0x40, 0x8f, 0x82, 0x76, 0xe4, 0xc2, 0xd8,
|
||||
0x7e, 0xc5, 0x2b, 0x61, 0xaa, 0x1b, 0x9f, 0x64,
|
||||
0x6e, 0x58, 0x73, 0x49, 0x30, 0xac, 0xeb, 0xe8,
|
||||
0x99, 0xb3, 0xe4, 0x64, 0x18, 0x9a, 0x14, 0xa8,
|
||||
0x72, 0x02, 0xfb, 0x02, 0x57, 0x4e, 0x70, 0x64,
|
||||
0x0b, 0xd2, 0x2e, 0xf4, 0x4b, 0x2d, 0x7e, 0x39,
|
||||
}, {
|
||||
// magic
|
||||
0x6b, 0x62, 0x6f, 0x78,
|
||||
}, {
|
||||
// Crc
|
||||
0x0a, 0x7a, 0x2c, 0x35,
|
||||
}
|
||||
};
|
||||
|
||||
WvKeybox::WvKeybox() : valid_(false) {
|
||||
Prepare();
|
||||
}
|
||||
|
||||
bool WvKeybox::Prepare() {
|
||||
InstallKeybox(reinterpret_cast<const uint8_t*>(&kDefaultKeybox),
|
||||
sizeof(kDefaultKeybox));
|
||||
valid_ = true;
|
||||
return valid_;
|
||||
WvKeybox::WvKeybox() {
|
||||
valid_ = Prepare();
|
||||
}
|
||||
|
||||
KeyboxError WvKeybox::Validate() {
|
||||
@@ -101,7 +62,8 @@ bool WvKeybox::InstallKeybox(const uint8_t* buffer, size_t keyBoxLength) {
|
||||
memcpy(key_data_, keybox->data_, sizeof(keybox->data_));
|
||||
memcpy(magic_, keybox->magic_, sizeof(keybox->magic_));
|
||||
memcpy(crc_, keybox->crc_, sizeof(keybox->crc_));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}; // namespace wvoec_mock
|
||||
} // namespace wvoec_mock
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
//
|
||||
// Mock implementation of OEMCrypto APIs
|
||||
//
|
||||
#ifndef WVOEC_MOCK_OEMCRYPTO_KEYBOX_MOCK_H_
|
||||
#define WVOEC_MOCK_OEMCRYPTO_KEYBOX_MOCK_H_
|
||||
#ifndef OEMCRYPTO_KEYBOX_MOCK_H_
|
||||
#define OEMCRYPTO_KEYBOX_MOCK_H_
|
||||
|
||||
#include "oemcrypto_key_mock.h"
|
||||
|
||||
@@ -41,6 +41,6 @@ class WvKeybox {
|
||||
uint8_t crc_[4];
|
||||
};
|
||||
|
||||
}; // namespace wvoec_eng
|
||||
} // namespace wvoec_mock
|
||||
|
||||
#endif // WVOEC_MOCK_OEMCRYPTO_KEYBOX_MOCK_H_
|
||||
#endif // OEMCRYPTO_KEYBOX_MOCK_H_
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright 2014 Google Inc. All Rights Reserved.
|
||||
//
|
||||
// Test keybox.
|
||||
|
||||
#include "oemcrypto_keybox_mock.h"
|
||||
#include "wv_keybox.h"
|
||||
|
||||
namespace wvoec_mock {
|
||||
|
||||
namespace {
|
||||
|
||||
const WidevineKeybox kKeybox = {
|
||||
// Sample keybox used for test vectors
|
||||
{
|
||||
// deviceID
|
||||
0x54, 0x65, 0x73, 0x74, 0x4b, 0x65, 0x79, 0x30, // TestKey01
|
||||
0x31, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // ........
|
||||
}, {
|
||||
// key
|
||||
0xfb, 0xda, 0x04, 0x89, 0xa1, 0x58, 0x16, 0x0e,
|
||||
0xa4, 0x02, 0xe9, 0x29, 0xe3, 0xb6, 0x8f, 0x04,
|
||||
}, {
|
||||
// data
|
||||
0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x10, 0x19,
|
||||
0x07, 0xd9, 0xff, 0xde, 0x13, 0xaa, 0x95, 0xc1,
|
||||
0x22, 0x67, 0x80, 0x53, 0x36, 0x21, 0x36, 0xbd,
|
||||
0xf8, 0x40, 0x8f, 0x82, 0x76, 0xe4, 0xc2, 0xd8,
|
||||
0x7e, 0xc5, 0x2b, 0x61, 0xaa, 0x1b, 0x9f, 0x64,
|
||||
0x6e, 0x58, 0x73, 0x49, 0x30, 0xac, 0xeb, 0xe8,
|
||||
0x99, 0xb3, 0xe4, 0x64, 0x18, 0x9a, 0x14, 0xa8,
|
||||
0x72, 0x02, 0xfb, 0x02, 0x57, 0x4e, 0x70, 0x64,
|
||||
0x0b, 0xd2, 0x2e, 0xf4, 0x4b, 0x2d, 0x7e, 0x39,
|
||||
}, {
|
||||
// magic
|
||||
0x6b, 0x62, 0x6f, 0x78,
|
||||
}, {
|
||||
// Crc
|
||||
0x0a, 0x7a, 0x2c, 0x35,
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
bool WvKeybox::Prepare() {
|
||||
InstallKeybox(reinterpret_cast<const uint8_t*>(&kKeybox),
|
||||
sizeof(kKeybox));
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace wvoec_mock
|
||||
@@ -105,5 +105,4 @@ void dump_array_part(std::string array, size_t index,
|
||||
LOGV(buffer.c_str());
|
||||
}
|
||||
|
||||
} // namespace wvoec_mock
|
||||
|
||||
} // namespace wvoec_mock
|
||||
|
||||
@@ -320,7 +320,7 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session,
|
||||
|
||||
// Later on, we use pst_length to verify the the pst is valid. This makes
|
||||
// sure that we aren't given a null string but told it has postiive length.
|
||||
if ((pst == NULL && pst_length > 0) || (pst != NULL && pst_length == 0)) {
|
||||
if (pst == NULL && pst_length > 0) {
|
||||
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_ONCTEXT - null pst.]");
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
@@ -346,8 +346,8 @@ OEMCryptoResult OEMCrypto_LoadKeys(OEMCrypto_SESSION session,
|
||||
wvcdm::KEY_CONTROL_SIZE, false) ||
|
||||
!RangeCheck(message, message_length, key_array[i].key_control_iv,
|
||||
wvcdm::KEY_IV_SIZE, false)) {
|
||||
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_SIGNATURE_FAILURE -range check %d]", i);
|
||||
return OEMCrypto_ERROR_SIGNATURE_FAILURE;
|
||||
LOGE("[OEMCrypto_LoadKeys(): OEMCrypto_ERROR_INVALID_CONTEXT -range check %d]", i);
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -397,7 +397,7 @@ OEMCryptoResult OEMCrypto_RefreshKeys(
|
||||
!RangeCheck(message, message_length, key_array[i].key_control_iv,
|
||||
wvcdm::KEY_IV_SIZE, true)) {
|
||||
LOGE("[OEMCrypto_RefreshKeys(): Range Check %d]", i);
|
||||
return OEMCrypto_ERROR_SIGNATURE_FAILURE;
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -721,7 +721,7 @@ OEMCryptoResult OEMCrypto_RewrapDeviceRSAKey(OEMCrypto_SESSION session,
|
||||
!RangeCheck(message, message_length, enc_rsa_key_iv, wvcdm::KEY_IV_SIZE,
|
||||
true)) {
|
||||
LOGE("[OEMCrypto_RewrapDeviceRSAKey(): - range check.]");
|
||||
return OEMCrypto_ERROR_SIGNATURE_FAILURE;
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
|
||||
// Validate nonce
|
||||
@@ -1175,11 +1175,14 @@ OEMCryptoResult OEMCrypto_Generic_Verify(OEMCrypto_SESSION session,
|
||||
|
||||
extern "C"
|
||||
bool OEMCrypto_SupportsUsageTable() {
|
||||
bool supports_usage = crypto_engine->supports_storage();
|
||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||
LOGI("-- bool OEMCrypto_SupportsUsageTable(); // returns true.\n");
|
||||
LOGI("-- bool OEMCrypto_SupportsUsageTable(); // returns %s.\n",
|
||||
(supports_usage ? "true" : "false"));
|
||||
}
|
||||
return true;
|
||||
return supports_usage;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
OEMCryptoResult OEMCrypto_UpdateUsageTable() {
|
||||
if (LogCategoryEnabled(kLoggingTraceOEMCryptoCalls)) {
|
||||
@@ -1264,7 +1267,7 @@ OEMCryptoResult OEMCrypto_DeleteUsageEntry(OEMCrypto_SESSION session,
|
||||
}
|
||||
if (!RangeCheck(message, message_length, pst, pst_length, false)) {
|
||||
LOGE("[OEMCrypto_DeleteUsageEntry(): range check.]");
|
||||
return OEMCrypto_ERROR_SIGNATURE_FAILURE;
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
// Validate message signature
|
||||
if (!session_ctx->ValidateMessage(message, message_length, signature,
|
||||
@@ -1288,4 +1291,4 @@ OEMCryptoResult OEMCrypto_DeleteUsageTable() {
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
}; // namespace wvoec_mock
|
||||
} // namespace wvoec_mock
|
||||
|
||||
@@ -153,12 +153,6 @@ UsageTable::UsageTable(CryptoEngine *ce) {
|
||||
LOGE("UsageTable: Unable to get base path");
|
||||
return;
|
||||
}
|
||||
if (!file.IsDirectory(path)) {
|
||||
if (!file.CreateDirectory(path)) {
|
||||
LOGE("UsageTable: could not create directory: %s", path.c_str());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
std::string filename = path + "UsageTable.dat";
|
||||
if (!file.Exists(filename)) {
|
||||
@@ -167,26 +161,28 @@ UsageTable::UsageTable(CryptoEngine *ce) {
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
size_t file_size = file.FileSize(filename);
|
||||
uint8_t encrypted_buffer[file_size];
|
||||
uint8_t buffer[file_size];
|
||||
StoredUsageTable *stored_table = reinterpret_cast<StoredUsageTable *>(buffer);
|
||||
std::vector<uint8_t> encrypted_buffer(file_size);
|
||||
std::vector<uint8_t> buffer(file_size);
|
||||
StoredUsageTable *stored_table =
|
||||
reinterpret_cast<StoredUsageTable *>(&buffer[0]);
|
||||
StoredUsageTable *encrypted_table =
|
||||
reinterpret_cast<StoredUsageTable *>(encrypted_buffer);
|
||||
reinterpret_cast<StoredUsageTable *>(&encrypted_buffer[0]);
|
||||
|
||||
if (!file.Open(filename, wvcdm::File::kReadOnly | wvcdm::File::kBinary)) {
|
||||
LOGE("UsageTable: File open failed: %s", path.c_str());
|
||||
return;
|
||||
}
|
||||
file.Read(reinterpret_cast<char *>(encrypted_buffer), file_size);
|
||||
file.Read(reinterpret_cast<char *>(&encrypted_buffer[0]), file_size);
|
||||
file.Close();
|
||||
|
||||
// First, verify the signature of the usage table file.
|
||||
std::vector<uint8_t> &key = ce_->keybox().device_key();
|
||||
unsigned int sig_length = sizeof(stored_table->signature);
|
||||
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,
|
||||
&encrypted_buffer[SHA256_DIGEST_LENGTH],
|
||||
file_size - SHA256_DIGEST_LENGTH, computed_signature,
|
||||
&sig_length)) {
|
||||
LOGE("UsageTable: Could not recreate signature.");
|
||||
@@ -195,7 +191,7 @@ UsageTable::UsageTable(CryptoEngine *ce) {
|
||||
}
|
||||
if (memcmp(encrypted_table->signature, computed_signature, sig_length)) {
|
||||
LOGE("UsageTable: Invalid signature given: %s",
|
||||
wvcdm::HexEncode(encrypted_buffer, sig_length).c_str());
|
||||
wvcdm::HexEncode(&encrypted_buffer[0], sig_length).c_str());
|
||||
LOGE("UsageTable: Invalid signature computed: %s",
|
||||
wvcdm::HexEncode(computed_signature, sig_length).c_str());
|
||||
table_.clear();
|
||||
@@ -203,13 +199,12 @@ UsageTable::UsageTable(CryptoEngine *ce) {
|
||||
}
|
||||
|
||||
// Next, decrypt the table.
|
||||
memset(buffer, 0, file_size);
|
||||
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,
|
||||
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);
|
||||
|
||||
@@ -263,12 +258,12 @@ bool UsageTable::SaveToFile() {
|
||||
// Now save data to the file as seen in the constructor, above.
|
||||
size_t file_size = sizeof(StoredUsageTable) +
|
||||
table_.size() * sizeof(AlignedStoredUsageEntry);
|
||||
uint8_t buffer[file_size];
|
||||
uint8_t encrypted_buffer[file_size];
|
||||
StoredUsageTable *stored_table = reinterpret_cast<StoredUsageTable *>(buffer);
|
||||
std::vector<uint8_t> buffer(file_size);
|
||||
std::vector<uint8_t> encrypted_buffer(file_size);
|
||||
StoredUsageTable *stored_table =
|
||||
reinterpret_cast<StoredUsageTable *>(&buffer[0]);
|
||||
StoredUsageTable *encrypted_table =
|
||||
reinterpret_cast<StoredUsageTable *>(encrypted_buffer);
|
||||
memset(buffer, 0, file_size);
|
||||
reinterpret_cast<StoredUsageTable *>(&encrypted_buffer[0]);
|
||||
stored_table->generation = generation_;
|
||||
stored_table->count = 0;
|
||||
for (EntryMap::iterator i = table_.begin(); i != table_.end(); ++i) {
|
||||
@@ -287,15 +282,15 @@ bool UsageTable::SaveToFile() {
|
||||
memcpy(iv_buffer, encrypted_table->iv, wvcdm::KEY_IV_SIZE);
|
||||
AES_KEY aes_key;
|
||||
AES_set_encrypt_key(&key[0], 128, &aes_key);
|
||||
AES_cbc_encrypt(buffer + SHA256_DIGEST_LENGTH + wvcdm::KEY_IV_SIZE,
|
||||
encrypted_buffer + SHA256_DIGEST_LENGTH + wvcdm::KEY_IV_SIZE,
|
||||
AES_cbc_encrypt(&buffer[SHA256_DIGEST_LENGTH + wvcdm::KEY_IV_SIZE],
|
||||
&encrypted_buffer[SHA256_DIGEST_LENGTH + wvcdm::KEY_IV_SIZE],
|
||||
file_size - SHA256_DIGEST_LENGTH - wvcdm::KEY_IV_SIZE,
|
||||
&aes_key, iv_buffer, AES_ENCRYPT);
|
||||
|
||||
// Sign the table.
|
||||
unsigned int sig_length = sizeof(stored_table->signature);
|
||||
if (!HMAC(EVP_sha256(), &key[0], key.size(),
|
||||
encrypted_buffer + SHA256_DIGEST_LENGTH,
|
||||
&encrypted_buffer[SHA256_DIGEST_LENGTH],
|
||||
file_size - SHA256_DIGEST_LENGTH, encrypted_table->signature,
|
||||
&sig_length)) {
|
||||
LOGE("UsageTable: Could not sign table.");
|
||||
@@ -330,7 +325,7 @@ bool UsageTable::SaveToFile() {
|
||||
LOGE("UsageTable: Could not save usage table: %s", path.c_str());
|
||||
return false;
|
||||
}
|
||||
file.Write(reinterpret_cast<char *>(encrypted_buffer), file_size);
|
||||
file.Write(reinterpret_cast<char *>(&encrypted_buffer[0]), file_size);
|
||||
file.Close();
|
||||
|
||||
// On a real implementation, you should NOT put the generation number in
|
||||
@@ -425,4 +420,5 @@ bool UsageTable::ComputeHash(const std::vector<uint8_t> &pst,
|
||||
if (!SHA256_Final(&pst_hash[0], &context)) return false;
|
||||
return true;
|
||||
}
|
||||
}; // namespace wvoec_mock
|
||||
|
||||
} // namespace wvoec_mock
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
//
|
||||
// Mock implementation of OEMCrypto APIs
|
||||
//
|
||||
#ifndef WVOEC_MOCK_OEMCRYPTO_USAGE_TABLE_MOCK_H_
|
||||
#define WVOEC_MOCK_OEMCRYPTO_USAGE_TABLE_MOCK_H_
|
||||
#ifndef OEMCRYPTO_USAGE_TABLE_MOCK_H_
|
||||
#define OEMCRYPTO_USAGE_TABLE_MOCK_H_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <map>
|
||||
@@ -101,6 +101,6 @@ class UsageTable {
|
||||
CryptoEngine *ce_;
|
||||
};
|
||||
|
||||
}; // namespace wvoec_mock
|
||||
} // namespace wvoec_mock
|
||||
|
||||
#endif // WVOEC_MOCK_OEMCRYPTO_USAGE_TABLE_MOCK_H_
|
||||
#endif // OEMCRYPTO_USAGE_TABLE_MOCK_H_
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
// Copyright 2013 Google Inc. All Rights Reserved.
|
||||
|
||||
#ifndef WVOEC_MOCK_WV_KEYBOX_H_
|
||||
#define WVOEC_MOCK_WV_KEYBOX_H_
|
||||
#ifndef WV_KEYBOX_H_
|
||||
#define WV_KEYBOX_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
namespace wvoec_mock {
|
||||
|
||||
@@ -19,6 +21,6 @@ typedef struct { // 128 bytes total.
|
||||
uint8_t crc_[4];
|
||||
} WidevineKeybox;
|
||||
|
||||
}
|
||||
} // namespace wvoec_mock
|
||||
|
||||
#endif // WVOEC_MOCK_WV_KEYBOX_H_
|
||||
#endif // WV_KEYBOX_H_
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
//
|
||||
// Compute CRC32 Checksum. Needed for verification of WV Keybox.
|
||||
//
|
||||
#ifndef WVOEC_MOCK_WVCRC32_H_
|
||||
#define WVOEC_MOCK_WVCRC32_H_
|
||||
#ifndef WVCRC32_H_
|
||||
#define WVCRC32_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
@@ -12,4 +12,4 @@ uint32_t wvcrc32(const uint8_t* p_begin, int i_count);
|
||||
// Convert to network byte order
|
||||
uint32_t wvcrc32n(const uint8_t* p_begin, int i_count);
|
||||
|
||||
#endif // WVOEC_MOCK_WVCRC32_H_
|
||||
#endif // WVCRC32_H_
|
||||
|
||||
Reference in New Issue
Block a user