Restructed reference root of trust (1/3 Keybox)
[ Merge of http://go/wvgerrit/115550 ] This change is the first part of a three part change for restructing the root of trust used by the reference implementation. The API of the AuthenticationRoot class has been updated to reflect the OEMCrypto functions that relate to the root of trust. This involves changing the keybox and DRM Cert methods and adding in new stubs for OEM Certificates. The WvKeybox now uses a RAII-like interface to ensure that keyboxes are provisioned correctly or not at all. Bug: 135283522 Test: oemcrypto_unittests ce_cdm_tests Change-Id: I3f2baf29c1022e1806b6196fa6650d761785c626
This commit is contained in:
@@ -17,58 +17,113 @@
|
||||
#include "wvcrc32.h"
|
||||
|
||||
namespace wvoec_ref {
|
||||
namespace {
|
||||
constexpr size_t kKeyboxSize = 128;
|
||||
constexpr size_t kDeviceIdSize = 32;
|
||||
constexpr size_t kKeyDataSize = 72;
|
||||
constexpr size_t kMagicOffset = 120;
|
||||
const uint8_t kMagic[4] = {'k', 'b', 'o', 'x'};
|
||||
constexpr size_t kCrcKeyboxSize = 124;
|
||||
constexpr size_t kCrcOffset = 124;
|
||||
|
||||
WvKeybox::WvKeybox() : loaded_(false) {
|
||||
static std::string fake_device_id = "device_with_no_keybox";
|
||||
device_id_.assign(fake_device_id.begin(), fake_device_id.end());
|
||||
static_assert(sizeof(wvoec::WidevineKeybox) == kKeyboxSize,
|
||||
"Unexpected keybox size");
|
||||
|
||||
template <size_t N>
|
||||
std::vector<uint8_t> ToVector(const uint8_t (&field)[N]) {
|
||||
return std::vector<uint8_t>(field, &field[N]);
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// static
|
||||
OEMCryptoResult WvKeybox::ValidateData(const uint8_t* keybox,
|
||||
size_t keybox_length) {
|
||||
if (keybox == nullptr) {
|
||||
LOGE("Keybox data buffer is null");
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
if (keybox_length != kKeyboxSize) {
|
||||
LOGE("Invalid keybox length: length = %zu", keybox_length);
|
||||
return OEMCrypto_ERROR_KEYBOX_INVALID;
|
||||
}
|
||||
if (memcmp(&keybox[kMagicOffset], kMagic, sizeof(kMagic))) {
|
||||
LOGE("Invalid keybox magic");
|
||||
return OEMCrypto_ERROR_BAD_MAGIC;
|
||||
}
|
||||
uint32_t crc_provided;
|
||||
memcpy(&crc_provided, &keybox[kCrcOffset], sizeof(crc_provided));
|
||||
const uint32_t crc_computed = wvcrc32n(keybox, kCrcKeyboxSize);
|
||||
if (crc_provided != crc_computed) {
|
||||
LOGE("Invalid keybox CRC: provided = %08x, computed = %08x", crc_provided,
|
||||
crc_computed);
|
||||
return OEMCrypto_ERROR_BAD_CRC;
|
||||
}
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
KeyboxError WvKeybox::Validate() {
|
||||
if (!loaded_) {
|
||||
LOGE("[KEYBOX NOT LOADED]");
|
||||
return OTHER_ERROR;
|
||||
// static
|
||||
std::unique_ptr<WvKeybox> WvKeybox::Create(const uint8_t* keybox_data,
|
||||
size_t keybox_length) {
|
||||
std::unique_ptr<WvKeybox> keybox;
|
||||
if (keybox_length != kKeyboxSize) {
|
||||
LOGE("Invalid keybox length: length = %zu", keybox_length);
|
||||
return keybox;
|
||||
}
|
||||
if (strncmp(reinterpret_cast<char*>(magic_), "kbox", 4) != 0) {
|
||||
LOGE("[KEYBOX HAS BAD MAGIC]");
|
||||
return BAD_MAGIC;
|
||||
}
|
||||
uint32_t crc_computed;
|
||||
uint32_t crc_stored;
|
||||
uint8_t* crc_stored_bytes = (uint8_t*)&crc_stored;
|
||||
memcpy(crc_stored_bytes, crc_, sizeof(crc_));
|
||||
wvoec::WidevineKeybox keybox;
|
||||
memset(&keybox, 0, sizeof(keybox));
|
||||
memcpy(keybox.device_id_, &device_id_[0], device_id_.size());
|
||||
memcpy(keybox.device_key_, &device_key_[0], sizeof(keybox.device_key_));
|
||||
memcpy(keybox.data_, key_data_, sizeof(keybox.data_));
|
||||
memcpy(keybox.magic_, magic_, sizeof(keybox.magic_));
|
||||
|
||||
crc_computed = ntohl(wvcrc32(reinterpret_cast<uint8_t*>(&keybox),
|
||||
sizeof(keybox) - 4)); // Drop last 4 bytes.
|
||||
if (crc_computed != crc_stored) {
|
||||
LOGE("[KEYBOX CRC problem: computed = %08x, stored = %08x]\n",
|
||||
crc_computed, crc_stored);
|
||||
return BAD_CRC;
|
||||
}
|
||||
return NO_ERROR;
|
||||
keybox.reset(new WvKeybox());
|
||||
memcpy(reinterpret_cast<uint8_t*>(&keybox->raw_keybox_), keybox_data,
|
||||
kKeyboxSize);
|
||||
return keybox;
|
||||
}
|
||||
|
||||
bool WvKeybox::InstallKeybox(const uint8_t* buffer, size_t keyBoxLength) {
|
||||
if (keyBoxLength != 128) {
|
||||
return false;
|
||||
OEMCryptoResult WvKeybox::GetDeviceId(uint8_t* device_id,
|
||||
size_t* device_id_length) const {
|
||||
if (device_id_length == nullptr) {
|
||||
LOGE("Output device ID length buffer is null");
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
const wvoec::WidevineKeybox* keybox =
|
||||
reinterpret_cast<const wvoec::WidevineKeybox*>(buffer);
|
||||
size_t device_id_length =
|
||||
strnlen(reinterpret_cast<const char*>(keybox->device_id_), 32);
|
||||
device_id_.assign(keybox->device_id_, keybox->device_id_ + device_id_length);
|
||||
device_key_.assign(keybox->device_key_,
|
||||
keybox->device_key_ + sizeof(keybox->device_key_));
|
||||
memcpy(key_data_, keybox->data_, sizeof(keybox->data_));
|
||||
memcpy(magic_, keybox->magic_, sizeof(keybox->magic_));
|
||||
memcpy(crc_, keybox->crc_, sizeof(keybox->crc_));
|
||||
loaded_ = true;
|
||||
return true;
|
||||
if (device_id == nullptr && *device_id_length > 0) {
|
||||
LOGE("Output device ID buffer is null");
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
if (*device_id_length < kDeviceIdSize) {
|
||||
*device_id_length = kDeviceIdSize;
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
*device_id_length = kDeviceIdSize;
|
||||
memcpy(device_id, raw_keybox_.device_id_, kDeviceIdSize);
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
std::vector<uint8_t> WvKeybox::DeviceId() const {
|
||||
return ToVector(raw_keybox_.device_id_);
|
||||
}
|
||||
|
||||
std::vector<uint8_t> WvKeybox::DeviceKey() const {
|
||||
return ToVector(raw_keybox_.device_key_);
|
||||
}
|
||||
|
||||
OEMCryptoResult WvKeybox::GetKeyData(uint8_t* key_data,
|
||||
size_t* key_data_length) const {
|
||||
if (key_data_length == nullptr) {
|
||||
LOGE("Output key data length buffer is null");
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
if (key_data == nullptr && *key_data_length > 0) {
|
||||
LOGE("Output key data buffer is null");
|
||||
return OEMCrypto_ERROR_INVALID_CONTEXT;
|
||||
}
|
||||
if (*key_data_length < kKeyDataSize) {
|
||||
*key_data_length = kKeyDataSize;
|
||||
return OEMCrypto_ERROR_SHORT_BUFFER;
|
||||
}
|
||||
*key_data_length = kKeyDataSize;
|
||||
memcpy(key_data, raw_keybox_.data_, kKeyDataSize);
|
||||
return OEMCrypto_SUCCESS;
|
||||
}
|
||||
|
||||
OEMCryptoResult WvKeybox::IsKeyboxValid() const {
|
||||
return ValidateData(reinterpret_cast<const uint8_t*>(&raw_keybox_),
|
||||
kKeyboxSize);
|
||||
}
|
||||
|
||||
} // namespace wvoec_ref
|
||||
|
||||
Reference in New Issue
Block a user