Add function to sign PST report
When using usage tables, the PST report needs to be signed with SHA1 instead of SHA256 like for renewal messages.
This commit is contained in:
@@ -237,8 +237,8 @@ WB_Result WB_License_QueryKeyStatus(const WB_License_Whitebox* whitebox,
|
||||
size_t key_id_size,
|
||||
WB_KeyStatus* key_status);
|
||||
|
||||
// Signs |message| and return the signature via |signature| using HMAC and the
|
||||
// client renewal signing key
|
||||
// Signs |message| and return the signature via |signature| using HMAC-SHA256
|
||||
// and the client renewal signing key
|
||||
//
|
||||
// Args:
|
||||
// whitebox (in) : The white-box instance containing the signing key.
|
||||
@@ -272,6 +272,41 @@ WB_Result WB_License_SignRenewalRequest(const WB_License_Whitebox* whitebox,
|
||||
uint8_t* signature,
|
||||
size_t* signature_size);
|
||||
|
||||
// Signs |message| and return the signature via |signature| using HMAC-SHA1 and
|
||||
// the client renewal signing key
|
||||
//
|
||||
// Args:
|
||||
// whitebox (in) : The white-box instance containing the signing key.
|
||||
//
|
||||
// message (in) : The message that should be signed.
|
||||
//
|
||||
// message_size (in) : The number of bytes in |message|.
|
||||
//
|
||||
// signature (out) : The output parameter used to return the signature. This
|
||||
// can be null if |*signature_size| is 0; this should return
|
||||
// WB_RESULT_BUFFER_TOO_SMALL and fill |signature_size|.
|
||||
//
|
||||
// signature_size (in/out) : As input, this contains the max number of bytes
|
||||
// that can be written to |signature|. As output, |signature_size| is set to
|
||||
// the required size on WB_RESULT_OK and WB_RESULT_BUFFER_TOO_SMALL.
|
||||
//
|
||||
// Returns:
|
||||
// WB_RESULT_OK if |message| was successfully signed.
|
||||
//
|
||||
// WB_RESULT_INVALID_PARAMETER if |whitebox| was null, if |message| was null,
|
||||
// if |message_size| was zero, if |signature| was null, or if |signature_size|
|
||||
// was null.
|
||||
//
|
||||
// WB_RESULT_BUFFER_TOO_SMALL if |signature_size| (as input) was less than the
|
||||
// required size.
|
||||
//
|
||||
// WB_RESULT_INVALID_STATE if |whitebox| had no signing keys.
|
||||
WB_Result WB_License_SignPstReport(const WB_License_Whitebox* whitebox,
|
||||
const uint8_t* message,
|
||||
size_t message_size,
|
||||
uint8_t* signature,
|
||||
size_t* signature_size);
|
||||
|
||||
// Verifies the renewal response using HMAC and the server signing key.
|
||||
//
|
||||
// Args:
|
||||
|
||||
@@ -14,7 +14,9 @@
|
||||
|
||||
namespace widevine {
|
||||
|
||||
class LicenseWhiteboxSignRenewalRequestTest : public LicenseWhiteboxTestBase {
|
||||
class LicenseWhiteboxSignRenewalPstTest
|
||||
: public LicenseWhiteboxTestBase,
|
||||
public testing::WithParamInterface<bool> {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
LicenseWhiteboxTestBase::SetUp();
|
||||
@@ -23,6 +25,9 @@ class LicenseWhiteboxSignRenewalRequestTest : public LicenseWhiteboxTestBase {
|
||||
// that it should accomidate any change in signature size.
|
||||
signature_size_ = 256;
|
||||
signature_.resize(signature_size_);
|
||||
|
||||
sign_func_ =
|
||||
GetParam() ? &WB_License_SignRenewalRequest : &WB_License_SignPstReport;
|
||||
}
|
||||
|
||||
void LoadLicense(const TestLicenseBuilder::Settings& settings) {
|
||||
@@ -57,8 +62,10 @@ class LicenseWhiteboxSignRenewalRequestTest : public LicenseWhiteboxTestBase {
|
||||
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()));
|
||||
auto func = GetParam() ? &widevine::crypto_util::CreateSignatureHmacSha256
|
||||
: &widevine::crypto_util::CreateSignatureHmacSha1;
|
||||
const std::string signature =
|
||||
func(key_str, std::string(message.begin(), message.end()));
|
||||
|
||||
return std::vector<uint8_t>(signature.begin(), signature.end());
|
||||
}
|
||||
@@ -78,108 +85,105 @@ class LicenseWhiteboxSignRenewalRequestTest : public LicenseWhiteboxTestBase {
|
||||
0x06, 0xbd, 0x2c, 0x66, 0x10, 0x42, 0x73, 0x8d, 0x88, 0x9b,
|
||||
0x18, 0xcc, 0xcb, 0x7e, 0x43, 0x23, 0x06, 0xe9, 0x8f, 0x8f,
|
||||
};
|
||||
|
||||
// Both functions have the same signature; store a pointer to which function
|
||||
// to call.
|
||||
decltype(&WB_License_SignRenewalRequest) sign_func_;
|
||||
};
|
||||
|
||||
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) {
|
||||
TEST_P(LicenseWhiteboxSignRenewalPstTest, SuccessWithInvalidRequest) {
|
||||
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);
|
||||
sign_func_(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,
|
||||
InvalidParameterForZeroMessageSize) {
|
||||
TEST_P(LicenseWhiteboxSignRenewalPstTest, SuccessWithSigningKeyPKSC8Padding) {
|
||||
TestLicenseBuilder::Settings settings;
|
||||
settings.padding = TestLicenseBuilder::Padding::kPKSC8;
|
||||
LoadLicense(settings);
|
||||
|
||||
ASSERT_EQ(
|
||||
sign_func_(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_P(LicenseWhiteboxSignRenewalPstTest, InvalidParameterForNullWhitebox) {
|
||||
TestLicenseBuilder::Settings settings;
|
||||
settings.padding = TestLicenseBuilder::Padding::kNone;
|
||||
LoadLicense(settings);
|
||||
|
||||
ASSERT_EQ(WB_License_SignRenewalRequest(whitebox_, garbage_request_.data(), 0,
|
||||
signature_.data(), &signature_size_),
|
||||
ASSERT_EQ(
|
||||
sign_func_(nullptr, garbage_request_.data(), garbage_request_.size(),
|
||||
signature_.data(), &signature_size_),
|
||||
WB_RESULT_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
TEST_P(LicenseWhiteboxSignRenewalPstTest, InvalidParameterForNullMessage) {
|
||||
TestLicenseBuilder::Settings settings;
|
||||
settings.padding = TestLicenseBuilder::Padding::kNone;
|
||||
LoadLicense(settings);
|
||||
|
||||
ASSERT_EQ(sign_func_(whitebox_, nullptr, garbage_request_.size(),
|
||||
signature_.data(), &signature_size_),
|
||||
WB_RESULT_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
TEST_F(LicenseWhiteboxSignRenewalRequestTest, CanProbeSizeWithNullSignature) {
|
||||
TEST_P(LicenseWhiteboxSignRenewalPstTest, InvalidParameterForZeroMessageSize) {
|
||||
TestLicenseBuilder::Settings settings;
|
||||
settings.padding = TestLicenseBuilder::Padding::kNone;
|
||||
LoadLicense(settings);
|
||||
|
||||
ASSERT_EQ(sign_func_(whitebox_, garbage_request_.data(), 0, signature_.data(),
|
||||
&signature_size_),
|
||||
WB_RESULT_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
TEST_P(LicenseWhiteboxSignRenewalPstTest, 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_),
|
||||
ASSERT_EQ(sign_func_(whitebox_, garbage_request_.data(),
|
||||
garbage_request_.size(), nullptr, &signature_size_),
|
||||
WB_RESULT_BUFFER_TOO_SMALL);
|
||||
ASSERT_GT(signature_size_, 0);
|
||||
}
|
||||
|
||||
TEST_F(LicenseWhiteboxSignRenewalRequestTest,
|
||||
InvalidParameterForNullSignature) {
|
||||
TEST_P(LicenseWhiteboxSignRenewalPstTest, 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_),
|
||||
ASSERT_EQ(sign_func_(whitebox_, garbage_request_.data(),
|
||||
garbage_request_.size(), nullptr, &signature_size_),
|
||||
WB_RESULT_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
TEST_F(LicenseWhiteboxSignRenewalRequestTest,
|
||||
TEST_P(LicenseWhiteboxSignRenewalPstTest,
|
||||
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),
|
||||
ASSERT_EQ(sign_func_(whitebox_, garbage_request_.data(),
|
||||
garbage_request_.size(), signature_.data(), nullptr),
|
||||
WB_RESULT_INVALID_PARAMETER);
|
||||
}
|
||||
|
||||
TEST_F(LicenseWhiteboxSignRenewalRequestTest, BufferTooSmall) {
|
||||
TEST_P(LicenseWhiteboxSignRenewalPstTest, BufferTooSmall) {
|
||||
TestLicenseBuilder::Settings settings;
|
||||
settings.padding = TestLicenseBuilder::Padding::kNone;
|
||||
LoadLicense(settings);
|
||||
@@ -189,10 +193,10 @@ TEST_F(LicenseWhiteboxSignRenewalRequestTest, BufferTooSmall) {
|
||||
// "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);
|
||||
ASSERT_EQ(
|
||||
sign_func_(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
|
||||
@@ -200,18 +204,18 @@ TEST_F(LicenseWhiteboxSignRenewalRequestTest, BufferTooSmall) {
|
||||
ASSERT_GT(signature_size_, 1u);
|
||||
}
|
||||
|
||||
TEST_F(LicenseWhiteboxSignRenewalRequestTest, InvalidStateForNoLicense) {
|
||||
TEST_P(LicenseWhiteboxSignRenewalPstTest, 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);
|
||||
ASSERT_EQ(
|
||||
sign_func_(whitebox_, garbage_request_.data(), garbage_request_.size(),
|
||||
signature_.data(), &signature_size_),
|
||||
WB_RESULT_INVALID_STATE);
|
||||
}
|
||||
|
||||
TEST_F(LicenseWhiteboxSignRenewalRequestTest, KeyUnavailableForNoSigningKey) {
|
||||
TEST_P(LicenseWhiteboxSignRenewalPstTest, KeyUnavailableForNoSigningKey) {
|
||||
// Make a license with no signing key but has a content key. Every license
|
||||
// must have a content key.
|
||||
TestLicenseBuilder builder;
|
||||
@@ -231,13 +235,13 @@ TEST_F(LicenseWhiteboxSignRenewalRequestTest, KeyUnavailableForNoSigningKey) {
|
||||
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);
|
||||
ASSERT_EQ(
|
||||
sign_func_(whitebox_, garbage_request_.data(), garbage_request_.size(),
|
||||
signature_.data(), &signature_size_),
|
||||
WB_RESULT_KEY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
TEST_F(LicenseWhiteboxSignRenewalRequestTest, KeyUnavailableForInvalidKey) {
|
||||
TEST_P(LicenseWhiteboxSignRenewalPstTest, 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.
|
||||
@@ -245,10 +249,17 @@ TEST_F(LicenseWhiteboxSignRenewalRequestTest, KeyUnavailableForInvalidKey) {
|
||||
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);
|
||||
ASSERT_EQ(
|
||||
sign_func_(whitebox_, garbage_request_.data(), garbage_request_.size(),
|
||||
signature_.data(), &signature_size_),
|
||||
WB_RESULT_KEY_UNAVAILABLE);
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(TestAll,
|
||||
LicenseWhiteboxSignRenewalPstTest,
|
||||
testing::Bool(),
|
||||
[](const testing::TestParamInfo<bool>& info) {
|
||||
return info.param ? "Renewal" : "PST";
|
||||
});
|
||||
|
||||
} // namespace widevine
|
||||
|
||||
@@ -511,17 +511,19 @@ WB_Result WB_License_QueryKeyStatus(const WB_License_Whitebox* whitebox,
|
||||
return WB_RESULT_INVALID_PARAMETER; // Unknown query type.
|
||||
}
|
||||
|
||||
WB_Result WB_License_SignRenewalRequest(const WB_License_Whitebox* whitebox,
|
||||
const uint8_t* message,
|
||||
size_t message_size,
|
||||
uint8_t* signature,
|
||||
size_t* signature_size) {
|
||||
static WB_Result WB_License_SignCommon(const WB_License_Whitebox* whitebox,
|
||||
const uint8_t* message,
|
||||
size_t message_size,
|
||||
uint8_t* signature,
|
||||
size_t* signature_size,
|
||||
bool sha256) {
|
||||
if (!whitebox || !message || !signature_size) {
|
||||
DVLOG(1) << "Invalid parameter: null pointer.";
|
||||
return WB_RESULT_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (!CheckAndUpdateSize(SHA256_DIGEST_LENGTH, signature_size)) {
|
||||
if (!CheckAndUpdateSize(sha256 ? SHA256_DIGEST_LENGTH : SHA_DIGEST_LENGTH,
|
||||
signature_size)) {
|
||||
return WB_RESULT_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
@@ -550,17 +552,36 @@ WB_Result WB_License_SignRenewalRequest(const WB_License_Whitebox* whitebox,
|
||||
return WB_RESULT_KEY_UNAVAILABLE;
|
||||
}
|
||||
|
||||
auto func = sha256 ? &widevine::crypto_util::CreateSignatureHmacSha256
|
||||
: &widevine::crypto_util::CreateSignatureHmacSha1;
|
||||
const std::string computed_signature =
|
||||
widevine::crypto_util::CreateSignatureHmacSha256(
|
||||
std::string(whitebox->renewal_key->client.begin(),
|
||||
whitebox->renewal_key->client.end()),
|
||||
std::string(message, message + message_size));
|
||||
func(std::string(whitebox->renewal_key->client.begin(),
|
||||
whitebox->renewal_key->client.end()),
|
||||
std::string(message, message + message_size));
|
||||
|
||||
CHECK(widevine::MemCopy(computed_signature.data(), computed_signature.size(),
|
||||
signature, *signature_size));
|
||||
return WB_RESULT_OK;
|
||||
}
|
||||
|
||||
WB_Result WB_License_SignRenewalRequest(const WB_License_Whitebox* whitebox,
|
||||
const uint8_t* message,
|
||||
size_t message_size,
|
||||
uint8_t* signature,
|
||||
size_t* signature_size) {
|
||||
return WB_License_SignCommon(whitebox, message, message_size, signature,
|
||||
signature_size, /* sha256= */ true);
|
||||
}
|
||||
|
||||
WB_Result WB_License_SignPstReport(const WB_License_Whitebox* whitebox,
|
||||
const uint8_t* message,
|
||||
size_t message_size,
|
||||
uint8_t* signature,
|
||||
size_t* signature_size) {
|
||||
return WB_License_SignCommon(whitebox, message, message_size, signature,
|
||||
signature_size, /* sha256= */ false);
|
||||
}
|
||||
|
||||
WB_Result WB_License_VerifyRenewalResponse(const WB_License_Whitebox* whitebox,
|
||||
const uint8_t* message,
|
||||
size_t message_size,
|
||||
|
||||
Reference in New Issue
Block a user