зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1289968 - [Part1] Ensure ClearKey doesn't assume keyIds can only be 16 bytes. r=cpearce
MozReview-Commit-ID: Hf2IQsAHa4r --HG-- extra : transplant_source : %D1%2C%B2j%1C%F5%A7%A9%D8%0B%EEE%92%B1%DC1%A5A%BC%8B
This commit is contained in:
Родитель
108459bd3b
Коммит
ee9ca0dd5e
|
@ -65,14 +65,6 @@ var tests = [
|
|||
sessionType: 'persistent-license',
|
||||
expectPass: false,
|
||||
},
|
||||
{
|
||||
name: "One valid and one invalid kid",
|
||||
initDataType: 'keyids',
|
||||
initData: '{"kids":["LwVHf8JLtPrv2GUXFW2v_A", "invalid"]}',
|
||||
expectedRequest: '{"kids":["LwVHf8JLtPrv2GUXFW2v_A"],"type":"temporary"}',
|
||||
sessionType: 'temporary',
|
||||
expectPass: true,
|
||||
},
|
||||
{
|
||||
name: "Invalid initData",
|
||||
initDataType: 'keyids',
|
||||
|
@ -92,8 +84,9 @@ var tests = [
|
|||
name: "'webm' initDataType with non 16 byte keyid",
|
||||
initDataType: 'webm',
|
||||
initData: 'YAYeAX5Hfod',
|
||||
expectedRequest: '{\"kids\":[\"YAYeAX5Hfoc\"],\"type\":\"temporary\"}',
|
||||
sessionType: 'temporary',
|
||||
expectPass: false,
|
||||
expectPass: true,
|
||||
},
|
||||
];
|
||||
|
||||
|
|
|
@ -59,18 +59,25 @@ Decode6Bit(string& aStr)
|
|||
}
|
||||
|
||||
bool
|
||||
DecodeBase64KeyOrId(const string& aEncoded, vector<uint8_t>& aOutDecoded)
|
||||
DecodeBase64(const string& aEncoded, vector<uint8_t>& aOutDecoded)
|
||||
{
|
||||
if (aEncoded.empty()) {
|
||||
aOutDecoded.clear();
|
||||
return true;
|
||||
}
|
||||
if (aEncoded.size() == 1) {
|
||||
// Invalid Base64 encoding.
|
||||
return false;
|
||||
}
|
||||
string encoded = aEncoded;
|
||||
if (!Decode6Bit(encoded) ||
|
||||
encoded.size() != 22) { // Can't decode to 16 byte CENC key or keyId.
|
||||
if (!Decode6Bit(encoded)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// The number of bytes we haven't yet filled in the current byte, mod 8.
|
||||
int shift = 0;
|
||||
|
||||
aOutDecoded.resize(16);
|
||||
aOutDecoded.resize((encoded.size() * 3) / 4);
|
||||
vector<uint8_t>::iterator out = aOutDecoded.begin();
|
||||
for (size_t i = 0; i < encoded.length(); i++) {
|
||||
if (!shift) {
|
||||
|
|
|
@ -21,11 +21,8 @@
|
|||
#include <string>
|
||||
#include <stdint.h>
|
||||
|
||||
// Decodes a base64 encoded CENC Key or KeyId into it's raw bytes. Note that
|
||||
// CENC Keys or KeyIds are 16 bytes long, so encoded they should be 22 bytes
|
||||
// plus any padding. Fails (returns false) on input that is more than 22 bytes
|
||||
// long after padding is stripped. Returns true on success.
|
||||
// Decodes a base64 encoded string. Returns true on success.
|
||||
bool
|
||||
DecodeBase64KeyOrId(const std::string& aEncoded, std::vector<uint8_t>& aOutDecoded);
|
||||
DecodeBase64(const std::string& aEncoded, std::vector<uint8_t>& aOutDecoded);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -70,7 +70,7 @@ ClearKeySession::Init(uint32_t aCreateSessionToken,
|
|||
mCallback->RejectPromise(aPromiseId, kGMPInvalidAccessError, message, strlen(message));
|
||||
return;
|
||||
}
|
||||
} else if (aInitDataType == "webm" && aInitDataSize == 16) {
|
||||
} else if (aInitDataType == "webm") {
|
||||
// "webm" initData format is simply the raw bytes of the keyId.
|
||||
vector<uint8_t> keyId;
|
||||
keyId.assign(aInitData, aInitData+aInitDataSize);
|
||||
|
|
|
@ -309,15 +309,6 @@ GetNextLabel(ParserContext& aCtx, string& aOutLabel)
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool
|
||||
DecodeKey(string& aEncoded, Key& aOutDecoded)
|
||||
{
|
||||
return
|
||||
DecodeBase64KeyOrId(aEncoded, aOutDecoded) &&
|
||||
// Key should be 128 bits long.
|
||||
aOutDecoded.size() == CLEARKEY_KEY_LEN;
|
||||
}
|
||||
|
||||
static bool
|
||||
ParseKeyObject(ParserContext& aCtx, KeyIdPair& aOutKey)
|
||||
{
|
||||
|
@ -363,8 +354,8 @@ ParseKeyObject(ParserContext& aCtx, KeyIdPair& aOutKey)
|
|||
|
||||
return !key.empty() &&
|
||||
!keyId.empty() &&
|
||||
DecodeBase64KeyOrId(keyId, aOutKey.mKeyId) &&
|
||||
DecodeKey(key, aOutKey.mKey) &&
|
||||
DecodeBase64(keyId, aOutKey.mKeyId) &&
|
||||
DecodeBase64(key, aOutKey.mKey) &&
|
||||
GetNextSymbol(aCtx) == '}';
|
||||
}
|
||||
|
||||
|
@ -451,12 +442,12 @@ ParseKeyIds(ParserContext& aCtx, vector<KeyId>& aOutKeyIds)
|
|||
while (true) {
|
||||
string label;
|
||||
vector<uint8_t> keyId;
|
||||
if (!GetNextLabel(aCtx, label) ||
|
||||
!DecodeBase64KeyOrId(label, keyId)) {
|
||||
if (!GetNextLabel(aCtx, label) || !DecodeBase64(label, keyId)) {
|
||||
return false;
|
||||
}
|
||||
assert(!keyId.empty());
|
||||
aOutKeyIds.push_back(keyId);
|
||||
if (!keyId.empty()) {
|
||||
aOutKeyIds.push_back(keyId);
|
||||
}
|
||||
|
||||
uint8_t sym = PeekSymbol(aCtx);
|
||||
if (!sym || sym == ']') {
|
||||
|
@ -493,7 +484,10 @@ ClearKeyUtils::ParseKeyIdsInitData(const uint8_t* aInitData,
|
|||
|
||||
if (label == "kids") {
|
||||
// Parse "kids" array.
|
||||
if (!ParseKeyIds(ctx, aOutKeyIds)) return false;
|
||||
if (!ParseKeyIds(ctx, aOutKeyIds) ||
|
||||
aOutKeyIds.empty()) {
|
||||
return false;
|
||||
}
|
||||
} else if (label == "type") {
|
||||
// Consume type string.
|
||||
if (!GetNextLabel(ctx, aOutSessionType)) return false;
|
||||
|
|
|
@ -13,16 +13,15 @@
|
|||
#include "../ClearKeyCencParser.cpp"
|
||||
#include "../ArrayUtils.h"
|
||||
|
||||
|
||||
using namespace std;
|
||||
|
||||
struct B64Test {
|
||||
const char* b64;
|
||||
uint8_t raw[16];
|
||||
string b64;
|
||||
vector<uint8_t> raw;
|
||||
bool shouldPass;
|
||||
};
|
||||
|
||||
B64Test tests[] = {
|
||||
const B64Test tests[] = {
|
||||
{
|
||||
"AAAAADk4AU4AAAAAAAAAAA",
|
||||
{ 0x0, 0x0, 0x0, 0x0, 0x39, 0x38, 0x1, 0x4e, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 },
|
||||
|
@ -41,7 +40,7 @@ B64Test tests[] = {
|
|||
{
|
||||
"flczM35XMzN-VzMzflczMw",
|
||||
{ 0x7e, 0x57, 0x33, 0x33, 0x7e, 0x57, 0x33, 0x33, 0x7e, 0x57, 0x33, 0x33, 0x7e, 0x57, 0x33, 0x33 },
|
||||
true
|
||||
true,
|
||||
},
|
||||
{
|
||||
"flcdBH5XHQR-Vx0EflcdBA",
|
||||
|
@ -53,23 +52,43 @@ B64Test tests[] = {
|
|||
{ 0x7e, 0x57, 0x44, 0x44, 0x7e, 0x57, 0x44, 0x44, 0x7e, 0x57, 0x44, 0x44, 0x7e, 0x57, 0x44, 0x44 },
|
||||
true
|
||||
},
|
||||
// Failure tests
|
||||
{ "", { 0 }, false }, // empty
|
||||
{ "fuzzbiz", { 0 }, false }, // Too short
|
||||
{ "fuzzbizfuzzbizfuzzbizfuzzbizfuzzbizfuzzbizfuzzbizfuzzbiz", { 0 }, false }, // too long
|
||||
{
|
||||
"fuzzbiz=",
|
||||
{ 0x7e, 0xec, 0xf3, 0x6e, 0x2c },
|
||||
true
|
||||
},
|
||||
{
|
||||
"fuzzbizfuzzbizfuzzbizfuzzbizfuzzbizfuzzbizfuzzbizfuzzbiz",
|
||||
{
|
||||
0x7e, 0xec, 0xf3, 0x6e, 0x2c, 0xdf, 0xbb, 0x3c, 0xdb, 0x8b,
|
||||
0x37, 0xee, 0xcf, 0x36, 0xe2, 0xcd, 0xfb, 0xb3, 0xcd, 0xb8,
|
||||
0xb3, 0x7e, 0xec, 0xf3, 0x6e, 0x2c, 0xdf, 0xbb, 0x3c, 0xdb,
|
||||
0x8b, 0x37, 0xee, 0xcf, 0x36, 0xe2, 0xcd, 0xfb, 0xb3, 0xcd,
|
||||
0xb8, 0xb3
|
||||
},
|
||||
true
|
||||
},
|
||||
{ "", { }, true },
|
||||
{ "00", { 0xd3 }, true },
|
||||
{ "000", { 0xd3, 0x4d }, true },
|
||||
|
||||
{ "invalid", { 0x8a, 0x7b, 0xda, 0x96, 0x27 }, true },
|
||||
{ "invalic", { 0x8a, 0x7b, 0xda, 0x96, 0x27 }, true },
|
||||
|
||||
// Failure tests
|
||||
{ "A", { }, false }, // 1 character is too few.
|
||||
{ "_", { }, false }, // 1 character is too few.
|
||||
};
|
||||
|
||||
TEST(ClearKey, DecodeBase64KeyOrId) {
|
||||
for (size_t i = 0; i < MOZ_ARRAY_LENGTH(tests); i++) {
|
||||
TEST(ClearKey, DecodeBase64) {
|
||||
for (const B64Test& test : tests) {
|
||||
vector<uint8_t> v;
|
||||
const B64Test& test = tests[i];
|
||||
bool rv = DecodeBase64KeyOrId(string(test.b64), v);
|
||||
EXPECT_EQ(rv, test.shouldPass);
|
||||
bool rv = DecodeBase64(string(test.b64), v);
|
||||
EXPECT_EQ(test.shouldPass, rv);
|
||||
if (test.shouldPass) {
|
||||
EXPECT_EQ(v.size(), 16u);
|
||||
for (size_t k = 0; k < 16; k++) {
|
||||
EXPECT_EQ(v[k], test.raw[k]);
|
||||
EXPECT_EQ(test.raw.size(), v.size());
|
||||
for (size_t k = 0; k < test.raw.size(); k++) {
|
||||
EXPECT_EQ(test.raw[k], v[k]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -186,7 +205,7 @@ const uint8_t g2xGoogleWPTCencInitData[] = {
|
|||
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
|
||||
0x00, 0x00, 0x00, 0x00 // datasize
|
||||
};
|
||||
|
||||
TEST(ClearKey, ParseCencInitData) {
|
||||
|
|
Загрузка…
Ссылка в новой задаче