diff --git a/libwvdrmengine/tools/factory_upload_tool/include/WidevineOemcryptoInterface.h b/libwvdrmengine/tools/factory_upload_tool/include/WidevineOemcryptoInterface.h index be355532..1723d985 100644 --- a/libwvdrmengine/tools/factory_upload_tool/include/WidevineOemcryptoInterface.h +++ b/libwvdrmengine/tools/factory_upload_tool/include/WidevineOemcryptoInterface.h @@ -13,6 +13,13 @@ namespace widevine { +struct VerifiedDeviceInfo { + std::vector device_info; + // Used by Interface of Remote Provisioning Component (IRPC) v3 for CSR + // uploading + std::vector signed_csr_payload; +}; + class OEMCryptoInterface { public: OEMCryptoInterface() = default; @@ -30,6 +37,11 @@ class OEMCryptoInterface { // implementation. OEMCryptoResult GetOEMCryptoBuildInfo(std::string& build_info); + // Retrieves the verified device information of the OEMCrypto library from + // OEMCrypto implementation. + OEMCryptoResult GetVerifiedDeviceInformation( + VerifiedDeviceInfo& verified_device_info); + private: typedef OEMCryptoResult (*Initialize_t)(); typedef OEMCryptoResult (*Terminate_t)(); @@ -38,11 +50,15 @@ class OEMCryptoInterface { size_t* additional_signature_size); typedef OEMCryptoResult (*BuildInformation_t)(char* buffer, size_t* buffer_length); + typedef OEMCryptoResult (*GetDeviceInformation_t)( + uint8_t* device_info, size_t* device_info_length, + uint8_t* signed_csr_payload, size_t* signed_csr_payload_length); Initialize_t Initialize = nullptr; Terminate_t Terminate = nullptr; GetBootCertificateChain_t GetBootCertificateChain = nullptr; BuildInformation_t BuildInformation = nullptr; + GetDeviceInformation_t GetDeviceInformation = nullptr; void* handle_ = nullptr; }; diff --git a/libwvdrmengine/tools/factory_upload_tool/include/WidevineProvisioner.h b/libwvdrmengine/tools/factory_upload_tool/include/WidevineProvisioner.h index 62b81d36..ea3ff86d 100644 --- a/libwvdrmengine/tools/factory_upload_tool/include/WidevineProvisioner.h +++ b/libwvdrmengine/tools/factory_upload_tool/include/WidevineProvisioner.h @@ -44,6 +44,8 @@ class WidevineProvisioner { cppbor::Array BuildCertReqRecipients(const std::vector& pubkey, const std::vector& kid) const; void InitializeCryptoInterface(); + bool GetDeviceInfoCommon(cppbor::Map& device_info_map); + bool TryAddVerifiedDeviceInfo(cppbor::Map& device_info_map); std::unique_ptr crypto_interface_; }; diff --git a/libwvdrmengine/tools/factory_upload_tool/src/WidevineOemcryptoInterface.cpp b/libwvdrmengine/tools/factory_upload_tool/src/WidevineOemcryptoInterface.cpp index 3c7d728b..1e52d4af 100644 --- a/libwvdrmengine/tools/factory_upload_tool/src/WidevineOemcryptoInterface.cpp +++ b/libwvdrmengine/tools/factory_upload_tool/src/WidevineOemcryptoInterface.cpp @@ -21,6 +21,8 @@ LOGE("%s", dlerror()); \ return false; \ } +#define LOAD_SYM_IF_EXIST(name) \ + name = reinterpret_cast(LOOKUP(handle_, OEMCrypto_##name)); // These are implementations required by OEMCrypto Reference Implementation // and/or the Testbed, but not needed in this package. @@ -78,6 +80,7 @@ bool OEMCryptoInterface::Init(const std::string& oemcrypto_path) { LOAD_SYM(Terminate); LOAD_SYM(GetBootCertificateChain); LOAD_SYM(BuildInformation); + LOAD_SYM_IF_EXIST(GetDeviceInformation); OEMCryptoResult status = Initialize(); if (status != OEMCrypto_SUCCESS) { @@ -141,4 +144,37 @@ OEMCryptoResult OEMCryptoInterface::GetOEMCryptoBuildInfo( return result; } +OEMCryptoResult OEMCryptoInterface::GetVerifiedDeviceInformation( + VerifiedDeviceInfo& verified_device_info) { + if (handle_ == nullptr) { + return OEMCrypto_ERROR_INIT_FAILED; + } + if (GetDeviceInformation == nullptr) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + + verified_device_info.device_info.resize(0); + size_t device_info_size = 0; + verified_device_info.signed_csr_payload.resize(0); + size_t signed_csr_payload_size = 0; + + OEMCryptoResult result = GetDeviceInformation( + verified_device_info.device_info.data(), &device_info_size, + verified_device_info.signed_csr_payload.data(), &signed_csr_payload_size); + LOGI("GetVerifiedDeviceInformation first attempt result %d", result); + if (result == OEMCrypto_ERROR_SHORT_BUFFER) { + verified_device_info.device_info.resize(device_info_size); + verified_device_info.signed_csr_payload.resize(signed_csr_payload_size); + result = GetDeviceInformation( + verified_device_info.device_info.data(), &device_info_size, + verified_device_info.signed_csr_payload.data(), + &signed_csr_payload_size); + verified_device_info.device_info.resize(device_info_size); + verified_device_info.signed_csr_payload.resize(signed_csr_payload_size); + LOGI("GetVerifiedDeviceInformation second attempt result %d", result); + } + + return result; +} + } // namespace widevine diff --git a/libwvdrmengine/tools/factory_upload_tool/src/WidevineProvisioner.cpp b/libwvdrmengine/tools/factory_upload_tool/src/WidevineProvisioner.cpp index c5c8515d..2c99cea5 100644 --- a/libwvdrmengine/tools/factory_upload_tool/src/WidevineProvisioner.cpp +++ b/libwvdrmengine/tools/factory_upload_tool/src/WidevineProvisioner.cpp @@ -19,6 +19,7 @@ #include #include +#include "WidevineOemcryptoInterface.h" #include "log.h" #include "properties.h" @@ -70,25 +71,87 @@ bool WidevineProvisioner::GenerateCertificateRequest( return true; } -bool WidevineProvisioner::GetDeviceInfo(std::vector& device_info) { - auto device_info_map = cppbor::Map(); - device_info_map.add(cppbor::Tstr("type"), cppbor::Tstr("widevine")); - device_info_map.add(cppbor::Tstr("version"), cppbor::Uint(2)); - - std::string company_name; - if (!wvcdm::Properties::GetCompanyName(&company_name) || - company_name.empty()) { - LOGE("Failed to get company name."); +bool WidevineProvisioner::TryAddVerifiedDeviceInfo( + cppbor::Map& device_info_map) { + VerifiedDeviceInfo verified_device_info; + OEMCryptoResult result = + crypto_interface_->GetVerifiedDeviceInformation(verified_device_info); + if (result == OEMCrypto_ERROR_NOT_IMPLEMENTED) { + // OEMCrypto v17 and earlier doesn't support GetDeviceInformation() + LOGI("OEMCrypto_GetDeviceInformation is not implemented."); + return true; + } + if (result != OEMCrypto_SUCCESS) { + LOGE("Failed to get verified device information."); return false; } - device_info_map.add(cppbor::Tstr("manufacturer"), cppbor::Tstr(company_name)); - - std::string model_name; - if (!wvcdm::Properties::GetModelName(&model_name) || model_name.empty()) { - LOGE("Failed to get model name."); + auto [parsed, _, err] = cppbor::parse( + reinterpret_cast(verified_device_info.device_info.data()), + verified_device_info.device_info.size()); + if (!parsed || !parsed->asMap()) { + LOGE("Failed to parse the verified device info cbor: %s", err.c_str()); return false; } - device_info_map.add(cppbor::Tstr("model"), cppbor::Tstr(model_name)); + const cppbor::Map* verified_device_info_map = parsed->asMap(); + auto& make = verified_device_info_map->get("manufacturer"); + if (make && make->asTstr() && make->asTstr()->value() != "") { + device_info_map.add("manufacturer", make->asTstr()->value()); + } + auto& model = verified_device_info_map->get("model"); + if (model && model->asTstr() && model->asTstr()->value() != "") { + device_info_map.add("model", model->asTstr()->value()); + } + auto& fused = verified_device_info_map->get("fused"); + if (fused && fused->asUint()) { + device_info_map.add("fused", fused->asUint()->value()); + } + device_info_map.canonicalize(); + return true; +} + +bool WidevineProvisioner::GetDeviceInfoCommon(cppbor::Map& device_info_map) { + if (!TryAddVerifiedDeviceInfo(device_info_map)) return false; + // Add device information from OS properties if the verified device info is + // not present + if (device_info_map.get("manufacturer") == nullptr) { + std::string company_name; + if (!wvcdm::Properties::GetCompanyName(&company_name) || + company_name.empty()) { + LOGE("Failed to get company name."); + return false; + } + device_info_map.add(cppbor::Tstr("manufacturer"), + cppbor::Tstr(company_name)); + } + + if (device_info_map.get("model") == nullptr) { + std::string model_name; + if (!wvcdm::Properties::GetModelName(&model_name) || model_name.empty()) { + LOGE("Failed to get model name."); + return false; + } + device_info_map.add(cppbor::Tstr("model"), cppbor::Tstr(model_name)); + } + + if (device_info_map.get("device") == nullptr) { + std::string device_name; + if (!wvcdm::Properties::GetDeviceName(&device_name) || + device_name.empty()) { + LOGE("Failed to get device name."); + return false; + } + device_info_map.add(cppbor::Tstr("device"), cppbor::Tstr(device_name)); + } + + if (device_info_map.get("product") == nullptr) { + std::string product_name; + if (!wvcdm::Properties::GetProductName(&product_name) || + product_name.empty()) { + LOGE("Failed to get product name."); + return false; + } + device_info_map.add(cppbor::Tstr("product"), cppbor::Tstr(product_name)); + } std::string arch_name; if (!wvcdm::Properties::GetArchitectureName(&arch_name) || @@ -98,21 +161,6 @@ bool WidevineProvisioner::GetDeviceInfo(std::vector& device_info) { } device_info_map.add(cppbor::Tstr("architecture"), cppbor::Tstr(arch_name)); - std::string device_name; - if (!wvcdm::Properties::GetDeviceName(&device_name) || device_name.empty()) { - LOGE("Failed to get device name."); - return false; - } - device_info_map.add(cppbor::Tstr("device"), cppbor::Tstr(device_name)); - - std::string product_name; - if (!wvcdm::Properties::GetProductName(&product_name) || - product_name.empty()) { - LOGE("Failed to get product name."); - return false; - } - device_info_map.add(cppbor::Tstr("product"), cppbor::Tstr(product_name)); - std::string build_info; if (!wvcdm::Properties::GetBuildInfo(&build_info) || build_info.empty()) { LOGE("Failed to get build info."); @@ -130,6 +178,16 @@ bool WidevineProvisioner::GetDeviceInfo(std::vector& device_info) { device_info_map.add(cppbor::Tstr("oemcrypto_build_info"), cppbor::Tstr(oemcrypto_build_info)); + device_info_map.canonicalize(); + return true; +} + +bool WidevineProvisioner::GetDeviceInfo(std::vector& device_info) { + auto device_info_map = cppbor::Map(); + device_info_map.add(cppbor::Tstr("type"), cppbor::Tstr("widevine")); + device_info_map.add(cppbor::Tstr("version"), cppbor::Uint(2)); + device_info_map.canonicalize(); + if (!GetDeviceInfoCommon(device_info_map)) return false; device_info = device_info_map.canonicalize().encode(); return true; }