diff --git a/libwvdrmengine/factory_upload_tool/README b/libwvdrmengine/factory_upload_tool/README index af5b1353..6f78a4fd 100644 --- a/libwvdrmengine/factory_upload_tool/README +++ b/libwvdrmengine/factory_upload_tool/README @@ -1 +1 @@ -This folder contains Widevine's implementation of Android Remote Provisioning HAL, which is used as part of provisioning 4.0 process. It is intented for factory usage only, and should not be present on user devices. \ No newline at end of file +This folder contains Widevine's implementation of Android Remote Provisioning HAL, which is used as part of provisioning 4.0 process. It is intended for factory usage only, and should not be present on user devices. \ No newline at end of file diff --git a/libwvdrmengine/factory_upload_tool/include/WidevineOemcryptoInterface.h b/libwvdrmengine/factory_upload_tool/include/WidevineOemcryptoInterface.h index be355532..1723d985 100644 --- a/libwvdrmengine/factory_upload_tool/include/WidevineOemcryptoInterface.h +++ b/libwvdrmengine/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/factory_upload_tool/include/WidevineProvisioner.h b/libwvdrmengine/factory_upload_tool/include/WidevineProvisioner.h index 41014642..f627489f 100644 --- a/libwvdrmengine/factory_upload_tool/include/WidevineProvisioner.h +++ b/libwvdrmengine/factory_upload_tool/include/WidevineProvisioner.h @@ -41,6 +41,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/factory_upload_tool/src/WidevineOemcryptoInterface.cpp b/libwvdrmengine/factory_upload_tool/src/WidevineOemcryptoInterface.cpp index 3c7d728b..1e52d4af 100644 --- a/libwvdrmengine/factory_upload_tool/src/WidevineOemcryptoInterface.cpp +++ b/libwvdrmengine/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/factory_upload_tool/src/WidevineProvisioner.cpp b/libwvdrmengine/factory_upload_tool/src/WidevineProvisioner.cpp index 82e7c4c5..aa3d31d9 100644 --- a/libwvdrmengine/factory_upload_tool/src/WidevineProvisioner.cpp +++ b/libwvdrmengine/factory_upload_tool/src/WidevineProvisioner.cpp @@ -19,6 +19,7 @@ #include #include +#include "WidevineOemcryptoInterface.h" #include "log.h" #include "properties.h" @@ -61,25 +62,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) || @@ -89,21 +152,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."); @@ -121,6 +169,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; }