Update SimulCrypt ECMG on injecting entitlement keys

This commit is contained in:
Lu Chen
2020-02-14 15:46:03 -08:00
parent 688dd62dae
commit d71d62d272
5 changed files with 141 additions and 170 deletions

View File

@@ -29,7 +29,7 @@ constexpr char kTestEcmgChannelSetup[] = {
constexpr char kTestEcmgChannelSetupWithPrivateParameters[] = {
'\x03', // protocol_version
'\x00', '\x01', // message_type - Channel_setup
'\x00', '\x8c', // message_length
'\x00', '\x1e', // message_length
'\x00', '\x0e', // parameter_type - ECM_channel_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
@@ -42,29 +42,7 @@ constexpr char kTestEcmgChannelSetupWithPrivateParameters[] = {
'\x80', '\x01', // parameter_type - CRYPTO_MODE
'\x00', '\x07', // parameter_length
'A', 'e', 's', 'S', 'c', 't', 'e', // parameter_value
'\x80', '\x02', // parameter_type - TRACK_TYPES
'\x00', '\x02', // parameter_length
'S', 'D', // parameter_value
'\x80', '\x05', // parameter_type - ENTITLEMENT_ID_KEY_COMBINATION
'\x00', '\x30', // parameter_length
// parameter_value - ENTITLEMENT_ID (16 bytes)
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', //
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', //
// parameter_value (continued) - ENTITLEMENT_KEY (32 bytes)
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', //
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', //
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', //
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', //
'\x80', '\x05', // parameter_type - ENTITLEMENT_ID_KEY_COMBINATION
'\x00', '\x30', // parameter_length
// parameter_value - ENTITLEMENT_ID (16 bytes)
'\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', //
'\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', //
// parameter_value (continued) - ENTITLEMENT_KEY (32 bytes)
'\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', //
'\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', //
'\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', //
'\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68'};
};
constexpr char kTestEcmgChannelTest[] = {
'\x03', // protocol_version
@@ -126,7 +104,7 @@ constexpr char kTestEcmgChannelStatus[] = {
constexpr char kTestEcmgStreamSetupWithPrivateParameters[] = {
'\x03', // protocol_version
'\x01', '\x01', // message_type - Stream_setup
'\x00', '\x46', // message_length
'\x00', '\xae', // message_length
'\x00', '\x0e', // parameter_type - ECM_channel_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
@@ -139,17 +117,37 @@ constexpr char kTestEcmgStreamSetupWithPrivateParameters[] = {
'\x00', '\x10', // parameter_type - nominal_CP_duration
'\x00', '\x02', // parameter_length
'\x00', '\x64', // parameter_value
'\x80', '\x03', // parameter_type - STREAM_TRACK_TYPE
'\x80', '\x02', // parameter_type - STREAM_TRACK_TYPE
'\x00', '\x02', // parameter_length
'S', 'D', // parameter_value
'\x80', '\x04', // parameter_type - CONTENT_IV
'\x80', '\x03', // parameter_type - CONTENT_IV
'\x00', '\x10', // parameter_length
'\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
'\x80', '\x04', // parameter_type - CONTENT_IV
'\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', //
'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', //
'\x80', '\x03', // parameter_type - CONTENT_IV
'\x00', '\x10', // parameter_length
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
'\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f'};
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', //
'\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', //
'\x80', '\x04', // parameter_type - ENTITLEMENT_ID_KEY_COMBINATION
'\x00', '\x30', // parameter_length
// parameter_value - ENTITLEMENT_ID (16 bytes)
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', //
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', //
// parameter_value (continued) - ENTITLEMENT_KEY (32 bytes)
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', //
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', //
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', //
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', //
'\x80', '\x04', // parameter_type - ENTITLEMENT_ID_KEY_COMBINATION
'\x00', '\x30', // parameter_length
// parameter_value - ENTITLEMENT_ID (16 bytes)
'\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', //
'\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', //
// parameter_value (continued) - ENTITLEMENT_KEY (32 bytes)
'\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', //
'\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', //
'\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', //
'\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68'};
constexpr char kTestEcmgStreamSetup[] = {
'\x03', // protocol_version
@@ -247,7 +245,7 @@ constexpr char kTestEcmgCwProvision[] = {
constexpr char kTestEcmgCwProvisionWithAccessCriteria[] = {
'\x03', // protocol_version
'\x02', '\x01', // message_type - CW_provision
'\x00', '\xf4', // message_length
'\x00', '\xee', // message_length
'\x00', '\x0e', // parameter_type - ECM_channel_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
@@ -271,28 +269,25 @@ constexpr char kTestEcmgCwProvisionWithAccessCriteria[] = {
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', //
'\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', //
'\x00', '\x0d', // parameter_type - access_criteria
'\x00', '\xac', // parameter_length
'\x00', '\xa6', // parameter_length
'\x80', '\x00', // access_criteria parameter_type - AGE_RESTRICTION
'\x00', '\x01', // parameter_length
'\x00', // parameter_value
'\x80', '\x01', // access_criteria parameter_type - CRYPTO_MODE
'\x00', '\x07', // parameter_length
'A', 'e', 's', 'S', 'c', 't', 'e', // parameter_value
'\x80', '\x02', // access_criteria parameter_type - TRACK_TYPES
'\x80', '\x02', // access_criteria parameter_type - STREAM_TRACK_TYPE
'\x00', '\x02', // parameter_length
'S', 'D', // parameter_value
'\x80', '\x03', // access_criteria parameter_type - STREAM_TRACK_TYPE
'\x00', '\x02', // parameter_length
'S', 'D', // parameter_value
'\x80', '\x04', // access_criteria parameter_type - CONTENT_IV
'\x80', '\x03', // access_criteria parameter_type - CONTENT_IV
'\x00', '\x10', // parameter_length
'\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', //
'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', //
'\x80', '\x04', // access_criteria parameter_type - CONTENT_IV
'\x80', '\x03', // access_criteria parameter_type - CONTENT_IV
'\x00', '\x10', // parameter_length
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', //
'\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', //
'\x80', '\x05', // parameter_type - ENTITLEMENT_ID_KEY_COMBINATION
'\x80', '\x04', // parameter_type - ENTITLEMENT_ID_KEY_COMBINATION
'\x00', '\x30', // parameter_length
// parameter_value - ENTITLEMENT_ID (16 bytes)
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', //
@@ -302,7 +297,7 @@ constexpr char kTestEcmgCwProvisionWithAccessCriteria[] = {
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', //
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', //
'\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37', //
'\x80', '\x05', // parameter_type - ENTITLEMENT_ID_KEY_COMBINATION
'\x80', '\x04', // parameter_type - ENTITLEMENT_ID_KEY_COMBINATION
'\x00', '\x30', // parameter_length
// parameter_value - ENTITLEMENT_ID (16 bytes)
'\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67', '\x68', //

View File

@@ -54,11 +54,6 @@ Status ProcessPrivateParameters(const char* const request, uint16_t param_type,
params->crypto_mode = std::string(request + *offset, param_length);
*offset += param_length;
break;
case TRACK_TYPES:
params->track_types.push_back(
std::string(request + *offset, param_length));
*offset += param_length;
break;
case STREAM_TRACK_TYPE:
params->stream_track_type = std::string(request + *offset, param_length);
*offset += param_length;
@@ -722,8 +717,7 @@ void EcmgClientHandler::HandleCwProvision(const EcmgParameters& params,
return;
}
// Request entitlement keys if they do not exist yet.
if (ecm_ == nullptr) {
if (streams_info_.at(params.ecm_stream_id)->ecm == nullptr) {
status = CheckAndInitializeEcm(params);
if (!status.ok()) {
LOG(ERROR) << status.ToString();
@@ -758,9 +752,6 @@ Status EcmgClientHandler::UpdateCommonPrivateParameters(
}
age_restriction_ = params.age_restriction;
}
if (!params.track_types.empty()) {
track_types_.assign(params.track_types.begin(), params.track_types.end());
}
if (!params.content_ivs.empty()) {
if (params.content_ivs.size() < ecmg_config_->number_of_content_keys) {
return {error::INVALID_ARGUMENT,
@@ -778,10 +769,6 @@ Status EcmgClientHandler::UpdateCommonPrivateParameters(
}
}
}
if (!params.entitlement_comb.empty()) {
entitlement_comb_.assign(params.entitlement_comb.begin(),
params.entitlement_comb.end());
}
return OkStatus();
}
@@ -825,26 +812,29 @@ Status EcmgClientHandler::UpdateStreamPrivateParameters(
stream_info->content_ivs.assign(params.content_ivs.begin(),
params.content_ivs.end());
}
if (!params.entitlement_comb.empty()) {
stream_info->entitlement_comb.assign(params.entitlement_comb.begin(),
params.entitlement_comb.end());
}
return OkStatus();
}
Status EcmgClientHandler::CheckAndInitializeEcm(const EcmgParameters& params) {
DCHECK(ecm_ == nullptr);
DCHECK(streams_info_.contains(params.ecm_stream_id));
EcmgStreamInfo* stream_info = streams_info_.at(params.ecm_stream_id).get();
DCHECK(stream_info->ecm == nullptr);
if (stream_info->content_ivs.empty() && content_ivs_.empty()) {
return {error::NOT_FOUND, "Content iv not specified."};
}
if (track_types_.empty()) {
return {error::NOT_FOUND, "Track type not specified."};
}
if (entitlement_comb_.empty()) {
if (stream_info->entitlement_comb.empty()) {
return {error::NOT_FOUND, "Entitlement key id comb not specified."};
}
if (entitlement_comb_.size() !=
track_types_.size() * ecmg_config_->number_of_content_keys) {
if (stream_info->entitlement_comb.size() !=
ecmg_config_->number_of_content_keys) {
return {error::NOT_FOUND,
"Number of injected entitlement keys must equal to number of "
"track types * number of content keys per ecm."};
"content keys per ecm."};
}
bool key_rotation = ecmg_config_->number_of_content_keys > 1;
@@ -862,25 +852,26 @@ Status EcmgClientHandler::CheckAndInitializeEcm(const EcmgParameters& params) {
}
std::vector<EntitlementKeyInfo> entitlements;
entitlements.reserve(entitlement_comb_.size());
for (size_t i = 0; i < entitlement_comb_.size(); i++) {
entitlements.reserve(stream_info->entitlement_comb.size());
for (size_t i = 0; i < stream_info->entitlement_comb.size(); i++) {
entitlements.emplace_back();
EntitlementKeyInfo* entitlement = &entitlements.back();
entitlement->track_type = track_types_.at(key_rotation ? i / 2 : i);
entitlement->track_type = stream_info->track_type;
entitlement->is_even_key = key_rotation ? i % 2 == 0 : true;
entitlement->key_id = entitlement_comb_[i].key_id;
entitlement->key_value = entitlement_comb_[i].key_value;
entitlement->key_id = stream_info->entitlement_comb[i].key_id;
entitlement->key_value = stream_info->entitlement_comb[i].key_value;
}
ecm_ = absl::make_unique<Ecm>();
return ecm_->Initialize(ecm_init_params, entitlements);
stream_info->ecm = absl::make_unique<Ecm>();
return stream_info->ecm->Initialize(ecm_init_params, entitlements);
}
Status EcmgClientHandler::BuildEcmDatagram(const EcmgParameters& params,
uint8_t* ecm_datagram) const {
DCHECK(ecm_datagram);
DCHECK(ecm_);
DCHECK(streams_info_.contains(params.ecm_stream_id));
EcmgStreamInfo* stream_info = streams_info_.at(params.ecm_stream_id).get();
DCHECK(stream_info->ecm);
// Generate serialized ECM.
std::vector<EntitledKeyInfo> keys;
@@ -901,11 +892,11 @@ Status EcmgClientHandler::BuildEcmDatagram(const EcmgParameters& params,
Status status;
std::string serialized_ecm;
if (ecmg_config_->number_of_content_keys > 1) {
status = ecm_->GenerateEcm(&keys[0], &keys[1], stream_info->track_type,
&serialized_ecm);
status = stream_info->ecm->GenerateEcm(
&keys[0], &keys[1], stream_info->track_type, &serialized_ecm);
} else {
status = ecm_->GenerateSingleKeyEcm(&keys[0], stream_info->track_type,
&serialized_ecm);
status = stream_info->ecm->GenerateSingleKeyEcm(
&keys[0], stream_info->track_type, &serialized_ecm);
}
if (!status.ok()) {
return status;

View File

@@ -62,9 +62,6 @@ struct EcmgParameters {
// User defined paremeters below.
uint8_t age_restriction = 0xff; // Assume 0xff (255) is an invalid value.
std::string crypto_mode;
// All track types that need to be supported in the channel.
// Used to request entitlement keys.
std::vector<std::string> track_types;
std::string stream_track_type;
std::vector<std::string> content_ivs; // 8 or 16 bytes, one for each key.
std::vector<EntitlementIdKeyComb> entitlement_comb;
@@ -77,6 +74,8 @@ struct EcmgStreamInfo {
CryptoMode crypto_mode = CryptoMode::kInvalid;
// 8 or 16 bytes, one for each key. Will use |content_ivs_| if empty.
std::vector<std::string> content_ivs;
std::vector<EntitlementIdKeyComb> entitlement_comb;
std::unique_ptr<Ecm> ecm;
};
// A class that handles one (and only one) ECMG client.
@@ -133,10 +132,7 @@ class EcmgClientHandler {
uint16_t channel_id_;
// Channel specific information.
std::unique_ptr<Ecm> ecm_; // |ecm_| is shared within the channel.
uint8_t age_restriction_ = 0;
std::vector<std::string> track_types_;
std::vector<EntitlementIdKeyComb> entitlement_comb_;
std::vector<std::string> content_ivs_;
// Map from ECM_stream_id to EcmgStreamInfo.

View File

@@ -92,10 +92,8 @@ class EcmgClientHandlerTest : public ::testing::Test {
void BuildChannelSetupRequest(uint16_t channel_id, uint32_t super_cas_id,
uint8_t age_restriction,
const std::string& crypto_mode,
const std::vector<std::string>& track_types,
const std::vector<std::string>& entitlements,
char* message, size_t* message_length) {
const std::string& crypto_mode, char* message,
size_t* message_length) {
EXPECT_TRUE(message != nullptr);
EXPECT_TRUE(message_length != nullptr);
BuildMessageHeader(ECMG_SCS_PROTOCOL_VERSION, ECMG_CHANNEL_SETUP, message,
@@ -110,21 +108,6 @@ class EcmgClientHandlerTest : public ::testing::Test {
AddParam(CRYPTO_MODE, reinterpret_cast<const uint8_t*>(crypto_mode.c_str()),
crypto_mode.size(), message, message_length);
}
if (!track_types.empty()) {
for (const auto& track_type : track_types) {
AddParam(TRACK_TYPES,
reinterpret_cast<const uint8_t*>(track_type.c_str()),
track_type.size(), message, message_length);
}
}
if (!entitlements.empty()) {
for (const auto& entitlement : entitlements) {
AddParam(ENTITLEMENT_ID_KEY_COMBINATION,
reinterpret_cast<const uint8_t*>(entitlement.c_str()),
entitlement.size(), message, message_length);
}
}
uint16_t total_param_length = *message_length - 5;
Host16ToBigEndian(message + 3, &total_param_length);
}
@@ -132,6 +115,7 @@ class EcmgClientHandlerTest : public ::testing::Test {
void BuildStreamSetupRequest(uint16_t channel_id, uint16_t stream_id,
uint16_t ecm_id, uint16_t nominal_CP_duration,
const std::string& stream_track_type,
const std::vector<std::string>& entitlements,
const std::vector<std::string>& content_ivs,
char* message, size_t* message_length) {
EXPECT_TRUE(message != nullptr);
@@ -149,6 +133,13 @@ class EcmgClientHandlerTest : public ::testing::Test {
reinterpret_cast<const uint8_t*>(stream_track_type.c_str()),
stream_track_type.size(), message, message_length);
}
if (!entitlements.empty()) {
for (const auto& entitlement : entitlements) {
AddParam(ENTITLEMENT_ID_KEY_COMBINATION,
reinterpret_cast<const uint8_t*>(entitlement.c_str()),
entitlement.size(), message, message_length);
}
}
if (!content_ivs.empty()) {
for (auto& content_iv : content_ivs) {
AddParam(CONTENT_IV, reinterpret_cast<const uint8_t*>(content_iv.c_str()),
@@ -293,25 +284,29 @@ TEST_F(EcmgClientHandlerTest, SuccessSequenceWithPrivateParameters) {
}
TEST_F(EcmgClientHandlerTest, SuccessSequenceInjectedEntitlements) {
BuildChannelSetupRequest(
kChannelId, kSuperCasId, kAgeRestriction, kCryptoMode,
{kTrackTypesHD, kTrackTypesSD},
{absl::StrCat(kEntitlementKeyIdEven, kEntitlementKeyValueEven),
absl::StrCat(kEntitlementKeyIdOdd, kEntitlementKeyValueOdd),
absl::StrCat(kEntitlementKeyIdEven, kEntitlementKeyValueEven),
absl::StrCat(kEntitlementKeyIdOdd, kEntitlementKeyValueOdd)},
request_, &request_len_);
BuildChannelSetupRequest(kChannelId, kSuperCasId, kAgeRestriction,
kCryptoMode, request_, &request_len_);
handler_->HandleRequest(request_, response_, &response_len_);
EXPECT_EQ(sizeof(kTestEcmgChannelStatus), response_len_);
EXPECT_EQ(0, memcmp(kTestEcmgChannelStatus, response_, response_len_));
BuildStreamSetupRequest(kChannelId, kStreamId, kEcmId, kNominalCpDuration,
kTrackTypesSD, {kContentKeyEven, kContentKeyEven},
request_, &request_len_);
BuildStreamSetupRequest(
kChannelId, kStreamId, kEcmId, kNominalCpDuration, kTrackTypesSD,
{absl::StrCat(kEntitlementKeyIdEven, kEntitlementKeyValueEven),
absl::StrCat(kEntitlementKeyIdOdd, kEntitlementKeyValueOdd)},
{kContentKeyEven, kContentKeyEven}, request_, &request_len_);
handler_->HandleRequest(request_, response_, &response_len_);
EXPECT_EQ(sizeof(kTestEcmgStreamStatus), response_len_);
EXPECT_EQ(0, memcmp(kTestEcmgStreamStatus, response_, response_len_));
BuildStreamSetupRequest(
kChannelId, kStreamId + 1, kEcmId, kNominalCpDuration, kTrackTypesHD,
{absl::StrCat(kEntitlementKeyIdEven, kEntitlementKeyValueEven),
absl::StrCat(kEntitlementKeyIdOdd, kEntitlementKeyValueOdd)},
{kContentKeyEven, kContentKeyEven}, request_, &request_len_);
handler_->HandleRequest(request_, response_, &response_len_);
EXPECT_EQ(sizeof(kTestEcmgStreamStatus), response_len_);
const std::vector<EcmgCpCwCombination> cp_cw_combination = {
{kCpNumber, kContentKeyEven}, {kCpNumber + 1, kContentKeyOdd}};
BuildCwProvisionRequest(kChannelId, kStreamId, kCpNumber, cp_cw_combination,
@@ -319,8 +314,13 @@ TEST_F(EcmgClientHandlerTest, SuccessSequenceInjectedEntitlements) {
handler_->HandleRequest(request_, response_, &response_len_);
EXPECT_EQ(sizeof(kTestEcmgEcmResponse), response_len_);
EXPECT_EQ(0, memcmp(kTestEcmgEcmResponse, response_, 27));
}
BuildCwProvisionRequest(kChannelId, kStreamId + 1, kCpNumber,
cp_cw_combination, request_, &request_len_);
handler_->HandleRequest(request_, response_, &response_len_);
EXPECT_EQ(sizeof(kTestEcmgEcmResponse), response_len_);
}
//
TEST_F(EcmgClientHandlerTest, SuccessChannelError) {
SetupValidChannel();
handler_->HandleRequest(kTestEcmgChannelError, response_, &response_len_);
@@ -410,11 +410,7 @@ TEST_F(EcmgClientHandlerTest, WrongParameterInsufficientKey) {
TEST_F(EcmgClientHandlerTest, WrongParameterSuperCasId) {
// Setup a channel with an unexpected super cas id (expecting kSuperCasId).
BuildChannelSetupRequest(
kChannelId, 0, kAgeRestriction, kCryptoMode,
{kTrackTypesHD, kTrackTypesSD},
{absl::StrCat(kEntitlementKeyIdEven, kEntitlementKeyValueEven),
absl::StrCat(kEntitlementKeyIdOdd, kEntitlementKeyValueOdd)},
BuildChannelSetupRequest(kChannelId, 0, kAgeRestriction, kCryptoMode,
request_, &request_len_);
handler_->HandleRequest(request_, response_, &response_len_);
CheckChannelError(UNKNOWN_SUPER_CAS_ID_VALUE, response_, response_len_);
@@ -423,20 +419,18 @@ TEST_F(EcmgClientHandlerTest, WrongParameterSuperCasId) {
TEST_F(EcmgClientHandlerTest, WrongParameterChannelId) {
SetupValidChannel();
// Setup a stream with an unexpected channel id (expecting kChannelId).
BuildStreamSetupRequest(0, kStreamId, kEcmId, kNominalCpDuration,
kTrackTypesSD, {kContentKeyEven, kContentKeyEven},
request_, &request_len_);
BuildStreamSetupRequest(
0, kStreamId, kEcmId, kNominalCpDuration, kTrackTypesSD,
{absl::StrCat(kEntitlementKeyIdEven, kEntitlementKeyValueEven),
absl::StrCat(kEntitlementKeyIdOdd, kEntitlementKeyValueOdd)},
{kContentKeyEven, kContentKeyEven}, request_, &request_len_);
handler_->HandleRequest(request_, response_, &response_len_);
CheckStreamError(UNKNOWN_ECM_CHANNEL_ID_VALUE, response_, response_len_);
}
TEST_F(EcmgClientHandlerTest, WrongParameterCryptoMode) {
BuildChannelSetupRequest(
kChannelId, kSuperCasId, kAgeRestriction, "someCryptoMode",
{kTrackTypesHD, kTrackTypesSD},
{absl::StrCat(kEntitlementKeyIdEven, kEntitlementKeyValueEven),
absl::StrCat(kEntitlementKeyIdOdd, kEntitlementKeyValueOdd)},
request_, &request_len_);
BuildChannelSetupRequest(kChannelId, kSuperCasId, kAgeRestriction,
"someCryptoMode", request_, &request_len_);
handler_->HandleRequest(request_, response_, &response_len_);
CheckChannelError(INVALID_VALUE_FOR_DVB_PARAMETER, response_, response_len_);
}
@@ -451,15 +445,15 @@ TEST_F(EcmgClientHandlerTest, WrongParameterLengthSuperCasId) {
TEST_F(EcmgClientHandlerTest, NoInjectedEntitlements) {
BuildChannelSetupRequest(kChannelId, kSuperCasId, kAgeRestriction,
kCryptoMode, {kTrackTypesSD},
/*entitlements*/ {}, request_, &request_len_);
kCryptoMode, request_, &request_len_);
handler_->HandleRequest(request_, response_, &response_len_);
EXPECT_EQ(sizeof(kTestEcmgChannelStatus), response_len_);
EXPECT_EQ(0, memcmp(kTestEcmgChannelStatus, response_, response_len_));
BuildStreamSetupRequest(kChannelId, kStreamId, kEcmId, kNominalCpDuration,
kTrackTypesSD, {kContentKeyEven, kContentKeyEven},
request_, &request_len_);
BuildStreamSetupRequest(
kChannelId, kStreamId, kEcmId, kNominalCpDuration, kTrackTypesSD,
/*entitlements*/ {}, {kContentKeyEven, kContentKeyEven}, request_,
&request_len_);
handler_->HandleRequest(request_, response_, &response_len_);
EXPECT_EQ(sizeof(kTestEcmgStreamStatus), response_len_);
EXPECT_EQ(0, memcmp(kTestEcmgStreamStatus, response_, response_len_));
@@ -473,19 +467,16 @@ TEST_F(EcmgClientHandlerTest, NoInjectedEntitlements) {
}
TEST_F(EcmgClientHandlerTest, NotEnoughInjectedEntitlements) {
BuildChannelSetupRequest(
kChannelId, kSuperCasId, kAgeRestriction, kCryptoMode,
{kTrackTypesHD, kTrackTypesSD},
{absl::StrCat(kEntitlementKeyIdEven, kEntitlementKeyValueEven),
absl::StrCat(kEntitlementKeyIdOdd, kEntitlementKeyValueOdd)},
request_, &request_len_);
BuildChannelSetupRequest(kChannelId, kSuperCasId, kAgeRestriction,
kCryptoMode, request_, &request_len_);
handler_->HandleRequest(request_, response_, &response_len_);
EXPECT_EQ(sizeof(kTestEcmgChannelStatus), response_len_);
EXPECT_EQ(0, memcmp(kTestEcmgChannelStatus, response_, response_len_));
BuildStreamSetupRequest(kChannelId, kStreamId, kEcmId, kNominalCpDuration,
kTrackTypesSD, {kContentKeyEven, kContentKeyEven},
request_, &request_len_);
BuildStreamSetupRequest(
kChannelId, kStreamId, kEcmId, kNominalCpDuration, kTrackTypesSD,
{absl::StrCat(kEntitlementKeyIdEven, kEntitlementKeyValueEven)},
{kContentKeyEven, kContentKeyEven}, request_, &request_len_);
handler_->HandleRequest(request_, response_, &response_len_);
EXPECT_EQ(sizeof(kTestEcmgStreamStatus), response_len_);
EXPECT_EQ(0, memcmp(kTestEcmgStreamStatus, response_, response_len_));
@@ -499,19 +490,18 @@ TEST_F(EcmgClientHandlerTest, NotEnoughInjectedEntitlements) {
}
TEST_F(EcmgClientHandlerTest, TooManyInjectedEntitlements) {
BuildChannelSetupRequest(
kChannelId, kSuperCasId, kAgeRestriction, kCryptoMode, {kTrackTypesSD},
{absl::StrCat(kEntitlementKeyIdEven, kEntitlementKeyValueEven),
absl::StrCat(kEntitlementKeyIdOdd, kEntitlementKeyValueOdd),
absl::StrCat(kEntitlementKeyIdEven, kEntitlementKeyValueEven)},
request_, &request_len_);
BuildChannelSetupRequest(kChannelId, kSuperCasId, kAgeRestriction,
kCryptoMode, request_, &request_len_);
handler_->HandleRequest(request_, response_, &response_len_);
EXPECT_EQ(sizeof(kTestEcmgChannelStatus), response_len_);
EXPECT_EQ(0, memcmp(kTestEcmgChannelStatus, response_, response_len_));
BuildStreamSetupRequest(kChannelId, kStreamId, kEcmId, kNominalCpDuration,
kTrackTypesSD, {kContentKeyEven, kContentKeyEven},
request_, &request_len_);
BuildStreamSetupRequest(
kChannelId, kStreamId, kEcmId, kNominalCpDuration, kTrackTypesSD,
{absl::StrCat(kEntitlementKeyIdEven, kEntitlementKeyValueEven),
absl::StrCat(kEntitlementKeyIdOdd, kEntitlementKeyValueOdd),
absl::StrCat(kEntitlementKeyIdEven, kEntitlementKeyValueEven)},
{kContentKeyEven, kContentKeyEven}, request_, &request_len_);
handler_->HandleRequest(request_, response_, &response_len_);
EXPECT_EQ(sizeof(kTestEcmgStreamStatus), response_len_);
EXPECT_EQ(0, memcmp(kTestEcmgStreamStatus, response_, response_len_));

View File

@@ -63,10 +63,9 @@
// User defined ECMG parameter type values - 0x8000 to 0xFFFF.
#define AGE_RESTRICTION (0x8000)
#define CRYPTO_MODE (0x8001)
#define TRACK_TYPES (0x8002)
#define STREAM_TRACK_TYPE (0x8003)
#define CONTENT_IV (0x8004)
#define ENTITLEMENT_ID_KEY_COMBINATION (0x8005)
#define STREAM_TRACK_TYPE (0x8002)
#define CONTENT_IV (0x8003)
#define ENTITLEMENT_ID_KEY_COMBINATION (0x8004)
// ECMG protocol error values.
#define INVALID_MESSAGE (0x0001)