From 8dc7cc0c749f9e46d875c3047b88cc49ee62bcf6 Mon Sep 17 00:00:00 2001 From: Cong Lin Date: Sun, 19 Feb 2023 17:38:25 -0800 Subject: [PATCH] Factory tool implements Widevine IRPC HAL v3 Implement IRPC HAL v3 interfaces for extracting device registration CSR. The new interface calls OEMCrypto_GetDeviceInformation() and OEMCrypto_GetSignedCsrPayload() and then constructs the CSR. Also added all mandatory fields of device info in the request. Test: Run extraction tool on Pixel 7 and upload CSR Test: Verified Widevine remote provisioning Bug: 268246995 Change-Id: I24097ba32c7a105266071c1341c938b5874b38d8 --- .../include/WidevineOemcryptoInterface.h | 23 +++--- .../include/WidevineProvisioner.h | 3 + .../WidevineRemotelyProvisionedComponent.h | 8 +- .../src/WidevineOemcryptoInterface.cpp | 54 +++++++++----- .../src/WidevineProvisioner.cpp | 73 ++++++++++++++----- .../WidevineRemotelyProvisionedComponent.cpp | 22 +++++- 6 files changed, 130 insertions(+), 53 deletions(-) diff --git a/libwvdrmengine/factory_upload_tool/include/WidevineOemcryptoInterface.h b/libwvdrmengine/factory_upload_tool/include/WidevineOemcryptoInterface.h index 1723d985..c5f02c58 100644 --- a/libwvdrmengine/factory_upload_tool/include/WidevineOemcryptoInterface.h +++ b/libwvdrmengine/factory_upload_tool/include/WidevineOemcryptoInterface.h @@ -13,13 +13,6 @@ 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; @@ -40,7 +33,13 @@ class OEMCryptoInterface { // Retrieves the verified device information of the OEMCrypto library from // OEMCrypto implementation. OEMCryptoResult GetVerifiedDeviceInformation( - VerifiedDeviceInfo& verified_device_info); + std::vector& verified_device_info); + + // Generates device registration CSR payload and signs it with the leaf cert + // of BCC. + OEMCryptoResult GetSignedCsrPayload(const std::vector& challenge, + const std::vector& device_info, + std::vector& signed_csr_payload); private: typedef OEMCryptoResult (*Initialize_t)(); @@ -50,8 +49,11 @@ 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, + typedef OEMCryptoResult (*GetDeviceInformation_t)(uint8_t* device_info, + size_t* device_info_length); + typedef OEMCryptoResult (*GetDeviceSignedCsrPayload_t)( + const uint8_t* challenge, size_t challenge_length, + const uint8_t* device_info, size_t device_info_length, uint8_t* signed_csr_payload, size_t* signed_csr_payload_length); Initialize_t Initialize = nullptr; @@ -59,6 +61,7 @@ class OEMCryptoInterface { GetBootCertificateChain_t GetBootCertificateChain = nullptr; BuildInformation_t BuildInformation = nullptr; GetDeviceInformation_t GetDeviceInformation = nullptr; + GetDeviceSignedCsrPayload_t GetDeviceSignedCsrPayload = nullptr; void* handle_ = nullptr; }; diff --git a/libwvdrmengine/factory_upload_tool/include/WidevineProvisioner.h b/libwvdrmengine/factory_upload_tool/include/WidevineProvisioner.h index f627489f..b2f138d7 100644 --- a/libwvdrmengine/factory_upload_tool/include/WidevineProvisioner.h +++ b/libwvdrmengine/factory_upload_tool/include/WidevineProvisioner.h @@ -27,6 +27,8 @@ class WidevineProvisioner { bool GenerateCertificateRequest( bool testMode, const std::vector& endpointEncCertChain, std::vector& deviceInfo, std::vector& protectedData); + bool GenerateCertificateRequestV2(const std::vector& challenge, + std::vector* csr); private: bool GetDeviceInfo(std::vector& device_info); @@ -43,6 +45,7 @@ class WidevineProvisioner { void InitializeCryptoInterface(); bool GetDeviceInfoCommon(cppbor::Map& device_info_map); bool TryAddVerifiedDeviceInfo(cppbor::Map& device_info_map); + bool GetDeviceInfoV2(cppbor::Map& device_info_map); std::unique_ptr crypto_interface_; }; diff --git a/libwvdrmengine/factory_upload_tool/include/WidevineRemotelyProvisionedComponent.h b/libwvdrmengine/factory_upload_tool/include/WidevineRemotelyProvisionedComponent.h index bb89b50f..90532c57 100644 --- a/libwvdrmengine/factory_upload_tool/include/WidevineRemotelyProvisionedComponent.h +++ b/libwvdrmengine/factory_upload_tool/include/WidevineRemotelyProvisionedComponent.h @@ -49,11 +49,9 @@ class WidevineRemotelyProvisionedComponent std::vector* keysToSignMac) override; ScopedAStatus generateCertificateRequestV2( - const std::vector& /* keysToSign */, - const std::vector& /* challenge */, - std::vector* /* csr */) override { - return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION); - } + const std::vector& keysToSign, + const std::vector& challenge, + std::vector* csr) override; private: std::unique_ptr provisioner_; diff --git a/libwvdrmengine/factory_upload_tool/src/WidevineOemcryptoInterface.cpp b/libwvdrmengine/factory_upload_tool/src/WidevineOemcryptoInterface.cpp index 1e52d4af..ccb105a3 100644 --- a/libwvdrmengine/factory_upload_tool/src/WidevineOemcryptoInterface.cpp +++ b/libwvdrmengine/factory_upload_tool/src/WidevineOemcryptoInterface.cpp @@ -81,6 +81,7 @@ bool OEMCryptoInterface::Init(const std::string& oemcrypto_path) { LOAD_SYM(GetBootCertificateChain); LOAD_SYM(BuildInformation); LOAD_SYM_IF_EXIST(GetDeviceInformation); + LOAD_SYM_IF_EXIST(GetDeviceSignedCsrPayload); OEMCryptoResult status = Initialize(); if (status != OEMCrypto_SUCCESS) { @@ -145,7 +146,7 @@ OEMCryptoResult OEMCryptoInterface::GetOEMCryptoBuildInfo( } OEMCryptoResult OEMCryptoInterface::GetVerifiedDeviceInformation( - VerifiedDeviceInfo& verified_device_info) { + std::vector& verified_device_info) { if (handle_ == nullptr) { return OEMCrypto_ERROR_INIT_FAILED; } @@ -153,27 +154,46 @@ OEMCryptoResult OEMCryptoInterface::GetVerifiedDeviceInformation( 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); + verified_device_info.resize(0); + size_t verified_device_info_size = 0; + OEMCryptoResult result = GetDeviceInformation(verified_device_info.data(), + &verified_device_info_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); + verified_device_info.resize(verified_device_info_size); + result = GetDeviceInformation(verified_device_info.data(), + &verified_device_info_size); + verified_device_info.resize(verified_device_info_size); LOGI("GetVerifiedDeviceInformation second attempt result %d", result); } + return result; +} +OEMCryptoResult OEMCryptoInterface::GetSignedCsrPayload( + const std::vector& challenge, + const std::vector& device_info, + std::vector& signed_csr_payload) { + if (handle_ == nullptr) { + return OEMCrypto_ERROR_INIT_FAILED; + } + if (GetDeviceSignedCsrPayload == nullptr) { + return OEMCrypto_ERROR_NOT_IMPLEMENTED; + } + + size_t signed_csr_payload_size = signed_csr_payload.size(); + OEMCryptoResult result = GetDeviceSignedCsrPayload( + challenge.data(), challenge.size(), device_info.data(), + device_info.size(), signed_csr_payload.data(), &signed_csr_payload_size); + LOGI("GetDeviceSignedCsrPayload first attempt result %d", result); + if (result == OEMCrypto_ERROR_SHORT_BUFFER) { + signed_csr_payload.resize(signed_csr_payload_size); + result = GetDeviceSignedCsrPayload(challenge.data(), challenge.size(), + device_info.data(), device_info.size(), + signed_csr_payload.data(), + &signed_csr_payload_size); + signed_csr_payload.resize(signed_csr_payload_size); + LOGI("GetDeviceSignedCsrPayload second attempt result %d", result); + } return result; } diff --git a/libwvdrmengine/factory_upload_tool/src/WidevineProvisioner.cpp b/libwvdrmengine/factory_upload_tool/src/WidevineProvisioner.cpp index aa3d31d9..2519304d 100644 --- a/libwvdrmengine/factory_upload_tool/src/WidevineProvisioner.cpp +++ b/libwvdrmengine/factory_upload_tool/src/WidevineProvisioner.cpp @@ -49,7 +49,7 @@ bool WidevineProvisioner::GenerateCertificateRequest( std::vector bcc; OEMCryptoResult result = crypto_interface_->GetBcc(bcc); if (result != OEMCrypto_SUCCESS) { - LOGE("Failed to get BCC."); + LOGE("Failed to get BCC, result = %d", result); return false; } @@ -64,7 +64,7 @@ bool WidevineProvisioner::GenerateCertificateRequest( bool WidevineProvisioner::TryAddVerifiedDeviceInfo( cppbor::Map& device_info_map) { - VerifiedDeviceInfo verified_device_info; + std::vector verified_device_info; OEMCryptoResult result = crypto_interface_->GetVerifiedDeviceInformation(verified_device_info); if (result == OEMCrypto_ERROR_NOT_IMPLEMENTED) { @@ -73,30 +73,22 @@ bool WidevineProvisioner::TryAddVerifiedDeviceInfo( return true; } if (result != OEMCrypto_SUCCESS) { - LOGE("Failed to get verified device information."); + LOGE("Failed to get verified device information, result = %d", result); return false; } auto [parsed, _, err] = cppbor::parse( - reinterpret_cast(verified_device_info.device_info.data()), - verified_device_info.device_info.size()); + reinterpret_cast(verified_device_info.data()), + verified_device_info.size()); if (!parsed || !parsed->asMap()) { LOGE("Failed to parse the verified device info cbor: %s", err.c_str()); return false; } 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()); + for (size_t i = 0; i < verified_device_info_map->size(); i++) { + auto& [key_item, value_item] = (*verified_device_info_map)[i]; + LOGI("Found device info %s", key_item->asTstr()->value().data()); + device_info_map.add(key_item->clone(), value_item->clone()); } - 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; } @@ -168,8 +160,6 @@ bool WidevineProvisioner::GetDeviceInfoCommon(cppbor::Map& device_info_map) { } device_info_map.add(cppbor::Tstr("oemcrypto_build_info"), cppbor::Tstr(oemcrypto_build_info)); - - device_info_map.canonicalize(); return true; } @@ -177,7 +167,6 @@ 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; @@ -309,6 +298,50 @@ cppbor::Array WidevineProvisioner::BuildCertReqRecipients( .add(cppbor::Null())); // No ciphertext } +bool WidevineProvisioner::GetDeviceInfoV2(cppbor::Map& device_info_map) { + if (!GetDeviceInfoCommon(device_info_map)) return false; + device_info_map.canonicalize(); + return true; +} + +bool WidevineProvisioner::GenerateCertificateRequestV2( + const std::vector& challenge, std::vector* csr) { + if (csr == nullptr) { + LOGE("CSR is null."); + return false; + } + // Prepare BCC + std::vector bcc; + OEMCryptoResult result = crypto_interface_->GetBcc(bcc); + if (result != OEMCrypto_SUCCESS) { + LOGE("Failed to get BCC, result = %d", result); + return false; + } + // Prepare device info + auto device_info_map = cppbor::Map(); + if (!GetDeviceInfoV2(device_info_map)) { + LOGE("Failed to get device_info."); + return false; + } + // Prepare signed CSR payload + auto device_info = device_info_map.encode(); + std::vector signed_csr_payload; + result = crypto_interface_->GetSignedCsrPayload(challenge, device_info, + signed_csr_payload); + if (result != OEMCrypto_SUCCESS) { + LOGE("Failed to get the signed CSR payload, result = %d", result); + return false; + } + // https://source.corp.google.com/android-internal/hardware/interfaces/security/rkp/aidl/android/hardware/security/keymint/IRemotelyProvisionedComponent.aidl + *csr = cppbor::Array() + .add(1 /* version */) + .add(cppbor::Map() /* UdsCerts */) + .add(cppbor::EncodedItem(std::move(bcc))) + .add(cppbor::EncodedItem(std::move(signed_csr_payload))) + .encode(); + return true; +} + void WidevineProvisioner::InitializeCryptoInterface() { std::string oemcrypto_path; if (!wvcdm::Properties::GetOEMCryptoPath(&oemcrypto_path)) { diff --git a/libwvdrmengine/factory_upload_tool/src/WidevineRemotelyProvisionedComponent.cpp b/libwvdrmengine/factory_upload_tool/src/WidevineRemotelyProvisionedComponent.cpp index 6c9fe9c3..31432704 100644 --- a/libwvdrmengine/factory_upload_tool/src/WidevineRemotelyProvisionedComponent.cpp +++ b/libwvdrmengine/factory_upload_tool/src/WidevineRemotelyProvisionedComponent.cpp @@ -75,9 +75,10 @@ class Status { ScopedAStatus WidevineRemotelyProvisionedComponent::getHardwareInfo( RpcHardwareInfo* info) { - info->versionNumber = 1; + info->versionNumber = 3; info->rpcAuthorName = "Google"; info->supportedEekCurve = RpcHardwareInfo::CURVE_25519; + info->uniqueId = "Widevine Implementation"; return ScopedAStatus::ok(); } @@ -112,4 +113,23 @@ ScopedAStatus WidevineRemotelyProvisionedComponent::generateCertificateRequest( return ScopedAStatus::ok(); } +ScopedAStatus +WidevineRemotelyProvisionedComponent::generateCertificateRequestV2( + const std::vector& keysToSign, + const std::vector& challenge, std::vector* csr) { + if (!keysToSign.empty()) { + return Status("Invalid operation: Keys to sign must be empty."); + } + if (csr == nullptr) { + return Status("Parameter csr must not be null."); + } + if (provisioner_ == nullptr) { + provisioner_ = std::make_unique(); + } + if (!provisioner_->GenerateCertificateRequestV2(challenge, csr)) { + return Status("Failed to generate certificate request V2."); + } + return ScopedAStatus::ok(); +} + } // namespace aidl::android::hardware::security::keymint