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:
Jacob Trimble 2016-02-19 12:23:37 -08:00
parent e39c3572af
commit d5cdd00ba1
21 changed files with 384 additions and 195 deletions

View File

@ -22,7 +22,11 @@ DEFINE_string(iv,
"",
"Iv in hex string format. If not specified, a random iv will be "
"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 {
@ -51,7 +55,7 @@ bool ValidateFixedCryptoFlags() {
if (!ValidateFlag("pssh",
FLAGS_pssh,
FLAGS_enable_fixed_key_encryption,
false,
true,
"--enable_fixed_key_encryption")) {
success = false;
}

View File

@ -15,6 +15,7 @@
#include "packager/app/widevine_encryption_flags.h"
#include "packager/base/logging.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/muxer.h"
#include "packager/media/base/muxer_options.h"
@ -100,7 +101,7 @@ scoped_ptr<KeySource> CreateEncryptionKeySource() {
}
encryption_key_source = widevine_key_source.Pass();
} 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);
}
return encryption_key_source.Pass();
@ -120,8 +121,10 @@ scoped_ptr<KeySource> CreateDecryptionKeySource() {
decryption_key_source = widevine_key_source.Pass();
} else if (FLAGS_enable_fixed_key_decryption) {
decryption_key_source =
KeySource::CreateFromHexStrings(FLAGS_key_id, FLAGS_key, "", "");
const char kNoPssh[] = "";
const char kNoIv[] = "";
decryption_key_source = FixedKeySource::CreateFromHexStrings(
FLAGS_key_id, FLAGS_key, kNoPssh, kNoIv);
}
return decryption_key_source.Pass();
}

View File

@ -389,10 +389,14 @@ class PackagerAppTest(unittest.TestCase):
'--key_server_url=' + widevine_server_url,
'--content_id=3031323334353637', '--signer=widevine_test']
elif encryption:
pssh_box = ('000000307073736800000000' # PSSH header
'edef8ba979d64acea3c827dcd51d21ed' # Widevine system ID
'00000010' # Data size
'31323334353637383930313233343536') # Data
flags += ['--enable_fixed_key_encryption',
'--key_id=31323334353637383930313233343536',
'--key=32333435363738393021323334353637',
'--pssh=31323334353637383930313233343536', '--clear_lead=1']
'--pssh=' + pssh_box, '--clear_lead=1']
if not random_iv:
flags.append('--iv=3334353637383930')
if key_rotation:

View File

