Files
whitebox/whitebox/api/license_whitebox_decrypt_test.cc
Jacob Trimble 66820d41c5 Update partner repo
This adds:
- Requires WB_RESULT_NOT_IMPLEMENTED for masked in CE
- WB_License_RemoveEntitledContentKey
- WB_License_Generic* methods
2022-11-16 11:37:39 -08:00

649 lines
27 KiB
C++

// Copyright 2020 Google LLC. All Rights Reserved.
#include "api/license_whitebox.h"
#include <memory>
#include <string>
#include <vector>
#include "api/golden_data.h"
#include "api/license_whitebox_test_base.h"
#include "api/test_license_builder.h"
#include "crypto_utils/rsa_key.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace widevine {
namespace {
using Padding = TestLicenseBuilder::Padding;
const size_t kValidProviderKeyId1 = 1;
const size_t kValidProviderKeyId2 = 2;
const size_t kInvalidProviderKeyId = 0xfff;
// There is also kNoProviderKeyId specified in test_license_builder.
} // namespace
class LicenseWhiteboxDecryptTest
: public LicenseWhiteboxTestBase,
public ::testing::WithParamInterface<std::tuple<Padding, size_t>> {
protected:
void SetUp() override {
LicenseWhiteboxTestBase::SetUp();
// Because we are using the same buffer for both CTR and CBC, need to make
// sure that it is large enough for either one.
plaintext_size_ = std::max(golden_data_.CBCContent().ciphertext.size(),
golden_data_.CTRContent().ciphertext.size());
plaintext_.resize(plaintext_size_);
non_content_key_id_ = golden_data_.GetFreeId();
missing_key_id_ = golden_data_.GetFreeId();
padding_ = std::get<0>(GetParam());
provider_key_id_ = std::get<1>(GetParam());
}
// 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|.
bool LoadLicense(const TestLicenseBuilder::Settings& settings,
size_t provider_key_id) {
TestLicenseBuilder builder;
builder.SetSettings(settings);
// Update settings with the test specified parameters.
builder.GetSettings().padding = padding_;
builder.GetSettings().provider_key_id = provider_key_id_;
builder.AddContentKey(golden_data_.CBCContent().software_crypto_key);
builder.AddContentKey(golden_data_.CBCContent().software_decode_key);
builder.AddContentKey(golden_data_.CBCContent().hardware_key);
builder.AddContentKey(golden_data_.CTRContent().software_crypto_key);
builder.AddOperatorSessionKey(non_content_key_id_);
auto server = TestServer::CreateDualKey();
License license;
builder.Build(*server, &license);
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
// non-content key and one that will never be in the license.
KeyId non_content_key_id_;
KeyId missing_key_id_;
// This is the buffer used to store the output of each decrypt call.
size_t plaintext_size_;
std::vector<uint8_t> plaintext_;
Padding padding_;
size_t provider_key_id_;
};
TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCbcDataInCbcMode) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_OK);
plaintext_.resize(plaintext_size_);
ASSERT_EQ(plaintext_, golden_data_.CBCContent().plaintext);
}
TEST_P(LicenseWhiteboxDecryptTest, InPlaceDecryptionCbc) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
memcpy(plaintext_.data(), golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size());
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
plaintext_.data(), plaintext_.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_OK);
plaintext_.resize(plaintext_size_);
ASSERT_EQ(plaintext_, golden_data_.CBCContent().plaintext);
}
TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCtrDataInCtrMode) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CTR,
golden_data_.CTRContent().software_crypto_key.id.data(),
golden_data_.CTRContent().software_crypto_key.id.size(),
golden_data_.CTRContent().ciphertext.data(),
golden_data_.CTRContent().ciphertext.size(),
golden_data_.CTRContent().iv.data(),
golden_data_.CTRContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_OK);
plaintext_.resize(plaintext_size_);
ASSERT_EQ(plaintext_, golden_data_.CTRContent().plaintext);
}
TEST_P(LicenseWhiteboxDecryptTest, InPlaceDecryptionCtr) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
memcpy(plaintext_.data(), golden_data_.CTRContent().ciphertext.data(),
golden_data_.CTRContent().ciphertext.size());
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CTR,
golden_data_.CTRContent().software_crypto_key.id.data(),
golden_data_.CTRContent().software_crypto_key.id.size(),
plaintext_.data(), plaintext_.size(),
golden_data_.CTRContent().iv.data(),
golden_data_.CTRContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_OK);
plaintext_.resize(plaintext_size_);
ASSERT_EQ(plaintext_, golden_data_.CTRContent().plaintext);
}
// We try to decrypt CBC encrypted data in CTR mode. All operations should be
// successful, but the resulting plaintext should not match.
TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCbcDataInCtrMode) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CTR,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_OK);
plaintext_.resize(plaintext_size_);
ASSERT_NE(plaintext_, golden_data_.CBCContent().plaintext);
}
// We try to decrypt CTR encrypted data in CBC mode. All operations should be
// successful, but the resulting plaintext should not match.
TEST_P(LicenseWhiteboxDecryptTest, CryptoKeyWithCtrDataInCbcMode) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CTRContent().software_crypto_key.id.data(),
golden_data_.CTRContent().software_crypto_key.id.size(),
golden_data_.CTRContent().ciphertext.data(),
golden_data_.CTRContent().ciphertext.size(),
golden_data_.CTRContent().iv.data(),
golden_data_.CTRContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_OK);
plaintext_.resize(plaintext_size_);
ASSERT_NE(plaintext_, golden_data_.CTRContent().plaintext);
}
// Try decrypting two different sets of content to make sure that two
// different keys can be used at the same time.
TEST_P(LicenseWhiteboxDecryptTest, SuccessWithMultipleKeys) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_OK);
plaintext_.resize(plaintext_size_);
ASSERT_EQ(plaintext_, golden_data_.CBCContent().plaintext);
// Reset our output buffer.
plaintext_.clear();
plaintext_size_ = golden_data_.CTRContent().plaintext.size();
plaintext_.resize(plaintext_size_);
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CTR,
golden_data_.CTRContent().software_crypto_key.id.data(),
golden_data_.CTRContent().software_crypto_key.id.size(),
golden_data_.CTRContent().ciphertext.data(),
golden_data_.CTRContent().ciphertext.size(),
golden_data_.CTRContent().iv.data(),
golden_data_.CTRContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_OK);
plaintext_.resize(plaintext_size_);
ASSERT_EQ(plaintext_, golden_data_.CTRContent().plaintext);
}
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullWhitebox) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
ASSERT_EQ(WB_License_Decrypt(
nullptr, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_INVALID_PARAMETER);
}
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidCipherMode) {
TestLicenseBuilder::Settings settings;
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
// compiler tries to save us.
const WB_CipherMode invalid_mode = static_cast<WB_CipherMode>(0xFF);
ASSERT_EQ(WB_License_Decrypt(
whitebox_, invalid_mode,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_INVALID_PARAMETER);
}
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullKeyId) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC, nullptr,
golden_data_.CBCContent().software_crypto_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_INVALID_PARAMETER);
}
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForZeroKeyIdSize) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_crypto_key.id.data(), 0,
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_INVALID_PARAMETER);
}
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullInputData) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
nullptr, golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_INVALID_PARAMETER);
}
// AES CBC requires that the input be block aligned (multiple of 16). CTR does
// not care.
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidCBCInputDataSize) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
golden_data_.CBCContent().ciphertext.data(), 14,
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_INVALID_PARAMETER);
}
// The white-box (using any cipher mode) should reject input with size zero.
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForZeroInputDataSize) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
golden_data_.CBCContent().ciphertext.data(), 0,
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_INVALID_PARAMETER);
}
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullIV) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(), nullptr,
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_INVALID_PARAMETER);
}
// IV size should be 16. Any number other than 16 should fail.
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForInvalidIVSize) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(), 9, plaintext_.data(),
&plaintext_size_),
WB_RESULT_INVALID_PARAMETER);
}
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullOutput) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), nullptr, &plaintext_size_),
WB_RESULT_INVALID_PARAMETER);
}
TEST_P(LicenseWhiteboxDecryptTest, InvalidParameterForNullOutputSize) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
ASSERT_EQ(
WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(), nullptr),
WB_RESULT_INVALID_PARAMETER);
}
// For this test, "missing key id" specifically means a key id that was never
// in the license to start with. This is different than "non content key"
// and "dropped content key", as those keys were in the license but ignored.
TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForMissingKeyId) {
TestLicenseBuilder::Settings settings;
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(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(),
plaintext_.data(), &plaintext_size_),
WB_RESULT_KEY_UNAVAILABLE);
}
TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForNonContentKey) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
ASSERT_EQ(
WB_License_Decrypt(whitebox_, WB_CIPHER_MODE_CBC,
non_content_key_id_.data(), non_content_key_id_.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_KEY_UNAVAILABLE);
}
// Under normal circumstances, a hardware key should be dropped. The exception
// to this rule is on ChromeOS with a special license.
TEST_P(LicenseWhiteboxDecryptTest,
InsufficientSecurityLevelForHardwareContentKey) {
TestLicenseBuilder::Settings settings;
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(),
golden_data_.CBCContent().hardware_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(),
plaintext_.data(), &plaintext_size_),
WB_RESULT_INSUFFICIENT_PERMISSIONS);
}
TEST_P(LicenseWhiteboxDecryptTest, InsufficientSecurityLevelForDecodeKey) {
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
// 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_PERMISSIONS;
#endif
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_decode_key.id.data(),
golden_data_.CBCContent().software_decode_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
expected);
}
TEST_P(LicenseWhiteboxDecryptTest, BufferTooSmall) {
TestLicenseBuilder::Settings settings;
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.
plaintext_size_ = 8;
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_BUFFER_TOO_SMALL);
// We don't use padding so the reported plaintext size should be the same as
// the cipher text size.
ASSERT_EQ(plaintext_size_, golden_data_.CBCContent().ciphertext.size());
}
TEST_P(LicenseWhiteboxDecryptTest, InvalidState) {
// Unlike the other tests, we do not call LoadLicense() as the criteria for
// WB_RESULT_INVALID_STATE is that no key can be found and keys are provided
// via a license.
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_INVALID_STATE);
}
TEST_P(LicenseWhiteboxDecryptTest, KeyUnavailableForInvalidKey) {
// There are multiple ways for us to invalidate a content key. We have tests
// that test invalid keys (see the query content key status tests). But here,
// we just need an invalid key, so we use one way of invalidating the key.
TestLicenseBuilder::Settings settings;
settings.include_content_key_iv = false;
if (!LoadLicense(settings, provider_key_id_))
GTEST_SKIP();
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_KEY_UNAVAILABLE);
}
// For this test, we create a license using the test specified Provider Key
// Id, then load the license using a different Provider Key Id.
TEST_P(LicenseWhiteboxDecryptTest, MismatchProviderKeyId) {
// These tests use 2 valid provider key IDs, so try loading the license
// with a different key. Not all possible combinations are tested.
size_t other_provider_key_id = kInvalidProviderKeyId;
switch (provider_key_id_) {
case kNoProviderKeyId:
other_provider_key_id = kValidProviderKeyId1;
break;
case kValidProviderKeyId1:
other_provider_key_id = kValidProviderKeyId2;
break;
case kValidProviderKeyId2:
other_provider_key_id = kNoProviderKeyId;
break;
case kInvalidProviderKeyId:
// This is the same as kNoProviderKeyId, so use one of the valid ids.
other_provider_key_id = kValidProviderKeyId2;
break;
}
TestLicenseBuilder::Settings settings;
if (!LoadLicense(settings, other_provider_key_id))
GTEST_SKIP();
// Decryption should succeed, but the plaintext should be incorrect.
ASSERT_EQ(WB_License_Decrypt(
whitebox_, WB_CIPHER_MODE_CBC,
golden_data_.CBCContent().software_crypto_key.id.data(),
golden_data_.CBCContent().software_crypto_key.id.size(),
golden_data_.CBCContent().ciphertext.data(),
golden_data_.CBCContent().ciphertext.size(),
golden_data_.CBCContent().iv.data(),
golden_data_.CBCContent().iv.size(), plaintext_.data(),
&plaintext_size_),
WB_RESULT_OK);
plaintext_.resize(plaintext_size_);
ASSERT_NE(plaintext_, golden_data_.CBCContent().plaintext);
}
INSTANTIATE_TEST_SUITE_P(
NoPadding,
LicenseWhiteboxDecryptTest,
::testing::Combine(::testing::Values(Padding::kNone),
::testing::Values(kNoProviderKeyId,
kValidProviderKeyId1,
kValidProviderKeyId2,
kInvalidProviderKeyId)));
INSTANTIATE_TEST_SUITE_P(
PKSC8,
LicenseWhiteboxDecryptTest,
::testing::Combine(::testing::Values(Padding::kPKSC8),
::testing::Values(kNoProviderKeyId,
kValidProviderKeyId1,
kValidProviderKeyId2,
kInvalidProviderKeyId)));
} // namespace widevine