Implement a set of "Simplified APIs" for ECM generation
------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=217601738
This commit is contained in:
@@ -55,7 +55,6 @@ cc_library(
|
||||
hdrs = ["ecm_generator.h"],
|
||||
deps = [
|
||||
"//base",
|
||||
"@abseil_repo//absl/base:core_headers",
|
||||
"//util:status",
|
||||
"//media_cas_packager_sdk/internal:ecm",
|
||||
],
|
||||
@@ -91,6 +90,7 @@ cc_library(
|
||||
"@abseil_repo//absl/memory",
|
||||
"@abseil_repo//absl/strings",
|
||||
"//util:status",
|
||||
"//example:constants",
|
||||
],
|
||||
)
|
||||
|
||||
|
||||
@@ -299,7 +299,12 @@ util::Status CasEcm::WrapEntitledKeys(
|
||||
for (auto entitled_key : keys) {
|
||||
entitled_key->entitlement_key_id = entitlement_key->key_id;
|
||||
// Wrap key using entitlement key. First generate new IV.
|
||||
CHECK(RandomBytes(kWrappedKeyIvSizeBytes, &entitled_key->wrapped_key_iv));
|
||||
// TODO(user): Do not randomly generate 'wrapped_key_iv' here ever,
|
||||
// enforce the caller of 'ecm generator' to provide it.
|
||||
// And check the provided 'wrapped_key_iv' has valid size.
|
||||
if (entitled_key->wrapped_key_iv.empty()) {
|
||||
CHECK(RandomBytes(kWrappedKeyIvSizeBytes, &entitled_key->wrapped_key_iv));
|
||||
}
|
||||
entitled_key->wrapped_key_value =
|
||||
WrapKey(entitlement_key->key_value, entitled_key->wrapped_key_iv,
|
||||
entitled_key->key_value);
|
||||
|
||||
@@ -75,6 +75,8 @@ struct EcmInitParameters {
|
||||
class CasEcm {
|
||||
public:
|
||||
CasEcm() = default;
|
||||
CasEcm(const CasEcm&) = delete;
|
||||
CasEcm& operator=(const CasEcm&) = delete;
|
||||
virtual ~CasEcm() = default;
|
||||
|
||||
// Perform initialization for a new ECM stream.
|
||||
|
||||
@@ -64,6 +64,7 @@ util::Status CasEcmGenerator::ProcessEcmParameters(
|
||||
EntitledKeyInfo& key = keys->back();
|
||||
key.key_id = ecm_params.key_params[i].key_id;
|
||||
key.key_value = ecm_params.key_params[i].key_data;
|
||||
key.wrapped_key_iv = ecm_params.key_params[i].wrapped_key_iv;
|
||||
key.content_iv = ecm_params.key_params[i].content_ivs[0];
|
||||
}
|
||||
current_key_index_ = 0;
|
||||
|
||||
@@ -59,6 +59,8 @@ struct EcmParameters {
|
||||
class CasEcmGenerator {
|
||||
public:
|
||||
CasEcmGenerator() = default;
|
||||
CasEcmGenerator(const CasEcmGenerator&) = delete;
|
||||
CasEcmGenerator& operator=(const CasEcmGenerator&) = delete;
|
||||
virtual ~CasEcmGenerator() = default;
|
||||
|
||||
virtual std::string GenerateEcm(const EcmParameters& params);
|
||||
|
||||
@@ -203,7 +203,7 @@ TEST_F(CasEcmGeneratorTest, GenerateNoRotation) {
|
||||
EXPECT_EQ(kFakeCasEncryptionResponseKeyId, ecm_string.substr(5, 16));
|
||||
EXPECT_EQ(kEcmKeyIdSingle, ecm_string.substr(21, 16));
|
||||
EXPECT_NE(kEcmWrappedKeySingle, ecm_string.substr(37, 16));
|
||||
EXPECT_NE(kEcmWrappedKeyIvSingle, ecm_string.substr(53, 16));
|
||||
EXPECT_EQ(kEcmWrappedKeyIvSingle, ecm_string.substr(53, 16));
|
||||
// Unwrap key and compare with original.
|
||||
std::string wrapping_key = kFakeCasEncryptionResponseKeyData;
|
||||
std::string wrapping_iv = ecm_string.substr(53, 16);
|
||||
@@ -233,7 +233,7 @@ TEST_F(CasEcmGeneratorTest, Generate2NoRotation) {
|
||||
EXPECT_EQ(kFakeCasEncryptionResponseKeyId, ecm_string.substr(5, 16));
|
||||
EXPECT_EQ(kEcmKeyIdSingle, ecm_string.substr(21, 16));
|
||||
EXPECT_NE(kEcmWrappedKeySingle, ecm_string.substr(37, 16));
|
||||
EXPECT_NE(kEcmWrappedKeyIvSingle, ecm_string.substr(53, 16));
|
||||
EXPECT_EQ(kEcmWrappedKeyIvSingle, ecm_string.substr(53, 16));
|
||||
// Unwrap key and compare with original.
|
||||
std::string wrapping_key = kFakeCasEncryptionResponseKeyData;
|
||||
std::string wrapping_iv = ecm_string.substr(53, 16);
|
||||
@@ -284,12 +284,12 @@ TEST_F(CasEcmGeneratorTest, GenerateSimpleRotation) {
|
||||
EXPECT_EQ(kFakeCasEncryptionResponseKeyId, ecm_string.substr(5, 16));
|
||||
EXPECT_EQ(kEcmKeyIdEven, ecm_string.substr(21, 16));
|
||||
EXPECT_NE(kEcmWrappedKeyEven, ecm_string.substr(37, 16));
|
||||
EXPECT_NE(kEcmWrappedKeyIvEven, ecm_string.substr(53, 16));
|
||||
EXPECT_EQ(kEcmWrappedKeyIvEven, ecm_string.substr(53, 16));
|
||||
EXPECT_EQ(kEcmContentIvEven, ecm_string.substr(69, 8));
|
||||
EXPECT_EQ(kFakeCasEncryptionResponseKeyId, ecm_string.substr(77, 16));
|
||||
EXPECT_EQ(kEcmKeyIdOdd, ecm_string.substr(93, 16));
|
||||
EXPECT_NE(kEcmWrappedKeyOdd, ecm_string.substr(109, 16));
|
||||
EXPECT_NE(kEcmWrappedKeyIvOdd, ecm_string.substr(125, 16));
|
||||
EXPECT_EQ(kEcmWrappedKeyIvOdd, ecm_string.substr(125, 16));
|
||||
EXPECT_EQ(kEcmContentIvOdd, ecm_string.substr(141, 8));
|
||||
// Unwrap even key and compare with original.
|
||||
std::string wrapping_key_even = kFakeCasEncryptionResponseKeyData;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "absl/memory/memory.h"
|
||||
#include "absl/strings/str_cat.h"
|
||||
#include "util/status.h"
|
||||
#include "example/constants.h"
|
||||
#include "media_cas_packager_sdk/internal/ecm_generator.h"
|
||||
#include "media_cas_packager_sdk/internal/ecmg_constants.h"
|
||||
#include "media_cas_packager_sdk/internal/util.h"
|
||||
@@ -28,13 +29,6 @@ namespace cas {
|
||||
|
||||
namespace {
|
||||
|
||||
static const char kDefaultContentId[] = "21140844";
|
||||
static const char kDefaultProvider[] = "widevine";
|
||||
// Size of this IV needs to match ecm_init_params.content_iv_size.
|
||||
static const char kDefaultContentIv[] = {'\x01', '\x01', '\x01', '\x01',
|
||||
'\x01', '\x01', '\x01', '\x01'};
|
||||
static const char kDefaultTrackTypeSd[] = "SD";
|
||||
|
||||
// Local helper function that processes all the parameters in an ECMG message.
|
||||
util::Status ProcessParameters(const char* message, size_t message_length,
|
||||
EcmgParameters* parameters) {
|
||||
@@ -271,7 +265,7 @@ util::Status Ecmg::ProcessCwProvisionMessage(const char* message,
|
||||
ecm_param.key_params[i].key_id = ecm_param.key_params[i].key_data;
|
||||
// TODO(user): MUST have a better way to generate/retrieve content_iv.
|
||||
ecm_param.key_params[i].content_ivs.push_back(
|
||||
std::string(kDefaultContentIv));
|
||||
std::string(kDefaultContentIv8Bytes));
|
||||
}
|
||||
std::string serialized_ecm = ecm_generator.GenerateEcm(ecm_param);
|
||||
std::cout << "serialized_ecm: " << serialized_ecm << std::endl;
|
||||
|
||||
@@ -14,16 +14,6 @@
|
||||
namespace widevine {
|
||||
namespace cas {
|
||||
|
||||
namespace {
|
||||
|
||||
// Key IDs are 16 bytes, keys are 32 bytes.
|
||||
static const char* kKeyId1 = "fake_key_id1....";
|
||||
static const char* kKey1 = "fakefakefakefakefakefakefake1...";
|
||||
static const char* kKeyId2 = "fake_key_id2....";
|
||||
static const char* kKey2 = "fakefakefakefakefakefakefake2...";
|
||||
|
||||
} // namespace
|
||||
|
||||
util::Status FixedKeyFetcher::RequestEntitlementKey(
|
||||
const std::string& request_string, std::string* signed_response_string) {
|
||||
CasEncryptionRequest request;
|
||||
@@ -36,20 +26,20 @@ util::Status FixedKeyFetcher::RequestEntitlementKey(
|
||||
if (request.key_rotation()) {
|
||||
// Add the Even key.
|
||||
auto key = response.add_entitlement_keys();
|
||||
key->set_key_id(kKeyId1);
|
||||
key->set_key(kKey1);
|
||||
key->set_key_id(even_entitlement_key_id_);
|
||||
key->set_key(even_entitlement_key_);
|
||||
key->set_track_type(track_type);
|
||||
key->set_key_slot(CasEncryptionResponse_KeyInfo_KeySlot_EVEN);
|
||||
// Add the Odd key.
|
||||
key = response.add_entitlement_keys();
|
||||
key->set_key_id(kKeyId2);
|
||||
key->set_key(kKey2);
|
||||
key->set_key_id(odd_entitlement_key_id_);
|
||||
key->set_key(odd_entitlement_key_);
|
||||
key->set_track_type(track_type);
|
||||
key->set_key_slot(CasEncryptionResponse_KeyInfo_KeySlot_ODD);
|
||||
} else {
|
||||
auto key = response.add_entitlement_keys();
|
||||
key->set_key_id(kKeyId1);
|
||||
key->set_key(kKey1);
|
||||
key->set_key_id(even_entitlement_key_id_);
|
||||
key->set_key(even_entitlement_key_);
|
||||
key->set_track_type(track_type);
|
||||
key->set_key_slot(CasEncryptionResponse_KeyInfo_KeySlot_SINGLE);
|
||||
}
|
||||
|
||||
@@ -18,7 +18,26 @@ namespace cas {
|
||||
// locally-constructed response that has known (predefined) entitlement keys.
|
||||
class FixedKeyFetcher : public KeyFetcher {
|
||||
public:
|
||||
FixedKeyFetcher() {}
|
||||
// Key IDs are 16 bytes, keys are 32 bytes.
|
||||
// TODO(user): There should be a single entitlement key for both even
|
||||
// and odd keys. Shouldn't have two different types of entitlement keys.
|
||||
FixedKeyFetcher()
|
||||
: even_entitlement_key_id_("fake_key_id1...."),
|
||||
even_entitlement_key_("fakefakefakefakefakefakefake1..."),
|
||||
odd_entitlement_key_id_("fake_key_id2...."),
|
||||
odd_entitlement_key_("fakefakefakefakefakefakefake2...") {}
|
||||
// Explictly provide the key_id and entitlement keys rather than using the
|
||||
// hardcoded default.
|
||||
FixedKeyFetcher(const std::string& even_entitlement_key_id,
|
||||
const std::string& even_entitlement_key,
|
||||
const std::string& odd_entitlement_key_id,
|
||||
const std::string& odd_entitlement_key)
|
||||
: even_entitlement_key_id_(even_entitlement_key_id),
|
||||
even_entitlement_key_(even_entitlement_key),
|
||||
odd_entitlement_key_id_(odd_entitlement_key_id),
|
||||
odd_entitlement_key_(odd_entitlement_key) {}
|
||||
FixedKeyFetcher(const FixedKeyFetcher&) = delete;
|
||||
FixedKeyFetcher& operator=(const FixedKeyFetcher&) = delete;
|
||||
~FixedKeyFetcher() override = default;
|
||||
|
||||
// Get entitlement keys. Process a CasEncryptionRequest message to
|
||||
@@ -32,6 +51,12 @@ class FixedKeyFetcher : public KeyFetcher {
|
||||
// WvCasEcm::ProcessCasEncryptionResponse().
|
||||
util::Status RequestEntitlementKey(const std::string& request_string,
|
||||
std::string* signed_response_string) override;
|
||||
|
||||
private:
|
||||
std::string even_entitlement_key_id_;
|
||||
std::string even_entitlement_key_;
|
||||
std::string odd_entitlement_key_id_;
|
||||
std::string odd_entitlement_key_;
|
||||
};
|
||||
|
||||
} // namespace cas
|
||||
|
||||
Reference in New Issue
Block a user