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:
Fang Yu
2018-10-17 15:38:59 -07:00
parent 08829edd17
commit 1547e62481
17 changed files with 703 additions and 38 deletions

View File

@@ -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",
],
)

View File

@@ -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);

View File

@@ -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.

View File

@@ -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;

View File

@@ -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);

View File

@@ -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;

View File

@@ -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;

View File

@@ -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);
}

View File

@@ -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