In this update we have:
- Added the verified platform tests. These tests show how some
platforms, when verified are allowed to by pass the normal policy
restrictions. This is done with ChromeOS, thus the name of the
tests use "chrome_os".
- Removed WB_RESULT_INVALID_PADDING. This error was when we the
non-license APIs exposed a AES function with padding. However,
those functions have been removed from the API and this error is
no longer used by the API.
- Tests have been updated to avoid signed-vs-unsigned comparison
and to use the Chromium path to gTest (which is mocked in this
library).
- Tests have been updated to use a new test base and golden data
system to make them easier to read.
229 lines
9.5 KiB
C++
229 lines
9.5 KiB
C++
// Copyright 2020 Google LLC. All Rights Reserved.
|
|
|
|
#include "api/license_whitebox.h"
|
|
|
|
#include <memory>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include "api/license_whitebox_test_base.h"
|
|
#include "api/test_data.h"
|
|
#include "api/test_license_builder.h"
|
|
#include "crypto_utils/crypto_util.h"
|
|
#include "crypto_utils/rsa_key.h"
|
|
#include "testing/gtest/include/gtest/gtest.h"
|
|
|
|
namespace widevine {
|
|
|
|
class LicenseWhiteboxVerifyRenewalResponseTest
|
|
: public LicenseWhiteboxTestBase {
|
|
protected:
|
|
void SetUp() override {
|
|
LicenseWhiteboxTestBase::SetUp();
|
|
garbage_renewal_signature_ = Sign(garbage_renewal_message_);
|
|
}
|
|
|
|
void LoadLicense(const std::vector<uint8_t>& padding) {
|
|
const auto signing_key = TestLicenseBuilder::DefaultSigningKey();
|
|
|
|
// We need a license so that we can always have a valid signature for our
|
|
// message(s), but don't load the license as some test will need no
|
|
// license loaded.
|
|
TestLicenseBuilder builder;
|
|
builder.AddSigningKey(signing_key, padding);
|
|
builder.AddStubbedContentKey();
|
|
|
|
License license;
|
|
builder.Build(*public_key_, &license);
|
|
|
|
ASSERT_EQ(WB_License_ProcessLicenseResponse(
|
|
whitebox_, 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> Sign(const std::vector<uint8_t>& message) {
|
|
const auto key = TestLicenseBuilder::DefaultSigningKey();
|
|
|
|
// The server signing key is the first half of the signing key.
|
|
std::string server_key = std::string(
|
|
key.begin(), key.begin() + crypto_util::kSigningKeySizeBytes);
|
|
|
|
const auto signature = crypto_util::CreateSignatureHmacSha256(
|
|
server_key, std::string(message.begin(), message.end()));
|
|
|
|
return std::vector<uint8_t>(signature.begin(), signature.end());
|
|
}
|
|
|
|
// Allow this to be mutable so that a test can corrupt it. This data is random
|
|
// and has no meaning.
|
|
std::vector<uint8_t> garbage_renewal_message_ = {
|
|
0xf1, 0x5c, 0xf1, 0x92, 0x73, 0x0c, 0xf9, 0x5d, 0x2b, 0x1e, 0x3f, 0x51,
|
|
0xb2, 0x75, 0xa1, 0xb3, 0xd3, 0xa8, 0x16, 0x83, 0x08, 0xf1, 0xe2, 0x47,
|
|
0x7b, 0x80, 0x37, 0xed, 0xf8, 0x8b, 0x1d, 0x79, 0x7f, 0xb0, 0xa1, 0xde,
|
|
0xcd, 0xba, 0xd4, 0x8f, 0xb7, 0x3c, 0x1a, 0x3f, 0x3e, 0x3a, 0xb4, 0xea,
|
|
0xd8, 0xd7, 0xa4, 0x65, 0xa1, 0x40, 0x87, 0xf6, 0xaa, 0xf4, 0xb1, 0x24,
|
|
0x17, 0xed, 0xf4, 0xca, 0x18, 0x51, 0x4a, 0x54, 0x3c, 0x73, 0xca, 0x45,
|
|
0x3e, 0xef, 0x39, 0x49, 0x65, 0xdd, 0x62, 0x11, 0x99, 0x13, 0x40, 0x67,
|
|
0x7f, 0xfb, 0x07, 0x09, 0x1e, 0xfe, 0x0e, 0xdc, 0xda, 0x0a, 0x85, 0x91,
|
|
0x15, 0x40, 0xa8, 0x7a, 0x0e, 0x76, 0xf6, 0xbe, 0x94, 0x2c, 0x70, 0xe9,
|
|
0x07, 0xea, 0xf8, 0x7a, 0xc3, 0x48, 0xe1, 0xcf, 0xf4, 0x7b, 0xd6, 0x27,
|
|
0xd7, 0x30, 0x6f, 0x18, 0xb3, 0x2d, 0x6a, 0x23,
|
|
};
|
|
|
|
// Allow this to be mutable so that we can initialize it in SetUp() but also
|
|
// so a test can corrupt it.
|
|
std::vector<uint8_t> garbage_renewal_signature_;
|
|
};
|
|
|
|
// TODO: Implement a test that uses a real serialized response. Once we have a
|
|
// real serialized response, we should update all the tests - except the
|
|
// SuccessForGarbageMessage - to use the real serialized response.
|
|
|
|
TEST_F(LicenseWhiteboxVerifyRenewalResponseTest, SuccessForGarbageMessage) {
|
|
LoadLicense(TestLicenseBuilder::NoPadding());
|
|
|
|
ASSERT_EQ(WB_License_VerifyRenewalResponse(whitebox_,
|
|
garbage_renewal_message_.data(),
|
|
garbage_renewal_message_.size(),
|
|
garbage_renewal_signature_.data(),
|
|
garbage_renewal_signature_.size()),
|
|
WB_RESULT_OK);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxVerifyRenewalResponseTest,
|
|
SuccessWithSigningKeyPKSC8Padding) {
|
|
LoadLicense(TestLicenseBuilder::PKSC8Padding());
|
|
|
|
ASSERT_EQ(WB_License_VerifyRenewalResponse(whitebox_,
|
|
garbage_renewal_message_.data(),
|
|
garbage_renewal_message_.size(),
|
|
garbage_renewal_signature_.data(),
|
|
garbage_renewal_signature_.size()),
|
|
WB_RESULT_OK);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxVerifyRenewalResponseTest,
|
|
InvalidParameterForNullWhitebox) {
|
|
LoadLicense(TestLicenseBuilder::NoPadding());
|
|
|
|
ASSERT_EQ(
|
|
WB_License_VerifyRenewalResponse(nullptr, garbage_renewal_message_.data(),
|
|
garbage_renewal_message_.size(),
|
|
garbage_renewal_signature_.data(),
|
|
garbage_renewal_signature_.size()),
|
|
WB_RESULT_INVALID_PARAMETER);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxVerifyRenewalResponseTest,
|
|
InvalidParameterForNullMessage) {
|
|
LoadLicense(TestLicenseBuilder::NoPadding());
|
|
|
|
ASSERT_EQ(WB_License_VerifyRenewalResponse(whitebox_, nullptr,
|
|
garbage_renewal_message_.size(),
|
|
garbage_renewal_signature_.data(),
|
|
garbage_renewal_signature_.size()),
|
|
WB_RESULT_INVALID_PARAMETER);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxVerifyRenewalResponseTest,
|
|
InvalidParameterForZeroMessageSize) {
|
|
LoadLicense(TestLicenseBuilder::NoPadding());
|
|
|
|
ASSERT_EQ(WB_License_VerifyRenewalResponse(whitebox_,
|
|
garbage_renewal_message_.data(), 0,
|
|
garbage_renewal_signature_.data(),
|
|
garbage_renewal_signature_.size()),
|
|
WB_RESULT_INVALID_PARAMETER);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxVerifyRenewalResponseTest,
|
|
InvalidParameterForNullSignature) {
|
|
LoadLicense(TestLicenseBuilder::NoPadding());
|
|
|
|
ASSERT_EQ(WB_License_VerifyRenewalResponse(
|
|
whitebox_, garbage_renewal_message_.data(),
|
|
garbage_renewal_message_.size(), nullptr,
|
|
garbage_renewal_signature_.size()),
|
|
WB_RESULT_INVALID_PARAMETER);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxVerifyRenewalResponseTest,
|
|
InvalidParameterForInvalidSignatureSize) {
|
|
LoadLicense(TestLicenseBuilder::NoPadding());
|
|
|
|
ASSERT_EQ(WB_License_VerifyRenewalResponse(
|
|
whitebox_, garbage_renewal_message_.data(),
|
|
garbage_renewal_message_.size(),
|
|
garbage_renewal_signature_.data(), 14),
|
|
WB_RESULT_INVALID_PARAMETER);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxVerifyRenewalResponseTest,
|
|
InvalidSignatureForModifiedMessage) {
|
|
LoadLicense(TestLicenseBuilder::NoPadding());
|
|
|
|
Modify(&garbage_renewal_message_);
|
|
|
|
ASSERT_EQ(WB_License_VerifyRenewalResponse(whitebox_,
|
|
garbage_renewal_message_.data(),
|
|
garbage_renewal_message_.size(),
|
|
garbage_renewal_signature_.data(),
|
|
garbage_renewal_signature_.size()),
|
|
WB_RESULT_INVALID_SIGNATURE);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxVerifyRenewalResponseTest,
|
|
InvalidSignatureForModifiedSignature) {
|
|
LoadLicense(TestLicenseBuilder::NoPadding());
|
|
|
|
Modify(&garbage_renewal_signature_);
|
|
|
|
ASSERT_EQ(WB_License_VerifyRenewalResponse(whitebox_,
|
|
garbage_renewal_message_.data(),
|
|
garbage_renewal_message_.size(),
|
|
garbage_renewal_signature_.data(),
|
|
garbage_renewal_signature_.size()),
|
|
WB_RESULT_INVALID_SIGNATURE);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxVerifyRenewalResponseTest, InvalidStateForNoLicense) {
|
|
// 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_VerifyRenewalResponse(whitebox_,
|
|
garbage_renewal_message_.data(),
|
|
garbage_renewal_message_.size(),
|
|
garbage_renewal_signature_.data(),
|
|
garbage_renewal_signature_.size()),
|
|
WB_RESULT_INVALID_STATE);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxVerifyRenewalResponseTest, InvalidStateForNoSigningKey) {
|
|
// Create a license with no signing key and one content key (every license
|
|
// must have a content key).
|
|
widevine::TestLicenseBuilder builder;
|
|
builder.AddStubbedContentKey();
|
|
|
|
License license;
|
|
builder.Build(*public_key_, &license);
|
|
|
|
ASSERT_EQ(WB_License_ProcessLicenseResponse(
|
|
whitebox_, 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);
|
|
|
|
ASSERT_EQ(WB_License_VerifyRenewalResponse(whitebox_,
|
|
garbage_renewal_message_.data(),
|
|
garbage_renewal_message_.size(),
|
|
garbage_renewal_signature_.data(),
|
|
garbage_renewal_signature_.size()),
|
|
WB_RESULT_INVALID_STATE);
|
|
}
|
|
|
|
} // namespace widevine
|