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.
This commit is contained in:
Aaron Vaage
2021-01-15 16:14:23 -08:00
parent c1d449e809
commit d0b37c53dd
4 changed files with 119 additions and 61 deletions

View File

@@ -134,9 +134,9 @@ cc_library(
"license_whitebox_create_test.cc", "license_whitebox_create_test.cc",
"license_whitebox_decrypt_test.cc", "license_whitebox_decrypt_test.cc",
"license_whitebox_get_secret_string_test.cc", "license_whitebox_get_secret_string_test.cc",
"license_whitebox_key_control_block_test.cc",
"license_whitebox_masked_decrypt_test.cc", "license_whitebox_masked_decrypt_test.cc",
"license_whitebox_process_license_response_core_message_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_process_license_response_test.cc",
"license_whitebox_sign_license_request_test.cc", "license_whitebox_sign_license_request_test.cc",
"license_whitebox_sign_renewal_request_test.cc", "license_whitebox_sign_renewal_request_test.cc",

View File

@@ -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<TestLicenseBuilder::KeyControlBlock,
TestLicenseBuilder::OdkVersion>> {
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<uint8_t> 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<uint8_t> 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

View File

@@ -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<TestLicenseBuilder::KeyControlBlock,
TestLicenseBuilder::OdkVersion>> {
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

View File

@@ -110,15 +110,19 @@ bool ExtractLevel(
case 0: case 0:
*security_level = *security_level =
video_widevine::License_KeyContainer_SecurityLevel_SW_SECURE_CRYPTO; video_widevine::License_KeyContainer_SecurityLevel_SW_SECURE_CRYPTO;
break;
case 1: case 1:
*security_level = *security_level =
video_widevine::License_KeyContainer_SecurityLevel_SW_SECURE_DECODE; video_widevine::License_KeyContainer_SecurityLevel_SW_SECURE_DECODE;
break;
case 2: case 2:
*security_level = *security_level =
video_widevine::License_KeyContainer_SecurityLevel_HW_SECURE_CRYPTO; video_widevine::License_KeyContainer_SecurityLevel_HW_SECURE_CRYPTO;
break;
default: default:
*security_level = *security_level =
video_widevine::License_KeyContainer_SecurityLevel_HW_SECURE_DECODE; video_widevine::License_KeyContainer_SecurityLevel_HW_SECURE_DECODE;
break;
} }
return true; return true;