From ad0d66c7e6a55ea9e4a5db57971e4985f86280dd Mon Sep 17 00:00:00 2001 From: Alex Dale Date: Wed, 2 Jun 2021 19:59:55 +0000 Subject: [PATCH] [DO NOT MERGE] Revert "Restructed reference root of trust (1/3 Keybox)" This reverts commit e4ee4eb40471c61a956b0f40d14d9d19ea5f97a2. Reason for revert: Feature missed deadline Bug: 135283522 Change-Id: I4ee2caac2dadfcc3e145b9c9b977d216d4edd929 --- .../oemcrypto/ref/src/oemcrypto_auth_ref.cpp | 250 ++---------------- .../oemcrypto/ref/src/oemcrypto_auth_ref.h | 148 +++-------- .../ref/src/oemcrypto_engine_ref.cpp | 6 +- .../oemcrypto/ref/src/oemcrypto_engine_ref.h | 31 +-- .../ref/src/oemcrypto_keybox_ref.cpp | 145 ++++------ .../oemcrypto/ref/src/oemcrypto_keybox_ref.h | 66 ++--- .../oemcrypto/ref/src/oemcrypto_ref.cpp | 75 +++++- .../oemcrypto/ref/src/oemcrypto_session.cpp | 2 +- 8 files changed, 199 insertions(+), 524 deletions(-) diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp index 8697860f..f3d9a451 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.cpp @@ -6,20 +6,14 @@ // #include "oemcrypto_auth_ref.h" -#include - -#include #include #include "keys.h" #include "log.h" +#include "oemcrypto_rsa_key_shared.h" -namespace wvoec_ref { namespace { -// Fake device ID which is to be returned inplace of a real ID. -const std::string kFakeDeviceId = "device_with_no_keybox"; - // A 2048 bit RSA key in PKCS#8 PrivateKeyInfo format // This is the RSA Test Key. This key is not derived // from any Widevine authentication root. @@ -178,240 +172,32 @@ static const uint8_t kTestRSAPKCS8PrivateKeyInfo2_2048[] = { 0x56, 0xfe, 0x39, 0x28, 0x33, 0xe0, 0xdb, 0x03 }; -// Filler for returning vector references. -const std::vector kEmptyVector; } // namespace -bool AuthenticationRoot::Initialize(OEMCrypto_ProvisioningMethod method) { - if (prov_method_ != OEMCrypto_ProvisioningError) { - // If provisioning method is something other than ProvisioningError - // indicates it has already been initialized before. Must - // existing data. - rsa_key_set_ = false; - rsa_key_.reset(); - test_rsa_key_.reset(); - keybox_.reset(); - test_keybox_.reset(); - } - prov_method_ = method; - switch (method) { - case OEMCrypto_DrmCertificate: { - rsa_key_set_ = rsa_key_.LoadPkcs8RsaKey(kPrivateKey, kPrivateKeySize); - if (!rsa_key_set_) { - // This error message is OK in unit tests which use test certificate. - LOGE( - "FATAL ERROR: Platform uses a baked-in certificate instead of a " - "keybox, but the certificate could not be loaded."); - } - return true; - } - case OEMCrypto_Keybox: - case OEMCrypto_OEMCertificate: - // Nothing to do yet. - return true; - case OEMCrypto_ProvisioningError: - default: { - LOGE("Invalid provisioning method: method = %d", - static_cast(method)); - prov_method_ = OEMCrypto_ProvisioningError; - return false; - } +namespace wvoec_ref { + +AuthenticationRoot::AuthenticationRoot(OEMCrypto_ProvisioningMethod method) : + provisioning_method_(method), + use_test_keybox_(false) { + if ((provisioning_method_ == OEMCrypto_DrmCertificate) && + !rsa_key_.LoadPkcs8RsaKey(kPrivateKey, kPrivateKeySize)) { + // This error message is OK in unit tests which use test certificate. + LOGE("FATAL ERROR: Platform uses a baked-in certificate instead of a " + "keybox, but the certificate could not be loaded."); } } -bool AuthenticationRoot::IsValid() const { - switch (prov_method_) { - case OEMCrypto_DrmCertificate: { - return rsa_key_set_ && HasDeviceKey(); - } - case OEMCrypto_Keybox: { - return HasDeviceKey(); - } - case OEMCrypto_OEMCertificate: { - // TODO(sigquit): Add OEM Certificate validation. - return true; - } - default: { - LOGE("Root of trust is not properly initialized"); - return false; - } - } +KeyboxError AuthenticationRoot::ValidateKeybox() { + return keybox().Validate(); } -OEMCryptoResult AuthenticationRoot::IsKeyboxOrOemCertValid() const { - switch (prov_method_) { - case OEMCrypto_Keybox: { - WvKeybox* kb = keybox(); - if (kb == nullptr) { - LOGW("Null keybox cannot be validated"); - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - return kb->IsKeyboxValid(); - } - case OEMCrypto_OEMCertificate: { - LOGW("OEM certificate validation is not implemented"); - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - case OEMCrypto_DrmCertificate: { - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - default: - LOGE("Root of trust is not properly initialized"); - return OEMCrypto_ERROR_SYSTEM_INVALIDATED; - } +bool AuthenticationRoot::LoadTestRsaKey() { + return rsa_key_.LoadPkcs8RsaKey(kTestRSAPKCS8PrivateKeyInfo2_2048, + sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048)); } -OEMCryptoResult AuthenticationRoot::GetDeviceId( - uint8_t* device_id, size_t* device_id_length) const { - WvKeybox* kb = keybox(); - if (kb != nullptr) { - return kb->GetDeviceId(device_id, device_id_length); - } - if (prov_method_ == OEMCrypto_Keybox) { - // Keybox devices must have keybox for the source of the device - // ID. - LOGE("Expected keybox to be set for a device ID"); - return OEMCrypto_ERROR_NO_DEVICEID; - } - // For non-Keybox devices use fake device ID. - if (device_id_length == nullptr) { - LOGE("Output device ID length 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 < kFakeDeviceId.size()) { - *device_id_length = kFakeDeviceId.size(); - return OEMCrypto_ERROR_SHORT_BUFFER; - } - *device_id_length = kFakeDeviceId.size(); - memcpy(device_id, kFakeDeviceId.data(), kFakeDeviceId.size()); - return OEMCrypto_SUCCESS; +bool AuthenticationRoot::Validate() { + return NO_ERROR == ValidateKeybox(); } -std::vector AuthenticationRoot::DeviceId() const { - WvKeybox* kb = keybox(); - if (kb != nullptr) { - return kb->DeviceId(); - } - if (prov_method_ == OEMCrypto_Keybox) { - LOGE("Expected keybox to be set for a device ID"); - return kEmptyVector; - } - return std::vector(kFakeDeviceId.begin(), kFakeDeviceId.end()); -} - -std::vector AuthenticationRoot::DeviceKey() const { - WvKeybox* kb = keybox(); - if (kb != nullptr) { - return kb->DeviceKey(); - } - LOGE("No device key has been set"); - return kEmptyVector; -} - -bool AuthenticationRoot::HasDeviceKey() const { return keybox() != nullptr; } - -void AuthenticationRoot::Clear() { - RemoveTestRsaKey(); - RemoveTestKeybox(); -} - -OEMCryptoResult AuthenticationRoot::LoadTestRsaKey() { - if (prov_method_ != OEMCrypto_DrmCertificate) { - LOGE("System does not support DRM certificates"); - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - if (test_rsa_key_.get() != nullptr) { - LOGE("Test RSA key is already loaded"); - return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES; - } - if (!test_rsa_key_.LoadPkcs8RsaKey( - kTestRSAPKCS8PrivateKeyInfo2_2048, - sizeof(kTestRSAPKCS8PrivateKeyInfo2_2048))) { - LOGE("Failed to load test RSA key"); - return OEMCrypto_ERROR_UNKNOWN_FAILURE; - } - rsa_key_set_ = true; - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult AuthenticationRoot::IsKeyboxValid() const { - WvKeybox* kb = keybox(); - if (kb == nullptr) { - return OEMCrypto_ERROR_KEYBOX_INVALID; - } - return kb->IsKeyboxValid(); -} - -OEMCryptoResult AuthenticationRoot::InstallKeybox(const uint8_t* keybox_data, - size_t keybox_length) { - if (keybox_) { - LOGE("Keybox already installed"); - return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES; - } - const OEMCryptoResult result = - WvKeybox::ValidateData(keybox_data, keybox_length); - if (result != OEMCrypto_SUCCESS) { - LOGE("Cannot install an invalid keybox"); - return result; - } - keybox_ = WvKeybox::Create(keybox_data, keybox_length); - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult AuthenticationRoot::InstallTestKeybox( - const uint8_t* keybox_data, size_t keybox_length) { - if (prov_method_ != OEMCrypto_Keybox) { - LOGE("System does not support keybox"); - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - if (test_keybox_) { - LOGE("Test keybox already installed"); - return OEMCrypto_ERROR_INSUFFICIENT_RESOURCES; - } - const OEMCryptoResult result = - WvKeybox::ValidateData(keybox_data, keybox_length); - if (result != OEMCrypto_SUCCESS) { - LOGE("Cannot install an invalid test keybox"); - return result; - } - test_keybox_ = WvKeybox::Create(keybox_data, keybox_length); - return OEMCrypto_SUCCESS; -} - -OEMCryptoResult AuthenticationRoot::GetKeyData(uint8_t* key_data, - size_t* key_data_length) const { - if (prov_method_ != OEMCrypto_Keybox) { - LOGE("System does not support keybox"); - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - WvKeybox* kb = keybox(); - if (kb == nullptr) { - LOGE("No keybox to be set for source of key data"); - return OEMCrypto_ERROR_NO_KEYDATA; - } - return kb->GetKeyData(key_data, key_data_length); -} - -OEMCryptoResult AuthenticationRoot::GetOemPublicCertificate( - uint8_t* public_cert, size_t* public_cert_length) const { - if (prov_method_ != OEMCrypto_OEMCertificate) { - LOGE("System does not support OEM certificates"); - return OEMCrypto_ERROR_NOT_IMPLEMENTED; - } - LOGE("OEM certificates have not been implemented on auth root"); - return OEMCrypto_ERROR_NOT_IMPLEMENTED; -} - -const std::vector& AuthenticationRoot::GetOemPrivateKey() const { - if (prov_method_ != OEMCrypto_OEMCertificate) { - LOGE("System does not support OEM certificates"); - return kEmptyVector; - } - LOGE("OEM certificates have not been implemented on auth root"); - return kEmptyVector; -} } // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h index 3269613b..4e8ede7e 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_auth_ref.h @@ -21,141 +21,61 @@ #include "oemcrypto_types.h" namespace wvoec_ref { -// The AuthenticationRoot class contains the OEMCrypto information -// which makes up the "root of trust" of a device. + class AuthenticationRoot { public: - AuthenticationRoot() {} + explicit AuthenticationRoot(OEMCrypto_ProvisioningMethod method); ~AuthenticationRoot() {} - // Initializes the root of authentication for the provided - // |method|. This will clear any previously initialied data. - bool Initialize(OEMCrypto_ProvisioningMethod method); + bool Validate(); - // General root of trust API. + KeyboxError ValidateKeybox(); - // Checks that the auth root has been properly initialized and can - // be used by the rest of OEMCrypto for the current provisioning - // method. - bool IsValid() const; - - // Checks the validity of the underlying Keybox or OEM Certificate - // depending on the provisioning method. - // Similar to the expected behavior of OEMCrypto_IsKeyboxOrOEMCertValid(). - OEMCryptoResult IsKeyboxOrOemCertValid() const; - - // Gets the device ID from the root of trust. - // Similar to the expected behavior of OEMCrypto_GetDeviceID(). - OEMCryptoResult GetDeviceId(uint8_t* device_id, - size_t* device_id_length) const; - - // Returns the device ID from the root of trust. Intended to be used - // for core message generation. - std::vector DeviceId() const; - - // Returns the device key from the root of trust. For keybox-based - // devices, this is the device key from the keybox (or test keybox - // if installed). For devices that use a non-keybox provisioning - // method, this will be a device specific key. - std::vector DeviceKey() const; - - // Check for the existence of a device key. - bool HasDeviceKey() const; - - // Clears any test data inside this root of trust. - void Clear(); - - // DRM Certificate-based root of trust API. - - // Returns the shared RSA private key from the built-in DRM - // Certificate. - RSA_shared_ptr& SharedRsaKey() { - return test_rsa_key_.get() != nullptr ? test_rsa_key_ : rsa_key_; - } - RSA* rsa_key() { - return test_rsa_key_.get() != nullptr ? test_rsa_key_.get() - : rsa_key_.get(); + bool InstallKeybox(const uint8_t* keybox_data, size_t keybox_length) { + return keybox().InstallKeybox(keybox_data, keybox_length); } - // Loads the system's built-in RSA key. Only implemented for - // devices that are that pre-provisioned with a built-in DRM - // Certificate, - // This method implements the expected behavior of - // OEMCrypto_LoadTestRSAKey(). - OEMCryptoResult LoadTestRsaKey(); - - // Removes any installed test RSA key. - void RemoveTestRsaKey() { test_rsa_key_.reset(); } - - // Keybox-based root of trust API. - - // Returns the currently installed keybox (or test keybox) if any - // present. The test keybox takes priority over the standard. - WvKeybox* keybox() const { - return test_keybox_ ? test_keybox_.get() : keybox_.get(); + const std::vector& DeviceKey(bool use_real_keybox = false) { + return use_real_keybox ? real_keybox().device_key() : + keybox().device_key(); } - // Checks the validity of the keybox regardless of the provisioning - // method. - OEMCryptoResult IsKeyboxValid() const; + const std::vector& DeviceId() { + return keybox().device_id(); + } - // Installs a clear WV keybox as the root of trust. - // A keybox can only be installed once, however, the provisioning - // method stated at initialization remains the same. - // - // This method is similar to the expected behavior of - // OEMCrypto_InstallKeyboxOrOEMCert() for keybox devices except - // that the keybox provided here must be decrypted before installing. - OEMCryptoResult InstallKeybox(const uint8_t* keybox_data, - size_t keybox_length); + size_t DeviceTokenLength() { + return keybox().key_data_length(); + } - // Installs a clear test WV keybox. Only settable for devices that - // uses a keybox for provisioning. - // - // This method is similar to the expected behavior of - // OEMCrypto_LoadTestKeybox() for keybox devices except that - // the keybox provided here must be decrypted before installing. - OEMCryptoResult InstallTestKeybox(const uint8_t* keybox_data, - size_t keybox_length); + const uint8_t* DeviceToken() { + return keybox().key_data(); + } - // Removes any installed test keybox. - void RemoveTestKeybox() { test_keybox_.reset(); } + WvKeybox& keybox() { return use_test_keybox_ ? test_keybox_ : keybox_; } + bool UseTestKeybox(const uint8_t* keybox_data, size_t keybox_length) { + use_test_keybox_ = true; + return test_keybox_.InstallKeybox(keybox_data, keybox_length); + } - // Gets the keybox key data. - // Implements the expected behavior of OEMCrypto_GetKeyData(). - OEMCryptoResult GetKeyData(uint8_t* key_data, size_t* key_data_length) const; - - // OEM Certificate-base root of trust API. - - // For OEM Cert-based devices, returns the OEM Public Certificate - // component of the OEM Certificate. - // This method implements the expected behavior of - // OEMCrypto_GetOEMPublicCertificate(). - OEMCryptoResult GetOemPublicCertificate(uint8_t* public_cert, - size_t* public_cert_length) const; - - // Returns the OEM private key. Intended to be used when loading - // the OEM private key into a session. - // Should only be called for devices that use OEM Certificates - // for provisioning. - const std::vector& GetOemPrivateKey() const; + RSA_shared_ptr& SharedRsaKey() { return rsa_key_; } + RSA* rsa_key() { return rsa_key_.get(); } + bool LoadTestRsaKey(); + void Clear() { use_test_keybox_ = false; } private: - OEMCrypto_ProvisioningMethod prov_method_ = OEMCrypto_ProvisioningError; + OEMCrypto_ProvisioningMethod provisioning_method_; + WvKeybox& real_keybox() { return keybox_; } + + WvKeybox keybox_; + WvKeybox test_keybox_; + bool use_test_keybox_; - // DRM certificate. - // TODO(b/168544740): Remove |rsa_key_set_| when RSA_shared_ptr has - // been replaced with scoped RsaPrivateKey. - bool rsa_key_set_ = false; RSA_shared_ptr rsa_key_; // If no keybox, this is baked in certificate. - RSA_shared_ptr test_rsa_key_; - - // Keybox data. - std::unique_ptr keybox_; - std::unique_ptr test_keybox_; CORE_DISALLOW_COPY_AND_ASSIGN(AuthenticationRoot); }; + } // namespace wvoec_ref #endif // OEMCRYPTO_AUTH_REF_H_ diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.cpp index d999fe6c..91956171 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.cpp @@ -39,7 +39,9 @@ namespace wvoec_ref { // for methods that are configured for specific configurations. CryptoEngine::CryptoEngine(std::unique_ptr&& file_system) - : file_system_(std::move(file_system)), usage_table_() { + : root_of_trust_(config_provisioning_method()), + file_system_(std::move(file_system)), + usage_table_() { ERR_load_crypto_strings(); } @@ -51,7 +53,7 @@ bool CryptoEngine::Initialize() { std::string file_path = GetUsageTimeFileFullPath(); LoadOfflineTimeInfo(file_path); usage_table_.reset(MakeUsageTable()); - return root_of_trust_.Initialize(config_provisioning_method()); + return true; } void CryptoEngine::Terminate() { diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h index 6ccf13c4..3150f21b 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_engine_ref.h @@ -65,40 +65,31 @@ class CryptoEngine { virtual bool Initialize(); - bool ValidRootOfTrust() const { return root_of_trust_.IsValid(); } + bool ValidRootOfTrust() { return root_of_trust_.Validate(); } - OEMCryptoResult InstallKeybox(const uint8_t* keybox, size_t keybox_length) { + bool InstallKeybox(const uint8_t* keybox, size_t keybox_length) { return root_of_trust_.InstallKeybox(keybox, keybox_length); } - OEMCryptoResult InstallTestKeybox(const uint8_t* keybox_data, - size_t keybox_length) { - return root_of_trust_.InstallTestKeybox(keybox_data, keybox_length); + bool UseTestKeybox(const uint8_t* keybox_data, size_t keybox_length) { + return root_of_trust_.UseTestKeybox(keybox_data, keybox_length); } - OEMCryptoResult LoadTestRsaKey() { return root_of_trust_.LoadTestRsaKey(); } + bool LoadTestRsaKey() { return root_of_trust_.LoadTestRsaKey(); } - OEMCryptoResult IsKeyboxValid() const { - return root_of_trust_.IsKeyboxValid(); - } + KeyboxError ValidateKeybox() { return root_of_trust_.ValidateKeybox(); } - std::vector DeviceRootKey() const { + const std::vector& DeviceRootKey() { return root_of_trust_.DeviceKey(); } - OEMCryptoResult GetDeviceRootId(uint8_t* device_id, - size_t* device_id_length) const { - return root_of_trust_.GetDeviceId(device_id, device_id_length); - } - - std::vector DeviceRootId() const { + const std::vector& DeviceRootId() { return root_of_trust_.DeviceId(); } - OEMCryptoResult GetRootKeyData(uint8_t* key_data, - size_t* key_data_length) const { - return root_of_trust_.GetKeyData(key_data, key_data_length); - } + size_t DeviceRootTokenLength() { return root_of_trust_.DeviceTokenLength(); } + + const uint8_t* DeviceRootToken() { return root_of_trust_.DeviceToken(); } virtual void Terminate(); diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.cpp index 987a5103..e1cc4bcb 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.cpp @@ -17,113 +17,58 @@ #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 -std::vector ToVector(const uint8_t (&field)[N]) { - return std::vector(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; +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 -std::unique_ptr WvKeybox::Create(const uint8_t* keybox_data, - size_t keybox_length) { - std::unique_ptr keybox; - if (keybox_length != kKeyboxSize) { - LOGE("Invalid keybox length: length = %zu", keybox_length); - return keybox; +KeyboxError WvKeybox::Validate() { + if (!loaded_) { + LOGE("[KEYBOX NOT LOADED]"); + return OTHER_ERROR; } - keybox.reset(new WvKeybox()); - memcpy(reinterpret_cast(&keybox->raw_keybox_), keybox_data, - kKeyboxSize); - return keybox; + if (strncmp(reinterpret_cast(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(&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; } -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; +bool WvKeybox::InstallKeybox(const uint8_t* buffer, size_t keyBoxLength) { + if (keyBoxLength != 128) { + return false; } - 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 WvKeybox::DeviceId() const { - return ToVector(raw_keybox_.device_id_); -} - -std::vector 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(&raw_keybox_), - kKeyboxSize); + const wvoec::WidevineKeybox* keybox = + reinterpret_cast(buffer); + size_t device_id_length = + strnlen(reinterpret_cast(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; } } // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.h b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.h index c9831c60..bb543fc2 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.h +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_keybox_ref.h @@ -7,58 +7,38 @@ #ifndef OEMCRYPTO_KEYBOX_REF_H_ #define OEMCRYPTO_KEYBOX_REF_H_ -#include -#include - -#include "OEMCryptoCENCCommon.h" -#include "oemcrypto_types.h" +#include "oemcrypto_key_ref.h" namespace wvoec_ref { +const int DEVICE_KEY_LENGTH = 16; +typedef uint8_t WvKeyboxKey[DEVICE_KEY_LENGTH]; + +const int KEY_DATA_LENGTH = 72; +typedef uint8_t WvKeyboxKeyData[KEY_DATA_LENGTH]; + +enum KeyboxError { NO_ERROR, BAD_CRC, BAD_MAGIC, OTHER_ERROR }; + // Widevine keybox class WvKeybox { public: - // Validates keybox data using the following rules: - // 1. Data is not null - // 2. Keybox size - // 3. Matching magic - // 4. CRC-32 check - static OEMCryptoResult ValidateData(const uint8_t* keybox_data, - size_t keybox_length); - - // Creates a keybox from the provided keybox data. - // Provided keybox data must be the proper length, but does - // not need to be valid. - // Once created, keyboxes are immutable. - static std::unique_ptr Create(const uint8_t* keybox_data, - size_t keybox_length); - - // Gets the device ID from the keybox. - // Similar to the expected behavior of OEMCrypto_GetDeviceID(). - OEMCryptoResult GetDeviceId(uint8_t* device_id, - size_t* device_id_length) const; - // Returns the keybox device ID directly. Intended to be used - // for core message generation. - std::vector DeviceId() const; - - // Returns the keybox device key directly. Intended to be used - // for key derivation. - std::vector DeviceKey() const; - - // Gets the keybox data. - // Similar to the expected behavior of OEMCrypto_GetKeyData(). - OEMCryptoResult GetKeyData(uint8_t* key_data, size_t* key_data_length) const; - - // Checks the current keybox instantiation that it is valid. - // Similar to the expected behavior of OEMCrypto_IsKeyboxValid(). - OEMCryptoResult IsKeyboxValid() const; - + WvKeybox(); ~WvKeybox() {} - private: - WvKeybox() {} + KeyboxError Validate(); + const std::vector& device_id() { return device_id_; } + std::vector& device_key() { return device_key_; } + const WvKeyboxKeyData& key_data() { return key_data_; } + size_t key_data_length() { return KEY_DATA_LENGTH; } + bool InstallKeybox(const uint8_t* keybox, size_t keyBoxLength); - wvoec::WidevineKeybox raw_keybox_; + private: + bool loaded_; + std::vector device_id_; + std::vector device_key_; + WvKeyboxKeyData key_data_; + uint8_t magic_[4]; + uint8_t crc_[4]; }; } // namespace wvoec_ref diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp index aeca0675..a05bb7f5 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_ref.cpp @@ -733,7 +733,7 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_WrapKeyboxOrOEMCert( } OEMCRYPTO_API OEMCryptoResult -OEMCrypto_InstallKeyboxOrOEMCert(const uint8_t* keybox, size_t keybox_length) { +OEMCrypto_InstallKeyboxOrOEMCert(const uint8_t* keybox, size_t keyBoxLength) { if (crypto_engine == nullptr) { LOGE("OEMCrypto_InstallKeyboxOrOEMCert: OEMCrypto Not Initialized."); return OEMCrypto_ERROR_UNKNOWN_FAILURE; @@ -741,7 +741,10 @@ OEMCrypto_InstallKeyboxOrOEMCert(const uint8_t* keybox, size_t keybox_length) { if (crypto_engine->config_provisioning_method() != OEMCrypto_Keybox) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } - return crypto_engine->InstallKeybox(keybox, keybox_length); + if (crypto_engine->InstallKeybox(keybox, keyBoxLength)) { + return OEMCrypto_SUCCESS; + } + return OEMCrypto_ERROR_WRITE_KEYBOX; } OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadTestKeybox(const uint8_t* buffer, @@ -753,7 +756,10 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadTestKeybox(const uint8_t* buffer, if (crypto_engine->config_provisioning_method() != OEMCrypto_Keybox) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } - return crypto_engine->InstallTestKeybox(buffer, length); + if (crypto_engine->UseTestKeybox(buffer, length)) { + return OEMCrypto_SUCCESS; + } + return OEMCrypto_ERROR_UNKNOWN_FAILURE; } OEMCRYPTO_API OEMCryptoResult OEMCrypto_IsKeyboxOrOEMCertValid(void) { @@ -765,10 +771,22 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_IsKeyboxOrOEMCertValid(void) { case OEMCrypto_DrmCertificate: return OEMCrypto_SUCCESS; case OEMCrypto_Keybox: - return crypto_engine->IsKeyboxValid(); + switch (crypto_engine->ValidateKeybox()) { + case NO_ERROR: + return OEMCrypto_SUCCESS; + case BAD_CRC: + return OEMCrypto_ERROR_BAD_CRC; + case BAD_MAGIC: + return OEMCrypto_ERROR_BAD_MAGIC; + default: + case OTHER_ERROR: + return OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + break; case OEMCrypto_OEMCertificate: - // TODO(sigquit): verify that the certificate exists and is valid. + // TODO(fredgc): verify that the certificate exists and is valid. return OEMCrypto_SUCCESS; + break; default: LOGE("Invalid provisioning method: %d.", crypto_engine->config_provisioning_method()); @@ -817,17 +835,32 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetOEMPublicCertificate( return crypto_engine->get_oem_certificate(public_cert, public_cert_length); } -OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* device_id, - size_t* device_id_length) { +OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetDeviceID(uint8_t* deviceID, + size_t* idLength) { if (crypto_engine == nullptr) { LOGE("OEMCrypto_GetDeviceID: OEMCrypto Not Initialized."); return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - return crypto_engine->GetDeviceRootId(device_id, device_id_length); + const std::vector& dev_id_string = crypto_engine->DeviceRootId(); + if (dev_id_string.empty()) { + LOGE("[OEMCrypto_GetDeviceId(): Keybox Invalid]"); + return OEMCrypto_ERROR_KEYBOX_INVALID; + } + + size_t dev_id_len = dev_id_string.size(); + if (*idLength < dev_id_len) { + *idLength = dev_id_len; + LOGE("[OEMCrypto_GetDeviceId(): ERROR_SHORT_BUFFER]"); + return OEMCrypto_ERROR_SHORT_BUFFER; + } + memset(deviceID, 0, *idLength); + memcpy(deviceID, &dev_id_string[0], dev_id_len); + *idLength = dev_id_len; + return OEMCrypto_SUCCESS; } -OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* key_data, - size_t* key_data_length) { +OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* keyData, + size_t* keyDataLength) { if (crypto_engine == nullptr) { LOGE("OEMCrypto_GetKeyData: OEMCrypto Not Initialized."); return OEMCrypto_ERROR_UNKNOWN_FAILURE; @@ -835,7 +868,24 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetKeyData(uint8_t* key_data, if (crypto_engine->config_provisioning_method() != OEMCrypto_Keybox) { return OEMCrypto_ERROR_NOT_IMPLEMENTED; } - return crypto_engine->GetRootKeyData(key_data, key_data_length); + size_t length = crypto_engine->DeviceRootTokenLength(); + if (keyDataLength == nullptr) { + LOGE("[OEMCrypto_GetKeyData(): null pointer. ERROR_UNKNOWN_FAILURE]"); + return OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + if (*keyDataLength < length) { + *keyDataLength = length; + LOGE("[OEMCrypto_GetKeyData(): ERROR_SHORT_BUFFER]"); + return OEMCrypto_ERROR_SHORT_BUFFER; + } + if (keyData == nullptr) { + LOGE("[OEMCrypto_GetKeyData(): null pointer. ERROR_UNKNOWN_FAILURE]"); + return OEMCrypto_ERROR_UNKNOWN_FAILURE; + } + memset(keyData, 0, *keyDataLength); + memcpy(keyData, crypto_engine->DeviceRootToken(), length); + *keyDataLength = length; + return OEMCrypto_SUCCESS; } OEMCRYPTO_API OEMCryptoResult OEMCrypto_GetRandom(uint8_t* randomData, @@ -1209,7 +1259,8 @@ OEMCRYPTO_API OEMCryptoResult OEMCrypto_LoadTestRSAKey() { LOGE("OEMCrypto_LoadTestRSAKey: OEMCrypto Not Initialized."); return OEMCrypto_ERROR_UNKNOWN_FAILURE; } - return crypto_engine->LoadTestRsaKey(); + if (crypto_engine->LoadTestRsaKey()) return OEMCrypto_SUCCESS; + return OEMCrypto_ERROR_UNKNOWN_FAILURE; } OEMCRYPTO_API OEMCryptoResult OEMCrypto_GenerateRSASignature( diff --git a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp index 51bf560e..9a1ab8e5 100644 --- a/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp +++ b/libwvdrmengine/oemcrypto/ref/src/oemcrypto_session.cpp @@ -430,7 +430,7 @@ OEMCryptoResult SessionContext::PrepAndSignProvisioningRequest( } const size_t required_signature_size = ROTSignatureSize(); if (required_signature_size == 0) return OEMCrypto_ERROR_UNKNOWN_FAILURE; - const std::vector device_id = ce_->DeviceRootId(); + const std::vector& device_id = ce_->DeviceRootId(); OEMCryptoResult result = ODK_PrepareCoreProvisioningRequest( message, message_length, core_message_length, &nonce_values_, device_id.data(), device_id.size());