7 #include "packager/media/crypto/encryption_handler.h" 15 #include "packager/media/base/aes_encryptor.h" 16 #include "packager/media/base/aes_pattern_cryptor.h" 17 #include "packager/media/base/audio_stream_info.h" 18 #include "packager/media/base/key_source.h" 19 #include "packager/media/base/media_sample.h" 20 #include "packager/media/base/video_stream_info.h" 21 #include "packager/media/codecs/video_slice_header_parser.h" 22 #include "packager/media/codecs/vp8_parser.h" 23 #include "packager/media/codecs/vp9_parser.h" 24 #include "packager/media/crypto/sample_aes_ec3_cryptor.h" 30 const size_t kCencBlockSize = 16u;
33 const size_t kStreamIndex = 0;
36 const uint8_t kKeyRotationDefaultKeyId[] = {
37 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
42 void AddSubsample(uint64_t clear_bytes,
43 uint64_t cipher_bytes,
44 DecryptConfig* decrypt_config) {
45 CHECK_LT(cipher_bytes, std::numeric_limits<uint32_t>::max());
46 const uint64_t kUInt16Max = std::numeric_limits<uint16_t>::max();
47 while (clear_bytes > kUInt16Max) {
48 decrypt_config->AddSubsample(kUInt16Max, 0);
49 clear_bytes -= kUInt16Max;
52 if (clear_bytes > 0 || cipher_bytes > 0)
53 decrypt_config->AddSubsample(clear_bytes, cipher_bytes);
56 uint8_t GetNaluLengthSize(
const StreamInfo& stream_info) {
57 if (stream_info.stream_type() != kStreamVideo)
60 const VideoStreamInfo& video_stream_info =
61 static_cast<const VideoStreamInfo&
>(stream_info);
62 return video_stream_info.nalu_length_size();
65 std::string GetStreamLabelForEncryption(
66 const StreamInfo& stream_info,
67 const std::function<std::string(
68 const EncryptionParams::EncryptedStreamAttributes& stream_attributes)>&
70 EncryptionParams::EncryptedStreamAttributes stream_attributes;
71 if (stream_info.stream_type() == kStreamAudio) {
72 stream_attributes.stream_type =
73 EncryptionParams::EncryptedStreamAttributes::kAudio;
74 }
else if (stream_info.stream_type() == kStreamVideo) {
75 const VideoStreamInfo& video_stream_info =
76 static_cast<const VideoStreamInfo&
>(stream_info);
77 stream_attributes.stream_type =
78 EncryptionParams::EncryptedStreamAttributes::kVideo;
79 stream_attributes.oneof.video.width = video_stream_info.width();
80 stream_attributes.oneof.video.height = video_stream_info.height();
82 return stream_label_func(stream_attributes);
86 EncryptionHandler::EncryptionHandler(
const EncryptionParams& encryption_params,
87 KeySource* key_source)
88 : encryption_params_(encryption_params),
90 static_cast<FourCC>(encryption_params.protection_scheme)),
91 key_source_(key_source) {}
93 EncryptionHandler::~EncryptionHandler() {}
96 if (!encryption_params_.stream_label_func) {
97 return Status(error::INVALID_ARGUMENT,
"Stream label function not set.");
99 if (num_input_streams() != 1 || next_output_stream_index() != 1) {
100 return Status(error::INVALID_ARGUMENT,
101 "Expects exactly one input and output.");
107 switch (stream_data->stream_data_type) {
108 case StreamDataType::kStreamInfo:
109 return ProcessStreamInfo(*stream_data->stream_info);
110 case StreamDataType::kSegmentInfo: {
111 std::shared_ptr<SegmentInfo> segment_info(
new SegmentInfo(
112 *stream_data->segment_info));
114 segment_info->is_encrypted = remaining_clear_lead_ <= 0;
116 const bool key_rotation_enabled = crypto_period_duration_ != 0;
117 if (key_rotation_enabled)
118 segment_info->key_rotation_encryption_config = encryption_config_;
119 if (!segment_info->is_subsegment) {
120 if (key_rotation_enabled)
121 check_new_crypto_period_ =
true;
122 if (remaining_clear_lead_ > 0)
123 remaining_clear_lead_ -= segment_info->duration;
126 return DispatchSegmentInfo(kStreamIndex, segment_info);
128 case StreamDataType::kMediaSample:
129 return ProcessMediaSample(std::move(stream_data->media_sample));
131 VLOG(3) <<
"Stream data type " 132 <<
static_cast<int>(stream_data->stream_data_type) <<
" ignored.";
133 return Dispatch(std::move(stream_data));
138 if (clear_info.is_encrypted()) {
139 return Status(error::INVALID_ARGUMENT,
140 "Input stream is already encrypted.");
143 DCHECK_NE(kStreamUnknown, clear_info.stream_type());
144 DCHECK_NE(kStreamText, clear_info.stream_type());
145 std::shared_ptr<StreamInfo> stream_info = clear_info.
Clone();
147 remaining_clear_lead_ =
148 encryption_params_.clear_lead_in_seconds * stream_info->time_scale();
149 crypto_period_duration_ =
150 encryption_params_.crypto_period_duration_in_seconds *
151 stream_info->time_scale();
152 codec_ = stream_info->codec();
153 nalu_length_size_ = GetNaluLengthSize(*stream_info);
154 stream_label_ = GetStreamLabelForEncryption(
155 *stream_info, encryption_params_.stream_label_func);
158 if (encryption_params_.vp9_subsample_encryption)
169 if (nalu_length_size_ > 0) {
170 LOG(WARNING) <<
"Unknown video codec '" << codec_ <<
"'";
171 return Status(error::ENCRYPTION_FAILURE,
"Unknown video codec.");
174 if (header_parser_) {
175 CHECK_NE(nalu_length_size_, 0u) <<
"AnnexB stream is not supported yet";
176 if (!header_parser_->Initialize(stream_info->codec_config())) {
177 return Status(error::ENCRYPTION_FAILURE,
178 "Fail to read SPS and PPS data.");
182 Status status = SetupProtectionPattern(stream_info->stream_type());
187 const bool key_rotation_enabled = crypto_period_duration_ != 0;
188 if (key_rotation_enabled) {
189 check_new_crypto_period_ =
true;
191 encryption_key.key_id.assign(
192 kKeyRotationDefaultKeyId,
193 kKeyRotationDefaultKeyId +
sizeof(kKeyRotationDefaultKeyId));
196 encryption_key.key = encryption_key.key_id;
198 status = key_source_->GetKey(stream_label_, &encryption_key);
202 if (!CreateEncryptor(encryption_key))
203 return Status(error::ENCRYPTION_FAILURE,
"Failed to create encryptor");
205 stream_info->set_is_encrypted(
true);
206 stream_info->set_has_clear_lead(encryption_params_.clear_lead_in_seconds > 0);
207 stream_info->set_encryption_config(*encryption_config_);
209 return DispatchStreamInfo(kStreamIndex, stream_info);
212 Status EncryptionHandler::ProcessMediaSample(
213 std::shared_ptr<const MediaSample> clear_sample) {
214 DCHECK(clear_sample);
219 std::vector<VPxFrameInfo> vpx_frames;
220 if (vpx_parser_ && !vpx_parser_->Parse(clear_sample->data(),
221 clear_sample->data_size(),
223 return Status(error::ENCRYPTION_FAILURE,
"Failed to parse vpx frame.");
229 if (check_new_crypto_period_) {
232 const int64_t dts = std::max(clear_sample->dts(),
static_cast<int64_t
>(0));
233 const int64_t current_crypto_period_index = dts / crypto_period_duration_;
234 if (current_crypto_period_index != prev_crypto_period_index_) {
236 Status status = key_source_->GetCryptoPeriodKey(
237 current_crypto_period_index, stream_label_, &encryption_key);
240 if (!CreateEncryptor(encryption_key))
241 return Status(error::ENCRYPTION_FAILURE,
"Failed to create encryptor");
242 prev_crypto_period_index_ = current_crypto_period_index;
244 check_new_crypto_period_ =
false;
249 if (remaining_clear_lead_ > 0) {
250 return DispatchMediaSample(kStreamIndex, std::move(clear_sample));
253 std::unique_ptr<DecryptConfig> decrypt_config(
new DecryptConfig(
254 encryption_config_->key_id,
256 std::vector<SubsampleEntry>(),
264 std::shared_ptr<MediaSample> cipher_sample(clear_sample->Clone());
268 std::shared_ptr<uint8_t> cipher_sample_data(
269 new uint8_t[clear_sample->data_size()], std::default_delete<uint8_t[]>());
272 if (!EncryptVpxFrame(vpx_frames, clear_sample->data(),
273 clear_sample->data_size(),
274 &cipher_sample_data.get()[0], decrypt_config.get())) {
275 return Status(error::ENCRYPTION_FAILURE,
"Failed to encrypt VPX frame.");
277 DCHECK_EQ(decrypt_config->GetTotalSizeOfSubsamples(),
278 clear_sample->data_size());
279 }
else if (header_parser_) {
280 if (!EncryptNalFrame(clear_sample->data(), clear_sample->data_size(),
281 &cipher_sample_data.get()[0], decrypt_config.get())) {
282 return Status(error::ENCRYPTION_FAILURE,
"Failed to encrypt NAL frame.");
284 DCHECK_EQ(decrypt_config->GetTotalSizeOfSubsamples(),
285 clear_sample->data_size());
287 memcpy(&cipher_sample_data.get()[0], clear_sample->data(),
288 std::min(clear_sample->data_size(), leading_clear_bytes_size_));
289 if (clear_sample->data_size() > leading_clear_bytes_size_) {
292 EncryptBytes(clear_sample->data() + leading_clear_bytes_size_,
293 clear_sample->data_size() - leading_clear_bytes_size_,
294 &cipher_sample_data.get()[leading_clear_bytes_size_]);
298 cipher_sample->TransferData(std::move(cipher_sample_data),
299 clear_sample->data_size());
303 cipher_sample->set_is_encrypted(
true);
304 cipher_sample->set_decrypt_config(std::move(decrypt_config));
306 encryptor_->UpdateIv();
308 return DispatchMediaSample(kStreamIndex, std::move(cipher_sample));
311 Status EncryptionHandler::SetupProtectionPattern(StreamType stream_type) {
312 switch (protection_scheme_) {
313 case kAppleSampleAesProtectionScheme: {
314 const size_t kH264LeadingClearBytesSize = 32u;
315 const size_t kSmallNalUnitSize = 32u + 16u;
316 const size_t kAudioLeadingClearBytesSize = 16u;
320 crypt_byte_block_ = 1u;
321 skip_byte_block_ = 9u;
322 leading_clear_bytes_size_ = kH264LeadingClearBytesSize;
323 min_protected_data_size_ = kSmallNalUnitSize + 1u;
326 FALLTHROUGH_INTENDED;
328 FALLTHROUGH_INTENDED;
334 crypt_byte_block_ = 0u;
335 skip_byte_block_ = 0u;
338 leading_clear_bytes_size_ =
339 codec_ == kCodecEAC3 ? 0 : kAudioLeadingClearBytesSize;
340 min_protected_data_size_ = leading_clear_bytes_size_ + 15u;
344 error::ENCRYPTION_FAILURE,
345 "Only AAC/AC3/EAC3 and H264 are supported in Sample AES.");
350 FALLTHROUGH_INTENDED;
352 if (stream_type == kStreamVideo) {
354 crypt_byte_block_ = 1u;
355 skip_byte_block_ = 9u;
365 crypt_byte_block_ = 1u;
366 skip_byte_block_ = 0u;
371 crypt_byte_block_ = 0u;
372 skip_byte_block_ = 0u;
378 bool EncryptionHandler::CreateEncryptor(
const EncryptionKey& encryption_key) {
379 std::unique_ptr<AesCryptor> encryptor;
380 switch (protection_scheme_) {
389 crypt_byte_block_, skip_byte_block_,
391 AesCryptor::kDontUseConstantIv,
396 crypt_byte_block_, skip_byte_block_,
398 AesCryptor::kUseConstantIv,
401 case kAppleSampleAesProtectionScheme:
402 if (crypt_byte_block_ == 0 && skip_byte_block_ == 0) {
403 if (codec_ == kCodecEAC3) {
412 crypt_byte_block_, skip_byte_block_,
414 AesCryptor::kUseConstantIv,
419 LOG(ERROR) <<
"Unsupported protection scheme.";
423 std::vector<uint8_t> iv = encryption_key.iv;
426 LOG(ERROR) <<
"Failed to generate random iv.";
430 const bool initialized =
431 encryptor->InitializeWithIv(encryption_key.key, iv);
432 encryptor_ = std::move(encryptor);
435 encryption_config_->protection_scheme = protection_scheme_;
436 encryption_config_->crypt_byte_block = crypt_byte_block_;
437 encryption_config_->skip_byte_block = skip_byte_block_;
438 if (encryptor_->use_constant_iv()) {
439 encryption_config_->per_sample_iv_size = 0;
440 encryption_config_->constant_iv = iv;
442 encryption_config_->per_sample_iv_size =
static_cast<uint8_t
>(iv.size());
444 encryption_config_->key_id = encryption_key.key_id;
445 encryption_config_->key_system_info = encryption_key.key_system_info;
449 bool EncryptionHandler::EncryptVpxFrame(
450 const std::vector<VPxFrameInfo>& vpx_frames,
451 const uint8_t* source,
455 const uint8_t* data = source;
457 uint16_t clear_bytes =
458 static_cast<uint16_t
>(frame.uncompressed_header_size);
459 uint32_t cipher_bytes =
static_cast<uint32_t
>(
460 frame.frame_size - frame.uncompressed_header_size);
470 const uint16_t misalign_bytes = cipher_bytes % kCencBlockSize;
471 clear_bytes += misalign_bytes;
472 cipher_bytes -= misalign_bytes;
474 decrypt_config->
AddSubsample(clear_bytes, cipher_bytes);
475 memcpy(dest, data, clear_bytes);
476 if (cipher_bytes > 0)
477 EncryptBytes(data + clear_bytes, cipher_bytes, dest + clear_bytes);
478 data += frame.frame_size;
479 dest += frame.frame_size;
482 const bool is_superframe = vpx_frames.size() > 1;
484 size_t index_size = source + source_size - data;
485 DCHECK_LE(index_size, 2 + vpx_frames.size() * 4);
486 DCHECK_GE(index_size, 2 + vpx_frames.size() * 1);
487 uint16_t clear_bytes =
static_cast<uint16_t
>(index_size);
488 uint32_t cipher_bytes = 0;
489 decrypt_config->
AddSubsample(clear_bytes, cipher_bytes);
490 memcpy(dest, data, clear_bytes);
495 bool EncryptionHandler::EncryptNalFrame(
const uint8_t* source,
499 DCHECK_NE(nalu_length_size_, 0u);
500 DCHECK(header_parser_);
501 const Nalu::CodecType nalu_type =
502 (codec_ == kCodecH265) ? Nalu::kH265 : Nalu::kH264;
503 NaluReader reader(nalu_type, nalu_length_size_, source, source_size);
507 uint64_t accumulated_clear_bytes = 0;
510 NaluReader::Result result;
511 while ((result = reader.
Advance(&nalu)) == NaluReader::kOk) {
513 if (nalu.
is_video_slice() && nalu_total_size >= min_protected_data_size_) {
514 uint64_t current_clear_bytes = leading_clear_bytes_size_;
515 if (current_clear_bytes == 0) {
518 const int64_t video_slice_header_size =
519 header_parser_->GetHeaderSize(nalu);
520 if (video_slice_header_size < 0) {
521 LOG(ERROR) <<
"Failed to read slice header.";
524 current_clear_bytes = nalu.
header_size() + video_slice_header_size;
526 uint64_t cipher_bytes = nalu_total_size - current_clear_bytes;
534 if (protection_scheme_ == FOURCC_cbc1 ||
535 protection_scheme_ == FOURCC_cens ||
536 protection_scheme_ == FOURCC_cenc) {
537 const uint16_t misalign_bytes = cipher_bytes % kCencBlockSize;
538 current_clear_bytes += misalign_bytes;
539 cipher_bytes -= misalign_bytes;
542 accumulated_clear_bytes += nalu_length_size_ + current_clear_bytes;
543 AddSubsample(accumulated_clear_bytes, cipher_bytes, decrypt_config);
544 memcpy(dest, source, accumulated_clear_bytes);
545 source += accumulated_clear_bytes;
546 dest += accumulated_clear_bytes;
547 accumulated_clear_bytes = 0;
549 DCHECK_EQ(nalu.
data() + current_clear_bytes, source);
550 EncryptBytes(source, cipher_bytes, dest);
551 source += cipher_bytes;
552 dest += cipher_bytes;
555 accumulated_clear_bytes += nalu_length_size_ + nalu_total_size;
558 if (result != NaluReader::kEOStream) {
559 LOG(ERROR) <<
"Failed to parse NAL units.";
562 AddSubsample(accumulated_clear_bytes, 0, decrypt_config);
563 memcpy(dest, source, accumulated_clear_bytes);
567 void EncryptionHandler::EncryptBytes(
const uint8_t* source,
573 CHECK(encryptor_->Crypt(source, source_size, dest));
576 void EncryptionHandler::InjectVpxParserForTesting(
577 std::unique_ptr<VPxParser> vpx_parser) {
578 vpx_parser_ = std::move(vpx_parser);
581 void EncryptionHandler::InjectVideoSliceHeaderParserForTesting(
582 std::unique_ptr<VideoSliceHeaderParser> header_parser) {
583 header_parser_ = std::move(header_parser);
All the methods that are virtual are virtual for mocking.