Fix AssetId overflow for classic WVM decryption
Javascript/JSON does not support int64_t or unsigned numbers. asset_id, if greater than 0x80000000 will be converted to negative number. Use double to represent asset_id instead as 32-bit integer can be lossless represented using double. Bug: 26309000 Change-Id: I3e800c396a1231375776295154fb0d96156e980b
This commit is contained in:
parent
a9b039c3f9
commit
a4659c40dd
|
@ -184,7 +184,9 @@ Status WidevineKeySource::FetchKeys(const std::vector<uint8_t>& pssh_data) {
|
||||||
Status WidevineKeySource::FetchKeys(uint32_t asset_id) {
|
Status WidevineKeySource::FetchKeys(uint32_t asset_id) {
|
||||||
base::AutoLock scoped_lock(lock_);
|
base::AutoLock scoped_lock(lock_);
|
||||||
request_dict_.Clear();
|
request_dict_.Clear();
|
||||||
request_dict_.SetInteger("asset_id", asset_id);
|
// Javascript/JSON does not support int64_t or unsigned numbers. Use double
|
||||||
|
// instead as 32-bit integer can be lossless represented using double.
|
||||||
|
request_dict_.SetDouble("asset_id", asset_id);
|
||||||
return FetchKeysInternal(!kEnableKeyRotation, 0, true);
|
return FetchKeysInternal(!kEnableKeyRotation, 0, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -381,12 +383,18 @@ void WidevineKeySource::FillRequest(bool enable_key_rotation,
|
||||||
|
|
||||||
// Build key rotation fields.
|
// Build key rotation fields.
|
||||||
if (enable_key_rotation) {
|
if (enable_key_rotation) {
|
||||||
request_dict_.SetInteger("first_crypto_period_index",
|
// Javascript/JSON does not support int64_t or unsigned numbers. Use double
|
||||||
|
// instead as 32-bit integer can be lossless represented using double.
|
||||||
|
request_dict_.SetDouble("first_crypto_period_index",
|
||||||
first_crypto_period_index);
|
first_crypto_period_index);
|
||||||
request_dict_.SetInteger("crypto_period_count", crypto_period_count_);
|
request_dict_.SetInteger("crypto_period_count", crypto_period_count_);
|
||||||
}
|
}
|
||||||
|
|
||||||
base::JSONWriter::Write(request_dict_, request);
|
base::JSONWriter::WriteWithOptions(
|
||||||
|
request_dict_,
|
||||||
|
// Write doubles that have no fractional part as a normal integer, i.e.
|
||||||
|
// without using exponential notation or appending a '.0'.
|
||||||
|
base::JSONWriter::OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
Status WidevineKeySource::GenerateKeyMessage(const std::string& request,
|
Status WidevineKeySource::GenerateKeyMessage(const std::string& request,
|
||||||
|
|
|
@ -43,6 +43,12 @@ const char kLicenseStatusUnknownError[] = "UNKNOWN_ERROR";
|
||||||
const char kExpectedRequestMessageFormat[] =
|
const char kExpectedRequestMessageFormat[] =
|
||||||
"{\"content_id\":\"%s\",\"drm_types\":[\"WIDEVINE\"],\"policy\":\"%s\","
|
"{\"content_id\":\"%s\",\"drm_types\":[\"WIDEVINE\"],\"policy\":\"%s\","
|
||||||
"\"tracks\":[{\"type\":\"SD\"},{\"type\":\"HD\"},{\"type\":\"AUDIO\"}]}";
|
"\"tracks\":[{\"type\":\"SD\"},{\"type\":\"HD\"},{\"type\":\"AUDIO\"}]}";
|
||||||
|
const char kExpectedRequestMessageWithAssetIdFormat[] =
|
||||||
|
"{\"asset_id\":%u,\"drm_types\":[\"WIDEVINE\"],"
|
||||||
|
"\"tracks\":[{\"type\":\"SD\"},{\"type\":\"HD\"},{\"type\":\"AUDIO\"}]}";
|
||||||
|
const char kExpectedRequestMessageWithPsshFormat[] =
|
||||||
|
"{\"drm_types\":[\"WIDEVINE\"],\"pssh_data\":\"%s\","
|
||||||
|
"\"tracks\":[{\"type\":\"SD\"},{\"type\":\"HD\"},{\"type\":\"AUDIO\"}]}";
|
||||||
const char kExpectedSignedMessageFormat[] =
|
const char kExpectedSignedMessageFormat[] =
|
||||||
"{\"request\":\"%s\",\"signature\":\"%s\",\"signer\":\"%s\"}";
|
"{\"request\":\"%s\",\"signature\":\"%s\",\"signer\":\"%s\"}";
|
||||||
const char kTrackFormat[] =
|
const char kTrackFormat[] =
|
||||||
|
@ -52,7 +58,9 @@ const char kClassicTrackFormat[] = "{\"type\":\"%s\",\"key\":\"%s\"}";
|
||||||
const char kLicenseResponseFormat[] = "{\"status\":\"%s\",\"tracks\":[%s]}";
|
const char kLicenseResponseFormat[] = "{\"status\":\"%s\",\"tracks\":[%s]}";
|
||||||
const char kHttpResponseFormat[] = "{\"response\":\"%s\"}";
|
const char kHttpResponseFormat[] = "{\"response\":\"%s\"}";
|
||||||
const char kRequestPsshData[] = "PSSH data";
|
const char kRequestPsshData[] = "PSSH data";
|
||||||
const uint32_t kClassicAssetId = 1234;
|
// 32-bit with leading bit set, to verify that big uint32_t can be handled
|
||||||
|
// correctly.
|
||||||
|
const uint32_t kClassicAssetId = 0x80038cd9;
|
||||||
|
|
||||||
std::string Base64Encode(const std::string& input) {
|
std::string Base64Encode(const std::string& input) {
|
||||||
std::string output;
|
std::string output;
|
||||||
|
@ -212,7 +220,8 @@ TEST_F(WidevineKeySourceTest, GenerateSignatureFailure) {
|
||||||
TEST_F(WidevineKeySourceTest, HttpFetchFailure) {
|
TEST_F(WidevineKeySourceTest, HttpFetchFailure) {
|
||||||
std::string expected_message = base::StringPrintf(
|
std::string expected_message = base::StringPrintf(
|
||||||
kExpectedRequestMessageFormat, Base64Encode(kContentId).c_str(), kPolicy);
|
kExpectedRequestMessageFormat, Base64Encode(kContentId).c_str(), kPolicy);
|
||||||
EXPECT_CALL(*mock_request_signer_, GenerateSignature(expected_message, _))
|
EXPECT_CALL(*mock_request_signer_,
|
||||||
|
GenerateSignature(StrEq(expected_message), _))
|
||||||
.WillOnce(DoAll(SetArgPointee<1>(kMockSignature), Return(true)));
|
.WillOnce(DoAll(SetArgPointee<1>(kMockSignature), Return(true)));
|
||||||
|
|
||||||
std::string expected_post_data =
|
std::string expected_post_data =
|
||||||
|
@ -258,29 +267,43 @@ TEST_F(WidevineKeySourceTest, LicenseStatusCencNotOK) {
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WidevineKeySourceTest, LicenseStatusCencWithPsshDataOK) {
|
TEST_F(WidevineKeySourceTest, LicenseStatusCencWithPsshDataOK) {
|
||||||
|
std::string expected_message =
|
||||||
|
base::StringPrintf(kExpectedRequestMessageWithPsshFormat,
|
||||||
|
Base64Encode(kRequestPsshData).c_str());
|
||||||
|
EXPECT_CALL(*mock_request_signer_,
|
||||||
|
GenerateSignature(StrEq(expected_message), _))
|
||||||
|
.WillOnce(DoAll(SetArgPointee<1>(kMockSignature), Return(true)));
|
||||||
|
|
||||||
std::string mock_response = base::StringPrintf(
|
std::string mock_response = base::StringPrintf(
|
||||||
kHttpResponseFormat, Base64Encode(GenerateMockLicenseResponse()).c_str());
|
kHttpResponseFormat, Base64Encode(GenerateMockLicenseResponse()).c_str());
|
||||||
|
|
||||||
EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _))
|
EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _))
|
||||||
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)));
|
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)));
|
||||||
|
|
||||||
CreateWidevineKeySource();
|
CreateWidevineKeySource();
|
||||||
|
widevine_key_source_->set_signer(mock_request_signer_.Pass());
|
||||||
std::vector<uint8_t> pssh_data(
|
std::vector<uint8_t> pssh_data(
|
||||||
reinterpret_cast<const uint8_t*>(kRequestPsshData),
|
reinterpret_cast<const uint8_t*>(kRequestPsshData),
|
||||||
reinterpret_cast<const uint8_t*>(kRequestPsshData) + strlen(kContentId));
|
reinterpret_cast<const uint8_t*>(kRequestPsshData) +
|
||||||
|
strlen(kRequestPsshData));
|
||||||
ASSERT_OK(widevine_key_source_->FetchKeys(pssh_data));
|
ASSERT_OK(widevine_key_source_->FetchKeys(pssh_data));
|
||||||
VerifyKeys(false);
|
VerifyKeys(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_F(WidevineKeySourceTest, LicenseStatusClassicOK) {
|
TEST_F(WidevineKeySourceTest, LicenseStatusClassicOK) {
|
||||||
|
std::string expected_message = base::StringPrintf(
|
||||||
|
kExpectedRequestMessageWithAssetIdFormat, kClassicAssetId);
|
||||||
|
EXPECT_CALL(*mock_request_signer_,
|
||||||
|
GenerateSignature(StrEq(expected_message), _))
|
||||||
|
.WillOnce(DoAll(SetArgPointee<1>(kMockSignature), Return(true)));
|
||||||
|
|
||||||
std::string mock_response = base::StringPrintf(
|
std::string mock_response = base::StringPrintf(
|
||||||
kHttpResponseFormat, Base64Encode(
|
kHttpResponseFormat, Base64Encode(
|
||||||
GenerateMockClassicLicenseResponse()).c_str());
|
GenerateMockClassicLicenseResponse()).c_str());
|
||||||
|
|
||||||
EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _))
|
EXPECT_CALL(*mock_key_fetcher_, FetchKeys(_, _, _))
|
||||||
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)));
|
.WillOnce(DoAll(SetArgPointee<2>(mock_response), Return(Status::OK)));
|
||||||
|
|
||||||
CreateWidevineKeySource();
|
CreateWidevineKeySource();
|
||||||
|
widevine_key_source_->set_signer(mock_request_signer_.Pass());
|
||||||
ASSERT_OK(widevine_key_source_->FetchKeys(kClassicAssetId));
|
ASSERT_OK(widevine_key_source_->FetchKeys(kClassicAssetId));
|
||||||
VerifyKeys(true);
|
VerifyKeys(true);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue