Decouple key fetcher; Update ECMG API
This commit is contained in:
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -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[] = {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
¶ms.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: ";
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user