Revert "Cherry pick 18.4 changes to udc-widevine-dev"

This reverts commit 7186433edf.

Reason for revert: Build breakage - b/323194350

Change-Id: Ibba4f5289b8f0d5e835dfba9ceb1e601784af634
This commit is contained in:
Kensuke Miyagi
2024-01-31 18:13:05 +00:00
committed by Android (Google) Code Review
parent 7186433edf
commit 540c8dfd50
98 changed files with 258 additions and 135280 deletions

View File

@@ -1,327 +0,0 @@
# Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
# source code may only be used and distributed under the Widevine License
# Agreement.
#
# Refer to the distribution package's integration guide for information about
# setting up your system, performing the build, and using/testing the build
# targets.
{
'includes': [
'platform_properties.gypi',
'core.gypi',
'util.gypi',
], # Get list of core source files.
'variables': {
'has_dual_key%': 'false',
'embedded_cert%': '',
},
'targets': [
{
'toolsets' : [ 'target' ],
'target_name': 'license_protocol',
'type': 'static_library',
'standalone_static_library': 1,
'hard_dependency': 1,
'includes': ['../third_party/disable_warnings.gypi'],
'dependencies': [ '<(proto_gen_gyp_path):generate_license_protocol' ],
'sources': [
'<(proto_cc_dir)/license_protocol.pb.cc'
],
'include_dirs': [
'<(proto_cc_dir)',
'<(DEPTH)/third_party/protobuf/src'
],
'direct_dependent_settings': {
'include_dirs': [
'<(proto_cc_dir)',
'<(DEPTH)/third_party/protobuf/src'
]
},
},
{
'toolsets' : [ 'target' ],
'target_name': 'device_files',
'type': 'static_library',
'standalone_static_library': 1,
'hard_dependency': 1,
'includes': ['../third_party/disable_warnings.gypi'],
'dependencies': [ '<(proto_gen_gyp_path):generate_device_files' ],
'sources': [
'<(proto_cc_dir)/device_files.pb.cc'
],
'include_dirs': [
'<(proto_cc_dir)',
'<(DEPTH)/third_party/protobuf/src'
],
'direct_dependent_settings': {
'include_dirs': [
'<(proto_cc_dir)',
'<(DEPTH)/third_party/protobuf/src'
]
},
},
{
'toolsets' : [ 'target' ],
'target_name': 'metrics_proto',
'type': 'static_library',
'standalone_static_library': 1,
'hard_dependency': 1,
'includes': ['../third_party/disable_warnings.gypi'],
'dependencies': [ '<(proto_gen_gyp_path):generate_metrics_proto' ],
'sources': [
'<(proto_cc_dir)/wv_metrics.pb.cc'
],
'include_dirs': [
'<(proto_cc_dir)',
'<(DEPTH)/third_party/protobuf/src'
],
'direct_dependent_settings': {
'include_dirs': [
'<(proto_cc_dir)',
'<(DEPTH)/third_party/protobuf/src'
]
},
},
{
'toolsets' : [ 'target' ],
'target_name': 'widevine_utils',
'type': 'static_library',
'standalone_static_library': 1,
'hard_dependency': 1,
'include_dirs': [
'../util/include',
],
'sources': [ '<@(wvutil_sources)'],
},
{
'toolsets' : [ 'target' ],
'target_name': 'widevine_cdm_core',
'type': 'static_library',
'standalone_static_library': 1,
'hard_dependency': 1,
'dependencies': [
'device_files',
'license_protocol',
'metrics_proto',
'widevine_utils',
],
'include_dirs': [
'../core/include',
'../metrics/include',
'../oemcrypto/include',
'../oemcrypto/odk/include',
'../third_party/jsmn',
'../util/include',
],
'direct_dependent_settings': {
'include_dirs': [
'../core/include',
'../metrics/include',
'../oemcrypto/include',
'../util/include',
],
},
'sources': [
'<@(wvcdm_sources)',
'../third_party/jsmn/jsmn.h',
'../third_party/jsmn/jsmn.c',
],
'includes': [ '../util/libcrypto_dependency.gypi' ],
'conditions': [
['client_info_source=="compiled"', {
'conditions': [
['client_company_name=="" or " | " in client_company_name or "%" in client_company_name', {
'sources': [ 'invalid_client_company_name.c' ],
}],
['client_model_name=="" or " | " in client_model_name or "%" in client_model_name', {
'sources': [ 'invalid_client_model_name.c' ],
}],
# year may be a number, so use __str__ to convert to string. Can't use
# str() since we can't use global functions.
['client_model_year=="" or " | " in client_model_year.__str__() or "%" in client_model_year.__str__()', {
'sources': [ 'invalid_client_model_year.c' ],
}],
['client_product_name=="" or " | " in client_product_name or "%" in client_product_name', {
'sources': [ 'invalid_client_product_name.c' ],
}],
['client_device_name=="" or " | " in client_device_name or "%" in client_device_name', {
'sources': [ 'invalid_client_device_name.c' ],
}],
['client_arch_name=="" or " | " in client_arch_name or "%" in client_arch_name', {
'sources': [ 'invalid_client_arch_name.c' ],
}],
['client_platform=="" or " | " in client_platform or "%" in client_platform', {
'sources': [ 'invalid_client_platform.c' ],
}],
['client_form_factor=="" or " | " in client_form_factor or "%" in client_form_factor', {
'sources': [ 'invalid_client_form_factor.c' ],
}],
['client_version=="" or " | " in client_version or "%" in client_version', {
'sources': [ 'invalid_client_version.c' ],
}],
],
}],
['privacy_crypto_impl=="boringssl" or privacy_crypto_impl=="openssl"', {
'sources': [
'../core/src/privacy_crypto_boringssl.cpp',
],
}, { # else
'sources': [
'../core/src/privacy_crypto_<(privacy_crypto_impl).cpp',
],
'conditions': [
['privacy_crypto_impl=="apple"', {
'link_settings': {
'libraries': [
'$(SDKROOT)/System/Library/Frameworks/Foundation.framework',
'$(SDKROOT)/System/Library/Frameworks/Security.framework',
],
},
}],
],
}], # end else
['oemcrypto_adapter_type=="dynamic"', {
'sources': [
'../core/src/oemcrypto_adapter_dynamic.cpp',
],
}],
['oemcrypto_adapter_type=="static"', {
'sources': [
'../core/src/oemcrypto_adapter_static.cpp',
],
}],
['oemcrypto_adapter_type=="static_v16"', {
'sources': [
'../core/src/oemcrypto_adapter_static.cpp',
'../core/src/oemcrypto_adapter_static_v17.cpp',
],
}],
['has_dual_key=="true"', {
'defines': ['HAS_DUAL_KEY'],
}],
['support_ota_keybox_functions=="false"', {
'sources': [
'../core/src/oemcrypto_ota_stubs.cpp',
],
}],
],
}, # widevine_cdm_core target
{
# This is the widevine_ce_cdm built as a static library. This name does
# not mean that it uses oemcrypto's static adapter. Control over which
# adapter is used comes from the settings file for the platform.
'toolsets' : [ 'target' ],
'target_name': 'widevine_ce_cdm_static',
'type': 'static_library',
'standalone_static_library': 1,
'hard_dependency': 1,
'dependencies': [
'widevine_cdm_core',
'device_files',
'license_protocol',
'metrics_proto',
],
# Without this, library deps do not propagate from the protocol targets
# up to the shared lib or executable above.
'export_dependent_settings': [
'device_files',
'license_protocol',
'metrics_proto',
],
'defines': [
'CDM_IMPLEMENTATION',
],
'include_dirs': [
'include',
],
'direct_dependent_settings': {
'include_dirs': [
'include',
],
},
'sources': [
'include/cdm.h',
'include/cdm_version.h',
'include/properties_ce.h',
'src/cdm.cpp',
'src/log.cpp',
'src/logger_global.cpp',
'src/properties_ce.cpp',
],
'conditions': [
['embedded_cert!=""', {
'actions': [{
'action_name': 'generate_cert',
'msvs_cygwin_shell': 0,
'message': 'Generating cert.cc',
'inputs': [
'create_cert_cc.py',
'<(embedded_cert)',
],
'outputs': [
'<(INTERMEDIATE_DIR)/cert.cc',
],
'action': [
'python3',
'>@(_inputs)',
'>@(_outputs)',
],
}],
'sources': [
'<(INTERMEDIATE_DIR)/cert.cc',
],
'defines': ['HAS_EMBEDDED_CERT'],
}], # embedded_cert!=""
# This block defines preprocessor values that match the client
# information variables in platform properties.gypi. If you are writing
# your own build files to build CE CDM insted of using these GYP files
# and you are using compile-time client info, make sure to define these
# values, following the rules in the client info section in
# platform_properties.gypi.
['client_info_source=="compiled"', {
'defines': [
'CLIENT_COMPANY_NAME="<(client_company_name)"',
'CLIENT_MODEL_NAME="<(client_model_name)"',
'CLIENT_MODEL_YEAR="<(client_model_year)"',
'CLIENT_PRODUCT_NAME="<(client_product_name)"',
'CLIENT_DEVICE_NAME="<(client_device_name)"',
'CLIENT_ARCH_NAME="<(client_arch_name)"',
'CLIENT_PLATFORM="<(client_platform)"',
'CLIENT_FORM_FACTOR="<(client_form_factor)"',
'CLIENT_VERSION="<(client_version)"',
],
}], # client_info_source=="compiled"
['client_info_source=="runtime"', {
'defines': [
'RUNTIME_CLIENT_INFO',
],
'dependencies': [
'<(read_client_info_path)',
],
}], # client_info_source=="runtime"
], # conditions
}, # widevine_cdm_static target
{
'toolsets' : [ 'target' ],
'target_name': 'widevine_ce_cdm_shared',
'type': 'shared_library',
'dependencies': [
'widevine_ce_cdm_static',
],
'direct_dependent_settings': {
'include_dirs': [
'include',
],
},
},
{
'toolsets' : [ 'target' ],
'target_name': 'dummy',
'type': 'none',
},
],
}

View File

@@ -1,134 +0,0 @@
# Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
# source code may only be used and distributed under the Widevine License
# Agreement.
#
# Any top-level targets in this file (and their dependencies) will be built by
# the CE CDM's ./build.py build system. Refer to the distribution package's
# README for details.
{
'includes': [
'platform_properties.gypi',
],
'variables': {
# Directory where OEMCrypto header, test, and reference files lives.
'oemcrypto_dir': '../oemcrypto',
# Directory where widevine utilities live.
'util_dir': '../util',
'metrics_target': 'cdm.gyp:metrics_proto',
'device_files_target': 'cdm.gyp:device_files',
},
'targets': [{
'toolsets' : [ 'target' ],
'target_name': 'widevine_ce_cdm_reboot_tests',
'sources': [
'test/cdm_reboot_test_main.cpp',
'test/cdm_test_runner.cpp',
'test/create_test_file_system.cpp',
'test/test_host.cpp',
'test/test_host.h',
'../core/test/config_test_env.cpp',
'../core/test/fake_provisioning_server.cpp',
'../core/test/http_socket.cpp',
'../core/test/license_holder.cpp',
'../core/test/license_request.cpp',
'../core/test/message_dumper.cpp',
'../core/test/provisioning_holder.cpp',
'../core/test/reboot_test.cpp',
'../core/test/test_base.cpp',
'../core/test/test_printers.cpp',
'../core/test/url_request.cpp',
'../oemcrypto/test/oec_key_deriver.cpp',
'../oemcrypto/test/oec_device_features.cpp',
'../util/test/test_sleep.cpp',
],
'includes': [
'../oemcrypto/odk/src/kdo.gypi',
'../util/libssl_dependency.gypi',
],
'include_dirs': [
'../cdm/include',
'../core/include',
'../core/test',
'../metrics/include',
'../oemcrypto/test',
'../oemcrypto/include',
'../util/include',
'../util/test',
],
'dependencies': [
'cdm.gyp:widevine_ce_cdm_static',
'../oemcrypto/odk/src/odk.gyp:odk',
'../third_party/googletest.gyp:gmock',
'../third_party/googletest.gyp:gtest',
'<(metrics_target)',
'<(device_files_target)',
],
'defines': [
'UNIT_TEST',
'CDM_TESTS',
],
'msvs_settings': {
'VCLinkerTool': {
# Additionally, since they are loaded locally, suppress these
# warnings.
'AdditionalOptions': [
'/IGNORE:4049',
'/IGNORE:4217',
],
},
},
'conditions': [
['OS=="ios"', {
'type': 'loadable_module',
'mac_xctest_bundle': '1',
'defines': [
'GTEST_FILTER="<(gtest_filter)"',
],
'dependencies': [
'cdm_unittests.gyp:dummy_app',
],
'sources': [
'test/gtest_xctest_wrapper.mm',
],
'xcode_settings': {
'BUNDLE_LOADER': '$(TEST_HOST)',
'TEST_HOST': '<(PRODUCT_DIR)/dummy_app.app/dummy_app',
'WRAPPER_EXTENSION': 'xctest',
},
}, {
'type': 'executable',
}],
# TODO(b/139814713): For testing and internal use only.
['oemcrypto_adapter_type=="static_v15"', {
'defines': [
# This is used by the unit tests to use some v15 functions.
'TEST_OEMCRYPTO_V15',
],
}],
['oemcrypto_lib=="level3"', {
'sources': [
# The test impl of OEMCrypto_Level3FileSystem and its factory.
'test/level3_file_system_ce_test.h',
'test/level3_file_system_ce_test.cpp',
'test/level3_file_system_ce_test_factory.cpp',
],
'conditions': [
['oemcrypto_adapter_type=="dynamic" ', {
'dependencies': [
'../oemcrypto/level3/oec_level3.gyp:oec_level3_dynamic',
],
}, {
'dependencies': [
'../oemcrypto/level3/oec_level3.gyp:oec_level3_static',
],
}],
],
}],
['oemcrypto_lib=="target"', {
'dependencies': [
'<(oemcrypto_gyp_path)',
],
}],
],
}],
}

View File

