(1) Change wv_cas_ecm to allow 16 bytes of content_iv

(2) Remove "wrapping_iv" parameters from wv_cas_ecm
(3) Internally derive "wrapping_iv"s and "key_id"s
(4) Add an example binary for demo the usage of wv_cas_ecm

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=218209010
This commit is contained in:
Fang Yu
2018-10-22 12:06:50 -07:00
parent fcdd9fa38c
commit 947b950d95
9 changed files with 185 additions and 131 deletions

View File

@@ -30,6 +30,9 @@ const size_t kSigningKeySizeBytes = 32;
const char kIvMasterKey[] = "1234567890123456"; const char kIvMasterKey[] = "1234567890123456";
const char kIvLabel[] = "IV_ENCRYPTION"; const char kIvLabel[] = "IV_ENCRYPTION";
const int kIvSizeBits = 128; const int kIvSizeBits = 128;
const char kKeyIdMasterKey[] = "0123456789abcdef";
const char kKeyIdLabel[] = "KEY_ID_ENCRYPTION";
const int kKeyIdSizeBits = 128;
const char kGroupKeyLabel[] = "GROUP_ENCRYPTION"; const char kGroupKeyLabel[] = "GROUP_ENCRYPTION";
// TODO(user): This is a temporary key for development. Replace this with // TODO(user): This is a temporary key for development. Replace this with
// a real group master key in keystore. // a real group master key in keystore.
@@ -137,6 +140,11 @@ std::string DeriveIv(absl::string_view context) {
return DeriveKey(kIvMasterKey, kIvLabel, context, kIvSizeBits); return DeriveKey(kIvMasterKey, kIvLabel, context, kIvSizeBits);
} }
// Derives a key ID from the provided info.
std::string DeriveKeyId(absl::string_view context) {
return DeriveKey(kKeyIdMasterKey, kKeyIdLabel, context, kKeyIdSizeBits);
}
std::string DeriveGroupSessionKey(absl::string_view context, std::string DeriveGroupSessionKey(absl::string_view context,
const uint32_t size_bits) { const uint32_t size_bits) {
return DeriveKey(kPhonyGroupMasterKey, kGroupKeyLabel, context, size_bits); return DeriveKey(kPhonyGroupMasterKey, kGroupKeyLabel, context, size_bits);

View File

@@ -49,6 +49,9 @@ std::string DeriveKey(absl::string_view key, absl::string_view label,
// Derives an IV from the provided |context|. // Derives an IV from the provided |context|.
std::string DeriveIv(absl::string_view context); std::string DeriveIv(absl::string_view context);
// Derives a key ID from the provided |context|.
std::string DeriveKeyId(absl::string_view context);
// Helper function to derive a key using the group master key and context. // Helper function to derive a key using the group master key and context.
std::string DeriveGroupSessionKey(absl::string_view context, const uint32_t size_bits); std::string DeriveGroupSessionKey(absl::string_view context, const uint32_t size_bits);

View File

@@ -198,6 +198,21 @@ TEST(CryptoUtilTest, DeriveIv) {
} }
} }
TEST(CryptoUtilTest, DeriveKeyId) {
// First value in the pair is the context, second value is the expected id.
std::pair<std::string, std::string> context_id_pairs[] = {
{"1234567890123456", "a3c4a8c0d0e24e96f38f492254186a9d"},
{"0987654321098765", "084fc6bece9688ccce6b1672d9b47e22"}};
for (const auto& context_id_pair : context_id_pairs) {
SCOPED_TRACE(absl::StrCat("test case:", context_id_pair.first));
EXPECT_EQ(context_id_pair.second,
absl::BytesToHexString(DeriveKeyId(context_id_pair.first)));
// Repeat same call to verify derivied result is repeatable.
EXPECT_EQ(context_id_pair.second,
absl::BytesToHexString(DeriveKeyId(context_id_pair.first)));
}
}
TEST(CryptoUtilTest, Verify4CCEncryptionIDFromBadString) { TEST(CryptoUtilTest, Verify4CCEncryptionIDFromBadString) {
uint32_t cc_code; uint32_t cc_code;
ASSERT_FALSE(FourCCEncryptionSchemeIDFromString("garbage", &cc_code)); ASSERT_FALSE(FourCCEncryptionSchemeIDFromString("garbage", &cc_code));

View File

@@ -16,7 +16,9 @@ package(
filegroup( filegroup(
name = "binary_release_files", name = "binary_release_files",
srcs = [ srcs = [
"wv_cas_ecm_example.cc",
":simulcrypt_client", ":simulcrypt_client",
":wv_cas_ecm_example",
], ],
) )
@@ -40,3 +42,14 @@ cc_library(
"//base", "//base",
], ],
) )
cc_binary(
name = "wv_cas_ecm_example",
srcs = ["wv_cas_ecm_example.cc"],
deps = [
"//base",
"@abseil_repo//absl/strings",
"//util:status",
"//media_cas_packager_sdk/public:wv_cas_ecm",
],
)

