Use FOURCC as protection scheme parameter

- Remove EncryptionMode enums
- Remove AesEncryptor::InitializeWithRandomIv, replaced with
  a static function AesCryptor::GenerateRandomIv, which should
  be called to generate the iv if the iv is empty.

This change is to prepare support for CBCS and CENS pattern-based
protection schemes.

Issue #77

Change-Id: Icba35089d6e451cbea7ebbf5dd5674079f206390
This commit is contained in:
KongQun Yang 2016-04-08 11:41:17 -07:00
parent 0218d9c690
commit 2ac57bf9b9
26 changed files with 197 additions and 204 deletions

View File

@ -25,7 +25,7 @@
#include "packager/base/time/clock.h" #include "packager/base/time/clock.h"
#include "packager/media/base/container_names.h" #include "packager/media/base/container_names.h"
#include "packager/media/base/demuxer.h" #include "packager/media/base/demuxer.h"
#include "packager/media/base/encryption_modes.h" #include "packager/media/base/fourccs.h"
#include "packager/media/base/key_source.h" #include "packager/media/base/key_source.h"
#include "packager/media/base/muxer_options.h" #include "packager/media/base/muxer_options.h"
#include "packager/media/base/muxer_util.h" #include "packager/media/base/muxer_util.h"
@ -105,15 +105,19 @@ std::string DetermineTextFileFormat(const std::string& file) {
return ""; return "";
} }
edash_packager::media::EncryptionMode GetEncryptionMode( edash_packager::media::FourCC GetProtectionScheme(
const std::string& protection_scheme) { const std::string& protection_scheme) {
if (protection_scheme == "cenc") { if (protection_scheme == "cenc") {
return edash_packager::media::kEncryptionModeAesCtr; return edash_packager::media::FOURCC_cenc;
} else if (protection_scheme == "cens") {
return edash_packager::media::FOURCC_cens;
} else if (protection_scheme == "cbc1") { } else if (protection_scheme == "cbc1") {
return edash_packager::media::kEncryptionModeAesCbc; return edash_packager::media::FOURCC_cbc1;
} else if (protection_scheme == "cbcs") {
return edash_packager::media::FOURCC_cbcs;
} else { } else {
LOG(ERROR) << "Unknown protection scheme: " << protection_scheme; LOG(ERROR) << "Unknown protection scheme: " << protection_scheme;
return edash_packager::media::kEncryptionModeUnknown; return edash_packager::media::FOURCC_NULL;
} }
} }
@ -310,7 +314,7 @@ bool CreateRemuxJobs(const StreamDescriptorList& stream_descriptors,
FLAGS_max_sd_pixels, FLAGS_max_sd_pixels,
FLAGS_clear_lead, FLAGS_clear_lead,
FLAGS_crypto_period_duration, FLAGS_crypto_period_duration,
GetEncryptionMode(FLAGS_protection_scheme)); GetProtectionScheme(FLAGS_protection_scheme));
} }
scoped_ptr<MuxerListener> muxer_listener; scoped_ptr<MuxerListener> muxer_listener;
@ -374,11 +378,11 @@ Status RunRemuxJobs(const std::vector<RemuxJob*>& remux_jobs) {
} }
bool RunPackager(const StreamDescriptorList& stream_descriptors) { bool RunPackager(const StreamDescriptorList& stream_descriptors) {
EncryptionMode encryption_mode = GetEncryptionMode(FLAGS_protection_scheme); const FourCC protection_scheme = GetProtectionScheme(FLAGS_protection_scheme);
if (encryption_mode == kEncryptionModeUnknown) if (protection_scheme == FOURCC_NULL)
return false; return false;
if (encryption_mode == kEncryptionModeAesCbc && !FLAGS_iv.empty()) { if (protection_scheme == FOURCC_cbc1 || protection_scheme == FOURCC_cbcs) {
if (FLAGS_iv.size() != 16) { if (!FLAGS_iv.empty() && FLAGS_iv.size() != 16) {
LOG(ERROR) << "Iv size should be 16 bytes for CBC encryption mode."; LOG(ERROR) << "Iv size should be 16 bytes for CBC encryption mode.";
return false; return false;
} }

View File

@ -7,6 +7,8 @@
#include "packager/media/base/aes_cryptor.h" #include "packager/media/base/aes_cryptor.h"
#include <openssl/aes.h> #include <openssl/aes.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include "packager/base/logging.h" #include "packager/base/logging.h"
#include "packager/base/stl_util.h" #include "packager/base/stl_util.h"
@ -53,6 +55,25 @@ size_t AesCryptor::NumPaddingBytes(size_t size) const {
return 0; return 0;
} }
bool AesCryptor::GenerateRandomIv(FourCC protection_scheme,
std::vector<uint8_t>* iv) {
// ISO/IEC 23001-7:2016 10.1 and 10.3 For 'cenc' and 'cens'
// default_Per_Sample_IV_Size and Per_Sample_IV_Size SHOULD be 8-bytes.
// There is no official guideline on the iv size for 'cbc1' and 'cbcs',
// but 16-byte provides better security.
const size_t iv_size =
(protection_scheme == FOURCC_cenc || protection_scheme == FOURCC_cens)
? 8
: 16;
iv->resize(iv_size);
if (RAND_bytes(iv->data(), iv_size) != 1) {
LOG(ERROR) << "RAND_bytes failed with error: "
<< ERR_error_string(ERR_get_error(), NULL);
return false;
}
return true;
}
} // namespace media } // namespace media
} // namespace edash_packager } // namespace edash_packager

View File

@ -12,6 +12,7 @@
#include "packager/base/macros.h" #include "packager/base/macros.h"
#include "packager/base/memory/scoped_ptr.h" #include "packager/base/memory/scoped_ptr.h"
#include "packager/media/base/fourccs.h"
struct aes_key_st; struct aes_key_st;
typedef struct aes_key_st AES_KEY; typedef struct aes_key_st AES_KEY;
@ -58,6 +59,13 @@ class AesCryptor {
/// @return The current iv. /// @return The current iv.
const std::vector<uint8_t>& iv() const { return iv_; } const std::vector<uint8_t>& iv() const { return iv_; }
/// @param protection_scheme specifies the protection scheme: 'cenc', 'cens',
/// 'cbc1', 'cbcs', which is useful to determine the random iv size.
/// @param iv points to generated initialization vector.
/// @return true on success, false otherwise.
static bool GenerateRandomIv(FourCC protection_scheme,
std::vector<uint8_t>* iv);
protected: protected:
void set_iv(const std::vector<uint8_t>& iv) { iv_ = iv; } void set_iv(const std::vector<uint8_t>& iv) { iv_ = iv; }
const AES_KEY* aes_key() const { return aes_key_.get(); } const AES_KEY* aes_key() const { return aes_key_.get(); }

View File

@ -220,12 +220,12 @@ TEST_F(AesCtrEncryptorTest, 128BitIVBoundaryCaseEncryption) {
EXPECT_EQ(encrypted, encrypted_verify); EXPECT_EQ(encrypted, encrypted_verify);
} }
TEST_F(AesCtrEncryptorTest, InitWithRandomIv) { TEST_F(AesCtrEncryptorTest, GenerateRandomIv) {
const uint8_t kIvSize = 8; const uint8_t kCencIvSize = 8;
ASSERT_TRUE(encryptor_.InitializeWithRandomIv(key_, kIvSize)); std::vector<uint8_t> iv;
ASSERT_EQ(kIvSize, encryptor_.iv().size()); ASSERT_TRUE(AesCryptor::GenerateRandomIv(FOURCC_cenc, &iv));
LOG(INFO) << "Random IV: " ASSERT_EQ(kCencIvSize, iv.size());
<< base::HexEncode(&encryptor_.iv()[0], encryptor_.iv().size()); LOG(INFO) << "Random IV: " << base::HexEncode(iv.data(), iv.size());
} }
TEST_F(AesCtrEncryptorTest, UnsupportedKeySize) { TEST_F(AesCtrEncryptorTest, UnsupportedKeySize) {
@ -238,10 +238,6 @@ TEST_F(AesCtrEncryptorTest, UnsupportedIV) {
ASSERT_FALSE(encryptor_.InitializeWithIv(key_, iv)); ASSERT_FALSE(encryptor_.InitializeWithIv(key_, iv));
} }
TEST_F(AesCtrEncryptorTest, IncorrectIvSize) {
ASSERT_FALSE(encryptor_.InitializeWithRandomIv(key_, 15));
}
class AesCtrEncryptorSubsampleTest class AesCtrEncryptorSubsampleTest
: public AesCtrEncryptorTest, : public AesCtrEncryptorTest,
public ::testing::WithParamInterface<SubsampleTestCase> {}; public ::testing::WithParamInterface<SubsampleTestCase> {};

View File

@ -7,8 +7,6 @@
#include "packager/media/base/aes_encryptor.h" #include "packager/media/base/aes_encryptor.h"
#include <openssl/aes.h> #include <openssl/aes.h>
#include <openssl/err.h>
#include <openssl/rand.h>
#include "packager/base/logging.h" #include "packager/base/logging.h"
@ -40,17 +38,6 @@ namespace media {
AesEncryptor::AesEncryptor() {} AesEncryptor::AesEncryptor() {}
AesEncryptor::~AesEncryptor() {} AesEncryptor::~AesEncryptor() {}
bool AesEncryptor::InitializeWithRandomIv(const std::vector<uint8_t>& key,
uint8_t iv_size) {
std::vector<uint8_t> iv(iv_size, 0);
if (RAND_bytes(iv.data(), iv_size) != 1) {
LOG(ERROR) << "RAND_bytes failed with error: "
<< ERR_error_string(ERR_get_error(), NULL);
return false;
}
return InitializeWithIv(key, iv);
}
bool AesEncryptor::InitializeWithIv(const std::vector<uint8_t>& key, bool AesEncryptor::InitializeWithIv(const std::vector<uint8_t>& key,
const std::vector<uint8_t>& iv) { const std::vector<uint8_t>& iv) {
if (!IsKeySizeValidForAes(key.size())) { if (!IsKeySizeValidForAes(key.size())) {

View File

@ -24,11 +24,6 @@ class AesEncryptor : public AesCryptor {
AesEncryptor(); AesEncryptor();
~AesEncryptor() override; ~AesEncryptor() override;
/// Initialize the encryptor with specified key and a random generated IV
/// of the specified size.
/// @return true on successful initialization, false otherwise.
bool InitializeWithRandomIv(const std::vector<uint8_t>& key, uint8_t iv_size);
/// Initialize the encryptor with specified key and IV. /// Initialize the encryptor with specified key and IV.
/// @return true on successful initialization, false otherwise. /// @return true on successful initialization, false otherwise.
bool InitializeWithIv(const std::vector<uint8_t>& key, bool InitializeWithIv(const std::vector<uint8_t>& key,

View File

@ -9,14 +9,19 @@
namespace edash_packager { namespace edash_packager {
namespace media { namespace media {
DecryptConfig::DecryptConfig(const std::vector<uint8_t>& key_id,
const std::vector<uint8_t>& iv,
const std::vector<SubsampleEntry>& subsamples)
: DecryptConfig(key_id, iv, subsamples, FOURCC_cenc) {}
DecryptConfig::DecryptConfig(const std::vector<uint8_t>& key_id, DecryptConfig::DecryptConfig(const std::vector<uint8_t>& key_id,
const std::vector<uint8_t>& iv, const std::vector<uint8_t>& iv,
const std::vector<SubsampleEntry>& subsamples, const std::vector<SubsampleEntry>& subsamples,
EncryptionMode decryption_mode) FourCC protection_scheme)
: key_id_(key_id), : key_id_(key_id),
iv_(iv), iv_(iv),
subsamples_(subsamples), subsamples_(subsamples),
decryption_mode_(decryption_mode) { protection_scheme_(protection_scheme) {
CHECK_GT(key_id.size(), 0u); CHECK_GT(key_id.size(), 0u);
} }

View File

@ -11,7 +11,7 @@
#include <vector> #include <vector>
#include "packager/base/memory/scoped_ptr.h" #include "packager/base/memory/scoped_ptr.h"
#include "packager/media/base/encryption_modes.h" #include "packager/media/base/fourccs.h"
namespace edash_packager { namespace edash_packager {
namespace media { namespace media {
@ -42,23 +42,35 @@ class DecryptConfig {
/// Keys are always 128 bits. /// Keys are always 128 bits.
static const size_t kDecryptionKeySize = 16; static const size_t kDecryptionKeySize = 16;
/// Create a 'cenc' decrypt config.
/// @param key_id is the ID that references the decryption key. /// @param key_id is the ID that references the decryption key.
/// @param iv is the initialization vector defined by the encryptor. /// @param iv is the initialization vector defined by the encryptor.
/// @param subsamples defines the clear and encrypted portions of the sample /// @param subsamples defines the clear and encrypted portions of the sample
/// as described in SubsampleEntry. A decrypted buffer will be equal /// as described in SubsampleEntry. A decrypted buffer will be equal
/// in size to the sum of the subsample sizes. /// in size to the sum of the subsample sizes.
/// @param decryption_mode decryption_mode is to determine which decryptor to DecryptConfig(const std::vector<uint8_t>& key_id,
/// use. const std::vector<uint8_t>& iv,
const std::vector<SubsampleEntry>& subsamples);
/// Create a general decrypt config with possible pattern-based encryption.
/// @param key_id is the ID that references the decryption key.
/// @param iv is the initialization vector defined by the encryptor.
/// @param subsamples defines the clear and encrypted portions of the sample
/// as described in SubsampleEntry. A decrypted buffer will be equal
/// in size to the sum of the subsample sizes.
/// @param protection_scheme specifies the protection scheme: 'cenc', 'cens',
/// 'cbc1', 'cbcs'.
DecryptConfig(const std::vector<uint8_t>& key_id, DecryptConfig(const std::vector<uint8_t>& key_id,
const std::vector<uint8_t>& iv, const std::vector<uint8_t>& iv,
const std::vector<SubsampleEntry>& subsamples, const std::vector<SubsampleEntry>& subsamples,
EncryptionMode decryption_mode); FourCC protection_scheme);
~DecryptConfig(); ~DecryptConfig();
const std::vector<uint8_t>& key_id() const { return key_id_; } const std::vector<uint8_t>& key_id() const { return key_id_; }
const std::vector<uint8_t>& iv() const { return iv_; } const std::vector<uint8_t>& iv() const { return iv_; }
const std::vector<SubsampleEntry>& subsamples() const { return subsamples_; } const std::vector<SubsampleEntry>& subsamples() const { return subsamples_; }
EncryptionMode decryption_mode() const { return decryption_mode_; } FourCC protection_scheme() const { return protection_scheme_; }
private: private:
const std::vector<uint8_t> key_id_; const std::vector<uint8_t> key_id_;
@ -70,7 +82,7 @@ class DecryptConfig {
// (less data ignored by data_offset_) is encrypted. // (less data ignored by data_offset_) is encrypted.
const std::vector<SubsampleEntry> subsamples_; const std::vector<SubsampleEntry> subsamples_;
EncryptionMode decryption_mode_; const FourCC protection_scheme_;
DISALLOW_COPY_AND_ASSIGN(DecryptConfig); DISALLOW_COPY_AND_ASSIGN(DecryptConfig);
}; };

View File

@ -8,6 +8,7 @@
#include "packager/base/logging.h" #include "packager/base/logging.h"
#include "packager/base/stl_util.h" #include "packager/base/stl_util.h"
#include "packager/media/base/aes_decryptor.h"
namespace edash_packager { namespace edash_packager {
namespace media { namespace media {
@ -39,16 +40,16 @@ bool DecryptorSource::DecryptSampleBuffer(const DecryptConfig* decrypt_config,
} }
scoped_ptr<AesCryptor> aes_decryptor; scoped_ptr<AesCryptor> aes_decryptor;
switch (decrypt_config->decryption_mode()) { switch (decrypt_config->protection_scheme()) {
case kEncryptionModeAesCtr: case FOURCC_cenc:
aes_decryptor.reset(new AesCtrDecryptor); aes_decryptor.reset(new AesCtrDecryptor);
break; break;
case kEncryptionModeAesCbc: case FOURCC_cbc1:
aes_decryptor.reset(new AesCbcDecryptor(kNoPadding, kChainAcrossCalls)); aes_decryptor.reset(new AesCbcDecryptor(kNoPadding, kChainAcrossCalls));
break; break;
default: default:
LOG(ERROR) << "Unsupported Decryption Mode: " LOG(ERROR) << "Unsupported protection scheme: "
<< decrypt_config->decryption_mode(); << decrypt_config->protection_scheme();
return false; return false;
} }

View File

@ -81,10 +81,9 @@ TEST_F(DecryptorSourceTest, FullSampleDecryption) {
DecryptConfig decrypt_config(key_id_, DecryptConfig decrypt_config(key_id_,
std::vector<uint8_t>(kIv, kIv + arraysize(kIv)), std::vector<uint8_t>(kIv, kIv + arraysize(kIv)),
std::vector<SubsampleEntry>(), std::vector<SubsampleEntry>());
kEncryptionModeAesCtr); ASSERT_TRUE(decryptor_source_.DecryptSampleBuffer(
ASSERT_TRUE(decryptor_source_.DecryptSampleBuffer(&decrypt_config, &buffer_[0], &decrypt_config, &buffer_[0], buffer_.size()));
buffer_.size()));
EXPECT_EQ(std::vector<uint8_t>( EXPECT_EQ(std::vector<uint8_t>(
kExpectedDecryptedBuffer, kExpectedDecryptedBuffer,
kExpectedDecryptedBuffer + arraysize(kExpectedDecryptedBuffer)), kExpectedDecryptedBuffer + arraysize(kExpectedDecryptedBuffer)),
@ -95,7 +94,7 @@ TEST_F(DecryptorSourceTest, FullSampleDecryption) {
buffer_.assign(kBuffer2, kBuffer2 + arraysize(kBuffer2)); buffer_.assign(kBuffer2, kBuffer2 + arraysize(kBuffer2));
DecryptConfig decrypt_config2( DecryptConfig decrypt_config2(
key_id_, std::vector<uint8_t>(kIv2, kIv2 + arraysize(kIv2)), key_id_, std::vector<uint8_t>(kIv2, kIv2 + arraysize(kIv2)),
std::vector<SubsampleEntry>(), kEncryptionModeAesCtr); std::vector<SubsampleEntry>());
ASSERT_TRUE(decryptor_source_.DecryptSampleBuffer( ASSERT_TRUE(decryptor_source_.DecryptSampleBuffer(
&decrypt_config2, &buffer_[0], buffer_.size())); &decrypt_config2, &buffer_[0], buffer_.size()));
EXPECT_EQ(std::vector<uint8_t>(kExpectedDecryptedBuffer2, EXPECT_EQ(std::vector<uint8_t>(kExpectedDecryptedBuffer2,
@ -130,8 +129,7 @@ TEST_F(DecryptorSourceTest, SubsampleDecryption) {
DecryptConfig decrypt_config( DecryptConfig decrypt_config(
key_id_, std::vector<uint8_t>(kIv, kIv + arraysize(kIv)), key_id_, std::vector<uint8_t>(kIv, kIv + arraysize(kIv)),
std::vector<SubsampleEntry>(kSubsamples, std::vector<SubsampleEntry>(kSubsamples,
kSubsamples + arraysize(kSubsamples)), kSubsamples + arraysize(kSubsamples)));
kEncryptionModeAesCtr);
ASSERT_TRUE(decryptor_source_.DecryptSampleBuffer( ASSERT_TRUE(decryptor_source_.DecryptSampleBuffer(
&decrypt_config, &buffer_[0], buffer_.size())); &decrypt_config, &buffer_[0], buffer_.size()));
EXPECT_EQ(std::vector<uint8_t>( EXPECT_EQ(std::vector<uint8_t>(
@ -155,8 +153,7 @@ TEST_F(DecryptorSourceTest, SubsampleDecryptionSizeValidation) {
DecryptConfig decrypt_config( DecryptConfig decrypt_config(
key_id_, std::vector<uint8_t>(kIv, kIv + arraysize(kIv)), key_id_, std::vector<uint8_t>(kIv, kIv + arraysize(kIv)),
std::vector<SubsampleEntry>(kSubsamples, std::vector<SubsampleEntry>(kSubsamples,
kSubsamples + arraysize(kSubsamples)), kSubsamples + arraysize(kSubsamples)));
kEncryptionModeAesCtr);
ASSERT_FALSE(decryptor_source_.DecryptSampleBuffer( ASSERT_FALSE(decryptor_source_.DecryptSampleBuffer(
&decrypt_config, &buffer_[0], buffer_.size())); &decrypt_config, &buffer_[0], buffer_.size()));
} }
@ -167,8 +164,7 @@ TEST_F(DecryptorSourceTest, DecryptFailedIfGetKeyFailed) {
DecryptConfig decrypt_config(key_id_, DecryptConfig decrypt_config(key_id_,
std::vector<uint8_t>(kIv, kIv + arraysize(kIv)), std::vector<uint8_t>(kIv, kIv + arraysize(kIv)),
std::vector<SubsampleEntry>(), std::vector<SubsampleEntry>());
kEncryptionModeAesCtr);
ASSERT_FALSE(decryptor_source_.DecryptSampleBuffer( ASSERT_FALSE(decryptor_source_.DecryptSampleBuffer(
&decrypt_config, &buffer_[0], buffer_.size())); &decrypt_config, &buffer_[0], buffer_.size()));
} }

View File

@ -1,23 +0,0 @@
// 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_ENCRYPTION_MODE_H_
#define MEDIA_BASE_ENCRYPTION_MODE_H_
namespace edash_packager {
namespace media {
/// Supported encryption mode.
enum EncryptionMode {
kEncryptionModeUnknown,
kEncryptionModeAesCtr,
kEncryptionModeAesCbc
};
} // namespace media
} // namespace edash_packager
#endif // MEDIA_BASE_ENCRYPTION_MODE_H_

View File

@ -21,7 +21,9 @@ enum FourCC {
FOURCC_avcC = 0x61766343, FOURCC_avcC = 0x61766343,
FOURCC_bloc = 0x626C6F63, FOURCC_bloc = 0x626C6F63,
FOURCC_cbc1 = 0x63626331, FOURCC_cbc1 = 0x63626331,
FOURCC_cbcs = 0x63626373,
FOURCC_cenc = 0x63656e63, FOURCC_cenc = 0x63656e63,
FOURCC_cens = 0x63656e73,
FOURCC_co64 = 0x636f3634, FOURCC_co64 = 0x636f3634,
FOURCC_ctim = 0x6374696d, FOURCC_ctim = 0x6374696d,
FOURCC_ctts = 0x63747473, FOURCC_ctts = 0x63747473,

View File

@ -6,6 +6,7 @@
#include "packager/media/base/muxer.h" #include "packager/media/base/muxer.h"
#include "packager/media/base/fourccs.h"
#include "packager/media/base/media_sample.h" #include "packager/media/base/media_sample.h"
#include "packager/media/base/media_stream.h" #include "packager/media/base/media_stream.h"
@ -19,7 +20,7 @@ Muxer::Muxer(const MuxerOptions& options)
max_sd_pixels_(0), max_sd_pixels_(0),
clear_lead_in_seconds_(0), clear_lead_in_seconds_(0),
crypto_period_duration_in_seconds_(0), crypto_period_duration_in_seconds_(0),
encryption_mode_(kEncryptionModeUnknown), protection_scheme_(FOURCC_NULL),
cancelled_(false), cancelled_(false),
clock_(NULL) {} clock_(NULL) {}
@ -29,13 +30,13 @@ void Muxer::SetKeySource(KeySource* encryption_key_source,
uint32_t max_sd_pixels, uint32_t max_sd_pixels,
double clear_lead_in_seconds, double clear_lead_in_seconds,
double crypto_period_duration_in_seconds, double crypto_period_duration_in_seconds,
EncryptionMode encryption_mode) { FourCC protection_scheme) {
DCHECK(encryption_key_source); DCHECK(encryption_key_source);
encryption_key_source_ = encryption_key_source; encryption_key_source_ = encryption_key_source;
max_sd_pixels_ = max_sd_pixels; max_sd_pixels_ = max_sd_pixels;
clear_lead_in_seconds_ = clear_lead_in_seconds; clear_lead_in_seconds_ = clear_lead_in_seconds;
crypto_period_duration_in_seconds_ = crypto_period_duration_in_seconds; crypto_period_duration_in_seconds_ = crypto_period_duration_in_seconds;
encryption_mode_ = encryption_mode; protection_scheme_ = protection_scheme;
} }
void Muxer::AddStream(MediaStream* stream) { void Muxer::AddStream(MediaStream* stream) {

View File

@ -14,7 +14,7 @@
#include "packager/base/memory/ref_counted.h" #include "packager/base/memory/ref_counted.h"
#include "packager/base/memory/scoped_ptr.h" #include "packager/base/memory/scoped_ptr.h"
#include "packager/base/time/clock.h" #include "packager/base/time/clock.h"
#include "packager/media/base/encryption_modes.h" #include "packager/media/base/fourccs.h"
#include "packager/media/base/muxer_options.h" #include "packager/media/base/muxer_options.h"
#include "packager/media/base/status.h" #include "packager/media/base/status.h"
#include "packager/media/event/muxer_listener.h" #include "packager/media/event/muxer_listener.h"
@ -45,11 +45,13 @@ class Muxer {
/// @param crypto_period_duration_in_seconds specifies crypto period duration /// @param crypto_period_duration_in_seconds specifies crypto period duration
/// in seconds. A positive value means key rotation is enabled, the /// in seconds. A positive value means key rotation is enabled, the
/// key source must support key rotation in this case. /// key source must support key rotation in this case.
/// @param protection_scheme specifies the protection scheme: 'cenc', 'cens',
/// 'cbc1', 'cbcs'.
void SetKeySource(KeySource* encryption_key_source, void SetKeySource(KeySource* encryption_key_source,
uint32_t max_sd_pixels, uint32_t max_sd_pixels,
double clear_lead_in_seconds, double clear_lead_in_seconds,
double crypto_period_duration_in_seconds, double crypto_period_duration_in_seconds,
EncryptionMode encryption_mode); FourCC protection_scheme);
/// Add video/audio stream. /// Add video/audio stream.
void AddStream(MediaStream* stream); void AddStream(MediaStream* stream);
@ -94,7 +96,7 @@ class Muxer {
MuxerListener* muxer_listener() { return muxer_listener_.get(); } MuxerListener* muxer_listener() { return muxer_listener_.get(); }
ProgressListener* progress_listener() { return progress_listener_.get(); } ProgressListener* progress_listener() { return progress_listener_.get(); }
base::Clock* clock() { return clock_; } base::Clock* clock() { return clock_; }
EncryptionMode encryption_mode() const { return encryption_mode_; } FourCC protection_scheme() const { return protection_scheme_; }
private: private:
friend class MediaStream; // Needed to access AddSample. friend class MediaStream; // Needed to access AddSample.
@ -120,7 +122,7 @@ class Muxer {
uint32_t max_sd_pixels_; uint32_t max_sd_pixels_;
double clear_lead_in_seconds_; double clear_lead_in_seconds_;
double crypto_period_duration_in_seconds_; double crypto_period_duration_in_seconds_;
EncryptionMode encryption_mode_; FourCC protection_scheme_;
bool cancelled_; bool cancelled_;
scoped_ptr<MuxerListener> muxer_listener_; scoped_ptr<MuxerListener> muxer_listener_;

View File

@ -22,9 +22,6 @@ namespace media {
namespace mp4 { namespace mp4 {
namespace { namespace {
// Generate 64bit IV by default.
const size_t kDefaultIvSizeForCtr = 8u;
const size_t kDefaultIvSizeForCbc = 16u;
const size_t kCencBlockSize = 16u; const size_t kCencBlockSize = 16u;
// Adds one or more subsamples to |*subsamples|. This may add more than one // Adds one or more subsamples to |*subsamples|. This may add more than one
@ -66,14 +63,14 @@ EncryptingFragmenter::EncryptingFragmenter(
TrackFragment* traf, TrackFragment* traf,
scoped_ptr<EncryptionKey> encryption_key, scoped_ptr<EncryptionKey> encryption_key,
int64_t clear_time, int64_t clear_time,
EncryptionMode encryption_mode) FourCC protection_scheme)
: Fragmenter(traf), : Fragmenter(traf),
info_(info), info_(info),
encryption_key_(encryption_key.Pass()), encryption_key_(encryption_key.Pass()),
nalu_length_size_(GetNaluLengthSize(*info)), nalu_length_size_(GetNaluLengthSize(*info)),
video_codec_(GetVideoCodec(*info)), video_codec_(GetVideoCodec(*info)),
clear_time_(clear_time), clear_time_(clear_time),
encryption_mode_(encryption_mode) { protection_scheme_(protection_scheme) {
DCHECK(encryption_key_); DCHECK(encryption_key_);
if (video_codec_ == kCodecVP8) { if (video_codec_ == kCodecVP8) {
vpx_parser_.reset(new VP8Parser); vpx_parser_.reset(new VP8Parser);
@ -175,22 +172,21 @@ void EncryptingFragmenter::FinalizeFragmentForEncryption() {
Status EncryptingFragmenter::CreateEncryptor() { Status EncryptingFragmenter::CreateEncryptor() {
DCHECK(encryption_key_); DCHECK(encryption_key_);
scoped_ptr<AesEncryptor> encryptor; scoped_ptr<AesCryptor> encryptor;
size_t default_iv_size = 0; switch (protection_scheme_) {
if (encryption_mode_ == kEncryptionModeAesCtr) { case FOURCC_cenc:
encryptor.reset(new AesCtrEncryptor); encryptor.reset(new AesCtrEncryptor);
default_iv_size = kDefaultIvSizeForCtr; break;
} else if (encryption_mode_ == kEncryptionModeAesCbc) { case FOURCC_cbc1:
encryptor.reset(new AesCbcEncryptor(kNoPadding, kChainAcrossCalls)); encryptor.reset(new AesCbcEncryptor(kNoPadding, kChainAcrossCalls));
default_iv_size = kDefaultIvSizeForCbc; break;
} else { default:
return Status(error::MUXER_FAILURE, "Unsupported encryption mode."); return Status(error::MUXER_FAILURE, "Unsupported protection scheme.");
} }
const bool initialized = encryption_key_->iv.empty()
? encryptor->InitializeWithRandomIv( DCHECK(!encryption_key_->iv.empty());
encryption_key_->key, default_iv_size) const bool initialized =
: encryptor->InitializeWithIv( encryptor->InitializeWithIv(encryption_key_->key, encryption_key_->iv);
encryption_key_->key, encryption_key_->iv);
if (!initialized) if (!initialized)
return Status(error::MUXER_FAILURE, "Failed to create the encryptor."); return Status(error::MUXER_FAILURE, "Failed to create the encryptor.");
encryptor_ = encryptor.Pass(); encryptor_ = encryptor.Pass();
@ -229,7 +225,7 @@ Status EncryptingFragmenter::EncryptSample(scoped_refptr<MediaSample> sample) {
// within the superframe. // within the superframe.
// For AES-CBC mode 'cbc1' scheme, clear data is sized appropriately so // For AES-CBC mode 'cbc1' scheme, clear data is sized appropriately so
// that the cipher data is block aligned. // that the cipher data is block aligned.
if (is_superframe || encryption_mode_ == kEncryptionModeAesCbc) { if (is_superframe || protection_scheme_ == FOURCC_cbc1) {
const uint16_t misalign_bytes = const uint16_t misalign_bytes =
subsample.cipher_bytes % kCencBlockSize; subsample.cipher_bytes % kCencBlockSize;
subsample.clear_bytes += misalign_bytes; subsample.clear_bytes += misalign_bytes;
@ -271,7 +267,7 @@ Status EncryptingFragmenter::EncryptSample(scoped_refptr<MediaSample> sample) {
// For AES-CBC mode 'cbc1' scheme, clear data is sized appropriately // For AES-CBC mode 'cbc1' scheme, clear data is sized appropriately
// so that the cipher data is block aligned. // so that the cipher data is block aligned.
if (encryption_mode_ == kEncryptionModeAesCbc) { if (protection_scheme_ == FOURCC_cbc1) {
const uint16_t misalign_bytes = cipher_bytes % kCencBlockSize; const uint16_t misalign_bytes = cipher_bytes % kCencBlockSize;
current_clear_bytes += misalign_bytes; current_clear_bytes += misalign_bytes;
cipher_bytes -= misalign_bytes; cipher_bytes -= misalign_bytes;
@ -303,7 +299,7 @@ Status EncryptingFragmenter::EncryptSample(scoped_refptr<MediaSample> sample) {
uint64_t encryption_data_size = sample->data_size(); uint64_t encryption_data_size = sample->data_size();
// AES-CBC mode requires all encrypted cipher blocks to be 16 bytes. The // AES-CBC mode requires all encrypted cipher blocks to be 16 bytes. The
// partial blocks are left unencrypted. // partial blocks are left unencrypted.
if (encryption_mode_ == kEncryptionModeAesCbc) if (protection_scheme_ == FOURCC_cbc1)
encryption_data_size -= encryption_data_size % kCencBlockSize; encryption_data_size -= encryption_data_size % kCencBlockSize;
EncryptBytes(data, encryption_data_size); EncryptBytes(data, encryption_data_size);
} }

View File

@ -9,7 +9,7 @@
#include "packager/base/memory/ref_counted.h" #include "packager/base/memory/ref_counted.h"
#include "packager/base/memory/scoped_ptr.h" #include "packager/base/memory/scoped_ptr.h"
#include "packager/media/base/encryption_modes.h" #include "packager/media/base/fourccs.h"
#include "packager/media/filters/vpx_parser.h" #include "packager/media/filters/vpx_parser.h"
#include "packager/media/formats/mp4/fragmenter.h" #include "packager/media/formats/mp4/fragmenter.h"
#include "packager/media/formats/mp4/video_slice_header_parser.h" #include "packager/media/formats/mp4/video_slice_header_parser.h"
@ -17,7 +17,7 @@
namespace edash_packager { namespace edash_packager {
namespace media { namespace media {
class AesEncryptor; class AesCryptor;
class StreamInfo; class StreamInfo;
struct EncryptionKey; struct EncryptionKey;
@ -30,11 +30,13 @@ class EncryptingFragmenter : public Fragmenter {
/// @param encryption_key contains the encryption parameters. /// @param encryption_key contains the encryption parameters.
/// @param clear_time specifies clear lead duration in units of the current /// @param clear_time specifies clear lead duration in units of the current
/// track's timescale. /// track's timescale.
/// @param protection_scheme specifies the protection scheme: 'cenc', 'cens',
/// 'cbc1', 'cbcs'.
EncryptingFragmenter(scoped_refptr<StreamInfo> info, EncryptingFragmenter(scoped_refptr<StreamInfo> info,
TrackFragment* traf, TrackFragment* traf,
scoped_ptr<EncryptionKey> encryption_key, scoped_ptr<EncryptionKey> encryption_key,
int64_t clear_time, int64_t clear_time,
EncryptionMode encryption_mode); FourCC protection_scheme);
~EncryptingFragmenter() override; ~EncryptingFragmenter() override;
@ -57,8 +59,9 @@ class EncryptingFragmenter : public Fragmenter {
/// @return OK on success, an error status otherwise. /// @return OK on success, an error status otherwise.
Status CreateEncryptor(); Status CreateEncryptor();
EncryptionKey* encryption_key() { return encryption_key_.get(); } const EncryptionKey* encryption_key() const { return encryption_key_.get(); }
AesEncryptor* encryptor() { return encryptor_.get(); } AesCryptor* encryptor() { return encryptor_.get(); }
FourCC protection_scheme() const { return protection_scheme_; }
void set_encryption_key(scoped_ptr<EncryptionKey> encryption_key) { void set_encryption_key(scoped_ptr<EncryptionKey> encryption_key) {
encryption_key_ = encryption_key.Pass(); encryption_key_ = encryption_key.Pass();
@ -73,14 +76,14 @@ class EncryptingFragmenter : public Fragmenter {
scoped_refptr<StreamInfo> info_; scoped_refptr<StreamInfo> info_;
scoped_ptr<EncryptionKey> encryption_key_; scoped_ptr<EncryptionKey> encryption_key_;
scoped_ptr<AesEncryptor> encryptor_; scoped_ptr<AesCryptor> encryptor_;
// If this stream contains AVC, subsample encryption specifies that the size // If this stream contains AVC, subsample encryption specifies that the size
// and type of NAL units remain unencrypted. This function returns the size of // and type of NAL units remain unencrypted. This function returns the size of
// the size field in bytes. Can be 1, 2 or 4 bytes. // the size field in bytes. Can be 1, 2 or 4 bytes.
const uint8_t nalu_length_size_; const uint8_t nalu_length_size_;
const VideoCodec video_codec_; const VideoCodec video_codec_;
int64_t clear_time_; int64_t clear_time_;
EncryptionMode encryption_mode_; FourCC protection_scheme_;
scoped_ptr<VPxParser> vpx_parser_; scoped_ptr<VPxParser> vpx_parser_;
scoped_ptr<VideoSliceHeaderParser> header_parser_; scoped_ptr<VideoSliceHeaderParser> header_parser_;

View File

@ -24,13 +24,13 @@ KeyRotationFragmenter::KeyRotationFragmenter(MovieFragment* moof,
KeySource::TrackType track_type, KeySource::TrackType track_type,
int64_t crypto_period_duration, int64_t crypto_period_duration,
int64_t clear_time, int64_t clear_time,
MuxerListener* muxer_listener, FourCC protection_scheme,
EncryptionMode encryption_mode) MuxerListener* muxer_listener)
: EncryptingFragmenter(info, : EncryptingFragmenter(info,
traf, traf,
scoped_ptr<EncryptionKey>(new EncryptionKey()), scoped_ptr<EncryptionKey>(new EncryptionKey()),
clear_time, clear_time,
encryption_mode), protection_scheme),
moof_(moof), moof_(moof),
encryption_key_source_(encryption_key_source), encryption_key_source_(encryption_key_source),
track_type_(track_type), track_type_(track_type),
@ -55,6 +55,12 @@ Status KeyRotationFragmenter::PrepareFragmentForEncryption(
current_crypto_period_index, track_type_, encryption_key.get()); current_crypto_period_index, track_type_, encryption_key.get());
if (!status.ok()) if (!status.ok())
return status; return status;
if (encryption_key->iv.empty()) {
if (!AesCryptor::GenerateRandomIv(protection_scheme(),
&encryption_key->iv)) {
return Status(error::INTERNAL_ERROR, "Failed to generate random iv.");
}
}
set_encryption_key(encryption_key.Pass()); set_encryption_key(encryption_key.Pass());
prev_crypto_period_index_ = current_crypto_period_index; prev_crypto_period_index_ = current_crypto_period_index;
need_to_refresh_encryptor = true; need_to_refresh_encryptor = true;

View File

@ -7,7 +7,7 @@
#ifndef MEDIA_FORMATS_MP4_KEY_ROTATION_FRAGMENTER_H_ #ifndef MEDIA_FORMATS_MP4_KEY_ROTATION_FRAGMENTER_H_
#define MEDIA_FORMATS_MP4_KEY_ROTATION_FRAGMENTER_H_ #define MEDIA_FORMATS_MP4_KEY_ROTATION_FRAGMENTER_H_
#include "packager/media/base/encryption_modes.h" #include "packager/media/base/fourccs.h"
#include "packager/media/base/key_source.h" #include "packager/media/base/key_source.h"
#include "packager/media/event/muxer_listener.h" #include "packager/media/event/muxer_listener.h"
#include "packager/media/formats/mp4/encrypting_fragmenter.h" #include "packager/media/formats/mp4/encrypting_fragmenter.h"
@ -32,6 +32,8 @@ class KeyRotationFragmenter : public EncryptingFragmenter {
/// of the current track's timescale. /// of the current track's timescale.
/// @param clear_time specifies clear lead duration in units of the current /// @param clear_time specifies clear lead duration in units of the current
/// track's timescale. /// track's timescale.
/// @param protection_scheme specifies the protection scheme: 'cenc', 'cens',
/// 'cbc1', 'cbcs'.
/// @param muxer_listener is a pointer to MuxerListener for notifying /// @param muxer_listener is a pointer to MuxerListener for notifying
/// muxer related events. This may be null. /// muxer related events. This may be null.
KeyRotationFragmenter(MovieFragment* moof, KeyRotationFragmenter(MovieFragment* moof,
@ -41,8 +43,8 @@ class KeyRotationFragmenter : public EncryptingFragmenter {
KeySource::TrackType track_type, KeySource::TrackType track_type,
int64_t crypto_period_duration, int64_t crypto_period_duration,
int64_t clear_time, int64_t clear_time,
MuxerListener* muxer_listener, FourCC protection_scheme,
EncryptionMode encryption_mode); MuxerListener* muxer_listener);
~KeyRotationFragmenter() override; ~KeyRotationFragmenter() override;
protected: protected:

View File

@ -147,15 +147,10 @@ Status MP4Muxer::Initialize() {
new MultiSegmentSegmenter(options(), ftyp.Pass(), moov.Pass())); new MultiSegmentSegmenter(options(), ftyp.Pass(), moov.Pass()));
} }
Status segmenter_initialized = const Status segmenter_initialized = segmenter_->Initialize(
segmenter_->Initialize(streams(), streams(), muxer_listener(), progress_listener(), encryption_key_source(),
muxer_listener(), max_sd_pixels(), clear_lead_in_seconds(),
progress_listener(), crypto_period_duration_in_seconds(), protection_scheme());
encryption_key_source(),
max_sd_pixels(),
clear_lead_in_seconds(),
crypto_period_duration_in_seconds(),
encryption_mode());
if (!segmenter_initialized.ok()) if (!segmenter_initialized.ok())
return segmenter_initialized; return segmenter_initialized;

View File

@ -9,6 +9,7 @@
#include <algorithm> #include <algorithm>
#include "packager/base/stl_util.h" #include "packager/base/stl_util.h"
#include "packager/media/base/aes_cryptor.h"
#include "packager/media/base/buffer_writer.h" #include "packager/media/base/buffer_writer.h"
#include "packager/media/base/key_source.h" #include "packager/media/base/key_source.h"
#include "packager/media/base/media_sample.h" #include "packager/media/base/media_sample.h"
@ -26,8 +27,6 @@ namespace mp4 {
namespace { namespace {
// Generate 64bit IV by default.
const size_t kDefaultIvSize = 8u;
const size_t kCencKeyIdSize = 16u; const size_t kCencKeyIdSize = 16u;
// The version of cenc implemented here. CENC 4. // The version of cenc implemented here. CENC 4.
@ -50,26 +49,24 @@ uint64_t Rescale(uint64_t time_in_old_scale,
void GenerateSinf(const EncryptionKey& encryption_key, void GenerateSinf(const EncryptionKey& encryption_key,
FourCC old_type, FourCC old_type,
EncryptionMode encryption_mode, FourCC protection_scheme,
ProtectionSchemeInfo* sinf) { ProtectionSchemeInfo* sinf) {
sinf->format.format = old_type; sinf->format.format = old_type;
if (encryption_mode == kEncryptionModeAesCtr){ DCHECK_NE(protection_scheme, FOURCC_NULL);
sinf->type.type = FOURCC_cenc; sinf->type.type = protection_scheme;
} else if (encryption_mode == kEncryptionModeAesCbc) {
sinf->type.type = FOURCC_cbc1;
}
sinf->type.version = kCencSchemeVersion; sinf->type.version = kCencSchemeVersion;
sinf->info.track_encryption.is_encrypted = true;
sinf->info.track_encryption.default_iv_size = auto& track_encryption = sinf->info.track_encryption;
encryption_key.iv.empty() ? kDefaultIvSize : encryption_key.iv.size(); track_encryption.is_encrypted = true;
sinf->info.track_encryption.default_kid = encryption_key.key_id; DCHECK(!encryption_key.iv.empty());
track_encryption.default_iv_size = encryption_key.iv.size();
track_encryption.default_kid = encryption_key.key_id;
} }
void GenerateEncryptedSampleEntry(const EncryptionKey& encryption_key, void GenerateEncryptedSampleEntry(const EncryptionKey& encryption_key,
double clear_lead_in_seconds, double clear_lead_in_seconds,
EncryptionMode encryption_mode, FourCC protection_scheme,
SampleDescription* description) { SampleDescription* description) {
DCHECK(description); DCHECK(description);
if (description->type == kVideo) { if (description->type == kVideo) {
@ -81,7 +78,7 @@ void GenerateEncryptedSampleEntry(const EncryptionKey& encryption_key,
// Convert the first entry to an encrypted entry. // Convert the first entry to an encrypted entry.
VideoSampleEntry& entry = description->video_entries[0]; VideoSampleEntry& entry = description->video_entries[0];
GenerateSinf(encryption_key, entry.format, encryption_mode, &entry.sinf); GenerateSinf(encryption_key, entry.format, protection_scheme, &entry.sinf);
entry.format = FOURCC_encv; entry.format = FOURCC_encv;
} else { } else {
DCHECK_EQ(kAudio, description->type); DCHECK_EQ(kAudio, description->type);
@ -93,7 +90,7 @@ void GenerateEncryptedSampleEntry(const EncryptionKey& encryption_key,
// Convert the first entry to an encrypted entry. // Convert the first entry to an encrypted entry.
AudioSampleEntry& entry = description->audio_entries[0]; AudioSampleEntry& entry = description->audio_entries[0];
GenerateSinf(encryption_key, entry.format, encryption_mode, &entry.sinf); GenerateSinf(encryption_key, entry.format, protection_scheme, &entry.sinf);
entry.format = FOURCC_enca; entry.format = FOURCC_enca;
} }
} }
@ -137,7 +134,7 @@ Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
uint32_t max_sd_pixels, uint32_t max_sd_pixels,
double clear_lead_in_seconds, double clear_lead_in_seconds,
double crypto_period_duration_in_seconds, double crypto_period_duration_in_seconds,
EncryptionMode encryption_mode) { FourCC protection_scheme) {
DCHECK_LT(0u, streams.size()); DCHECK_LT(0u, streams.size());
muxer_listener_ = muxer_listener; muxer_listener_ = muxer_listener;
progress_listener_ = progress_listener; progress_listener_ = progress_listener;
@ -173,8 +170,10 @@ Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
encryption_key.key_id.assign( encryption_key.key_id.assign(
kKeyRotationDefaultKeyId, kKeyRotationDefaultKeyId,
kKeyRotationDefaultKeyId + arraysize(kKeyRotationDefaultKeyId)); kKeyRotationDefaultKeyId + arraysize(kKeyRotationDefaultKeyId));
if (!AesCryptor::GenerateRandomIv(protection_scheme, &encryption_key.iv))
return Status(error::INTERNAL_ERROR, "Failed to generate random iv.");
GenerateEncryptedSampleEntry(encryption_key, clear_lead_in_seconds, GenerateEncryptedSampleEntry(encryption_key, clear_lead_in_seconds,
encryption_mode, &description); protection_scheme, &description);
if (muxer_listener_) { if (muxer_listener_) {
muxer_listener_->OnEncryptionInfoReady( muxer_listener_->OnEncryptionInfoReady(
kInitialEncryptionInfo, encryption_key.key_id, kInitialEncryptionInfo, encryption_key.key_id,
@ -186,7 +185,7 @@ Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
encryption_key_source, track_type, encryption_key_source, track_type,
crypto_period_duration_in_seconds * streams[i]->info()->time_scale(), crypto_period_duration_in_seconds * streams[i]->info()->time_scale(),
clear_lead_in_seconds * streams[i]->info()->time_scale(), clear_lead_in_seconds * streams[i]->info()->time_scale(),
muxer_listener_, encryption_mode); protection_scheme, muxer_listener_);
continue; continue;
} }
@ -195,9 +194,13 @@ Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
encryption_key_source->GetKey(track_type, encryption_key.get()); encryption_key_source->GetKey(track_type, encryption_key.get());
if (!status.ok()) if (!status.ok())
return status; return status;
if (encryption_key->iv.empty()) {
if (!AesCryptor::GenerateRandomIv(protection_scheme, &encryption_key->iv))
return Status(error::INTERNAL_ERROR, "Failed to generate random iv.");
}
GenerateEncryptedSampleEntry(*encryption_key, clear_lead_in_seconds, GenerateEncryptedSampleEntry(*encryption_key, clear_lead_in_seconds,
encryption_mode, &description); protection_scheme, &description);
if (moov_->pssh.empty()) { if (moov_->pssh.empty()) {
moov_->pssh.resize(encryption_key->key_system_info.size()); moov_->pssh.resize(encryption_key->key_system_info.size());
@ -215,7 +218,7 @@ Status Segmenter::Initialize(const std::vector<MediaStream*>& streams,
fragmenters_[i] = new EncryptingFragmenter( fragmenters_[i] = new EncryptingFragmenter(
streams[i]->info(), &moof_->tracks[i], encryption_key.Pass(), streams[i]->info(), &moof_->tracks[i], encryption_key.Pass(),
clear_lead_in_seconds * streams[i]->info()->time_scale(), clear_lead_in_seconds * streams[i]->info()->time_scale(),
encryption_mode); protection_scheme);
} }
// Choose the first stream if there is no VIDEO. // Choose the first stream if there is no VIDEO.

View File

@ -12,7 +12,7 @@
#include "packager/base/memory/ref_counted.h" #include "packager/base/memory/ref_counted.h"
#include "packager/base/memory/scoped_ptr.h" #include "packager/base/memory/scoped_ptr.h"
#include "packager/media/base/encryption_modes.h" #include "packager/media/base/fourccs.h"
#include "packager/media/base/status.h" #include "packager/media/base/status.h"
#include "packager/media/formats/mp4/box_definitions.h" #include "packager/media/formats/mp4/box_definitions.h"
@ -59,6 +59,8 @@ class Segmenter {
/// pixels per frame than max_sd_pixels, it is HD, SD otherwise. /// pixels per frame than max_sd_pixels, it is HD, SD otherwise.
/// @param clear_time specifies clear lead duration in seconds. /// @param clear_time specifies clear lead duration in seconds.
/// @param crypto_period_duration specifies crypto period duration in seconds. /// @param crypto_period_duration specifies crypto period duration in seconds.
/// @param protection_scheme specifies the protection scheme: 'senc', 'sens',
/// 'cbc1', 'cbcs'.
/// @return OK on success, an error status otherwise. /// @return OK on success, an error status otherwise.
Status Initialize(const std::vector<MediaStream*>& streams, Status Initialize(const std::vector<MediaStream*>& streams,
MuxerListener* muxer_listener, MuxerListener* muxer_listener,
@ -67,7 +69,7 @@ class Segmenter {
uint32_t max_sd_pixels, uint32_t max_sd_pixels,
double clear_lead_in_seconds, double clear_lead_in_seconds,
double crypto_period_duration_in_seconds, double crypto_period_duration_in_seconds,
EncryptionMode encryption_mode); FourCC protection_scheme);
/// Finalize the segmenter. /// Finalize the segmenter.
/// @return OK on success, an error status otherwise. /// @return OK on success, an error status otherwise.

View File

@ -8,7 +8,7 @@
#include <limits> #include <limits>
#include "packager/media/base/buffer_reader.h" #include "packager/media/base/buffer_reader.h"
#include "packager/media/base/encryption_modes.h" #include "packager/media/base/fourccs.h"
#include "packager/media/base/rcheck.h" #include "packager/media/base/rcheck.h"
#include "packager/media/formats/mp4/chunk_info_iterator.h" #include "packager/media/formats/mp4/chunk_info_iterator.h"
#include "packager/media/formats/mp4/composition_offset_iterator.h" #include "packager/media/formats/mp4/composition_offset_iterator.h"
@ -600,24 +600,10 @@ scoped_ptr<DecryptConfig> TrackRunIterator::GetDecryptConfig() {
FourCC protection_scheme = is_audio() ? audio_description().sinf.type.type FourCC protection_scheme = is_audio() ? audio_description().sinf.type.type
: video_description().sinf.type.type; : video_description().sinf.type.type;
EncryptionMode decryption_mode; return scoped_ptr<DecryptConfig>(
switch (protection_scheme) { new DecryptConfig(track_encryption().default_kid,
case FOURCC_cenc:
decryption_mode = kEncryptionModeAesCtr;
break;
case FOURCC_cbc1:
decryption_mode = kEncryptionModeAesCbc;
break;
default:
LOG(ERROR) << "Unsupported protection scheme.";
return scoped_ptr<DecryptConfig>();
}
return scoped_ptr<DecryptConfig>(new DecryptConfig(
track_encryption().default_kid,
sample_encryption_entry.initialization_vector, sample_encryption_entry.initialization_vector,
sample_encryption_entry.subsamples, sample_encryption_entry.subsamples, protection_scheme));
decryption_mode));
} }
} // namespace mp4 } // namespace mp4

View File

@ -7,6 +7,7 @@
#include "packager/media/formats/webm/encryptor.h" #include "packager/media/formats/webm/encryptor.h"
#include "packager/media/base/aes_encryptor.h" #include "packager/media/base/aes_encryptor.h"
#include "packager/media/base/fourccs.h"
#include "packager/media/base/media_sample.h" #include "packager/media/base/media_sample.h"
namespace edash_packager { namespace edash_packager {
@ -14,9 +15,6 @@ namespace media {
namespace webm { namespace webm {
namespace { namespace {
// Generate 64bit IV by default.
const size_t kDefaultIvSize = 8u;
Status CreateContentEncryption(mkvmuxer::Track* track, EncryptionKey* key) { Status CreateContentEncryption(mkvmuxer::Track* track, EncryptionKey* key) {
if (!track->AddContentEncoding()) { if (!track->AddContentEncoding()) {
return Status(error::INTERNAL_ERROR, return Status(error::INTERNAL_ERROR,
@ -107,13 +105,14 @@ Status Encryptor::CreateEncryptor(MuxerListener* muxer_listener,
Status status = key_source->GetKey(track_type, encryption_key.get()); Status status = key_source->GetKey(track_type, encryption_key.get());
if (!status.ok()) if (!status.ok())
return status; return status;
if (encryption_key->iv.empty()) {
if (!AesCryptor::GenerateRandomIv(FOURCC_cenc, &encryption_key->iv))
return Status(error::INTERNAL_ERROR, "Failed to generate random iv.");
}
scoped_ptr<AesCtrEncryptor> encryptor(new AesCtrEncryptor()); scoped_ptr<AesCtrEncryptor> encryptor(new AesCtrEncryptor());
const bool initialized = encryption_key->iv.empty() const bool initialized =
? encryptor->InitializeWithRandomIv( encryptor->InitializeWithIv(encryption_key->key, encryption_key->iv);
encryption_key->key, kDefaultIvSize)
: encryptor->InitializeWithIv(
encryption_key->key, encryption_key->iv);
if (!initialized) if (!initialized)
return Status(error::INTERNAL_ERROR, "Failed to create the encryptor."); return Status(error::INTERNAL_ERROR, "Failed to create the encryptor.");

View File

@ -6,7 +6,6 @@
#include "packager/base/logging.h" #include "packager/base/logging.h"
#include "packager/base/sys_byteorder.h" #include "packager/base/sys_byteorder.h"
#include "packager/media/base/encryption_modes.h"
#include "packager/media/formats/webm/webm_constants.h" #include "packager/media/formats/webm/webm_constants.h"
namespace edash_packager { namespace edash_packager {
@ -56,8 +55,7 @@ bool WebMCreateDecryptConfig(const uint8_t* data,
decrypt_config->reset(new DecryptConfig( decrypt_config->reset(new DecryptConfig(
std::vector<uint8_t>(key_id, key_id + key_id_size), std::vector<uint8_t>(key_id, key_id + key_id_size),
std::vector<uint8_t>(counter_block.begin(), counter_block.end()), std::vector<uint8_t>(counter_block.begin(), counter_block.end()),
std::vector<SubsampleEntry>(), std::vector<SubsampleEntry>()));
kEncryptionModeAesCtr));
*data_offset = frame_offset; *data_offset = frame_offset;
return true; return true;

View File

@ -6,6 +6,7 @@
#include "packager/media/formats/webm/webm_muxer.h" #include "packager/media/formats/webm/webm_muxer.h"
#include "packager/media/base/fourccs.h"
#include "packager/media/base/media_sample.h" #include "packager/media/base/media_sample.h"
#include "packager/media/base/media_stream.h" #include "packager/media/base/media_stream.h"
#include "packager/media/base/stream_info.h" #include "packager/media/base/stream_info.h"
@ -30,12 +31,11 @@ Status WebMMuxer::Initialize() {
"Key rotation is not implemented for WebM"); "Key rotation is not implemented for WebM");
} }
if (encryption_key_source() && (encryption_mode() != kEncryptionModeAesCtr)) { if (encryption_key_source() && (protection_scheme() != FOURCC_cenc)) {
NOTIMPLEMENTED() NOTIMPLEMENTED()
<< "WebM muxer does not support encryption mode other than AES-CTR."; << "WebM does not support protection scheme other than 'cenc'.";
return Status( return Status(error::UNIMPLEMENTED,
error::UNIMPLEMENTED, "WebM does not support protection scheme other than 'cenc'.");
"WebM muxer does not support encryption mode other than AES-CTR.");
} }
scoped_ptr<MkvWriter> writer(new MkvWriter); scoped_ptr<MkvWriter> writer(new MkvWriter);

View File

@ -11,8 +11,8 @@
#include "packager/base/strings/stringprintf.h" #include "packager/base/strings/stringprintf.h"
#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/fixed_key_source.h" #include "packager/media/base/fixed_key_source.h"
#include "packager/media/base/fourccs.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"
@ -174,10 +174,8 @@ void PackagerTestBasic::Remux(const std::string& input,
if (enable_encryption) { if (enable_encryption) {
muxer_video->SetKeySource(encryption_key_source.get(), muxer_video->SetKeySource(encryption_key_source.get(),
KeySource::TRACK_TYPE_SD, KeySource::TRACK_TYPE_SD, kClearLeadInSeconds,
kClearLeadInSeconds, kCryptoDurationInSeconds, FOURCC_cenc);
kCryptoDurationInSeconds,
kEncryptionModeAesCtr);
} }
} }
@ -196,10 +194,8 @@ void PackagerTestBasic::Remux(const std::string& input,
if (enable_encryption) { if (enable_encryption) {
muxer_audio->SetKeySource(encryption_key_source.get(), muxer_audio->SetKeySource(encryption_key_source.get(),
KeySource::TRACK_TYPE_SD, KeySource::TRACK_TYPE_SD, kClearLeadInSeconds,
kClearLeadInSeconds, kCryptoDurationInSeconds, FOURCC_cenc);
kCryptoDurationInSeconds,
kEncryptionModeAesCtr);
} }
} }