Move fixed key encryption code to new FixedKeySource.
KeySource is now an abstract class that is implemented in two types WidevineKeySource and FixedKeySource. This also updates fixed key encryption to use v1 PSSH boxes with the common system ID. This also updates the --pssh argument. Now it accepts full PSSH boxes rather than data. Multiple PSSH boxes can be concatenated together. Issue #88 Change-Id: I4bd0290f6d8b965f7d118f075c96e0f267d7e831
This commit is contained in:
parent
e39c3572af
commit
d5cdd00ba1
|
@ -22,7 +22,11 @@ DEFINE_string(iv,
|
||||||
"",
|
"",
|
||||||
"Iv in hex string format. If not specified, a random iv will be "
|
"Iv in hex string format. If not specified, a random iv will be "
|
||||||
"generated. This flag should only be used for testing.");
|
"generated. This flag should only be used for testing.");
|
||||||
DEFINE_string(pssh, "", "PSSH in hex string format.");
|
DEFINE_string(pssh,
|
||||||
|
"",
|
||||||
|
"One or more PSSH boxes in hex string format. If not specified, "
|
||||||
|
"will generate a v1 common PSSH box according to "
|
||||||
|
"https://goo.gl/507mKp.");
|
||||||
|
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
|
|
||||||
|
@ -51,7 +55,7 @@ bool ValidateFixedCryptoFlags() {
|
||||||
if (!ValidateFlag("pssh",
|
if (!ValidateFlag("pssh",
|
||||||
FLAGS_pssh,
|
FLAGS_pssh,
|
||||||
FLAGS_enable_fixed_key_encryption,
|
FLAGS_enable_fixed_key_encryption,
|
||||||
false,
|
true,
|
||||||
"--enable_fixed_key_encryption")) {
|
"--enable_fixed_key_encryption")) {
|
||||||
success = false;
|
success = false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include "packager/app/widevine_encryption_flags.h"
|
#include "packager/app/widevine_encryption_flags.h"
|
||||||
#include "packager/base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/base/strings/string_number_conversions.h"
|
#include "packager/base/strings/string_number_conversions.h"
|
||||||
|
#include "packager/media/base/fixed_key_source.h"
|
||||||
#include "packager/media/base/media_stream.h"
|
#include "packager/media/base/media_stream.h"
|
||||||
#include "packager/media/base/muxer.h"
|
#include "packager/media/base/muxer.h"
|
||||||
#include "packager/media/base/muxer_options.h"
|
#include "packager/media/base/muxer_options.h"
|
||||||
|
@ -100,7 +101,7 @@ scoped_ptr<KeySource> CreateEncryptionKeySource() {
|
||||||
}
|
}
|
||||||
encryption_key_source = widevine_key_source.Pass();
|
encryption_key_source = widevine_key_source.Pass();
|
||||||
} else if (FLAGS_enable_fixed_key_encryption) {
|
} else if (FLAGS_enable_fixed_key_encryption) {
|
||||||
encryption_key_source = KeySource::CreateFromHexStrings(
|
encryption_key_source = FixedKeySource::CreateFromHexStrings(
|
||||||
FLAGS_key_id, FLAGS_key, FLAGS_pssh, FLAGS_iv);
|
FLAGS_key_id, FLAGS_key, FLAGS_pssh, FLAGS_iv);
|
||||||
}
|
}
|
||||||
return encryption_key_source.Pass();
|
return encryption_key_source.Pass();
|
||||||
|
@ -120,8 +121,10 @@ scoped_ptr<KeySource> CreateDecryptionKeySource() {
|
||||||
|
|
||||||
decryption_key_source = widevine_key_source.Pass();
|
decryption_key_source = widevine_key_source.Pass();
|
||||||
} else if (FLAGS_enable_fixed_key_decryption) {
|
} else if (FLAGS_enable_fixed_key_decryption) {
|
||||||
decryption_key_source =
|
const char kNoPssh[] = "";
|
||||||
KeySource::CreateFromHexStrings(FLAGS_key_id, FLAGS_key, "", "");
|
const char kNoIv[] = "";
|
||||||
|
decryption_key_source = FixedKeySource::CreateFromHexStrings(
|
||||||
|
FLAGS_key_id, FLAGS_key, kNoPssh, kNoIv);
|
||||||
}
|
}
|
||||||
return decryption_key_source.Pass();
|
return decryption_key_source.Pass();
|
||||||
}
|
}
|
||||||
|
|
|
@ -389,10 +389,14 @@ class PackagerAppTest(unittest.TestCase):
|
||||||
'--key_server_url=' + widevine_server_url,
|
'--key_server_url=' + widevine_server_url,
|
||||||
'--content_id=3031323334353637', '--signer=widevine_test']
|
'--content_id=3031323334353637', '--signer=widevine_test']
|
||||||
elif encryption:
|
elif encryption:
|
||||||
|
pssh_box = ('000000307073736800000000' # PSSH header
|
||||||
|
'edef8ba979d64acea3c827dcd51d21ed' # Widevine system ID
|
||||||
|
'00000010' # Data size
|
||||||
|
'31323334353637383930313233343536') # Data
|
||||||
flags += ['--enable_fixed_key_encryption',
|
flags += ['--enable_fixed_key_encryption',
|
||||||
'--key_id=31323334353637383930313233343536',
|
'--key_id=31323334353637383930313233343536',
|
||||||
'--key=32333435363738393021323334353637',
|
'--key=32333435363738393021323334353637',
|
||||||
'--pssh=31323334353637383930313233343536', '--clear_lead=1']
|
'--pssh=' + pssh_box, '--clear_lead=1']
|
||||||
if not random_iv:
|
if not random_iv:
|
||||||
flags.append('--iv=3334353637383930')
|
flags.append('--iv=3334353637383930')
|
||||||
if key_rotation:
|
if key_rotation:
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include "packager/base/macros.h"
|
#include "packager/base/macros.h"
|
||||||
|
#include "packager/media/base/fixed_key_source.h"
|
||||||
|
|
||||||
using ::testing::Return;
|
using ::testing::Return;
|
||||||
using ::testing::SetArgPointee;
|
using ::testing::SetArgPointee;
|
||||||
|
@ -50,7 +51,7 @@ const uint8_t kBuffer2[] = {0x05, 0x02};
|
||||||
// Expected decrypted buffer with the above kMockKey and kIv2.
|
// Expected decrypted buffer with the above kMockKey and kIv2.
|
||||||
const uint8_t kExpectedDecryptedBuffer2[] = {0x20, 0x62};
|
const uint8_t kExpectedDecryptedBuffer2[] = {0x20, 0x62};
|
||||||
|
|
||||||
class MockKeySource : public KeySource {
|
class MockKeySource : public FixedKeySource {
|
||||||
public:
|
public:
|
||||||
MOCK_METHOD2(GetKey,
|
MOCK_METHOD2(GetKey,
|
||||||
Status(const std::vector<uint8_t>& key_id, EncryptionKey* key));
|
Status(const std::vector<uint8_t>& key_id, EncryptionKey* key));
|
||||||
|
|
|
@ -0,0 +1,153 @@
|
||||||
|
// Copyright 2016 Google Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file or at
|
||||||
|
// https://developers.google.com/open-source/licenses/bsd
|
||||||
|
|
||||||
|
#include "packager/media/base/fixed_key_source.h"
|
||||||
|
|
||||||
|
#include "packager/base/logging.h"
|
||||||
|
#include "packager/base/strings/string_number_conversions.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
|
namespace media {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
// Common SystemID defined by EME, which requires Key System implementations
|
||||||
|
// supporting ISO Common Encryption to support this SystemID and format.
|
||||||
|
// http://goo.gl/PHZDAF
|
||||||
|
const uint8_t kCommonSystemId[] = {0x10, 0x77, 0xef, 0xec, 0xc0, 0xb2,
|
||||||
|
0x4d, 0x02, 0xac, 0xe3, 0x3c, 0x1e,
|
||||||
|
0x52, 0xe2, 0xfb, 0x4b};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
FixedKeySource::~FixedKeySource() {}
|
||||||
|
|
||||||
|
Status FixedKeySource::FetchKeys(const std::vector<uint8_t>& pssh_box) {
|
||||||
|
// Do nothing for fixed key encryption/decryption.
|
||||||
|
return Status::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status FixedKeySource::FetchKeys(
|
||||||
|
const std::vector<std::vector<uint8_t>>& key_ids) {
|
||||||
|
// Do nothing for fixed key encryption/decryption.
|
||||||
|
return Status::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status FixedKeySource::FetchKeys(uint32_t asset_id) {
|
||||||
|
// Do nothing for fixed key encryption/decryption.
|
||||||
|
return Status::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status FixedKeySource::GetKey(TrackType track_type, EncryptionKey* key) {
|
||||||
|
DCHECK(key);
|
||||||
|
DCHECK(encryption_key_);
|
||||||
|
*key = *encryption_key_;
|
||||||
|
return Status::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status FixedKeySource::GetKey(const std::vector<uint8_t>& key_id,
|
||||||
|
EncryptionKey* key) {
|
||||||
|
DCHECK(key);
|
||||||
|
DCHECK(encryption_key_);
|
||||||
|
if (key_id != encryption_key_->key_id) {
|
||||||
|
return Status(error::NOT_FOUND,
|
||||||
|
std::string("Key for key ID ") +
|
||||||
|
base::HexEncode(&key_id[0], key_id.size()) +
|
||||||
|
" was not found.");
|
||||||
|
}
|
||||||
|
*key = *encryption_key_;
|
||||||
|
return Status::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
Status FixedKeySource::GetCryptoPeriodKey(uint32_t crypto_period_index,
|
||||||
|
TrackType track_type,
|
||||||
|
EncryptionKey* key) {
|
||||||
|
// Create a copy of the key.
|
||||||
|
*key = *encryption_key_;
|
||||||
|
|
||||||
|
// A naive key rotation algorithm is implemented here by left rotating the
|
||||||
|
// key, key_id and pssh. Note that this implementation is only intended for
|
||||||
|
// testing purpose. The actual key rotation algorithm can be much more
|
||||||
|
// complicated.
|
||||||
|
LOG(WARNING)
|
||||||
|
<< "This naive key rotation algorithm should not be used in production.";
|
||||||
|
std::rotate(key->key_id.begin(),
|
||||||
|
key->key_id.begin() + (crypto_period_index % key->key_id.size()),
|
||||||
|
key->key_id.end());
|
||||||
|
std::rotate(key->key.begin(),
|
||||||
|
key->key.begin() + (crypto_period_index % key->key.size()),
|
||||||
|
key->key.end());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < key->key_system_info.size(); i++) {
|
||||||
|
std::vector<uint8_t> pssh_data = key->key_system_info[i].pssh_data();
|
||||||
|
std::rotate(pssh_data.begin(),
|
||||||
|
pssh_data.begin() + (crypto_period_index % pssh_data.size()),
|
||||||
|
pssh_data.end());
|
||||||
|
key->key_system_info[i].set_pssh_data(pssh_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Status::OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
scoped_ptr<FixedKeySource> FixedKeySource::CreateFromHexStrings(
|
||||||
|
const std::string& key_id_hex,
|
||||||
|
const std::string& key_hex,
|
||||||
|
const std::string& pssh_boxes_hex,
|
||||||
|
const std::string& iv_hex) {
|
||||||
|
scoped_ptr<EncryptionKey> encryption_key(new EncryptionKey());
|
||||||
|
|
||||||
|
if (!base::HexStringToBytes(key_id_hex, &encryption_key->key_id)) {
|
||||||
|
LOG(ERROR) << "Cannot parse key_id_hex " << key_id_hex;
|
||||||
|
return scoped_ptr<FixedKeySource>();
|
||||||
|
} else if (encryption_key->key_id.size() != 16) {
|
||||||
|
LOG(ERROR) << "Invalid key ID size '" << encryption_key->key_id.size()
|
||||||
|
<< "', must be 16 bytes.";
|
||||||
|
return scoped_ptr<FixedKeySource>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!base::HexStringToBytes(key_hex, &encryption_key->key)) {
|
||||||
|
LOG(ERROR) << "Cannot parse key_hex " << key_hex;
|
||||||
|
return scoped_ptr<FixedKeySource>();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint8_t> pssh_boxes;
|
||||||
|
if (!pssh_boxes_hex.empty() &&
|
||||||
|
!base::HexStringToBytes(pssh_boxes_hex, &pssh_boxes)) {
|
||||||
|
LOG(ERROR) << "Cannot parse pssh_hex " << pssh_boxes_hex;
|
||||||
|
return scoped_ptr<FixedKeySource>();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!iv_hex.empty()) {
|
||||||
|
if (!base::HexStringToBytes(iv_hex, &encryption_key->iv)) {
|
||||||
|
LOG(ERROR) << "Cannot parse iv_hex " << iv_hex;
|
||||||
|
return scoped_ptr<FixedKeySource>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!ProtectionSystemSpecificInfo::ParseBoxes(
|
||||||
|
pssh_boxes.data(), pssh_boxes.size(),
|
||||||
|
&encryption_key->key_system_info)) {
|
||||||
|
LOG(ERROR) << "--pssh argument should be full PSSH boxes.";
|
||||||
|
return scoped_ptr<FixedKeySource>();
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there aren't any PSSH boxes given, create one with the common system ID.
|
||||||
|
if (encryption_key->key_system_info.size() == 0) {
|
||||||
|
ProtectionSystemSpecificInfo info;
|
||||||
|
info.add_key_id(encryption_key->key_id);
|
||||||
|
info.set_system_id(kCommonSystemId, arraysize(kCommonSystemId));
|
||||||
|
info.set_pssh_box_version(1);
|
||||||
|
|
||||||
|
encryption_key->key_system_info.push_back(info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return scoped_ptr<FixedKeySource>(new FixedKeySource(encryption_key.Pass()));
|
||||||
|
}
|
||||||
|
|
||||||
|
FixedKeySource::FixedKeySource() {}
|
||||||
|
FixedKeySource::FixedKeySource(scoped_ptr<EncryptionKey> key)
|
||||||
|
: encryption_key_(key.Pass()) {}
|
||||||
|
|
||||||
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
|
@ -0,0 +1,68 @@
|
||||||
|
// Copyright 2016 Google Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file or at
|
||||||
|
// https://developers.google.com/open-source/licenses/bsd
|
||||||
|
|
||||||
|
#ifndef MEDIA_BASE_FIXED_KEY_SOURCE_H_
|
||||||
|
#define MEDIA_BASE_FIXED_KEY_SOURCE_H_
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
|
#include "packager/media/base/key_source.h"
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
|
namespace media {
|
||||||
|
|
||||||
|
/// A key source that uses fixed keys for encryption.
|
||||||
|
class FixedKeySource : public KeySource {
|
||||||
|
public:
|
||||||
|
~FixedKeySource() override;
|
||||||
|
|
||||||
|
/// @name KeySource implementation overrides.
|
||||||
|
/// @{
|
||||||
|
Status FetchKeys(const std::vector<uint8_t>& pssh_box) override;
|
||||||
|
Status FetchKeys(const std::vector<std::vector<uint8_t>>& key_ids) override;
|
||||||
|
Status FetchKeys(uint32_t asset_id) override;
|
||||||
|
|
||||||
|
Status GetKey(TrackType track_type, EncryptionKey* key) override;
|
||||||
|
Status GetKey(const std::vector<uint8_t>& key_id,
|
||||||
|
EncryptionKey* key) override;
|
||||||
|
Status GetCryptoPeriodKey(uint32_t crypto_period_index,
|
||||||
|
TrackType track_type,
|
||||||
|
EncryptionKey* key) override;
|
||||||
|
/// @}
|
||||||
|
|
||||||
|
/// Creates a new FixedKeySource from the given hex strings. Returns null
|
||||||
|
/// if the strings are invalid.
|
||||||
|
/// @param key_id_hex is the key id in hex string.
|
||||||
|
/// @param key_hex is the key in hex string.
|
||||||
|
/// @param pssh_boxes_hex is the pssh_boxes in hex string.
|
||||||
|
/// @param iv_hex is the IV in hex string. If not specified, a randomly
|
||||||
|
/// generated IV with the default length will be used.
|
||||||
|
/// Note: GetKey on the created key source will always return the same key
|
||||||
|
/// for all track types.
|
||||||
|
static scoped_ptr<FixedKeySource> CreateFromHexStrings(
|
||||||
|
const std::string& key_id_hex,
|
||||||
|
const std::string& key_hex,
|
||||||
|
const std::string& pssh_boxes_hex,
|
||||||
|
const std::string& iv_hex);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Allow default constructor for mock key sources.
|
||||||
|
FixedKeySource();
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit FixedKeySource(scoped_ptr<EncryptionKey> key);
|
||||||
|
|
||||||
|
scoped_ptr<EncryptionKey> encryption_key_;
|
||||||
|
|
||||||
|
DISALLOW_COPY_AND_ASSIGN(FixedKeySource);
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
||||||
|
|
||||||
|
#endif // MEDIA_BASE_FIXED_KEY_SOURCE_H_
|
|
@ -0,0 +1,99 @@
|
||||||
|
// Copyright 2016 Google Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
// Use of this source code is governed by a BSD-style
|
||||||
|
// license that can be found in the LICENSE file or at
|
||||||
|
// https://developers.google.com/open-source/licenses/bsd
|
||||||
|
|
||||||
|
#include <gmock/gmock.h>
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include "packager/base/strings/string_number_conversions.h"
|
||||||
|
#include "packager/media/base/fixed_key_source.h"
|
||||||
|
#include "packager/media/base/test/status_test_util.h"
|
||||||
|
|
||||||
|
#define EXPECT_HEX_EQ(expected, actual) \
|
||||||
|
do { \
|
||||||
|
std::vector<uint8_t> decoded_; \
|
||||||
|
ASSERT_TRUE(base::HexStringToBytes((expected), &decoded_)); \
|
||||||
|
EXPECT_EQ(decoded_, (actual)); \
|
||||||
|
} while (false)
|
||||||
|
|
||||||
|
namespace edash_packager {
|
||||||
|
namespace media {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
const char kKeyIdHex[] = "0101020305080d1522375990e9000000";
|
||||||
|
const char kKeyHex[] = "00100100200300500801302103405500";
|
||||||
|
const char kIvHex[] = "000102030405060708090a0b0c0d0e0f";
|
||||||
|
const char kPsshBox1Hex[] =
|
||||||
|
"000000427073736801000000"
|
||||||
|
"020305070b0d1113171d1f25292b2f35"
|
||||||
|
"00000001"
|
||||||
|
"0101020305080d1522375990e9000000"
|
||||||
|
"0000000e"
|
||||||
|
"6544617368207061636b61676572";
|
||||||
|
const char kPsshBox2Hex[] =
|
||||||
|
"0000002e7073736800000000"
|
||||||
|
"bbbbbbbbbaaaaaaaaaaaaddddddddddd"
|
||||||
|
"0000000e"
|
||||||
|
"fffffffff000000000000ddddddd";
|
||||||
|
const char kDefaultPsshBoxHex[] =
|
||||||
|
"000000347073736801000000"
|
||||||
|
"1077efecc0b24d02ace33c1e52e2fb4b"
|
||||||
|
"00000001"
|
||||||
|
"0101020305080d1522375990e9000000"
|
||||||
|
"00000000";
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FixedKeySourceTest, CreateFromHexStrings_Succes) {
|
||||||
|
std::string pssh_boxes = std::string(kPsshBox1Hex) + kPsshBox2Hex;
|
||||||
|
scoped_ptr<FixedKeySource> key_source = FixedKeySource::CreateFromHexStrings(
|
||||||
|
kKeyIdHex, kKeyHex, pssh_boxes, kIvHex);
|
||||||
|
ASSERT_NE(nullptr, key_source);
|
||||||
|
|
||||||
|
EncryptionKey key;
|
||||||
|
ASSERT_OK(key_source->GetKey(KeySource::TRACK_TYPE_SD, &key));
|
||||||
|
|
||||||
|
EXPECT_HEX_EQ(kKeyIdHex, key.key_id);
|
||||||
|
EXPECT_HEX_EQ(kKeyHex, key.key);
|
||||||
|
EXPECT_HEX_EQ(kIvHex, key.iv);
|
||||||
|
|
||||||
|
ASSERT_EQ(2u, key.key_system_info.size());
|
||||||
|
EXPECT_HEX_EQ(kPsshBox1Hex, key.key_system_info[0].CreateBox());
|
||||||
|
EXPECT_HEX_EQ(kPsshBox2Hex, key.key_system_info[1].CreateBox());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FixedKeySourceTest, CreateFromHexStrings_EmptyPssh) {
|
||||||
|
scoped_ptr<FixedKeySource> key_source = FixedKeySource::CreateFromHexStrings(
|
||||||
|
kKeyIdHex, kKeyHex, "", kIvHex);
|
||||||
|
ASSERT_NE(nullptr, key_source);
|
||||||
|
|
||||||
|
EncryptionKey key;
|
||||||
|
ASSERT_OK(key_source->GetKey(KeySource::TRACK_TYPE_SD, &key));
|
||||||
|
|
||||||
|
EXPECT_HEX_EQ(kKeyIdHex, key.key_id);
|
||||||
|
EXPECT_HEX_EQ(kKeyHex, key.key);
|
||||||
|
EXPECT_HEX_EQ(kIvHex, key.iv);
|
||||||
|
|
||||||
|
ASSERT_EQ(1u, key.key_system_info.size());
|
||||||
|
EXPECT_HEX_EQ(kDefaultPsshBoxHex, key.key_system_info[0].CreateBox());
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FixedKeySourceTest, CreateFromHexStrings_Failure) {
|
||||||
|
scoped_ptr<FixedKeySource> key_source = FixedKeySource::CreateFromHexStrings(
|
||||||
|
kKeyIdHex, "invalid_hex_value", kPsshBox1Hex, kIvHex);
|
||||||
|
EXPECT_EQ(nullptr, key_source);
|
||||||
|
|
||||||
|
// Invalid key id size.
|
||||||
|
key_source = FixedKeySource::CreateFromHexStrings("000102030405", kKeyHex,
|
||||||
|
kPsshBox1Hex, kIvHex);
|
||||||
|
EXPECT_EQ(nullptr, key_source);
|
||||||
|
|
||||||
|
// Invalid pssh box.
|
||||||
|
key_source = FixedKeySource::CreateFromHexStrings(kKeyIdHex, kKeyHex,
|
||||||
|
"000102030405", kIvHex);
|
||||||
|
EXPECT_EQ(nullptr, key_source);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace media
|
||||||
|
} // namespace edash_packager
|
|
@ -6,9 +6,7 @@
|
||||||
|
|
||||||
#include "packager/media/base/key_source.h"
|
#include "packager/media/base/key_source.h"
|
||||||
|
|
||||||
#include "packager/base/strings/string_number_conversions.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/media/base/aes_encryptor.h"
|
|
||||||
#include "packager/media/base/buffer_writer.h"
|
|
||||||
|
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
@ -18,127 +16,6 @@ EncryptionKey::~EncryptionKey() {}
|
||||||
|
|
||||||
KeySource::~KeySource() {}
|
KeySource::~KeySource() {}
|
||||||
|
|
||||||
Status KeySource::FetchKeys(const std::vector<uint8_t>& content_id,
|
|
||||||
const std::string& policy) {
|
|
||||||
// Do nothing for fixed key encryption/decryption.
|
|
||||||
return Status::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status KeySource::FetchKeys(const std::vector<uint8_t>& pssh_box) {
|
|
||||||
// Do nothing for fixed key encryption/decryption.
|
|
||||||
return Status::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status KeySource::FetchKeys(const std::vector<std::vector<uint8_t>>& key_ids) {
|
|
||||||
// Do nothing for fixed key encryption/decryption.
|
|
||||||
return Status::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status KeySource::FetchKeys(uint32_t asset_id) {
|
|
||||||
// Do nothing for fixed key encryption/decryption.
|
|
||||||
return Status::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status KeySource::GetKey(TrackType track_type, EncryptionKey* key) {
|
|
||||||
DCHECK(key);
|
|
||||||
DCHECK(encryption_key_);
|
|
||||||
*key = *encryption_key_;
|
|
||||||
return Status::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status KeySource::GetKey(const std::vector<uint8_t>& key_id,
|
|
||||||
EncryptionKey* key) {
|
|
||||||
DCHECK(key);
|
|
||||||
DCHECK(encryption_key_);
|
|
||||||
if (key_id != encryption_key_->key_id) {
|
|
||||||
return Status(error::NOT_FOUND, std::string("Key for key ID ") +
|
|
||||||
base::HexEncode(&key_id[0], key_id.size()) +
|
|
||||||
" was not found.");
|
|
||||||
}
|
|
||||||
*key = *encryption_key_;
|
|
||||||
return Status::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Status KeySource::GetCryptoPeriodKey(uint32_t crypto_period_index,
|
|
||||||
TrackType track_type,
|
|
||||||
EncryptionKey* key) {
|
|
||||||
*key = *encryption_key_;
|
|
||||||
// A naive key rotation algorithm is implemented here by left rotating the
|
|
||||||
// key, key_id and pssh. Note that this implementation is only intended for
|
|
||||||
// testing purpose. The actual key rotation algorithm can be much more
|
|
||||||
// complicated.
|
|
||||||
LOG(WARNING)
|
|
||||||
<< "This naive key rotation algorithm should not be used in production.";
|
|
||||||
std::rotate(key->key_id.begin(),
|
|
||||||
key->key_id.begin() + (crypto_period_index % key->key_id.size()),
|
|
||||||
key->key_id.end());
|
|
||||||
std::rotate(key->key.begin(),
|
|
||||||
key->key.begin() + (crypto_period_index % key->key.size()),
|
|
||||||
key->key.end());
|
|
||||||
|
|
||||||
std::vector<uint8_t> pssh_data(
|
|
||||||
key->key_system_info[0].pssh_data().begin(),
|
|
||||||
key->key_system_info[0].pssh_data().end());
|
|
||||||
std::rotate(pssh_data.begin(),
|
|
||||||
pssh_data.begin() + (crypto_period_index % pssh_data.size()),
|
|
||||||
pssh_data.end());
|
|
||||||
|
|
||||||
// Since this should only be used for testing, use the Widevine system id.
|
|
||||||
// TODO(modmaker): Change to FixedKeySource
|
|
||||||
ProtectionSystemSpecificInfo info;
|
|
||||||
info.add_key_id(key->key_id);
|
|
||||||
info.set_system_id(kWidevineSystemId, arraysize(kWidevineSystemId));
|
|
||||||
info.set_pssh_box_version(0);
|
|
||||||
info.set_pssh_data(pssh_data);
|
|
||||||
|
|
||||||
key->key_system_info.clear();
|
|
||||||
key->key_system_info.push_back(info);
|
|
||||||
|
|
||||||
return Status::OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
scoped_ptr<KeySource> KeySource::CreateFromHexStrings(
|
|
||||||
const std::string& key_id_hex,
|
|
||||||
const std::string& key_hex,
|
|
||||||
const std::string& pssh_data_hex,
|
|
||||||
const std::string& iv_hex) {
|
|
||||||
scoped_ptr<EncryptionKey> encryption_key(new EncryptionKey());
|
|
||||||
|
|
||||||
if (!base::HexStringToBytes(key_id_hex, &encryption_key->key_id)) {
|
|
||||||
LOG(ERROR) << "Cannot parse key_id_hex " << key_id_hex;
|
|
||||||
return scoped_ptr<KeySource>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!base::HexStringToBytes(key_hex, &encryption_key->key)) {
|
|
||||||
LOG(ERROR) << "Cannot parse key_hex " << key_hex;
|
|
||||||
return scoped_ptr<KeySource>();
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<uint8_t> pssh_data;
|
|
||||||
if (!pssh_data_hex.empty() &&
|
|
||||||
!base::HexStringToBytes(pssh_data_hex, &pssh_data)) {
|
|
||||||
LOG(ERROR) << "Cannot parse pssh_hex " << pssh_data_hex;
|
|
||||||
return scoped_ptr<KeySource>();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!iv_hex.empty()) {
|
|
||||||
if (!base::HexStringToBytes(iv_hex, &encryption_key->iv)) {
|
|
||||||
LOG(ERROR) << "Cannot parse iv_hex " << iv_hex;
|
|
||||||
return scoped_ptr<KeySource>();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(modmaker): Change to FixedKeySource
|
|
||||||
ProtectionSystemSpecificInfo info;
|
|
||||||
info.add_key_id(encryption_key->key_id);
|
|
||||||
info.set_system_id(kWidevineSystemId, arraysize(kWidevineSystemId));
|
|
||||||
info.set_pssh_box_version(0);
|
|
||||||
info.set_pssh_data(pssh_data);
|
|
||||||
|
|
||||||
encryption_key->key_system_info.push_back(info);
|
|
||||||
return scoped_ptr<KeySource>(new KeySource(encryption_key.Pass()));
|
|
||||||
}
|
|
||||||
|
|
||||||
KeySource::TrackType KeySource::GetTrackTypeFromString(
|
KeySource::TrackType KeySource::GetTrackTypeFromString(
|
||||||
const std::string& track_type_string) {
|
const std::string& track_type_string) {
|
||||||
if (track_type_string == "SD")
|
if (track_type_string == "SD")
|
||||||
|
@ -168,10 +45,6 @@ std::string KeySource::TrackTypeToString(TrackType track_type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
KeySource::KeySource() {}
|
KeySource::KeySource() {}
|
||||||
KeySource::KeySource(scoped_ptr<EncryptionKey> encryption_key)
|
|
||||||
: encryption_key_(encryption_key.Pass()) {
|
|
||||||
DCHECK(encryption_key_);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace media
|
} // namespace media
|
||||||
} // namespace edash_packager
|
} // namespace edash_packager
|
||||||
|
|
|
@ -17,10 +17,6 @@
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
const uint8_t kWidevineSystemId[] = {0xed, 0xef, 0x8b, 0xa9, 0x79, 0xd6,
|
|
||||||
0x4a, 0xce, 0xa3, 0xc8, 0x27, 0xdc,
|
|
||||||
0xd5, 0x1d, 0x21, 0xed};
|
|
||||||
|
|
||||||
struct EncryptionKey {
|
struct EncryptionKey {
|
||||||
EncryptionKey();
|
EncryptionKey();
|
||||||
~EncryptionKey();
|
~EncryptionKey();
|
||||||
|
@ -43,44 +39,40 @@ class KeySource {
|
||||||
NUM_VALID_TRACK_TYPES = 4
|
NUM_VALID_TRACK_TYPES = 4
|
||||||
};
|
};
|
||||||
|
|
||||||
|
KeySource();
|
||||||
virtual ~KeySource();
|
virtual ~KeySource();
|
||||||
|
|
||||||
/// Fetch keys for CENC from the key server.
|
|
||||||
/// @param content_id the unique id identify the content.
|
|
||||||
/// @param policy specifies the DRM content rights.
|
|
||||||
/// @return OK on success, an error status otherwise.
|
|
||||||
virtual Status FetchKeys(const std::vector<uint8_t>& content_id,
|
|
||||||
const std::string& policy);
|
|
||||||
|
|
||||||
/// Fetch keys for CENC from the key server.
|
/// Fetch keys for CENC from the key server.
|
||||||
/// @param pssh_box The entire PSSH box for the content to be decrypted
|
/// @param pssh_box The entire PSSH box for the content to be decrypted
|
||||||
/// @return OK on success, an error status otherwise.
|
/// @return OK on success, an error status otherwise.
|
||||||
virtual Status FetchKeys(const std::vector<uint8_t>& pssh_box);
|
virtual Status FetchKeys(const std::vector<uint8_t>& pssh_box) = 0;
|
||||||
|
|
||||||
/// Fetch keys for CENC from the key server.
|
/// Fetch keys for CENC from the key server.
|
||||||
/// @param key_ids the key IDs for the keys to fetch from the server.
|
/// @param key_ids the key IDs for the keys to fetch from the server.
|
||||||
/// @return OK on success, an error status otherwise.
|
/// @return OK on success, an error status otherwise.
|
||||||
virtual Status FetchKeys(const std::vector<std::vector<uint8_t>>& key_ids);
|
virtual Status FetchKeys(
|
||||||
|
const std::vector<std::vector<uint8_t>>& key_ids) = 0;
|
||||||
|
|
||||||
/// Fetch keys for WVM decryption from the key server.
|
/// Fetch keys for WVM decryption from the key server.
|
||||||
/// @param asset_id is the Widevine Classic asset ID for the content to be
|
/// @param asset_id is the Widevine Classic asset ID for the content to be
|
||||||
/// decrypted.
|
/// decrypted.
|
||||||
/// @return OK on success, an error status otherwise.
|
/// @return OK on success, an error status otherwise.
|
||||||
virtual Status FetchKeys(uint32_t asset_id);
|
virtual Status FetchKeys(uint32_t asset_id) = 0;
|
||||||
|
|
||||||
/// Get encryption key of the specified track type.
|
/// Get encryption key of the specified track type.
|
||||||
/// @param track_type is the type of track for which retrieving the key.
|
/// @param track_type is the type of track for which retrieving the key.
|
||||||
/// @param key is a pointer to the EncryptionKey which will hold the retrieved
|
/// @param key is a pointer to the EncryptionKey which will hold the retrieved
|
||||||
/// key. Owner retains ownership, and may not be NULL.
|
/// key. Owner retains ownership, and may not be NULL.
|
||||||
/// @return OK on success, an error status otherwise.
|
/// @return OK on success, an error status otherwise.
|
||||||
virtual Status GetKey(TrackType track_type, EncryptionKey* key);
|
virtual Status GetKey(TrackType track_type, EncryptionKey* key) = 0;
|
||||||
|
|
||||||
/// Get the encryption key specified by the CENC key ID.
|
/// Get the encryption key specified by the CENC key ID.
|
||||||
/// @param key_id is the unique identifier for the key being retreived.
|
/// @param key_id is the unique identifier for the key being retreived.
|
||||||
/// @param key is a pointer to the EncryptionKey which will hold the retrieved
|
/// @param key is a pointer to the EncryptionKey which will hold the retrieved
|
||||||
/// key. Owner retains ownership, and may not be NULL.
|
/// key. Owner retains ownership, and may not be NULL.
|
||||||
/// @return OK on success, or an error status otherwise.
|
/// @return OK on success, or an error status otherwise.
|
||||||
virtual Status GetKey(const std::vector<uint8_t>& key_id, EncryptionKey* key);
|
virtual Status GetKey(const std::vector<uint8_t>& key_id,
|
||||||
|
EncryptionKey* key) = 0;
|
||||||
|
|
||||||
/// Get encryption key of the specified track type at the specified index.
|
/// Get encryption key of the specified track type at the specified index.
|
||||||
/// @param crypto_period_index is the sequence number of the key rotation
|
/// @param crypto_period_index is the sequence number of the key rotation
|
||||||
|
@ -91,21 +83,7 @@ class KeySource {
|
||||||
/// @return OK on success, an error status otherwise.
|
/// @return OK on success, an error status otherwise.
|
||||||
virtual Status GetCryptoPeriodKey(uint32_t crypto_period_index,
|
virtual Status GetCryptoPeriodKey(uint32_t crypto_period_index,
|
||||||
TrackType track_type,
|
TrackType track_type,
|
||||||
EncryptionKey* key);
|
EncryptionKey* key) = 0;
|
||||||
|
|
||||||
/// Create KeySource object from hex strings.
|
|
||||||
/// @param key_id_hex is the key id in hex string.
|
|
||||||
/// @param key_hex is the key in hex string.
|
|
||||||
/// @param pssh_data_hex is the pssh_data in hex string.
|
|
||||||
/// @param iv_hex is the IV in hex string. If not specified, a randomly
|
|
||||||
/// generated IV with the default length will be used.
|
|
||||||
/// Note: GetKey on the created key source will always return the same key
|
|
||||||
/// for all track types.
|
|
||||||
static scoped_ptr<KeySource> CreateFromHexStrings(
|
|
||||||
const std::string& key_id_hex,
|
|
||||||
const std::string& key_hex,
|
|
||||||
const std::string& pssh_data_hex,
|
|
||||||
const std::string& iv_hex);
|
|
||||||
|
|
||||||
/// Convert string representation of track type to enum representation.
|
/// Convert string representation of track type to enum representation.
|
||||||
static TrackType GetTrackTypeFromString(const std::string& track_type_string);
|
static TrackType GetTrackTypeFromString(const std::string& track_type_string);
|
||||||
|
@ -113,14 +91,7 @@ class KeySource {
|
||||||
/// Convert TrackType to string.
|
/// Convert TrackType to string.
|
||||||
static std::string TrackTypeToString(TrackType track_type);
|
static std::string TrackTypeToString(TrackType track_type);
|
||||||
|
|
||||||
protected:
|
|
||||||
KeySource();
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit KeySource(scoped_ptr<EncryptionKey> encryption_key);
|
|
||||||
|
|
||||||
scoped_ptr<EncryptionKey> encryption_key_;
|
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(KeySource);
|
DISALLOW_COPY_AND_ASSIGN(KeySource);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -40,6 +40,8 @@
|
||||||
'decryptor_source.cc',
|
'decryptor_source.cc',
|
||||||
'decryptor_source.h',
|
'decryptor_source.h',
|
||||||
'encryption_modes.h',
|
'encryption_modes.h',
|
||||||
|
'fixed_key_source.cc',
|
||||||
|
'fixed_key_source.h',
|
||||||
'http_key_fetcher.cc',
|
'http_key_fetcher.cc',
|
||||||
'http_key_fetcher.h',
|
'http_key_fetcher.h',
|
||||||
'key_fetcher.cc',
|
'key_fetcher.cc',
|
||||||
|
@ -118,6 +120,7 @@
|
||||||
'closure_thread_unittest.cc',
|
'closure_thread_unittest.cc',
|
||||||
'container_names_unittest.cc',
|
'container_names_unittest.cc',
|
||||||
'decryptor_source_unittest.cc',
|
'decryptor_source_unittest.cc',
|
||||||
|
'fixed_key_source_unittest.cc',
|
||||||
'http_key_fetcher_unittest.cc',
|
'http_key_fetcher_unittest.cc',
|
||||||
'muxer_util_unittest.cc',
|
'muxer_util_unittest.cc',
|
||||||
'offset_byte_queue_unittest.cc',
|
'offset_byte_queue_unittest.cc',
|
||||||
|
|
|
@ -47,6 +47,10 @@ const int kDefaultCryptoPeriodCount = 10;
|
||||||
const int kGetKeyTimeoutInSeconds = 5 * 60; // 5 minutes.
|
const int kGetKeyTimeoutInSeconds = 5 * 60; // 5 minutes.
|
||||||
const int kKeyFetchTimeoutInSeconds = 60; // 1 minute.
|
const int kKeyFetchTimeoutInSeconds = 60; // 1 minute.
|
||||||
|
|
||||||
|
const uint8_t kWidevineSystemId[] = {0xed, 0xef, 0x8b, 0xa9, 0x79, 0xd6,
|
||||||
|
0x4a, 0xce, 0xa3, 0xc8, 0x27, 0xdc,
|
||||||
|
0xd5, 0x1d, 0x21, 0xed};
|
||||||
|
|
||||||
bool Base64StringToBytes(const std::string& base64_string,
|
bool Base64StringToBytes(const std::string& base64_string,
|
||||||
std::vector<uint8_t>* bytes) {
|
std::vector<uint8_t>* bytes) {
|
||||||
DCHECK(bytes);
|
DCHECK(bytes);
|
||||||
|
|
|
@ -32,8 +32,6 @@ class WidevineKeySource : public KeySource {
|
||||||
|
|
||||||
/// @name KeySource implementation overrides.
|
/// @name KeySource implementation overrides.
|
||||||
/// @{
|
/// @{
|
||||||
Status FetchKeys(const std::vector<uint8_t>& content_id,
|
|
||||||
const std::string& policy) override;
|
|
||||||
Status FetchKeys(const std::vector<uint8_t>& pssh_box) override;
|
Status FetchKeys(const std::vector<uint8_t>& pssh_box) override;
|
||||||
Status FetchKeys(const std::vector<std::vector<uint8_t>>& key_ids) override;
|
Status FetchKeys(const std::vector<std::vector<uint8_t>>& key_ids) override;
|
||||||
Status FetchKeys(uint32_t asset_id) override;
|
Status FetchKeys(uint32_t asset_id) override;
|
||||||
|
@ -46,6 +44,13 @@ class WidevineKeySource : public KeySource {
|
||||||
EncryptionKey* key) override;
|
EncryptionKey* key) override;
|
||||||
/// @}
|
/// @}
|
||||||
|
|
||||||
|
/// Fetch keys for CENC from the key server.
|
||||||
|
/// @param content_id the unique id identify the content.
|
||||||
|
/// @param policy specifies the DRM content rights.
|
||||||
|
/// @return OK on success, an error status otherwise.
|
||||||
|
Status FetchKeys(const std::vector<uint8_t>& content_id,
|
||||||
|
const std::string& policy);
|
||||||
|
|
||||||
/// Set signer for the key source.
|
/// Set signer for the key source.
|
||||||
/// @param signer signs the request message.
|
/// @param signer signs the request message.
|
||||||
void set_signer(scoped_ptr<RequestSigner> signer);
|
void set_signer(scoped_ptr<RequestSigner> signer);
|
||||||
|
|
|
@ -154,7 +154,7 @@ TEST_F(MpdNotifyMuxerListenerTest, VodEncryptedContent) {
|
||||||
std::string(kExpectedDefaultMediaInfo) +
|
std::string(kExpectedDefaultMediaInfo) +
|
||||||
"protected_content {\n"
|
"protected_content {\n"
|
||||||
" content_protection_entry {\n"
|
" content_protection_entry {\n"
|
||||||
" uuid: 'edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'\n"
|
" uuid: '00010203-0405-0607-0809-0a0b0c0d0e0f'\n"
|
||||||
" pssh: '" + std::string(kExpectedDefaultPsshBox) + "'\n"
|
" pssh: '" + std::string(kExpectedDefaultPsshBox) + "'\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" default_key_id: 'defaultkeyid'\n"
|
" default_key_id: 'defaultkeyid'\n"
|
||||||
|
@ -286,7 +286,7 @@ TEST_F(MpdNotifyMuxerListenerTest, LiveNoKeyRotation) {
|
||||||
"protected_content {\n"
|
"protected_content {\n"
|
||||||
" default_key_id: \"defaultkeyid\"\n"
|
" default_key_id: \"defaultkeyid\"\n"
|
||||||
" content_protection_entry {\n"
|
" content_protection_entry {\n"
|
||||||
" uuid: 'edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'\n"
|
" uuid: '00010203-0405-0607-0809-0a0b0c0d0e0f'\n"
|
||||||
" pssh: \"" + std::string(kExpectedDefaultPsshBox) + "\"\n"
|
" pssh: \"" + std::string(kExpectedDefaultPsshBox) + "\"\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
|
|
|
@ -96,9 +96,12 @@ void SetDefaultMuxerOptionsValues(MuxerOptions* muxer_options) {
|
||||||
|
|
||||||
std::vector<ProtectionSystemSpecificInfo> GetDefaultKeySystemInfo() {
|
std::vector<ProtectionSystemSpecificInfo> GetDefaultKeySystemInfo() {
|
||||||
const uint8_t kPsshData[] = {'p', 's', 's', 'h'};
|
const uint8_t kPsshData[] = {'p', 's', 's', 'h'};
|
||||||
|
const uint8_t kTestSystemId[] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
|
||||||
|
0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
|
||||||
|
0x0c, 0x0d, 0x0e, 0x0f};
|
||||||
|
|
||||||
ProtectionSystemSpecificInfo info;
|
ProtectionSystemSpecificInfo info;
|
||||||
info.set_system_id(kWidevineSystemId, arraysize(kWidevineSystemId));
|
info.set_system_id(kTestSystemId, arraysize(kTestSystemId));
|
||||||
info.set_pssh_data(
|
info.set_pssh_data(
|
||||||
std::vector<uint8_t>(kPsshData, kPsshData + arraysize(kPsshData)));
|
std::vector<uint8_t>(kPsshData, kPsshData + arraysize(kPsshData)));
|
||||||
info.set_pssh_box_version(0);
|
info.set_pssh_box_version(0);
|
||||||
|
|
|
@ -25,8 +25,8 @@ namespace media {
|
||||||
// This is a full v0 PSSH box with the Widevine system ID and the PSSH data
|
// This is a full v0 PSSH box with the Widevine system ID and the PSSH data
|
||||||
// 'pssh'
|
// 'pssh'
|
||||||
const char kExpectedDefaultPsshBox[] =
|
const char kExpectedDefaultPsshBox[] =
|
||||||
"\\000\\000\\000$pssh\\000\\000\\000\\000\\355\\357\\213\\251y\\326J\\316"
|
"\\000\\000\\000$pssh\\000\\000\\000\\000\\000\\001\\002\\003\\004\\005"
|
||||||
"\\243\\310\\'\\334\\325\\035!\\355\\000\\000\\000\\4pssh";
|
"\\006\\007\\010\\t\\n\\013\\014\\r\\016\\017\\000\\000\\000\\004pssh";
|
||||||
const char kExpectedDefaultMediaInfo[] =
|
const char kExpectedDefaultMediaInfo[] =
|
||||||
"bandwidth: 7620\n"
|
"bandwidth: 7620\n"
|
||||||
"video_info {\n"
|
"video_info {\n"
|
||||||
|
|
|
@ -179,7 +179,7 @@ TEST_F(VodMediaInfoDumpMuxerListenerTest, EncryptedStream_Normal) {
|
||||||
"media_duration_seconds: 10.5\n"
|
"media_duration_seconds: 10.5\n"
|
||||||
"protected_content {\n"
|
"protected_content {\n"
|
||||||
" content_protection_entry {\n"
|
" content_protection_entry {\n"
|
||||||
" uuid: 'edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'\n"
|
" uuid: '00010203-0405-0607-0809-0a0b0c0d0e0f'\n"
|
||||||
" pssh: '" + std::string(kExpectedDefaultPsshBox) + "'\n"
|
" pssh: '" + std::string(kExpectedDefaultPsshBox) + "'\n"
|
||||||
" }\n"
|
" }\n"
|
||||||
" default_key_id: '_default_key_id_'\n"
|
" default_key_id: '_default_key_id_'\n"
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
|
|
||||||
#include "packager/base/bind.h"
|
#include "packager/base/bind.h"
|
||||||
#include "packager/base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/media/base/key_source.h"
|
#include "packager/media/base/fixed_key_source.h"
|
||||||
#include "packager/media/base/media_sample.h"
|
#include "packager/media/base/media_sample.h"
|
||||||
#include "packager/media/base/stream_info.h"
|
#include "packager/media/base/stream_info.h"
|
||||||
#include "packager/media/base/video_stream_info.h"
|
#include "packager/media/base/video_stream_info.h"
|
||||||
|
@ -29,7 +29,7 @@ const char kKey[] =
|
||||||
"\xeb\xdd\x62\xf1\x68\x14\xd2\x7b\x68\xef\x12\x2a\xfc\xe4\xae\x3c";
|
"\xeb\xdd\x62\xf1\x68\x14\xd2\x7b\x68\xef\x12\x2a\xfc\xe4\xae\x3c";
|
||||||
const char kKeyId[] = "0123456789012345";
|
const char kKeyId[] = "0123456789012345";
|
||||||
|
|
||||||
class MockKeySource : public KeySource {
|
class MockKeySource : public FixedKeySource {
|
||||||
public:
|
public:
|
||||||
MOCK_METHOD1(FetchKeys, Status(const std::vector<uint8_t>& pssh_data));
|
MOCK_METHOD1(FetchKeys, Status(const std::vector<uint8_t>& pssh_data));
|
||||||
MOCK_METHOD2(GetKey,
|
MOCK_METHOD2(GetKey,
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include <gtest/gtest.h>
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
#include "packager/base/memory/scoped_ptr.h"
|
#include "packager/base/memory/scoped_ptr.h"
|
||||||
|
#include "packager/media/base/fixed_key_source.h"
|
||||||
#include "packager/media/formats/webm/segmenter_test_base.h"
|
#include "packager/media/formats/webm/segmenter_test_base.h"
|
||||||
|
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
|
@ -189,7 +190,8 @@ class EncrypedSegmenterTest : public SegmentTestBase {
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void InitializeSegmenter(const MuxerOptions& options) {
|
void InitializeSegmenter(const MuxerOptions& options) {
|
||||||
key_source_ = KeySource::CreateFromHexStrings(kKeyId, kKey, kPsshData, kIv);
|
key_source_ =
|
||||||
|
FixedKeySource::CreateFromHexStrings(kKeyId, kKey, kPsshData, kIv);
|
||||||
ASSERT_NO_FATAL_FAILURE(
|
ASSERT_NO_FATAL_FAILURE(
|
||||||
CreateAndInitializeSegmenter<webm::SingleSegmentSegmenter>(
|
CreateAndInitializeSegmenter<webm::SingleSegmentSegmenter>(
|
||||||
options, info_.get(), key_source_.get(), &segmenter_));
|
options, info_.get(), key_source_.get(), &segmenter_));
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
#include "packager/base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/base/strings/string_number_conversions.h"
|
#include "packager/base/strings/string_number_conversions.h"
|
||||||
#include "packager/media/base/decrypt_config.h"
|
#include "packager/media/base/decrypt_config.h"
|
||||||
|
#include "packager/media/base/fixed_key_source.h"
|
||||||
#include "packager/media/base/timestamp.h"
|
#include "packager/media/base/timestamp.h"
|
||||||
#include "packager/media/formats/webm/cluster_builder.h"
|
#include "packager/media/formats/webm/cluster_builder.h"
|
||||||
#include "packager/media/formats/webm/webm_constants.h"
|
#include "packager/media/formats/webm/webm_constants.h"
|
||||||
|
@ -171,7 +172,7 @@ const uint8_t kVP9Frame[] = {
|
||||||
0xe1, 0xe6, 0xef, 0xff, 0xfd, 0xf7, 0x4f, 0x0f,
|
0xe1, 0xe6, 0xef, 0xff, 0xfd, 0xf7, 0x4f, 0x0f,
|
||||||
};
|
};
|
||||||
|
|
||||||
class MockKeySource : public KeySource {
|
class MockKeySource : public FixedKeySource {
|
||||||
public:
|
public:
|
||||||
MOCK_METHOD2(GetKey,
|
MOCK_METHOD2(GetKey,
|
||||||
Status(const std::vector<uint8_t>& key_id, EncryptionKey* key));
|
Status(const std::vector<uint8_t>& key_id, EncryptionKey* key));
|
||||||
|
|
|
@ -13,12 +13,12 @@
|
||||||
#include "packager/base/logging.h"
|
#include "packager/base/logging.h"
|
||||||
#include "packager/base/memory/ref_counted.h"
|
#include "packager/base/memory/ref_counted.h"
|
||||||
#include "packager/media/base/audio_stream_info.h"
|
#include "packager/media/base/audio_stream_info.h"
|
||||||
|
#include "packager/media/base/fixed_key_source.h"
|
||||||
#include "packager/media/base/media_sample.h"
|
#include "packager/media/base/media_sample.h"
|
||||||
#include "packager/media/base/request_signer.h"
|
#include "packager/media/base/request_signer.h"
|
||||||
#include "packager/media/base/stream_info.h"
|
#include "packager/media/base/stream_info.h"
|
||||||
#include "packager/media/base/timestamp.h"
|
#include "packager/media/base/timestamp.h"
|
||||||
#include "packager/media/base/video_stream_info.h"
|
#include "packager/media/base/video_stream_info.h"
|
||||||
#include "packager/media/base/key_source.h"
|
|
||||||
#include "packager/media/formats/wvm/wvm_media_parser.h"
|
#include "packager/media/formats/wvm/wvm_media_parser.h"
|
||||||
#include "packager/media/test/test_data_util.h"
|
#include "packager/media/test/test_data_util.h"
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ using ::testing::SetArgPointee;
|
||||||
namespace edash_packager {
|
namespace edash_packager {
|
||||||
namespace media {
|
namespace media {
|
||||||
|
|
||||||
class MockKeySource : public KeySource {
|
class MockKeySource : public FixedKeySource {
|
||||||
public:
|
public:
|
||||||
MockKeySource() {}
|
MockKeySource() {}
|
||||||
~MockKeySource() override {}
|
~MockKeySource() override {}
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
#include "packager/base/time/clock.h"
|
#include "packager/base/time/clock.h"
|
||||||
#include "packager/media/base/demuxer.h"
|
#include "packager/media/base/demuxer.h"
|
||||||
#include "packager/media/base/encryption_modes.h"
|
#include "packager/media/base/encryption_modes.h"
|
||||||
#include "packager/media/base/key_source.h"
|
#include "packager/media/base/fixed_key_source.h"
|
||||||
#include "packager/media/base/media_stream.h"
|
#include "packager/media/base/media_stream.h"
|
||||||
#include "packager/media/base/muxer.h"
|
#include "packager/media/base/muxer.h"
|
||||||
#include "packager/media/base/stream_info.h"
|
#include "packager/media/base/stream_info.h"
|
||||||
|
@ -54,10 +54,6 @@ const char kNoLanguageOverride[] = "";
|
||||||
// Encryption constants.
|
// Encryption constants.
|
||||||
const char kKeyIdHex[] = "e5007e6e9dcd5ac095202ed3758382cd";
|
const char kKeyIdHex[] = "e5007e6e9dcd5ac095202ed3758382cd";
|
||||||
const char kKeyHex[] = "6fc96fe628a265b13aeddec0bc421f4d";
|
const char kKeyHex[] = "6fc96fe628a265b13aeddec0bc421f4d";
|
||||||
const char kPsshHex[] =
|
|
||||||
"08011210e5007e6e9dcd5ac095202ed3"
|
|
||||||
"758382cd1a0d7769646576696e655f746573742211544553545f"
|
|
||||||
"434f4e54454e545f49445f312a025344";
|
|
||||||
const double kClearLeadInSeconds = 1.5;
|
const double kClearLeadInSeconds = 1.5;
|
||||||
const double kCryptoDurationInSeconds = 0; // Key rotation is disabled.
|
const double kCryptoDurationInSeconds = 0; // Key rotation is disabled.
|
||||||
|
|
||||||
|
@ -160,8 +156,7 @@ void PackagerTestBasic::Remux(const std::string& input,
|
||||||
ASSERT_OK(demuxer.Initialize());
|
ASSERT_OK(demuxer.Initialize());
|
||||||
|
|
||||||
scoped_ptr<KeySource> encryption_key_source(
|
scoped_ptr<KeySource> encryption_key_source(
|
||||||
KeySource::CreateFromHexStrings(
|
FixedKeySource::CreateFromHexStrings(kKeyIdHex, kKeyHex, "", ""));
|
||||||
kKeyIdHex, kKeyHex, kPsshHex, ""));
|
|
||||||
DCHECK(encryption_key_source);
|
DCHECK(encryption_key_source);
|
||||||
|
|
||||||
scoped_ptr<Muxer> muxer_video;
|
scoped_ptr<Muxer> muxer_video;
|
||||||
|
@ -219,7 +214,7 @@ void PackagerTestBasic::Decrypt(const std::string& input,
|
||||||
|
|
||||||
Demuxer demuxer(GetFullPath(input));
|
Demuxer demuxer(GetFullPath(input));
|
||||||
scoped_ptr<KeySource> decryption_key_source(
|
scoped_ptr<KeySource> decryption_key_source(
|
||||||
KeySource::CreateFromHexStrings(kKeyIdHex, kKeyHex, "", ""));
|
FixedKeySource::CreateFromHexStrings(kKeyIdHex, kKeyHex, "", ""));
|
||||||
ASSERT_TRUE(decryption_key_source);
|
ASSERT_TRUE(decryption_key_source);
|
||||||
demuxer.SetKeySource(decryption_key_source.Pass());
|
demuxer.SetKeySource(decryption_key_source.Pass());
|
||||||
ASSERT_OK(demuxer.Initialize());
|
ASSERT_OK(demuxer.Initialize());
|
||||||
|
|
Loading…
Reference in New Issue