View File

@@ -0,0 +1,55 @@
////////////////////////////////////////////////////////////////////////////////
// Copyright 2018 Google LLC.
//
// This software is licensed under the terms defined in the Widevine Master
// License Agreement. For a copy of this agreement, please contact
// widevine-licensing@google.com.
////////////////////////////////////////////////////////////////////////////////
// Example of how to use the wv_cas_ecm library.
#include <string>
#include "gflags/gflags.h"
#include "glog/logging.h"
#include "absl/strings/escaping.h"
#include "absl/strings/str_cat.h"
#include "util/status.h"
#include "media_cas_packager_sdk/public/wv_cas_ecm.h"
const char kEvenKey[] = "even_content_key"; // 16 bytes
const char kEvenContentIv8Bytes[] = "evencont"; // 8 bytes
const char kOddKey[] = "odd_content_key."; // 16 bytes
const char kOddContentIv8Bytes[] = "oddcont."; // 8 bytes
const char kEntitlementKeyId[] = "ent_key_id......"; // 16 bytes
const char kEntitlementKey[] = "entitlement_key................."; // 32 bytes
int main(int argc, char **argv) {
gflags::ParseCommandLineFlags(&argc, &argv, true);
widevine::cas::WvCasEcm wv_cas_ecm;
auto status = wv_cas_ecm.Initialize(/* content_iv_size= */ 16,
/* key_rotation_enabled= */ true,
/* crypto_mode= */ 1);
if (!status.ok()) {
LOG(FATAL) << "Failed to initialize WV CAS ECM, error: " << status;
}
std::string ecm;
status = wv_cas_ecm.GenerateEcm(
/* even_key= */ kEvenKey,
/* even_content_iv= */
absl::StrCat(kEvenContentIv8Bytes, kEvenContentIv8Bytes),
/* odd_key= */ kOddKey,
/* odd_content_iv= */
absl::StrCat(kOddContentIv8Bytes, kOddContentIv8Bytes),
/* entitlement_key_id= */ kEntitlementKeyId,
/* entitlement_key= */ kEntitlementKey, &ecm);
if (!status.ok()) {
LOG(FATAL) << "Failed to generate WV CAS ECM, error: " << status;
} else {
LOG(INFO) << "Generated WV CAS ECM (in hex): "
<< absl::BytesToHexString(ecm);
}
return 0;
}

View File

@@ -65,6 +65,7 @@ cc_library(
"@abseil_repo//absl/memory", "@abseil_repo//absl/memory",
"@abseil_repo//absl/strings", "@abseil_repo//absl/strings",
"//util:status", "//util:status",
"//common:crypto_util",
"//example:constants", "//example:constants",
"//media_cas_packager_sdk/internal:ecm", "//media_cas_packager_sdk/internal:ecm",
"//media_cas_packager_sdk/internal:ecm_generator", "//media_cas_packager_sdk/internal:ecm_generator",
@@ -80,6 +81,6 @@ cc_test(
deps = [ deps = [
":wv_cas_ecm", ":wv_cas_ecm",
"//testing:gunit_main", "//testing:gunit_main",
"//util:status", "@abseil_repo//absl/strings",
], ],
) )

View File