@@ -1,242 +0,0 @@
# Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
# source code may only be used and distributed under the Widevine License
# Agreement.
#
# Any top-level targets in this file (and their dependencies) will be built by
# the CE CDM's ./build.py build system. Refer to the distribution package's
# README for details.
{
'includes': [
'platform_properties.gypi',
],
'variables': {
# Directory where OEMCrypto header, test, and reference files lives.
'oemcrypto_dir': '../oemcrypto',
# Directory where widevine utilities live.
'util_dir': '../util',
'metrics_target': 'cdm.gyp:metrics_proto',
'device_files_target': 'cdm.gyp:device_files',
# The path to the prebuilt CDM to test against. (iOS only)
'prebuilt_cdm_path%': '',
'supports_dynamic_perf_test%': 0,
'json_dir': '../third_party/nlohmann-json',
'jsmn_dir': '../third_party/jsmn',
},
'targets': [{
'toolsets' : [ 'target' ],
'target_name': 'widevine_ce_cdm_unittest',
'sources': [
'test/cdm_test_main.cpp',
'test/cdm_test_runner.cpp',
'test/create_test_file_system.cpp',
# The test host, which is required for all test suites on CE.
'test/test_host.cpp',
'test/test_host.h',
'../util/test/test_sleep.cpp',
],
'includes': [
'../oemcrypto/test/oemcrypto_unittests.gypi',
'../oemcrypto/odk/src/kdo.gypi',
'../oemcrypto/odk/test/odk_test.gypi',
'../oemcrypto/util/oec_ref_util_unittests.gypi',
'cdm_unittests.gypi',
'core_unittests.gypi',
'util_unittests.gypi',
],
'dependencies': [
'cdm.gyp:widevine_ce_cdm_static',
'../oemcrypto/util/oec_ref_util.gyp:oec_ref_util',
'../third_party/googletest.gyp:gmock',
'../third_party/googletest.gyp:gtest',
],
'msvs_settings': {
'VCLinkerTool': {
# Additionally, since they are loaded locally, suppress these
# warnings.
'AdditionalOptions': [
'/IGNORE:4049',
'/IGNORE:4217',
],
},
},
'conditions': [
['OS=="ios"', {
'type': 'loadable_module',
'mac_xctest_bundle': '1',
'defines': [
'GTEST_FILTER="<(gtest_filter)"',
],
'dependencies': [
'dummy_app',
],
'sources': [
'test/gtest_xctest_wrapper.mm',
],
'xcode_settings': {
'BUNDLE_LOADER': '$(TEST_HOST)',
'INFOPLIST_FILE': 'test/info.plist',
'PRODUCT_BUNDLE_IDENTIFIER': 'EQHXZ8M8AV.widevine_ce_cdm_unittest',
'TEST_HOST': '<(PRODUCT_DIR)/dummy_app.app/dummy_app',
'WRAPPER_EXTENSION': 'xctest',
},
}, {
'type': 'executable',
}],
# TODO(b/139814713): For testing and internal use only.
['oemcrypto_adapter_type=="static_v15"', {
'defines': [
# This is used by the unit tests to use some v15 functions.
'TEST_OEMCRYPTO_V15',
],
}],
['oemcrypto_lib=="level3"', {
'sources': [
# The test impl of OEMCrypto_Level3FileSystem and its factory.
'test/level3_file_system_ce_test.h',
'test/level3_file_system_ce_test.cpp',
'test/level3_file_system_ce_test_factory.cpp',
],
'conditions': [
['oemcrypto_adapter_type=="dynamic" ', {
'dependencies': [
'../oemcrypto/level3/oec_level3.gyp:oec_level3_dynamic',
],
}, {
'dependencies': [
'../oemcrypto/level3/oec_level3.gyp:oec_level3_static',
],
}],
],
}],
['oemcrypto_lib=="target"', {
'dependencies': [
'<(oemcrypto_gyp_path)',
],
}],
],
}],
'conditions': [
['supports_dynamic_perf_test', {
'targets': [{
'target_name': 'widevine_perf_test_dynamic',
'type': 'executable',
'sources': [
'../core/test/config_test_env.cpp',
'../core/test/http_socket.cpp',
'../core/test/license_request.cpp',
'../core/test/url_request.cpp',
'../util/src/string_conversions.cpp',
'../util/src/string_format.cpp',
'../util/test/test_sleep.cpp',
'src/log.cpp',
'src/logger_global.cpp',
'test/perf_test.cpp',
'test/perf_test_dynamic.cpp',
'test/test_host.cpp',
],
'includes': [ '../util/libssl_dependency.gypi' ],
'include_dirs': [
'../core/include',
'../core/test',
'../oemcrypto/include',
'../util/include',
'../util/test',
'include',
],
'dependencies': [
'../third_party/googletest.gyp:gmock',
'../third_party/googletest.gyp:gtest',
],
'conditions': [
['OS=="linux"', {
'libraries': [ '-ldl' ],
}],
],
}],
}], # condition: supports_dynamic_perf_test
['OS=="ios"', {
'targets': [{
'toolsets' : [ 'target' ],
'target_name': 'dummy_app',
'type': 'executable',
'mac_bundle': '1',
'sources': [
'test/dummy_app.mm',
],
'libraries': [
'CoreFoundation.framework',
'UIKit.framework',
],
'xcode_settings': {
'INFOPLIST_FILE': 'test/info.plist',
},
'conditions': [
['prebuilt_cdm_path!=""', {
'copies': [{
'destination': '<(PRODUCT_DIR)/dummy_app.app/Frameworks',
'xcode_code_sign': 1,
'files': [
# GYP seems to always use relative paths here, even if they
# start with '/'.
'<!(realpath --relative-to=. "<(prebuilt_cdm_path)")',
],
}],
}],
],
}],
'conditions': [
['supports_dynamic_perf_test', {
'targets': [{
'target_name': 'widevine_perf_test_xctest',
'type': 'loadable_module',
'mac_xctest_bundle': '1',
'defines': [
'GTEST_FILTER="<(gtest_filter)"',
],
'xcode_settings': {
'BUNDLE_LOADER': '$(TEST_HOST)',
'INFOPLIST_FILE': 'test/info.plist',
'PRODUCT_BUNDLE_IDENTIFIER': 'EQHXZ8M8AV.widevine_perf_test_xctest',
'TEST_HOST': '<(PRODUCT_DIR)/dummy_app.app/dummy_app',
'WRAPPER_EXTENSION': 'xctest',
'OTHER_LDFLAGS': [
'-iframework',
'<(prebuilt_cdm_path)/..',
],
},
'libraries': [
'<(prebuilt_cdm_path)',
],
'sources': [
'../core/test/config_test_env.cpp',
'../core/test/http_socket.cpp',
'../core/test/license_request.cpp',
'../core/test/url_request.cpp',
'../util/src/string_conversions.cpp',
'../util/test/test_clock.cpp',
'../util/test/test_sleep.cpp',
'src/log.cpp',
'test/perf_test.cpp',
'test/perf_test_xctest.mm',
'test/test_host.cpp',
],
'includes': [ '../util/libssl_dependency.gypi' ],
'include_dirs': [
'../core/include',
'../core/test',
'../util/include',
'../util/test',
'include',
],
'dependencies': [
'../third_party/googletest.gyp:gmock',
'../third_party/googletest.gyp:gtest',
'dummy_app',
],
}],
}], # condition: supports_dynamic_perf_test
],
}], # condition: OS=="ios"
],
}

View File

@@ -1,40 +0,0 @@
# 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 this in any custom unit test targets.
# Does not include the device certificate or the test runner main.
{
'cflags_cc+': [
'-Wno-inconsistent-missing-override',
],
'sources': [
'../core/test/http_socket.cpp',
'../core/test/license_request.cpp',
'../core/test/url_request.cpp',
'test/cdm_test.cpp',
'test/cdm_test_printers.cpp',
'test/cdm_test_printers.h',
'test/test_host.cpp',
'test/test_host.h',
'../util/test/test_sleep.cpp',
],
'conditions': [
['support_ota_keybox_functions=="true"', {
'sources': [
'../core/test/keybox_ota_test.cpp',
],
}],
],
'include_dirs': [
'../core/test',
'../util/test',
],
'defines': [
'UNIT_TEST',
'CDM_TESTS',
],
'includes': [ '../util/libssl_dependency.gypi' ],
}

View File

@@ -1,80 +0,0 @@
# 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 this in any custom unit test targets.
# Does not include the test runner main.
{
'variables': {
'wvcdm_sources': [
'../core/include/buffer_reader.h',
'../core/include/cdm_client_property_set.h',
'../core/include/cdm_engine.h',
'../core/include/cdm_engine_factory.h',
'../core/include/cdm_engine_metrics_decorator.h',
'../core/include/cdm_session.h',
'../core/include/cdm_session_map.h',
'../core/include/cdm_usage_table.h',
'../core/include/certificate_provisioning.h',
'../core/include/client_identification.h',
'../core/include/content_key_session.h',
'../core/include/crypto_key.h',
'../core/include/crypto_session.h',
'../core/include/crypto_wrapped_key.h',
'../core/include/device_files.h',
'../core/include/entitlement_key_session.h',
'../core/include/initialization_data.h',
'../core/include/key_session.h',
'../core/include/license_key_status.h',
'../core/include/license.h',
'../core/include/oemcrypto_adapter.h',
'../core/include/okp_fallback_policy.h',
'../core/include/okp_info.h',
'../core/include/ota_keybox_provisioner.h',
'../core/include/policy_engine.h',
'../core/include/policy_timers.h',
'../core/include/policy_timers_v16.h',
'../core/include/policy_timers_v18.h',
'../core/include/privacy_crypto.h',
'../core/include/properties.h',
'../core/include/service_certificate.h',
'../core/include/wv_cdm_constants.h',
'../core/include/wv_cdm_event_listener.h',
'../core/include/wv_cdm_types.h',
'../core/src/buffer_reader.cpp',
'../core/src/cdm_engine.cpp',
'../core/src/cdm_engine_factory.cpp',
'../core/src/cdm_session.cpp',
'../core/src/cdm_session_map.cpp',
'../core/src/cdm_usage_table.cpp',
'../core/src/certificate_provisioning.cpp',
'../core/src/client_identification.cpp',
'../core/src/content_key_session.cpp',
'../core/src/crypto_session.cpp',
'../core/src/device_files.cpp',
'../core/src/entitlement_key_session.cpp',
'../core/src/initialization_data.cpp',
'../core/src/license.cpp',
'../core/src/license_key_status.cpp',
'../core/src/license_protocol_conversions.cpp',
'../core/src/okp_fallback_policy.cpp',
'../core/src/okp_info.cpp',
'../core/src/ota_keybox_provisioner.cpp',
'../core/src/policy_engine.cpp',
'../core/src/policy_timers.cpp',
'../core/src/policy_timers_v16.cpp',
'../core/src/policy_timers_v18.cpp',
'../core/src/properties.cpp',
'../core/src/service_certificate.cpp',
'../core/src/system_id_extractor.cpp',
'../core/src/wv_cdm_types.cpp',
'../metrics/src/attribute_handler.cpp',
'../metrics/src/counter_metric.cpp',
'../metrics/src/distribution.cpp',
'../metrics/src/event_metric.cpp',
'../metrics/src/metrics_collections.cpp',
'../metrics/src/timer_metric.cpp',
'../metrics/src/value_metric.cpp',
],
},
}

View File

@@ -1,65 +0,0 @@
# 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 this in any custom unit test targets.
# Does not include the test runner main.
{
'sources': [
'../core/test/buffer_reader_test.cpp',
'../core/test/cdm_engine_test.cpp',
'../core/test/cdm_engine_metrics_decorator_unittest.cpp',
'../core/test/cdm_session_unittest.cpp',
'../core/test/cdm_usage_table_unittest.cpp',
'../core/test/config_test_env.cpp',
'../core/test/certificate_provisioning_unittest.cpp',
'../core/test/crypto_session_unittest.cpp',
'../core/test/device_files_unittest.cpp',
'../core/test/duration_use_case_test.cpp',
'../core/test/fake_provisioning_server.cpp',
'../core/test/generic_crypto_unittest.cpp',
'../core/test/http_socket.cpp',
'../core/test/http_socket_test.cpp',
'../core/test/initialization_data_unittest.cpp',
'../core/test/license_holder.cpp',
'../core/test/license_keys_unittest.cpp',
'../core/test/license_request.cpp',
'../core/test/license_unittest.cpp',
'../core/test/message_dumper.cpp',
'../core/test/okp_fallback_policy_test.cpp',
'../core/test/ota_keybox_provisioner_test.cpp',
'../core/test/parallel_operations_test.cpp',
'../core/test/policy_engine_constraints_unittest.cpp',
'../core/test/policy_engine_unittest.cpp',
'../core/test/policy_integration_test.cpp',
'../core/test/provisioning_holder.cpp',
'../core/test/rw_lock_test.cpp',
'../core/test/service_certificate_unittest.cpp',
'../core/test/system_id_extractor_unittest.cpp',
'../core/test/test_base.cpp',
'../core/test/test_printers.cpp',
'../core/test/url_request.cpp',
'../core/test/url_request_unittest.cpp',
'../metrics/test/counter_metric_unittest.cpp',
'../metrics/test/distribution_unittest.cpp',
'../metrics/test/event_metric_unittest.cpp',
'../metrics/test/metrics_collections_unittest.cpp',
'../metrics/test/value_metric_unittest.cpp',
],
'include_dirs': [
'../cdm/include',
'../core/include',
'../core/test',
'../metrics/include',
'../util/include',
],
'defines': [
'UNIT_TEST',
'CORE_TESTS',
],
'dependencies': [
'<(metrics_target)',
'<(device_files_target)',
],
'includes': [ '../util/libssl_dependency.gypi' ],
}

View File

@@ -1,34 +0,0 @@
#!/usr/bin/python3
# Copyright 2022 Google LLC. All Rights Reserved. This file and proprietary
# source code may only be used and distributed under the Widevine License
# Agreement.
"""Creates a cert.cc file from a cert.bin file."""
import argparse
import pathlib
import sys
if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('input')
parser.add_argument('output')
parser.add_argument('--variable', default='DeviceCert')
options = parser.parse_args(sys.argv[1:])
in_path = pathlib.Path(options.input)
dat = ', '.join(str(x) for x in in_path.read_bytes())
out_path = pathlib.Path(options.output)
out_path.write_text(f"""// Copyright 2021 Google LLC. All Rights Reserved.
#include <stdint.h>
#include <stddef.h>
namespace widevine {{
extern const uint8_t k{options.variable}[];
const uint8_t k{options.variable}[] = {{ {dat} }};
extern const size_t k{options.variable}Size;
const size_t k{options.variable}Size = sizeof(k{options.variable});
}} // namespace widevine""")

View File

