123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290 |
- // Copyright 2016 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "components/cdm/renderer/widevine_key_system_properties.h"
- #include "base/command_line.h"
- #include "base/feature_list.h"
- #include "build/build_config.h"
- #include "build/chromeos_buildflags.h"
- #include "media/base/media_switches.h"
- #include "media/media_buildflags.h"
- #include "third_party/widevine/cdm/buildflags.h"
- #include "third_party/widevine/cdm/widevine_cdm_common.h"
- #if !BUILDFLAG(ENABLE_WIDEVINE)
- #error This file should only be built when Widevine is enabled.
- #endif
- using media::CdmSessionType;
- using media::EmeConfig;
- using media::EmeConfigRuleState;
- using media::EmeFeatureSupport;
- using media::EmeInitDataType;
- using media::EmeMediaType;
- using media::EncryptionScheme;
- using media::SupportedCodecs;
- using Robustness = cdm::WidevineKeySystemProperties::Robustness;
- namespace cdm {
- namespace {
- Robustness ConvertRobustness(const std::string& robustness) {
- if (robustness.empty())
- return Robustness::EMPTY;
- if (robustness == "SW_SECURE_CRYPTO")
- return Robustness::SW_SECURE_CRYPTO;
- if (robustness == "SW_SECURE_DECODE")
- return Robustness::SW_SECURE_DECODE;
- if (robustness == "HW_SECURE_CRYPTO")
- return Robustness::HW_SECURE_CRYPTO;
- if (robustness == "HW_SECURE_DECODE")
- return Robustness::HW_SECURE_DECODE;
- if (robustness == "HW_SECURE_ALL")
- return Robustness::HW_SECURE_ALL;
- return Robustness::INVALID;
- }
- #if BUILDFLAG(IS_WIN)
- bool IsHardwareSecurityEnabledForKeySystem(const std::string& key_system) {
- return (key_system == kWidevineKeySystem &&
- base::FeatureList::IsEnabled(media::kHardwareSecureDecryption)) ||
- (key_system == kWidevineExperimentKeySystem &&
- base::FeatureList::IsEnabled(
- media::kHardwareSecureDecryptionExperiment));
- }
- #endif // BUILDFLAG(IS_WIN)
- } // namespace
- WidevineKeySystemProperties::WidevineKeySystemProperties(
- SupportedCodecs codecs,
- base::flat_set<EncryptionScheme> encryption_schemes,
- base::flat_set<CdmSessionType> session_types,
- SupportedCodecs hw_secure_codecs,
- base::flat_set<EncryptionScheme> hw_secure_encryption_schemes,
- base::flat_set<CdmSessionType> hw_secure_session_types,
- Robustness max_audio_robustness,
- Robustness max_video_robustness,
- EmeFeatureSupport persistent_state_support,
- EmeFeatureSupport distinctive_identifier_support)
- : codecs_(codecs),
- encryption_schemes_(std::move(encryption_schemes)),
- session_types_(std::move(session_types)),
- hw_secure_codecs_(hw_secure_codecs),
- hw_secure_encryption_schemes_(std::move(hw_secure_encryption_schemes)),
- hw_secure_session_types_(std::move(hw_secure_session_types)),
- max_audio_robustness_(max_audio_robustness),
- max_video_robustness_(max_video_robustness),
- persistent_state_support_(persistent_state_support),
- distinctive_identifier_support_(distinctive_identifier_support) {}
- WidevineKeySystemProperties::~WidevineKeySystemProperties() = default;
- std::string WidevineKeySystemProperties::GetBaseKeySystemName() const {
- return kWidevineKeySystem;
- }
- bool WidevineKeySystemProperties::IsSupportedKeySystem(
- const std::string& key_system) const {
- #if BUILDFLAG(IS_WIN)
- if (key_system == kWidevineExperimentKeySystem &&
- base::FeatureList::IsEnabled(
- media::kHardwareSecureDecryptionExperiment)) {
- return true;
- }
- #endif // BUILDFLAG(IS_WIN)
- return key_system == kWidevineKeySystem;
- }
- bool WidevineKeySystemProperties::ShouldUseBaseKeySystemName() const {
- // Internally Widevine CDM only supports kWidevineKeySystem.
- return true;
- }
- bool WidevineKeySystemProperties::IsSupportedInitDataType(
- EmeInitDataType init_data_type) const {
- // Here we assume that support for a container implies support for the
- // associated initialization data type. KeySystems handles validating
- // |init_data_type| x |container| pairings.
- if (init_data_type == EmeInitDataType::WEBM)
- return (codecs_ & media::EME_CODEC_WEBM_ALL) != 0;
- if (init_data_type == EmeInitDataType::CENC)
- return (codecs_ & media::EME_CODEC_MP4_ALL) != 0;
- return false;
- }
- EmeConfig::Rule WidevineKeySystemProperties::GetEncryptionSchemeConfigRule(
- EncryptionScheme encryption_scheme) const {
- bool is_supported = encryption_schemes_.contains(encryption_scheme);
- bool is_hw_secure_supported =
- hw_secure_encryption_schemes_.contains(encryption_scheme);
- if (is_supported && is_hw_secure_supported) {
- return EmeConfig::SupportedRule();
- } else if (is_supported && !is_hw_secure_supported) {
- return EmeConfig{.hw_secure_codecs = EmeConfigRuleState::kNotAllowed};
- } else if (!is_supported && is_hw_secure_supported) {
- return EmeConfig{.hw_secure_codecs = EmeConfigRuleState::kRequired};
- } else {
- return media::EmeConfig::UnsupportedRule();
- }
- }
- SupportedCodecs WidevineKeySystemProperties::GetSupportedCodecs() const {
- return codecs_;
- }
- SupportedCodecs WidevineKeySystemProperties::GetSupportedHwSecureCodecs()
- const {
- return hw_secure_codecs_;
- }
- EmeConfig::Rule WidevineKeySystemProperties::GetRobustnessConfigRule(
- const std::string& key_system,
- EmeMediaType media_type,
- const std::string& requested_robustness,
- const bool* hw_secure_requirement) const {
- Robustness robustness = ConvertRobustness(requested_robustness);
- if (robustness == Robustness::INVALID) {
- return EmeConfig::UnsupportedRule();
- }
- Robustness max_robustness = Robustness::INVALID;
- switch (media_type) {
- case EmeMediaType::AUDIO:
- max_robustness = max_audio_robustness_;
- break;
- case EmeMediaType::VIDEO:
- max_robustness = max_video_robustness_;
- break;
- }
- // We can compare robustness levels whenever they are not HW_SECURE_CRYPTO
- // and SW_SECURE_DECODE in some order. If they are exactly those two then the
- // robustness requirement is not supported.
- if ((max_robustness == Robustness::HW_SECURE_CRYPTO &&
- robustness == Robustness::SW_SECURE_DECODE) ||
- (max_robustness == Robustness::SW_SECURE_DECODE &&
- robustness == Robustness::HW_SECURE_CRYPTO) ||
- robustness > max_robustness) {
- return media::EmeConfig::UnsupportedRule();
- }
- [[maybe_unused]] bool hw_secure_codecs_required =
- hw_secure_requirement && *hw_secure_requirement;
- #if BUILDFLAG(IS_CHROMEOS)
- // Hardware security requires HWDRM or remote attestation, both of these
- // require an identifier.
- if (robustness >= Robustness::HW_SECURE_CRYPTO || hw_secure_codecs_required) {
- #if BUILDFLAG(USE_CHROMEOS_PROTECTED_MEDIA)
- #if BUILDFLAG(IS_CHROMEOS_LACROS)
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kLacrosUseChromeosProtectedMedia)) {
- return EmeConfig{.identifier = EmeConfigRuleState::kRequired};
- }
- #endif // BUILDFLAG(IS_CHROMEOS_LACROS)
- return EmeConfig{.identifier = EmeConfigRuleState::kRequired,
- .hw_secure_codecs = EmeConfigRuleState::kRequired};
- #else
- return EmeConfig{.identifier = EmeConfigRuleState::kRequired};
- #endif
- }
- // For video, recommend remote attestation if HW_SECURE_ALL is available,
- // regardless of the value of |robustness|, because it enables hardware
- // accelerated decoding.
- // TODO(sandersd): Only do this when hardware accelerated decoding is
- // available for the requested codecs.
- if (media_type == EmeMediaType::VIDEO &&
- max_robustness == Robustness::HW_SECURE_ALL) {
- return EmeConfig{.identifier = EmeConfigRuleState::kRecommended};
- }
- #elif BUILDFLAG(IS_ANDROID)
- // On Android, require hardware secure codecs for SW_SECURE_DECODE and above.
- if (robustness >= Robustness::SW_SECURE_DECODE || hw_secure_codecs_required) {
- return EmeConfig{.hw_secure_codecs = EmeConfigRuleState::kRequired};
- }
- #elif BUILDFLAG(IS_WIN)
- if (robustness >= Robustness::HW_SECURE_CRYPTO) {
- // On Windows, hardware security uses MediaFoundation-based CDM which
- // requires identifier and persistent state.
- if (IsHardwareSecurityEnabledForKeySystem(key_system)) {
- return EmeConfig{.identifier = EmeConfigRuleState::kRequired,
- .persistence = EmeConfigRuleState::kRequired,
- .hw_secure_codecs = EmeConfigRuleState::kRequired};
- } else {
- return media::EmeConfig::UnsupportedRule();
- }
- } else if (robustness < Robustness::HW_SECURE_CRYPTO) {
- // On Windows, when software security is queried, explicitly not allow
- // hardware secure codecs to prevent robustness level upgrade, for stability
- // and compatibility reasons. See https://crbug.com/1327043.
- return EmeConfig{.hw_secure_codecs = EmeConfigRuleState::kNotAllowed};
- }
- #else
- // On other platforms, require hardware secure codecs for HW_SECURE_CRYPTO and
- // above.
- if (robustness >= Robustness::HW_SECURE_CRYPTO) {
- return EmeConfig{.hw_secure_codecs = EmeConfigRuleState::kRequired};
- }
- #endif // BUILDFLAG(IS_CHROMEOS)
- return media::EmeConfig::SupportedRule();
- }
- EmeConfig::Rule
- WidevineKeySystemProperties::GetPersistentLicenseSessionSupport() const {
- bool is_supported =
- session_types_.contains(CdmSessionType::kPersistentLicense);
- #if BUILDFLAG(IS_CHROMEOS)
- // The logic around hardware/software security support is complicated on
- // ChromeOS. This code is to preserve the original logic, by deciding the
- // support only based on `is_supported` and ignore `is_hw_secure_supported`.
- // Note: On ChromeOS, platform verification (similar to CDM host verification)
- // is required for persistent license support, which requires identifier.
- // TODO(crbug.com/1324262): Fix the logic after refactoring EmeConfig.
- if (is_supported) {
- return EmeConfig{.identifier = EmeConfigRuleState::kRequired,
- .persistence = EmeConfigRuleState::kRequired};
- } else {
- return media::EmeConfig::UnsupportedRule();
- }
- #else // BUILDFLAG(IS_CHROMEOS)
- bool is_hw_secure_supported =
- hw_secure_session_types_.contains(CdmSessionType::kPersistentLicense);
- // Per GetPersistentLicenseSessionSupport() API, there's no need to specify
- // the PERSISTENCE requirement here, which is implicitly assumed and enforced
- // by `KeySystemConfigSelector`.
- if (is_supported && is_hw_secure_supported) {
- return EmeConfig::SupportedRule();
- } else if (is_supported && !is_hw_secure_supported) {
- return EmeConfig{.hw_secure_codecs = EmeConfigRuleState::kNotAllowed};
- } else if (!is_supported && is_hw_secure_supported) {
- return EmeConfig{.hw_secure_codecs = EmeConfigRuleState::kRequired};
- } else {
- return media::EmeConfig::UnsupportedRule();
- }
- #endif // BUILDFLAG(IS_CHROMEOS)
- }
- EmeFeatureSupport WidevineKeySystemProperties::GetPersistentStateSupport()
- const {
- return persistent_state_support_;
- }
- EmeFeatureSupport WidevineKeySystemProperties::GetDistinctiveIdentifierSupport()
- const {
- return distinctive_identifier_support_;
- }
- } // namespace cdm
|