Merge "Handle key rotation" into qt-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
862cb96e77
@@ -34,6 +34,7 @@ class InitializationData {
|
||||
CdmHlsMethod hls_method() const { return hls_method_; }
|
||||
std::vector<video_widevine::WidevinePsshData_EntitledKey> ExtractWrappedKeys()
|
||||
const;
|
||||
bool contains_entitled_keys() const { return contains_entitled_keys_; }
|
||||
|
||||
private:
|
||||
bool SelectWidevinePssh(const CdmInitData& init_data,
|
||||
@@ -86,6 +87,7 @@ class InitializationData {
|
||||
bool is_hls_;
|
||||
bool is_webm_;
|
||||
bool is_audio_;
|
||||
bool contains_entitled_keys_;
|
||||
|
||||
std::vector<uint8_t> hls_iv_;
|
||||
CdmHlsMethod hls_method_;
|
||||
|
||||
@@ -439,8 +439,13 @@ CdmResponseType CdmSession::GenerateKeyRequestInternal(
|
||||
|
||||
if (is_release_) {
|
||||
return GenerateReleaseRequest(key_request);
|
||||
} else if (license_received_) { // renewal
|
||||
return GenerateRenewalRequest(key_request);
|
||||
} else if (license_received_) {
|
||||
// A call to GenerateKeyRequest after the initial license has been received
|
||||
// is either a renewal request or a key rotation event
|
||||
if (init_data.contains_entitled_keys())
|
||||
return license_parser_->HandleEmbeddedKeyData(init_data);
|
||||
else
|
||||
return GenerateRenewalRequest(key_request);
|
||||
} else {
|
||||
key_request->type = kKeyRequestTypeInitial;
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ InitializationData::InitializationData(const std::string& type,
|
||||
is_hls_(false),
|
||||
is_webm_(false),
|
||||
is_audio_(false),
|
||||
contains_entitled_keys_(false),
|
||||
hls_method_(kHlsMethodNone) {
|
||||
if (type == ISO_BMFF_VIDEO_MIME_TYPE || type == ISO_BMFF_AUDIO_MIME_TYPE ||
|
||||
type == CENC_INIT_DATA_FORMAT) {
|
||||
@@ -138,12 +139,19 @@ bool InitializationData::SelectWidevinePssh(const CdmInitData& init_data,
|
||||
continue;
|
||||
}
|
||||
if (pssh.type() == WidevinePsshData_Type_ENTITLED_KEY) {
|
||||
contains_entitled_keys_ = true;
|
||||
*output = pssh_payloads[i];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
WidevinePsshData pssh;
|
||||
if (prefer_entitlements && pssh.ParseFromString(pssh_payloads[0])) {
|
||||
if (pssh.type() == WidevinePsshData_Type_ENTITLED_KEY)
|
||||
contains_entitled_keys_ = true;
|
||||
}
|
||||
|
||||
// Either there is only one PSSH, this device does not prefer entitlements,
|
||||
// or no entitlement PSSH was found. Regardless of how we got here, select the
|
||||
// first PSSH, which should be a |SINGLE| PSSH.
|
||||
|
||||
@@ -524,12 +524,14 @@ TEST_F(InitializationDataTest, HandlesMultipleWidevinePsshs) {
|
||||
kOemCryptoWithoutEntitlements);
|
||||
EXPECT_FALSE(single_init_data.IsEmpty());
|
||||
EXPECT_EQ(kSingleKeyWidevinePsshBoxData, single_init_data.data());
|
||||
EXPECT_FALSE(single_init_data.contains_entitled_keys());
|
||||
|
||||
InitializationData entitled_init_data(ISO_BMFF_VIDEO_MIME_TYPE,
|
||||
kMultipleWidevinePsshBox,
|
||||
kOemCryptoWithEntitlements);
|
||||
EXPECT_FALSE(entitled_init_data.IsEmpty());
|
||||
EXPECT_EQ(kEntitledKeysWidevinePsshBoxData, entitled_init_data.data());
|
||||
EXPECT_TRUE(entitled_init_data.contains_entitled_keys());
|
||||
}
|
||||
|
||||
TEST_P(HlsKeyFormatVersionsExtractionTest, ExtractKeyFormatVersions) {
|
||||
|
||||
@@ -446,6 +446,54 @@ SubSampleInfo usage_info_sub_samples_icp[] = {
|
||||
wvcdm::a2b_hex("964c2dfda920357c668308d52d33c652"), 0,
|
||||
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample}};
|
||||
|
||||
SubSampleInfo entitlement_with_key_rotation_sub_sample[] = {
|
||||
{
|
||||
true, 1, true, true, false,
|
||||
wvcdm::a2bs_hex("1D9B8E13B59951169348FF8D5B9394C0"),
|
||||
wvcdm::a2b_hex(
|
||||
"64ab17b3e3dfab47245c7cce4543d4fc7a26dcf248f19f9b59f3c92601440b36"
|
||||
"17c8ed0c96c656549e461f38708cd47a434066f8df28ccc28b79252eee3f9c2d"
|
||||
"7f6c68ebe40141fe818fe082ca523c03d69ddaf183a93c022327fedc5582c5ab"
|
||||
"ca9d342b71263a67f9cb2336f12108aaaef464f17177e44e9b0c4e56e61da53c"
|
||||
"2150b4405cc82d994dfd9bf4087c761956d6688a9705db4cf350381085f383c4"
|
||||
"9666d4aed135c519c1f0b5cba06e287feea96ea367bf54e7368dcf998276c6e4"
|
||||
"6497e0c50e20fef74e42cb518fe7f22ef27202428688f86404e8278587017012"
|
||||
"c1d65537c6cbd7dde04aae338d68115a9f430afc100ab83cdadf45dca39db685"),
|
||||
wvcdm::a2b_hex(
|
||||
"4bb2ff540e12e4c97248b63abdf30c4474df11ae8f22ba587e5aa9b64d51f8ce"
|
||||
"209b13cb24f436ac192060690d13d5a1230fe5207287678a3acbaf59b5381186"
|
||||
"92dcdec42c770afc0545407c243a452214d0497f1a044adc56ac1dba5530d5a5"
|
||||
"482f9fc67a5e1d1314e864ad85fec9f78657e10f68ae8720b218339c96e878c1"
|
||||
"c0f09015172d8a52a85b6f09526b98aad6d7326d3799a418581efadd16f9ba3e"
|
||||
"454945428a36959a296aa14fe05cb8ae7b44ae68d82950f0742d38d86f167c36"
|
||||
"75e75390d3cc6cd6db267729b2aa81a7e7c4db186e82d4300c4123c0a5de73e9"
|
||||
"a6bb238bd351769359d1b46c9702270b756038fd54ef609d985eecde58e9a58e"),
|
||||
wvcdm::a2b_hex("f6f4b1e600a5b67813ed2bded913ba9f"), 0,
|
||||
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample},
|
||||
{
|
||||
true, 1, true, true, false,
|
||||
wvcdm::a2bs_hex("A0396729B3795B46A5EA7F9919B96A67"),
|
||||
wvcdm::a2b_hex(
|
||||
"64ab17b3e3dfab47245c7cce4543d4fc7a26dcf248f19f9b59f3c92601440b36"
|
||||
"17c8ed0c96c656549e461f38708cd47a434066f8df28ccc28b79252eee3f9c2d"
|
||||
"7f6c68ebe40141fe818fe082ca523c03d69ddaf183a93c022327fedc5582c5ab"
|
||||
"ca9d342b71263a67f9cb2336f12108aaaef464f17177e44e9b0c4e56e61da53c"
|
||||
"2150b4405cc82d994dfd9bf4087c761956d6688a9705db4cf350381085f383c4"
|
||||
"9666d4aed135c519c1f0b5cba06e287feea96ea367bf54e7368dcf998276c6e4"
|
||||
"6497e0c50e20fef74e42cb518fe7f22ef27202428688f86404e8278587017012"
|
||||
"c1d65537c6cbd7dde04aae338d68115a9f430afc100ab83cdadf45dca39db685"),
|
||||
wvcdm::a2b_hex(
|
||||
"49067453f9fe1b36fb2b37a2bba927bfe7f5f81ce715047beb99675da809b502"
|
||||
"a5638f891cfad95c9fefdb32b6e8614ce3d5528032d51644a6cfaaccea2ad0b6"
|
||||
"dd8bd36a0fb751bf4b70e1cb02266f373be467d3167aed4f3820eb4af884cc39"
|
||||
"f60f83e060c8674b7e53d7ec8934ec07750d4677ed14ad6f6bacf46f46cf3ea8"
|
||||
"560f704220bc3e32b9ad21c74aff6dbdbd64f49f38717ab7a05042dfe6fdc56f"
|
||||
"47ddc384822b9a3fab3445653fa51f2405fcbcfd6d39a7fb8a99777c41960b94"
|
||||
"74f1deb4b9b242bef609c625af791cba63e8c184b0312d624daba3889307b48b"
|
||||
"00c362f246c3bc0b36cd41f9ec8eb72eab603f9517c7948f5e317a93ac1a5631"),
|
||||
wvcdm::a2b_hex("f6f4b1e600a5b67813ed2bded913ba9f"), 0,
|
||||
OEMCrypto_FirstSubsample | OEMCrypto_LastSubsample}};
|
||||
|
||||
// License duration and uncertainty window
|
||||
const uint32_t kSingleEncryptedSubSampleIcpLicenseDurationExpiration = 5;
|
||||
const uint32_t kSingleEncryptedSubSampleIcpLicenseExpirationWindow = 2;
|
||||
@@ -530,6 +578,83 @@ std::string kPsshStreamingClip21 = wvcdm::a2bs_hex(
|
||||
"EDEF8BA979D64ACEA3C827DCD51D21ED00000023" // Widevine system id
|
||||
"08011a0d7769646576696e655f746573" // pssh data
|
||||
"74221073747265616d696e675f636c69703231");
|
||||
const std::string kPsshEntitlementWithKeyRotation[] = {
|
||||
wvcdm::a2bs_hex(
|
||||
"0000003e7073736800000000" // blob size and pssh
|
||||
"edef8ba979d64acea3c827dcd51d21ed0000001e" // Widevine system id
|
||||
"2210426f6f5261646c6579666137613664393800" // pssh data
|
||||
"48e3dc959b0650126a00000002027073"
|
||||
"736800000000edef8ba979d64acea3c8"
|
||||
"27dcd51d21ed000001e22210426f6f52"
|
||||
"61646c657966613761366439380048e3"
|
||||
"dc959b06501258026a0072580a109ab3"
|
||||
"fb7eaffc5ee087568b9581ff0e721210"
|
||||
"4a2da018480c51358c660c4b1a198721"
|
||||
"1a20a00425ef5fe538adba59a6c4ce9a"
|
||||
"fbff394351b79552643e08ed3a0cde2c"
|
||||
"3ca42210931a2ef95b898d804b9a25ef"
|
||||
"6d2805f072580a100fba9bd0f8e055d5"
|
||||
"900bbfaabf5033141210f9bfca8cd3b8"
|
||||
"593897f0b9283cd768f61a209c1d9a96"
|
||||
"573a4dbba68327f03e598adfde1bd29f"
|
||||
"1e709f206c2424d82ca14c1c22108428"
|
||||
"46cffba58c12742418a702138c3a7258"
|
||||
"0a109fec6ad1d36e56cdaf5c232480f6"
|
||||
"3f8812101d9b8e13b59951169348ff8d"
|
||||
"5b9394c01a2058ee6164ae759802e0b1"
|
||||
"f9f7eeeaa3606faf21182777fe716c01"
|
||||
"4c2412621543221039c8a6caab12515e"
|
||||
"3c744a5447e9b72372580a10cd2e9ebf"
|
||||
"89c257e2a3196c82ac4c76ba1210d48f"
|
||||
"8f11c2d853289e981f5775db60441a20"
|
||||
"3b491980b27587592c86e73da27caa12"
|
||||
"d95acda2295f768746090b55b81c9d61"
|
||||
"2210dd7f29944aaeb08826ba4fc0dec6"
|
||||
"c88d72580a10b3fd79204b9d5cbf8f67"
|
||||
"2eca27255e9e121023feaaf517585fde"
|
||||
"bdf0d4693f32c1091a20d18a1c0e54b8"
|
||||
"fbc189b58ccc0dc5a0c541b628b8fe23"
|
||||
"34c862944b5555ad7f7f221091269127"
|
||||
"e4feb6a8fa878c6e9781a55f"),
|
||||
wvcdm::a2bs_hex(
|
||||
"0000003e7073736800000000ed" // blob size and pssh
|
||||
"ef8ba979d64acea3c827dcd51d21ed0000001e" // Widevine system id
|
||||
"2210426f6f5261646c65796661" // pssh data
|
||||
"3761366439380448e3dc959b0650126a"
|
||||
"00000002027073736800000000edef8b"
|
||||
"a979d64acea3c827dcd51d21ed000001"
|
||||
"e22210426f6f5261646c657966613761"
|
||||
"366439380448e3dc959b06501258026a"
|
||||
"0072580a109ab3fb7eaffc5ee087568b"
|
||||
"9581ff0e721210777bc13c94c4568b84"
|
||||
"ddaf99de3f03311a2042949649205d0d"
|
||||
"f4f4a4eec94263561931066a9fc18b61"
|
||||
"8b3929a168b4c2404222101e7aad142f"
|
||||
"59edb962816e8d0702356b72580a100f"
|
||||
"ba9bd0f8e055d5900bbfaabf50331412"
|
||||
"10537cb8f017ec59e7be3c309e6d7f4b"
|
||||
"5d1a2089c49c0f0e214c3765cbb37ab5"
|
||||
"41dc0625c0087fa94317528ee8265431"
|
||||
"71cabe2210dddba401d4eaaa76437638"
|
||||
"a29dbdc38472580a109fec6ad1d36e56"
|
||||
"cdaf5c232480f63f881210a0396729b3"
|
||||
"795b46a5ea7f9919b96a671a209245a1"
|
||||
"c821de9c65fb1086d9af8aaca4b7da0e"
|
||||
"bbd0850a56ab36c23bb71b507e2210b0"
|
||||
"531d2235575ff9ba5af4545bb43fdd72"
|
||||
"580a10cd2e9ebf89c257e2a3196c82ac"
|
||||
"4c76ba121011647820b33352349942cd"
|
||||
"31ce352e571a20277b4392c76a04335d"
|
||||
"3eadf22705184eb1adc057a61e372e78"
|
||||
"30b7a20361d2472210d954557dc853a7"
|
||||
"42283e6dfe16677a6a72580a10b3fd79"
|
||||
"204b9d5cbf8f672eca27255e9e1210c4"
|
||||
"78fb09c0c6531b92c571972c36098b1a"
|
||||
"20bf17c678ac01685e258192eb4d2d49"
|
||||
"157c3a07a95342d8be8b2f9f121f596b"
|
||||
"8622100d9cfe972bc17003b49ecd5f45"
|
||||
"f3bb28")
|
||||
};
|
||||
|
||||
std::string kProviderSessionTokenStreamingClip3 = wvcdm::a2bs_hex(
|
||||
"4851305A4A4156485A554936444E4931");
|
||||
@@ -1513,6 +1638,22 @@ class WvCdmRequestLicenseTest : public WvCdmTestBase {
|
||||
EXPECT_NE(0u, key_request.url.size());
|
||||
}
|
||||
|
||||
bool KeyRotationRequest(CdmLicenseType license_type,
|
||||
const std::string& init_data) {
|
||||
wvcdm::CdmAppParameterMap app_parameters;
|
||||
CdmKeyRequest key_request;
|
||||
CdmResponseType status =
|
||||
decryptor_.GenerateKeyRequest(
|
||||
session_id_, key_set_id_, "video/mp4", init_data,
|
||||
license_type, app_parameters, NULL, kDefaultCdmIdentifier,
|
||||
&key_request);
|
||||
EXPECT_EQ(wvcdm::KEY_ADDED, status);
|
||||
EXPECT_TRUE(key_request.message.empty());
|
||||
EXPECT_TRUE(key_request.url.empty());
|
||||
return wvcdm::KEY_ADDED == status && key_request.message.empty()
|
||||
&& key_request.url.empty();
|
||||
}
|
||||
|
||||
void GenerateKeyRelease(CdmKeySetId key_set_id) {
|
||||
GenerateKeyRelease(key_set_id, NULL, NULL);
|
||||
}
|
||||
@@ -2739,6 +2880,29 @@ TEST_F(WvCdmRequestLicenseTest, OfflineLicenseRenewalAndRelease) {
|
||||
VerifyKeyRequestResponse(config_.license_server(), client_auth);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, EntitlementWithKeyRotation) {
|
||||
decryptor_.OpenSession(config_.key_system(), NULL, kDefaultCdmIdentifier,
|
||||
NULL, &session_id_);
|
||||
|
||||
// Fetch entitlement license
|
||||
GenerateKeyRequest(kPsshEntitlementWithKeyRotation[0], kLicenseTypeStreaming);
|
||||
VerifyKeyRequestResponse(config_.license_server(), config_.client_auth());
|
||||
|
||||
// Verify that we can decrypt a subsample
|
||||
ASSERT_TRUE(VerifyDecryption(session_id_,
|
||||
entitlement_with_key_rotation_sub_sample[0]));
|
||||
|
||||
// Key rotation
|
||||
ASSERT_TRUE(KeyRotationRequest(kLicenseTypeStreaming,
|
||||
kPsshEntitlementWithKeyRotation[1]));
|
||||
|
||||
// Verify that we can decrypt a subsample
|
||||
ASSERT_TRUE(VerifyDecryption(session_id_,
|
||||
entitlement_with_key_rotation_sub_sample[1]));
|
||||
|
||||
decryptor_.CloseSession(session_id_);
|
||||
}
|
||||
|
||||
TEST_F(WvCdmRequestLicenseTest, RemoveKeys) {
|
||||
ASSERT_EQ(NO_ERROR, decryptor_.OpenSession(config_.key_system(), NULL,
|
||||
kDefaultCdmIdentifier, NULL,
|
||||
|
||||
Reference in New Issue
Block a user