[ 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
130 lines
3.9 KiB
C++
130 lines
3.9 KiB
C++
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
|
|
// source code may only be used and distributed under the Widevine Master
|
|
// License Agreement.
|
|
//
|
|
// Reference implementation of OEMCrypto APIs
|
|
//
|
|
#include "oemcrypto_keybox_ref.h"
|
|
|
|
#include <string.h>
|
|
|
|
#include <cstdint>
|
|
#include <string>
|
|
|
|
#include "log.h"
|
|
#include "oemcrypto_types.h"
|
|
#include "platform.h"
|
|
#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;
|
|
|
|
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;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
keybox.reset(new WvKeybox());
|
|
memcpy(reinterpret_cast<uint8_t*>(&keybox->raw_keybox_), keybox_data,
|
|
kKeyboxSize);
|
|
return keybox;
|
|
}
|
|
|
|
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;
|
|
}
|
|
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
|