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;