@@ -1,953 +0,0 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
// Based on the EME draft spec from 2016 June 10.
// http://www.w3.org/TR/2016/WD-encrypted-media-20160610/"
#ifndef WVCDM_CDM_CDM_H_
#define WVCDM_CDM_CDM_H_
#include <stdint.h>
#include <map>
#include <string>
#include <vector>
// Uncomment this line when making static CDM builds. This will be edited by
// release scripts.
//#define CDM_STATIC 1
// Define CDM_EXPORT to export functionality across shared library boundaries.
#if defined(CDM_STATIC)
# define CDM_EXPORT
#else
# if defined(_WIN32)
# if defined(CDM_IMPLEMENTATION)
# define CDM_EXPORT __declspec(dllexport)
# else
# define CDM_EXPORT __declspec(dllimport)
# endif // defined(CDM_IMPLEMENTATION)
# else // defined(_WIN32)
# if defined(CDM_IMPLEMENTATION)
# define CDM_EXPORT __attribute__((visibility("default")))
# else
# define CDM_EXPORT
# endif
# endif // defined(_WIN32)
#endif // defined(CDM_STATIC)
namespace widevine {
class CDM_EXPORT ITimerClient {
public:
virtual ~ITimerClient() {}
// Called by ITimer when a timer expires.
virtual void onTimerExpired(void* context) = 0;
protected:
ITimerClient() {}
};
class CDM_EXPORT Cdm : public ITimerClient {
public:
// Session types defined by EME.
enum SessionType : int32_t {
kTemporary = 0,
kPersistentLicense = 1,
kPersistent = kPersistentLicense, // deprecated name from June 1 draft
// kPersistentUsageRecord = 2, // deprecated, no longer supported.
};
// Message types defined by EME.
enum MessageType : int32_t {
kLicenseRequest = 0,
kLicenseRenewal = 1,
kLicenseRelease = 2,
kIndividualizationRequest = 3, // Not used. Direct Individualization
// is used instead of App-Assisted
};
// Status codes returned by CDM functions.
//
enum Status : int32_t {
kSuccess = 0,
// These are analogous to the exceptions defined in the EME specification.
// Client implementations that support the EME API should pass these
// directly to the client application.
// Note: kTypeError replaced kInvalidAccess in the 6/1/2015 EME spec.
kTypeError = 1,
kNotSupported = 2,
kInvalidState = 3,
kQuotaExceeded = 4,
// These are additional codes defined by Widevine. In client implementations
// that support the EME API, these codes should be handled in the system
// layer. If it is necessary to notify the client application of one of
// these statuses, it should be mapped to one of the exception codes defined
// in the EME specification. Some of these errors are considered
// "recoverable" in that there are specific known remedies that the client
// may take in response to them. See the Integration Guide for further
// information.
kNeedsDeviceCertificate = 101, // Recoverable
kSessionNotFound = 102,
kDecryptError = 103,
kNoKey = 104,
kKeyUsageBlockedByPolicy = 105,
kRangeError = 106,
kResourceContention = 107, // Recoverable
kSessionStateLost = 108, // Recoverable
kSystemStateLost = 109, // Recoverable
kOutputTooLarge = 110, // Recoverable
kNeedsServiceCertificate = 111, // Recoverable
// This covers errors that we do not expect (see logs for details):
kUnexpectedError = 99999,
};
// These are the init data types defined by EME.
enum InitDataType : int32_t {
kCenc = 0,
kKeyIds = 1, // NOTE: not supported by Widevine at this time
kWebM = 2,
// This type is not defined by EME but is supported by Widevine
kHls = 10000,
};
// These are the crypto schemes supported by CENC 3.0.
enum EncryptionScheme : int32_t {
kClear = 0,
kAesCtr = 1, // AES-CTR, for use with the "cenc" schema
kAesCbc = 2, // AES-CBC, for use with the "cbcs" schema
};
// These are key statuses defined by EME.
enum KeyStatus : int32_t {
kUsable = 0,
kExpired = 1,
kOutputRestricted = 2,
kOutputNotAllowed = kOutputRestricted, // deprecated name from June 1 draft
kStatusPending = 3,
kInternalError = 4,
kReleased = 5,
};
// These are the possible HDCP levels supported by Widevine.
// For ease of comparison, these values are kept in ascending order by version
// number.
enum HdcpVersion : int32_t {
kHdcp1_x = 0,
kHdcp2_0 = 1,
kHdcp2_1 = 2,
kHdcp2_2 = 3,
kHdcp2_3 = 4,
};
// Permissible usages for a key. Returned as a set of flags; multiple
// flags may be set. The specific settings are defined in the license
// and the OEMCrypto Key Control Block. The CDM uses settings in the
// license to derive these flags.
typedef uint32_t KeyAllowedUsageFlags;
static const KeyAllowedUsageFlags kAllowNone = 0;
static const KeyAllowedUsageFlags kAllowDecryptToClearBuffer = 1;
static const KeyAllowedUsageFlags kAllowDecryptToSecureBuffer = 2;
static const KeyAllowedUsageFlags kAllowGenericEncrypt = 4;
static const KeyAllowedUsageFlags kAllowGenericDecrypt = 8;
static const KeyAllowedUsageFlags kAllowGenericSign = 16;
static const KeyAllowedUsageFlags kAllowGenericSignatureVerify = 32;
// These are defined by Widevine. The CDM can be configured to decrypt in
// three modes (dependent on OEMCrypto support).
enum SecureOutputType : int32_t {
// Data is decrypted to an opaque handle.
// Translates to OEMCrypto's OEMCrypto_BufferType_Secure.
kOpaqueHandle = 0,
// Decrypted data never returned to the caller, but is decoded and rendered
// by OEMCrypto.
// Translates to OEMCrypto's OEMCrypto_BufferType_Direct.
kDirectRender = 1,
// There is no secure output available, so all data is decrypted into a
// clear buffer in main memory.
// Translates to OEMCrypto's OEMCrypto_BufferType_Clear.
kNoSecureOutput = 2,
};
// Logging levels defined by Widevine.
// See Cdm::initialize().
enum LogLevel : int32_t {
kSilent = -1,
kErrors = 0,
kWarnings = 1,
kInfo = 2,
kDebug = 3,
kVerbose = 4,
};
// Types of service defined by Widevine.
// The service certificate installation methods - Cdm::setServiceCertificate()
// and Cdm::parseAndLoadServiceCertificateResponse() - use these to identify
// which service the certificate is intended for.
enum ServiceRole : int32_t {
kAllServices = 0,
kProvisioningService = 1,
kLicensingService = 2,
};
// These are the available Widevine robustness levels.
enum RobustnessLevel : int32_t {
kL1 = 1,
kL2 = 2,
kL3 = 3,
};
// Status code returned by getProvisioningStatus API.
enum ProvisioningStatus : int32_t {
kProvisioned = 0,
kUnknownProvisionStatus = 1,
kNeedsDrmCertProvisioning = 2,
kNeedsOemCertProvisioning = 3,
};
// A map of key statuses.
// See Cdm::getKeyStatuses().
typedef std::map<std::string, KeyStatus> KeyStatusMap;
// An event listener interface provided by the application and attached to
// each CDM session.
// See Cdm::createSession().
class IEventListener {
public:
virtual ~IEventListener() {}
// A message (license request, renewal, etc.) to be dispatched to the
// application's license server.
// The response, if successful, should be provided back to the CDM via a
// call to Cdm::update().
//
// The |server_url| parameter is not part of EME and may be ignored
// on EME-based integrations. It will be blank for initial license requests
// but filled in for renewal and release messages. It's offered for the use
// of apps that want to know the URL to send renewals and releases to
// without hardcoding it or retrieving it out-of-band.
virtual void onMessage(const std::string& session_id,
MessageType message_type, const std::string& message,
const std::string& server_url) = 0;
// There has been a change in the keys in the session or their status.
virtual void onKeyStatusesChange(const std::string& session_id,
bool has_new_usable_key) = 0;
// Called when the CDM changes the expiration time for a session.
// |new_expiration| is in milliseconds since 1970 UTC. If the license
// doesn't expire, it'll be -1.
virtual void onExpirationChange(const std::string& session_id,
int64_t new_expiration) = 0;
// A remove() operation has been completed.
virtual void onRemoveComplete(const std::string& session_id) = 0;
protected:
IEventListener() {}
};
// A storage interface provided by the application. This defines the "origin"
// that the CDM will operate in by the files it can access. Passing different
// IStorage instances to Cdm::create will cause those CDM instances to be in
// different "origins" as defined by the IStorage instance. For example,
// different IStorage instances could be tied to different folders for
// different origins.
//
// It is important for multi-origin hosts to verify the application's origin.
// This ensures that the application does not access files from another
// origin.
//
// NOTE: It is important for users of your application to be able to clear
// stored data. Also, browsers or other multi-application systems should
// store data separately per-app or per-origin.
// See http://www.w3.org/TR/encrypted-media/#privacy-storedinfo.
class IStorage {
public:
virtual ~IStorage() {}
virtual bool read(const std::string& name, std::string* data) = 0;
virtual bool write(const std::string& name, const std::string& data) = 0;
virtual bool exists(const std::string& name) = 0;
virtual bool remove(const std::string& name) = 0;
// Returns the size of the given file. If the file does not exist or any
// other error occurs, this should return a negative number.
virtual int32_t size(const std::string& name) = 0;
// Populates |file_names| with the name of each file in the file system.
// This is assumed to be a flat filename space (top level directory is
// unnamed, and there are no subdirectories).
virtual bool list(std::vector<std::string>* file_names) = 0;
protected:
IStorage() {}
};
// A clock interface provided by the application, independent of CDM
// instances.
// See Cdm::initialize().
class IClock {
public:
virtual ~IClock() {}
// Returns the current time in milliseconds since 1970 UTC.
virtual int64_t now() = 0;
protected:
IClock() {}
};
// A timer interface provided by the application, independent of CDM
// instances.
// See Cdm::initialize().
// Implementations of this class only need to deal with at most one
// outstanding timer per IClient at a time. It is an error for setTimeout() to
// be called while there is already a timer running for that client. It is
// recommended for implementers of this class to cancel the preexisting timer
// and start the new timer if this erroneous situation occurs.
// Timers are non-repeating. If the CDM wants to repeat a timer, it will call
// setTimeout() again inside the timeout callback.
class ITimer {
public:
virtual ~ITimer() {}
// This typedef is for backward compatibility with v3.0.0.
typedef ITimerClient IClient;
// Call |client->onTimerExpired(context)| after a delay of |delay_ms| ms.
virtual void setTimeout(int64_t delay_ms, IClient* client,
void* context) = 0;
// Cancel the timer associated with |client|.
virtual void cancel(IClient* client) = 0;
protected:
ITimer() {}
};
// A logging interface provided by the application. This will be called any
// time the CE CDM wants to log a message.
// See Cdm::initialize().
//
// A reference implementation that logs to stderr is provided in
// stderr_logger.h. Its behavior is identical to the behavior of previous
// CE CDM releases.
class ILogger {
public:
virtual ~ILogger() {}
// Log the provided message.
virtual void log(const std::string& message) = 0;
protected:
ILogger() {}
};
// The CE CDM has various pieces of client information baked into it at
// compile-time. These can be retrieved at runtime by Cdm::getClientInfo(),
// which returns them in this struct.
// These parameters match the client identification in license requests.
struct ClientInfo {
// The name of the company who makes the client, e.g. "KubrickTech".
// This matches the "Make" field in the Widevine Integration Console.
std::string company_name;
// The client's model name, e.g. "HAL 9000".
// This matches the "Model" field in the Widevine Integration Console.
std::string model_name;
// The client's model year, e.g. "2001".
// Can be used to distinguish different devices with the same model name.
// This matches the "Year" field in the Widevine Integration Console.
std::string model_year;
// The name or codename of the product or application, e.g. "clarke".
// This may be the same as "model_name".
std::string product_name;
// The name or codename of the client, e.g. "HAL".
// This may be the same as "model_name" or "product_name".
std::string device_name;
// The CPU architecture of the client, e.g. "ARMv7".
std::string arch_name;
// A string containing build information about the CE CDM and the client
// it's integrated into. Consists of multiple values separated by spaces
// and vertical pipes. (e.g. " | ")
std::string build_info;
};
// Initialize the CDM library and provide access to platform services.
// All platform interfaces are required. It is the responsibility of the host
// platform to ensure that the objects passed into this method remain valid
// for the lifetime of the CDM library.
// Logging is controlled by |verbosity|.
// Must be called and must return kSuccess before create() is called.
static Status initialize(SecureOutputType secure_output_type,
IStorage* storage, IClock* clock, ITimer* timer,
ILogger* logger, LogLevel verbosity);
// This is a variant of the above function that allows the caller to pass a
// Sandbox ID. Platforms that use Sandbox IDs should use this initialize()
// function instead of the previous one. Platforms that do not use Sandbox IDs
// should not use this version of initialize().
static Status initialize(SecureOutputType secure_output_type,
IStorage* storage, IClock* clock, ITimer* timer,
ILogger* logger, LogLevel verbosity,
const std::string& sandbox_id);
// Query the CDM library version.
static const char* version();
// Retrieves the client information for this CE CDM integration.
static Status getClientInfo(ClientInfo* client_info);
// Constructs a new CDM instance.
// initialize() must be called first and must return kSuccess before a CDM
// instance may be constructed.
// The CDM may notify of events at any time via the provided |listener|,
// which may not be NULL.
// |storage| defines the storage to use for this instance. By providing
// different objects here for different origins, this parameter can be used to
// provide per-origin storage. It may not be NULL.
//
// If |privacy_mode| is true, service certificates are required and will be
// used to encrypt messages to the license server.
// By using service certificates to encrypt communication with the license
// server, device-identifying information cannot be extracted from the
// license exchange process by an intermediate layer between the CDM and
// the server.
// This is particularly useful for browser environments, but is recommended
// for use whenever possible.
//
// If |storage_is_read_only| is true, the Widevine CE CDM will treat |storage|
// as read-only and prevent attempts to modify any data in the IStorage. Note
// that this is *not* the expected operation mode for most clients and will
// likely lead to playback failures. It should only be used in cases where
// read-only certificates and licenses have been pre-loaded on a device, such
// as the preloaded licenses in ATSC 3.
// It is not possible to mix read-only and non-read-only files in the same
// IStorage instance. A separate CDM with a separate IStorage pointing to the
// non-read-only files should be created with the read-only flag set to false.
static Cdm* create(IEventListener* listener, IStorage* storage,
bool privacy_mode = false,
bool storage_is_read_only = false);
~Cdm() override {}
// The following three methods relate to service certificates. A service
// certificate holds the RSA public key for a server, as well as other fields
// needed for provisioning. Service certificates are mandatory if privacy mode
// is turned on, as they are used to encrypt portions of outgoing messages to
// the provisioning and licensing servers.
// If a provisioning service certificate has not been installed before
// generating a provisioning request, a default certificate that only works
// with the Widevine-hosted provisioning service will be used.
// It is an error to generate a licensing request while privacy mode is
// turned on without installing a service certificate for the licensing
// service first.
// Installs a service certificate from a data buffer.
// This is used when the system or application already knows the certificate
// of the service it wishes to communicate with, either because it is baked
// into the software or because it was previously cached after a call to
// Cdm::parseAndLoadServiceCertificateResponse().
// If this method returns |Status::kSuccess|, the service certificate was
// installed successfully.
// The certificate is installed only for the service given by |role|. If the
// role |ServiceRole::kAllServices| is given, it is installed for all
// services.
virtual Status setServiceCertificate(ServiceRole role,
const std::string& certificate) = 0;
// Generate a Service Certificate Request message.
// This is used to fetch a service certificate from the license server.
// It is needed in cases where the system or application does not have
// a service certificate for the license server already.
virtual Status getServiceCertificateRequest(std::string* message) = 0;
// Parse a Service Certificate Response message, extracting the certificate
// from the message and installing it into the CDM.
// This is used when fetching a service certificate from the license server.
// A request should be generated by getServiceCertificateRequest() and sent
// to the license server. The server's response should be passed into this
// method.
// If this method returns |Status::kSuccess|, the service certificate was
// installed successfully.
// If a pointer to a string is passed in the |certificate| parameter, this
// method will fill it with the extracted certificate. This certificate
// string may be used with future CDM instances as the input to
// setServiceCertificate(). This avoids needing to make a call to the license
// server to get the certificate. The |certificate| argument may be NULL if
// you do not want to take advantage of this.
// The certificate is installed only for the service given by |role|. If the
// role |ServiceRole::kAllServices| is given, it is installed for all
// services.
virtual Status parseAndLoadServiceCertificateResponse(
ServiceRole role, const std::string& response,
std::string* certificate) = 0;
// Returns the robustness level of the device, as reported by OEMCrypto. Note
// that this function is *not* cryptographically secure and it should only be
// relied upon for informational purposes (e.g. determining which content to
// show in the UI) and not security purposes. (e.g. determining which content
// to allow the device to play) *Only* secure communication between OEMCrypto
// and the license service should be used to make security decisions.
virtual Status getRobustnessLevel(RobustnessLevel* level) = 0;
// Query the underlying OEMCrypto implementation's System ID.
virtual Status getSystemId(uint32_t* id) = 0;
// Returns the resource rating tier of the device, as reported by OEMCrypto.
virtual Status getResourceRatingTier(uint32_t* tier) = 0;
// Retrieves the build information for the underlying OEMCrypto
// implementation.
virtual Status getOemCryptoBuildInfo(std::string* build_info) = 0;
// Retrieves the current provisioning status. The Device Certificate is
// origin-specific, and the origin is determined by the CDM's current IStorage
// object.
virtual ProvisioningStatus getProvisioningStatus() = 0;
// Creates a Provisioning Request message.
// This is used to provision the device. The request should be sent to the
// provisioning server and the response given to handleProvisioningResponse().
virtual Status getProvisioningRequest(std::string* request) = 0;
// Handles a provisioning response and provisions the device. If this returns
// success, the device will now be provisioned.
virtual Status handleProvisioningResponse(const std::string& response) = 0;
// Remove the device's Device Certificate (for the current origin).
// The Device Certificate is origin-specific, and the origin is
// determined by the CDM's current IStorage object.
virtual Status removeProvisioning() = 0;
// Get the current list of offline licenses on the system.
// License storage is origin-specific, and the origin is determined by the
// CDM's current IStorage object.
virtual Status listStoredLicenses(std::vector<std::string>* key_set_ids) = 0;
// Checks whether the device is capable of supporting a given HDCP version.
// If successful, |key_status| is set to either kUsable or kOutputRestricted.
virtual Status getStatusForHdcpVersion(HdcpVersion hdcp,
KeyStatus* key_status) = 0;
// Checks if the given initialization data contains embedded, entitled keys.
// Sets the variable pointed to by |contains_keys| to true if the init data
// contains embedded keys or false if it does not. This function is useful if
// apps choose to handle such initialization data differently, such as in the
// case of key rotation or loading an offline entitlement license.
//
// For PSSH init data, this function accepts the full concatenated blob of
// PSSH boxes from the stream. It will return true if any of the PSSHs contain
// embedded Widevine keys.
virtual Status initDataContainsEmbeddedKeys(InitDataType init_data_type,
const std::string& init_data,
bool* contains_keys) = 0;
// Creates a new session.
// Do not use this to load an existing persistent session (use load()).
// If successful, the session ID is returned via |session_id|.
virtual Status createSession(SessionType session_type,
std::string* session_id) = 0;
// Generates a request based on the provided |init_data|. For PSSH init data,
// the CE CDM can accept the full concatenated blob of PSSH boxes from the
// stream. It will select the correct Widevine PSSH, so callers do not have to
// determine the correct PSSH from the list themselves.
// If the init data contains embedded keys, they will be remembered by the
// session and loaded after the matching entitlement key is provided to
// update().
//
// The request will be provided via a synchronous call to
// IEventListener::onMessage().
// This is done so that license requests and renewals follow the same flow.
virtual Status generateRequest(const std::string& session_id,
InitDataType init_data_type,
const std::string& init_data) = 0;
// Loads an existing persisted session from storage.
virtual Status load(const std::string& session_id) = 0;
// Provides messages, including licenses, to the CDM.
// If the message is a successful response to a release message, stored
// session data will be removed for the session.
virtual Status update(const std::string& session_id,
const std::string& response) = 0;
// Loads the entitled keys embedded in |init_data| into the session identified
// by |session_id|. The matching entitlement key must already be loaded in the
// session via previous calls to update() or load(). For PSSH init data, the
// CE CDM can accept the full concatenated blob of PSSH boxes from the stream.
// It will select the correct Widevine PSSH, so callers do not have to
// determine the correct PSSH from the list themselves.
//
// It is not necessary to call this function after passing PSSHs containing
// entitled keys to generateRequest(). This function is only used when adding
// new entitled keys to an existing session, such as for key rotation or
// after loading a persisted entitlement license.
virtual Status loadEmbeddedKeys(const std::string& session_id,
InitDataType init_data_type,
const std::string& init_data) = 0;
// The time, in milliseconds since 1970 UTC, after which the key(s) in the
// session will no longer be usable to decrypt media data, or -1 if no such
// time exists.
virtual Status getExpiration(const std::string& session_id,
int64_t* expiration) = 0;
// A map of known key IDs to the current status of the associated key.
virtual Status getKeyStatuses(const std::string& session_id,
KeyStatusMap* key_statuses) = 0;
// Gets the permitted usage for a specific key by ID.
virtual Status getKeyAllowedUsages(const std::string& session_id,
const std::string& key_id,
KeyAllowedUsageFlags* usage_flags) = 0;
// Gets the permitted usage for a specific key by ID.
// Search for key across all known sessions. If there are keys in separate
// sessions that match the given key_id, return kTypeError unless all such
// keys have identical Allowed Usage settings.
virtual Status getKeyAllowedUsages(const std::string& key_id,
KeyAllowedUsageFlags* usage_flags) = 0;
// Indicates that the application no longer needs the session and the CDM
// should release any resources associated with it and close it.
// Does not generate release messages for persistent sessions.
// Does not remove stored session data for persistent sessions.
virtual Status close(const std::string& session_id) = 0;
// Removes stored session data associated with the session.
// The session must be loaded before it can be removed.
// Generates release messages, which must be delivered to the license server.
// A reply from the license server must be provided via update() before the
// session is fully removed.
virtual Status remove(const std::string& session_id) = 0;
// Removes stored session data associated with the session.
// The session must be loaded before it can be removed.
// Unlike remove(), this method does not generate a release message. The
// stored data is removed immediately. The session is closed if this function
// returns successfully.
// Generally, callers should not use this method, as it prevents usage data
// from being gathered and it does not allow the license's release to be
// tracked by the server. Most callers will want to use remove(), which
// generates a release request. However, this method is provided for
// applications that have a specific need to release licenses without a server
// roundtrip and are aware of the costs of doing so.
// There is no EME equivalent to this method. EME specifies that removal
// should require a release request, as is done by the remove() method.
virtual Status forceRemove(const std::string& session_id) = 0;
// Describes a repeating pattern as defined by the CENC 3.0 standard. A
// CENC 3.0 pattern consists of a number of encrypted blocks followed by a
// number of clear blocks, after which it repeats.
struct Pattern {
public:
Pattern() : encrypted_blocks(0), clear_blocks(0) {}
Pattern(uint32_t encrypt, uint32_t clear)
: encrypted_blocks(encrypt), clear_blocks(clear) {}
// The number of crypto blocks that are encrypted and therefore need to be
// decrypted.
uint32_t encrypted_blocks;
// The number of crypto blocks that are not encrypted and therefore should
// be skipped when doing decryption.
uint32_t clear_blocks;
};
struct Subsample {
public:
Subsample() : clear_bytes(0), protected_bytes(0) {}
// The number of bytes of data that are not protected and therefore should
// be copied unchanged when doing decryption. The clear bytes come before
// the protected bytes in the subsample.
uint32_t clear_bytes;
// The number of bytes of data that are protected and therefore should be
// considered for decryption. Depending on the pattern, these bytes may all
// be decrypted or only some of them may be. The protected bytes come after
// the clear bytes in the subsample.
uint32_t protected_bytes;
};
struct InputBuffer {
public:
InputBuffer()
: iv(nullptr),
iv_length(0),
data(nullptr),
data_length(0),
subsamples(nullptr),
subsamples_length(0) {}
// These fields are treated as an array of bytes, with the |iv| pointer
// pointing to the first byte and containing |iv_length| number of bytes.
// These should be the bytes of the initial IV that should be used to
// decrypt this sample.
//
// |iv_length| must be 16 if the sample contains any protected data. If the
// content contains an 8-byte IV, it is the responsibility of the caller to
// expand it to 16 bytes following the method in the ISO-CENC standard.
const uint8_t* iv;
uint32_t iv_length;
// These fields are treated as an array of bytes, with the |data| pointer
// pointing to the first byte and containing |data_length| number of bytes.
// This data should be ready to be decrypted with no further processing. If
// the data is coming from a format that requires processing before
// decryption, that processing needs to happen before the data is passed in
// here. For example, content coming from HLS will need to have its extra
// start code emulation prevention removed before it is passed to the
// Widevine CE CDM.
const uint8_t* data;
uint32_t data_length;
// These fields are treated as an array of Subsample structs, with the
// |subsamples| pointer pointing to the first Subsample and containing
// |samples_length| number of entries. These structs describe all the
// ISO-CENC subsamples that make up the sample.
//
// The sum of all the |clear_bytes| and |protected_bytes| in all the
// subsamples must equal the |data_length| field.
const Subsample* subsamples;
uint32_t subsamples_length;
};
struct OutputBuffer {
OutputBuffer() : data(nullptr), data_offset(0), data_length(0) {}
// The type of value stored in this pointer depends on the secure output
// type passed to Cdm::initialize() and the |is_secure| field of the
// DecryptionBatch.
//
// If |is_secure| is false or the secure output type is kNoSecureOutput,
// this is a memory address in main memory.
// If |is_secure| is true and the secure output type is kOpaqueHandle,
// this is an opaque handle.
// If |is_secure| is true and the secure output type is kDirectRender,
// this is ignored.
//
// See also the SecureOutputType argument to initialize().
void* data;
// An offset applied to the output address inside OEMCrypto.
// Useful when |data| is an opaque handle rather than a memory address.
uint32_t data_offset;
// The maximum amount of data that can be decrypted to the |data| buffer.
// Must be at least as large as the input buffer's |data_length| plus the
// bytes that will be skipped by |data_offset|.
uint32_t data_length;
};
struct Sample {
public:
Sample() : input(), output() {}
// These structs describe the protected input data of the sample and the
// output buffer that decrypted data should be written to.
InputBuffer input;
OutputBuffer output;
};
struct DecryptionBatch {
public:
DecryptionBatch()
: samples(nullptr),
samples_length(0),
key_id(nullptr),
key_id_length(0),
pattern(),
is_secure(false),
encryption_scheme(kClear),
is_video(true) {}
// These fields are treated as an array of Sample structs, with the
// |samples| pointer pointing to the first Sample and containing
// |samples_length| number of entries. These structs describe all the data
// that is going to be decrypted. You can pass as many samples to the CDM as
// you want, but be aware that passing more samples than your OEMCrypto
// implementation can handle in one decrypt call is inefficient, as the CDM
// will have to do work to break the data up into smaller pieces.
const Sample* samples;
uint32_t samples_length;
// These fields are treated as an array of bytes, with the |key_id| pointer
// pointing to the first byte and containing |key_id_length| number of
// bytes. These should be the bytes of the Key ID of the key that should be
// used to decrypt the |samples|.
const uint8_t* key_id;
uint32_t key_id_length;
// Describes the repeating pattern with which the content was encrypted. If
// left at its default value of (0,0), patterns will be disabled. Should
// only be changed for content that uses patterns, such as for CENC 3.0
// "cbcs" content or for HLS content.
Pattern pattern;
// Indicates whether the OutputBuffers in the Samples are secure outputs or
// not. False for clear buffers, true otherwise.
// Must be false if the secure output type is kNoSecureOutput.
// See also the SecureOutputType argument to initialize().
bool is_secure;
// Specifies the encryption scheme, if any, to be used to decrypt the data.
// When set to kClear, decryption will copy the input data directly to the
// output buffer. This is necessary for secure output types, where the
// output buffer cannot be directly accessed above the CDM.
EncryptionScheme encryption_scheme;
// Used by secure output type kDirectRender, where the secure hardware must
// decode and render the decrypted content:
bool is_video;
};
// Decrypt the samples contained in the DecryptionBatch |batch| from their
// InputBuffer to their OutputBuffer. The |key_id| field of |batch|
// must refer to a key that is already loaded in some session.
virtual Status decrypt(const DecryptionBatch& batch) = 0;
// Decrypt the samples contained in the DecryptionBatch |batch| from their
// InputBuffer to their OutputBuffer. Decryption will be attempted in the
// session identified by |session_id|, regardless of whether the |key_id|
// field of |batch| refers to a key loaded in that session. If |key_id| refers
// to a key that is not loaded in the given session, decryption will fail.
//
// This overload is used when platforms need to play clear content through the
// secure path before a key is loaded.
virtual Status decrypt(const std::string& session_id,
const DecryptionBatch& batch) = 0;
// Sets a value in the custom app settings. These are settings
// that are sent with any message to the license server. These methods
// should only be used by advanced users maintaining existing systems.
// The |key| cannot be empty.
virtual Status setAppParameter(const std::string& key,
const std::string& value) = 0;
// Gets the current value in the custom app settings. If the key is
// not present, then kTypeError is returned. The |key| cannot be
// empty. |result| cannot be null. See setAppParameter().
virtual Status getAppParameter(const std::string& key,
std::string* result) = 0;
// Removes the value in the custom app settings. If the key is not
// present, then kTypeError is returned. The |key| cannot be empty.
// See setAppParameter().
virtual Status removeAppParameter(const std::string& key) = 0;
// Clears all the values in the custom app settings. See setAppParameter().
virtual Status clearAppParameters() = 0;
// Generic crypto - functions for applying crypto operations to
// app-level data (outside the content stream).
enum GenericEncryptionAlgorithmType : int32_t {
kEncryptionAlgorithmUnknown,
kEncryptionAlgorithmAesCbc128,
};
enum GenericSigningAlgorithmType : int32_t {
kSigningAlgorithmUnknown,
kSigningAlgorithmHmacSha256
};
// Encrypts a buffer of app-level data.
virtual Status genericEncrypt(const std::string& session_id,
const std::string& in_buffer,
const std::string& key_id,
const std::string& iv,
GenericEncryptionAlgorithmType algorithm,
std::string* out_buffer) = 0;
// Decrypts a buffer of app-level data.
virtual Status genericDecrypt(const std::string& session_id,
const std::string& in_buffer,
const std::string& key_id,
const std::string& iv,
GenericEncryptionAlgorithmType algorithm,
std::string* out_buffer) = 0;
// Signs a buffer of app-level data.
virtual Status genericSign(const std::string& session_id,
const std::string& message,
const std::string& key_id,
GenericSigningAlgorithmType algorithm,
std::string* signature) = 0;
// Verifies the signature on a buffer of app-level data.
// Returns kSuccess if signature is verified, otherwise returns kDecryptError.
virtual Status genericVerify(const std::string& session_id,
const std::string& message,
const std::string& key_id,
GenericSigningAlgorithmType algorithm,
const std::string& signature) = 0;
// Enable enforcement of Video Resolution Constraints.
// This function should be called during session startup and any time
// the resolution of the video stream changes. The resolution passed in should
// be the resolution of the content being played, not the output resolution of
// the device.
// Video resolutions in the license policy are stored as 32-bit values
// representing the total number of pixels. If the product of |width| and
// |height| is greater than or equal to 2^32, this will return kRangeError.
virtual Status setVideoResolution(const std::string& session_id,
uint32_t width, uint32_t height) = 0;
// Retrieve the metrics gathered by this CDM instance.
// The Widevine CE CDM gathers metrics about the time taken to perform various
// computations, as well as their error codes. This method allows platforms
// and apps to gather these metrics to send them back to Google for analysis.
virtual Status getMetrics(std::string* serialized_metrics) = 0;
// Creates a Cast Provisioning Request message.
// This method is only useful on devices that implement support for Google
// Cast. Calling this method will generate a provisioning request that can be
// used to provision the device's Cast certificate. The request should be sent
// to the provisioning server just like a request from
// getProvisioningRequest(). However, the response should be given to
// handleCastProvisioningResponse() in order to extract the additional,
// Cast-specific fields.
virtual Status getCastProvisioningRequest(std::string* request) = 0;
// Handles a Cast provisioning response.
// This method is only useful on devices that implement support for Google
// Cast. It returns both the Cast public certificate and a wrapped private key
// that can be used with castSign(). Handling a Cast provisioning response
// does not affect the device's Widevine provisioning status. See
// handleProvisioningResponse() for handling Widevine provisioning.
virtual Status handleCastProvisioningResponse(const std::string& response,
std::string* cert,
std::string* wrapped_key) = 0;
// Signs a method for Cast usage.
// This method is only useful on devices that support Google Cast and after
// receiving a wrapped private key from handleCastProvisioningResponse(). This
// method generates a signature for the message using the given private key in
// PKCS#1 with block type 1 padding.
virtual Status castSign(const std::string& wrapped_key,
const std::string& message,
std::string* signature) = 0;
protected:
Cdm() {}
};
} // namespace widevine
#endif // WVCDM_CDM_CDM_H_

