Update includes and BUILD

This commit is contained in:
Widevine Buildbot
2020-02-10 22:05:22 +00:00
parent 420cbad45a
commit 05c27554f4
15 changed files with 347 additions and 79 deletions

View File

@@ -14,7 +14,7 @@
namespace widevine { namespace widevine {
namespace cas { namespace cas {
const char kTestEcmgChannelSetup[] = { constexpr char kTestEcmgChannelSetup[] = {
'\x03', // protocol_version '\x03', // protocol_version
'\x00', '\x01', // message_type - Channel_setup '\x00', '\x01', // message_type - Channel_setup
'\x00', '\x0e', // message_length '\x00', '\x0e', // message_length
@@ -26,7 +26,55 @@ const char kTestEcmgChannelSetup[] = {
'\x4a', '\xd4', '\x00', '\x00' // parameter_value '\x4a', '\xd4', '\x00', '\x00' // parameter_value
}; };
const char kTestEcmgChannelStatus[] = { 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'};
constexpr char kTestEcmgChannelTest[] = {
'\x03', // protocol_version
'\x00', '\x02', // message_type - Channel_test
'\x00', '\x06', // message_length
'\x00', '\x0e', // parameter_type - ECM_channel_id
'\x00', '\x02', // parameter_length
'\x00', '\x01', // parameter_value
};
constexpr char kTestEcmgChannelStatus[] = {
'\x03', // protocol_version '\x03', // protocol_version
'\x00', '\x03', // message_type - Channel_status '\x00', '\x03', // message_type - Channel_status
'\x00', '\x39', // message_length '\x00', '\x39', // message_length
@@ -62,7 +110,28 @@ const char kTestEcmgChannelStatus[] = {
'\x00', '\x64' // parameter_value '\x00', '\x64' // parameter_value
}; };
const char kTestEcmgStreamSetup[] = { constexpr char kTestEcmgStreamSetupWithPrivateParameters[] = {
'\x03', // protocol_version
'\x01', '\x01', // message_type - Stream_setup
'\x00', '\x1e', // 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
'\x00', '\x19', // parameter_type - ECM_id
'\x00', '\x02', // parameter_length
'\x00', '\x02', // parameter_value
'\x00', '\x10', // parameter_type - nominal_CP_duration
'\x00', '\x02', // parameter_length
'\x00', '\x64', // parameter_value
'\x80', '\x05', // parameter_type - STREAM_TRACK_TYPE
'\x00', '\x02', // parameter_length
'S', 'D', // parameter_value
};
constexpr char kTestEcmgStreamSetup[] = {
'\x03', // protocol_version '\x03', // protocol_version
'\x01', '\x01', // message_type - Stream_setup '\x01', '\x01', // message_type - Stream_setup
'\x00', '\x18', // message_length '\x00', '\x18', // message_length
@@ -80,7 +149,19 @@ const char kTestEcmgStreamSetup[] = {
'\x00', '\x64' // parameter_value '\x00', '\x64' // parameter_value
}; };
const char kTestEcmgStreamStatus[] = { constexpr char kTestEcmgStreamTest[] = {
'\x03', // protocol_version
'\x01', '\x02', // message_type - Stream_test
'\x00', '\x0c', // 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
};
constexpr char kTestEcmgStreamStatus[] = {
'\x03', // protocol_version '\x03', // protocol_version
'\x01', '\x03', // message_type - Stream_status '\x01', '\x03', // message_type - Stream_status
'\x00', '\x17', // message_length '\x00', '\x17', // message_length
@@ -98,7 +179,7 @@ const char kTestEcmgStreamStatus[] = {
'\x01' // parameter_value '\x01' // parameter_value
}; };
const char kTestEcmgCwProvision[] = { constexpr char kTestEcmgCwProvision[] = {
'\x03', // protocol_version '\x03', // protocol_version
'\x02', '\x01', // message_type - CW_provision '\x02', '\x01', // message_type - CW_provision
'\x00', '\x44', // message_length '\x00', '\x44', // message_length
@@ -125,8 +206,87 @@ const char kTestEcmgCwProvision[] = {
'\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17', '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
'\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f'}; '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f'};
constexpr char kTestEcmgCwProvisionWithAccessCriteria[] = {
'\x03', // protocol_version
'\x02', '\x01', // message_type - CW_provision
'\x00', '\xaa', // 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
'\x00', '\x12', // parameter_type - CP_number
'\x00', '\x02', // parameter_length
'\x00', '\x00', // parameter_value
'\x00', '\x13', // parameter_type - CP_duration
'\x00', '\x02', // parameter_length
'\x00', '\x64', // parameter_value
'\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', '\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',
'\x00', '\x0d', // parameter_type - access_criteria
'\x00', '\x62', // 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', '\x04', // access_criteria parameter_type - TRACK_TYPES
'\x00', '\x02', // parameter_length
'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
'\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',
'\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'};
constexpr char kTestEcmgCwProvisionSingleKey[] = {
'\x03', // protocol_version
'\x02', '\x01', // message_type - CW_provision
'\x00', '\x2e', // 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
'\x00', '\x12', // parameter_type - CP_number
'\x00', '\x02', // parameter_length
'\x00', '\x00', // parameter_value
'\x00', '\x13', // parameter_type - CP_duration
'\x00', '\x02', // parameter_length
'\x00', '\x64', // parameter_value
'\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'};
// CW is encrypted using hardcoded fixed entitlement key. // CW is encrypted using hardcoded fixed entitlement key.
const char kTestEcmgEcmResponse[] = { constexpr char kTestEcmgEcmResponse[] = {
'\x03', // protocol_version '\x03', // protocol_version
'\x02', '\x02', // message_type - ECM_response '\x02', '\x02', // message_type - ECM_response
'\x00', '\xd2', // message_length '\x00', '\xd2', // message_length
@@ -142,8 +302,8 @@ const char kTestEcmgEcmResponse[] = {
'\x00', '\x15', // parameter_type - ECM_datagram '\x00', '\x15', // parameter_type - ECM_datagram
'\x00', '\xbc', // parameter_length '\x00', '\xbc', // parameter_length
// parameter_value - ECM_datagram // parameter_value - ECM_datagram
'\x47', '\x40', '\x02', '\x10', '\x00', '\x80', '\x70', '\x95', '\x4a', '\x47', '\x40', '\x00', '\x10', '\x00', '\x80', '\x70', '\xa5', '\x4a',
'\xd4', '\x01', '\x05', '\x80', '\x66', '\x61', '\x6b', '\x65', '\x5f', '\xd4', '\x02', '\x0b', '\xc0', '\x66', '\x61', '\x6b', '\x65', '\x5f',
'\x6b', '\x65', '\x79', '\x5f', '\x69', '\x64', '\x31', '\x2e', '\x2e', '\x6b', '\x65', '\x79', '\x5f', '\x69', '\x64', '\x31', '\x2e', '\x2e',
'\x2e', '\x2e', '\xef', '\x40', '\x57', '\x48', '\xa7', '\xad', '\xdd', '\x2e', '\x2e', '\xef', '\x40', '\x57', '\x48', '\xa7', '\xad', '\xdd',
'\x34', '\x73', '\xfe', '\x5d', '\x1c', '\x65', '\xa0', '\xbf', '\x93', '\x34', '\x73', '\xfe', '\x5d', '\x1c', '\x65', '\xa0', '\xbf', '\x93',
@@ -164,7 +324,7 @@ const char kTestEcmgEcmResponse[] = {
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff',
'\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff'}; '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff', '\xff'};
const char kTestEcmgStreamCloseRequest[] = { constexpr char kTestEcmgStreamClose[] = {
'\x03', // protocol_version '\x03', // protocol_version
'\x01', '\x04', // message_type - Stream_close_request '\x01', '\x04', // message_type - Stream_close_request
'\x00', '\x0c', // message_length '\x00', '\x0c', // message_length
@@ -176,7 +336,7 @@ const char kTestEcmgStreamCloseRequest[] = {
'\x00', '\x01' // parameter_value '\x00', '\x01' // parameter_value
}; };
const char kTestEcmgStreamCloseResponse[] = { constexpr char kTestEcmgStreamCloseResponse[] = {
'\x03', // protocol_version '\x03', // protocol_version
'\x01', '\x05', // message_type - Stream_close_response '\x01', '\x05', // message_type - Stream_close_response
'\x00', '\x0c', // message_length '\x00', '\x0c', // message_length
@@ -188,7 +348,7 @@ const char kTestEcmgStreamCloseResponse[] = {
'\x00', '\x01' // parameter_value '\x00', '\x01' // parameter_value
}; };
const char kTestEcmgChannelClose[] = { constexpr char kTestEcmgChannelClose[] = {
'\x03', // protocol_version '\x03', // protocol_version
'\x00', '\x04', // message_type - Channel_close '\x00', '\x04', // message_type - Channel_close
'\x00', '\x06', // message_length '\x00', '\x06', // message_length
@@ -197,6 +357,57 @@ const char kTestEcmgChannelClose[] = {
'\x00', '\x01' // parameter_value '\x00', '\x01' // parameter_value
}; };
constexpr char kTestChannelErrorResponse[] = {
'\x03', // protocol_version
'\x00', '\x05', // message_type - Channel_error_response
'\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
'\x00', '\x00' // parameter_value: actual value varies.
};
constexpr char kTestStreamErrorResponse[] = {
'\x03', // protocol_version
'\x01', '\x06', // message_type - Stream_error_response
'\x00', '\x12', // 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
'\x00', '\x00' // parameter_value: actual value varies.
};
constexpr char kTestEcmgChannelSetupWrongParameterLength[] = {
'\x03', // protocol_version
'\x00', '\x01', // message_type - Channel_setup
'\x00', '\x0e', // 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', '\x02', // parameter_length -- Should be \x04
'\x4a', '\xd4', '\x00', '\x00' // parameter_value
};
constexpr char kTestEcmgChannelSetupWrongMessageLength[] = {
'\x03', // protocol_version
'\x00', '\x01', // message_type - Channel_setup
'\x00', '\xee', // message_length -- Should be \x0e
'\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 -- Should be \x04
'\x4a', '\xd4', '\x00', '\x00' // parameter_value
};
} // namespace cas } // namespace cas
} // namespace widevine } // namespace widevine

Binary file not shown.

View File

@@ -8,11 +8,15 @@
// Example of how to use the wv_cas_ecm library. // Example of how to use the wv_cas_ecm library.
#include <stddef.h>
#include <stdio.h>
#include <cassert> #include <cassert>
#include <fstream> #include <fstream>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <cstdint>
#include "media_cas_packager_sdk/public/wv_cas_ecm.h" #include "media_cas_packager_sdk/public/wv_cas_ecm.h"
#include "media_cas_packager_sdk/public/wv_cas_types.h" #include "media_cas_packager_sdk/public/wv_cas_types.h"
@@ -96,11 +100,11 @@ int main(int argc, char** argv) {
std::cout << std::endl; std::cout << std::endl;
} }
// Write ECM TS Packet to a file. // Write ECM TS Packet to a file.
std::ofstream file; std::ofstream file;
file.open(kOutputFile, std::ios_base::binary); file.open(kOutputFile, std::ios_base::binary);
assert(file.is_open()); assert(file.is_open());
file.write(reinterpret_cast<char *>(packet), kTsPacketSize); file.write(reinterpret_cast<char*>(packet), kTsPacketSize);
file.close(); file.close();
return 0; return 0;
} }

Binary file not shown.

View File

@@ -7,36 +7,39 @@
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
#include <iostream>
#include <string> #include <string>
#include "gflags/gflags.h"
#include "glog/logging.h" #include "glog/logging.h"
#include "absl/flags/flag.h"
#include "absl/flags/parse.h"
#include "common/status.h" #include "common/status.h"
#include "media_cas_packager_sdk/public/wv_cas_key_fetcher.h" #include "media_cas_packager_sdk/public/wv_cas_key_fetcher.h"
#include "protos/public/media_cas_encryption.pb.h" #include "protos/public/media_cas_encryption.pb.h"
DEFINE_string(content_id, "21140844", "Content ID"); ABSL_FLAG(std::string, content_id, "21140844", "Content ID");
DEFINE_bool(key_rotation, true, "Whether key rotation is enabled"); ABSL_FLAG(bool, key_rotation, true, "Whether key rotation is enabled");
DEFINE_string(track_type, "SD", "Provider name"); ABSL_FLAG(std::string, track_type, "SD", "Provider name");
int main(int argc, char **argv) { int main(int argc, char **argv) {
gflags::ParseCommandLineFlags(&argc, &argv, true); absl::ParseCommandLine(argc, argv);
CHECK(!FLAGS_content_id.empty() && !FLAGS_track_type.empty()) CHECK(!absl::GetFlag(FLAGS_content_id).empty() &&
!absl::GetFlag(FLAGS_track_type).empty())
<< "Flags 'content_id' and 'track_type' are required"; << "Flags 'content_id' and 'track_type' are required";
// Required flags in key fetcher. // Required flags in key fetcher.
CHECK(!FLAGS_license_server.empty() && !FLAGS_signing_provider.empty() && CHECK(!absl::GetFlag(FLAGS_license_server).empty() &&
!FLAGS_signing_key.empty() && !FLAGS_signing_iv.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' " << "Flags 'license_server', 'signing_provider', 'signing_key' "
"and 'signing_iv' are required"; "and 'signing_iv' are required";
std::string request_str; std::string request_str;
widevine::CasEncryptionRequest request; widevine::CasEncryptionRequest request;
request.set_provider(FLAGS_signing_provider); request.set_provider(absl::GetFlag(FLAGS_signing_provider));
request.set_content_id(FLAGS_content_id); request.set_content_id(absl::GetFlag(FLAGS_content_id));
request.set_key_rotation(FLAGS_key_rotation); request.set_key_rotation(absl::GetFlag(FLAGS_key_rotation));
// Only 1 track in this example. // Only 1 track in this example.
request.add_track_types(FLAGS_track_type); request.add_track_types(absl::GetFlag(FLAGS_track_type));
LOG(INFO) << "Request: " << request.ShortDebugString(); LOG(INFO) << "Request: " << request.ShortDebugString();
if (!request.SerializeToString(&request_str)) { if (!request.SerializeToString(&request_str)) {
LOG(ERROR) << "Failed to serialize request"; LOG(ERROR) << "Failed to serialize request";

Binary file not shown.

View File

@@ -10,6 +10,7 @@
#include <iostream> #include <iostream>
#include <string> #include <string>
#include <vector>
#include "media_cas_packager_sdk/public/wv_cas_types.h" #include "media_cas_packager_sdk/public/wv_cas_types.h"

Binary file not shown.

View File

@@ -10,8 +10,10 @@
#define MEDIA_CAS_PACKAGER_SDK_PUBLIC_WV_CAS_CA_DESCRIPTOR_H_ #define MEDIA_CAS_PACKAGER_SDK_PUBLIC_WV_CAS_CA_DESCRIPTOR_H_
#include <stddef.h> #include <stddef.h>
#include <string> #include <string>
#include <cstdint>
#include "media_cas_packager_sdk/public/wv_cas_types.h" #include "media_cas_packager_sdk/public/wv_cas_types.h"
namespace widevine { namespace widevine {
@@ -53,10 +55,9 @@ class WvCasCaDescriptor {
// section (for an EMM stream) or into a TS Program Map Table section (for an // section (for an EMM stream) or into a TS Program Map Table section (for an
// ECM stream). The descriptor will be 6 bytes plus any bytes added as // ECM stream). The descriptor will be 6 bytes plus any bytes added as
// (user-defined) private data. // (user-defined) private data.
virtual WvCasStatus GenerateCaDescriptor(uint16_t ca_pid, virtual WvCasStatus GenerateCaDescriptor(
const std::string& provider, uint16_t ca_pid, const std::string& provider, const std::string& content_id,
const std::string& content_id, std::string* serialized_ca_desc) const;
std::string* serialized_ca_desc) const;
// Return the base size (before private data is added) of the CA // Return the base size (before private data is added) of the CA
// descriptor. The user can call this to plan the layout of the Table section // descriptor. The user can call this to plan the layout of the Table section
@@ -65,7 +66,7 @@ class WvCasCaDescriptor {
// Return private data in the CA descriptor. // Return private data in the CA descriptor.
virtual std::string GeneratePrivateData(const std::string& provider, virtual std::string GeneratePrivateData(const std::string& provider,
const std::string& content_id) const; const std::string& content_id) const;
}; };
} // namespace cas } // namespace cas

View File

@@ -9,13 +9,9 @@
#ifndef MEDIA_CAS_PACKAGER_SDK_PUBLIC_WV_CAS_ECM_H_ #ifndef MEDIA_CAS_PACKAGER_SDK_PUBLIC_WV_CAS_ECM_H_
#define MEDIA_CAS_PACKAGER_SDK_PUBLIC_WV_CAS_ECM_H_ #define MEDIA_CAS_PACKAGER_SDK_PUBLIC_WV_CAS_ECM_H_
#include <cstddef>
#include <list>
#include <map>
#include <string> #include <string>
#include <utility>
#include <vector>
#include <cstdint>
#include "media_cas_packager_sdk/public/wv_cas_types.h" #include "media_cas_packager_sdk/public/wv_cas_types.h"
namespace widevine { namespace widevine {
@@ -118,7 +114,7 @@ class WvCasEcm {
// - |pid| program ID for the ECM stream // - |pid| program ID for the ECM stream
// - |table_id| is the table ID byte put in the section header, it should be // - |table_id| is the table ID byte put in the section header, it should be
// either 0x80 or 0x81. Changing table ID from 0x80 or 0x81 or // either 0x80 or 0x81. Changing table ID from 0x80 or 0x81 or
// 0x81 to 0x80 is used to singal to the client that the key contained // 0x81 to 0x80 is used to signal to the client that the key contained
// in the ECM has changed. In other words, if you are building an ECM // in the ECM has changed. In other words, if you are building an ECM
// with a new key that was not in any previous ECM, you should flip the // with a new key that was not in any previous ECM, you should flip the
// table ID so the client knows this is an important ECM it should process. // table ID so the client knows this is an important ECM it should process.
@@ -132,7 +128,7 @@ class WvCasEcm {
virtual WvCasStatus GenerateTsPacket(const std::string& ecm, uint16_t pid, virtual WvCasStatus GenerateTsPacket(const std::string& ecm, uint16_t pid,
uint8_t table_id, uint8_t table_id,
uint8_t* continuity_counter, uint8_t* continuity_counter,
uint8_t* packet); uint8_t* packet) const;
private: private:
bool initialized_ = false; bool initialized_ = false;

View File

@@ -10,40 +10,42 @@
#include <stddef.h> #include <stddef.h>
#include <string.h> #include <string.h>
#include <string>
#include "gflags/gflags.h" #include <cstdint>
#include "glog/logging.h" #include "glog/logging.h"
#include "google/protobuf/util/json_util.h" #include "google/protobuf/util/json_util.h"
#include "absl/flags/flag.h"
#include "absl/strings/escaping.h" #include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "curl/curl.h" #include "curl/curl.h"
#include "curl/easy.h" #include "curl/easy.h"
#include "common/signature_util.h" #include "common/signature_util.h"
#include "common/status.h"
#include "protos/public/media_cas_encryption.pb.h" #include "protos/public/media_cas_encryption.pb.h"
using google::protobuf::util::JsonPrintOptions; using google::protobuf::util::JsonPrintOptions;
using google::protobuf::util::JsonStringToMessage; using google::protobuf::util::JsonStringToMessage;
using google::protobuf::util::MessageToJsonString; using google::protobuf::util::MessageToJsonString;
DEFINE_string( ABSL_FLAG(std::string, license_server, "",
license_server, "", "HTTP URL to the license server for making CAS encryption request.");
"HTTP URL to the license server for making CAS encryption request"); ABSL_FLAG(std::string, signing_provider, "",
DEFINE_string(signing_provider, "", "Name of the provider signing the CAS encryption request.");
"Name of the provider signing the CAS encryption request"); ABSL_FLAG(std::string, signing_key, "",
DEFINE_string(signing_key, "", "AES key (in hex) for signing the CAS encryption request.");
"AES key (in hex) for signing the CAS encryption request"); ABSL_FLAG(std::string, signing_iv, "",
DEFINE_string(signing_iv, "", "AES iv (in hex) for signing the CAS encryption request.");
"AES iv (in hex) for signing the CAS encryption request");
namespace widevine { namespace widevine {
namespace cas { namespace cas {
Status WvCasKeyFetcher::RequestEntitlementKey(const std::string& request_string, Status WvCasKeyFetcher::RequestEntitlementKey(
std::string* signed_response_string) { const std::string& request_string,
if (FLAGS_signing_provider.empty() || FLAGS_signing_key.empty() || std::string* signed_response_string) const {
FLAGS_signing_iv.empty()) { if (absl::GetFlag(FLAGS_signing_provider).empty() ||
absl::GetFlag(FLAGS_signing_key).empty() ||
absl::GetFlag(FLAGS_signing_iv).empty()) {
return Status( return Status(
error::INVALID_ARGUMENT, error::INVALID_ARGUMENT,
"Flag 'signing_provider', 'signing_key' or 'signing_iv' is empty"); "Flag 'signing_provider', 'signing_key' or 'signing_iv' is empty");
@@ -72,13 +74,14 @@ Status WvCasKeyFetcher::RequestEntitlementKey(const std::string& request_string,
signed_request.set_request(request_json); signed_request.set_request(request_json);
std::string signature; std::string signature;
if (!signature_util::GenerateAesSignature( if (!signature_util::GenerateAesSignature(
request_json, absl::HexStringToBytes(FLAGS_signing_key), request_json,
absl::HexStringToBytes(FLAGS_signing_iv), &signature) absl::HexStringToBytes(absl::GetFlag(FLAGS_signing_key)),
absl::HexStringToBytes(absl::GetFlag(FLAGS_signing_iv)), &signature)
.ok()) { .ok()) {
return Status(error::INTERNAL, "Failed to sign the request."); return Status(error::INTERNAL, "Failed to sign the request.");
} }
signed_request.set_signature(signature); signed_request.set_signature(signature);
signed_request.set_signer(FLAGS_signing_provider); signed_request.set_signer(absl::GetFlag(FLAGS_signing_provider));
std::string signed_request_json; std::string signed_request_json;
// NOTE: MessageToJsonString will automatically converts the 'request' and // NOTE: MessageToJsonString will automatically converts the 'request' and
// 'signature' fields in SignedCasEncryptionRequest to base64, because they // 'signature' fields in SignedCasEncryptionRequest to base64, because they
@@ -115,7 +118,8 @@ Status WvCasKeyFetcher::RequestEntitlementKey(const std::string& request_string,
return OkStatus(); return OkStatus();
} }
size_t AppendToString(void* ptr, size_t size, size_t count, std::string* output) { size_t AppendToString(void* ptr, size_t size, size_t count,
std::string* output) {
const absl::string_view data(static_cast<char*>(ptr), size * count); const absl::string_view data(static_cast<char*>(ptr), size * count);
absl::StrAppend(output, data); absl::StrAppend(output, data);
return data.size(); return data.size();
@@ -124,14 +128,15 @@ size_t AppendToString(void* ptr, size_t size, size_t count, std::string* output)
Status WvCasKeyFetcher::MakeHttpRequest(const std::string& signed_request_json, Status WvCasKeyFetcher::MakeHttpRequest(const std::string& signed_request_json,
std::string* http_response_json) const { std::string* http_response_json) const {
CHECK(http_response_json); CHECK(http_response_json);
if (FLAGS_license_server.empty()) { if (absl::GetFlag(FLAGS_license_server).empty()) {
return Status(error::INVALID_ARGUMENT, "Flag 'license_server' is empty"); return Status(error::INVALID_ARGUMENT, "Flag 'license_server' is empty");
} }
CURL* curl; CURL* curl;
CURLcode curl_code; CURLcode curl_code;
curl = curl_easy_init(); curl = curl_easy_init();
if (curl) { if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, FLAGS_license_server.c_str()); curl_easy_setopt(curl, CURLOPT_URL,
absl::GetFlag(FLAGS_license_server).c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, signed_request_json.c_str()); curl_easy_setopt(curl, CURLOPT_POSTFIELDS, signed_request_json.c_str());
curl_easy_setopt(curl, CURLOPT_WRITEDATA, http_response_json); curl_easy_setopt(curl, CURLOPT_WRITEDATA, http_response_json);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &AppendToString); curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &AppendToString);
@@ -140,8 +145,9 @@ Status WvCasKeyFetcher::MakeHttpRequest(const std::string& signed_request_json,
(int64_t)strlen(signed_request_json.c_str())); (int64_t)strlen(signed_request_json.c_str()));
curl_code = curl_easy_perform(curl); curl_code = curl_easy_perform(curl);
if (curl_code != CURLE_OK) { if (curl_code != CURLE_OK) {
return Status(error::INTERNAL, "curl_easy_perform() failed: " + return Status(error::INTERNAL,
std::string(curl_easy_strerror(curl_code))); "curl_easy_perform() failed: " +
std::string(curl_easy_strerror(curl_code)));
} }
curl_easy_cleanup(curl); curl_easy_cleanup(curl);
} else { } else {

View File

@@ -11,14 +11,10 @@
#include <string> #include <string>
#include "gflags/gflags.h" #include "absl/flags/declare.h"
#include "common/status.h"
#include "media_cas_packager_sdk/internal/key_fetcher.h" #include "media_cas_packager_sdk/internal/key_fetcher.h"
DECLARE_string(license_server);
DECLARE_string(signing_provider);
DECLARE_string(signing_key);
DECLARE_string(signing_iv);
namespace widevine { namespace widevine {
namespace cas { namespace cas {
@@ -29,7 +25,7 @@ class WvCasKeyFetcher : public KeyFetcher {
WvCasKeyFetcher() = default; WvCasKeyFetcher() = default;
WvCasKeyFetcher(const WvCasKeyFetcher&) = delete; WvCasKeyFetcher(const WvCasKeyFetcher&) = delete;
WvCasKeyFetcher& operator=(const WvCasKeyFetcher&) = delete; WvCasKeyFetcher& operator=(const WvCasKeyFetcher&) = delete;
virtual ~WvCasKeyFetcher() = default; ~WvCasKeyFetcher() override = default;
// Get entitlement keys from the license server. Send a // Get entitlement keys from the license server. Send a
// SignedCasEncryptionRequest message to the license server, receive a // SignedCasEncryptionRequest message to the license server, receive a
@@ -40,8 +36,9 @@ class WvCasKeyFetcher : public KeyFetcher {
// |signed_response_string| a serialized SignedCasEncryptionResponse // |signed_response_string| a serialized SignedCasEncryptionResponse
// message. It should be passed into // message. It should be passed into
// widevine::cas::Ecm::ProcessCasEncryptionResponse(). // widevine::cas::Ecm::ProcessCasEncryptionResponse().
Status RequestEntitlementKey(const std::string& request_string, Status RequestEntitlementKey(
std::string* signed_response_string) override; const std::string& request_string,
std::string* signed_response_string) const override;
protected: protected:
// Makes a HTTP request to License Server for entitlement key(s). // Makes a HTTP request to License Server for entitlement key(s).
@@ -54,4 +51,10 @@ class WvCasKeyFetcher : public KeyFetcher {
} // namespace cas } // namespace cas
} // namespace widevine } // namespace widevine
// Exposed for testing and example.
ABSL_DECLARE_FLAG(std::string, license_server);
ABSL_DECLARE_FLAG(std::string, signing_provider);
ABSL_DECLARE_FLAG(std::string, signing_key);
ABSL_DECLARE_FLAG(std::string, signing_iv);
#endif // MEDIA_CAS_PACKAGER_SDK_PUBLIC_WV_CAS_KEY_FETCHER_H_ #endif // MEDIA_CAS_PACKAGER_SDK_PUBLIC_WV_CAS_KEY_FETCHER_H_

View File

@@ -46,9 +46,13 @@ std::string GetWvCasStatusMessage(WvCasStatus status) {
// Numeric value of crypto mode is the index into strings array. // Numeric value of crypto mode is the index into strings array.
static const char* kCrypoModeStrings[] = { static const char* kCrypoModeStrings[] = {
"AesCbc", "AesCbc", "AesCtr", "DvbCsa2", "DvbCsa3", "AesOfb", "AesScte",
"AesCtr", };
"DvbCsa2",
// Numeric value of scrambling level is the index into strings array.
static const char* kScramblingLevelStrings[] = {
"PES",
"TS",
}; };
bool CryptoModeToString(CryptoMode mode, std::string* str) { bool CryptoModeToString(CryptoMode mode, std::string* str) {
@@ -69,7 +73,7 @@ bool StringToCryptoMode(const std::string& str, CryptoMode* mode) {
return false; return false;
} }
for (int i = 0; i < arraysize(kCrypoModeStrings); ++i) { for (int i = 0; i < arraysize(kCrypoModeStrings); ++i) {
if (str.compare(kCrypoModeStrings[i]) == 0) { if (str == kCrypoModeStrings[i]) {
*mode = static_cast<CryptoMode>(i); *mode = static_cast<CryptoMode>(i);
return true; return true;
} }
@@ -78,6 +82,33 @@ bool StringToCryptoMode(const std::string& str, CryptoMode* mode) {
return false; return false;
} }
bool ScramblingLevelToString(ScramblingLevel mode, std::string* str) {
if (str == nullptr) {
return false;
}
int mode_idx = static_cast<int>(mode);
if (mode_idx >= 0 && mode_idx < arraysize(kScramblingLevelStrings)) {
*str = kScramblingLevelStrings[mode_idx];
return true;
}
LOG(ERROR) << "Invalid scrambling mode: " << mode_idx;
return false;
}
bool StringToScramblingLevel(const std::string& str, ScramblingLevel* mode) {
if (mode == nullptr) {
return false;
}
for (int i = 0; i < arraysize(kScramblingLevelStrings); ++i) {
if (str == kScramblingLevelStrings[i]) {
*mode = static_cast<ScramblingLevel>(i);
return true;
}
}
LOG(ERROR) << "Invalid scrambling mode: " << str;
return false;
}
WvCasStatus CreateWvCasEncryptionRequestJson( WvCasStatus CreateWvCasEncryptionRequestJson(
const WvCasEncryptionRequest& request, std::string* request_json) { const WvCasEncryptionRequest& request, std::string* request_json) {
CHECK(request_json); CHECK(request_json);

View File

@@ -52,19 +52,31 @@ enum WvCasStatus {
std::string GetWvCasStatusMessage(WvCasStatus status); std::string GetWvCasStatusMessage(WvCasStatus status);
// Crypto mode for encryption / decryption. ENUM value should be consistent with // Crypto mode for encryption / decryption. ENUM value should be consistent with
// https://docs.google.com/document/d/1A5vflf8tbKyUheV-xsvfxFqB6YyNLNdsGXYx8ZnhjfY/edit#heading=h.ej4ts3lifoio // ECM V2 definition. Largest supported value for this CryptoMode ENUM is 15.
enum class CryptoMode : int { enum class CryptoMode : int {
kInvalid = -1,
kAesCbc = 0, kAesCbc = 0,
kAesCtr = 1, kAesCtr = 1,
kDvbCsa2 = 2, kDvbCsa2 = 2,
kDvbCsa3 = 3,
kAesOfb = 4,
kAesScte = 5,
}; };
enum class ScramblingLevel : int { kPES = 0, kTS = 1 };
// Returns false if mode is not a valid CryptoMode. // Returns false if mode is not a valid CryptoMode.
bool CryptoModeToString(CryptoMode mode, std::string* str); bool CryptoModeToString(CryptoMode mode, std::string* str);
// Returns false if str is not a valid CryptoMode. // Returns false if str is not a valid CryptoMode.
bool StringToCryptoMode(const std::string& str, CryptoMode* mode); bool StringToCryptoMode(const std::string& str, CryptoMode* mode);
// Returns false if mode is not a valid ScramblingLevel.
bool ScramblingLevelToString(ScramblingLevel mode, std::string* str);
// Returns false if str is not a valid ScramblingLevel.
bool StringToScramblingLevel(const std::string& str, ScramblingLevel* mode);
struct WvCasEncryptionRequest { struct WvCasEncryptionRequest {
std::string content_id; std::string content_id;
std::string provider; std::string provider;
@@ -111,7 +123,7 @@ struct WvCasEncryptionResponse {
// This request JSON can be later put into the 'request' field of a signed // This request JSON can be later put into the 'request' field of a signed
// request JSON message. // request JSON message.
// And that signed JSON message can be sent to Widevine license server for // And that signed JSON message can be sent to Widevine license server for
// aquiring entitlement keys. // acquiring entitlement keys.
WvCasStatus CreateWvCasEncryptionRequestJson( WvCasStatus CreateWvCasEncryptionRequestJson(
const WvCasEncryptionRequest& request, std::string* request_json); const WvCasEncryptionRequest& request, std::string* request_json);