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:
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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_;
|
||||
};
|
||||
|
||||
@@ -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_;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user