@ -10,6 +10,7 @@
#include <gtest/gtest.h>
#include "packager/base/macros.h"
#include "packager/media/base/fixed_key_source.h"
using ::testing::Return;
using ::testing::SetArgPointee;
@ -50,7 +51,7 @@ const uint8_t kBuffer2[] = {0x05, 0x02};
// Expected decrypted buffer with the above kMockKey and kIv2.
const uint8_t kExpectedDecryptedBuffer2[] = {0x20, 0x62};
class MockKeySource : public KeySource {
class MockKeySource : public FixedKeySource {
public:
MOCK_METHOD2(GetKey,
Status(const std::vector<uint8_t>& key_id, EncryptionKey* key));

View File

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

View File

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

View File

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

View File

@ -6,9 +6,7 @@
#include "packager/media/base/key_source.h"
#include "packager/base/strings/string_number_conversions.h"
#include "packager/media/base/aes_encryptor.h"
#include "packager/media/base/buffer_writer.h"
#include "packager/base/logging.h"
namespace edash_packager {
namespace media {
@ -18,127 +16,6 @@ EncryptionKey::~EncryptionKey() {}
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(
const std::string& track_type_string) {
if (track_type_string == "SD")
@ -168,10 +45,6 @@ std::string KeySource::TrackTypeToString(TrackType track_type) {
}
KeySource::KeySource() {}
KeySource::KeySource(scoped_ptr<EncryptionKey> encryption_key)
: encryption_key_(encryption_key.Pass()) {
DCHECK(encryption_key_);
}
} // namespace media
} // namespace edash_packager

View File

@ -17,10 +17,6 @@
namespace edash_packager {
namespace media {
const uint8_t kWidevineSystemId[] = {0xed, 0xef, 0x8b, 0xa9, 0x79, 0xd6,
0x4a, 0xce, 0xa3, 0xc8, 0x27, 0xdc,
0xd5, 0x1d, 0x21, 0xed};
struct EncryptionKey {
EncryptionKey();
~EncryptionKey();
@ -43,44 +39,40 @@ class KeySource {
NUM_VALID_TRACK_TYPES = 4
};
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.
/// @param pssh_box The entire PSSH box for the content to be decrypted
/// @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.
/// @param key_ids the key IDs for the keys to fetch from the server.
/// @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.
/// @param asset_id is the Widevine Classic asset ID for the content to be
/// decrypted.
/// @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.
/// @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
/// key. Owner retains ownership, and may not be NULL.
/// @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.
/// @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
/// key. Owner retains ownership, and may not be NULL.
/// @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.
/// @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.
virtual Status GetCryptoPeriodKey(uint32_t crypto_period_index,
TrackType track_type,
EncryptionKey* key);
/// 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);
EncryptionKey* key) = 0;
/// Convert string representation of track type to enum representation.
static TrackType GetTrackTypeFromString(const std::string& track_type_string);
@ -113,14 +91,7 @@ class KeySource {
/// Convert TrackType to string.
static std::string TrackTypeToString(TrackType track_type);
protected:
KeySource();
private:
explicit KeySource(scoped_ptr<EncryptionKey> encryption_key);
scoped_ptr<EncryptionKey> encryption_key_;
DISALLOW_COPY_AND_ASSIGN(KeySource);
};

View File

@ -40,6 +40,8 @@
'decryptor_source.cc',
'decryptor_source.h',
'encryption_modes.h',
'fixed_key_source.cc',
'fixed_key_source.h',
'http_key_fetcher.cc',
'http_key_fetcher.h',
'key_fetcher.cc',
@ -118,6 +120,7 @@
'closure_thread_unittest.cc',
'container_names_unittest.cc',
'decryptor_source_unittest.cc',
'fixed_key_source_unittest.cc',
'http_key_fetcher_unittest.cc',
'muxer_util_unittest.cc',
'offset_byte_queue_unittest.cc',

View File

@ -47,6 +47,10 @@ const int kDefaultCryptoPeriodCount = 10;
const int kGetKeyTimeoutInSeconds = 5 * 60; // 5 minutes.
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,
std::vector<uint8_t>* bytes) {
DCHECK(bytes);

View File

@ -32,8 +32,6 @@ class WidevineKeySource : public KeySource {
/// @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<std::vector<uint8_t>>& key_ids) override;
Status FetchKeys(uint32_t asset_id) override;
@ -46,6 +44,13 @@ class WidevineKeySource : public KeySource {
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.
/// @param signer signs the request message.
void set_signer(scoped_ptr<RequestSigner> signer);

View File

@ -154,7 +154,7 @@ TEST_F(MpdNotifyMuxerListenerTest, VodEncryptedContent) {
std::string(kExpectedDefaultMediaInfo) +
"protected_content {\n"
" content_protection_entry {\n"
" uuid: 'edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'\n"
" uuid: '00010203-0405-0607-0809-0a0b0c0d0e0f'\n"
" pssh: '" + std::string(kExpectedDefaultPsshBox) + "'\n"
" }\n"
" default_key_id: 'defaultkeyid'\n"
@ -286,7 +286,7 @@ TEST_F(MpdNotifyMuxerListenerTest, LiveNoKeyRotation) {
"protected_content {\n"
" default_key_id: \"defaultkeyid\"\n"
" content_protection_entry {\n"
" uuid: 'edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'\n"
" uuid: '00010203-0405-0607-0809-0a0b0c0d0e0f'\n"
" pssh: \"" + std::string(kExpectedDefaultPsshBox) + "\"\n"
" }\n"
"}\n";

View File

@ -96,9 +96,12 @@ void SetDefaultMuxerOptionsValues(MuxerOptions* muxer_options) {
std::vector<ProtectionSystemSpecificInfo> GetDefaultKeySystemInfo() {
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;
info.set_system_id(kWidevineSystemId, arraysize(kWidevineSystemId));
info.set_system_id(kTestSystemId, arraysize(kTestSystemId));
info.set_pssh_data(
std::vector<uint8_t>(kPsshData, kPsshData + arraysize(kPsshData)));
info.set_pssh_box_version(0);

View File

@ -25,8 +25,8 @@ namespace media {
// This is a full v0 PSSH box with the Widevine system ID and the PSSH data
// 'pssh'
const char kExpectedDefaultPsshBox[] =
"\\000\\000\\000$pssh\\000\\000\\000\\000\\355\\357\\213\\251y\\326J\\316"
"\\243\\310\\'\\334\\325\\035!\\355\\000\\000\\000\\4pssh";
"\\000\\000\\000$pssh\\000\\000\\000\\000\\000\\001\\002\\003\\004\\005"
"\\006\\007\\010\\t\\n\\013\\014\\r\\016\\017\\000\\000\\000\\004pssh";
const char kExpectedDefaultMediaInfo[] =
"bandwidth: 7620\n"
"video_info {\n"

View File

@ -179,7 +179,7 @@ TEST_F(VodMediaInfoDumpMuxerListenerTest, EncryptedStream_Normal) {
"media_duration_seconds: 10.5\n"
"protected_content {\n"
" content_protection_entry {\n"
" uuid: 'edef8ba9-79d6-4ace-a3c8-27dcd51d21ed'\n"
" uuid: '00010203-0405-0607-0809-0a0b0c0d0e0f'\n"
" pssh: '" + std::string(kExpectedDefaultPsshBox) + "'\n"
" }\n"
" default_key_id: '_default_key_id_'\n"

View File

@ -9,7 +9,7 @@
#include "packager/base/bind.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/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";
const char kKeyId[] = "0123456789012345";
class MockKeySource : public KeySource {
class MockKeySource : public FixedKeySource {
public:
MOCK_METHOD1(FetchKeys, Status(const std::vector<uint8_t>& pssh_data));
MOCK_METHOD2(GetKey,

View File

@ -8,6 +8,7 @@
#include <gtest/gtest.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"
namespace edash_packager {
@ -189,7 +190,8 @@ class EncrypedSegmenterTest : public SegmentTestBase {
protected:
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(
CreateAndInitializeSegmenter<webm::SingleSegmentSegmenter>(
options, info_.get(), key_source_.get(), &segmenter_));

View File

@ -16,6 +16,7 @@
#include "packager/base/logging.h"
#include "packager/base/strings/string_number_conversions.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/formats/webm/cluster_builder.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,
};
class MockKeySource : public KeySource {
class MockKeySource : public FixedKeySource {
public:
MOCK_METHOD2(GetKey,
Status(const std::vector<uint8_t>& key_id, EncryptionKey* key));

View File

@ -13,12 +13,12 @@
#include "packager/base/logging.h"
#include "packager/base/memory/ref_counted.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/request_signer.h"
#include "packager/media/base/stream_info.h"
#include "packager/media/base/timestamp.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/test/test_data_util.h"
@ -49,7 +49,7 @@ using ::testing::SetArgPointee;
namespace edash_packager {
namespace media {
class MockKeySource : public KeySource {
class MockKeySource : public FixedKeySource {
public:
MockKeySource() {}
~MockKeySource() override {}

View File

@ -12,7 +12,7 @@
#include "packager/base/time/clock.h"
#include "packager/media/base/demuxer.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/muxer.h"
#include "packager/media/base/stream_info.h"
@ -54,10 +54,6 @@ const char kNoLanguageOverride[] = "";
// Encryption constants.
const char kKeyIdHex[] = "e5007e6e9dcd5ac095202ed3758382cd";
const char kKeyHex[] = "6fc96fe628a265b13aeddec0bc421f4d";
const char kPsshHex[] =
"08011210e5007e6e9dcd5ac095202ed3"
"758382cd1a0d7769646576696e655f746573742211544553545f"
"434f4e54454e545f49445f312a025344";
const double kClearLeadInSeconds = 1.5;
const double kCryptoDurationInSeconds = 0; // Key rotation is disabled.
@ -160,8 +156,7 @@ void PackagerTestBasic::Remux(const std::string& input,
ASSERT_OK(demuxer.Initialize());
scoped_ptr<KeySource> encryption_key_source(
KeySource::CreateFromHexStrings(
kKeyIdHex, kKeyHex, kPsshHex, ""));
FixedKeySource::CreateFromHexStrings(kKeyIdHex, kKeyHex, "", ""));
DCHECK(encryption_key_source);
scoped_ptr<Muxer> muxer_video;
@ -219,7 +214,7 @@ void PackagerTestBasic::Decrypt(const std::string& input,
Demuxer demuxer(GetFullPath(input));
scoped_ptr<KeySource> decryption_key_source(
KeySource::CreateFromHexStrings(kKeyIdHex, kKeyHex, "", ""));
FixedKeySource::CreateFromHexStrings(kKeyIdHex, kKeyHex, "", ""));
ASSERT_TRUE(decryption_key_source);
demuxer.SetKeySource(decryption_key_source.Pass());
ASSERT_OK(demuxer.Initialize());