diff --git a/whitebox-impl/impl/BUILD b/whitebox-impl/impl/BUILD index af074b1..d5dacad 100644 --- a/whitebox-impl/impl/BUILD +++ b/whitebox-impl/impl/BUILD @@ -7,11 +7,7 @@ # # test_aead_whitebox : The target for testing the AEAD white-box. # -# general_license_whitebox_with_vmpra : The target for testing the license -# white-box against generated licenses with VMP/RA functionality. -# -# general_license_whitebox_without_vmpra : The target for testing the license -# white-box against generated licenses without VMP/RA functionality. +# general_license_whitebox: The target for testing the license white-box. # # uat_license_whitebox : The target for testing the license white-box against # licenses from Widevine's UAT server. @@ -26,12 +22,7 @@ cc_library( ) cc_library( - name = "general_license_whitebox_with_vmpra", - visibility = ["//visibility:public"], -) - -cc_library( - name = "general_license_whitebox_without_vmpra", + name = "general_license_whitebox", visibility = ["//visibility:public"], ) diff --git a/whitebox-impl/tests/BUILD b/whitebox-impl/tests/BUILD index f4f1898..e821591 100644 --- a/whitebox-impl/tests/BUILD +++ b/whitebox-impl/tests/BUILD @@ -13,11 +13,7 @@ package(default_visibility = [ # # test_aead_whitebox : The target for testing the AEAD white-box. # -# general_license_whitebox_with_vmpra : The target for testing the license -# white-box against generated licenses with VMP/RA functionality. -# -# general_license_whitebox_without_vmpra : The target for testing the license -# white-box against generated licenses without VMP/RA functionality. +# general_license_whitebox: The target for testing the license white-box. # # uat_license_whitebox : The target for testing the license white-box against # licenses from Widevine's UAT server. @@ -53,25 +49,16 @@ cc_test( size = "small", deps = [ "@whitebox_api//api:license_whitebox_test", - "//impl:general_license_whitebox_without_vmpra", + "//impl:general_license_whitebox", ], ) cc_test( - name = "remote_attestation_and_verification_with_vmpra_test", + name = "remote_attestation_and_verification_test", size = "small", deps = [ - "@whitebox_api//api:remote_attestation_and_verification_with_vmpra_test", - "//impl:general_license_whitebox_with_vmpra", - ], -) - -cc_test( - name = "remote_attestation_and_verification_without_vmpra_test", - size = "small", - deps = [ - "@whitebox_api//api:remote_attestation_and_verification_without_vmpra_test", - "//impl:general_license_whitebox_without_vmpra", + "@whitebox_api//api:remote_attestation_and_verification_test", + "//impl:general_license_whitebox", ], ) @@ -80,7 +67,7 @@ cc_test( size = "small", deps = [ "@whitebox_api//api:license_whitebox_benchmark", - "//impl:general_license_whitebox_without_vmpra", + "//impl:general_license_whitebox", ], ) diff --git a/whitebox/BUILD b/whitebox/BUILD new file mode 100644 index 0000000..fb083ec --- /dev/null +++ b/whitebox/BUILD @@ -0,0 +1,40 @@ +# Copyright 2022 Google LLC. All Rights Reserved. + +load("//:defs.bzl", "build_type") + +build_type(name="build_type", build_setting_default="chrome") + +config_setting( + name="is_chrome", + flag_values={ + "//:build_type": "chrome", + } +) + +config_setting( + name="is_chromeos", + flag_values={ + "//:build_type": "chromeos", + } +) + +config_setting( + name="is_ce", + flag_values={ + "//:build_type": "ce", + } +) + +config_setting( + name="is_old_api", + flag_values={ + "//:build_type": "old", + } +) + +config_setting( + name="is_old_vmpra", + flag_values={ + "//:build_type": "old_vmpra", + } +) diff --git a/whitebox/README.md b/whitebox/README.md index d0e6c1d..060a86a 100644 --- a/whitebox/README.md +++ b/whitebox/README.md @@ -30,6 +30,27 @@ To build the full repo and run all tests, from within or below the repo root bazel build "//..." bazel test "//..." ``` +## Security Level + +There are two possible interpretations of the `SW_SECURE_DECODE` security level: +first is used by Chrome, where it can only be used with the "masked" decrypt +path; the second is used by the CE CDM where it is treated the same as +`SW_SECURE_CRYPTO`. + +Both the tests and the reference implementation support both interpretations. +Selecting which one is done using a pre-processor define +`ALWAYS_DECRYPT_TO_CLEAR`. This is set automatically by Bazel based on the +build type, which can be set with either `--//:build_type=chrome` or +`--//:build_type=ce` (defaulting to Chrome). This also controls the tests and +their expectations. e.g. + +```bash +bazel test ... --//:build_type=ce +``` + +The external implementations don't need to use this pre-processor define to +control which interpretation is used, but it must conform to one of them and +pass the associated tests. ## API diff --git a/whitebox/api/BUILD b/whitebox/api/BUILD index acb6639..108491b 100644 --- a/whitebox/api/BUILD +++ b/whitebox/api/BUILD @@ -2,12 +2,34 @@ package(default_visibility = ["//visibility:private"]) +cc_library( + name = "shared_settings", + defines = select({ + "//:is_ce": [ + "ALWAYS_DECRYPT_TO_CLEAR", + "HAS_ENTITLEMENT", + "HAS_SIGN_PST_REPORT", + ], + "//:is_old_api": [], + "//:is_old_vmpra": [], + "//conditions:default": [ + "HAS_PROVIDER_KEYS", + ], + }) + select({ + "//:is_chromeos": ["WV_ENABLE_HW_VERIFICATION=1"], + "//:is_old_vmpra": ["WV_ENABLE_HW_VERIFICATION=1"], + "//conditions:default": ["WV_ENABLE_HW_VERIFICATION=0"], + }), + visibility = ["//visibility:public"], +) + cc_library( name = "result", hdrs = [ "result.h", ], visibility = ["//visibility:public"], + deps = [":shared_settings"], ) cc_library( @@ -18,6 +40,7 @@ cc_library( visibility = ["//visibility:public"], deps = [ ":result", + ":shared_settings", ], ) @@ -29,6 +52,21 @@ cc_library( visibility = ["//visibility:public"], deps = [ ":result", + ":shared_settings", + ], +) + +cc_library( + name = "license_whitebox_proxy", + srcs = select({ + "//:is_old_api": ["license_whitebox_proxy_impl.cc"], + "//:is_old_vmpra": ["license_whitebox_proxy_impl.cc"], + "//conditions:default": [], + }), + visibility = ["//visibility:public"], + deps = [ + ":license_whitebox", + ":license_whitebox_provider_keys_test_data", ], ) @@ -37,6 +75,7 @@ cc_library( hdrs = [ "test_key_types.h", ], + deps = [":shared_settings"], ) # This target provided the header needed to access the test keys. The @@ -49,6 +88,7 @@ cc_library( "test_license_whitebox_keys.h", ], visibility = ["//visibility:public"], + deps = [":shared_settings"], ) cc_library( @@ -57,7 +97,11 @@ cc_library( "test_license_whitebox_keys_general.cc", ], visibility = ["//visibility:public"], - deps = [":test_license_whitebox_keys"], + deps = [ + ":license_whitebox_proxy", + ":shared_settings", + ":test_license_whitebox_keys", + ], ) cc_library( @@ -66,7 +110,11 @@ cc_library( "test_license_whitebox_keys_uat.cc", ], visibility = ["//visibility:public"], - deps = [":test_license_whitebox_keys"], + deps = [ + ":license_whitebox_proxy", + ":shared_settings", + ":test_license_whitebox_keys", + ], ) cc_library( @@ -75,6 +123,7 @@ cc_library( "aead_test_data.h", ], visibility = ["//visibility:public"], + deps = [":shared_settings"], ) cc_library( @@ -86,6 +135,7 @@ cc_library( "test_license_provider_keys.h", ], visibility = ["//visibility:public"], + deps = [":shared_settings"], ) cc_library( @@ -94,6 +144,7 @@ cc_library( "license_whitebox_provider_keys_test_data.h", ], visibility = ["//visibility:public"], + deps = [":shared_settings"], ) cc_library( @@ -105,6 +156,7 @@ cc_library( "golden_data.h", ], deps = [ + ":shared_settings", ":test_key_types", "//chromium_deps/cdm/protos:license_protocol_proto", ], @@ -115,6 +167,7 @@ cc_library( srcs = ["test_server.cc"], hdrs = ["test_server.h"], deps = [ + ":shared_settings", ":test_license_whitebox_keys", "//chromium_deps/base:glog", "//crypto_utils:rsa_key", @@ -127,6 +180,7 @@ cc_library( hdrs = ["test_license_builder.h"], visibility = ["//visibility:public"], deps = [ + ":shared_settings", ":test_key_types", ":test_license_provider_keys", ":test_server", @@ -150,6 +204,7 @@ cc_library( deps = [ ":aead_test_data", ":aead_whitebox", + ":shared_settings", "//chromium_deps/testing", ], alwayslink = True, @@ -164,6 +219,7 @@ cc_library( deps = [ ":aead_test_data", ":aead_whitebox", + ":shared_settings", "//benchmarking:data_source", "//benchmarking:measurements", "//chromium_deps/base:glog", @@ -184,6 +240,8 @@ cc_library( ":golden_data", ":license_whitebox", ":license_whitebox_provider_keys_test_data", + ":license_whitebox_proxy", + ":shared_settings", ":test_license_whitebox_keys", "//chromium_deps/testing", "//crypto_utils:rsa_key", @@ -215,6 +273,7 @@ cc_library( ":license_whitebox", ":license_whitebox_provider_keys_test_data", ":license_whitebox_test_base", + ":shared_settings", ":test_license_builder", "//chromium_deps/testing", ], @@ -222,31 +281,15 @@ cc_library( ) cc_library( - name = "remote_attestation_and_verification_with_vmpra_test", + name = "remote_attestation_and_verification_test", srcs = [ "remote_attestation_and_verification_test.cc", ], - defines = ["WV_ENABLE_HW_VERIFICATION=1"], - visibility = ["//visibility:public"], - deps = [ - ":license_whitebox", - ":license_whitebox_test_base", - ":test_license_builder", - "//chromium_deps/testing", - ], - alwayslink = True, -) - -cc_library( - name = "remote_attestation_and_verification_without_vmpra_test", - srcs = [ - "remote_attestation_and_verification_test.cc", - ], - defines = ["WV_ENABLE_HW_VERIFICATION=0"], visibility = ["//visibility:public"], deps = [ ":license_whitebox", ":license_whitebox_test_base", + ":shared_settings", ":test_license_builder", "//chromium_deps/testing", ], @@ -269,6 +312,7 @@ cc_library( deps = [ ":license_whitebox", ":license_whitebox_provider_keys_test_data", + ":shared_settings", ":test_key_types", ":test_license_builder", ":test_license_whitebox_keys", @@ -290,6 +334,7 @@ cc_library( deps = [ ":license_whitebox", ":license_whitebox_provider_keys_test_data", + ":shared_settings", "//chromium_deps/testing", ], alwayslink = True, diff --git a/whitebox/api/license_whitebox_decrypt_test.cc b/whitebox/api/license_whitebox_decrypt_test.cc index 78a571f..7df3786 100644 --- a/whitebox/api/license_whitebox_decrypt_test.cc +++ b/whitebox/api/license_whitebox_decrypt_test.cc @@ -47,7 +47,7 @@ class LicenseWhiteboxDecryptTest // Creates and loads a license. The license is created using |settings| // updated to include the test parameters. The license is loaded using // |provider_key_id|. - void LoadLicense(const TestLicenseBuilder::Settings& settings, + bool LoadLicense(const TestLicenseBuilder::Settings& settings, size_t provider_key_id) { TestLicenseBuilder builder; builder.SetSettings(settings); @@ -69,15 +69,19 @@ class LicenseWhiteboxDecryptTest License license; builder.Build(*server, &license); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license.core_message.data(), license.core_message.size(), - license.message.data(), license.message.size(), - license.signature.data(), license.signature.size(), - license.session_key.data(), license.session_key.size(), - provider_key_id, license.request.data(), license.request.size()), - WB_RESULT_OK); + const auto result = WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license.core_message.data(), + license.core_message.size(), license.message.data(), + license.message.size(), license.signature.data(), + license.signature.size(), license.session_key.data(), + license.session_key.size(), provider_key_id, license.request.data(), + license.request.size()); +#ifndef HAS_PROVIDER_KEYS + if (provider_key_id != 0 && result == WB_RESULT_NOT_IMPLEMENTED) + return false; +#endif + EXPECT_EQ(result, WB_RESULT_OK); + return true; } // We need two special keys for this test, one that will be used for a @@ -95,7 +99,8 @@ class LicenseWhiteboxDecryptTest TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCbcDataInCbcMode) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -113,7 +118,8 @@ TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCbcDataInCbcMode) { TEST_P(LicenseWhiteboxDecryptTest, InPlaceDecryptionCbc) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); memcpy(plaintext_.data(), golden_data_.CBCContent().ciphertext.data(), golden_data_.CBCContent().ciphertext.size()); @@ -133,7 +139,8 @@ TEST_P(LicenseWhiteboxDecryptTest, InPlaceDecryptionCbc) { TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCtrDataInCtrMode) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CTR, @@ -151,7 +158,8 @@ TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCtrDataInCtrMode) { TEST_P(LicenseWhiteboxDecryptTest, InPlaceDecryptionCtr) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); memcpy(plaintext_.data(), golden_data_.CTRContent().ciphertext.data(), golden_data_.CTRContent().ciphertext.size()); @@ -173,7 +181,8 @@ TEST_P(LicenseWhiteboxDecryptTest, InPlaceDecryptionCtr) { // successful, but the resulting plaintext should not match. TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCbcDataInCtrMode) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CTR, @@ -193,7 +202,8 @@ TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCbcDataInCtrMode) { // successful, but the resulting plaintext should not match. TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCtrDataInCbcMode) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -213,7 +223,8 @@ TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCtrDataInCbcMode) { // different keys can be used at the same time. TEST_P(LicenseWhiteboxDecryptTest, SuccessWithMultipleKeys) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -250,7 +261,8 @@ TEST_P(LicenseWhiteboxDecryptTest, SuccessWithMultipleKeys) { TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullWhitebox) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_Decrypt( nullptr, WB_CIPHER_MODE_CBC, @@ -266,7 +278,8 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullWhitebox) { TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidCipherMode) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); // In order to trick the compiler into letting us pass an invalid enum value // to WB__License_Decrypt(), we need to cast it. If we don't do this, the @@ -287,7 +300,8 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidCipherMode) { TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullKeyId) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, nullptr, @@ -302,7 +316,8 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullKeyId) { TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForZeroKeyIdSize) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -317,7 +332,8 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForZeroKeyIdSize) { TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullInputData) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -334,7 +350,8 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullInputData) { // not care. TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidCBCInputDataSize) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -350,7 +367,8 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidCBCInputDataSize) { // The white-box (using any cipher mode) should reject input with size zero. TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForZeroInputDataSize) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -365,7 +383,8 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForZeroInputDataSize) { TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullIV) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -381,7 +400,8 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullIV) { // IV size should be 16. Any number other than 16 should fail. TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidIVSize) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -396,7 +416,8 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidIVSize) { TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullOutput) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -411,7 +432,8 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullOutput) { TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullOutputSize) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ( WB_License_Decrypt( @@ -430,7 +452,8 @@ TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullOutputSize) { // and "dropped content key", as those keys were in the license but ignored. TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForMissingKeyId) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_Decrypt(whitebox_, WB_CIPHER_MODE_CBC, missing_key_id_.data(), missing_key_id_.size(), @@ -444,7 +467,8 @@ TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForMissingKeyId) { TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForNonContentKey) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ( WB_License_Decrypt(whitebox_, WB_CIPHER_MODE_CBC, @@ -462,7 +486,8 @@ TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForNonContentKey) { TEST_P(LicenseWhiteboxDecryptTest, InsufficientSecurityLevelForHardwareContentKey) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_Decrypt(whitebox_, WB_CIPHER_MODE_CBC, golden_data_.CBCContent().hardware_key.id.data(), @@ -477,10 +502,16 @@ TEST_P(LicenseWhiteboxDecryptTest, TEST_P(LicenseWhiteboxDecryptTest, InsufficientSecurityLevelForDecodeKey) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); - // Use the software decode key as they are limited to - // WB_License_Decrypt(). + // Use the software decode key as they are limited to + // WB_License_Decrypt(). +#ifdef ALWAYS_DECRYPT_TO_CLEAR + const auto expected = WB_RESULT_OK; +#else + const auto expected = WB_RESULT_INSUFFICIENT_SECURITY_LEVEL; +#endif ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, golden_data_.CBCContent().software_decode_key.id.data(), @@ -490,12 +521,13 @@ TEST_P(LicenseWhiteboxDecryptTest, InsufficientSecurityLevelForDecodeKey) { golden_data_.CBCContent().iv.data(), golden_data_.CBCContent().iv.size(), plaintext_.data(), &plaintext_size_), - WB_RESULT_INSUFFICIENT_SECURITY_LEVEL); + expected); } TEST_P(LicenseWhiteboxDecryptTest, BufferTooSmall) { TestLicenseBuilder::Settings settings; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); // Our ciphertext will be large enough that we should not need to worry about // using a constant here. @@ -540,7 +572,8 @@ TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForInvalidKey) { // we just need an invalid key, so we use one way of invalidating the key. TestLicenseBuilder::Settings settings; settings.include_content_key_iv = false; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_Decrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -577,7 +610,8 @@ TEST_P(LicenseWhiteboxDecryptTest, MismatchProviderKeyId) { } TestLicenseBuilder::Settings settings; - LoadLicense(settings, other_provider_key_id); + if (!LoadLicense(settings, other_provider_key_id)) + GTEST_SKIP(); // Decryption should succeed, but the plaintext should be incorrect. ASSERT_EQ(WB_License_Decrypt( diff --git a/whitebox/api/license_whitebox_entitlement_content_key_test.cc b/whitebox/api/license_whitebox_entitlement_content_key_test.cc index c9b4af9..41b39cf 100644 --- a/whitebox/api/license_whitebox_entitlement_content_key_test.cc +++ b/whitebox/api/license_whitebox_entitlement_content_key_test.cc @@ -32,29 +32,31 @@ class LicenseWhiteboxEntitlementContentKeyTest }; TEST_F(LicenseWhiteboxEntitlementContentKeyTest, Decrypt) { - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - kNoProviderKeyId, license_.request.data(), - license_.request.size()), - WB_RESULT_OK); + auto result = WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, license_.request.data(), + license_.request.size()); +#ifndef HAS_ENTITLEMENT + if (result == WB_RESULT_NOT_IMPLEMENTED) + GTEST_SKIP(); +#endif + ASSERT_EQ(result, WB_RESULT_OK); const KeyId key_id = golden_data_.GetFreeId(); auto& content = golden_data_.EntitlementContent(); - ASSERT_EQ(WB_License_LoadEntitledContentKey( - whitebox_, - content.entitlement_key.id.data(), - content.entitlement_key.id.size(), - key_id.data(), - key_id.size(), - content.key_data_iv.data(), - content.key_data_iv.size(), - content.key_data.data(), - content.key_data.size()), - WB_RESULT_OK); + result = WB_License_LoadEntitledContentKey( + whitebox_, content.entitlement_key.id.data(), + content.entitlement_key.id.size(), key_id.data(), key_id.size(), + content.key_data_iv.data(), content.key_data_iv.size(), + content.key_data.data(), content.key_data.size()); +#ifndef HAS_ENTITLEMENT + if (result == WB_RESULT_NOT_IMPLEMENTED) + GTEST_SKIP(); +#endif + ASSERT_EQ(result, WB_RESULT_OK); std::vector decrypted(content.plaintext.size()); size_t decrypted_size = decrypted.size(); diff --git a/whitebox/api/license_whitebox_masked_decrypt_test.cc b/whitebox/api/license_whitebox_masked_decrypt_test.cc index 5f7ca4d..982c816 100644 --- a/whitebox/api/license_whitebox_masked_decrypt_test.cc +++ b/whitebox/api/license_whitebox_masked_decrypt_test.cc @@ -54,7 +54,7 @@ class LicenseWhiteboxMaskedDecryptTest // Creates and loads a license. The license is created using |settings| // updated to include the test parameters. The license is loaded using // |provider_key_id|. - void LoadLicense(const TestLicenseBuilder::Settings& settings, + bool LoadLicense(const TestLicenseBuilder::Settings& settings, size_t provider_key_id) { TestLicenseBuilder builder; builder.SetSettings(settings); @@ -75,15 +75,19 @@ class LicenseWhiteboxMaskedDecryptTest License license; builder.Build(*server, &license); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license.core_message.data(), license.core_message.size(), - license.message.data(), license.message.size(), - license.signature.data(), license.signature.size(), - license.session_key.data(), license.session_key.size(), - provider_key_id, license.request.data(), license.request.size()), - WB_RESULT_OK); + const auto result = WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license.core_message.data(), + license.core_message.size(), license.message.data(), + license.message.size(), license.signature.data(), + license.signature.size(), license.session_key.data(), + license.session_key.size(), provider_key_id, license.request.data(), + license.request.size()); +#ifndef HAS_PROVIDER_KEYS + if (provider_key_id != 0 && result == WB_RESULT_NOT_IMPLEMENTED) + return false; +#endif + EXPECT_EQ(result, WB_RESULT_OK); + return true; } // We need two special keys for this test, one that will be used for a @@ -106,7 +110,8 @@ class LicenseWhiteboxMaskedDecryptTest TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCbcMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -145,7 +150,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCbcMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyInPlaceCbc) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); memcpy(masked_text_.data(), golden_data_.CBCContent().ciphertext.data(), golden_data_.CBCContent().ciphertext.size()); @@ -186,7 +192,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyInPlaceCbc) { TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCtrMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CTR, @@ -225,7 +232,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCtrMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyInPlaceCtr) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); memcpy(masked_text_.data(), golden_data_.CTRContent().ciphertext.data(), golden_data_.CTRContent().ciphertext.size()); @@ -268,7 +276,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyInPlaceCtr) { TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCtrMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CTR, @@ -308,7 +317,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCbcDataInCtrMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCbcMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -346,7 +356,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, DecodeKeyWithCtrDataInCbcMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCbcMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -385,7 +396,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCbcMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCtrMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CTR, @@ -426,7 +438,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCtrMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCtrMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CTR, @@ -466,7 +479,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataInCtrMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCbcMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -504,7 +518,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataInCbcMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataAndPKCS8Padding) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kPKSC8; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -543,7 +558,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCbcDataAndPKCS8Padding) { TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataAndPKCS8Padding) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kPKSC8; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CTR, @@ -587,7 +603,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, CryptoKeyWithCtrDataAndPKCS8Padding) { TEST_P(LicenseWhiteboxMaskedDecryptTest, SuccessWithMultipleKeys) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -667,7 +684,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, SuccessWithMultipleKeys) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullWhitebox) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( nullptr, WB_CIPHER_MODE_CBC, @@ -684,7 +702,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullWhitebox) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidCipherMode) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); // In order to trick the compiler into letting us pass an invalid enum value // to WB__License_MaskedDecrypt(), we need to cast it. If we don't do this, @@ -706,7 +725,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidCipherMode) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullKeyId) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, nullptr, @@ -722,7 +742,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullKeyId) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullZeroKeyIdSize) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -738,7 +759,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullZeroKeyIdSize) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullInputData) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -757,7 +779,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidCBCInputDataSize) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -774,7 +797,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForZeroInputDataSize) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -790,7 +814,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForZeroInputDataSize) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullIV) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -807,7 +832,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullIV) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidIVSize) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -823,7 +849,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForInvalidIVSize) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullOutput) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ( WB_License_MaskedDecrypt( @@ -840,7 +867,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullOutput) { TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullOutputSize) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ( WB_License_MaskedDecrypt( @@ -860,7 +888,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidParameterForNullOutputSize) { TEST_P(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForMissingKeyId) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ( WB_License_MaskedDecrypt(whitebox_, WB_CIPHER_MODE_CBC, @@ -876,7 +905,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForMissingKeyId) { TEST_P(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForNonContentKey) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, non_content_key_id_.data(), @@ -895,7 +925,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InsufficientSecurityLevelForHardwareContentKey) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ( WB_License_MaskedDecrypt(whitebox_, WB_CIPHER_MODE_CBC, @@ -928,7 +959,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, InvalidState) { TEST_P(LicenseWhiteboxMaskedDecryptTest, BufferTooSmall) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); // Our ciphertext will be large enough that we should not need to worry about // using a constant here. @@ -955,7 +987,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, BufferTooSmall) { TEST_P(LicenseWhiteboxMaskedDecryptTest, SuccessForSubRangeUnmask) { TestLicenseBuilder::Settings settings; settings.padding = TestLicenseBuilder::Padding::kNone; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -997,7 +1030,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, KeyUnavailableForInvalidKey) { // we just need an invalid key, so we use one way of invalidating the key. TestLicenseBuilder::Settings settings; settings.include_content_key_iv = false; - LoadLicense(settings, provider_key_id_); + if (!LoadLicense(settings, provider_key_id_)) + GTEST_SKIP(); ASSERT_EQ(WB_License_MaskedDecrypt( whitebox_, WB_CIPHER_MODE_CBC, @@ -1034,7 +1068,8 @@ TEST_P(LicenseWhiteboxMaskedDecryptTest, MismatchProviderKeyId) { } TestLicenseBuilder::Settings settings; - LoadLicense(settings, alternate_provider_key_id); + if (!LoadLicense(settings, alternate_provider_key_id)) + GTEST_SKIP(); // Decryption should succeed, but the plaintext should be incorrect. ASSERT_EQ(WB_License_MaskedDecrypt( diff --git a/whitebox/api/license_whitebox_process_license_response_benchmark.cc b/whitebox/api/license_whitebox_process_license_response_benchmark.cc index a206431..6bc9afc 100644 --- a/whitebox/api/license_whitebox_process_license_response_benchmark.cc +++ b/whitebox/api/license_whitebox_process_license_response_benchmark.cc @@ -95,14 +95,18 @@ TEST_P(LicenseWhiteboxProcessLicenseResponseBenchmark, WB_License_Create(init_data_.data(), init_data_.size(), &whitebox_), WB_RESULT_OK); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, key_mode_, license_.core_message.data(), - license_.core_message.size(), license_.message.data(), - license_.message.size(), license_.signature.data(), - license_.signature.size(), license_.session_key.data(), - license_.session_key.size(), provider_key_id_, - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + const auto result = WB_License_ProcessLicenseResponse( + whitebox_, key_mode_, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), provider_key_id_, license_.request.data(), + license_.request.size()); +#ifndef HAS_PROVIDER_KEYS + if (provider_key_id_ != 0 && result == WB_RESULT_NOT_IMPLEMENTED) + GTEST_SKIP(); +#endif + ASSERT_EQ(result, WB_RESULT_OK); WB_License_Delete(whitebox_); @@ -130,14 +134,18 @@ TEST_P(LicenseWhiteboxProcessLicenseResponseBenchmark, WB_License_Create(init_data_.data(), init_data_.size(), &whitebox_), WB_RESULT_OK); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, key_mode_, license_.core_message.data(), - license_.core_message.size(), license_.message.data(), - license_.message.size(), license_.signature.data(), - license_.signature.size(), license_.session_key.data(), - license_.session_key.size(), provider_key_id_, - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + const auto result = WB_License_ProcessLicenseResponse( + whitebox_, key_mode_, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), provider_key_id_, license_.request.data(), + license_.request.size()); +#ifndef HAS_PROVIDER_KEYS + if (provider_key_id_ != 0 && result == WB_RESULT_NOT_IMPLEMENTED) + GTEST_SKIP(); +#endif + ASSERT_EQ(result, WB_RESULT_OK); sampler.Push(timer.Get()); @@ -163,14 +171,18 @@ TEST_P(LicenseWhiteboxProcessLicenseResponseBenchmark, ProcessLicenseResponse) { timer.Reset(); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, key_mode_, license_.core_message.data(), - license_.core_message.size(), license_.message.data(), - license_.message.size(), license_.signature.data(), - license_.signature.size(), license_.session_key.data(), - license_.session_key.size(), provider_key_id_, - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + const auto result = WB_License_ProcessLicenseResponse( + whitebox_, key_mode_, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), provider_key_id_, license_.request.data(), + license_.request.size()); +#ifndef HAS_PROVIDER_KEYS + if (provider_key_id_ != 0 && result == WB_RESULT_NOT_IMPLEMENTED) + GTEST_SKIP(); +#endif + ASSERT_EQ(result, WB_RESULT_OK); sampler.Push(timer.Get()); diff --git a/whitebox/api/license_whitebox_process_license_response_test.cc b/whitebox/api/license_whitebox_process_license_response_test.cc index 968463a..34a3e66 100644 --- a/whitebox/api/license_whitebox_process_license_response_test.cc +++ b/whitebox/api/license_whitebox_process_license_response_test.cc @@ -103,15 +103,18 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseTest, SuccessWithEntitlementKey) { UseLicenseWithEntitlementKey(); - ASSERT_EQ(WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, - license_.core_message.data(), license_.core_message.size(), - license_.message.data(), license_.message.size(), - license_.signature.data(), license_.signature.size(), - license_.session_key.data(), license_.session_key.size(), - kNoProviderKeyId, license_.request.data(), - license_.request.size()), - WB_RESULT_OK); + const auto result = WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kNoProviderKeyId, license_.request.data(), + license_.request.size()); +#ifndef HAS_ENTITLEMENT + if (result == WB_RESULT_NOT_IMPLEMENTED) + GTEST_SKIP(); +#endif + ASSERT_EQ(result, WB_RESULT_OK); } // If there were multiple signing keys (this can only happen if a license server @@ -163,15 +166,18 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseTest, SuccessWithProviderKey) { builder.AddContentKey(golden_data_.CBCContent().software_crypto_key); builder.Build(*server_, &license_); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), - license_.core_message.size(), license_.message.data(), - license_.message.size(), license_.signature.data(), - license_.signature.size(), license_.session_key.data(), - license_.session_key.size(), kProviderKeyId, license_.request.data(), - license_.request.size()), - WB_RESULT_OK); + const auto result = WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kProviderKeyId, license_.request.data(), + license_.request.size()); +#ifndef HAS_PROVIDER_KEYS + if (result == WB_RESULT_NOT_IMPLEMENTED) + GTEST_SKIP(); +#endif + ASSERT_EQ(result, WB_RESULT_OK); } TEST_F(LicenseWhiteboxProcessLicenseResponseTest, InvalidProviderKey) { @@ -181,15 +187,18 @@ TEST_F(LicenseWhiteboxProcessLicenseResponseTest, InvalidProviderKey) { const size_t kInvalidProviderKey = 0xfff; UseLicenseWithSigningKey(TestLicenseBuilder::Padding::kNone); - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), - license_.core_message.size(), license_.message.data(), - license_.message.size(), license_.signature.data(), - license_.signature.size(), license_.session_key.data(), - license_.session_key.size(), kInvalidProviderKey, - license_.request.data(), license_.request.size()), - WB_RESULT_OK); + const auto result = WB_License_ProcessLicenseResponse( + whitebox_, WB_LICENSE_KEY_MODE_DUAL_KEY, license_.core_message.data(), + license_.core_message.size(), license_.message.data(), + license_.message.size(), license_.signature.data(), + license_.signature.size(), license_.session_key.data(), + license_.session_key.size(), kInvalidProviderKey, license_.request.data(), + license_.request.size()); +#ifndef HAS_PROVIDER_KEYS + if (result == WB_RESULT_NOT_IMPLEMENTED) + GTEST_SKIP(); +#endif + ASSERT_EQ(result, WB_RESULT_OK); } class LicenseWhiteboxProcessLicenseResponseErrorTest diff --git a/whitebox/api/license_whitebox_proxy_impl.cc b/whitebox/api/license_whitebox_proxy_impl.cc new file mode 100644 index 0000000..815b896 --- /dev/null +++ b/whitebox/api/license_whitebox_proxy_impl.cc @@ -0,0 +1,95 @@ +// Copyright 2022 Google LLC. All Rights Reserved. + +#include "api/license_whitebox.h" +#include "api/license_whitebox_provider_keys_test_data.h" + +// This file contains definitions of the new whitebox API functions that proxy +// to older versions of the API to allow running tests against old +// implementations. These functions are marked with WEAK to make sure they are +// only used in the final binary if another definition doesn't appear. + +#ifdef _MSC_VER +// MSVC handles weak symbols the way we want, so we don't need to define +// anything. +# define WEAK +#elif defined(__GNUC__) +# define WEAK __attribute__((weak)) +#else +# error "Unknown compiler" +#endif + +WEAK WB_Result WB_License_Create(WB_License_Whitebox** whitebox); +WEAK WB_Result +WB_License_ProcessLicenseResponse(WB_License_Whitebox* whitebox, + WB_LicenseKeyMode license_key_mode, + const uint8_t* core_message, + size_t core_message_size, + const uint8_t* message, + size_t message_size, + const uint8_t* signature, + size_t signature_size, + const uint8_t* session_key, + size_t session_key_size, + const uint8_t* license_request, + size_t license_request_size); + +WEAK WB_Result WB_License_Create(const uint8_t* whitebox_init_data, + size_t whitebox_init_data_size, + WB_License_Whitebox** whitebox) { + if (whitebox_init_data_size && !whitebox_init_data) { + return WB_RESULT_INVALID_PARAMETER; + } + return WB_License_Create(whitebox); +} + +WEAK WB_Result WB_License_ProcessLicenseResponse( + WB_License_Whitebox* whitebox, WB_LicenseKeyMode license_key_mode, + const uint8_t* core_message, size_t core_message_size, + const uint8_t* message, size_t message_size, const uint8_t* signature, + size_t signature_size, const uint8_t* session_key, size_t session_key_size, + size_t provider_key_id, const uint8_t* license_request, + size_t license_request_size) { + if (provider_key_id != 0) { + return WB_RESULT_NOT_IMPLEMENTED; + } + + return WB_License_ProcessLicenseResponse( + whitebox, license_key_mode, core_message, core_message_size, message, + message_size, signature, signature_size, session_key, session_key_size, + license_request, license_request_size); +} + +WEAK WB_Result +WB_License_LoadEntitledContentKey(WB_License_Whitebox* whitebox, + const uint8_t* entitlement_key_id, + size_t entitlement_key_id_size, + const uint8_t* content_key_id, + size_t content_key_id_size, + const uint8_t* iv, + size_t iv_size, + const uint8_t* key_data, + size_t key_data_size) { + return WB_RESULT_NOT_IMPLEMENTED; +} + +WEAK WB_Result WB_License_SignPstReport(const WB_License_Whitebox* whitebox, + const uint8_t* message, + size_t message_size, + uint8_t* signature, + size_t* signature_size) { + return WB_RESULT_NOT_IMPLEMENTED; +} + +namespace widevine { + +WEAK std::vector GetLicenseWhiteboxProviderKeysInitData() { + // Note that for some reason, this replaces the reference implementation, + // even though the others don't. So this function means we can't use this + // file with the reference implementation. + + // Return a non-empty buffer so we can check whether the data is passed for + // a test. + return {1}; +} + +} // namespace widevine diff --git a/whitebox/api/license_whitebox_query_content_key_status_test.cc b/whitebox/api/license_whitebox_query_content_key_status_test.cc index b6de010..6a1ef8e 100644 --- a/whitebox/api/license_whitebox_query_content_key_status_test.cc +++ b/whitebox/api/license_whitebox_query_content_key_status_test.cc @@ -122,7 +122,11 @@ TEST_P(LicenseWhiteboxQueryContentKeyStatus, ValidMaskedDecryptKey) { masked_decrypt_key_->id.size(), &key_state), WB_RESULT_OK); +#ifdef ALWAYS_DECRYPT_TO_CLEAR + ASSERT_EQ(key_state, WB_KEY_STATUS_CONTENT_KEY_DECRYPT); +#else ASSERT_EQ(key_state, WB_KEY_STATUS_CONTENT_KEY_MASKED_DECRYPT); +#endif } TEST_P(LicenseWhiteboxQueryContentKeyStatus, NoKeyForNoId) { diff --git a/whitebox/api/license_whitebox_sign_renewal_request_test.cc b/whitebox/api/license_whitebox_sign_renewal_request_test.cc index ee68929..5a92ade 100644 --- a/whitebox/api/license_whitebox_sign_renewal_request_test.cc +++ b/whitebox/api/license_whitebox_sign_renewal_request_test.cc @@ -14,6 +14,8 @@ namespace widevine { +constexpr const bool kRenewal = true; + class LicenseWhiteboxSignRenewalPstTest : public LicenseWhiteboxTestBase, public testing::WithParamInterface { @@ -26,8 +28,8 @@ class LicenseWhiteboxSignRenewalPstTest signature_size_ = 256; signature_.resize(signature_size_); - sign_func_ = - GetParam() ? &WB_License_SignRenewalRequest : &WB_License_SignPstReport; + sign_func_ = GetParam() == kRenewal ? &WB_License_SignRenewalRequest + : &WB_License_SignPstReport; } void LoadLicense(const TestLicenseBuilder::Settings& settings) { @@ -63,8 +65,9 @@ class LicenseWhiteboxSignRenewalPstTest std::string key_str(signing_key_.begin(), signing_key_.end()); key_str.erase(0, crypto_util::kSigningKeySizeBytes); - auto func = GetParam() ? &widevine::crypto_util::CreateSignatureHmacSha256 - : &widevine::crypto_util::CreateSignatureHmacSha1; + auto func = GetParam() == kRenewal + ? &widevine::crypto_util::CreateSignatureHmacSha256 + : &widevine::crypto_util::CreateSignatureHmacSha1; const std::string signature = func(key_str, std::string(message.begin(), message.end())); @@ -97,10 +100,15 @@ TEST_P(LicenseWhiteboxSignRenewalPstTest, SuccessWithInvalidRequest) { settings.padding = TestLicenseBuilder::Padding::kNone; LoadLicense(settings); - ASSERT_EQ( + const auto result = sign_func_(whitebox_, garbage_request_.data(), garbage_request_.size(), - signature_.data(), &signature_size_), - WB_RESULT_OK); + signature_.data(), &signature_size_); +#ifndef HAS_SIGN_PST_REPORT + if (GetParam() != kRenewal && result == WB_RESULT_NOT_IMPLEMENTED) { + GTEST_SKIP(); + } +#endif + ASSERT_EQ(result, WB_RESULT_OK); signature_.resize(signature_size_); ASSERT_EQ(signature_, GetSignature(garbage_request_)); @@ -111,10 +119,15 @@ TEST_P(LicenseWhiteboxSignRenewalPstTest, SuccessWithSigningKeyPKSC8Padding) { settings.padding = TestLicenseBuilder::Padding::kPKSC8; LoadLicense(settings); - ASSERT_EQ( + const auto result = sign_func_(whitebox_, garbage_request_.data(), garbage_request_.size(), - signature_.data(), &signature_size_), - WB_RESULT_OK); + signature_.data(), &signature_size_); +#ifndef HAS_SIGN_PST_REPORT + if (GetParam() != kRenewal && result == WB_RESULT_NOT_IMPLEMENTED) { + GTEST_SKIP(); + } +#endif + ASSERT_EQ(result, WB_RESULT_OK); signature_.resize(signature_size_); ASSERT_EQ(signature_, GetSignature(garbage_request_)); @@ -125,10 +138,15 @@ TEST_P(LicenseWhiteboxSignRenewalPstTest, InvalidParameterForNullWhitebox) { settings.padding = TestLicenseBuilder::Padding::kNone; LoadLicense(settings); - ASSERT_EQ( + const auto result = sign_func_(nullptr, garbage_request_.data(), garbage_request_.size(), - signature_.data(), &signature_size_), - WB_RESULT_INVALID_PARAMETER); + signature_.data(), &signature_size_); +#ifndef HAS_SIGN_PST_REPORT + if (GetParam() != kRenewal && result == WB_RESULT_NOT_IMPLEMENTED) { + GTEST_SKIP(); + } +#endif + ASSERT_EQ(result, WB_RESULT_INVALID_PARAMETER); } TEST_P(LicenseWhiteboxSignRenewalPstTest, InvalidParameterForNullMessage) { @@ -136,9 +154,14 @@ TEST_P(LicenseWhiteboxSignRenewalPstTest, InvalidParameterForNullMessage) { settings.padding = TestLicenseBuilder::Padding::kNone; LoadLicense(settings); - ASSERT_EQ(sign_func_(whitebox_, nullptr, garbage_request_.size(), - signature_.data(), &signature_size_), - WB_RESULT_INVALID_PARAMETER); + const auto result = sign_func_(whitebox_, nullptr, garbage_request_.size(), + signature_.data(), &signature_size_); +#ifndef HAS_SIGN_PST_REPORT + if (GetParam() != kRenewal && result == WB_RESULT_NOT_IMPLEMENTED) { + GTEST_SKIP(); + } +#endif + ASSERT_EQ(result, WB_RESULT_INVALID_PARAMETER); } TEST_P(LicenseWhiteboxSignRenewalPstTest, InvalidParameterForZeroMessageSize) { @@ -146,9 +169,14 @@ TEST_P(LicenseWhiteboxSignRenewalPstTest, InvalidParameterForZeroMessageSize) { settings.padding = TestLicenseBuilder::Padding::kNone; LoadLicense(settings); - ASSERT_EQ(sign_func_(whitebox_, garbage_request_.data(), 0, signature_.data(), - &signature_size_), - WB_RESULT_INVALID_PARAMETER); + const auto result = sign_func_(whitebox_, garbage_request_.data(), 0, + signature_.data(), &signature_size_); +#ifndef HAS_SIGN_PST_REPORT + if (GetParam() != kRenewal && result == WB_RESULT_NOT_IMPLEMENTED) { + GTEST_SKIP(); + } +#endif + ASSERT_EQ(result, WB_RESULT_INVALID_PARAMETER); } TEST_P(LicenseWhiteboxSignRenewalPstTest, CanProbeSizeWithNullSignature) { @@ -157,9 +185,15 @@ TEST_P(LicenseWhiteboxSignRenewalPstTest, CanProbeSizeWithNullSignature) { LoadLicense(settings); signature_size_ = 0; - ASSERT_EQ(sign_func_(whitebox_, garbage_request_.data(), - garbage_request_.size(), nullptr, &signature_size_), - WB_RESULT_BUFFER_TOO_SMALL); + const auto result = + sign_func_(whitebox_, garbage_request_.data(), garbage_request_.size(), + nullptr, &signature_size_); +#ifndef HAS_SIGN_PST_REPORT + if (GetParam() != kRenewal && result == WB_RESULT_NOT_IMPLEMENTED) { + GTEST_SKIP(); + } +#endif + ASSERT_EQ(result, WB_RESULT_BUFFER_TOO_SMALL); ASSERT_GT(signature_size_, 0); } @@ -168,9 +202,15 @@ TEST_P(LicenseWhiteboxSignRenewalPstTest, InvalidParameterForNullSignature) { settings.padding = TestLicenseBuilder::Padding::kNone; LoadLicense(settings); - ASSERT_EQ(sign_func_(whitebox_, garbage_request_.data(), - garbage_request_.size(), nullptr, &signature_size_), - WB_RESULT_INVALID_PARAMETER); + const auto result = + sign_func_(whitebox_, garbage_request_.data(), garbage_request_.size(), + nullptr, &signature_size_); +#ifndef HAS_SIGN_PST_REPORT + if (GetParam() != kRenewal && result == WB_RESULT_NOT_IMPLEMENTED) { + GTEST_SKIP(); + } +#endif + ASSERT_EQ(result, WB_RESULT_INVALID_PARAMETER); } TEST_P(LicenseWhiteboxSignRenewalPstTest, @@ -179,9 +219,15 @@ TEST_P(LicenseWhiteboxSignRenewalPstTest, settings.padding = TestLicenseBuilder::Padding::kNone; LoadLicense(settings); - ASSERT_EQ(sign_func_(whitebox_, garbage_request_.data(), - garbage_request_.size(), signature_.data(), nullptr), - WB_RESULT_INVALID_PARAMETER); + const auto result = + sign_func_(whitebox_, garbage_request_.data(), garbage_request_.size(), + signature_.data(), nullptr); +#ifndef HAS_SIGN_PST_REPORT + if (GetParam() != kRenewal && result == WB_RESULT_NOT_IMPLEMENTED) { + GTEST_SKIP(); + } +#endif + ASSERT_EQ(result, WB_RESULT_INVALID_PARAMETER); } TEST_P(LicenseWhiteboxSignRenewalPstTest, BufferTooSmall) { @@ -194,10 +240,15 @@ TEST_P(LicenseWhiteboxSignRenewalPstTest, BufferTooSmall) { // "too small". signature_size_ = 1; - ASSERT_EQ( + const auto result = sign_func_(whitebox_, garbage_request_.data(), garbage_request_.size(), - signature_.data(), &signature_size_), - WB_RESULT_BUFFER_TOO_SMALL); + signature_.data(), &signature_size_); +#ifndef HAS_SIGN_PST_REPORT + if (GetParam() != kRenewal && result == WB_RESULT_NOT_IMPLEMENTED) { + GTEST_SKIP(); + } +#endif + ASSERT_EQ(result, WB_RESULT_BUFFER_TOO_SMALL); // Since the API does not limit the signature size, we can't specify the // actual expected size, however, it should at least be greater than our "too @@ -210,10 +261,15 @@ TEST_P(LicenseWhiteboxSignRenewalPstTest, InvalidStateForNoLicense) { // have no license loaded in order to have no renewal key, which is the // criteria WB_RESULT_INVALID_STATE. - ASSERT_EQ( + const auto result = sign_func_(whitebox_, garbage_request_.data(), garbage_request_.size(), - signature_.data(), &signature_size_), - WB_RESULT_INVALID_STATE); + signature_.data(), &signature_size_); +#ifndef HAS_SIGN_PST_REPORT + if (GetParam() != kRenewal && result == WB_RESULT_NOT_IMPLEMENTED) { + GTEST_SKIP(); + } +#endif + ASSERT_EQ(result, WB_RESULT_INVALID_STATE); } TEST_P(LicenseWhiteboxSignRenewalPstTest, KeyUnavailableForNoSigningKey) { @@ -237,10 +293,15 @@ TEST_P(LicenseWhiteboxSignRenewalPstTest, KeyUnavailableForNoSigningKey) { license.request.size()), WB_RESULT_OK); - ASSERT_EQ( + const auto result = sign_func_(whitebox_, garbage_request_.data(), garbage_request_.size(), - signature_.data(), &signature_size_), - WB_RESULT_KEY_UNAVAILABLE); + signature_.data(), &signature_size_); +#ifndef HAS_SIGN_PST_REPORT + if (GetParam() != kRenewal && result == WB_RESULT_NOT_IMPLEMENTED) { + GTEST_SKIP(); + } +#endif + ASSERT_EQ(result, WB_RESULT_KEY_UNAVAILABLE); } TEST_P(LicenseWhiteboxSignRenewalPstTest, KeyUnavailableForInvalidKey) { @@ -251,17 +312,22 @@ TEST_P(LicenseWhiteboxSignRenewalPstTest, KeyUnavailableForInvalidKey) { settings.include_signing_key_iv = false; LoadLicense(settings); - ASSERT_EQ( + const auto result = sign_func_(whitebox_, garbage_request_.data(), garbage_request_.size(), - signature_.data(), &signature_size_), - WB_RESULT_KEY_UNAVAILABLE); + signature_.data(), &signature_size_); +#ifndef HAS_SIGN_PST_REPORT + if (GetParam() != kRenewal && result == WB_RESULT_NOT_IMPLEMENTED) { + GTEST_SKIP(); + } +#endif + ASSERT_EQ(result, WB_RESULT_KEY_UNAVAILABLE); } INSTANTIATE_TEST_SUITE_P(TestAll, LicenseWhiteboxSignRenewalPstTest, testing::Bool(), [](const testing::TestParamInfo& info) { - return info.param ? "Renewal" : "PST"; + return info.param == kRenewal ? "Renewal" : "PST"; }); } // namespace widevine diff --git a/whitebox/api/remote_attestation_and_verification_test.cc b/whitebox/api/remote_attestation_and_verification_test.cc index 89557ab..d6f5ec4 100644 --- a/whitebox/api/remote_attestation_and_verification_test.cc +++ b/whitebox/api/remote_attestation_and_verification_test.cc @@ -35,6 +35,32 @@ enum class Mode { kMaskedDecryptFail, }; +std::ostream& operator<<(std::ostream& os, Key key) { + switch (key) { + case Key::kCrypto: + return os << "SW_SECURE_CRYPTO"; + case Key::kDecode: + return os << "SW_SECURE_DECODE"; + case Key::kHardware: + return os << "HW_SECURE_DECODE"; + } + return os; +} + +std::ostream& operator<<(std::ostream& os, Mode mode) { + switch (mode) { + case Mode::kDecryptPass: + return os << "DecryptPass"; + case Mode::kDecryptFail: + return os << "DecryptFail"; + case Mode::kMaskedDecryptPass: + return os << "MaskedDecryptPass"; + case Mode::kMaskedDecryptFail: + return os << "MaskedDecryptFail"; + } + return os; +} + // WV_ENABLE_HW_VERIFICATION = 0: prevent VMP/RA from overriding the key // security level. // @@ -58,9 +84,11 @@ Mode DisableOverrideForCrypto(Mode mode) { // it says that we could use it with decrypt. Remember, anything that works // with decrypt can work with masked decrypt, but not the other way around. Mode DisableOverrideForDecode(Mode mode) { +#ifndef ALWAYS_DECRYPT_TO_CLEAR if (mode == Mode::kDecryptPass) { return Mode::kDecryptFail; } +#endif return mode; } @@ -107,6 +135,12 @@ class RemoteAttestationAndVerificationTest padding_ = std::get<0>(params); std::tie(key, ra_, vmp_, mode_) = std::get<1>(params); +#ifdef ALWAYS_DECRYPT_TO_CLEAR + if (key == Key::kDecode) { + if (mode_ == Mode::kDecryptFail) mode_ = Mode::kDecryptPass; + } +#endif + // These tests are written as "we are testing that VMP/RA can override the // key's security level". However, when the white-box does not have that // functionality, it should not be able to do that. As a simple way to test diff --git a/whitebox/api/result.h b/whitebox/api/result.h index 173d887..9a29dfe 100644 --- a/whitebox/api/result.h +++ b/whitebox/api/result.h @@ -39,6 +39,9 @@ typedef enum { // The input data failed to be verified. This may happen if the data was // corrupted or tampered. WB_RESULT_DATA_VERIFICATION_ERROR = 8, + + // The method or settings aren't supported in this version of the whitebox. + WB_RESULT_NOT_IMPLEMENTED = 9, } WB_Result; #ifdef __cplusplus diff --git a/whitebox/api/test_license_builder.h b/whitebox/api/test_license_builder.h index 975530d..d5eb6e6 100644 --- a/whitebox/api/test_license_builder.h +++ b/whitebox/api/test_license_builder.h @@ -4,6 +4,7 @@ #define WHITEBOX_API_LICENSE_BUILDER_H_ #include +#include #include #include @@ -152,6 +153,45 @@ class TestLicenseBuilder { std::vector operator_session_keys_; }; +inline std::ostream& operator<<(std::ostream& os, + TestLicenseBuilder::Padding value) { + switch (value) { + case TestLicenseBuilder::Padding::kNone: + return os << "NoPadding"; + case TestLicenseBuilder::Padding::kPKSC8: + return os << "PKSC8"; + default: + return os << ""; + } +} + +inline std::ostream& operator<<(std::ostream& os, + TestLicenseBuilder::RemoteAttestation value) { + switch (value) { + case TestLicenseBuilder::RemoteAttestation::kUnavailable: + return os << "RA Unavailable"; + case TestLicenseBuilder::RemoteAttestation::kVerified: + return os << "RA Verified"; + case TestLicenseBuilder::RemoteAttestation::kUnverified: + return os << "RA Unverified"; + default: + return os << ""; + } +} + +inline std::ostream& operator<<(std::ostream& os, + TestLicenseBuilder::VerificationStatus value) { + switch (value) { + case TestLicenseBuilder::VerificationStatus::kUnavailable: + return os << "Unverified"; + case TestLicenseBuilder::VerificationStatus::kHardwareVerified: + return os << "HardwareVerified"; + default: + return os << "VerifiedOther"; + } +} + + } // namespace widevine #endif // WHITEBOX_API_LICENSE_BUILDER_H_ diff --git a/whitebox/defs.bzl b/whitebox/defs.bzl new file mode 100644 index 0000000..49fb7f2 --- /dev/null +++ b/whitebox/defs.bzl @@ -0,0 +1,14 @@ +# Copyright 2022 Google LLC. All Rights Reserved. + +BuildType = provider(fields = ["type"]) + +# old/old_vmpra are used to test against the old API; this involves adding +# compatibility proxies for old functions and not expecting any "extra" features +possible_types = ["chrome", "chromeos", "ce", "old", "old_vmpra"] + +def _impl(ctx): + if ctx.build_setting_value not in possible_types: + fail("Invalid build type: " + ctx.build_setting_value) + return BuildType(type=ctx.build_setting_value) + +build_type = rule(implementation=_impl, build_setting=config.string(flag=True)) diff --git a/whitebox/reference/impl/BUILD b/whitebox/reference/impl/BUILD index 1857991..1dff330 100644 --- a/whitebox/reference/impl/BUILD +++ b/whitebox/reference/impl/BUILD @@ -13,11 +13,7 @@ package(default_visibility = [ # # test_aead_whitebox : The target for testing the AEAD white-box. # -# general_license_whitebox_with_vmpra : The target for testing the license -# white-box against generated licenses with VMP/RA functionality. -# -# general_license_whitebox_without_vmpra : The target for testing the license -# white-box against generated licenses without VMP/RA functionality. +# general_license_whitebox: The target for testing the license white-box. # # uat_license_whitebox : The target for testing the license white-box against # licenses from Widevine's UAT server. @@ -32,6 +28,7 @@ cc_library( hdrs = ["odk.h"], deps = [ "//api:result", + "//api:shared_settings", "//chromium_deps/base:glog", "//external:odk", ], @@ -41,6 +38,7 @@ cc_library( name = "memory_util", srcs = ["memory_util.cc"], hdrs = ["memory_util.h"], + deps = ["//api:shared_settings"], ) cc_library( @@ -48,6 +46,7 @@ cc_library( hdrs = ["content_key.h"], deps = [ "//api:license_whitebox", + "//api:shared_settings", "//chromium_deps/cdm/protos:license_protocol_proto", ], ) @@ -69,6 +68,7 @@ cc_library( ":odk", ":renewal_key", "//api:result", + "//api:shared_settings", "//chromium_deps/cdm/protos:license_protocol_proto", "//crypto_utils:aes_cbc_decryptor", "//crypto_utils:crypto_util", @@ -81,49 +81,19 @@ cc_library( hdrs = ["odk_license_parser.h"], deps = [ ":license_parser", + "//api:shared_settings", "//chromium_deps/base:glog", "//crypto_utils:crypto_util", ], ) -# For the protobuf license parser, we need to have three targets: -# 1. The header target -# 2. The VMP/RA enabled target -# 3. The VMP/RA disabled target -# -# The header target is needed so that we can defer which parser we are going to -# support until the top-level target. -# -# The two implementation targets are created (as near copies) to avoid issues -# around when the define is resolved. cc_library( name = "protobuf_license_parser", hdrs = ["protobuf_license_parser.h"], - deps = [ - ":license_parser", - ], -) - -cc_library( - name = "protobuf_license_parser_with_vmpra", srcs = ["protobuf_license_parser.cc"], - defines = ["WV_ENABLE_HW_VERIFICATION=1"], deps = [ ":license_parser", - ":protobuf_license_parser", - "//chromium_deps/base:glog", - "//chromium_deps/cdm/protos:license_protocol_proto", - "//crypto_utils:crypto_util", - ], -) - -cc_library( - name = "protobuf_license_parser_without_vmpra", - srcs = ["protobuf_license_parser.cc"], - defines = ["WV_ENABLE_HW_VERIFICATION=0"], - deps = [ - ":license_parser", - ":protobuf_license_parser", + "//api:shared_settings", "//chromium_deps/base:glog", "//chromium_deps/cdm/protos:license_protocol_proto", "//crypto_utils:crypto_util", @@ -140,6 +110,7 @@ cc_library( srcs = ["private_keys.cc"], hdrs = ["private_keys.h"], deps = [ + "//api:shared_settings", "//api:test_license_whitebox_keys", ], ) @@ -153,6 +124,7 @@ cc_library( visibility = ["//visibility:public"], deps = [ "//api:license_whitebox_provider_keys_test_data", + "//api:shared_settings", ], ) @@ -172,6 +144,7 @@ cc_library( "//api:aead_test_data", "//api:aead_whitebox", "//api:result", + "//api:shared_settings", "//chromium_deps/third_party/boringssl", "//crypto_utils:crypto_util", ], @@ -197,6 +170,7 @@ cc_library( ":protobuf_license_parser", "//api:license_whitebox", "//api:result", + "//api:shared_settings", "//chromium_deps/cdm/keys:dev_certs", "//chromium_deps/cdm/protos:license_protocol_proto", "//crypto_utils:aes_cbc_decryptor", @@ -208,21 +182,12 @@ cc_library( # These targets provid the license whitebox for all general tests. cc_library( - name = "general_license_whitebox_with_vmpra", + name = "general_license_whitebox", visibility = ["//visibility:public"], deps = [ ":license_whitebox_core", - ":protobuf_license_parser_with_vmpra", - "//api:test_license_whitebox_keys_general", - ], -) - -cc_library( - name = "general_license_whitebox_without_vmpra", - visibility = ["//visibility:public"], - deps = [ - ":license_whitebox_core", - ":protobuf_license_parser_without_vmpra", + ":protobuf_license_parser", + "//api:shared_settings", "//api:test_license_whitebox_keys_general", ], ) @@ -234,7 +199,8 @@ cc_library( visibility = ["//visibility:public"], deps = [ ":license_whitebox_core", - ":protobuf_license_parser_with_vmpra", + ":protobuf_license_parser", + "//api:shared_settings", "//api:test_license_whitebox_keys_uat", ], ) diff --git a/whitebox/reference/impl/license_parser.cc b/whitebox/reference/impl/license_parser.cc index efaab80..dd003fb 100644 --- a/whitebox/reference/impl/license_parser.cc +++ b/whitebox/reference/impl/license_parser.cc @@ -88,7 +88,11 @@ WB_KeyStatus LicenseParser::GetKeyStatus( case video_widevine::License_KeyContainer_SecurityLevel_SW_SECURE_CRYPTO: return WB_KEY_STATUS_CONTENT_KEY_DECRYPT; case video_widevine::License_KeyContainer_SecurityLevel_SW_SECURE_DECODE: +#ifdef ALWAYS_DECRYPT_TO_CLEAR + return WB_KEY_STATUS_CONTENT_KEY_DECRYPT; +#else return WB_KEY_STATUS_CONTENT_KEY_MASKED_DECRYPT; +#endif default: // For example, this could be a hardware key - a valid key but can't be // used by the CDM. However, this may get override later if the device is diff --git a/whitebox/reference/impl/odk.cc b/whitebox/reference/impl/odk.cc index ab24c08..1164c7a 100644 --- a/whitebox/reference/impl/odk.cc +++ b/whitebox/reference/impl/odk.cc @@ -9,45 +9,48 @@ #include "base/logging.h" #include "oemcrypto/odk/include/OEMCryptoCENCCommon.h" #include "oemcrypto/odk/include/odk.h" -#include "oemcrypto/odk/include/odk_message.h" -#include "oemcrypto/odk/src/odk_serialize.h" -#include "oemcrypto/odk/src/serialization_base.h" +#include "oemcrypto/odk/include/odk_structs.h" -// Most of the logic to parse the core message comes from `ODK_ParseResponse()`. -// We copy the logic since the function as a whole is not compatible with what -// we need to do here. WB_Result GetODKContext(const std::string& combined_message, size_t core_message_size, ODKContext* context) { - // ODK_Message requires a mutable buffer and the buffer must exist as long as - // the message exists. - std::vector mutable_message(combined_message.begin(), - combined_message.end()); + ODK_TimerLimits timer; + ODK_ClockValues clock; + ODK_NonceValues nonce; - ODK_Message msg = - ODK_Message_Create(mutable_message.data(), mutable_message.size()); - ODK_Message_SetSize(&msg, core_message_size); - - ODK_LicenseResponse license_response{{{0, 0, {}}}, nullptr, {0}}; - license_response.parsed_license = &(context->license); - - Unpack_ODK_LicenseResponse(&msg, &license_response); - - const ODK_MessageStatus message_status = ODK_Message_GetStatus(&msg); - if (message_status != MESSAGE_STATUS_OK) { - DVLOG(1) << "Invalid core message status: 0x" << std::hex << message_status; + OEMCryptoResult result = ODK_InitializeSessionValues( + &timer, &clock, &nonce, ODK_MAJOR_VERSION, /* session_id= */ 0); + if (result != OEMCrypto_SUCCESS) { + DVLOG(1) << "Error initializing ODK structs: " << result; return WB_RESULT_INVALID_PARAMETER; } - const auto& core_message = license_response.request.core_message; - - if (core_message.message_type != ODK_License_Response_Type) { - DVLOG(1) << "Failed core message type: " << core_message.message_type; + // By using initial_license_load==false, ODK won't validate the nonce. +#if ODK_MAJOR_VERSION == 16 + uint8_t request_hash[16]; +#endif + for (bool usage_entry_present : {false, true}) { + // Parse using both values for |usage_entry_present|, it needs to match the + // license request, but we don't know it here. This avoids an extra + // argument and allows us to use ODK_ParseLicense. The value will be + // verified by the caller. + result = ODK_ParseLicense( + reinterpret_cast(combined_message.c_str()), + combined_message.size(), core_message_size, + /* initial_license_load= */ false, usage_entry_present, +#if ODK_MAJOR_VERSION == 16 + request_hash, +#endif + &timer, &clock, &nonce, &context->license); + if (result != ODK_ERROR_CORE_MESSAGE) break; + } + if (result != OEMCrypto_SUCCESS) { + DVLOG(1) << "Error parsing license response: " << result; return WB_RESULT_INVALID_PARAMETER; } - context->major_version = core_message.nonce_values.api_major_version; - context->minor_version = core_message.nonce_values.api_minor_version; + context->major_version = nonce.api_major_version; + context->minor_version = nonce.api_minor_version; // Now that it is initialized, mark it as valid. context->is_valid = true; diff --git a/whitebox/reference/impl/odk_license_parser.cc b/whitebox/reference/impl/odk_license_parser.cc index 665f52c..49292ea 100644 --- a/whitebox/reference/impl/odk_license_parser.cc +++ b/whitebox/reference/impl/odk_license_parser.cc @@ -201,6 +201,10 @@ InternalKey OdkLicenseParser::ParseInternalKey( } const std::string key_control_block = ExtractItem(key.key_control, message); + if (key_control_block.empty()) { + VLOG(3) << "Empty key control block."; + return InternalKey(); + } video_widevine::License_KeyContainer_SecurityLevel security_level; CHECK(ExtractLevel(key_control_block, &security_level)); diff --git a/whitebox/reference/tests/BUILD b/whitebox/reference/tests/BUILD index 88fa500..66c0aa4 100644 --- a/whitebox/reference/tests/BUILD +++ b/whitebox/reference/tests/BUILD @@ -13,11 +13,7 @@ package(default_visibility = [ # # test_aead_whitebox : The target for testing the AEAD white-box. # -# general_license_whitebox_with_vmpra : The target for testing the license -# white-box against generated licenses with VMP/RA functionality. -# -# general_license_whitebox_without_vmpra : The target for testing the license -# white-box against generated licenses without VMP/RA functionality. +# general_license_whitebox: The target for testing the license white-box. # # uat_license_whitebox : The target for testing the license white-box against # licenses from Widevine's UAT server. @@ -53,27 +49,17 @@ cc_test( size = "small", deps = [ "//api:license_whitebox_test", - "//reference/impl:general_license_whitebox_without_vmpra", + "//reference/impl:general_license_whitebox", "//reference/impl:license_whitebox_provider_keys_test_data" ], ) cc_test( - name = "remote_attestation_and_verification_with_vmpra_test", + name = "remote_attestation_and_verification_test", size = "small", deps = [ - "//api:remote_attestation_and_verification_with_vmpra_test", - "//reference/impl:general_license_whitebox_with_vmpra", - "//reference/impl:license_whitebox_provider_keys_test_data" - ], -) - -cc_test( - name = "remote_attestation_and_verification_without_vmpra_test", - size = "small", - deps = [ - "//api:remote_attestation_and_verification_without_vmpra_test", - "//reference/impl:general_license_whitebox_without_vmpra", + "//api:remote_attestation_and_verification_test", + "//reference/impl:general_license_whitebox", "//reference/impl:license_whitebox_provider_keys_test_data" ], ) @@ -83,7 +69,7 @@ cc_test( size = "small", deps = [ "//api:license_whitebox_benchmark", - "//reference/impl:general_license_whitebox_without_vmpra", + "//reference/impl:general_license_whitebox", "//reference/impl:license_whitebox_provider_keys_test_data" ], )