@@ -18,6 +18,7 @@
#include "absl/memory/memory.h" #include "absl/memory/memory.h"
#include "absl/strings/str_cat.h" #include "absl/strings/str_cat.h"
#include "util/status.h" #include "util/status.h"
#include "common/crypto_util.h"
#include "example/constants.h" #include "example/constants.h"
#include "media_cas_packager_sdk/internal/ecm.h" #include "media_cas_packager_sdk/internal/ecm.h"
#include "media_cas_packager_sdk/internal/ecm_generator.h" #include "media_cas_packager_sdk/internal/ecm_generator.h"
@@ -28,8 +29,6 @@ namespace widevine {
namespace cas { namespace cas {
namespace { namespace {
static constexpr size_t kContentIvSizeBytes8 = 8;
static constexpr size_t kWrappedKeyIvSizeBytes = 16;
static constexpr size_t kCryptoModeCbc = 0; static constexpr size_t kCryptoModeCbc = 0;
static constexpr size_t kCryptoModeCtr = 1; static constexpr size_t kCryptoModeCtr = 1;
@@ -51,11 +50,14 @@ util::Status WvCasEcm::Initialize(int content_iv_size,
util::error::INTERNAL, util::error::INTERNAL,
"Cannot initialize an instance of WvCasEcm more than once"); "Cannot initialize an instance of WvCasEcm more than once");
} }
if (content_iv_size != kContentIvSizeBytes8) { if (content_iv_size == 8) {
ecm_init_params_.content_iv_size = kIvSize8;
} else if (content_iv_size == 16) {
ecm_init_params_.content_iv_size = kIvSize16;
} else {
return util::Status(util::error::INVALID_ARGUMENT, return util::Status(util::error::INVALID_ARGUMENT,
"Only support content_iv_size being 8 now"); "Only support content_iv_size being 8 now");
} }
ecm_init_params_.content_iv_size = kIvSize8;
ecm_init_params_.key_rotation_enabled = key_rotation_enabled; ecm_init_params_.key_rotation_enabled = key_rotation_enabled;
if (crypto_mode != kCryptoModeCtr) { if (crypto_mode != kCryptoModeCtr) {
return util::Status(util::error::INVALID_ARGUMENT, return util::Status(util::error::INVALID_ARGUMENT,
@@ -74,10 +76,9 @@ util::Status WvCasEcm::Initialize(int content_iv_size,
} }
util::Status WvCasEcm::GenerateEcm(const std::string& even_key, util::Status WvCasEcm::GenerateEcm(const std::string& even_key,
const std::string& even_wrapping_iv,
const std::string& even_content_iv, const std::string& even_content_iv,
const std::string& odd_key, const std::string& odd_key,
const std::string& odd_wrapping_iv,
const std::string& odd_content_iv, const std::string& odd_content_iv,
const std::string& entitlement_key_id, const std::string& entitlement_key_id,
const std::string& entitlement_key, std::string* ecm) { const std::string& entitlement_key, std::string* ecm) {
@@ -91,11 +92,6 @@ util::Status WvCasEcm::GenerateEcm(const std::string& even_key,
"Please call GenerateSingleKeyEcm() instead when key " "Please call GenerateSingleKeyEcm() instead when key "
"rotation is disabled"); "rotation is disabled");
} }
if (even_wrapping_iv.size() != kWrappedKeyIvSizeBytes ||
odd_wrapping_iv.size() != kWrappedKeyIvSizeBytes) {
return util::Status(util::error::INVALID_ARGUMENT,
"Size of wrapping IV is incorrect");
}
if (even_content_iv.size() != if (even_content_iv.size() !=
EcmIvSizeToInt(ecm_init_params_.content_iv_size) || EcmIvSizeToInt(ecm_init_params_.content_iv_size) ||
odd_content_iv.size() != odd_content_iv.size() !=
@@ -143,16 +139,14 @@ util::Status WvCasEcm::GenerateEcm(const std::string& even_key,
// Add even entitlement key. // Add even entitlement key.
ecm_param.key_params.emplace_back(); ecm_param.key_params.emplace_back();
ecm_param.key_params[0].key_data = even_key; ecm_param.key_params[0].key_data = even_key;
ecm_param.key_params[0].wrapped_key_iv = even_wrapping_iv; ecm_param.key_params[0].wrapped_key_iv = crypto_util::DeriveIv(even_key);
// Per 1:1 with hali@ just use entitlement_key_id for key_id here. ecm_param.key_params[0].key_id = crypto_util::DeriveKeyId(even_key);
// TODO(user): Follow up with jfore@ why we need key_id in the ECM.
ecm_param.key_params[0].key_id = entitlement_key_id;
ecm_param.key_params[0].content_ivs.push_back(even_content_iv); ecm_param.key_params[0].content_ivs.push_back(even_content_iv);
// Add odd entitlement key. // Add odd entitlement key.
ecm_param.key_params.emplace_back(); ecm_param.key_params.emplace_back();
ecm_param.key_params[1].key_data = odd_key; ecm_param.key_params[1].key_data = odd_key;
ecm_param.key_params[1].wrapped_key_iv = odd_wrapping_iv; ecm_param.key_params[1].wrapped_key_iv = crypto_util::DeriveIv(odd_key);
ecm_param.key_params[1].key_id = entitlement_key_id; ecm_param.key_params[1].key_id = crypto_util::DeriveKeyId(odd_key);
ecm_param.key_params[1].content_ivs.push_back(odd_content_iv); ecm_param.key_params[1].content_ivs.push_back(odd_content_iv);
*ecm = ecm_generator.GenerateEcm(ecm_param); *ecm = ecm_generator.GenerateEcm(ecm_param);
@@ -160,7 +154,6 @@ util::Status WvCasEcm::GenerateEcm(const std::string& even_key,
} }
util::Status WvCasEcm::GenerateSingleKeyEcm(const std::string& even_key, util::Status WvCasEcm::GenerateSingleKeyEcm(const std::string& even_key,
const std::string& even_wrapping_iv,
const std::string& even_content_iv, const std::string& even_content_iv,
const std::string& entitlement_key_id, const std::string& entitlement_key_id,
const std::string& entitlement_key, const std::string& entitlement_key,
@@ -175,10 +168,6 @@ util::Status WvCasEcm::GenerateSingleKeyEcm(const std::string& even_key,
util::error::INTERNAL, util::error::INTERNAL,
"Please call GenerateEcm() instead when key rotation is enabled"); "Please call GenerateEcm() instead when key rotation is enabled");
} }
if (even_wrapping_iv.size() != kWrappedKeyIvSizeBytes) {
return util::Status(util::error::INVALID_ARGUMENT,
"Size of wrapping IV is incorrect");
}
if (even_content_iv.size() != if (even_content_iv.size() !=
EcmIvSizeToInt(ecm_init_params_.content_iv_size)) { EcmIvSizeToInt(ecm_init_params_.content_iv_size)) {
return util::Status(util::error::INVALID_ARGUMENT, return util::Status(util::error::INVALID_ARGUMENT,
@@ -224,8 +213,8 @@ util::Status WvCasEcm::GenerateSingleKeyEcm(const std::string& even_key,
// Add even entitlement key. // Add even entitlement key.
ecm_param.key_params.emplace_back(); ecm_param.key_params.emplace_back();
ecm_param.key_params[0].key_data = even_key; ecm_param.key_params[0].key_data = even_key;
ecm_param.key_params[0].wrapped_key_iv = even_wrapping_iv; ecm_param.key_params[0].wrapped_key_iv = crypto_util::DeriveIv(even_key);
ecm_param.key_params[0].key_id = entitlement_key_id; ecm_param.key_params[0].key_id = crypto_util::DeriveKeyId(even_key);
ecm_param.key_params[0].content_ivs.push_back(even_content_iv); ecm_param.key_params[0].content_ivs.push_back(even_content_iv);
*ecm = ecm_generator.GenerateEcm(ecm_param); *ecm = ecm_generator.GenerateEcm(ecm_param);

View File

@@ -38,8 +38,9 @@ class WvCasEcm {
// //
// Args: // Args:
// - |content_iv_size| iv size in bytes for encrypting the content, // - |content_iv_size| iv size in bytes for encrypting the content,
// only support 8 bytes now // only support 8 bytes or 16 bytes
// TODO(user): Double-check with jfore@ regarding only support 8 bytes. // When using 8 bytes content_iv, we assume additional 8 bytes of '\x00' are
// appended to the iv to form a 16 bytes AES IV when content is encrypted.
// - |key_rotation_enabled| whether key rotation is enabled, // - |key_rotation_enabled| whether key rotation is enabled,
// if this is 'true' only subsequent call to GenerateEcm will be allowed, // if this is 'true' only subsequent call to GenerateEcm will be allowed,
// if this is 'false' only subsequent call to GenerateSingleKeyEcm will // if this is 'false' only subsequent call to GenerateSingleKeyEcm will
@@ -47,7 +48,6 @@ class WvCasEcm {
// - |crypto_mode| crypto mode for encrypting content, // - |crypto_mode| crypto mode for encrypting content,
// kCryptoModeCbc = 0, kCryptoModeCtr = 1 // kCryptoModeCbc = 0, kCryptoModeCtr = 1
// only CTR is supported by Widevine CAS plugin for now // only CTR is supported by Widevine CAS plugin for now
// TODO(user): Check with jfore@ regarding supporting kCryptoModeCbc.
// //
// Returns: // Returns:
// - A status indicating whether there was any error during initialization // - A status indicating whether there was any error during initialization
@@ -62,10 +62,8 @@ class WvCasEcm {
// //
// Args: // Args:
// - |even_key| clear even content key // - |even_key| clear even content key
// - |even_wrapping_iv| iv used when encrypting |even_key| in the ECM
// - |even_content_iv| iv used along with |even_key| for encrypting content // - |even_content_iv| iv used along with |even_key| for encrypting content
// - |odd_key| clear odd content key // - |odd_key| clear odd content key
// - |odd_wrapping_iv| iv used when encrypting |odd_key| in the ECM
// - |odd_content_iv| iv used along with |odd_key| for encrypting content // - |odd_content_iv| iv used along with |odd_key| for encrypting content
// - |entitlement_key_id| key id for |entitlement_key| // - |entitlement_key_id| key id for |entitlement_key|
// - |entitlement_key| entitlement key used to encrypt even and odd keys // - |entitlement_key| entitlement key used to encrypt even and odd keys
@@ -77,15 +75,10 @@ class WvCasEcm {
// Note: // Note:
// - The same |entitlement_key| will be used to encrypt both |even_key| // - The same |entitlement_key| will be used to encrypt both |even_key|
// and |odd_key| in the ECM // and |odd_key| in the ECM
// - Currently, we only allow |even_content_iv| and |odd_content_iv| // - Size of |even_content_iv| and |odd_content_iv| must match
// to be of size 8 bytes, so we assume the encryptor would append suffix // |content_iv_size| set during initialization
// {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'}
// to |even_content_iv| and |odd_content_iv| to obtain a 16 bytes IV
// before encrypting the content
util::Status GenerateEcm(const std::string& even_key, util::Status GenerateEcm(const std::string& even_key,
const std::string& even_wrapping_iv,
const std::string& even_content_iv, const std::string& odd_key, const std::string& even_content_iv, const std::string& odd_key,
const std::string& odd_wrapping_iv,
const std::string& odd_content_iv, const std::string& odd_content_iv,
const std::string& entitlement_key_id, const std::string& entitlement_key_id,
const std::string& entitlement_key, std::string* ecm); const std::string& entitlement_key, std::string* ecm);
@@ -95,7 +88,6 @@ class WvCasEcm {
// //
// Args: // Args:
// - |even_key| clear even content key // - |even_key| clear even content key
// - |even_wrapping_iv| iv used when encrypting |even_key| in the ECM
// - |even_content_iv| iv used along with |even_key| for encrypting content // - |even_content_iv| iv used along with |even_key| for encrypting content
// - |entitlement_key_id| key id for |entitlement_key| // - |entitlement_key_id| key id for |entitlement_key|
// - |entitlement_key| entitlement key used to encrypt even key // - |entitlement_key| entitlement key used to encrypt even key
@@ -105,14 +97,9 @@ class WvCasEcm {
// - A status indicating whether there was any error during processing // - A status indicating whether there was any error during processing
// //
// Note: // Note:
// // - Size of |even_content_iv| and |odd_content_iv| must match
// - Currently, we only allow |even_content_iv| // |content_iv_size| set during initialization
// to be of size 8 bytes, so we assume the encryptor would append suffix
// {'\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00', '\x00'}
// to |even_content_iv| to obtain a 16 bytes IV
// before encrypting the content
util::Status GenerateSingleKeyEcm(const std::string& even_key, util::Status GenerateSingleKeyEcm(const std::string& even_key,
const std::string& even_wrapping_iv,
const std::string& even_content_iv, const std::string& even_content_iv,
const std::string& entitlement_key_id, const std::string& entitlement_key_id,
const std::string& entitlement_key, std::string* ecm); const std::string& entitlement_key, std::string* ecm);

View File

@@ -9,6 +9,7 @@
#include "media_cas_packager_sdk/public/wv_cas_ecm.h" #include "media_cas_packager_sdk/public/wv_cas_ecm.h"
#include "testing/gmock.h" #include "testing/gmock.h"
#include "testing/gunit.h" #include "testing/gunit.h"
#include "absl/strings/escaping.h"
using ::testing::Test; using ::testing::Test;
@@ -16,11 +17,9 @@ namespace widevine {
namespace cas { namespace cas {
const char kEvenKey[] = "even_content_key"; // 16 bytes const char kEvenKey[] = "even_content_key"; // 16 bytes
const char kEvenWrappingIv[] = "even_wrap_iv...."; // 16 bytes const char kEvenContentIv8Bytes[] = "evencont"; // 8 bytes
const char kEvenContentIv[] = "evencont"; // 8 bytes
const char kOddKey[] = "odd_content_key."; // 16 bytes const char kOddKey[] = "odd_content_key."; // 16 bytes
const char kOddWrappingIv[] = "odd_wrap_iv....."; // 16 bytes const char kOddContentIv8Bytes[] = "oddcont."; // 8 bytes
const char kOddContentIv[] = "oddcont."; // 8 bytes
const char kEntitlementKeyId[] = "ent_key_id......"; // 16 bytes const char kEntitlementKeyId[] = "ent_key_id......"; // 16 bytes
const char kEntitlementKey[] = "entitlement_key................."; // 32 bytes const char kEntitlementKey[] = "entitlement_key................."; // 32 bytes
@@ -46,7 +45,7 @@ TEST_F(WvCasEcmTest, InitializeContentIvSize) {
EXPECT_EQ( EXPECT_EQ(
util::error::INVALID_ARGUMENT, util::error::INVALID_ARGUMENT,
wv_cas_ecm_ wv_cas_ecm_
.Initialize(/* content_iv_size= */ 16, .Initialize(/* content_iv_size= */ 4,
/* key_rotation_enabled= */ true, /* crypto_mode= */ 1) /* key_rotation_enabled= */ true, /* crypto_mode= */ 1)
.error_code()); .error_code());
} }
@@ -66,7 +65,7 @@ TEST_F(WvCasEcmTest, InitializeKeyRotationEnabled) {
/* crypto_mode= */ 1)); /* crypto_mode= */ 1));
std::string actual_ecm; std::string actual_ecm;
EXPECT_EQ(util::error::INTERNAL, EXPECT_EQ(util::error::INTERNAL,
wv_cas_ecm_.GenerateSingleKeyEcm("", "", "", "", "", &actual_ecm) wv_cas_ecm_.GenerateSingleKeyEcm("", "", "", "", &actual_ecm)
.error_code()); .error_code());
} }
@@ -76,26 +75,7 @@ TEST_F(WvCasEcmTest, InitializeKeyRotationDisabled) {
/* crypto_mode= */ 1)); /* crypto_mode= */ 1));
std::string actual_ecm; std::string actual_ecm;
EXPECT_EQ(util::error::INTERNAL, EXPECT_EQ(util::error::INTERNAL,
wv_cas_ecm_.GenerateEcm("", "", "", "", "", "", "", "", &actual_ecm) wv_cas_ecm_.GenerateEcm("", "", "", "", "", "", &actual_ecm)
.error_code());
}
TEST_F(WvCasEcmTest, GenerateEcmInvalidWrappingIv) {
EXPECT_OK(wv_cas_ecm_.Initialize(/* content_iv_size= */ 8,
/* key_rotation_enabled= */ true,
/* crypto_mode= */ 1));
std::string actual_ecm;
EXPECT_EQ(util::error::INVALID_ARGUMENT,
wv_cas_ecm_
.GenerateEcm(
/* even_key= */ kEvenKey,
/* even_wrapping_iv= */ kEvenWrappingIv,
/* even_content_iv= */ kEvenContentIv,
/* odd_key= */ kOddKey,
/* odd_wrapping_iv= */ "12345678",
/* odd_content_iv= */ kOddContentIv,
/* entitlement_key_id= */ kEntitlementKeyId,
/* entitlement_key= */ kEntitlementKey, &actual_ecm)
.error_code()); .error_code());
} }
@@ -108,32 +88,14 @@ TEST_F(WvCasEcmTest, GenerateEcmInvalidContentIv) {
wv_cas_ecm_ wv_cas_ecm_
.GenerateEcm( .GenerateEcm(
/* even_key= */ kEvenKey, /* even_key= */ kEvenKey,
/* even_wrapping_iv= */ kEvenWrappingIv, /* even_content_iv= */ kEvenContentIv8Bytes,
/* even_content_iv= */ kEvenContentIv,
/* odd_key= */ kOddKey, /* odd_key= */ kOddKey,
/* odd_wrapping_iv= */ kOddWrappingIv,
/* odd_content_iv= */ "123456789", /* odd_content_iv= */ "123456789",
/* entitlement_key_id= */ kEntitlementKeyId, /* entitlement_key_id= */ kEntitlementKeyId,
/* entitlement_key= */ kEntitlementKey, &actual_ecm) /* entitlement_key= */ kEntitlementKey, &actual_ecm)
.error_code()); .error_code());
} }
TEST_F(WvCasEcmTest, GenerateSingleKeyEcmInvalidWrappingIv) {
EXPECT_OK(wv_cas_ecm_.Initialize(/* content_iv_size= */ 8,
/* key_rotation_enabled= */ false,
/* crypto_mode= */ 1));
std::string actual_ecm;
EXPECT_EQ(util::error::INVALID_ARGUMENT,
wv_cas_ecm_
.GenerateSingleKeyEcm(
/* even_key= */ kEvenKey,
/* even_wrapping_iv= */ "12345678",
/* even_content_iv= */ kEvenContentIv,
/* entitlement_key_id= */ kEntitlementKeyId,
/* entitlement_key= */ kEntitlementKey, &actual_ecm)
.error_code());
}
TEST_F(WvCasEcmTest, GenerateSingleKeyEcmInvalidContentIv) { TEST_F(WvCasEcmTest, GenerateSingleKeyEcmInvalidContentIv) {
EXPECT_OK(wv_cas_ecm_.Initialize(/* content_iv_size= */ 8, EXPECT_OK(wv_cas_ecm_.Initialize(/* content_iv_size= */ 8,
/* key_rotation_enabled= */ false, /* key_rotation_enabled= */ false,
@@ -143,14 +105,13 @@ TEST_F(WvCasEcmTest, GenerateSingleKeyEcmInvalidContentIv) {
wv_cas_ecm_ wv_cas_ecm_
.GenerateSingleKeyEcm( .GenerateSingleKeyEcm(
/* even_key= */ kEvenKey, /* even_key= */ kEvenKey,
/* even_wrapping_iv= */ kEvenWrappingIv,
/* even_content_iv= */ "1234", /* even_content_iv= */ "1234",
/* entitlement_key_id= */ kEntitlementKeyId, /* entitlement_key_id= */ kEntitlementKeyId,
/* entitlement_key= */ kEntitlementKey, &actual_ecm) /* entitlement_key= */ kEntitlementKey, &actual_ecm)
.error_code()); .error_code());
} }
TEST_F(WvCasEcmTest, GenerateEcmSuccess) { TEST_F(WvCasEcmTest, GenerateEcm8BytesContentIvSuccess) {
EXPECT_OK(wv_cas_ecm_.Initialize(/* content_iv_size= */ 8, EXPECT_OK(wv_cas_ecm_.Initialize(/* content_iv_size= */ 8,
/* key_rotation_enabled= */ true, /* key_rotation_enabled= */ true,
/* crypto_mode= */ 1)); /* crypto_mode= */ 1));
@@ -158,37 +119,22 @@ TEST_F(WvCasEcmTest, GenerateEcmSuccess) {
std::string actual_ecm; std::string actual_ecm;
EXPECT_OK(wv_cas_ecm_.GenerateEcm( EXPECT_OK(wv_cas_ecm_.GenerateEcm(
/* even_key= */ kEvenKey, /* even_key= */ kEvenKey,
/* even_wrapping_iv= */ kEvenWrappingIv, /* even_content_iv= */ kEvenContentIv8Bytes,
/* even_content_iv= */ kEvenContentIv,
/* odd_key= */ kOddKey, /* odd_key= */ kOddKey,
/* odd_wrapping_iv= */ kOddWrappingIv, /* odd_content_iv= */ kOddContentIv8Bytes,
/* odd_content_iv= */ kOddContentIv,
/* entitlement_key_id= */ kEntitlementKeyId, /* entitlement_key_id= */ kEntitlementKeyId,
/* entitlement_key= */ kEntitlementKey, &actual_ecm)); /* entitlement_key= */ kEntitlementKey, &actual_ecm));
// 149 bytes. EXPECT_EQ(
char expected_ecm[] = { "4ad4010380656e745f6b65795f69642e2e2e2e2e2ea5693deeba52b4cb27e7021eefa2f8"
'\x4a', '\xd4', '\x1', '\x3', '\x80', '\x65', '\x6e', '\x74', '\x5f', "c2b25f7d48e60627208f4ecca00703aa2467f28b214546a42320e3fa49f936369c657665"
'\x6b', '\x65', '\x79', '\x5f', '\x69', '\x64', '\x2e', '\x2e', '\x2e', "6e636f6e74656e745f6b65795f69642e2e2e2e2e2e0700509b67763b3f1c356bc1e1dc8b"
'\x2e', '\x2e', '\x2e', '\x65', '\x6e', '\x74', '\x5f', '\x6b', '\x65', "ac99a1e2f95c37d9183cbb96582f3a05fdbe29925c37c6c6a45eb552b5ddf87f8a6f6464"
'\x79', '\x5f', '\x69', '\x64', '\x2e', '\x2e', '\x2e', '\x2e', '\x2e', "636f6e742e",
'\x2e', '\x1d', '\xb6', '\x2f', '\x14', '\x1f', '\xa3', '\xd6', '\x68', absl::BytesToHexString(actual_ecm));
'\xd8', '\x79', '\xfe', '\x69', '\x5f', '\x3c', '\xad', '\x8b', '\x65',
'\x76', '\x65', '\x6e', '\x5f', '\x77', '\x72', '\x61', '\x70', '\x5f',
'\x69', '\x76', '\x2e', '\x2e', '\x2e', '\x2e', '\x65', '\x76', '\x65',
'\x6e', '\x63', '\x6f', '\x6e', '\x74', '\x65', '\x6e', '\x74', '\x5f',
'\x6b', '\x65', '\x79', '\x5f', '\x69', '\x64', '\x2e', '\x2e', '\x2e',
'\x2e', '\x2e', '\x2e', '\x65', '\x6e', '\x74', '\x5f', '\x6b', '\x65',
'\x79', '\x5f', '\x69', '\x64', '\x2e', '\x2e', '\x2e', '\x2e', '\x2e',
'\x2e', '\xcb', '\xb2', '\x4d', '\x7d', '\xd1', '\x27', '\x97', '\xd3',
'\xf7', '\xe0', '\x11', '\x93', '\xa3', '\x43', '\xd9', '\x55', '\x6f',
'\x64', '\x64', '\x5f', '\x77', '\x72', '\x61', '\x70', '\x5f', '\x69',
'\x76', '\x2e', '\x2e', '\x2e', '\x2e', '\x2e', '\x6f', '\x64', '\x64',
'\x63', '\x6f', '\x6e', '\x74', '\x2e'};
EXPECT_EQ(std::string(expected_ecm, sizeof(expected_ecm)), actual_ecm);
} }
TEST_F(WvCasEcmTest, GenerateSingleKeyEcmSuccess) { TEST_F(WvCasEcmTest, GenerateSingleKeyEcm8BytesContentIvSuccess) {
EXPECT_OK(wv_cas_ecm_.Initialize(/* content_iv_size= */ 8, EXPECT_OK(wv_cas_ecm_.Initialize(/* content_iv_size= */ 8,
/* key_rotation_enabled= */ false, /* key_rotation_enabled= */ false,
/* crypto_mode= */ 1)); /* crypto_mode= */ 1));
@@ -196,23 +142,60 @@ TEST_F(WvCasEcmTest, GenerateSingleKeyEcmSuccess) {
std::string actual_ecm; std::string actual_ecm;
EXPECT_OK(wv_cas_ecm_.GenerateSingleKeyEcm( EXPECT_OK(wv_cas_ecm_.GenerateSingleKeyEcm(
/* even_key= */ kEvenKey, /* even_key= */ kEvenKey,
/* even_wrapping_iv= */ kEvenWrappingIv, /* even_content_iv= */ kEvenContentIv8Bytes,
/* even_content_iv= */ kEvenContentIv,
/* entitlement_key_id= */ kEntitlementKeyId, /* entitlement_key_id= */ kEntitlementKeyId,
/* entitlement_key= */ kEntitlementKey, &actual_ecm)); /* entitlement_key= */ kEntitlementKey, &actual_ecm));
// 77 bytes. EXPECT_EQ(
char expected_ecm[] = { "4ad4010280656e745f6b65795f69642e2e2e2e2e2ea5693deeba52b4cb27e7021eefa2f8"
'\x4a', '\xd4', '\x1', '\x2', '\x80', '\x65', '\x6e', '\x74', '\x5f', "c2b25f7d48e60627208f4ecca00703aa2467f28b214546a42320e3fa49f936369c657665"
'\x6b', '\x65', '\x79', '\x5f', '\x69', '\x64', '\x2e', '\x2e', '\x2e', "6e636f6e74",
'\x2e', '\x2e', '\x2e', '\x65', '\x6e', '\x74', '\x5f', '\x6b', '\x65', absl::BytesToHexString(actual_ecm));
'\x79', '\x5f', '\x69', '\x64', '\x2e', '\x2e', '\x2e', '\x2e', '\x2e', }
'\x2e', '\x1d', '\xb6', '\x2f', '\x14', '\x1f', '\xa3', '\xd6', '\x68',
'\xd8', '\x79', '\xfe', '\x69', '\x5f', '\x3c', '\xad', '\x8b', '\x65', TEST_F(WvCasEcmTest, GenerateEcm16BytesContentIvSuccess) {
'\x76', '\x65', '\x6e', '\x5f', '\x77', '\x72', '\x61', '\x70', '\x5f', EXPECT_OK(wv_cas_ecm_.Initialize(/* content_iv_size= */ 16,
'\x69', '\x76', '\x2e', '\x2e', '\x2e', '\x2e', '\x65', '\x76', '\x65', /* key_rotation_enabled= */ true,
'\x6e', '\x63', '\x6f', '\x6e', '\x74'}; /* crypto_mode= */ 1));
EXPECT_EQ(std::string(expected_ecm, sizeof(expected_ecm)), actual_ecm);
std::string actual_ecm;
EXPECT_OK(wv_cas_ecm_.GenerateEcm(
/* even_key= */ kEvenKey,
/* even_content_iv= */
absl::StrCat(kEvenContentIv8Bytes, kEvenContentIv8Bytes),
/* odd_key= */ kOddKey,
/* odd_content_iv= */
absl::StrCat(kOddContentIv8Bytes, kOddContentIv8Bytes),
/* entitlement_key_id= */ kEntitlementKeyId,
/* entitlement_key= */ kEntitlementKey, &actual_ecm));
EXPECT_EQ(
"4ad40103c0656e745f6b65795f69642e2e2e2e2e2ea5693deeba52b4cb27e7021eefa2f8"
"c2b25f7d48e60627208f4ecca00703aa2467f28b214546a42320e3fa49f936369c657665"
"6e636f6e746576656e636f6e74656e745f6b65795f69642e2e2e2e2e2e0700509b67763b"
"3f1c356bc1e1dc8bac99a1e2f95c37d9183cbb96582f3a05fdbe29925c37c6c6a45eb552"
"b5ddf87f8a6f6464636f6e742e6f6464636f6e742e",
absl::BytesToHexString(actual_ecm));
}
TEST_F(WvCasEcmTest, GenerateSingleKeyEcm16BytesContentIvSuccess) {
EXPECT_OK(wv_cas_ecm_.Initialize(/* content_iv_size= */ 16,
/* key_rotation_enabled= */ false,
/* crypto_mode= */ 1));
std::string actual_ecm;
EXPECT_OK(wv_cas_ecm_.GenerateSingleKeyEcm(
/* even_key= */ kEvenKey,
/* even_content_iv= */
absl::StrCat(kEvenContentIv8Bytes, kEvenContentIv8Bytes),
/* entitlement_key_id= */ kEntitlementKeyId,
/* entitlement_key= */ kEntitlementKey, &actual_ecm));
EXPECT_EQ(
"4ad40102c0656e745f6b65795f69642e2e2e2e2e2ea5693deeba52b4cb27e7021eefa2f8"
"c2b25f7d48e60627208f4ecca00703aa2467f28b214546a42320e3fa49f936369c657665"
"6e636f6e746576656e636f6e74",
absl::BytesToHexString(actual_ecm));
} }
} // namespace cas } // namespace cas