// 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 #include "OEMCryptoCENC.h" #include "clock.h" #include "file_store.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(LOOKUP(handle_, OEMCrypto_##name)); \ if (name == nullptr) { \ 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. namespace wvutil { int64_t Clock::GetCurrentTime() { return 0; } class FileImpl final : public File { public: FileImpl() {} ssize_t Read(char*, size_t) override { return 0; } ssize_t Write(const char*, size_t) override { return 0; } }; class FileSystem::Impl { public: Impl() {} }; FileSystem::FileSystem() {} FileSystem::FileSystem(const std::string&, void*) {} FileSystem::~FileSystem() {} std::unique_ptr FileSystem::Open(const std::string&, int) { return std::unique_ptr(new FileImpl()); } bool FileSystem::Exists(const std::string&) { return false; } bool FileSystem::Remove(const std::string&) { return false; } ssize_t FileSystem::FileSize(const std::string&) { return false; } bool FileSystem::List(const std::string&, std::vector*) { return false; } } // namespace wvutil 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); OEMCryptoResult status = Initialize(); if (status != OEMCrypto_SUCCESS) { LOGE("OEMCrypto Initialize failed: %d", status); return false; } return true; } OEMCryptoResult OEMCryptoInterface::GetBcc(std::vector& bcc) { if (handle_ == nullptr) { return OEMCrypto_ERROR_INIT_FAILED; } bcc.resize(0); size_t bcc_size = 0; std::vector 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( 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