From d0b37c53ddffece1d6ea65c5c4e314b182a40a69 Mon Sep 17 00:00:00 2001 From: Aaron Vaage Date: Fri, 15 Jan 2021 16:14:23 -0800 Subject: [PATCH] Fx Key Security Level From Key Control Block We were missing break-statements when parsing the security levels from the key control block. To confirm this, the key control block tests were updated to attempt decrypting so that we will try using the keys. The test that used the KCB was failing since they key security level was "hardware". This brings this repo in sync with the internal repo at commit 499bfbbb5beb6842071e47125842aedb12b1a8e0. --- whitebox/api/BUILD | 2 +- ...license_whitebox_key_control_block_test.cc | 114 ++++++++++++++++++ ...sponse_with_encrypted_key_control_block.cc | 60 --------- .../impl/reference/license_whitebox_impl.cc | 4 + 4 files changed, 119 insertions(+), 61 deletions(-) create mode 100644 whitebox/api/license_whitebox_key_control_block_test.cc delete mode 100644 whitebox/api/license_whitebox_process_license_response_with_encrypted_key_control_block.cc diff --git a/whitebox/api/BUILD b/whitebox/api/BUILD index 8cc10ce..f82c66c 100644 --- a/whitebox/api/BUILD +++ b/whitebox/api/BUILD @@ -134,9 +134,9 @@ cc_library( "license_whitebox_create_test.cc", "license_whitebox_decrypt_test.cc", "license_whitebox_get_secret_string_test.cc", + "license_whitebox_key_control_block_test.cc", "license_whitebox_masked_decrypt_test.cc", "license_whitebox_process_license_response_core_message_test.cc", - "license_whitebox_process_license_response_with_encrypted_key_control_block.cc", "license_whitebox_process_license_response_test.cc", "license_whitebox_sign_license_request_test.cc", "license_whitebox_sign_renewal_request_test.cc", diff --git a/whitebox/api/license_whitebox_key_control_block_test.cc b/whitebox/api/license_whitebox_key_control_block_test.cc new file mode 100644 index 0000000..4e3a421 --- /dev/null +++ b/whitebox/api/license_whitebox_key_control_block_test.cc @@ -0,0 +1,114 @@ +// Copyright 2020 Google LLC. All Rights Reserved. + +#include "api/license_whitebox.h" + +#include "api/license_whitebox_test_base.h" +#include "api/test_license_builder.h" +#include "base/logging.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace widevine { +class LicenseWhiteboxKeyControlBlockTest + : public LicenseWhiteboxTestBase, + public testing::WithParamInterface< + std::tuple> { + protected: + void SetUp() override { + LicenseWhiteboxTestBase::SetUp(); + std::tie(kcb_, odk_) = GetParam(); + } + + void AddKeyToLicense(const GoldenData::Key& key, + TestLicenseBuilder* license) { + license->AddContentKey(key.level, key.id, key.content->key); + } + + TestLicenseBuilder::KeyControlBlock kcb_; + TestLicenseBuilder::OdkVersion odk_; +}; + +// Even though we are saying to use the ODK, since the key control block is +// encrypted, it should either decrypt the key control block or fallback to +// using protobuf parsing. It does not matter which method is used as long +// as it handles it. +TEST_P(LicenseWhiteboxKeyControlBlockTest, Decrypt) { + TestLicenseBuilder builder; + builder.GetSettings().key_control_block = kcb_; + builder.GetSettings().odk_version = odk_; + + const auto& cbc_test_data = golden_data_.CBCCryptoKey(); + + AddKeyToLicense(cbc_test_data, &builder); + + License license; + builder.Build(*public_key_, &license); + + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, 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(), + license.request.data(), license.request.size()), + WB_RESULT_OK); + + std::vector plaintext(cbc_test_data.content->ciphertext.size()); + size_t plaintext_size = plaintext.size(); + + // Make sure we can actually decrypt some data. + ASSERT_EQ(WB_License_Decrypt(whitebox_, WB_CIPHER_MODE_CBC, + cbc_test_data.id.data(), cbc_test_data.id.size(), + cbc_test_data.content->ciphertext.data(), + cbc_test_data.content->ciphertext.size(), + cbc_test_data.content->iv.data(), + cbc_test_data.content->iv.size(), + plaintext.data(), &plaintext_size), + WB_RESULT_OK); +} + +TEST_P(LicenseWhiteboxKeyControlBlockTest, MaskedDecrypt) { + TestLicenseBuilder builder; + builder.GetSettings().key_control_block = kcb_; + builder.GetSettings().odk_version = odk_; + + const auto& cbc_test_data = golden_data_.CBCDecodeKey(); + + AddKeyToLicense(cbc_test_data, &builder); + + License license; + builder.Build(*public_key_, &license); + + ASSERT_EQ( + WB_License_ProcessLicenseResponse( + whitebox_, 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(), + license.request.data(), license.request.size()), + WB_RESULT_OK); + + std::vector plaintext(cbc_test_data.content->ciphertext.size()); + size_t plaintext_size = plaintext.size(); + + // Make sure we can actually decrypt some data. + ASSERT_EQ( + WB_License_MaskedDecrypt( + whitebox_, WB_CIPHER_MODE_CBC, cbc_test_data.id.data(), + cbc_test_data.id.size(), cbc_test_data.content->ciphertext.data(), + cbc_test_data.content->ciphertext.size(), + cbc_test_data.content->iv.data(), cbc_test_data.content->iv.size(), + plaintext.data(), &plaintext_size), + WB_RESULT_OK); +} + +INSTANTIATE_TEST_SUITE_P( + AllCombination, + LicenseWhiteboxKeyControlBlockTest, + ::testing::Combine( + ::testing::Values(TestLicenseBuilder::KeyControlBlock::kClear, + TestLicenseBuilder::KeyControlBlock::kEncrypted), + ::testing::Values(TestLicenseBuilder::OdkVersion::kNone, + TestLicenseBuilder::OdkVersion::k16_3, + TestLicenseBuilder::OdkVersion::k16_5))); +} // namespace widevine diff --git a/whitebox/api/license_whitebox_process_license_response_with_encrypted_key_control_block.cc b/whitebox/api/license_whitebox_process_license_response_with_encrypted_key_control_block.cc deleted file mode 100644 index 9fbb0d8..0000000 --- a/whitebox/api/license_whitebox_process_license_response_with_encrypted_key_control_block.cc +++ /dev/null @@ -1,60 +0,0 @@ -// Copyright 2020 Google LLC. All Rights Reserved. - -#include "api/license_whitebox.h" - -#include "api/license_whitebox_test_base.h" -#include "api/test_license_builder.h" -#include "base/logging.h" -#include "testing/gtest/include/gtest/gtest.h" - -namespace widevine { -class LicenseWhiteboxProcessLicenseResponseWithEncryptedKeyControlBlockTest - : public LicenseWhiteboxTestBase, - public testing::WithParamInterface< - std::tuple> { - protected: - void SetUp() override { - LicenseWhiteboxTestBase::SetUp(); - std::tie(kcb_, odk_) = GetParam(); - } - - TestLicenseBuilder::KeyControlBlock kcb_; - TestLicenseBuilder::OdkVersion odk_; -}; - -// Even though we are saying to use the ODK, since the key control block is -// encrypted, it should either decrypt the key control block or fallback to -// using protobuf parsing. It does not matter which method is used as long -// as it handles it. -TEST_P(LicenseWhiteboxProcessLicenseResponseWithEncryptedKeyControlBlockTest, - Success) { - TestLicenseBuilder builder; - builder.GetSettings().key_control_block = kcb_; - builder.GetSettings().odk_version = odk_; - - builder.AddStubbedContentKey(); - - License license; - builder.Build(*public_key_, &license); - - ASSERT_EQ( - WB_License_ProcessLicenseResponse( - whitebox_, 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(), - license.request.data(), license.request.size()), - WB_RESULT_OK); -} - -INSTANTIATE_TEST_SUITE_P( - AllCombination, - LicenseWhiteboxProcessLicenseResponseWithEncryptedKeyControlBlockTest, - ::testing::Combine( - ::testing::Values(TestLicenseBuilder::KeyControlBlock::kClear, - TestLicenseBuilder::KeyControlBlock::kEncrypted), - ::testing::Values(TestLicenseBuilder::OdkVersion::kNone, - TestLicenseBuilder::OdkVersion::k16_3, - TestLicenseBuilder::OdkVersion::k16_5))); -} // namespace widevine diff --git a/whitebox/impl/reference/license_whitebox_impl.cc b/whitebox/impl/reference/license_whitebox_impl.cc index 018658f..ed2cf39 100644 --- a/whitebox/impl/reference/license_whitebox_impl.cc +++ b/whitebox/impl/reference/license_whitebox_impl.cc @@ -110,15 +110,19 @@ bool ExtractLevel( case 0: *security_level = video_widevine::License_KeyContainer_SecurityLevel_SW_SECURE_CRYPTO; + break; case 1: *security_level = video_widevine::License_KeyContainer_SecurityLevel_SW_SECURE_DECODE; + break; case 2: *security_level = video_widevine::License_KeyContainer_SecurityLevel_HW_SECURE_CRYPTO; + break; default: *security_level = video_widevine::License_KeyContainer_SecurityLevel_HW_SECURE_DECODE; + break; } return true;