7 #include "packager/media/crypto/encryption_handler.h" 14 #include "packager/media/base/aes_encryptor.h" 15 #include "packager/media/base/audio_stream_info.h" 16 #include "packager/media/base/key_source.h" 17 #include "packager/media/base/macros.h" 18 #include "packager/media/base/media_sample.h" 19 #include "packager/media/base/video_stream_info.h" 20 #include "packager/media/crypto/aes_encryptor_factory.h" 21 #include "packager/media/crypto/subsample_generator.h" 22 #include "packager/status_macros.h" 29 const size_t kStreamIndex = 0;
33 const uint8_t kKeyRotationDefaultKeyId[] = {
34 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36 const uint8_t kKeyRotationDefaultKey[] = {
37 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
39 const uint8_t kKeyRotationDefaultIv[] = {
40 0, 0, 0, 0, 0, 0, 0, 0,
43 std::string GetStreamLabelForEncryption(
44 const StreamInfo& stream_info,
45 const std::function<std::string(
46 const EncryptionParams::EncryptedStreamAttributes& stream_attributes)>&
48 EncryptionParams::EncryptedStreamAttributes stream_attributes;
49 if (stream_info.stream_type() == kStreamAudio) {
50 stream_attributes.stream_type =
51 EncryptionParams::EncryptedStreamAttributes::kAudio;
52 }
else if (stream_info.stream_type() == kStreamVideo) {
53 const VideoStreamInfo& video_stream_info =
54 static_cast<const VideoStreamInfo&
>(stream_info);
55 stream_attributes.stream_type =
56 EncryptionParams::EncryptedStreamAttributes::kVideo;
57 stream_attributes.oneof.video.width = video_stream_info.width();
58 stream_attributes.oneof.video.height = video_stream_info.height();
60 return stream_label_func(stream_attributes);
63 bool IsPatternEncryptionScheme(FourCC protection_scheme) {
64 return protection_scheme == kAppleSampleAesProtectionScheme ||
65 protection_scheme == FOURCC_cbcs || protection_scheme == FOURCC_cens;
70 EncryptionHandler::EncryptionHandler(
const EncryptionParams& encryption_params,
71 KeySource* key_source)
72 : encryption_params_(encryption_params),
74 static_cast<FourCC>(encryption_params.protection_scheme)),
75 key_source_(key_source),
77 new SubsampleGenerator(encryption_params.vp9_subsample_encryption)),
78 encryptor_factory_(new AesEncryptorFactory) {}
80 EncryptionHandler::~EncryptionHandler() =
default;
83 if (!encryption_params_.stream_label_func) {
84 return Status(error::INVALID_ARGUMENT,
"Stream label function not set.");
86 if (num_input_streams() != 1 || next_output_stream_index() != 1) {
87 return Status(error::INVALID_ARGUMENT,
88 "Expects exactly one input and output.");
94 switch (stream_data->stream_data_type) {
95 case StreamDataType::kStreamInfo:
96 return ProcessStreamInfo(*stream_data->stream_info);
97 case StreamDataType::kSegmentInfo: {
98 std::shared_ptr<SegmentInfo> segment_info(
new SegmentInfo(
99 *stream_data->segment_info));
101 segment_info->is_encrypted = remaining_clear_lead_ <= 0;
103 const bool key_rotation_enabled = crypto_period_duration_ != 0;
104 if (key_rotation_enabled)
105 segment_info->key_rotation_encryption_config = encryption_config_;
106 if (!segment_info->is_subsegment) {
107 if (key_rotation_enabled)
108 check_new_crypto_period_ =
true;
109 if (remaining_clear_lead_ > 0)
110 remaining_clear_lead_ -= segment_info->duration;
113 return DispatchSegmentInfo(kStreamIndex, segment_info);
115 case StreamDataType::kMediaSample:
116 return ProcessMediaSample(std::move(stream_data->media_sample));
118 VLOG(3) <<
"Stream data type " 119 <<
static_cast<int>(stream_data->stream_data_type) <<
" ignored.";
120 return Dispatch(std::move(stream_data));
125 if (clear_info.is_encrypted()) {
126 return Status(error::INVALID_ARGUMENT,
127 "Input stream is already encrypted.");
130 DCHECK_NE(kStreamUnknown, clear_info.stream_type());
131 DCHECK_NE(kStreamText, clear_info.stream_type());
132 std::shared_ptr<StreamInfo> stream_info = clear_info.
Clone();
134 subsample_generator_->Initialize(protection_scheme_, *stream_info));
136 remaining_clear_lead_ =
137 encryption_params_.clear_lead_in_seconds * stream_info->time_scale();
138 crypto_period_duration_ =
139 encryption_params_.crypto_period_duration_in_seconds *
140 stream_info->time_scale();
141 codec_ = stream_info->codec();
142 stream_label_ = GetStreamLabelForEncryption(
143 *stream_info, encryption_params_.stream_label_func);
145 SetupProtectionPattern(stream_info->stream_type());
148 const bool key_rotation_enabled = crypto_period_duration_ != 0;
149 if (key_rotation_enabled) {
150 check_new_crypto_period_ =
true;
152 encryption_key.key_id.assign(std::begin(kKeyRotationDefaultKeyId),
153 std::end(kKeyRotationDefaultKeyId));
154 encryption_key.key.assign(std::begin(kKeyRotationDefaultKey),
155 std::end(kKeyRotationDefaultKey));
156 encryption_key.iv.assign(std::begin(kKeyRotationDefaultIv),
157 std::end(kKeyRotationDefaultIv));
159 RETURN_IF_ERROR(key_source_->GetKey(stream_label_, &encryption_key));
161 if (!CreateEncryptor(encryption_key))
162 return Status(error::ENCRYPTION_FAILURE,
"Failed to create encryptor");
164 stream_info->set_is_encrypted(
true);
165 stream_info->set_has_clear_lead(encryption_params_.clear_lead_in_seconds > 0);
166 stream_info->set_encryption_config(*encryption_config_);
168 return DispatchStreamInfo(kStreamIndex, stream_info);
171 Status EncryptionHandler::ProcessMediaSample(
172 std::shared_ptr<const MediaSample> clear_sample) {
173 DCHECK(clear_sample);
177 std::vector<SubsampleEntry> subsamples;
178 RETURN_IF_ERROR(subsample_generator_->GenerateSubsamples(
179 clear_sample->data(), clear_sample->data_size(), &subsamples));
184 if (check_new_crypto_period_) {
187 const int64_t dts = std::max(clear_sample->dts(),
static_cast<int64_t
>(0));
188 const int64_t current_crypto_period_index = dts / crypto_period_duration_;
189 if (current_crypto_period_index != prev_crypto_period_index_) {
191 RETURN_IF_ERROR(key_source_->GetCryptoPeriodKey(
192 current_crypto_period_index, stream_label_, &encryption_key));
193 if (!CreateEncryptor(encryption_key))
194 return Status(error::ENCRYPTION_FAILURE,
"Failed to create encryptor");
195 prev_crypto_period_index_ = current_crypto_period_index;
197 check_new_crypto_period_ =
false;
202 if (remaining_clear_lead_ > 0) {
203 return DispatchMediaSample(kStreamIndex, std::move(clear_sample));
206 std::shared_ptr<uint8_t> cipher_sample_data(
207 new uint8_t[clear_sample->data_size()], std::default_delete<uint8_t[]>());
209 const uint8_t* source = clear_sample->data();
210 uint8_t* dest = cipher_sample_data.get();
211 if (!subsamples.empty()) {
212 size_t total_size = 0;
214 if (subsample.clear_bytes > 0) {
215 memcpy(dest, source, subsample.clear_bytes);
216 source += subsample.clear_bytes;
217 dest += subsample.clear_bytes;
218 total_size += subsample.clear_bytes;
220 if (subsample.cipher_bytes > 0) {
221 EncryptBytes(source, subsample.cipher_bytes, dest);
222 source += subsample.cipher_bytes;
223 dest += subsample.cipher_bytes;
224 total_size += subsample.cipher_bytes;
227 DCHECK_EQ(total_size, clear_sample->data_size());
229 EncryptBytes(source, clear_sample->data_size(), dest);
232 std::shared_ptr<MediaSample> cipher_sample(clear_sample->Clone());
233 cipher_sample->TransferData(std::move(cipher_sample_data),
234 clear_sample->data_size());
239 cipher_sample->set_is_encrypted(
true);
240 std::unique_ptr<DecryptConfig> decrypt_config(
new DecryptConfig(
241 encryption_config_->key_id, encryptor_->iv(), subsamples,
242 protection_scheme_, crypt_byte_block_, skip_byte_block_));
243 cipher_sample->set_decrypt_config(std::move(decrypt_config));
245 encryptor_->UpdateIv();
247 return DispatchMediaSample(kStreamIndex, std::move(cipher_sample));
250 void EncryptionHandler::SetupProtectionPattern(StreamType stream_type) {
251 if (stream_type == kStreamVideo &&
252 IsPatternEncryptionScheme(protection_scheme_)) {
254 crypt_byte_block_ = 1u;
255 skip_byte_block_ = 9u;
260 crypt_byte_block_ = 0u;
261 skip_byte_block_ = 0u;
265 bool EncryptionHandler::CreateEncryptor(
const EncryptionKey& encryption_key) {
266 std::unique_ptr<AesCryptor> encryptor = encryptor_factory_->CreateEncryptor(
267 protection_scheme_, crypt_byte_block_, skip_byte_block_, codec_,
268 encryption_key.key, encryption_key.iv);
271 encryptor_ = std::move(encryptor);
274 encryption_config_->protection_scheme = protection_scheme_;
275 encryption_config_->crypt_byte_block = crypt_byte_block_;
276 encryption_config_->skip_byte_block = skip_byte_block_;
278 const std::vector<uint8_t>& iv = encryptor_->iv();
279 if (encryptor_->use_constant_iv()) {
280 encryption_config_->per_sample_iv_size = 0;
281 encryption_config_->constant_iv = iv;
283 encryption_config_->per_sample_iv_size =
static_cast<uint8_t
>(iv.size());
286 encryption_config_->key_id = encryption_key.key_id;
287 encryption_config_->key_system_info = encryption_key.key_system_info;
291 void EncryptionHandler::EncryptBytes(
const uint8_t* source,
297 CHECK(encryptor_->Crypt(source, source_size, dest));
300 void EncryptionHandler::InjectSubsampleGeneratorForTesting(
301 std::unique_ptr<SubsampleGenerator> generator) {
302 subsample_generator_ = std::move(generator);
305 void EncryptionHandler::InjectEncryptorFactoryForTesting(
306 std::unique_ptr<AesEncryptorFactory> encryptor_factory) {
307 encryptor_factory_ = std::move(encryptor_factory);
All the methods that are virtual are virtual for mocking.