View File

@@ -1,25 +0,0 @@
// Copyright 2015 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
#define CDM_VERSION_STR_(x, y, z, w) #x "." #y "." #z w
#define CDM_VERSION_STR(x, y, z, w) CDM_VERSION_STR_(x, y, z, w)
// Widevine CE CDM Version
#ifndef CDM_VERSION_MAJOR
# define CDM_VERSION_MAJOR 18
#endif
#ifndef CDM_VERSION_MINOR
# define CDM_VERSION_MINOR 3
#endif
#ifndef CDM_VERSION_PATCH
# define CDM_VERSION_PATCH 0
#endif
#ifndef CDM_VERSION_TAG
# define CDM_VERSION_TAG "-non-prod"
#endif
#define CDM_VERSION \
CDM_VERSION_STR(CDM_VERSION_MAJOR, CDM_VERSION_MINOR, CDM_VERSION_PATCH, \
CDM_VERSION_TAG)
#define EME_VERSION "https://www.w3.org/TR/2017/REC-encrypted-media-20170918"

View File

@@ -1,42 +0,0 @@
// Copyright 2022 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
#ifndef WVCDM_CDM_COMPILER_DETECTION_H_
#define WVCDM_CDM_COMPILER_DETECTION_H_
// This file makes some best-effort attempts to detect details about the
// compilation environment used by SetClientInfo.
#if defined(CDM_DISABLE_LOGGING)
# define LOGGING_MESSAGE "Logging Disabled"
#else
# define LOGGING_MESSAGE "Logging Enabled"
#endif
#if defined(_DEBUG)
# define BUILD_FLAVOR_MESSAGE "Debug"
#elif defined(NDEBUG)
# define BUILD_FLAVOR_MESSAGE "Release"
#else
# define BUILD_FLAVOR_MESSAGE "Unknown"
#endif
#if defined(__x86_64__) || defined(_M_X64)
# define CPU_ARCH_MESSAGE "x86-64"
#elif defined(__i386__) || defined(_M_IX86)
# define CPU_ARCH_MESSAGE "i386"
#elif defined(__aarch64__) || defined(_M_ARM64)
# define CPU_ARCH_MESSAGE "AArch64"
#elif defined(__arm__) || defined(_M_ARM)
# define CPU_ARCH_MESSAGE "AArch32"
#elif defined(__mips__)
# define CPU_ARCH_MESSAGE "MIPS"
#elif defined(__powerpc64__)
# define CPU_ARCH_MESSAGE "64-bit PowerPC"
#elif defined(__powerpc__) || defined(_M_PPC)
# define CPU_ARCH_MESSAGE "32-bit PowerPC"
#else
# define CPU_ARCH_MESSAGE "Unrecognized CPU"
#endif
#endif // WVCDM_CDM_COMPILER_DETECTION_H_

