Decouple key fetcher; Update ECMG API

This commit is contained in:
Lu Chen
2020-02-11 18:08:06 -08:00
parent ac564bb46f
commit 77b2fcc678
41 changed files with 1872 additions and 1905 deletions

View File

@@ -46,6 +46,7 @@ cc_binary(
srcs = ["wv_cas_ecm_example.cc"],
deps = [
"//base",
"//common:status",
"//media_cas_packager_sdk/public:wv_cas_ecm",
"//media_cas_packager_sdk/public:wv_cas_types",
],
@@ -55,12 +56,8 @@ cc_binary(
name = "wv_cas_key_fetcher_example",
srcs = ["wv_cas_key_fetcher_example.cc"],
deps = [
"//base",
"@abseil_repo//absl/flags:flag",
"@abseil_repo//absl/flags:parse",
"//common:status",
"//media_cas_packager_sdk/public:wv_cas_key_fetcher",
"//protos/public:media_cas_encryption_cc_proto",
],
)

View File

@@ -27,43 +27,44 @@ constexpr char kTestEcmgChannelSetup[] = {
};
constexpr char kTestEcmgChannelSetupWithPrivateParameters[] = {
'\x03', // protocol_version
'\x00', '\x01', // message_type - Channel_setup
'\x00', '\x70', // message_length
'\x00', '\x0e', // parameter_type - ECM_channel_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
'\x00', '\x01', // parameter_type- SUPER_CAS_ID
'\x00', '\x04', // parameter_length
'\x4a', '\xd4', '\x00', '\x00', // parameter_value
'\x80', '\x00', // parameter_type - AGE_RESTRICTION
'\x00', '\x01', // parameter_length
'\x00', // parameter_value
'\x80', '\x01', // parameter_type - CRYPTO_MODE
'\x00', '\x07', // parameter_length
'A', 'e', 's', 'S', 'c', 't', 'e', // parameter_value
'\x80', '\x04', // parameter_type - TRACK_TYPES
'\x00', '\x02', // parameter_length
'S', 'D', // parameter_value
'\x80', '\x04', // parameter_type - TRACK_TYPES
'\x00', '\x02', // parameter_length
'H', 'D', // parameter_value
'\x80', '\x02', // parameter_type - CONTENT_ID
'\x00', '\x09', // parameter_length
'C', 'a', 's', 'T', 's', 'F', 'a', 'k',
'e', // parameter_value - CasTsFake
'\x80', '\x03', // parameter_type - CONTENT_PROVIDER
'\x00', '\x0d', // parameter_length
'w', 'i', 'd', 'e', 'v', 'i', 'n', 'e',
'_', 't', 'e', 's', 't', // parameter_value - widevine_test
'\x80', '\x06', // 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', '\x06', // parameter_type - CONTENT_IV
'\x00', '\x10', // parameter_length
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
'\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f'};
'\x03', // protocol_version
'\x00', '\x01', // message_type - Channel_setup
'\x00', '\x8c', // message_length
'\x00', '\x0e', // parameter_type - ECM_channel_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
'\x00', '\x01', // parameter_type- SUPER_CAS_ID
'\x00', '\x04', // parameter_length
'\x4a', '\xd4', '\x00', '\x00', // parameter_value
'\x80', '\x00', // parameter_type - AGE_RESTRICTION
'\x00', '\x01', // parameter_length
'\x00', // parameter_value
'\x80', '\x01', // parameter_type - CRYPTO_MODE
'\x00', '\x07', // parameter_length
'A', 'e', 's', 'S', 'c', 't', 'e', // parameter_value
'\x80', '\x04', // parameter_type - TRACK_TYPES
'\x00', '\x02', // parameter_length
'S', 'D', // parameter_value
'\x80', '\x07', // 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', '\x07', // 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
@@ -74,6 +75,18 @@ constexpr char kTestEcmgChannelTest[] = {
'\x00', '\x01', // parameter_value
};
constexpr char kTestEcmgChannelError[] = {
'\x03', // protocol_version
'\x00', '\x05', // message_type - Stream_error
'\x00', '\x0c', // message_length
'\x00', '\x0e', // parameter_type - ECM_channel_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
'\x70', '\x00', // parameter_type - Error_status
'\x00', '\x02', // parameter_length
'\x70', '\x00', // parameter_value (UNKNOWN_ERROR)
};
constexpr char kTestEcmgChannelStatus[] = {
'\x03', // protocol_version
'\x00', '\x03', // message_type - Channel_status
@@ -113,7 +126,7 @@ constexpr char kTestEcmgChannelStatus[] = {
constexpr char kTestEcmgStreamSetupWithPrivateParameters[] = {
'\x03', // protocol_version
'\x01', '\x01', // message_type - Stream_setup
'\x00', '\x1e', // message_length
'\x00', '\x46', // message_length
'\x00', '\x0e', // parameter_type - ECM_channel_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
@@ -129,7 +142,14 @@ constexpr char kTestEcmgStreamSetupWithPrivateParameters[] = {
'\x80', '\x05', // parameter_type - STREAM_TRACK_TYPE
'\x00', '\x02', // parameter_length
'S', 'D', // parameter_value
};
'\x80', '\x06', // 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', '\x06', // parameter_type - CONTENT_IV
'\x00', '\x10', // parameter_length
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
'\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f'};
constexpr char kTestEcmgStreamSetup[] = {
'\x03', // protocol_version
@@ -179,6 +199,24 @@ constexpr char kTestEcmgStreamStatus[] = {
'\x01' // parameter_value
};
constexpr char kTestEcmgStreamError[] = {
'\x03', // protocol_version
'\x01', '\x06', // message_type - Stream_error
'\x00', '\x1a', // message_length
'\x00', '\x0e', // parameter_type - ECM_channel_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
'\x00', '\x0f', // parameter_type - ECM_stream_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
'\x70', '\x00', // parameter_type - Error_status
'\x00', '\x02', // parameter_length
'\x70', '\x00', // parameter_value (UNKNOWN_ERROR)
'\x70', '\x01', // parameter_type - Error_information
'\x00', '\x04', // parameter_length
'i', 'n', 'f', 'o' // parameter_value
};
constexpr char kTestEcmgCwProvision[] = {
'\x03', // protocol_version
'\x02', '\x01', // message_type - CW_provision
@@ -209,7 +247,7 @@ constexpr char kTestEcmgCwProvision[] = {
constexpr char kTestEcmgCwProvisionWithAccessCriteria[] = {
'\x03', // protocol_version
'\x02', '\x01', // message_type - CW_provision
'\x00', '\xaa', // message_length
'\x00', '\xf4', // message_length
'\x00', '\x0e', // parameter_type - ECM_channel_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
@@ -225,43 +263,55 @@ constexpr char kTestEcmgCwProvisionWithAccessCriteria[] = {
'\x00', '\x14', // parameter_type - CP_CW_Combination
'\x00', '\x12', // parameter_length
'\x00', '\x00', // parameter_value - CP (2 bytes) then CW next (16 bytes)
'\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
'\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', //
'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', //
'\x00', '\x14', // parameter_type - CP_CW_Combination
'\x00', '\x12', // parameter_length
'\x00', '\x01', // parameter_value - CP (2 bytes) then CW next (16 bytes)
'\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', //
'\x00', '\x0d', // parameter_type - access_criteria
'\x00', '\x62', // parameter_length
'\x00', '\xac', // 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
'A', 'e', 's', 'S', 'c', 't', 'e', // parameter_value
'\x80', '\x04', // access_criteria parameter_type - TRACK_TYPES
'\x00', '\x02', // parameter_length
'S', 'D', // parameter_value
'S', 'D', // parameter_value
'\x80', '\x05', // access_criteria parameter_type - STREAM_TRACK_TYPE
'\x00', '\x02', // parameter_length
'S', 'D', // parameter_value
'\x80', '\x02', // access_criteria parameter_type - CONTENT_ID
'\x00', '\x09', // parameter_length
'C', 'a', 's', 'T', 's', 'F', 'a', 'k',
'e', // parameter_value - CasTsFake
'\x80', '\x03', // access_criteria parameter_type - CONTENT_PROVIDER
'\x00', '\x0d', // parameter_length
'w', 'i', 'd', 'e', 'v', 'i', 'n', 'e',
'_', 't', 'e', 's', 't', // parameter_value - widevine_test
'S', 'D', // parameter_value
'\x80', '\x06', // 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',
'\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07', //
'\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f', //
'\x80', '\x06', // 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'};
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', //
'\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f', //
'\x80', '\x07', // 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', '\x07', // 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 kTestEcmgCwProvisionSingleKey[] = {
'\x03', // protocol_version
@@ -303,25 +353,25 @@ constexpr char kTestEcmgEcmResponse[] = {
'\x00', '\xbc', // parameter_length
// parameter_value - ECM_datagram
'\x47', '\x40', '\x00', '\x10', '\x00', '\x80', '\x70', '\xa5', '\x4a',
'\xd4', '\x02', '\x0b', '\xc0', '\x66', '\x61', '\x6b', '\x65', '\x5f',
'\x6b', '\x65', '\x79', '\x5f', '\x69', '\x64', '\x31', '\x2e', '\x2e',
'\x2e', '\x2e', '\xef', '\x40', '\x57', '\x48', '\xa7', '\xad', '\xdd',
'\xd4', '\x02', '\x0b', '\xc0', '\x30', '\x31', '\x32', '\x33', '\x34',
'\x35', '\x36', '\x37', '\x30', '\x31', '\x32', '\x33', '\x34', '\x35',
'\x36', '\x37', '\xef', '\x40', '\x57', '\x48', '\xa7', '\xad', '\xdd',
'\x34', '\x73', '\xfe', '\x5d', '\x1c', '\x65', '\xa0', '\xbf', '\x93',
'\xfe', '\x01', '\x4b', '\x1d', '\xcd', '\x9e', '\x1d', '\x3a', '\x36',
'\x99', '\x8f', '\x47', '\xa1', '\x3b', '\x46', '\xf1', '\xde', '\x9e',
'\xc2', '\x88', '\xf8', '\x27', '\x2f', '\xea', '\xa1', '\x63', '\x9b',
'\x1b', '\x6a', '\x56', '\x2d', '\x26', '\x31', '\x32', '\x33', '\x34',
'\x35', '\x36', '\x37', '\x38', '\x66', '\x61', '\x6b', '\x65', '\x5f',
'\x6b', '\x65', '\x79', '\x5f', '\x69', '\x64', '\x32', '\x2e', '\x2e',
'\x2e', '\x2e', '\xf4', '\x71', '\x2a', '\x4b', '\x6d', '\x6d', '\x14',
'\x4d', '\x2e', '\x53', '\xe7', '\x4b', '\x9f', '\x4b', '\x0a', '\x34',
'\xb4', '\xfd', '\xbe', '\x86', '\x21', '\x35', '\x1e', '\xda', '\x81',
'\x89', '\x6f', '\x70', '\xd3', '\xd2', '\xb2', '\x79', '\xf2', '\xcd',
'\xeb', '\xc5', '\xaf', '\x89', '\xab', '\xeb', '\xf0', '\x1b', '\xd0',
'\xd3', '\xe9', '\x7d', '\x81', '\x8a', '\x31', '\x32', '\x33', '\x34',
'\x35', '\x36', '\x37', '\x38', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\x90', '\x04', '\x1a', '\xab', '\x1a', '\x46', '\x00', '\xdb', '\xdb',
'\x2f', '\xcb', '\xa5', '\x10', '\x2a', '\x3b', '\x73', '\xf1', '\xfe',
'\x9d', '\x28', '\x2a', '\x3c', '\x0a', '\x5c', '\x58', '\xbc', '\x97',
'\x1d', '\x81', '\x5b', '\x5b', '\xf7', '\x00', '\x01', '\x02', '\x03',
'\x04', '\x05', '\x06', '\x07', '\x08', '\x09', '\x0a', '\x0b', '\x0c',
'\x0d', '\x0e', '\x0f', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66',
'\x67', '\x68', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67',
'\x68', '\xf4', '\x71', '\x2a', '\x4b', '\x6d', '\x6d', '\x14', '\x4d',
'\x2e', '\x53', '\xe7', '\x4b', '\x9f', '\x4b', '\x0a', '\x34', '\x84',
'\xe7', '\xe8', '\xf5', '\x02', '\x39', '\x1f', '\x62', '\x43', '\xb5',
'\xca', '\xb0', '\xee', '\x77', '\xaf', '\xe9', '\x84', '\x41', '\x0a',
'\x16', '\x45', '\x23', '\x6c', '\x1d', '\xe7', '\xdb', '\xfd', '\x91',
'\x91', '\xac', '\x47', '\xbc', '\x10', '\x11', '\x12', '\x13', '\x14',
'\x15', '\x16', '\x17', '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d',
'\x1e', '\x1f', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff'};
constexpr char kTestEcmgStreamClose[] = {

View File

@@ -73,6 +73,42 @@ const char kTestEmmgStreamSetup[] = {
'\x01' // parameter_value - private data
};
const char kTestEmmgStreamBwRequest[] = {
'\x02', // protocol_version
'\x01', '\x17', // message_type - Stream_BW_request
'\x00', '\x1a', // message_length
'\x00', '\x01', // parameter_type - client_id
'\x00', '\x04', // parameter_length
'\x4a', '\xd4', '\x00', '\x00', // parameter_value
'\x00', '\x03', // parameter_type - data_channel_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
'\x00', '\x04', // parameter_type - data_stream_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
'\x00', '\x06', // parameter_type - bandwidth
'\x00', '\x02', // parameter_length
'\x00', '\x64' // parameter_value
};
const char kTestEmmgStreamBwAllocation[] = {
'\x02', // protocol_version
'\x01', '\x18', // message_type - Stream_BW_allocation
'\x00', '\x1a', // message_length
'\x00', '\x01', // parameter_type - client_id
'\x00', '\x04', // parameter_length
'\x4a', '\xd4', '\x00', '\x00', // parameter_value
'\x00', '\x03', // parameter_type - data_channel_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
'\x00', '\x04', // parameter_type - data_stream_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
'\x00', '\x06', // parameter_type - bandwidth
'\x00', '\x02', // parameter_length
'\x00', '\x32' // parameter_value (50 kbps)
};
const char kTestEmmgDataProvision[] = {
'\x02', // protocol_version
'\x02', '\x11', // message_type - Data_provision

View File

@@ -17,63 +17,125 @@
#include <string>
#include <cstdint>
#include "common/status.h"
#include "media_cas_packager_sdk/public/wv_cas_ecm.h"
#include "media_cas_packager_sdk/public/wv_cas_types.h"
const size_t kContentIvSize = 8;
const bool kKeyRotation = false; // whether key rotation is enabled
const char kCryptoMode[] = "CTR"; // CBC, CTR, or CSA2
const int kEcmPid = 149; // PID for the ECM packet
const size_t kContentIvSize = 16; // 8 or 16
const bool kKeyRotation = true; // whether key rotation is enabled
const char kCryptoMode[] =
"AesScte"; // "AesCbc", "AesCtr", "DvbCsa2", "DvbCsa3", "AesOfb", "AesScte"
const int kEcmPid = 149; // PID for the ECM packet
const int kAgeRestriction = 0; // Age restriction for the ECM
const char kOutputFile[] =
"/tmp/ecm.ts"; // ECM TS packet will be output to here
"/tmp/ecm.ts"; // ECM TS packet will be output to here
const uint8_t kTableId = 0x80; // 0x80 or 0x81
const char kDefaultTrackTypeSd[] = "SD";
const char kCsaEvenKey[] = "even_key"; // 8 bytes
const char kEvenKey[] = "even_key........"; // 16 bytes
const char kEvenKeyId[] = "even_key_id....."; // 16 bytes
const char kEvenContentIv8Bytes[] = "even_iv."; // 8 bytes
const char kEvenContentIv16Bytes[] = "even_iv.even_iv."; // 16 bytes
const char kEvenEntitlementKeyId[] = "fake_key_id1...."; // 16 bytes
const char kEvenEntitlementKey[] =
"fakefakefakefakefakefakefake1..."; // 32 bytes
const char kCsaOddKey[] = "odd_key."; // 8 bytes
"fakefakefakefakefakefakefake1..."; // 32 bytes
const char kEvenWrapIv[] = "even_warp_iv...."; // 16 bytes
const char kOddKey[] = "odd_key........."; // 16 bytes
const char kOddKeyId[] = "odd_key_id......"; // 16 bytes
const char kOddContentIv8Bytes[] = "odd_iv.."; // 8 bytes
const char kOddContentIv16Bytes[] = "odd_iv..odd_iv.."; // 16 bytes
const char kOddEntitlementKeyId[] = "fake_key_id2...."; // 16 bytes
const char kOddEntitlementKey[] =
"fakefakefakefakefakefakefake2..."; // 32 bytes
const uint8_t kTableId = 0x80;
"fakefakefakefakefakefakefake2..."; // 32 bytes
const char kOddWrapIv[] = "odd_warp_iv....."; // 16 bytes
const size_t kTsPacketSize = 188;
widevine::cas::CryptoMode GetCryptoMode(const std::string& crypto_mode) {
if (crypto_mode.compare("CBC") == 0) {
return widevine::cas::CryptoMode::kAesCbc;
using widevine::cas::EntitlementKeyInfo;
using widevine::cas::WvCasContentKeyInfo;
using widevine::cas::WvCasEcmParameters;
WvCasEcmParameters CreateWvCasEcmParameters(bool key_rotation,
int content_iv_size) {
WvCasEcmParameters params;
params.content_iv_size = content_iv_size == 8
? widevine::cas::kIvSize8
: widevine::cas::kIvSize16;
params.key_rotation_enabled = key_rotation;
if (!widevine::cas::StringToCryptoMode(kCryptoMode,
&params.crypto_mode)) {
std::cerr << "Unsupported crypto mode " << kCryptoMode << std::endl;
}
if (crypto_mode.compare("CTR") == 0) {
return widevine::cas::CryptoMode::kAesCtr;
params.age_restriction = kAgeRestriction;
return params;
}
std::vector<EntitlementKeyInfo> CreateInjectedEntitlements(bool key_rotation) {
std::vector<EntitlementKeyInfo> injected_entitlements;
injected_entitlements.reserve(key_rotation ? 2 : 1);
injected_entitlements.emplace_back();
EntitlementKeyInfo* entitlement = &injected_entitlements.back();
entitlement->key_id = kEvenEntitlementKeyId;
entitlement->key_value = kEvenEntitlementKey;
entitlement->is_even_key = true;
entitlement->track_type = kDefaultTrackTypeSd;
if (key_rotation) {
injected_entitlements.emplace_back();
EntitlementKeyInfo* entitlement = &injected_entitlements.back();
entitlement->key_id = kOddEntitlementKeyId;
entitlement->key_value = kOddEntitlementKey;
entitlement->is_even_key = false;
entitlement->track_type = kDefaultTrackTypeSd;
}
return widevine::cas::CryptoMode::kDvbCsa2;
return injected_entitlements;
}
std::vector<WvCasContentKeyInfo> CreateContentKeyInfo(bool key_rotation,
int content_iv_size) {
std::vector<WvCasContentKeyInfo> content_keys;
content_keys.reserve(key_rotation ? 2 : 1);
content_keys.emplace_back();
WvCasContentKeyInfo* content_key = &content_keys.back();
content_key->key = kEvenKey;
content_key->key_id = kEvenKeyId;
content_key->content_iv =
content_iv_size == 8 ? kEvenContentIv8Bytes : kEvenContentIv16Bytes;
content_key->wrapped_key_iv = kEvenWrapIv;
if (key_rotation) {
content_keys.emplace_back();
WvCasContentKeyInfo* content_key = &content_keys.back();
content_key->key = kOddKey;
content_key->key_id = kOddKeyId;
content_key->content_iv =
content_iv_size == 8 ? kOddContentIv8Bytes : kOddContentIv16Bytes;
content_key->wrapped_key_iv = kOddWrapIv;
}
return content_keys;
}
int main(int argc, char** argv) {
// Generate ECM.
widevine::cas::WvCasEcm wv_cas_ecm;
widevine::cas::WvCasStatus status = wv_cas_ecm.Initialize(
kContentIvSize, kKeyRotation, GetCryptoMode(kCryptoMode));
if (status != widevine::cas::OK) {
std::cerr << "Failed to initialize WV CAS ECM, error: "
<< widevine::cas::GetWvCasStatusMessage(status)
<< std::endl;
}
WvCasEcmParameters params =
CreateWvCasEcmParameters(kKeyRotation, kContentIvSize);
std::vector<EntitlementKeyInfo> entitlements =
CreateInjectedEntitlements(kKeyRotation);
widevine::cas::WvCasEcm wv_cas_ecm(params, entitlements);
std::vector<WvCasContentKeyInfo> content_keys =
CreateContentKeyInfo(kKeyRotation, kContentIvSize);
std::string ecm;
widevine::Status status;
if (kKeyRotation) {
status = wv_cas_ecm.GenerateEcm(
kCsaEvenKey, kEvenContentIv8Bytes, kEvenEntitlementKeyId,
kEvenEntitlementKey, kCsaOddKey, kOddContentIv8Bytes,
kOddEntitlementKeyId, kOddEntitlementKey, &ecm);
status = wv_cas_ecm.GenerateEcm(content_keys[0], content_keys[1],
kDefaultTrackTypeSd, &ecm);
} else {
status = wv_cas_ecm.GenerateSingleKeyEcm(kCsaEvenKey, kEvenContentIv8Bytes,
kEvenEntitlementKeyId,
kEvenEntitlementKey, &ecm);
status = wv_cas_ecm.GenerateSingleKeyEcm(content_keys[0],
kDefaultTrackTypeSd, &ecm);
}
if (status != widevine::cas::OK) {
std::cerr << "Failed to generate WV CAS ECM, error: "
<< widevine::cas::GetWvCasStatusMessage(status)
if (!status.ok()) {
std::cerr << "Failed to generate WV CAS ECM, error: " << status
<< std::endl;
return -1;
} else {
@@ -89,8 +151,8 @@ int main(int argc, char** argv) {
uint8_t continuity_counter; // not used.
status = wv_cas_ecm.GenerateTsPacket(ecm, kEcmPid, kTableId,
&continuity_counter, packet);
if (status != widevine::cas::OK) {
std::cerr << "Failed to create ECM TS packet" << std::endl;
if (!status.ok()) {
std::cerr << "Failed to create ECM TS packet: " << status << std::endl;
return -1;
} else {
std::cout << "TS packet bytes: ";

View File

@@ -7,65 +7,86 @@
////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <string>
#include <vector>
#include "glog/logging.h"
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "common/status.h"
#include "media_cas_packager_sdk/public/wv_cas_key_fetcher.h"
#include "protos/public/media_cas_encryption.pb.h"
ABSL_FLAG(std::string, content_id, "21140844", "Content ID");
ABSL_FLAG(bool, key_rotation, true, "Whether key rotation is enabled");
ABSL_FLAG(std::string, track_type, "SD", "Provider name");
const char kContentId[] = "21140844";
const char kContentProvider[] = "widevine";
const char kTrackType[] = "SD";
const bool kKeyRotation = false;
const char kSigningProvider[] = "widevine_test";
const char kSingingKey[] =
"1ae8ccd0e7985cc0b6203a55855a1034afc252980e970ca90e5202689f947ab9";
const char kSingingIv[] = "d58ce954203b7c9a9a9d467f59839249";
const char kHttpResponse[] =
"{\"response\":"
"\"eyJzdGF0dXMiOiJPSyIsImNvbnRlbnRfaWQiOiJNakV4TkRBNE5EUT0iLCJlbnRpdGxlbWVu"
"dF9rZXlzIjpbeyJrZXlfaWQiOiJNUGFndXhNb1hNNkUxUzhEOUF3RkNBPT0iLCJrZXkiOiJoZ1"
"JycmdqeUg4NjQycjY3VHd0OHJ1cU5MUGNMRmtKcWRVSUROdm5GZDBNPSIsInRyYWNrX3R5cGUi"
"OiJTRCIsImtleV9zbG90IjoiU0lOR0xFIn1dfQ==\"}";
int main(int argc, char **argv) {
absl::ParseCommandLine(argc, argv);
CHECK(!absl::GetFlag(FLAGS_content_id).empty() &&
!absl::GetFlag(FLAGS_track_type).empty())
<< "Flags 'content_id' and 'track_type' are required";
// Required flags in key fetcher.
CHECK(!absl::GetFlag(FLAGS_license_server).empty() &&
!absl::GetFlag(FLAGS_signing_provider).empty() &&
!absl::GetFlag(FLAGS_signing_key).empty() &&
!absl::GetFlag(FLAGS_signing_iv).empty())
<< "Flags 'license_server', 'signing_provider', 'signing_key' "
"and 'signing_iv' are required";
using widevine::Status;
using widevine::cas::EntitlementKeyInfo;
using widevine::cas::EntitlementRequestParams;
using widevine::cas::WvCasKeyFetcher;
class ExampleKeyFetcher : public WvCasKeyFetcher {
public:
ExampleKeyFetcher(const std::string& signing_provider,
const std::string& signing_key,
const std::string& signing_iv)
: WvCasKeyFetcher(signing_provider, signing_key, signing_iv) {}
// An example that always returns the same response.
Status MakeHttpRequest(const std::string& signed_request_json,
std::string* http_response_json) const override {
*http_response_json = kHttpResponse;
return widevine::OkStatus();
}
};
int main(int argc, char** argv) {
// Initialize key fetcher.
ExampleKeyFetcher key_fetcher(kSigningProvider, kSingingKey, kSingingIv);
// Create request string.
std::string request_str;
widevine::CasEncryptionRequest request;
request.set_provider(absl::GetFlag(FLAGS_signing_provider));
request.set_content_id(absl::GetFlag(FLAGS_content_id));
request.set_key_rotation(absl::GetFlag(FLAGS_key_rotation));
// Only 1 track in this example.
request.add_track_types(absl::GetFlag(FLAGS_track_type));
LOG(INFO) << "Request: " << request.ShortDebugString();
if (!request.SerializeToString(&request_str)) {
LOG(ERROR) << "Failed to serialize request";
return -1;
}
std::string signed_response_str;
widevine::cas::WvCasKeyFetcher key_fetcher;
widevine::Status status =
key_fetcher.RequestEntitlementKey(request_str, &signed_response_str);
EntitlementRequestParams request_params;
request_params.content_id = kContentId;
request_params.content_provider = kContentProvider;
request_params.track_types = {kTrackType};
request_params.key_rotation = kKeyRotation;
Status status =
key_fetcher.CreateEntitlementRequest(request_params, &request_str);
if (!status.ok()) {
LOG(ERROR) << "Failed to request entitlement key";
return -1;
std::cerr << "Failed to create entitlement request, error: " << status
<< std::endl;
}
widevine::SignedCasEncryptionResponse signed_response;
if (!signed_response.ParseFromString(signed_response_str)) {
LOG(ERROR) << "Failed to deserialize signed response";
return -1;
std::cout << "Request: " << request_str << std::endl;
// Request entitlement keys.
std::string signed_response_str;
status = key_fetcher.MakeHttpRequest(request_str, &signed_response_str);
if (!status.ok()) {
std::cerr << "Failed to request entitlement key, error: " << status
<< std::endl;
}
LOG(INFO) << "Signed response: " << signed_response.ShortDebugString();
widevine::CasEncryptionResponse response;
if (!response.ParseFromString(signed_response.response())) {
LOG(ERROR) << "Failed to deserialize response";
return -1;
std::cout << "Response: " << signed_response_str << std::endl;
// Parse entitlement key response.
std::vector<widevine::cas::EntitlementKeyInfo> entitlements;
status =
key_fetcher.ParseEntitlementResponse(signed_response_str, &entitlements);
if (!status.ok()) {
std::cerr << "Failed to parse entitlement response, error: " << status
<< std::endl;
}
LOG(INFO) << "Response: " << response.ShortDebugString();
std::cout << "Parsed: " << entitlements.size() << " entitlement keys."
<< std::endl;
return 0;
}