This tool was supposed to be used for internal debugging purpose on Android devices. It already supports RKP uploading CSR format. Extend this tool to support Widevine uploading format: JSON csr and make this format as default output for AOSP (non-GMS) partners. A later change will move it to its own aosp/ directory. Test: run "wv_factory_extraction_tool json_csr" on Pixel 9 Bug: 414642286 Change-Id: I9cf4e9696d32201cc1ad70b6bee7932f7126a4ba
167 lines
5.7 KiB
C++
167 lines
5.7 KiB
C++
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
|
|
// source code may only be used and distributed under the Widevine License
|
|
// Agreement.
|
|
|
|
#include "WidevineOemcryptoInterface.h"
|
|
|
|
#include <dlfcn.h>
|
|
|
|
#include "OEMCryptoCENC.h"
|
|
#include "log.h"
|
|
|
|
// These macros lookup the obfuscated name used for OEMCrypto.
|
|
#define QUOTE_DEFINE(A) #A
|
|
#define QUOTE(A) QUOTE_DEFINE(A)
|
|
#define LOOKUP(handle, name) dlsym(handle, QUOTE(name))
|
|
#define LOAD_SYM(name) \
|
|
name = reinterpret_cast<name##_t>(LOOKUP(handle_, OEMCrypto_##name)); \
|
|
if (name == nullptr) { \
|
|
LOGE("%s", dlerror()); \
|
|
return false; \
|
|
}
|
|
#define LOAD_SYM_IF_EXIST(name) \
|
|
name = reinterpret_cast<name##_t>(LOOKUP(handle_, OEMCrypto_##name));
|
|
|
|
namespace widevine {
|
|
|
|
OEMCryptoInterface::~OEMCryptoInterface() {
|
|
if (Terminate != nullptr) {
|
|
Terminate();
|
|
}
|
|
if (handle_ != nullptr) {
|
|
dlclose(handle_);
|
|
}
|
|
}
|
|
|
|
bool OEMCryptoInterface::Init(const std::string& oemcrypto_path) {
|
|
dlerror();
|
|
handle_ = dlopen(oemcrypto_path.c_str(), RTLD_LAZY | RTLD_GLOBAL);
|
|
if (handle_ == nullptr) {
|
|
LOGE("Can't open OEMCrypto library: %s", dlerror());
|
|
return false;
|
|
}
|
|
LOGI("OEMCrypto library opened.");
|
|
|
|
LOAD_SYM(Initialize);
|
|
LOAD_SYM(Terminate);
|
|
LOAD_SYM(GetBootCertificateChain);
|
|
LOAD_SYM(BuildInformation);
|
|
LOAD_SYM_IF_EXIST(GetDeviceInformation);
|
|
LOAD_SYM_IF_EXIST(GetDeviceSignedCsrPayload);
|
|
|
|
OEMCryptoResult status = Initialize();
|
|
if (status != OEMCrypto_SUCCESS) {
|
|
LOGE("OEMCrypto Initialize failed: %d", status);
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
OEMCryptoResult OEMCryptoInterface::GetBcc(std::vector<uint8_t>& bcc) {
|
|
if (handle_ == nullptr) {
|
|
return OEMCrypto_ERROR_INIT_FAILED;
|
|
}
|
|
|
|
bcc.resize(0);
|
|
size_t bcc_size = 0;
|
|
|
|
std::vector<uint8_t> additional_signature; // It should be empty.
|
|
size_t additional_signature_size = 0;
|
|
OEMCryptoResult result = GetBootCertificateChain(bcc.data(), &bcc_size,
|
|
additional_signature.data(),
|
|
&additional_signature_size);
|
|
LOGI("GetBootCertificateChain first attempt result %d", result);
|
|
if (additional_signature_size != 0) {
|
|
LOGW(
|
|
"The additional_signature_size required by OEMCrypto is %zu, while it "
|
|
"is expected to be zero.",
|
|
additional_signature_size);
|
|
}
|
|
|
|
if (result == OEMCrypto_ERROR_SHORT_BUFFER) {
|
|
bcc.resize(bcc_size);
|
|
additional_signature.resize(additional_signature_size);
|
|
result = GetBootCertificateChain(bcc.data(), &bcc_size,
|
|
additional_signature.data(),
|
|
&additional_signature_size);
|
|
if (result == OEMCrypto_SUCCESS) bcc.resize(bcc_size);
|
|
LOGI("GetBootCertificateChain second attempt result %d", result);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
OEMCryptoResult OEMCryptoInterface::GetOEMCryptoBuildInfo(
|
|
std::string& build_info) {
|
|
if (handle_ == nullptr) {
|
|
return OEMCrypto_ERROR_INIT_FAILED;
|
|
}
|
|
|
|
build_info.resize(0);
|
|
size_t build_info_size = 0;
|
|
|
|
OEMCryptoResult result = BuildInformation(&build_info[0], &build_info_size);
|
|
LOGI("BuildInformation first attempt result %d", result);
|
|
if (result == OEMCrypto_ERROR_SHORT_BUFFER) {
|
|
build_info.resize(build_info_size);
|
|
result = BuildInformation(&build_info[0], &build_info_size);
|
|
LOGI("BuildInformation second attempt result %d", result);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
OEMCryptoResult OEMCryptoInterface::GetVerifiedDeviceInformation(
|
|
std::vector<uint8_t>& verified_device_info) {
|
|
if (handle_ == nullptr) {
|
|
return OEMCrypto_ERROR_INIT_FAILED;
|
|
}
|
|
if (GetDeviceInformation == nullptr) {
|
|
return OEMCrypto_ERROR_NOT_IMPLEMENTED;
|
|
}
|
|
|
|
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.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;
|
|
}
|
|
|
|
} // namespace widevine
|