View File

@@ -1,14 +0,0 @@
// Copyright 2023 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
#ifndef WVCDM_CDM_LOGGER_GLOBAL_H_
#define WVCDM_CDM_LOGGER_GLOBAL_H_
#include "cdm.h"
namespace widevine {
extern Cdm::ILogger* g_logger;
}
#endif // WVCDM_CDM_LOGGER_GLOBAL_H_

View File

@@ -1,35 +0,0 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
#ifndef WVCDM_CDM_PROPERTIES_CE_H_
#define WVCDM_CDM_PROPERTIES_CE_H_
#include "cdm.h"
#if defined(UNIT_TEST)
# include <gtest/gtest.h>
#endif
namespace widevine {
class PropertiesCE {
public:
static Cdm::SecureOutputType GetSecureOutputType();
static void SetProvisioningMessagesAreBinary(bool bin_prov);
// If this is set to an empty string, (which is the default) then PropertiesCE
// will report that there is no Sandbox ID in use.
static void SetSandboxId(const std::string& sandbox_id);
static bool ClientInfoIsValid();
private:
static void SetSecureOutputType(Cdm::SecureOutputType secure_output_type);
friend class Cdm;
#if defined(UNIT_TEST)
FRIEND_TEST(CdmTest, DeviceCertificateRequest);
#endif
};
} // namespace widevine
#endif // WVCDM_CDM_PROPERTIES_CE_H_

View File

@@ -1,32 +0,0 @@
// Copyright 2022 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
#ifndef WVCDM_CDM_READ_CLIENT_INFO_H_
#define WVCDM_CDM_READ_CLIENT_INFO_H_
#include <string>
namespace widevine {
// This function must be implemented by partners who wish to use run-time client
// information. (i.e. Those that set 'client_info_source' to 'runtime' in their
// platform's properties.) These partners must set 'read_client_info_path' to
// a GYP target that contains an implementation of this function. This function
// will be called by the CE CDM during Cdm::initialize() to retrieve the client
// information at runtime.
//
// This function should fill in each of the strings with the relevant piece of
// client information and return true. If for any reason the platform cannot
// fill in all the strings or an error occurs, the function should return false.
//
// For a definition of each string's meaning, see the client info property
// documentation in platform_properties.gypi.
bool ReadClientInformation(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* platform, std::string* form_factor,
std::string* version);
} // namespace widevine
#endif // WVCDM_CDM_READ_CLIENT_INFO_H_

View File

@@ -1,28 +0,0 @@
// Copyright 2023 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
//
// You can use this implementation of ILogger when calling Cdm::initialize() in
// order to log all messages to stderr. This preserves the behavior of past CE
// CDM releases.
#ifndef WVCDM_CDM_STDERR_LOGGER_H_
#define WVCDM_CDM_STDERR_LOGGER_H_
#include <iostream>
#include <string>
#include "cdm.h"
namespace widevine {
class StderrLogger : public Cdm::ILogger {
public:
StderrLogger() {}
~StderrLogger() override {}
void log(const std::string& message) override {
std::cerr << message << std::endl << std::flush;
}
};
} // namespace widevine
#endif // WVCDM_CDM_STDERR_LOGGER_H_

View File

