This updates the repo to match the internal repo at commit: 521466f84993e273105bd41d930c00cf6d61008f
255 lines
9.9 KiB
C++
255 lines
9.9 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_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 LicenseWhiteboxSignRenewalRequestTest : public LicenseWhiteboxTestBase {
|
|
protected:
|
|
void SetUp() override {
|
|
LicenseWhiteboxTestBase::SetUp();
|
|
|
|
// We don't know the actual signature size, so make the buffer large enough
|
|
// that it should accomidate any change in signature size.
|
|
signature_size_ = 256;
|
|
signature_.resize(signature_size_);
|
|
}
|
|
|
|
void LoadLicense(const TestLicenseBuilder::Settings& settings) {
|
|
TestLicenseBuilder builder;
|
|
builder.SetSettings(settings);
|
|
|
|
builder.AddSigningKey(signing_key_);
|
|
// Add a throw away key. We just need a key in the license since a license
|
|
// should always have a content key.
|
|
builder.AddContentKey(golden_data_.CBCContent().software_crypto_key);
|
|
|
|
auto server = TestServer::CreateDualKey();
|
|
|
|
License license;
|
|
builder.Build(*server, &license);
|
|
|
|
ASSERT_EQ(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(),
|
|
license.request.data(), license.request.size()),
|
|
WB_RESULT_OK);
|
|
}
|
|
|
|
// Get the expected signature for |message|. By returning the message, this
|
|
// will allow us to assert in the test, giving us better output in the case of
|
|
// a failure.
|
|
std::vector<uint8_t> GetSignature(const std::vector<uint8_t>& message) {
|
|
// The client key is the second half of the signing key.
|
|
std::string key_str(signing_key_.begin(), signing_key_.end());
|
|
key_str.erase(0, crypto_util::kSigningKeySizeBytes);
|
|
|
|
const std::string signature = crypto_util::CreateSignatureHmacSha256(
|
|
key_str, std::string(message.begin(), message.end()));
|
|
|
|
return std::vector<uint8_t>(signature.begin(), signature.end());
|
|
}
|
|
|
|
const std::string session_key_ = "0123456789ABCDEF";
|
|
|
|
const std::array<uint8_t, 64> signing_key_ =
|
|
TestLicenseBuilder::DefaultSigningKey();
|
|
|
|
size_t signature_size_;
|
|
std::vector<uint8_t> signature_;
|
|
|
|
const std::vector<uint8_t> garbage_request_ = {
|
|
0x1e, 0x70, 0xbd, 0xeb, 0x24, 0xf2, 0x9d, 0x05, 0xc5, 0xb5,
|
|
0xf4, 0xca, 0xe6, 0x1d, 0x01, 0x97, 0x29, 0xf4, 0xe0, 0x7c,
|
|
0xfd, 0xcc, 0x97, 0x8d, 0xc2, 0xbb, 0x2d, 0x9b, 0x6b, 0x45,
|
|
0x06, 0xbd, 0x2c, 0x66, 0x10, 0x42, 0x73, 0x8d, 0x88, 0x9b,
|
|
0x18, 0xcc, 0xcb, 0x7e, 0x43, 0x23, 0x06, 0xe9, 0x8f, 0x8f,
|
|
};
|
|
};
|
|
|
|
TEST_F(LicenseWhiteboxSignRenewalRequestTest, SuccessWithInvalidRequest) {
|
|
TestLicenseBuilder::Settings settings;
|
|
settings.padding = TestLicenseBuilder::Padding::kNone;
|
|
LoadLicense(settings);
|
|
|
|
ASSERT_EQ(WB_License_SignRenewalRequest(whitebox_, garbage_request_.data(),
|
|
garbage_request_.size(),
|
|
signature_.data(), &signature_size_),
|
|
WB_RESULT_OK);
|
|
|
|
signature_.resize(signature_size_);
|
|
ASSERT_EQ(signature_, GetSignature(garbage_request_));
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxSignRenewalRequestTest,
|
|
SuccessWithSigningKeyPKSC8Padding) {
|
|
TestLicenseBuilder::Settings settings;
|
|
settings.padding = TestLicenseBuilder::Padding::kPKSC8;
|
|
LoadLicense(settings);
|
|
|
|
ASSERT_EQ(WB_License_SignRenewalRequest(whitebox_, garbage_request_.data(),
|
|
garbage_request_.size(),
|
|
signature_.data(), &signature_size_),
|
|
WB_RESULT_OK);
|
|
|
|
signature_.resize(signature_size_);
|
|
ASSERT_EQ(signature_, GetSignature(garbage_request_));
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxSignRenewalRequestTest, InvalidParameterForNullWhitebox) {
|
|
TestLicenseBuilder::Settings settings;
|
|
settings.padding = TestLicenseBuilder::Padding::kNone;
|
|
LoadLicense(settings);
|
|
|
|
ASSERT_EQ(WB_License_SignRenewalRequest(nullptr, garbage_request_.data(),
|
|
garbage_request_.size(),
|
|
signature_.data(), &signature_size_),
|
|
WB_RESULT_INVALID_PARAMETER);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxSignRenewalRequestTest, InvalidParameterForNullMessage) {
|
|
TestLicenseBuilder::Settings settings;
|
|
settings.padding = TestLicenseBuilder::Padding::kNone;
|
|
LoadLicense(settings);
|
|
|
|
ASSERT_EQ(
|
|
WB_License_SignRenewalRequest(whitebox_, nullptr, garbage_request_.size(),
|
|
signature_.data(), &signature_size_),
|
|
WB_RESULT_INVALID_PARAMETER);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxSignRenewalRequestTest,
|
|
InvalidParameterForZeroMessageSize) {
|
|
TestLicenseBuilder::Settings settings;
|
|
settings.padding = TestLicenseBuilder::Padding::kNone;
|
|
LoadLicense(settings);
|
|
|
|
ASSERT_EQ(WB_License_SignRenewalRequest(whitebox_, garbage_request_.data(), 0,
|
|
signature_.data(), &signature_size_),
|
|
WB_RESULT_INVALID_PARAMETER);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxSignRenewalRequestTest, CanProbeSizeWithNullSignature) {
|
|
TestLicenseBuilder::Settings settings;
|
|
settings.padding = TestLicenseBuilder::Padding::kNone;
|
|
LoadLicense(settings);
|
|
signature_size_ = 0;
|
|
|
|
ASSERT_EQ(WB_License_SignRenewalRequest(whitebox_, garbage_request_.data(),
|
|
garbage_request_.size(), nullptr,
|
|
&signature_size_),
|
|
WB_RESULT_BUFFER_TOO_SMALL);
|
|
ASSERT_GT(signature_size_, 0);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxSignRenewalRequestTest,
|
|
InvalidParameterForNullSignature) {
|
|
TestLicenseBuilder::Settings settings;
|
|
settings.padding = TestLicenseBuilder::Padding::kNone;
|
|
LoadLicense(settings);
|
|
|
|
ASSERT_EQ(WB_License_SignRenewalRequest(whitebox_, garbage_request_.data(),
|
|
garbage_request_.size(), nullptr,
|
|
&signature_size_),
|
|
WB_RESULT_INVALID_PARAMETER);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxSignRenewalRequestTest,
|
|
InvalidParameterForNullSignatureSize) {
|
|
TestLicenseBuilder::Settings settings;
|
|
settings.padding = TestLicenseBuilder::Padding::kNone;
|
|
LoadLicense(settings);
|
|
|
|
ASSERT_EQ(WB_License_SignRenewalRequest(whitebox_, garbage_request_.data(),
|
|
garbage_request_.size(),
|
|
signature_.data(), nullptr),
|
|
WB_RESULT_INVALID_PARAMETER);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxSignRenewalRequestTest, BufferTooSmall) {
|
|
TestLicenseBuilder::Settings settings;
|
|
settings.padding = TestLicenseBuilder::Padding::kNone;
|
|
LoadLicense(settings);
|
|
|
|
// We need the signature to be too small. While it would be possible to use
|
|
// zero, using a non-zero value ensures that we are not combining "empty" and
|
|
// "too small".
|
|
signature_size_ = 1;
|
|
|
|
ASSERT_EQ(WB_License_SignRenewalRequest(whitebox_, garbage_request_.data(),
|
|
garbage_request_.size(),
|
|
signature_.data(), &signature_size_),
|
|
WB_RESULT_BUFFER_TOO_SMALL);
|
|
|
|
// Since the API does not limit the signature size, we can't specify the
|
|
// actual expected size, however, it should at least be greater than our "too
|
|
// small" size.
|
|
ASSERT_GT(signature_size_, 1u);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxSignRenewalRequestTest, InvalidStateForNoLicense) {
|
|
// Unlike the other tests, we do not call LoadLicense() because we need to
|
|
// have no license loaded in order to have no renewal key, which is the
|
|
// criteria WB_RESULT_INVALID_STATE.
|
|
|
|
ASSERT_EQ(WB_License_SignRenewalRequest(whitebox_, garbage_request_.data(),
|
|
garbage_request_.size(),
|
|
signature_.data(), &signature_size_),
|
|
WB_RESULT_INVALID_STATE);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxSignRenewalRequestTest, KeyUnavailableForNoSigningKey) {
|
|
// Make a license with no signing key but has a content key. Every license
|
|
// must have a content key.
|
|
TestLicenseBuilder builder;
|
|
builder.AddContentKey(golden_data_.CBCContent().software_crypto_key);
|
|
|
|
auto server = TestServer::CreateDualKey();
|
|
|
|
License license;
|
|
builder.Build(*server, &license);
|
|
|
|
ASSERT_EQ(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(),
|
|
license.request.data(), license.request.size()),
|
|
WB_RESULT_OK);
|
|
|
|
ASSERT_EQ(WB_License_SignRenewalRequest(whitebox_, garbage_request_.data(),
|
|
garbage_request_.size(),
|
|
signature_.data(), &signature_size_),
|
|
WB_RESULT_KEY_UNAVAILABLE);
|
|
}
|
|
|
|
TEST_F(LicenseWhiteboxSignRenewalRequestTest, KeyUnavailableForInvalidKey) {
|
|
// There are multiple ways for us to invalid a signing key. We have tests that
|
|
// test invalid keys (see the query signing 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_signing_key_iv = false;
|
|
LoadLicense(settings);
|
|
|
|
ASSERT_EQ(WB_License_SignRenewalRequest(whitebox_, garbage_request_.data(),
|
|
garbage_request_.size(),
|
|
signature_.data(), &signature_size_),
|
|
WB_RESULT_KEY_UNAVAILABLE);
|
|
}
|
|
|
|
} // namespace widevine
|