// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary // source code may only be used and distributed under the Widevine License // Agreement. #include "properties_ce.h" #include #include #include #include #include "cdm_version.h" #include "compiler_detection.h" #include "log.h" #include "properties.h" #include "read_client_info.h" #include "string_format.h" // This anonymous namespace is shared between both the widevine namespace and // wvcdm namespace objects below. namespace { bool use_secure_buffers_ = false; bool use_fifo_ = false; bool use_userspace_buffers_ = true; bool set_provisioning_messages_to_binary_ = false; std::string sandbox_id_; widevine::Cdm::SecureOutputType secure_output_type_ = widevine::Cdm::kNoSecureOutput; bool client_info_is_valid_; std::string company_name_; std::string model_name_; std::string model_year_; std::string product_name_; std::string device_name_; std::string arch_name_; std::string build_info_; bool isClientInfoFieldValid(const char* tag, const char* value) { constexpr char kForbiddenSeparator[] = " | "; constexpr char kForbiddenPercent[] = "%"; if (value[0] == '\0') { LOGE("%s may not be empty, but it is.", tag); return false; } if (strstr(value, kForbiddenSeparator) != nullptr) { LOGE("%s may not contain \"%s\", but it's \"%s\"", tag, kForbiddenSeparator, value); return false; } if (strstr(value, kForbiddenPercent) != nullptr) { LOGE("%s may not contain \"%s\", but it's \"%s\"", tag, kForbiddenPercent, value); return false; } return true; } void SetClientInfo() { std::string platform; std::string form_factor; std::string version; #if defined(RUNTIME_CLIENT_INFO) if (!widevine::ReadClientInformation( &company_name_, &model_name_, &model_year_, &product_name_, &device_name_, &arch_name_, &platform, &form_factor, &version)) { LOGE("ReadClientInformation failed."); client_info_is_valid_ = false; return; } if (!(isClientInfoFieldValid("company_name", company_name_.c_str()) && isClientInfoFieldValid("model_name", model_name_.c_str()) && isClientInfoFieldValid("model_year", model_year_.c_str()) && isClientInfoFieldValid("product_name", product_name_.c_str()) && isClientInfoFieldValid("device_name", device_name_.c_str()) && isClientInfoFieldValid("arch_name", arch_name_.c_str()) && isClientInfoFieldValid("platform", platform.c_str()) && isClientInfoFieldValid("form_factor", form_factor.c_str()) && isClientInfoFieldValid("version", version.c_str()))) { client_info_is_valid_ = false; return; } #else if (!(isClientInfoFieldValid("CLIENT_COMPANY_NAME", CLIENT_COMPANY_NAME) && isClientInfoFieldValid("CLIENT_MODEL_NAME", CLIENT_MODEL_NAME) && isClientInfoFieldValid("CLIENT_MODEL_YEAR", CLIENT_MODEL_YEAR) && isClientInfoFieldValid("CLIENT_PRODUCT_NAME", CLIENT_PRODUCT_NAME) && isClientInfoFieldValid("CLIENT_DEVICE_NAME", CLIENT_DEVICE_NAME) && isClientInfoFieldValid("CLIENT_ARCH_NAME", CLIENT_ARCH_NAME) && isClientInfoFieldValid("CLIENT_PLATFORM", CLIENT_PLATFORM) && isClientInfoFieldValid("CLIENT_FORM_FACTOR", CLIENT_FORM_FACTOR) && isClientInfoFieldValid("CLIENT_VERSION", CLIENT_VERSION))) { client_info_is_valid_ = false; return; } company_name_ = CLIENT_COMPANY_NAME; model_name_ = CLIENT_MODEL_NAME; model_year_ = CLIENT_MODEL_YEAR; product_name_ = CLIENT_PRODUCT_NAME; device_name_ = CLIENT_DEVICE_NAME; arch_name_ = CLIENT_ARCH_NAME; platform = CLIENT_PLATFORM; form_factor = CLIENT_FORM_FACTOR; version = CLIENT_VERSION; #endif if (!wvutil::FormatString( &build_info_, "%s | %s | %s | %s | CE CDM %s | %s | %s | %s", version.c_str(), platform.c_str(), form_factor.c_str(), arch_name_.c_str(), CDM_VERSION, CPU_ARCH_MESSAGE, LOGGING_MESSAGE, BUILD_FLAVOR_MESSAGE)) { client_info_is_valid_ = false; LOGE("Formatting the build info failed."); } else { client_info_is_valid_ = true; } } bool GetValue(const char* source, std::string* output) { if (!source || !output) { return false; } *output = source; return source[0] != '\0'; } } // namespace namespace widevine { // static void PropertiesCE::SetSecureOutputType( Cdm::SecureOutputType secure_output_type) { secure_output_type_ = secure_output_type; switch (secure_output_type) { case Cdm::kOpaqueHandle: use_secure_buffers_ = true; use_fifo_ = false; use_userspace_buffers_ = false; break; case Cdm::kDirectRender: use_secure_buffers_ = false; use_fifo_ = true; use_userspace_buffers_ = false; break; case Cdm::kNoSecureOutput: default: use_secure_buffers_ = false; use_fifo_ = false; use_userspace_buffers_ = true; break; } } // static Cdm::SecureOutputType PropertiesCE::GetSecureOutputType() { return secure_output_type_; } // static void PropertiesCE::SetProvisioningMessagesAreBinary(bool new_setting) { set_provisioning_messages_to_binary_ = new_setting; } // static void PropertiesCE::SetSandboxId(const std::string& sandbox_id) { sandbox_id_ = sandbox_id; } // static bool PropertiesCE::ClientInfoIsValid() { return client_info_is_valid_; } } // namespace widevine namespace wvcdm { // static void Properties::InitOnce() { oem_crypto_use_secure_buffers_ = use_secure_buffers_; oem_crypto_use_fifo_ = use_fifo_; oem_crypto_use_userspace_buffers_ = use_userspace_buffers_; provisioning_messages_are_binary_ = set_provisioning_messages_to_binary_; allow_service_certificate_requests_ = false; device_files_is_a_real_filesystem_ = false; allow_restore_of_offline_licenses_with_release_ = true; delay_oem_crypto_termination_ = false; SetClientInfo(); { std::unique_lock lock(session_mutex_); session_property_set_.reset(new CdmClientPropertySetMap()); } } // static bool Properties::GetCompanyName(std::string* company_name) { return GetValue(company_name_.c_str(), company_name); } // static bool Properties::GetModelName(std::string* model_name) { return GetValue(model_name_.c_str(), model_name); } // static bool Properties::GetModelYear(std::string* model_year) { return GetValue(model_year_.c_str(), model_year); } // static bool Properties::GetArchitectureName(std::string* arch_name) { return GetValue(arch_name_.c_str(), arch_name); } // static bool Properties::GetDeviceName(std::string* device_name) { return GetValue(device_name_.c_str(), device_name); } // static bool Properties::GetProductName(std::string* product_name) { return GetValue(product_name_.c_str(), product_name); } // static bool Properties::GetBuildInfo(std::string* build_info) { return GetValue(build_info_.c_str(), build_info); } // static bool Properties::GetWVCdmVersion(std::string* version) { return GetValue(CDM_VERSION, version); } // static bool Properties::GetDeviceFilesBasePath(CdmSecurityLevel, std::string* base_path) { if (base_path == nullptr) return false; // A no-op, but successful. base_path->clear(); return true; } // static bool Properties::GetFactoryKeyboxPath(std::string*) { // Unused on CE devices. return false; } // static bool Properties::GetOEMCryptoPaths(std::vector* paths) { if (paths == nullptr) return false; // Using an environment variable is useful for testing. const char* env_path = getenv("LIBOEMCRYPTO_PATH"); if (env_path) { paths->push_back(std::string(env_path)); } else { paths->push_back(std::string("liboemcrypto.so")); } return true; } // static bool Properties::GetSandboxId(std::string* sandbox_id_ptr) { if (sandbox_id_.empty() || sandbox_id_ptr == nullptr) return false; (*sandbox_id_ptr) = sandbox_id_; return true; } // static bool Properties::AlwaysUseKeySetIds() { return true; } // static bool Properties::UseProviderIdInProvisioningRequest() { return true; } } // namespace wvcdm