@@ -1,218 +0,0 @@
# Copyright 2020 Google LLC. All Rights Reserved. This file and proprietary
# source code may only be used and distributed under the Widevine License
# Agreement.
# This file contains all the variables that Widevine exposes for integration
# partners to customize in their platforms' settings.gypi files. Partners will
# usually need to override some or all of these variables in the 'variables'
# section of their platform's settings.gypi file.
#
# This file is included into multiple GYP files throughout the project. Those
# files may also define their own variables. However, variables defined outside
# this file are *not* intended to be overridden by integration partners. If
# your device requires overriding a variable from outside this file, please let
# Widevine know so that we can evaluate whether it should be included in this
# file or whether there is a better way to achieve what you are trying to
# achieve.
{
'variables': {
# Choose whether the client information is compiled into the binary at
# compile-time or whether it is gathered by the CDM at runtime. The client
# information ends up as client identification in license requests. All
# values may be used by a license server proxy to drive business logic.
# Valid values are:
#
# 'compiled' - The client information is read from the platform properties
# and compiled into the CE CDM binary. The platform properties
# that define client info must be defined.
#
# 'runtime' - The client information is read at runtime using
# read_client_info.h. The property 'read_client_info_path' must
# also be defined, pointing to a GYP target that provides an
# implementation of read_client_info.h.
'client_info_source%': 'compiled',
# The following variables define the client info that is baked into the CDM
# binary at build-time. If 'client_info_source' is 'compiled'. You *must*
# set meaningful values for all of these variables as part of defining your
# platform. Values may not contain double quotes, percent signs, or the
# substring " | ". (a vertical pipe surrounded by spaces) If
# 'client_info_source' is 'runtime', these variables are ignored.
# The name of the company who makes the client, e.g. "KubrickTech".
# This should match the "Make" field in the Widevine Integration Console.
#'client_company_name%': '',
# The client's model name, e.g. "HAL 9000".
# This should match the "Model" field in the Widevine Integration Console.
#'client_model_name%': '',
# The client's model year, e.g. "2001".
# Can be used to distinguish different devices with the same model name.
# This should match the "Year" field in the Widevine Integration Console.
#'client_model_year%': '',
# The name or codename of the product or application, e.g. "clarke".
# This may be the same as "client_model_name".
#'client_product_name%': '',
# The name or codename of the client, e.g. "HAL".
# This may be the same as "client_model_name" or "client_product_name".
#'client_device_name%': '',
# The CPU architecture of the client, e.g. "ARMv7".
#'client_arch_name%': '',
# The OS platform of the client, e.g. "Linux".
# This should match the "Platform" field in the Widevine Integration
# Console.
#'client_platform%': '',
# The form factor of the client, e.g. "TV".
# This should match the "Type" field in the Widevine Integration Console.
#'client_form_factor%': '',
# The version number of the client that the CE CDM is integrated into. This
# is the operating system or app version, not the CDM version.
#'client_version%': '',
# If 'client_info_source' is 'runtime', this variable must be set to the
# path to a GYP target that provides an implementation of
# read_client_info.h. This implementation will be compiled into the CDM and
# used at runtime to get the client info. If 'client_info_source' is
# 'compiled', this variable is ignored.
'read_client_info_path%': '',
# Choose type of OEMCrypto library to compile in. Valid values are:
#
# 'vendor' - Production Level 1 systems should use 'vendor' to indicate that
# they are providing their own OEMCrypto library and the Widevine
# CE CDM build system is not responsible for building anything.
#
# 'level3' - Partners who have received a Widevine-generated Level 3 library
# should use 'level3' to indicate that the Widevine CE CDM build
# system should include it in the build.
#
# 'target' - If your vendor OEMCrypto is built using GYP and you would like
# the Widevine CE CDM build system to build it as part of the CE
# CDM build process, you can use 'target' and also set the
# variable 'oemcrypto_gyp_path' below. Most vendors will want to
# use 'vendor', above, instead. This setting exists primarily for
# Google's internal testing.
#'oemcrypto_lib%': '',
# You only need to set this value if you set 'oemcrypto_lib' to 'target'
# above.
#'oemcrypto_gyp_path%': '',
# Choose the oemcrypto adapter type. Valid values are:
#
# 'static' - (default). Statically link oemcrypto into the tests.
# other values - for internal testing.
'oemcrypto_adapter_type%': 'static',
# Whether to include OTA Keybox functionality or not. This is an optional
# feature that is only used a few platforms. Generally, to qualify as an L1
# device, a keybox must be installed on the device in the factory.
# Valid values are 'true' or 'false'.
'support_ota_keybox_functions%': 'false',
# Compile with clang source based code coverage tool when run a code coverage
# build by set this to true.
'generate_code_coverage_report%': 'false',
# Override this to indicate what CPU architecture's assembly-language files
# should be used when building assembly language files. Or, set it to
# "none" to turn off the use of assembly language. The default is "none" for
# compatibility, but we strongly recommend overriding this value to
# improve performance. Turning it off or leaving it turned off is not
# recommended unless your CPU architecture is unsupported or you are using
# a tool that does not play nice with assembly language, like Address
# Sanitizer.
#
# Valid values are:
# * x86
# * x64 or x86-64
# * arm
# * arm64
# * ppc64
# * none
'asm_target_arch%': 'none',
# When building on Windows, we have to use the NASM assembler. By default
# we disable assembly on Windows since this is usually not installed. You
# can override it with these variables.
'has_nasm%': 'false',
'nasm_path%': 'nasm.exe',
# Although OEMCrypto is used to perform secure crypto operations, the
# Widevine CE CDM also needs a crypto library to perform non-secure crypto
# operations for Privacy Mode and Provisioning 3.0. By default, the copy
# of BoringSSL in third_party/boringssl/ is compiled statically into the CE
# CDM with hidden linkage. However, by overriding these values, partners can
# choose to use other crypto libraries.
#
# Valid values are:
# * boringssl
# * openssl
# * dummy
#
# If this option is set to 'dummy', the CDM will compile, but Privacy Mode
# and Provisioning 3.0 will always fail.
#
# Some of these libraries can be further configured with the options that
# follow this one.
'privacy_crypto_impl%': 'boringssl',
# BoringSSL Configuration
# These options are only relevant if privacy_crypto_impl is 'boringssl'.
#
# When using BoringSSL, the Widevine CE CDM defaults to the copy of
# BoringSSL in third_party/boringssl/. If you have an alternative BoringSSL
# GYP build, you can override these variables to point to it instead.
'boringssl_libcrypto_path%': '<(DEPTH)/third_party/boringssl/boringssl.gyp:crypto',
'boringssl_libssl_path%': '<(DEPTH)/third_party/boringssl/boringssl.gyp:ssl',
# There are three protobuf configurations:
#
# 1) protobuf_config == 'system'
# Use a system-wide installation of protobuf.
# Specify the protobuf library in protobuf_lib.
# Specify the path to protoc in protoc_bin.
#
# 2) protobuf_config == 'target'
# Use an existing protobuf gyp target from your project.
# Specify the protobuf gyp file and target in protobuf_lib_path.
# Specify the protoc gyp file and target in protoc_host_path.
# Specify the path to protoc in protoc_bin.
#
# 3) protobuf_config == 'source' (default)
# Build protobuf and protoc from the copy in third_party/protobuf.
'protobuf_config%': 'source',
'protobuf_lib%': '',
'protoc_bin%': '',
'protobuf_lib_path%': '',
'protoc_host_path%': '',
# Protobuf Generation and Build configurations:
#
# These options allow for different build steps to be specified for proto
# cc file generation than the default step. This can be used to customize
# cc file generation or add additional cc file processing steps before
# proto cc files are built.
#
# The directory where proto cc files that will be compiled are located.
'proto_cc_dir%': '<(SHARED_INTERMEDIATE_DIR)/protoc_out',
# The directory where proto cc files generated from proto files will be
# located.
'proto_gen_dir%': '<(SHARED_INTERMEDIATE_DIR)/protoc_out',
# Path to the GYP file that contains the proto cc file generation targets.
# This file must provide the following targets:
# - generate_license_protocol
# - generate_device_files
# - generate_metrics_proto
'proto_gen_gyp_path%': '<(DEPTH)/third_party/generate_proto_cc.gyp',
}, # variables
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,68 +0,0 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
//
// Log - implemented using stderr.
#include "log.h"
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include "logger_global.h"
#include "string_format.h"
namespace {
// We initialize every log message with this message so that if formatting
// fails, we'll still get a readable message.
const char* const kFallbackLogMessage = "[FATAL] Unable to format log message";
} // namespace
namespace wvutil {
LogPriority g_cutoff = CDM_LOG_WARN;
void InitLogging() {}
void Log(const char* file, const char* function, int line, LogPriority level,
const char* fmt, ...) {
if (widevine::g_logger == nullptr) {
// If somehow we got here with no logger configured, as a last resort
// complain to stderr and bail.
fprintf(stderr, "[FATAL:%s(%d):%s] NO LOGGER CONFIGURED\n", file, line,
function);
fflush(stderr);
return;
}
const char* severities[] = {"ERROR", "WARN", "INFO", "DEBUG", "VERBOSE"};
if (level >=
static_cast<LogPriority>(sizeof(severities) / sizeof(*severities))) {
std::string fatal_message(kFallbackLogMessage);
FormatString(&fatal_message,
"[FATAL:%s(%d):%s] Invalid log priority level: %d", file, line,
function, level);
widevine::g_logger->log(fatal_message);
return;
}
if (level > g_cutoff) return;
std::string formatted_message(kFallbackLogMessage);
va_list ap;
va_start(ap, fmt);
VFormatString(&formatted_message, fmt, ap);
va_end(ap);
std::string log_line(kFallbackLogMessage);
FormatString(&log_line, "[%s:%s(%d):%s] %s", severities[level], file, line,
function, formatted_message.c_str());
widevine::g_logger->log(log_line);
}
} // namespace wvutil

View File

@@ -1,9 +0,0 @@
// Copyright 2023 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
#include "logger_global.h"
namespace widevine {
Cdm::ILogger* g_logger = nullptr;
}

View File

@@ -1,281 +0,0 @@
// 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 <stdio.h>
#include <string.h>
#include <memory>
#include <string>
#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<std::mutex> 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<std::string>* 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

View File

@@ -1,121 +0,0 @@
// 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 <assert.h>
#include <gtest/gtest.h>
#include <string.h>
#include <time.h>
#include <algorithm>
#include <fstream>
#include <iostream>
#include <string>
#include <vector>
#if defined(__linux__)
# include <sys/utsname.h>
#endif
#include "cdm.h"
#include "cdm_test_runner.h"
#include "clock.h"
#include "log.h"
#include "reboot_test.h"
#include "test_base.h"
#include "test_host.h"
using namespace widevine;
// TODO(b/195338975): document how a partner should modify this so that they can
// use a real host.
TestHost* g_host = nullptr;
namespace {
constexpr char kGlobalDumpFileName[] = "dumped_global_filesystem.dat";
constexpr char kPerOriginDumpFileName[] = "dumped_per_origin_filesystem.dat";
using StorageMap = TestHost::Storage::StorageMap;
// Load a TestHost file system from the real file system.
bool ReloadFileSystem(const char* file_name, StorageMap* map) {
std::ifstream input(file_name);
if (input.fail()) {
// This is OK for first pass, but an error for later passes.
LOGD("Could not read %s", file_name);
return false;
}
std::string dumped_file_system((std::istreambuf_iterator<char>(input)),
std::istreambuf_iterator<char>());
if (!wvcdm::RebootTest::ParseDump(dumped_file_system, map)) {
LOGE("Could not parse %s", file_name);
return false;
}
return true;
}
bool ReloadFileSystems() {
StorageMap global_map;
StorageMap per_origin_map;
if (!ReloadFileSystem(kGlobalDumpFileName, &global_map) ||
!ReloadFileSystem(kPerOriginDumpFileName, &per_origin_map)) {
return false;
}
g_host->global_storage().ResetFiles(global_map);
g_host->per_origin_storage().ResetFiles(per_origin_map);
return true;
}
// Dump a TestHost file system to the real file system. If the dump file
// cannot be written, this raises an exception and crashes the program. Since
// we usually build with exceptions turned off, what this means is that the test
// executable will halt if the file cannot be written.
void DumpFileSystem(const char* file_name, const StorageMap& map) {
std::string dump = wvcdm::RebootTest::DumpData(map);
std::ofstream output(file_name);
output << dump;
output.close();
}
void DumpFileSystems() {
DumpFileSystem(kGlobalDumpFileName, g_host->global_storage().files());
DumpFileSystem(kPerOriginDumpFileName, g_host->per_origin_storage().files());
}
} // namespace
int main(int argc, char** argv) {
// Set up a Host and initialize the library. This makes these services
// available to the tests. We would do this in the test suite itself, but the
// core & OEMCrypto tests don't know they depend on this for storage.
g_host = new TestHost();
ReloadFileSystems();
// Partners will want to replace this with a real IStorage.
Cdm::IStorage* const storage = &g_host->global_storage();
// Partners may also want to replace this with real implementations of IClock
// and ITimer. If so, make not to set the command line argument
// "--fake_sleep".
Cdm::IClock* const clock = g_host;
Cdm::ITimer* const timer = g_host;
// Partners who prefer their logs to go somewhere other than stderr may want
// to replace this implementation.
Cdm::ILogger* const logger = &g_stderr_logger;
// If the tests need a separate file system from that used by the host, that
// should be set up here. For the reference code, we use a default test file
// system, but save the data from the file system.
// A separate file system might be needed, for example, if the test data needs
// to be saved off-device. Or, for example, if the main file system limits the
// names and types of files it can save to certificates and offline licenses.
wvutil::FileSystem* file_system = nullptr;
wvcdm::RebootTest::set_file_system(file_system);
const int test_results = Main(storage, clock, timer, logger, argc, argv);
DumpFileSystems();
// This is used by the test driver to know what time to use for initializing
// the fake clock for the next pass.
std::cout << "END_OF_TEST " << wvutil::Clock().GetCurrentTime() << "\n";
return test_results;
}

File diff suppressed because it is too large Load Diff

View File

@@ -1,44 +0,0 @@
// 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 <assert.h>
#include <gtest/gtest.h>
#include <string.h>
#include <time.h>
#include <algorithm>
#include <string>
#include <vector>
#include "cdm.h"
#include "cdm_test_runner.h"
#include "log.h"
#include "test_base.h"
#include "test_host.h"
using namespace widevine;
TestHost* g_host = nullptr;
int main(int argc, char** argv) {
g_host = new TestHost();
// TODO(b/195338975): document that using a real IStorage means you should not
// run the tests in $CDM_DIR/cdm/test/cdm_test.cpp
// Partners will want to replace this with a real IStorage.
Cdm::IStorage* const storage = &g_host->global_storage();
// Partners may also want to replace this with real implementations of IClock
// and ITimer. If so, make not to set the command line argument
// "--fake_sleep".
Cdm::IClock* const clock = g_host;
Cdm::ITimer* const timer = g_host;
// Partners who prefer their logs to go somewhere other than stderr may want
// to replace this implementation.
Cdm::ILogger* const logger = &g_stderr_logger;
const int test_results = Main(storage, clock, timer, logger, argc, argv);
return test_results;
}

View File

@@ -1,118 +0,0 @@
// 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 "cdm_test_printers.h"
namespace widevine {
void PrintTo(const Cdm::MessageType& value, ::std::ostream* os) {
switch (value) {
case Cdm::kLicenseRequest:
*os << "Cdm::kLicenseRequest";
break;
case Cdm::kLicenseRenewal:
*os << "Cdm::kLicenseRenewal";
break;
case Cdm::kLicenseRelease:
*os << "Cdm::kLicenseRelease";
break;
case Cdm::kIndividualizationRequest:
*os << "Cdm::kIndividualizationRequest";
break;
default:
*os << "Unknown Cdm::MessageType value " << value;
break;
}
}
void PrintTo(const Cdm::Status& value, ::std::ostream* os) {
switch (value) {
case Cdm::kSuccess:
*os << "Cdm::kSuccess";
break;
case Cdm::kTypeError:
*os << "Cdm::kTypeError";
break;
case Cdm::kNotSupported:
*os << "Cdm::kNotSupported";
break;
case Cdm::kInvalidState:
*os << "Cdm::kInvalidState";
break;
case Cdm::kQuotaExceeded:
*os << "Cdm::kQuotaExceeded";
break;
case Cdm::kNeedsDeviceCertificate:
*os << "Cdm::kNeedsDeviceCertificate";
break;
case Cdm::kSessionNotFound:
*os << "Cdm::kSessionNotFound";
break;
case Cdm::kDecryptError:
*os << "Cdm::kDecryptError";
break;
case Cdm::kNoKey:
*os << "Cdm::kNoKey";
break;
case Cdm::kKeyUsageBlockedByPolicy:
*os << "Cdm::kKeyUsageBlockedByPolicy";
break;
case Cdm::kRangeError:
*os << "Cdm::kRangeError";
break;
case Cdm::kResourceContention:
*os << "Cdm::kResourceContention";
break;
case Cdm::kSessionStateLost:
*os << "Cdm::kSessionStateLost";
break;
case Cdm::kSystemStateLost:
*os << "Cdm::kSystemStateLost";
break;
case Cdm::kOutputTooLarge:
*os << "Cdm::kOutputTooLarge";
break;
case Cdm::kNeedsServiceCertificate:
*os << "Cdm::kNeedsServiceCertificate";
break;
case Cdm::kUnexpectedError:
*os << "Cdm::kUnexpectedError";
break;
default:
*os << "Unknown Cdm::Status value " << value;
break;
}
}
void PrintTo(const Cdm::KeyStatus& value, ::std::ostream* os) {
switch (value) {
case Cdm::kUsable:
*os << "Cdm::kUsable";
break;
case Cdm::kExpired:
*os << "Cdm::kExpired";
break;
case Cdm::kOutputRestricted:
*os << "Cdm::kOutputRestricted";
break;
case Cdm::kStatusPending:
*os << "Cdm::kStatusPending";
break;
case Cdm::kInternalError:
*os << "Cdm::kInternalError";
break;
case Cdm::kReleased:
*os << "Cdm::kReleased";
break;
default:
*os << "Unknown Cdm::KeyStatus value " << value;
break;
}
}
} // namespace widevine

View File

@@ -1,21 +0,0 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
// This file adds some print methods so that when unit tests fail, the
// will print the name of an enumeration instead of the numeric value.
#ifndef WVCDM_CDM_TEST_CDM_TEST_PRINTERS_H_
#define WVCDM_CDM_TEST_CDM_TEST_PRINTERS_H_
#include <iostream>
#include "cdm.h"
namespace widevine {
void PrintTo(const Cdm::MessageType& value, ::std::ostream* os);
void PrintTo(const Cdm::Status& value, ::std::ostream* os);
void PrintTo(const Cdm::KeyStatus& value, ::std::ostream* os);
} // namespace widevine
#endif // WVCDM_CDM_TEST_CDM_TEST_PRINTERS_H_

View File

@@ -1,69 +0,0 @@
// 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 <assert.h>
#include <gtest/gtest.h>
#include <string.h>
#include <time.h>
#include <algorithm>
#include <string>
#include <vector>
#include "cdm.h"
#include "log.h"
#include "stderr_logger.h"
#include "test_base.h"
#include "test_host.h"
widevine::StderrLogger g_stderr_logger;
std::string g_sandbox_id;
namespace widevine {
namespace {
constexpr char kSandboxIdParam[] = "--sandbox_id=";
// Following the pattern established by help text in test_base.cpp
constexpr char kExtraHelpText[] =
" --sandbox_id=<sandbox_id>\n"
" Specifies the Sandbox ID that should be sent to OEMCrypto via\n"
" OEMCrypto_SetSandbox(). On most platforms, since Sandbox IDs are not\n"
" in use, this parameter should be omitted.\n";
} // namespace
int Main(Cdm::IStorage* storage, Cdm::IClock* clock, Cdm::ITimer* timer,
Cdm::ILogger* logger, int argc, char** argv) {
// Find and filter out the Sandbox ID, if any.
std::vector<std::string> args(argv, argv + argc);
auto sandbox_id_iter = std::find_if(std::begin(args) + 1, std::end(args),
[](const std::string& elem) -> bool {
return elem.find(kSandboxIdParam) == 0;
});
if (sandbox_id_iter != std::end(args)) {
g_sandbox_id = sandbox_id_iter->substr(strlen(kSandboxIdParam));
args.erase(sandbox_id_iter);
}
Cdm::Status status = Cdm::initialize(
Cdm::kOpaqueHandle, storage, clock, timer, logger,
static_cast<Cdm::LogLevel>(wvutil::g_cutoff), g_sandbox_id);
(void)status; // status is now used when assertions are turned off.
assert(status == Cdm::kSuccess);
std::vector<const char*> new_argv(args.size());
std::transform(
std::begin(args), std::end(args), std::begin(new_argv),
[](const std::string& arg) -> const char* { return arg.c_str(); });
// This must take place after the call to Cdm::initialize() because it makes
// calls that are only valid after the library is initialized.
if (!wvcdm::WvCdmTestBase::Initialize(static_cast<int>(new_argv.size()),
new_argv.data(), kExtraHelpText)) {
return 1;
}
// Init gtest after oemcrypto and cdm host have been initialized.
::testing::InitGoogleTest(&argc, argv);
return RUN_ALL_TESTS();
}
} // namespace widevine

View File

@@ -1,20 +0,0 @@
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
#ifndef WVCDM_CDM_TEST_CDM_TEST_RUNNER_H_
#define WVCDM_CDM_TEST_CDM_TEST_RUNNER_H_
#include <iostream>
#include "cdm.h"
namespace widevine {
// Run all CDM tests using the specified storage, clock, and timer. It parses
// standard command line arguments, sets some default test client info,
// initializes a CDM object, and then runs all the tests.
// Returns 0 on success.
int Main(Cdm::IStorage* storage, Cdm::IClock* clock, Cdm::ITimer* timer,
Cdm::ILogger* logger, int argc, char** argv);
} // namespace widevine
#endif // WVCDM_CDM_TEST_CDM_TEST_RUNNER_H_

View File

@@ -4,8 +4,4 @@
#include "create_test_file_system.h"
#include "test_host.h"
wvutil::FileSystem* CreateTestFileSystem() {
return new wvutil::FileSystem("", &g_host->per_origin_storage());
}
wvutil::FileSystem* CreateTestFileSystem() { return new wvutil::FileSystem(); }

File diff suppressed because it is too large Load Diff

View File

@@ -1,14 +0,0 @@
// Copyright 2019 Google LLC. All Rights Reserved.
#import <UIKit/UIKit.h>
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@end
@implementation AppDelegate {
}
@end
int main(int argc, char** argv) {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}

View File

@@ -1,23 +0,0 @@
// Copyright 2019 Google LLC. All Rights Reserved.
#import <XCTest/XCTest.h>
#include <gtest/gtest.h>
// Defined in cdm_test_main.cpp.
int main(int argc, char** argv);
@interface GtestTests : XCTestCase
@end
@implementation GtestTests
- (void)testAll {
testing::GTEST_FLAG(filter) = GTEST_FILTER;
char arg0[] = "tests";
char* argv[] = {arg0, nullptr};
XCTAssertEqual(main(1, argv), 0);
}
@end

View File

@@ -1,25 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>EQHXZ8M8AV.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
</dict>
</plist>

View File

@@ -1,64 +0,0 @@
// Copyright 2022 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
/**
The test file system for the Level 3 OEMCrypto sits on top of the host file
system. A real production version may either use the host file system or it
may write files directly to the file system.
*/
#include <algorithm>
#include <cstring>
#include <map>
#include <string>
#include "level3_file_system_ce_test.h"
#include "test_host.h"
namespace wvoec3 {
ssize_t OEMCrypto_Level3CETestFileSystem::Read(const char* filename,
void* buffer, size_t size) {
if (!g_host) return 0;
const std::string name(filename);
if (!g_host->global_storage().exists(name)) return 0;
std::string data;
if (!g_host->global_storage().read(name, &data)) return 0;
size_t bytes_read = std::min(size, data.size());
memcpy(buffer, data.data(), bytes_read);
return bytes_read;
}
ssize_t OEMCrypto_Level3CETestFileSystem::Write(const char* filename,
const void* buffer,
size_t size) {
if (!g_host) return 0;
std::string data(static_cast<const char*>(buffer), size);
const std::string name(filename);
if (!g_host->global_storage().write(name, data)) return 0;
return size;
}
bool OEMCrypto_Level3CETestFileSystem::Exists(const char* filename) {
if (!g_host) return false;
const std::string name(filename);
return g_host->global_storage().exists(name);
}
ssize_t OEMCrypto_Level3CETestFileSystem::FileSize(const char* filename) {
if (!g_host) return 0;
const std::string name(filename);
if (!g_host->global_storage().exists(name)) return 0;
return static_cast<ssize_t>(g_host->global_storage().size(name));
}
bool OEMCrypto_Level3CETestFileSystem::Remove(const char* filename) {
if (!g_host) return false;
const std::string name(filename);
if (!g_host->global_storage().exists(name)) return false;
return g_host->global_storage().remove(name);
}
} // namespace wvoec3

View File

@@ -1,33 +0,0 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
/*********************************************************************
* level3_file_system_ce_test.h
*
* Test file system for CE CDM for OEMCrypto Level3 File Operations.
*********************************************************************/
#ifndef LEVEL3_FILE_SYSTEM_CE_TEST_H_
#define LEVEL3_FILE_SYSTEM_CE_TEST_H_
#include "cdm.h"
#include "file_store.h"
#include "level3_file_system.h"
namespace wvoec3 {
class OEMCrypto_Level3CETestFileSystem : public OEMCrypto_Level3FileSystem {
public:
OEMCrypto_Level3CETestFileSystem() {}
~OEMCrypto_Level3CETestFileSystem() override {}
ssize_t Read(const char* filename, void* buffer, size_t size) override;
ssize_t Write(const char* filename, const void* buffer, size_t size) override;
bool Exists(const char* filename) override;
ssize_t FileSize(const char* filename) override;
bool Remove(const char* filename) override;
};
} // namespace wvoec3
#endif

View File

@@ -1,17 +0,0 @@
#include "level3.h"
#include "level3_file_system_ce_test.h"
namespace wvoec3 {
OEMCrypto_Level3FileSystem* createLevel3FileSystem() {
return new OEMCrypto_Level3CETestFileSystem();
}
void deleteLevel3FileSystem(OEMCrypto_Level3FileSystem* file_system) {
if (file_system) {
delete file_system;
}
}
} // namespace wvoec3

View File

@@ -1,349 +0,0 @@
// 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 "perf_test.h"
#include <gtest/gtest.h>
#include <stdio.h>
#include <stdlib.h>
#include <chrono>
#include <cmath>
#include <cstring>
#include <ctime>
#include <fstream>
#include <iostream>
#include <memory>
#include <string>
#include <vector>
#include "config_test_env.h"
#include "license_request.h"
#include "logger_global.h"
#include "test_host.h"
#include "url_request.h"
#define ASSERT_SUCCESS(code) ASSERT_EQ(code, Cdm::kSuccess)
#define EXPECT_SUCCESS(code) EXPECT_EQ(code, Cdm::kSuccess)
#define WALL_NOW std::chrono::high_resolution_clock::now()
TestHost* g_host = nullptr;
widevine::StderrLogger g_stderr_logger;
namespace widevine {
namespace {
constexpr const size_t kTestCount = 50;
const wvcdm::ConfigTestEnv kTestData(wvcdm::kContentProtectionUatServer);
CreateFuncType create_func = nullptr;
using TimeType = std::chrono::duration<double, std::milli>;
struct PerfInfo {
double mean;
double min;
double max;
double std_dev;
template <size_t Size>
PerfInfo(const double (&values)[Size]) {
static_assert(Size > 0, "Must pass at least one value");
// First pass to calculate min/max/mean.
bool first = true;
double sum = 0;
for (auto v : values) {
sum += v;
if (first) {
min = max = v;
first = false;
} else {
if (v < min) min = v;
if (v > max) max = v;
}
}
mean = sum / Size;
// Second pass to calculate standard deviation.
sum = 0;
for (auto v : values) {
sum += (v - mean) * (v - mean);
}
std_dev = std::sqrt(sum / Size);
}
};
std::ostream& operator<<(std::ostream& os, const PerfInfo& info) {
// mean=12.33442, std-dev=1.44421, min=1.22431, max=244.1133144
return os << "mean=" << info.mean << ", std-dev=" << info.std_dev
<< ", min=" << info.min << ", max=" << info.max;
}
class PerfTracker {
public:
class Test {
public:
Test(PerfTracker* tracker)
: wall_start_(WALL_NOW), cpu_start_(std::clock()), tracker_(tracker) {}
~Test() {
tracker_->wall_times_[tracker_->index_] =
TimeType(WALL_NOW - wall_start_).count();
tracker_->cpu_times_[tracker_->index_] =
(std::clock() - cpu_start_) * 1000.0 / CLOCKS_PER_SEC;
tracker_->index_++;
}
private:
std::chrono::high_resolution_clock::time_point wall_start_;
std::clock_t cpu_start_;
PerfTracker* tracker_;
};
void Print(const std::string& name, size_t block_size_bytes = 0) {
PerfInfo wall_perf(wall_times_);
PerfInfo cpu_perf(cpu_times_);
std::cout << name << " (wall, ms): " << wall_perf << "\n";
std::cout << name << " (cpu, ms): " << cpu_perf << "\n";
if (block_size_bytes) {
// |mean| is in milliseconds.
std::cout << name << " (wall, MBit/sec): "
<< (block_size_bytes * 8 * 1000 / wall_perf.mean / 1024 / 1024)
<< "\n";
std::cout << name << " (cpu, MBit/sec): "
<< (block_size_bytes * 8 * 1000 / cpu_perf.mean / 1024 / 1024)
<< "\n";
}
}
private:
double wall_times_[kTestCount];
double cpu_times_[kTestCount];
size_t index_ = 0;
};
#define MEASURE_PERF(tracker, code) \
{ \
PerfTracker::Test test(&(tracker)); \
code; \
}
class EventListener : public Cdm::IEventListener {
public:
struct MessageInfo {
std::string session_id;
std::string message;
Cdm::MessageType message_type;
std::string url;
};
void onMessage(const std::string& session_id, Cdm::MessageType message_type,
const std::string& message, const std::string& url) override {
messages.push_back({session_id, message, message_type, url});
}
void onKeyStatusesChange(const std::string& session_id,
bool has_new_usable_key) override {}
void onExpirationChange(const std::string& session_id,
int64_t new_expiration) override {}
void onRemoveComplete(const std::string& session_id) override {}
std::vector<MessageInfo> messages;
};
bool SendPost(const std::string& message, std::string* response) {
wvcdm::UrlRequest req(kTestData.license_server());
std::string raw_response;
if (!req.is_connected() || !req.PostRequest(message) ||
!req.GetResponse(&raw_response)) {
return false;
}
wvcdm::LicenseRequest helper;
helper.GetDrmMessage(raw_response, *response);
return true;
}
std::unique_ptr<Cdm> CreateCdm(EventListener* event_listener) {
std::unique_ptr<Cdm> ret(
create_func(event_listener, &g_host->per_origin_storage(), true));
if (ret) {
EXPECT_SUCCESS(ret->setServiceCertificate(
Cdm::kProvisioningService,
kTestData.provisioning_service_certificate()));
EXPECT_SUCCESS(ret->setServiceCertificate(
Cdm::kLicensingService, kTestData.license_service_certificate()));
}
return ret;
}
class GlobalEnv : public testing::Environment {
public:
GlobalEnv(InitFuncType init_func, const std::string& cert)
: init_func_(init_func), cert_(cert) {}
void SetUp() override {
// Manually set the logger because `TestHost` makes logging calls before
// the global logger is set in |init_func_|.
g_logger = &g_stderr_logger;
g_host = new TestHost;
if (!cert_.empty()) g_host->per_origin_storage().write("cert.bin", cert_);
Cdm::LogLevel log_level = Cdm::kErrors;
if (const char* verbose = getenv("VERBOSE_OUTPUT")) {
if (std::strcmp(verbose, "1") == 0) log_level = Cdm::kVerbose;
}
ASSERT_SUCCESS(init_func_(Cdm::kNoSecureOutput, &g_host->global_storage(),
g_host, g_host, &g_stderr_logger, log_level));
}
private:
const InitFuncType init_func_;
const std::string cert_;
};
} // namespace
class PerfTest : public testing::Test {};
TEST_F(PerfTest, LicenseExchange) {
EventListener event_listener;
auto cdm = CreateCdm(&event_listener);
ASSERT_TRUE(cdm);
ASSERT_EQ(cdm->getProvisioningStatus(), Cdm::kProvisioned);
PerfTracker create;
PerfTracker generate;
PerfTracker update;
PerfTracker close;
for (size_t i = 0; i < kTestCount; i++) {
std::string session_id;
MEASURE_PERF(create, ASSERT_SUCCESS(
cdm->createSession(Cdm::kTemporary, &session_id)));
MEASURE_PERF(
generate,
ASSERT_SUCCESS(cdm->generateRequest(
session_id, Cdm::kCenc,
wvcdm::ConfigTestEnv::GetInitData(wvcdm::kContentIdStreaming))));
std::string response;
ASSERT_TRUE(SendPost(event_listener.messages[0].message, &response));
MEASURE_PERF(update, ASSERT_SUCCESS(cdm->update(session_id, response)));
MEASURE_PERF(close, ASSERT_SUCCESS(cdm->close(session_id)));
event_listener.messages.pop_back();
}
create.Print("Create ");
generate.Print("Generate");
update.Print("Update ");
close.Print("Close ");
}
class DecryptPerfTest : public PerfTest,
public testing::WithParamInterface<bool> {};
TEST_P(DecryptPerfTest, Decrypt) {
EventListener event_listener;
auto cdm = CreateCdm(&event_listener);
ASSERT_TRUE(cdm);
ASSERT_EQ(cdm->getProvisioningStatus(), Cdm::kProvisioned);
std::string session_id;
ASSERT_SUCCESS(cdm->createSession(Cdm::kTemporary, &session_id));
ASSERT_SUCCESS(cdm->generateRequest(
session_id, Cdm::kCenc,
wvcdm::ConfigTestEnv::GetInitData(wvcdm::kContentIdStreaming)));
std::string response;
ASSERT_TRUE(SendPost(event_listener.messages[0].message, &response));
ASSERT_SUCCESS(cdm->update(session_id, response));
Cdm::KeyStatusMap statuses;
ASSERT_SUCCESS(cdm->getKeyStatuses(session_id, &statuses));
ASSERT_GT(statuses.size(), 0u);
const std::string key_id = statuses.begin()->first;
// Use in-place decrypt to avoid allocations. We don't care about the data,
// so we can just decrypt the same buffer again.
constexpr const size_t k16M = 16 * 1024 * 1024;
std::vector<uint8_t> buffer(k16M);
uint8_t iv[16];
for (auto& b : buffer) b = rand();
Cdm::DecryptionBatch batch;
batch.key_id = reinterpret_cast<const uint8_t*>(key_id.data());
batch.key_id_length = static_cast<uint32_t>(key_id.size());
if (GetParam()) {
batch.pattern.encrypted_blocks = batch.pattern.clear_blocks = 0;
} else {
batch.pattern.encrypted_blocks = 1;
batch.pattern.clear_blocks = 9;
}
batch.is_secure = false;
batch.encryption_scheme = GetParam() ? Cdm::kAesCtr : Cdm::kAesCbc;
batch.is_video = true;
Cdm::Subsample subsample;
subsample.clear_bytes = 0;
// subsample.encrypted_bytes set in the test.
Cdm::Sample sample;
sample.input.iv = iv;
sample.input.iv_length = 16;
sample.input.data = buffer.data();
// sample.data_length set in the test.
sample.input.subsamples = &subsample;
sample.input.subsamples_length = 1;
sample.output.data = buffer.data();
sample.output.data_offset = 0;
sample.output.data_length = static_cast<uint32_t>(buffer.size());
batch.samples = &sample;
batch.samples_length = 1;
constexpr const size_t block_sizes[] = {8 * 1024, 256 * 1024, k16M};
constexpr const size_t sizes_count =
sizeof(block_sizes) / sizeof(block_sizes[0]);
const std::string block_names[] = {" 8k", "256k", " 16M"};
PerfTracker perf[sizes_count];
for (size_t i = 0; i < sizes_count; i++) {
subsample.protected_bytes = sample.input.data_length =
sample.output.data_length = static_cast<uint32_t>(block_sizes[i]);
for (size_t j = 0; j < kTestCount; j++) {
MEASURE_PERF(perf[i], ASSERT_SUCCESS(cdm->decrypt(batch)));
}
}
for (size_t i = 0; i < sizes_count; i++) {
perf[i].Print("Decrypt " + block_names[i], block_sizes[i]);
}
}
std::string PrintDecryptParam(const testing::TestParamInfo<bool>& info) {
return info.param ? "CTR" : "CBC";
}
INSTANTIATE_TEST_SUITE_P(Decrypt, DecryptPerfTest, testing::Bool(),
PrintDecryptParam);
int PerfTestMain(InitFuncType init_func, CreateFuncType create,
const std::string& cert) {
#ifdef _DEBUG
// Don't use #error since we build all targets and we don't want to fail the
// debug build (and we can't have configuration-specific targets).
fprintf(stderr, "Don't run performance tests in Debug mode\n");
return 1;
#else
create_func = create;
testing::AddGlobalTestEnvironment(new GlobalEnv(init_func, cert));
return RUN_ALL_TESTS();
#endif
}
} // namespace widevine

View File

@@ -1,24 +0,0 @@
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
#ifndef WVCDM_CDM_TEST_PERF_TEST_H_
#define WVCDM_CDM_TEST_PERF_TEST_H_
#include <string>
#include "cdm.h"
namespace widevine {
using InitFuncType = Cdm::Status (*)(Cdm::SecureOutputType, Cdm::IStorage*,
Cdm::IClock*, Cdm::ITimer*, Cdm::ILogger*,
Cdm::LogLevel);
using CreateFuncType = Cdm* (*)(Cdm::IEventListener*, Cdm::IStorage*, bool);
int PerfTestMain(InitFuncType init_func, CreateFuncType create_func,
const std::string& cert);
} // namespace widevine
#endif // WVCDM_CDM_TEST_PERF_TEST_H_

View File

@@ -1,84 +0,0 @@
// Copyright 2021 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
// This uses dlopen() which is only usable on POSIX platforms. The function
// names assume GCC/Clang.
#include <dlfcn.h>
#include <gtest/gtest.h>
#include <stdio.h>
#include <fstream>
#include <tuple>
#include "clock.h"
#include "perf_test.h"
#include "test_host.h"
namespace widevine {
constexpr char kInitName[] =
"_ZN8widevine3Cdm10initializeENS0_16SecureOutputTypeEPNS0_8IStorageEPNS0_"
"6IClockEPNS0_6ITimerEPNS0_7ILoggerENS0_8LogLevelE";
constexpr char kCreateName[] =
"_ZN8widevine3Cdm6createEPNS0_14IEventListenerEPNS0_8IStorageEbb";
bool ReadFile(const std::string& path, std::string* output) {
constexpr size_t kReadSize = 8 * 1024;
std::ifstream fs(path, std::ios::in | std::ios::binary);
if (!fs) return false;
while (true) {
const size_t offset = output->size();
output->resize(output->size() + kReadSize);
fs.read(&output->at(offset), kReadSize);
if (fs.eof()) {
output->resize(offset + fs.gcount());
return true;
} else if (!fs) {
fprintf(stderr, "Error reading from cert file\n");
return false;
}
}
}
std::tuple<InitFuncType, CreateFuncType> LoadCdm(const char* path) {
// Note we will leak the library object; but this is just for tests and will
// be unloaded when we exit anyway.
auto dll = dlopen(path, RTLD_NOW);
if (!dll) {
fprintf(stderr, "Error loading so file: %s\n", dlerror());
exit(1);
}
auto init = reinterpret_cast<InitFuncType>(dlsym(dll, kInitName));
auto create = reinterpret_cast<CreateFuncType>(dlsym(dll, kCreateName));
if (!init || !create) {
fprintf(stderr, "Error finding CDM functions: %s\n", dlerror());
exit(1);
}
return std::make_tuple(init, create);
}
} // namespace widevine
namespace wvutil {
int64_t Clock::GetCurrentTime() { return g_host->now() / 1000; }
} // namespace wvutil
int main(int argc, char** argv) {
testing::InitGoogleTest(&argc, argv);
if (argc != 3) {
fprintf(stderr, "Usage: %s <CDM_SO_PATH> <CERT_PATH>\n", argv[0]);
return 1;
}
std::string cert;
if (!widevine::ReadFile(argv[2], &cert))
return 1;
auto funcs = widevine::LoadCdm(argv[1]);
return widevine::PerfTestMain(std::get<0>(funcs), std::get<1>(funcs), cert);
}

View File

@@ -1,26 +0,0 @@
// Copyright 2022 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
#include <gtest/gtest.h>
#import <XCTest/XCTest.h>
#include "cdm.h"
#include "perf_test.h"
@interface GtestTests : XCTestCase
@end
@implementation GtestTests
- (void)testAll {
testing::GTEST_FLAG(filter) = GTEST_FILTER;
char arg0[] = "tests";
char* argv[] = {arg0, nullptr};
int argc = 1;
testing::InitGoogleTest(&argc, argv);
XCTAssertEqual(widevine::PerfTestMain(&widevine::Cdm::initialize, &widevine::Cdm::create, ""), 0);
}
@end

View File

@@ -1,185 +0,0 @@
// 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 "test_host.h"
#include <gtest/gtest.h>
#include <chrono>
#include <unordered_set>
#include "cdm_version.h"
#include "file_store.h"
#include "log.h"
using namespace widevine;
namespace {
// Some files are expected to go in global storage. All other files are expected
// to go in per-origin storage. To help us enforce this in tests, this set
// tracks the filenames that belong in global storage. TestHost::Storage will
// reject attempts to access these files via per-origin storage or to access
// files not in this list via global storage.
const std::unordered_set<std::string> kGlobalFilenames = {
"usgtable.bin", // CDM usage table data
"StoredUsageTime.dat", // Reference OEMCrypto usage table data
"GenerationNumber.dat", // Reference OEMCrypto master generation number
"persistent.dat", // Persistent data storage for certain TEE
// implementations
"keybox.dat", // Legacy file for storing keybox in non-secure storage.
// CDM data for OTA keybox renewal.
"okp.bin",
"debug_ignore_keybox_count.txt",
"debug_allow_test_keybox.txt",
// Widevine L3 data files.
"ay64.dat",
"ay64.dat2",
"ay64.dat3",
"ay64.dat4",
"ay64.dat5",
"ay64.dat6",
"l3_failure_file",
wvutil::kOemCertificateFileName,
};
} // namespace
TestHost::TestHost() : global_storage_(true), per_origin_storage_(false) {
Reset();
}
TestHost::~TestHost() { wvutil::TestSleep::set_callback(nullptr); }
void TestHost::Reset() {
auto now = std::chrono::system_clock().now();
now_ = now.time_since_epoch() / std::chrono::milliseconds(1);
wvutil::TestSleep::set_callback(this);
// Surprisingly, std::priority_queue has no clear().
while (!timers_.empty()) {
timers_.pop();
}
global_storage_.Reset();
per_origin_storage_.Reset();
}
void TestHost::ElapseTime(int64_t milliseconds) {
// Note that, during the time rollback tests, milliseconds will be negative,
// so we cannot assume goal_time > now_.
int64_t goal_time = now_ + milliseconds;
// Walk forward from now_ to goal_time, stepping at each timer along the way
// to fire its callback.
while (!timers_.empty() && now_ < goal_time) {
Timer t = timers_.top();
ASSERT_GE(t.expiry_time(), now_);
if (t.expiry_time() <= goal_time) {
timers_.pop();
now_ = t.expiry_time();
t.client()->onTimerExpired(t.context());
} else {
// The next timer is further in the future than goal_time, so we are done
// processing the timers.
break;
}
}
// No matter what happened with the timers, update now_ to the goal_time.
now_ = goal_time;
}
size_t TestHost::NumTimers() const { return timers_.size(); }
int64_t TestHost::now() { return now_; }
void TestHost::setTimeout(int64_t delay_ms, IClient* client, void* context) {
int64_t expiry_time = now_ + delay_ms;
timers_.push(Timer(expiry_time, client, context));
}
void TestHost::cancel(IClient* client) {
// Filter out the timers for this client and put the rest into |others|.
std::priority_queue<Timer> others;
while (timers_.size()) {
Timer t = timers_.top();
timers_.pop();
if (t.client() != client) {
others.push(t);
}
}
// Now swap the queues.
std::swap(timers_, others);
}
TestHost::Storage::Storage(bool is_global) : is_global_(is_global) { Reset(); }
void TestHost::Storage::Reset() {
files_.clear();
}
bool TestHost::Storage::read(const std::string& name, std::string* data) {
StorageMap::iterator it = files_.find(name);
bool ok = it != files_.end();
LOGV("read file: %s: %s", name.c_str(), ok ? "ok" : "fail");
if (!CheckFilename(name) || !ok) return false;
*data = it->second;
return true;
}
bool TestHost::Storage::write(const std::string& name,
const std::string& data) {
LOGV("write file: %s", name.c_str());
if (!CheckFilename(name)) return false;
files_[name] = data;
return true;
}
bool TestHost::Storage::exists(const std::string& name) {
StorageMap::iterator it = files_.find(name);
bool ok = it != files_.end();
LOGV("exists? %s: %s", name.c_str(), ok ? "true" : "false");
if (!CheckFilename(name)) return false;
return ok;
}
bool TestHost::Storage::remove(const std::string& name) {
if (name.empty()) {
// If no name, delete all files (see DeviceFiles::DeleteAllFiles())
LOGV("remove all files");
files_.clear();
return true;
}
LOGV("remove: %s", name.c_str());
if (!CheckFilename(name)) return false;
return files_.erase(name) > 0;
}
int32_t TestHost::Storage::size(const std::string& name) {
StorageMap::iterator it = files_.find(name);
bool ok = (it != files_.end());
LOGV("size? %s: %s", name.c_str(), ok ? "ok" : "fail");
if (!CheckFilename(name) || !ok) return -1;
return static_cast<int32_t>(it->second.size());
}
bool TestHost::Storage::list(std::vector<std::string>* names) {
names->clear();
for (StorageMap::iterator it = files_.begin(); it != files_.end(); it++) {
names->push_back(it->first);
}
return true;
}
bool TestHost::Storage::CheckFilename(const std::string& name) {
const bool is_global_filename =
(kGlobalFilenames.find(name) != kGlobalFilenames.end());
if (is_global_ != is_global_filename) {
LOGE("Attempt to access %s in %s storage rejected.", name.c_str(),
is_global_ ? "global" : "per-origin");
return false;
}
return true;
}

View File

@@ -1,101 +0,0 @@
// Copyright 2018 Google LLC. All Rights Reserved. This file and proprietary
// source code may only be used and distributed under the Widevine License
// Agreement.
#ifndef WVCDM_CDM_TEST_TEST_HOST_H_
#define WVCDM_CDM_TEST_TEST_HOST_H_
#include <map>
#include <queue>
#include <string>
#include <vector>
#include "cdm.h"
#include "stderr_logger.h"
#include "test_sleep.h"
// This provides a host environment for running CDM tests. It implements the
// IStorage, IClock and ITimer interfaces that a host would normally implement,
// while allowing them to be manipulated by the test.
class TestHost : public widevine::Cdm::IClock,
public widevine::Cdm::ITimer,
public wvutil::TestSleep::CallBack {
public:
class Storage : public widevine::Cdm::IStorage {
public:
typedef std::map<std::string, std::string> StorageMap;
explicit Storage(bool is_global);
~Storage() override {}
void Reset();
// Reset the file system to contain the specified files.
void ResetFiles(const StorageMap& files) { files_ = files; };
const StorageMap& files() const { return files_; }
// widevine::Cdm::IStorage
bool read(const std::string& name, std::string* data) override;
bool write(const std::string& name, const std::string& data) override;
bool exists(const std::string& name) override;
bool remove(const std::string& name) override;
int32_t size(const std::string& name) override;
bool list(std::vector<std::string>* names) override;
private:
bool is_global_;
StorageMap files_;
bool CheckFilename(const std::string& name);
};
TestHost();
~TestHost() override;
void Reset();
// Used for manipulating and inspecting timer states during testing.
void ElapseTime(int64_t milliseconds) override;
size_t NumTimers() const;
Storage& global_storage() { return global_storage_; }
Storage& per_origin_storage() { return per_origin_storage_; }
// widevine::Cdm::IClock
int64_t now() override;
// widevine::Cdm::ITimer
void setTimeout(int64_t delay_ms, IClient* client, void* context) override;
void cancel(IClient* client) override;
private:
struct Timer {
Timer(int64_t expiry_time, IClient* client, void* context)
: expiry_time_(expiry_time), client_(client), context_(context) {}
bool operator<(const Timer& other) const {
// We want to reverse the order so that the smallest expiry times go to
// the top of the priority queue.
return expiry_time_ > other.expiry_time_;
}
int64_t expiry_time() { return expiry_time_; }
IClient* client() { return client_; }
void* context() { return context_; }
private:
int64_t expiry_time_;
IClient* client_;
void* context_;
};
int64_t now_;
std::priority_queue<Timer> timers_;
Storage global_storage_;
Storage per_origin_storage_;
};
// Owned and managed by the test runner.
extern TestHost* g_host;
extern widevine::StderrLogger g_stderr_logger;
extern std::string g_sandbox_id;
#endif // WVCDM_CDM_TEST_TEST_HOST_H_

View File

@@ -1,14 +0,0 @@
# Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
# source code may only be used and distributed under the Widevine License
# Agreement.
{
'variables': {
'wvutil_sources': [
'../util/src/cdm_random.cpp',
'../util/src/platform.cpp',
'../util/src/rw_lock.cpp',
'../util/src/string_conversions.cpp',
'../util/src/string_format.cpp',
],
},
}

View File

@@ -1,19 +0,0 @@
# Copyright 2019 Google LLC. All Rights Reserved. This file and proprietary
# source code may only be used and distributed under the Widevine License
# Agreement.
{
'sources': [
'../util/test/base64_test.cpp',
'../util/test/cdm_random_unittest.cpp',
# TODO(b/167126046): Needs test vectors
# '../util/test/file_store_unittest.cpp',
'../util/test/string_format_unittest.cpp',
],
'include_dirs': [
'../util/include'
],
'defines': [
'UNIT_TEST',
'UTIL_TESTS'
]
}