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
This commit is contained in:
Cong Lin
2023-02-19 17:38:25 -08:00
parent e8add8eed8
commit 8dc7cc0c74
6 changed files with 130 additions and 53 deletions

View File

@@ -13,13 +13,6 @@
namespace widevine {
struct VerifiedDeviceInfo {
std::vector<uint8_t> device_info;
// Used by Interface of Remote Provisioning Component (IRPC) v3 for CSR
// uploading
std::vector<uint8_t> 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<uint8_t>& verified_device_info);
// Generates device registration CSR payload and signs it with the leaf cert
// of BCC.
OEMCryptoResult GetSignedCsrPayload(const std::vector<uint8_t>& challenge,
const std::vector<uint8_t>& device_info,
std::vector<uint8_t>& 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;
};

View File

@@ -27,6 +27,8 @@ class WidevineProvisioner {
bool GenerateCertificateRequest(
bool testMode, const std::vector<uint8_t>& endpointEncCertChain,
std::vector<uint8_t>& deviceInfo, std::vector<uint8_t>& protectedData);
bool GenerateCertificateRequestV2(const std::vector<uint8_t>& challenge,
std::vector<uint8_t>* csr);
private:
bool GetDeviceInfo(std::vector<uint8_t>& 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<OEMCryptoInterface> crypto_interface_;
};

View File

@@ -49,11 +49,9 @@ class WidevineRemotelyProvisionedComponent
std::vector<uint8_t>* keysToSignMac) override;
ScopedAStatus generateCertificateRequestV2(
const std::vector<MacedPublicKey>& /* keysToSign */,
const std::vector<uint8_t>& /* challenge */,
std::vector<uint8_t>* /* csr */) override {
return ScopedAStatus::fromExceptionCode(EX_UNSUPPORTED_OPERATION);
}
const std::vector<MacedPublicKey>& keysToSign,
const std::vector<uint8_t>& challenge,
std::vector<uint8_t>* csr) override;
private:
std::unique_ptr<widevine::WidevineProvisioner> provisioner_;

View File

@@ -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<uint8_t>& 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<uint8_t>& challenge,
const std::vector<uint8_t>& device_info,
std::vector<uint8_t>& 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;
}

View File

@@ -49,7 +49,7 @@ bool WidevineProvisioner::GenerateCertificateRequest(
std::vector<uint8_t> 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<uint8_t> 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<const uint8_t*>(verified_device_info.device_info.data()),
verified_device_info.device_info.size());
reinterpret_cast<const uint8_t*>(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<uint8_t>& 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<uint8_t>& challenge, std::vector<uint8_t>* csr) {
if (csr == nullptr) {
LOGE("CSR is null.");
return false;
}
// Prepare BCC
std::vector<uint8_t> 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<uint8_t> 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)) {

View File

@@ -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<MacedPublicKey>& keysToSign,
const std::vector<uint8_t>& challenge, std::vector<uint8_t>* 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<widevine::WidevineProvisioner>();
}
if (!provisioner_->GenerateCertificateRequestV2(challenge, csr)) {
return Status("Failed to generate certificate request V2.");
}
return ScopedAStatus::ok();
}
} // namespace aidl::android::hardware::security::keymint