Bug 1308076 - Ensure Primetime PSSH boxes pass the PSSH validator. r=jwwang
Primetime PSSH boxes don't use the common encryption system ID.
So to ensure we don't break any existing Primetime players, we
must allow PSSH boxes with the Primetime system ID to pass the
PSSH validator.
MozReview-Commit-ID: 3q58FKLQXgV
--- a/media/psshparser/PsshParser.cpp
+++ b/media/psshparser/PsshParser.cpp
@@ -102,16 +102,21 @@ private:
// System ID identifying the cenc v2 pssh box format; specified at:
// https://dvcs.w3.org/hg/html-media/raw-file/tip/encrypted-media/cenc-format.html
const uint8_t kSystemID[] = {
0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2, 0x4d, 0x02,
0xac, 0xe3, 0x3c, 0x1e, 0x52, 0xe2, 0xfb, 0x4b
};
+const uint8_t kPrimetimeID[] = {
+ 0xf2, 0x39, 0xe7, 0x69, 0xef, 0xa3, 0x48, 0x50,
+ 0x9c, 0x16, 0xa9, 0x03, 0xc6, 0x93, 0x2e, 0xfb
+};
+
bool
ParseCENCInitData(const uint8_t* aInitData,
uint32_t aInitDataSize,
std::vector<std::vector<uint8_t>>& aOutKeyIds)
{
aOutKeyIds.clear();
std::vector<std::vector<uint8_t>> keyIds;
ByteReader reader(aInitData, aInitDataSize);
@@ -152,16 +157,22 @@ ParseCENCInitData(const uint8_t* aInitDa
reader.Read(3); // skip flags.
// SystemID
const uint8_t* sid = reader.Read(sizeof(kSystemID));
if (!sid) {
// Insufficient bytes to read SystemID.
return false;
}
+ if (!memcmp(kPrimetimeID, sid, sizeof(kSystemID))) {
+ // Allow legacy Primetime key system PSSH boxes, which
+ // don't conform to common encryption format.
+ return true;
+ }
+
if (memcmp(kSystemID, sid, sizeof(kSystemID))) {
// Ignore pssh boxes with wrong system ID.
reader.Seek(std::max<size_t>(reader.Offset(), end));
continue;
}
if (!reader.CanRead32()) {
return false;
--- a/media/psshparser/gtest/TestPsshParser.cpp
+++ b/media/psshparser/gtest/TestPsshParser.cpp
@@ -108,16 +108,25 @@ const uint8_t g2xGoogleWPTCencInitData[]
0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, // Common SystemID
0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B,
0x00, 0x00, 0x00, 0x01, // key count
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, // key
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x00, 0x00, 0x00, 0x00 // datasize
};
+const uint8_t gPrimetimePSSH[] = {
+ 0x00, 0x00, 0x00, 0x00, // size = 0
+ 0x70, 0x73, 0x73, 0x68, // 'pssh'
+ 0x01, // version = 1
+ 0x00, 0x00, 0x00, // flags
+ 0xf2, 0x39, 0xe7, 0x69, 0xef, 0xa3, 0x48, 0x50, // Primetime system Id
+ 0x9c, 0x16, 0xa9, 0x03, 0xc6, 0x93, 0x2e, 0xfb
+};
+
TEST(PsshParser, ParseCencInitData) {
std::vector<std::vector<uint8_t>> keyIds;
bool rv;
rv = ParseCENCInitData(gGoogleWPTCencInitData, MOZ_ARRAY_LENGTH(gGoogleWPTCencInitData), keyIds);
EXPECT_TRUE(rv);
EXPECT_EQ(1u, keyIds.size());
EXPECT_EQ(16u, keyIds[0].size());
@@ -148,9 +157,13 @@ TEST(PsshParser, ParseCencInitData) {
rv = ParseCENCInitData(g2xGoogleWPTCencInitData, MOZ_ARRAY_LENGTH(g2xGoogleWPTCencInitData), keyIds);
EXPECT_TRUE(rv);
EXPECT_EQ(2u, keyIds.size());
EXPECT_EQ(16u, keyIds[0].size());
EXPECT_EQ(16u, keyIds[1].size());
EXPECT_EQ(0, memcmp(&keyIds[0].front(), &g2xGoogleWPTCencInitData[32], 16));
EXPECT_EQ(0, memcmp(&keyIds[1].front(), &g2xGoogleWPTCencInitData[84], 16));
+
+ rv = ParseCENCInitData(gPrimetimePSSH, MOZ_ARRAY_LENGTH(gPrimetimePSSH), keyIds);
+ EXPECT_TRUE(rv);
+ EXPECT_EQ(0u, keyIds.size());
}