Included changes: - 676ac7be8548d80c420591fc0b4fb9a11723ef34 Backwards compatibility script for CDM v18 and OPK v19 by Vicky Min <vickymin@google.com> - 3cd4f71fda91245ac0b61c4c847950952f3021c0 Change BuildInformation ree fields to optional by Matt Feddersen <mattfedd@google.com> - a2259e95dea40c27a4be02ad479aec8f1fc84737 Created a DICE CBOR Cert parser/serializer. by Alex Dale <sigquit@google.com> - b8f2c364afeb6279e5aee6488d4527e189ac42ff Don't create invalid enum value by John "Juce" Bruce <juce@google.com> - b0aed212a3b2dd8f752d8fc43982848c1aa6c152 Created an HLS Key type. by Alex Dale <sigquit@google.com> - f8cfc54b41f124ba849596dbe6438b7f271a72b7 Specify C/C++ standard when running clang-tidy on OPK by John "Juce" Bruce <juce@google.com> GitOrigin-RevId: 676ac7be8548d80c420591fc0b4fb9a11723ef34
867 lines
28 KiB
C++
867 lines
28 KiB
C++
// Copyright 2025 Google LLC. All Rights Reserved. This file and proprietary
|
|
// source code may only be used and distributed under the Widevine License
|
|
// Agreement.
|
|
#include "hls_key.h"
|
|
|
|
#include <inttypes.h>
|
|
|
|
#include <set>
|
|
#include <sstream>
|
|
#include <string>
|
|
#include <vector>
|
|
|
|
#include <gtest/gtest.h>
|
|
|
|
#include "hls_attribute_list.h"
|
|
#include "string_conversions.h"
|
|
|
|
namespace wvutil {
|
|
namespace test {
|
|
TEST(HlsKeyTest, ClassConstants) {
|
|
// Validity checks on the class constants.
|
|
// Verify names.
|
|
EXPECT_TRUE(HlsAttributeList::IsValidName(HlsKey::kMethodName))
|
|
<< "METHOD key invalid: " << HlsKey::kMethodName;
|
|
EXPECT_TRUE(HlsAttributeList::IsValidName(HlsKey::kUriName))
|
|
<< "URI key invalid: " << HlsKey::kUriName;
|
|
EXPECT_TRUE(HlsAttributeList::IsValidName(HlsKey::kIvName))
|
|
<< "IV key invalid: " << HlsKey::kIvName;
|
|
EXPECT_TRUE(HlsAttributeList::IsValidName(HlsKey::kKeyFormatName))
|
|
<< "KEYFORMAT key invalid: " << HlsKey::kKeyFormatName;
|
|
EXPECT_TRUE(HlsAttributeList::IsValidName(HlsKey::kKeyFormatVersionsName))
|
|
<< "KEYFORMATVERSIONS key invalid: " << HlsKey::kKeyFormatVersionsName;
|
|
|
|
// Well-known methods.
|
|
EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue(HlsKey::kMethodNone))
|
|
<< "METHOD=NONE value invalid: " << HlsKey::kMethodNone;
|
|
EXPECT_TRUE(HlsAttributeList::IsValidEnumStringValue(HlsKey::kMethodAes128))
|
|
<< "METHOD=AES-128 value invalid: " << HlsKey::kMethodAes128;
|
|
EXPECT_TRUE(
|
|
HlsAttributeList::IsValidEnumStringValue(HlsKey::kMethodSampleAes))
|
|
<< "METHOD=SAMPLE-AES value invalid: " << HlsKey::kMethodSampleAes;
|
|
}
|
|
|
|
TEST(HlsKeyTest, IsValidKeyFormatVersion) {
|
|
EXPECT_TRUE(HlsKey::IsValidKeyFormatVersion(1));
|
|
EXPECT_TRUE(HlsKey::IsValidKeyFormatVersion(2));
|
|
EXPECT_TRUE(HlsKey::IsValidKeyFormatVersion(1337));
|
|
EXPECT_TRUE(
|
|
HlsKey::IsValidKeyFormatVersion(std::numeric_limits<uint64_t>::max()));
|
|
}
|
|
|
|
TEST(HlsKeyTest, IsValidKeyFormatVersion_Invalid) {
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersion(0));
|
|
}
|
|
|
|
TEST(HlsKeyTest, IsValidKeyFormatVersions) {
|
|
const std::set<uint64_t> kSingleVersion = {2};
|
|
EXPECT_TRUE(HlsKey::IsValidKeyFormatVersions(kSingleVersion));
|
|
|
|
const std::set<uint64_t> kFewVersions = {1, 2, 5};
|
|
EXPECT_TRUE(HlsKey::IsValidKeyFormatVersions(kFewVersions));
|
|
|
|
const std::set<uint64_t> kLargeVersion = {
|
|
1, 2, std::numeric_limits<uint64_t>::max()};
|
|
EXPECT_TRUE(HlsKey::IsValidKeyFormatVersions(kLargeVersion));
|
|
}
|
|
|
|
TEST(HlsKeyTest, IsValidKeyFormatVersions_Invalid) {
|
|
const std::set<uint64_t> kEmptySet;
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersions(kEmptySet));
|
|
|
|
const std::set<uint64_t> kZeroOnly = {0};
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersions(kZeroOnly));
|
|
|
|
const std::set<uint64_t> kWithZero = {0, 1, 2, 5};
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersions(kWithZero));
|
|
}
|
|
|
|
TEST(HlsKeyTest, IsValidKeyFormatVersionListRep) {
|
|
EXPECT_TRUE(HlsKey::IsValidKeyFormatVersionListRep("1"));
|
|
EXPECT_TRUE(HlsKey::IsValidKeyFormatVersionListRep("1/2"));
|
|
EXPECT_TRUE(HlsKey::IsValidKeyFormatVersionListRep("1/2/5"));
|
|
EXPECT_TRUE(HlsKey::IsValidKeyFormatVersionListRep("1337"));
|
|
}
|
|
|
|
TEST(HlsKeyTest, IsValidKeyFormatVersionListRep_Invalid) {
|
|
// Empty not allowed.
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep(""));
|
|
// Zero is not allowed.
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("0"));
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("0/2/5"));
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/0/5"));
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/2/0"));
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/2/000000"));
|
|
|
|
// All must integers.
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("NONE"));
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/NONE/4"));
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/1.2/2"));
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/0xDEADBEAF"));
|
|
|
|
// Cannot have empty values.
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("/2/5"));
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1//5"));
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/2/"));
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("/"));
|
|
|
|
// Must be a slash separated list.
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1,0,5"));
|
|
|
|
// Cannot have spaces.
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep(" 1/2/5"));
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1 /2/5"));
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/ 2/5"));
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/2 /5"));
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/2/ 5"));
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("1/2/5 "));
|
|
|
|
// Must fit in the 64-bit integer range.
|
|
EXPECT_FALSE(HlsKey::IsValidKeyFormatVersionListRep("100000000000000000000"));
|
|
}
|
|
|
|
TEST(HlsKeyTest, Empty) {
|
|
const HlsKey key;
|
|
|
|
EXPECT_FALSE(key.HasMethod());
|
|
EXPECT_FALSE(key.HasUri());
|
|
EXPECT_FALSE(key.HasIv());
|
|
EXPECT_FALSE(key.HasKeyFormat());
|
|
EXPECT_FALSE(key.HasKeyFormatVersions());
|
|
EXPECT_FALSE(key.HasKeyFormatVersion(1));
|
|
}
|
|
|
|
TEST(HlsKeyTest, SetMethod) {
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.SetMethod("NONE"));
|
|
EXPECT_TRUE(key.HasMethod());
|
|
EXPECT_EQ(key.method(), "NONE");
|
|
key.ClearMethod();
|
|
EXPECT_FALSE(key.HasMethod());
|
|
}
|
|
|
|
TEST(HlsKeyTest, SetMethod_Invalid) {
|
|
HlsKey key;
|
|
// Check that an invalid cannot be set.
|
|
EXPECT_FALSE(key.SetMethod("NOT VALID"));
|
|
EXPECT_FALSE(key.HasMethod());
|
|
|
|
EXPECT_TRUE(key.SetMethod("SAMPLE-AES"));
|
|
|
|
// Check that setting an invalid method does not
|
|
// overwrite the existing method.
|
|
EXPECT_FALSE(key.SetMethod("NOT VALID"));
|
|
EXPECT_EQ(key.method(), "SAMPLE-AES");
|
|
}
|
|
|
|
TEST(HlsKeyTest, SetUri) {
|
|
const std::string kSampleUri = "http://media.src/some-key";
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.SetUri(kSampleUri));
|
|
EXPECT_TRUE(key.HasUri());
|
|
EXPECT_EQ(key.uri(), kSampleUri);
|
|
key.ClearUri();
|
|
EXPECT_FALSE(key.HasUri());
|
|
}
|
|
|
|
TEST(HlsKeyTest, SetUri_Invalid) {
|
|
const std::string kBadUri = "No\"quotes";
|
|
const std::string kGoodUri = "http://media.src/some-key";
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.SetUri(kBadUri));
|
|
EXPECT_FALSE(key.HasUri());
|
|
EXPECT_FALSE(key.SetUri(""));
|
|
EXPECT_FALSE(key.HasUri());
|
|
|
|
EXPECT_TRUE(key.SetUri(kGoodUri));
|
|
|
|
EXPECT_FALSE(key.SetUri(kBadUri));
|
|
EXPECT_EQ(key.uri(), kGoodUri);
|
|
}
|
|
|
|
TEST(HlsKeyTest, SetIv_Vec) {
|
|
const std::vector<uint8_t> kGoodIv(HlsKey::kIvLength, 42);
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.SetIv(kGoodIv));
|
|
EXPECT_TRUE(key.HasIv());
|
|
EXPECT_EQ(key.iv(), kGoodIv);
|
|
key.ClearIv();
|
|
EXPECT_FALSE(key.HasIv());
|
|
}
|
|
|
|
TEST(HlsKeyTest, SetIv_Vec_Invalid) {
|
|
const std::vector<uint8_t> kGoodIv(HlsKey::kIvLength, 42);
|
|
const std::vector<uint8_t> kEmptyIv;
|
|
const std::vector<uint8_t> kShortIv(HlsKey::kIvLength / 2, 22);
|
|
const std::vector<uint8_t> kLargeIv(HlsKey::kIvLength * 2, 22);
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.SetIv(kEmptyIv));
|
|
EXPECT_FALSE(key.SetIv(kShortIv));
|
|
EXPECT_FALSE(key.SetIv(kLargeIv));
|
|
EXPECT_FALSE(key.HasIv());
|
|
|
|
EXPECT_TRUE(key.SetIv(kGoodIv));
|
|
|
|
EXPECT_FALSE(key.SetIv(kShortIv));
|
|
EXPECT_EQ(key.iv(), kGoodIv);
|
|
}
|
|
|
|
TEST(HlsKeyTest, SetIv_String) {
|
|
const std::string kGoodIv(HlsKey::kIvLength, 'x');
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.SetIv(kGoodIv));
|
|
EXPECT_TRUE(key.HasIv());
|
|
const std::vector<uint8_t> kGoodIvVec(kGoodIv.begin(), kGoodIv.end());
|
|
EXPECT_EQ(key.iv(), kGoodIvVec);
|
|
key.ClearIv();
|
|
EXPECT_FALSE(key.HasIv());
|
|
}
|
|
|
|
TEST(HlsKeyTest, SetIv_String_Invalid) {
|
|
const std::vector<uint8_t> kGoodIv(HlsKey::kIvLength, 42);
|
|
const std::string kEmptyIv;
|
|
const std::string kShortIv(HlsKey::kIvLength / 2, 'y');
|
|
const std::string kLargeIv(HlsKey::kIvLength * 2, 'z');
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.SetIv(kEmptyIv));
|
|
EXPECT_FALSE(key.SetIv(kShortIv));
|
|
EXPECT_FALSE(key.SetIv(kLargeIv));
|
|
EXPECT_FALSE(key.HasIv());
|
|
|
|
EXPECT_TRUE(key.SetIv(kGoodIv));
|
|
|
|
EXPECT_FALSE(key.SetIv(kShortIv));
|
|
EXPECT_EQ(key.iv(), kGoodIv);
|
|
}
|
|
|
|
TEST(HlsKeyTest, SetIvHex) {
|
|
const std::vector<uint8_t> kGoodIv(HlsKey::kIvLength, 42);
|
|
const std::string kGoodIvHex = b2a_hex(kGoodIv);
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.SetIvHex(kGoodIvHex));
|
|
EXPECT_TRUE(key.HasIv());
|
|
EXPECT_EQ(key.iv(), kGoodIv);
|
|
key.ClearIv();
|
|
EXPECT_FALSE(key.HasIv());
|
|
}
|
|
|
|
TEST(HlsKeyTest, SetIvHex_Invalid) {
|
|
const std::vector<uint8_t> kGoodIv(HlsKey::kIvLength, 42);
|
|
const std::string kEmptyIvHex;
|
|
const std::string kShortIvHex(HlsKey::kIvLength, 'e');
|
|
const std::string kLargeIvHex(HlsKey::kIvLength * 4, 'e');
|
|
const std::string kNonHexIv(HlsKey::kIvLength * 2, 'x');
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.SetIvHex(kEmptyIvHex));
|
|
EXPECT_FALSE(key.SetIvHex(kShortIvHex));
|
|
EXPECT_FALSE(key.SetIvHex(kLargeIvHex));
|
|
EXPECT_FALSE(key.SetIvHex(kNonHexIv));
|
|
|
|
EXPECT_TRUE(key.SetIv(kGoodIv));
|
|
|
|
EXPECT_FALSE(key.SetIvHex(kShortIvHex));
|
|
EXPECT_EQ(key.iv(), kGoodIv);
|
|
}
|
|
|
|
TEST(HlsKeyTest, SetKeyFormat) {
|
|
const std::string kGoodKeyFormat = "com.widevine";
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.SetKeyFormat(kGoodKeyFormat));
|
|
EXPECT_TRUE(key.HasKeyFormat());
|
|
EXPECT_EQ(key.key_format(), kGoodKeyFormat);
|
|
key.ClearKeyFormat();
|
|
EXPECT_FALSE(key.HasKeyFormat());
|
|
}
|
|
|
|
TEST(HlsKeyTest, SetKeyFormat_Invalid) {
|
|
const std::string kGoodKeyFormat = "com.widevine";
|
|
const std::string kEmptyKeyFormat;
|
|
const std::string kInvalidKeyFormat = "com\"widevine";
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.SetKeyFormat(kEmptyKeyFormat));
|
|
EXPECT_FALSE(key.SetKeyFormat(kInvalidKeyFormat));
|
|
|
|
EXPECT_TRUE(key.SetKeyFormat(kGoodKeyFormat));
|
|
|
|
EXPECT_FALSE(key.SetKeyFormat(kInvalidKeyFormat));
|
|
EXPECT_EQ(key.key_format(), kGoodKeyFormat);
|
|
}
|
|
|
|
TEST(HlsKeyTest, SetKeyFormatVersions_Set) {
|
|
const std::set<uint64_t> kSingleVersion = {3};
|
|
const std::set<uint64_t> kFewVersions = {1, 2, 5};
|
|
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.SetKeyFormatVersions(kSingleVersion));
|
|
EXPECT_TRUE(key.HasKeyFormatVersions());
|
|
EXPECT_EQ(key.key_format_versions(), kSingleVersion);
|
|
|
|
key.ClearKeyFormatVersions();
|
|
EXPECT_FALSE(key.HasKeyFormatVersions());
|
|
|
|
EXPECT_TRUE(key.SetKeyFormatVersions(kFewVersions));
|
|
EXPECT_TRUE(key.HasKeyFormatVersions());
|
|
EXPECT_EQ(key.key_format_versions(), kFewVersions);
|
|
|
|
// Ensure that set is not merging.
|
|
EXPECT_TRUE(key.SetKeyFormatVersions(kSingleVersion));
|
|
EXPECT_EQ(key.key_format_versions(), kSingleVersion);
|
|
}
|
|
|
|
TEST(HlsKeyTest, SetKeyFormatVersions_Set_Invalid) {
|
|
const std::set<uint64_t> kSingleVersion = {3};
|
|
const std::set<uint64_t> kBadVersions = {0, 2, 5};
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.SetKeyFormatVersions(kBadVersions));
|
|
EXPECT_FALSE(key.HasKeyFormatVersions());
|
|
|
|
EXPECT_TRUE(key.SetKeyFormatVersions(kSingleVersion));
|
|
|
|
EXPECT_FALSE(key.SetKeyFormatVersions(kBadVersions));
|
|
EXPECT_EQ(key.key_format_versions(), kSingleVersion);
|
|
}
|
|
|
|
TEST(HlsKeyTest, SetKeyFormatVersions_Vec) {
|
|
const std::vector<uint64_t> kSingleVersionVec = {3};
|
|
const std::vector<uint64_t> kFewVersionsVec = {1, 2, 5};
|
|
const std::vector<uint64_t> kRepeatedVersionsVec = {1, 1, 2, 5, 5, 5, 5, 5};
|
|
|
|
const std::set<uint64_t> kSingleVersion = {3};
|
|
const std::set<uint64_t> kFewVersions = {1, 2, 5};
|
|
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.SetKeyFormatVersions(kSingleVersionVec));
|
|
EXPECT_TRUE(key.HasKeyFormatVersions());
|
|
EXPECT_EQ(key.key_format_versions(), kSingleVersion);
|
|
|
|
key.ClearKeyFormatVersions();
|
|
EXPECT_FALSE(key.HasKeyFormatVersions());
|
|
|
|
EXPECT_TRUE(key.SetKeyFormatVersions(kFewVersionsVec));
|
|
EXPECT_TRUE(key.HasKeyFormatVersions());
|
|
EXPECT_EQ(key.key_format_versions(), kFewVersions);
|
|
|
|
// Ensure that set is not merging.
|
|
EXPECT_TRUE(key.SetKeyFormatVersions(kSingleVersionVec));
|
|
EXPECT_EQ(key.key_format_versions(), kSingleVersion);
|
|
|
|
// Ensure that repeated values are not stored.
|
|
EXPECT_TRUE(key.SetKeyFormatVersions(kRepeatedVersionsVec));
|
|
EXPECT_EQ(key.key_format_versions(), kFewVersions);
|
|
}
|
|
|
|
TEST(HlsKeyTest, SetKeyFormatVersions_Vec_Invalid) {
|
|
const std::set<uint64_t> kSingleVersion = {3};
|
|
const std::vector<uint64_t> kBadVersionsVec = {1, 2, 0, 5};
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.SetKeyFormatVersions(kBadVersionsVec));
|
|
EXPECT_FALSE(key.HasKeyFormatVersions());
|
|
|
|
EXPECT_TRUE(key.SetKeyFormatVersions(kSingleVersion));
|
|
|
|
EXPECT_FALSE(key.SetKeyFormatVersions(kBadVersionsVec));
|
|
EXPECT_EQ(key.key_format_versions(), kSingleVersion);
|
|
}
|
|
|
|
TEST(HlsKeyTest, HasKeyFormatVersion) {
|
|
const std::set<uint64_t> kFewVersions = {1, 2, 5};
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.HasKeyFormatVersion(1));
|
|
EXPECT_FALSE(key.HasKeyFormatVersion(std::numeric_limits<uint64_t>::max()));
|
|
|
|
EXPECT_TRUE(key.SetKeyFormatVersions(kFewVersions));
|
|
|
|
EXPECT_FALSE(key.HasKeyFormatVersion(0));
|
|
EXPECT_TRUE(key.HasKeyFormatVersion(1));
|
|
EXPECT_TRUE(key.HasKeyFormatVersion(2));
|
|
EXPECT_FALSE(key.HasKeyFormatVersion(3));
|
|
EXPECT_FALSE(key.HasKeyFormatVersion(4));
|
|
EXPECT_TRUE(key.HasKeyFormatVersion(5));
|
|
EXPECT_FALSE(key.HasKeyFormatVersion(std::numeric_limits<uint64_t>::max()));
|
|
}
|
|
|
|
TEST(HlsKeyTest, AddKeyFormatVersion) {
|
|
const std::set<uint64_t> kFewVersions = {1, 2, 5};
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.AddKeyFormatVersion(1));
|
|
EXPECT_TRUE(key.AddKeyFormatVersion(2));
|
|
EXPECT_TRUE(key.AddKeyFormatVersion(5));
|
|
|
|
EXPECT_EQ(key.key_format_versions(), kFewVersions);
|
|
|
|
// Repeated adds doesn't count as error.
|
|
EXPECT_TRUE(key.AddKeyFormatVersion(5));
|
|
// Cannot add invalid.
|
|
EXPECT_FALSE(key.AddKeyFormatVersion(0));
|
|
|
|
EXPECT_EQ(key.key_format_versions(), kFewVersions);
|
|
}
|
|
|
|
TEST(HlsKeyTest, IsWellFormed_Empty) {
|
|
const HlsKey key;
|
|
EXPECT_FALSE(key.IsWellFormed());
|
|
}
|
|
|
|
TEST(HlsKeyTest, IsWellFormed_MethodNone) {
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.SetMethod("NONE"));
|
|
EXPECT_TRUE(key.IsWellFormed());
|
|
}
|
|
|
|
// When method is none, all other fields must be empty.
|
|
TEST(HlsKeyTest, IsWellFormed_MethodNone_Invalid) {
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.SetMethod("NONE"));
|
|
|
|
// With URI.
|
|
EXPECT_TRUE(key.SetUri("http://domain.tld/key"));
|
|
EXPECT_FALSE(key.IsWellFormed());
|
|
key.ClearUri();
|
|
|
|
// With IV.
|
|
EXPECT_TRUE(key.SetIv(std::vector<uint8_t>(HlsKey::kIvLength, 42)));
|
|
EXPECT_FALSE(key.IsWellFormed());
|
|
key.ClearIv();
|
|
|
|
// With key format.
|
|
EXPECT_TRUE(key.SetKeyFormat("com.widevine"));
|
|
EXPECT_FALSE(key.IsWellFormed());
|
|
key.ClearKeyFormat();
|
|
|
|
// With key format versions.
|
|
EXPECT_TRUE(key.AddKeyFormatVersion(1));
|
|
EXPECT_FALSE(key.IsWellFormed());
|
|
key.ClearKeyFormatVersions();
|
|
|
|
// Should be well-formed again.
|
|
EXPECT_TRUE(key.IsWellFormed());
|
|
}
|
|
|
|
TEST(HlsKeyTest, IsWellFormed_MethodNonNone) {
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.SetMethod("AES-128"));
|
|
// Required fields.
|
|
EXPECT_TRUE(key.SetUri("http://domain.tld/key"));
|
|
EXPECT_TRUE(key.SetIv(std::vector<uint8_t>(HlsKey::kIvLength, 42)));
|
|
EXPECT_TRUE(key.IsWellFormed());
|
|
|
|
// Optional fields.
|
|
EXPECT_TRUE(key.SetKeyFormat("com.widevine"));
|
|
EXPECT_TRUE(key.IsWellFormed());
|
|
|
|
EXPECT_TRUE(key.AddKeyFormatVersion(1));
|
|
EXPECT_TRUE(key.IsWellFormed());
|
|
}
|
|
|
|
TEST(HlsKeyTest, IsWellFormed_MethodNonNone_Invalid) {
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.SetMethod("AES-128"));
|
|
// Missing required all fields.
|
|
EXPECT_FALSE(key.IsWellFormed());
|
|
|
|
// URI is the only required field.
|
|
EXPECT_TRUE(key.SetUri("http://domain.tld/key"));
|
|
EXPECT_TRUE(key.IsWellFormed());
|
|
|
|
// Missing URI.
|
|
key.ClearUri();
|
|
EXPECT_FALSE(key.IsWellFormed());
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_MethodNone) {
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetEnumString("METHOD", "NONE"));
|
|
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.FromAttributeList(list));
|
|
|
|
EXPECT_TRUE(key.IsWellFormed());
|
|
EXPECT_EQ(key.method(), "NONE");
|
|
EXPECT_FALSE(key.HasUri());
|
|
EXPECT_FALSE(key.HasIv());
|
|
EXPECT_FALSE(key.HasKeyFormat());
|
|
EXPECT_FALSE(key.HasKeyFormatVersions());
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_MethodNone_IgnoreOtherFields) {
|
|
// The HLS specification states that if METHOD is NONE, then
|
|
// there should not be any other fields. However, this parser
|
|
// is less strict, and will simply ignore the other fields
|
|
// when reading from an attribute list.
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetEnumString("METHOD", "NONE"));
|
|
EXPECT_TRUE(
|
|
list.SetHexSequence("IV", std::vector<uint8_t>(HlsKey::kIvLength, 42)));
|
|
EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data"));
|
|
EXPECT_TRUE(list.SetQuotedString("KEYFORMAT", "com.example"));
|
|
EXPECT_TRUE(list.SetQuotedString("KEYFORMATVERSIONS", "1337"));
|
|
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.FromAttributeList(list));
|
|
|
|
EXPECT_TRUE(key.IsWellFormed());
|
|
EXPECT_EQ(key.method(), "NONE");
|
|
EXPECT_FALSE(key.HasUri());
|
|
EXPECT_FALSE(key.HasIv());
|
|
EXPECT_FALSE(key.HasKeyFormat());
|
|
EXPECT_FALSE(key.HasKeyFormatVersions());
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_MethodNonNone_OnlyRequiredFields) {
|
|
const std::vector<uint8_t> kIv(HlsKey::kIvLength, 42);
|
|
const std::string kUri = "http://domain.tld/key";
|
|
// HLS standard says to use the following defaults if not
|
|
// present in the HLS list.
|
|
const std::string kDefaultKeyFormat = "identity";
|
|
const std::set<uint64_t> kDefaultKeyFormatVersions = {1};
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128"));
|
|
EXPECT_TRUE(list.SetHexSequence("IV", kIv));
|
|
EXPECT_TRUE(list.SetQuotedString("URI", kUri));
|
|
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.FromAttributeList(list));
|
|
|
|
EXPECT_TRUE(key.IsWellFormed());
|
|
EXPECT_EQ(key.method(), "AES-128");
|
|
EXPECT_EQ(key.uri(), kUri);
|
|
EXPECT_EQ(key.iv(), kIv);
|
|
EXPECT_EQ(key.key_format(), kDefaultKeyFormat);
|
|
EXPECT_EQ(key.key_format_versions(), kDefaultKeyFormatVersions);
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_MethodNonNone_AllFields) {
|
|
const std::vector<uint8_t> kIv(HlsKey::kIvLength, 42);
|
|
const std::string kUri = "http://domain.tld/key";
|
|
const std::string kKeyFormat = "com.widevine";
|
|
const std::set<uint64_t> kKeyFormatVersion = {1, 2, 5};
|
|
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetEnumString("METHOD", "SAMPLE-AES"));
|
|
EXPECT_TRUE(list.SetHexSequence("IV", kIv));
|
|
EXPECT_TRUE(list.SetQuotedString("URI", kUri));
|
|
EXPECT_TRUE(list.SetQuotedString("KEYFORMAT", kKeyFormat));
|
|
EXPECT_TRUE(list.SetQuotedString("KEYFORMATVERSIONS", "1/2/5"));
|
|
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.FromAttributeList(list));
|
|
|
|
EXPECT_TRUE(key.IsWellFormed());
|
|
EXPECT_EQ(key.method(), "SAMPLE-AES");
|
|
EXPECT_EQ(key.uri(), kUri);
|
|
EXPECT_EQ(key.iv(), kIv);
|
|
EXPECT_EQ(key.key_format(), kKeyFormat);
|
|
EXPECT_EQ(key.key_format_versions(), kKeyFormatVersion);
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_MissingFields_All) {
|
|
HlsAttributeList list;
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.FromAttributeList(list));
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_MissingFields_Method) {
|
|
const std::string kUri = "http://domain.tld/key";
|
|
const std::vector<uint8_t> kIv(HlsKey::kIvLength, 42);
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetQuotedString("URI", kUri));
|
|
EXPECT_TRUE(list.SetHexSequence("IV", kIv));
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.FromAttributeList(list));
|
|
// Nothing should be set.
|
|
EXPECT_FALSE(key.HasUri());
|
|
EXPECT_FALSE(key.HasIv());
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_MissingFields_MissingUri) {
|
|
const std::vector<uint8_t> kIv(HlsKey::kIvLength, 42);
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128"));
|
|
EXPECT_TRUE(list.SetHexSequence("IV", kIv));
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.FromAttributeList(list));
|
|
// Nothing should be set.
|
|
EXPECT_FALSE(key.HasMethod());
|
|
EXPECT_FALSE(key.HasIv());
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_InvalidFields_BadMethodType) {
|
|
HlsAttributeList list;
|
|
// Must be enum string not quoted string.
|
|
EXPECT_TRUE(list.SetQuotedString("METHOD", "NONE"));
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.FromAttributeList(list));
|
|
EXPECT_FALSE(key.HasMethod());
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_InvalidFields_EmptyUri) {
|
|
const std::vector<uint8_t> kIv(HlsKey::kIvLength, 42);
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128"));
|
|
EXPECT_TRUE(list.SetQuotedString("URI", ""));
|
|
EXPECT_TRUE(list.SetHexSequence("IV", kIv));
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.FromAttributeList(list));
|
|
// Nothing should be set.
|
|
EXPECT_FALSE(key.HasMethod());
|
|
EXPECT_FALSE(key.HasUri());
|
|
EXPECT_FALSE(key.HasIv());
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_InvalidFields_BadUriType) {
|
|
const std::vector<uint8_t> kIv(HlsKey::kIvLength, 42);
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128"));
|
|
EXPECT_TRUE(list.SetEnumString("URI", "DATA"));
|
|
EXPECT_TRUE(list.SetHexSequence("IV", kIv));
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.FromAttributeList(list));
|
|
// Nothing should be set.
|
|
EXPECT_FALSE(key.HasMethod());
|
|
EXPECT_FALSE(key.HasUri());
|
|
EXPECT_FALSE(key.HasIv());
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_InvalidFields_ShortIv) {
|
|
const std::vector<uint8_t> kShortIv(HlsKey::kIvLength / 2, 42);
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128"));
|
|
EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data"));
|
|
EXPECT_TRUE(list.SetHexSequence("IV", kShortIv));
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.FromAttributeList(list));
|
|
EXPECT_FALSE(key.HasMethod());
|
|
EXPECT_FALSE(key.HasUri());
|
|
EXPECT_FALSE(key.HasIv());
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_InvalidFields_LargeIv) {
|
|
const std::vector<uint8_t> kLargeIv(HlsKey::kIvLength * 2, 42);
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128"));
|
|
EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data"));
|
|
EXPECT_TRUE(list.SetHexSequence("IV", kLargeIv));
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.FromAttributeList(list));
|
|
EXPECT_FALSE(key.HasMethod());
|
|
EXPECT_FALSE(key.HasUri());
|
|
EXPECT_FALSE(key.HasIv());
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_InvalidFields_BadIvType) {
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128"));
|
|
EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data"));
|
|
EXPECT_TRUE(list.SetQuotedString("IV", "42 repeated 16 times"));
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.FromAttributeList(list));
|
|
EXPECT_FALSE(key.HasMethod());
|
|
EXPECT_FALSE(key.HasUri());
|
|
EXPECT_FALSE(key.HasIv());
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_InvalidFields_EmptyKeyFormat) {
|
|
const std::vector<uint8_t> kIv(HlsKey::kIvLength, 42);
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128"));
|
|
EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data"));
|
|
EXPECT_TRUE(list.SetHexSequence("IV", kIv));
|
|
EXPECT_TRUE(list.SetQuotedString("KEYFORMAT", ""));
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.FromAttributeList(list));
|
|
// Nothing should be set.
|
|
EXPECT_FALSE(key.HasMethod());
|
|
EXPECT_FALSE(key.HasUri());
|
|
EXPECT_FALSE(key.HasIv());
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_InvalidFields_BadKeyFormatType) {
|
|
const std::vector<uint8_t> kIv(HlsKey::kIvLength, 42);
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128"));
|
|
EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data"));
|
|
EXPECT_TRUE(list.SetHexSequence("IV", kIv));
|
|
EXPECT_TRUE(list.SetEnumString("KEYFORMAT", "COM-EXAMPLE"));
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.FromAttributeList(list));
|
|
// Nothing should be set.
|
|
EXPECT_FALSE(key.HasMethod());
|
|
EXPECT_FALSE(key.HasUri());
|
|
EXPECT_FALSE(key.HasIv());
|
|
EXPECT_FALSE(key.HasKeyFormat());
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_InvalidFields_EmptyKeyFormatVersions) {
|
|
const std::vector<uint8_t> kIv(HlsKey::kIvLength, 42);
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128"));
|
|
EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data"));
|
|
EXPECT_TRUE(list.SetHexSequence("IV", kIv));
|
|
EXPECT_TRUE(list.SetQuotedString("KEYFORMAT", "com.example"));
|
|
EXPECT_TRUE(list.SetQuotedString("KEYFORMATVERSIONS", ""));
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.FromAttributeList(list));
|
|
// Nothing should be set.
|
|
EXPECT_FALSE(key.HasMethod());
|
|
EXPECT_FALSE(key.HasUri());
|
|
EXPECT_FALSE(key.HasIv());
|
|
EXPECT_FALSE(key.HasKeyFormat());
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_InvalidFields_ZeroKeyFormatVersions) {
|
|
const std::vector<uint8_t> kIv(HlsKey::kIvLength, 42);
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128"));
|
|
EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data"));
|
|
EXPECT_TRUE(list.SetHexSequence("IV", kIv));
|
|
EXPECT_TRUE(list.SetQuotedString("KEYFORMAT", "com.example"));
|
|
EXPECT_TRUE(list.SetQuotedString("KEYFORMATVERSIONS", "0/1/5"));
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.FromAttributeList(list));
|
|
// Nothing should be set.
|
|
EXPECT_FALSE(key.HasMethod());
|
|
EXPECT_FALSE(key.HasUri());
|
|
EXPECT_FALSE(key.HasIv());
|
|
EXPECT_FALSE(key.HasKeyFormat());
|
|
EXPECT_FALSE(key.HasKeyFormatVersions());
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_InvalidFields_BadKeyFormatVersionsFormat) {
|
|
const std::vector<uint8_t> kIv(HlsKey::kIvLength, 42);
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128"));
|
|
EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data"));
|
|
EXPECT_TRUE(list.SetHexSequence("IV", kIv));
|
|
EXPECT_TRUE(list.SetQuotedString("KEYFORMAT", "com.example"));
|
|
EXPECT_TRUE(list.SetQuotedString("KEYFORMATVERSIONS", "1,2,5"));
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.FromAttributeList(list));
|
|
// Nothing should be set.
|
|
EXPECT_FALSE(key.HasMethod());
|
|
EXPECT_FALSE(key.HasUri());
|
|
EXPECT_FALSE(key.HasIv());
|
|
EXPECT_FALSE(key.HasKeyFormat());
|
|
EXPECT_FALSE(key.HasKeyFormatVersions());
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_InvalidFields_BadKeyFormatVersionsType) {
|
|
const std::vector<uint8_t> kIv(HlsKey::kIvLength, 42);
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetEnumString("METHOD", "AES-128"));
|
|
EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/key-data"));
|
|
EXPECT_TRUE(list.SetHexSequence("IV", kIv));
|
|
EXPECT_TRUE(list.SetQuotedString("KEYFORMAT", "com.example"));
|
|
EXPECT_TRUE(list.SetInteger("KEYFORMATVERSIONS", 1));
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.FromAttributeList(list));
|
|
// Nothing should be set.
|
|
EXPECT_FALSE(key.HasMethod());
|
|
EXPECT_FALSE(key.HasUri());
|
|
EXPECT_FALSE(key.HasIv());
|
|
EXPECT_FALSE(key.HasKeyFormat());
|
|
EXPECT_FALSE(key.HasKeyFormatVersions());
|
|
}
|
|
|
|
TEST(HlsKeyTest, FromAttributeList_InvalidList) {
|
|
// Populate HLS Attribute List as if it is a different message.
|
|
// Using EXT-X-MEDIA.
|
|
HlsAttributeList list;
|
|
EXPECT_TRUE(list.SetEnumString("TYPE", "AUDIO"));
|
|
EXPECT_TRUE(list.SetQuotedString("URI", "http://example.com/video-data"));
|
|
EXPECT_TRUE(list.SetQuotedString("GROUP-ID", "Video Group"));
|
|
EXPECT_TRUE(list.SetQuotedString("LANGUAGE", "en"));
|
|
EXPECT_TRUE(list.SetQuotedString("NAME", "A nice video"));
|
|
EXPECT_TRUE(list.SetEnumString("DEFAULT", "YES"));
|
|
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.FromAttributeList(list));
|
|
}
|
|
|
|
TEST(HlsKeyTest, ParseAttributeList_MethodNone) {
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.ParseAttributeList("METHOD=NONE"));
|
|
|
|
EXPECT_TRUE(key.IsWellFormed());
|
|
EXPECT_EQ(key.method(), "NONE");
|
|
}
|
|
|
|
TEST(HlsKeyTest, ParseAttributeList_MethodNonNone_OnlyRequiredFields) {
|
|
const std::string kUri = "http://domain.tld/key";
|
|
const std::vector<uint8_t> kEmptyIv;
|
|
const std::string kDefaultKeyFormat = "identity";
|
|
const std::set<uint64_t> kDefaultKeyFormatVersions = {1};
|
|
|
|
std::ostringstream hls_stream;
|
|
hls_stream << "METHOD=AES-128,";
|
|
hls_stream << "URI=\"" << kUri << "\"";
|
|
|
|
const std::string key_rep = hls_stream.str();
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.ParseAttributeList(key_rep));
|
|
|
|
EXPECT_TRUE(key.IsWellFormed());
|
|
EXPECT_EQ(key.method(), "AES-128");
|
|
EXPECT_EQ(key.uri(), kUri);
|
|
EXPECT_EQ(key.iv(), kEmptyIv);
|
|
EXPECT_EQ(key.key_format(), kDefaultKeyFormat);
|
|
EXPECT_EQ(key.key_format_versions(), kDefaultKeyFormatVersions);
|
|
}
|
|
|
|
TEST(HlsKeyTest, ParseAttributeList_MethodNonNone_AllFields) {
|
|
const std::string kIvHex(HlsKey::kIvLength * 2, 'A');
|
|
const std::vector<uint8_t> kIv(HlsKey::kIvLength, 0xaa);
|
|
const std::string kUri = "http://domain.tld/key";
|
|
const std::string kKeyFormat = "com.widevine";
|
|
const std::set<uint64_t> kKeyFormatVersion = {1, 2, 5};
|
|
|
|
std::ostringstream hls_stream;
|
|
hls_stream << "METHOD=SAMPLE-AES,";
|
|
hls_stream << "URI=\"" << kUri << "\",";
|
|
hls_stream << "IV=0x" << kIvHex << ',';
|
|
hls_stream << "KEYFORMAT=\"" << kKeyFormat << "\",";
|
|
hls_stream << "KEYFORMATVERSIONS=\"1/2/5\"";
|
|
|
|
const std::string key_rep = hls_stream.str();
|
|
HlsKey key;
|
|
EXPECT_TRUE(key.ParseAttributeList(key_rep));
|
|
|
|
EXPECT_TRUE(key.IsWellFormed());
|
|
EXPECT_EQ(key.method(), "SAMPLE-AES");
|
|
EXPECT_EQ(key.uri(), kUri);
|
|
EXPECT_EQ(key.iv(), kIv);
|
|
EXPECT_EQ(key.key_format(), kKeyFormat);
|
|
EXPECT_EQ(key.key_format_versions(), kKeyFormatVersion);
|
|
}
|
|
|
|
TEST(HlsKeyTest, ParseAttributeList_Empty) {
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.ParseAttributeList(""));
|
|
}
|
|
|
|
TEST(HlsKeyTest, ParseAttributeList_InvalidAttributeList) {
|
|
HlsKey key;
|
|
EXPECT_FALSE(key.ParseAttributeList("Not an Attribute List"));
|
|
}
|
|
} // namespace test
|
|
} // namespace wvutil
|