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/key_source.h"
18 #include "packager/media/base/media_sample.h"
19 #include "packager/media/base/audio_stream_info.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"
29 const size_t kCencBlockSize = 16u;
32 const size_t kStreamIndex = 0;
35 const uint8_t kKeyRotationDefaultKeyId[] = {
36 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
41 void AddSubsample(uint64_t clear_bytes,
42 uint64_t cipher_bytes,
43 DecryptConfig* decrypt_config) {
44 CHECK_LT(cipher_bytes, std::numeric_limits<uint32_t>::max());
45 const uint64_t kUInt16Max = std::numeric_limits<uint16_t>::max();
46 while (clear_bytes > kUInt16Max) {
47 decrypt_config->AddSubsample(kUInt16Max, 0);
48 clear_bytes -= kUInt16Max;
51 if (clear_bytes > 0 || cipher_bytes > 0)
52 decrypt_config->AddSubsample(clear_bytes, cipher_bytes);
55 uint8_t GetNaluLengthSize(
const StreamInfo& stream_info) {
56 if (stream_info.stream_type() != kStreamVideo)
59 const VideoStreamInfo& video_stream_info =
60 static_cast<const VideoStreamInfo&
>(stream_info);
61 return video_stream_info.nalu_length_size();
64 std::string GetStreamLabelForEncryption(
65 const StreamInfo& stream_info,
66 const std::function<std::string(
67 const EncryptionParams::EncryptedStreamAttributes& stream_attributes)>&
69 EncryptionParams::EncryptedStreamAttributes stream_attributes;
70 if (stream_info.stream_type() == kStreamAudio) {
71 stream_attributes.stream_type =
72 EncryptionParams::EncryptedStreamAttributes::kAudio;
73 }
else if (stream_info.stream_type() == kStreamVideo) {
74 const VideoStreamInfo& video_stream_info =
75 static_cast<const VideoStreamInfo&
>(stream_info);
76 stream_attributes.stream_type =
77 EncryptionParams::EncryptedStreamAttributes::kVideo;
78 stream_attributes.oneof.video.width = video_stream_info.width();
79 stream_attributes.oneof.video.height = video_stream_info.height();
81 return stream_label_func(stream_attributes);
85 EncryptionHandler::EncryptionHandler(
const EncryptionParams& encryption_params,
86 KeySource* key_source)
87 : encryption_params_(encryption_params),
89 static_cast<FourCC>(encryption_params.protection_scheme)),
90 key_source_(key_source) {}
92 EncryptionHandler::~EncryptionHandler() {}
96 return Status(error::INVALID_ARGUMENT,
"Stream label function not set.");
98 if (num_input_streams() != 1 || next_output_stream_index() != 1) {
99 return Status(error::INVALID_ARGUMENT,
100 "Expects exactly one input and output.");
106 switch (stream_data->stream_data_type) {
107 case StreamDataType::kStreamInfo:
108 return ProcessStreamInfo(*stream_data->stream_info);
109 case StreamDataType::kSegmentInfo: {
110 std::shared_ptr<SegmentInfo> segment_info(
new SegmentInfo(
111 *stream_data->segment_info));
113 segment_info->is_encrypted = remaining_clear_lead_ <= 0;
115 const bool key_rotation_enabled = crypto_period_duration_ != 0;
116 if (key_rotation_enabled)
117 segment_info->key_rotation_encryption_config = encryption_config_;
118 if (!segment_info->is_subsegment) {
119 if (key_rotation_enabled)
120 check_new_crypto_period_ =
true;
121 if (remaining_clear_lead_ > 0)
122 remaining_clear_lead_ -= segment_info->duration;
127 case StreamDataType::kMediaSample:
128 return ProcessMediaSample(std::move(stream_data->media_sample));
130 VLOG(3) <<
"Stream data type "
131 <<
static_cast<int>(stream_data->stream_data_type) <<
" ignored.";
132 return Dispatch(std::move(stream_data));
137 if (clear_info.is_encrypted()) {
138 return Status(error::INVALID_ARGUMENT,
139 "Input stream is already encrypted.");
142 DCHECK_NE(kStreamUnknown, clear_info.stream_type());
143 DCHECK_NE(kStreamText, clear_info.stream_type());
144 std::shared_ptr<StreamInfo> stream_info = clear_info.
Clone();
146 remaining_clear_lead_ =
148 crypto_period_duration_ =
149 encryption_params_.crypto_period_duration_in_seconds *
150 stream_info->time_scale();
151 codec_ = stream_info->codec();
152 nalu_length_size_ = GetNaluLengthSize(*stream_info);
153 stream_label_ = GetStreamLabelForEncryption(
158 vpx_parser_.reset(
new VP9Parser);
161 header_parser_.reset(
new H264VideoSliceHeaderParser);
164 header_parser_.reset(
new H265VideoSliceHeaderParser);
168 if (nalu_length_size_ > 0) {
169 LOG(WARNING) <<
"Unknown video codec '" << codec_ <<
"'";
170 return Status(error::ENCRYPTION_FAILURE,
"Unknown video codec.");
173 if (header_parser_) {
174 CHECK_NE(nalu_length_size_, 0u) <<
"AnnexB stream is not supported yet";
175 if (!header_parser_->Initialize(stream_info->codec_config())) {
176 return Status(error::ENCRYPTION_FAILURE,
177 "Fail to read SPS and PPS data.");
181 Status status = SetupProtectionPattern(stream_info->stream_type());
185 EncryptionKey encryption_key;
186 const bool key_rotation_enabled = crypto_period_duration_ != 0;
187 if (key_rotation_enabled) {
188 check_new_crypto_period_ =
true;
190 encryption_key.key_id.assign(
191 kKeyRotationDefaultKeyId,
192 kKeyRotationDefaultKeyId +
sizeof(kKeyRotationDefaultKeyId));
195 encryption_key.key = encryption_key.key_id;
197 status = key_source_->
GetKey(stream_label_, &encryption_key);
201 if (!CreateEncryptor(encryption_key))
202 return Status(error::ENCRYPTION_FAILURE,
"Failed to create encryptor");
204 stream_info->set_is_encrypted(
true);
206 stream_info->set_encryption_config(*encryption_config_);
211 Status EncryptionHandler::ProcessMediaSample(
212 std::shared_ptr<const MediaSample> clear_sample) {
213 DCHECK(clear_sample);
218 std::vector<VPxFrameInfo> vpx_frames;
219 if (vpx_parser_ && !vpx_parser_->Parse(clear_sample->data(),
220 clear_sample->data_size(),
222 return Status(error::ENCRYPTION_FAILURE,
"Failed to parse vpx frame.");
228 if (check_new_crypto_period_) {
229 const int64_t current_crypto_period_index =
230 clear_sample->dts() / crypto_period_duration_;
231 if (current_crypto_period_index != prev_crypto_period_index_) {
232 EncryptionKey encryption_key;
234 current_crypto_period_index, stream_label_, &encryption_key);
237 if (!CreateEncryptor(encryption_key))
238 return Status(error::ENCRYPTION_FAILURE,
"Failed to create encryptor");
239 prev_crypto_period_index_ = current_crypto_period_index;
241 check_new_crypto_period_ =
false;
246 if (remaining_clear_lead_ > 0) {
250 std::unique_ptr<DecryptConfig> decrypt_config(
new DecryptConfig(
251 encryption_config_->key_id,
253 std::vector<SubsampleEntry>(),
261 std::shared_ptr<MediaSample> cipher_sample(clear_sample->Clone());
265 std::shared_ptr<uint8_t> cipher_sample_data(
266 new uint8_t[clear_sample->data_size()], std::default_delete<uint8_t[]>());
269 if (!EncryptVpxFrame(vpx_frames, clear_sample->data(),
270 clear_sample->data_size(),
271 &cipher_sample_data.get()[0], decrypt_config.get())) {
272 return Status(error::ENCRYPTION_FAILURE,
"Failed to encrypt VPX frame.");
274 DCHECK_EQ(decrypt_config->GetTotalSizeOfSubsamples(),
275 clear_sample->data_size());
276 }
else if (header_parser_) {
277 if (!EncryptNalFrame(clear_sample->data(), clear_sample->data_size(),
278 &cipher_sample_data.get()[0], decrypt_config.get())) {
279 return Status(error::ENCRYPTION_FAILURE,
"Failed to encrypt NAL frame.");
281 DCHECK_EQ(decrypt_config->GetTotalSizeOfSubsamples(),
282 clear_sample->data_size());
284 memcpy(&cipher_sample_data.get()[0], clear_sample->data(),
285 std::min(clear_sample->data_size(), leading_clear_bytes_size_));
286 if (clear_sample->data_size() > leading_clear_bytes_size_) {
287 EncryptBytes(clear_sample->data() + leading_clear_bytes_size_,
288 clear_sample->data_size() - leading_clear_bytes_size_,
289 &cipher_sample_data.get()[leading_clear_bytes_size_]);
293 cipher_sample->TransferData(std::move(cipher_sample_data),
294 clear_sample->data_size());
298 cipher_sample->set_is_encrypted(
true);
299 cipher_sample->set_decrypt_config(std::move(decrypt_config));
301 encryptor_->UpdateIv();
306 Status EncryptionHandler::SetupProtectionPattern(StreamType stream_type) {
307 switch (protection_scheme_) {
308 case kAppleSampleAesProtectionScheme: {
309 const size_t kH264LeadingClearBytesSize = 32u;
310 const size_t kSmallNalUnitSize = 32u + 16u;
311 const size_t kAudioLeadingClearBytesSize = 16u;
315 crypt_byte_block_ = 1u;
316 skip_byte_block_ = 9u;
317 leading_clear_bytes_size_ = kH264LeadingClearBytesSize;
318 min_protected_data_size_ = kSmallNalUnitSize + 1u;
321 FALLTHROUGH_INTENDED;
327 crypt_byte_block_ = 0u;
328 skip_byte_block_ = 0u;
329 leading_clear_bytes_size_ = kAudioLeadingClearBytesSize;
330 min_protected_data_size_ = leading_clear_bytes_size_ + 1u;
333 return Status(error::ENCRYPTION_FAILURE,
334 "Only AAC/AC3 and H264 are supported in Sample AES.");
339 FALLTHROUGH_INTENDED;
341 if (stream_type == kStreamVideo) {
343 crypt_byte_block_ = 1u;
344 skip_byte_block_ = 9u;
354 crypt_byte_block_ = 1u;
355 skip_byte_block_ = 0u;
360 crypt_byte_block_ = 0u;
361 skip_byte_block_ = 0u;
366 bool EncryptionHandler::CreateEncryptor(
const EncryptionKey& encryption_key) {
367 std::unique_ptr<AesCryptor> encryptor;
368 switch (protection_scheme_) {
370 encryptor.reset(
new AesCtrEncryptor);
373 encryptor.reset(
new AesCbcEncryptor(kNoPadding));
376 encryptor.reset(
new AesPatternCryptor(
377 crypt_byte_block_, skip_byte_block_,
379 AesCryptor::kDontUseConstantIv,
380 std::unique_ptr<AesCryptor>(
new AesCtrEncryptor())));
383 encryptor.reset(
new AesPatternCryptor(
384 crypt_byte_block_, skip_byte_block_,
386 AesCryptor::kUseConstantIv,
387 std::unique_ptr<AesCryptor>(
new AesCbcEncryptor(kNoPadding))));
389 case kAppleSampleAesProtectionScheme:
390 if (crypt_byte_block_ == 0 && skip_byte_block_ == 0) {
392 new AesCbcEncryptor(kNoPadding, AesCryptor::kUseConstantIv));
394 encryptor.reset(
new AesPatternCryptor(
395 crypt_byte_block_, skip_byte_block_,
397 AesCryptor::kUseConstantIv,
398 std::unique_ptr<AesCryptor>(
new AesCbcEncryptor(kNoPadding))));
402 LOG(ERROR) <<
"Unsupported protection scheme.";
406 std::vector<uint8_t> iv = encryption_key.iv;
409 LOG(ERROR) <<
"Failed to generate random iv.";
413 const bool initialized =
414 encryptor->InitializeWithIv(encryption_key.key, iv);
415 encryptor_ = std::move(encryptor);
417 encryption_config_.reset(
new EncryptionConfig);
418 encryption_config_->protection_scheme = protection_scheme_;
419 encryption_config_->crypt_byte_block = crypt_byte_block_;
420 encryption_config_->skip_byte_block = skip_byte_block_;
421 if (encryptor_->use_constant_iv()) {
422 encryption_config_->per_sample_iv_size = 0;
423 encryption_config_->constant_iv = iv;
425 encryption_config_->per_sample_iv_size =
static_cast<uint8_t
>(iv.size());
427 encryption_config_->key_id = encryption_key.key_id;
428 encryption_config_->key_system_info = encryption_key.key_system_info;
432 bool EncryptionHandler::EncryptVpxFrame(
433 const std::vector<VPxFrameInfo>& vpx_frames,
434 const uint8_t* source,
437 DecryptConfig* decrypt_config) {
438 const uint8_t* data = source;
439 for (
const VPxFrameInfo& frame : vpx_frames) {
440 uint16_t clear_bytes =
441 static_cast<uint16_t
>(frame.uncompressed_header_size);
442 uint32_t cipher_bytes =
static_cast<uint32_t
>(
443 frame.frame_size - frame.uncompressed_header_size);
453 const uint16_t misalign_bytes = cipher_bytes % kCencBlockSize;
454 clear_bytes += misalign_bytes;
455 cipher_bytes -= misalign_bytes;
457 decrypt_config->AddSubsample(clear_bytes, cipher_bytes);
458 memcpy(dest, data, clear_bytes);
459 if (cipher_bytes > 0)
460 EncryptBytes(data + clear_bytes, cipher_bytes, dest + clear_bytes);
461 data += frame.frame_size;
462 dest += frame.frame_size;
465 const bool is_superframe = vpx_frames.size() > 1;
467 size_t index_size = source + source_size - data;
468 DCHECK_LE(index_size, 2 + vpx_frames.size() * 4);
469 DCHECK_GE(index_size, 2 + vpx_frames.size() * 1);
470 uint16_t clear_bytes =
static_cast<uint16_t
>(index_size);
471 uint32_t cipher_bytes = 0;
472 decrypt_config->AddSubsample(clear_bytes, cipher_bytes);
473 memcpy(dest, data, clear_bytes);
478 bool EncryptionHandler::EncryptNalFrame(
const uint8_t* source,
481 DecryptConfig* decrypt_config) {
482 DCHECK_NE(nalu_length_size_, 0u);
483 DCHECK(header_parser_);
484 const Nalu::CodecType nalu_type =
485 (codec_ == kCodecH265) ? Nalu::kH265 : Nalu::kH264;
486 NaluReader reader(nalu_type, nalu_length_size_, source, source_size);
490 uint64_t accumulated_clear_bytes = 0;
493 NaluReader::Result result;
494 while ((result = reader.Advance(&nalu)) == NaluReader::kOk) {
495 const uint64_t nalu_total_size = nalu.header_size() + nalu.payload_size();
496 if (nalu.is_video_slice() && nalu_total_size >= min_protected_data_size_) {
497 uint64_t current_clear_bytes = leading_clear_bytes_size_;
498 if (current_clear_bytes == 0) {
501 const int64_t video_slice_header_size =
502 header_parser_->GetHeaderSize(nalu);
503 if (video_slice_header_size < 0) {
504 LOG(ERROR) <<
"Failed to read slice header.";
507 current_clear_bytes = nalu.header_size() + video_slice_header_size;
509 uint64_t cipher_bytes = nalu_total_size - current_clear_bytes;
517 if (protection_scheme_ == FOURCC_cbc1 ||
518 protection_scheme_ == FOURCC_cens ||
519 protection_scheme_ == FOURCC_cenc) {
520 const uint16_t misalign_bytes = cipher_bytes % kCencBlockSize;
521 current_clear_bytes += misalign_bytes;
522 cipher_bytes -= misalign_bytes;
525 accumulated_clear_bytes += nalu_length_size_ + current_clear_bytes;
526 AddSubsample(accumulated_clear_bytes, cipher_bytes, decrypt_config);
527 memcpy(dest, source, accumulated_clear_bytes);
528 source += accumulated_clear_bytes;
529 dest += accumulated_clear_bytes;
530 accumulated_clear_bytes = 0;
532 DCHECK_EQ(nalu.data() + current_clear_bytes, source);
533 EncryptBytes(source, cipher_bytes, dest);
534 source += cipher_bytes;
535 dest += cipher_bytes;
538 accumulated_clear_bytes += nalu_length_size_ + nalu_total_size;
541 if (result != NaluReader::kEOStream) {
542 LOG(ERROR) <<
"Failed to parse NAL units.";
545 AddSubsample(accumulated_clear_bytes, 0, decrypt_config);
546 memcpy(dest, source, accumulated_clear_bytes);
550 void EncryptionHandler::EncryptBytes(
const uint8_t* source,
556 CHECK(encryptor_->Crypt(source, source_size, dest));
559 void EncryptionHandler::InjectVpxParserForTesting(
560 std::unique_ptr<VPxParser> vpx_parser) {
561 vpx_parser_ = std::move(vpx_parser);
564 void EncryptionHandler::InjectVideoSliceHeaderParserForTesting(
565 std::unique_ptr<VideoSliceHeaderParser> header_parser) {
566 header_parser_ = std::move(header_parser);
std::function< std::string(const EncryptedStreamAttributes &stream_attributes)> stream_label_func
double clear_lead_in_seconds
Clear lead duration in seconds.
bool vp9_subsample_encryption
Enable/disable subsample encryption for VP9.