7 #include "packager/media/crypto/encryption_handler.h"
14 #include "packager/media/base/aes_encryptor.h"
15 #include "packager/media/base/aes_pattern_cryptor.h"
16 #include "packager/media/base/key_source.h"
17 #include "packager/media/base/media_sample.h"
18 #include "packager/media/base/audio_stream_info.h"
19 #include "packager/media/base/video_stream_info.h"
20 #include "packager/media/codecs/video_slice_header_parser.h"
21 #include "packager/media/codecs/vp8_parser.h"
22 #include "packager/media/codecs/vp9_parser.h"
28 const size_t kCencBlockSize = 16u;
31 const size_t kStreamIndex = 0;
34 const uint8_t kKeyRotationDefaultKeyId[] = {
35 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
40 void AddSubsample(uint64_t clear_bytes,
41 uint64_t cipher_bytes,
42 DecryptConfig* decrypt_config) {
43 CHECK_LT(cipher_bytes, std::numeric_limits<uint32_t>::max());
44 const uint64_t kUInt16Max = std::numeric_limits<uint16_t>::max();
45 while (clear_bytes > kUInt16Max) {
46 decrypt_config->AddSubsample(kUInt16Max, 0);
47 clear_bytes -= kUInt16Max;
50 if (clear_bytes > 0 || cipher_bytes > 0)
51 decrypt_config->AddSubsample(clear_bytes, cipher_bytes);
54 uint8_t GetNaluLengthSize(
const StreamInfo& stream_info) {
55 if (stream_info.stream_type() != kStreamVideo)
58 const VideoStreamInfo& video_stream_info =
59 static_cast<const VideoStreamInfo&
>(stream_info);
60 return video_stream_info.nalu_length_size();
63 std::string GetStreamLabelForEncryption(
64 const StreamInfo& stream_info,
65 const std::function<std::string(
66 const EncryptionParams::EncryptedStreamAttributes& stream_attributes)>&
68 EncryptionParams::EncryptedStreamAttributes stream_attributes;
69 if (stream_info.stream_type() == kStreamAudio) {
70 stream_attributes.stream_type =
71 EncryptionParams::EncryptedStreamAttributes::kAudio;
72 }
else if (stream_info.stream_type() == kStreamVideo) {
73 const VideoStreamInfo& video_stream_info =
74 static_cast<const VideoStreamInfo&
>(stream_info);
75 stream_attributes.stream_type =
76 EncryptionParams::EncryptedStreamAttributes::kVideo;
77 stream_attributes.oneof.video.width = video_stream_info.width();
78 stream_attributes.oneof.video.height = video_stream_info.height();
80 return stream_label_func(stream_attributes);
84 EncryptionHandler::EncryptionHandler(
const EncryptionParams& encryption_params,
85 KeySource* key_source)
86 : encryption_params_(encryption_params),
88 static_cast<FourCC>(encryption_params.protection_scheme)),
89 key_source_(key_source) {}
91 EncryptionHandler::~EncryptionHandler() {}
95 return Status(error::INVALID_ARGUMENT,
"Stream label function not set.");
97 if (num_input_streams() != 1 || next_output_stream_index() != 1) {
98 return Status(error::INVALID_ARGUMENT,
99 "Expects exactly one input and output.");
105 switch (stream_data->stream_data_type) {
106 case StreamDataType::kStreamInfo:
107 return ProcessStreamInfo(*stream_data->stream_info);
108 case StreamDataType::kSegmentInfo: {
109 std::shared_ptr<SegmentInfo> segment_info(
new SegmentInfo(
110 *stream_data->segment_info));
112 segment_info->is_encrypted = remaining_clear_lead_ <= 0;
114 const bool key_rotation_enabled = crypto_period_duration_ != 0;
115 if (key_rotation_enabled)
116 segment_info->key_rotation_encryption_config = encryption_config_;
117 if (!segment_info->is_subsegment) {
118 if (key_rotation_enabled)
119 check_new_crypto_period_ =
true;
120 if (remaining_clear_lead_ > 0)
121 remaining_clear_lead_ -= segment_info->duration;
126 case StreamDataType::kMediaSample:
127 return ProcessMediaSample(std::move(stream_data->media_sample));
129 VLOG(3) <<
"Stream data type "
130 <<
static_cast<int>(stream_data->stream_data_type) <<
" ignored.";
131 return Dispatch(std::move(stream_data));
136 if (clear_info.is_encrypted()) {
137 return Status(error::INVALID_ARGUMENT,
138 "Input stream is already encrypted.");
141 DCHECK_NE(kStreamUnknown, clear_info.stream_type());
142 DCHECK_NE(kStreamText, clear_info.stream_type());
143 std::shared_ptr<StreamInfo> stream_info = clear_info.
Clone();
145 remaining_clear_lead_ =
147 crypto_period_duration_ =
148 encryption_params_.crypto_period_duration_in_seconds *
149 stream_info->time_scale();
150 codec_ = stream_info->codec();
151 nalu_length_size_ = GetNaluLengthSize(*stream_info);
152 stream_label_ = GetStreamLabelForEncryption(
157 vpx_parser_.reset(
new VP9Parser);
160 header_parser_.reset(
new H264VideoSliceHeaderParser);
163 header_parser_.reset(
new H265VideoSliceHeaderParser);
167 if (nalu_length_size_ > 0) {
168 LOG(WARNING) <<
"Unknown video codec '" << codec_ <<
"'";
169 return Status(error::ENCRYPTION_FAILURE,
"Unknown video codec.");
172 if (header_parser_) {
173 CHECK_NE(nalu_length_size_, 0u) <<
"AnnexB stream is not supported yet";
174 if (!header_parser_->Initialize(stream_info->codec_config())) {
175 return Status(error::ENCRYPTION_FAILURE,
176 "Fail to read SPS and PPS data.");
180 Status status = SetupProtectionPattern(stream_info->stream_type());
184 EncryptionKey encryption_key;
185 const bool key_rotation_enabled = crypto_period_duration_ != 0;
186 if (key_rotation_enabled) {
187 check_new_crypto_period_ =
true;
189 encryption_key.key_id.assign(
190 kKeyRotationDefaultKeyId,
191 kKeyRotationDefaultKeyId +
sizeof(kKeyRotationDefaultKeyId));
194 encryption_key.key = encryption_key.key_id;
196 status = key_source_->
GetKey(stream_label_, &encryption_key);
200 if (!CreateEncryptor(encryption_key))
201 return Status(error::ENCRYPTION_FAILURE,
"Failed to create encryptor");
203 stream_info->set_is_encrypted(
true);
205 stream_info->set_encryption_config(*encryption_config_);
210 Status EncryptionHandler::ProcessMediaSample(
211 std::shared_ptr<const MediaSample> clear_sample) {
212 DCHECK(clear_sample);
217 std::vector<VPxFrameInfo> vpx_frames;
218 if (vpx_parser_ && !vpx_parser_->Parse(clear_sample->data(),
219 clear_sample->data_size(),
221 return Status(error::ENCRYPTION_FAILURE,
"Failed to parse vpx frame.");
227 if (check_new_crypto_period_) {
228 const int64_t current_crypto_period_index =
229 clear_sample->dts() / crypto_period_duration_;
230 if (current_crypto_period_index != prev_crypto_period_index_) {
231 EncryptionKey encryption_key;
233 current_crypto_period_index, stream_label_, &encryption_key);
236 if (!CreateEncryptor(encryption_key))
237 return Status(error::ENCRYPTION_FAILURE,
"Failed to create encryptor");
238 prev_crypto_period_index_ = current_crypto_period_index;
240 check_new_crypto_period_ =
false;
245 if (remaining_clear_lead_ > 0) {
249 std::unique_ptr<DecryptConfig> decrypt_config(
new DecryptConfig(
250 encryption_config_->key_id,
252 std::vector<SubsampleEntry>(),
260 std::shared_ptr<MediaSample> cipher_sample =
265 if (EncryptVpxFrame(vpx_frames,
266 cipher_sample->writable_data(),
267 cipher_sample->data_size(),
268 decrypt_config.get())) {
269 DCHECK_EQ(decrypt_config->GetTotalSizeOfSubsamples(),
270 cipher_sample->data_size());
273 error::ENCRYPTION_FAILURE,
274 "Failed to encrypt VPX frame.");
276 }
else if (header_parser_) {
277 if (EncryptNalFrame(cipher_sample->writable_data(),
278 cipher_sample->data_size(),
279 decrypt_config.get())) {
280 DCHECK_EQ(decrypt_config->GetTotalSizeOfSubsamples(),
281 cipher_sample->data_size());
284 error::ENCRYPTION_FAILURE,
285 "Failed to encrypt NAL frame.");
287 }
else if (cipher_sample->data_size() > leading_clear_bytes_size_) {
289 cipher_sample->writable_data() + leading_clear_bytes_size_,
290 cipher_sample->data_size() - leading_clear_bytes_size_);
297 encryptor_->UpdateIv();
302 cipher_sample->set_is_encrypted(
true);
303 cipher_sample->set_decrypt_config(std::move(decrypt_config));
308 Status EncryptionHandler::SetupProtectionPattern(StreamType stream_type) {
309 switch (protection_scheme_) {
310 case kAppleSampleAesProtectionScheme: {
311 const size_t kH264LeadingClearBytesSize = 32u;
312 const size_t kSmallNalUnitSize = 32u + 16u;
313 const size_t kAudioLeadingClearBytesSize = 16u;
317 crypt_byte_block_ = 1u;
318 skip_byte_block_ = 9u;
319 leading_clear_bytes_size_ = kH264LeadingClearBytesSize;
320 min_protected_data_size_ = kSmallNalUnitSize + 1u;
323 FALLTHROUGH_INTENDED;
329 crypt_byte_block_ = 0u;
330 skip_byte_block_ = 0u;
331 leading_clear_bytes_size_ = kAudioLeadingClearBytesSize;
332 min_protected_data_size_ = leading_clear_bytes_size_ + 1u;
335 return Status(error::ENCRYPTION_FAILURE,
336 "Only AAC/AC3 and H264 are supported in Sample AES.");
341 FALLTHROUGH_INTENDED;
343 if (stream_type == kStreamVideo) {
345 crypt_byte_block_ = 1u;
346 skip_byte_block_ = 9u;
356 crypt_byte_block_ = 1u;
357 skip_byte_block_ = 0u;
362 crypt_byte_block_ = 0u;
363 skip_byte_block_ = 0u;
368 bool EncryptionHandler::CreateEncryptor(
const EncryptionKey& encryption_key) {
369 std::unique_ptr<AesCryptor> encryptor;
370 switch (protection_scheme_) {
372 encryptor.reset(
new AesCtrEncryptor);
375 encryptor.reset(
new AesCbcEncryptor(kNoPadding));
378 encryptor.reset(
new AesPatternCryptor(
379 crypt_byte_block_, skip_byte_block_,
381 AesCryptor::kDontUseConstantIv,
382 std::unique_ptr<AesCryptor>(
new AesCtrEncryptor())));
385 encryptor.reset(
new AesPatternCryptor(
386 crypt_byte_block_, skip_byte_block_,
388 AesCryptor::kUseConstantIv,
389 std::unique_ptr<AesCryptor>(
new AesCbcEncryptor(kNoPadding))));
391 case kAppleSampleAesProtectionScheme:
392 if (crypt_byte_block_ == 0 && skip_byte_block_ == 0) {
394 new AesCbcEncryptor(kNoPadding, AesCryptor::kUseConstantIv));
396 encryptor.reset(
new AesPatternCryptor(
397 crypt_byte_block_, skip_byte_block_,
399 AesCryptor::kUseConstantIv,
400 std::unique_ptr<AesCryptor>(
new AesCbcEncryptor(kNoPadding))));
404 LOG(ERROR) <<
"Unsupported protection scheme.";
408 std::vector<uint8_t> iv = encryption_key.iv;
411 LOG(ERROR) <<
"Failed to generate random iv.";
415 const bool initialized =
416 encryptor->InitializeWithIv(encryption_key.key, iv);
417 encryptor_ = std::move(encryptor);
419 encryption_config_.reset(
new EncryptionConfig);
420 encryption_config_->protection_scheme = protection_scheme_;
421 encryption_config_->crypt_byte_block = crypt_byte_block_;
422 encryption_config_->skip_byte_block = skip_byte_block_;
423 if (encryptor_->use_constant_iv()) {
424 encryption_config_->per_sample_iv_size = 0;
425 encryption_config_->constant_iv = iv;
427 encryption_config_->per_sample_iv_size =
static_cast<uint8_t
>(iv.size());
429 encryption_config_->key_id = encryption_key.key_id;
430 encryption_config_->key_system_info = encryption_key.key_system_info;
434 bool EncryptionHandler::EncryptVpxFrame(
435 const std::vector<VPxFrameInfo>& vpx_frames,
438 DecryptConfig* decrypt_config) {
439 uint8_t* data = source;
440 for (
const VPxFrameInfo& frame : vpx_frames) {
441 uint16_t clear_bytes =
442 static_cast<uint16_t
>(frame.uncompressed_header_size);
443 uint32_t cipher_bytes =
static_cast<uint32_t
>(
444 frame.frame_size - frame.uncompressed_header_size);
454 const uint16_t misalign_bytes = cipher_bytes % kCencBlockSize;
455 clear_bytes += misalign_bytes;
456 cipher_bytes -= misalign_bytes;
458 decrypt_config->AddSubsample(clear_bytes, cipher_bytes);
459 if (cipher_bytes > 0)
460 EncryptBytes(data + clear_bytes, cipher_bytes);
461 data += frame.frame_size;
464 const bool is_superframe = vpx_frames.size() > 1;
466 size_t index_size = source + source_size - data;
467 DCHECK_LE(index_size, 2 + vpx_frames.size() * 4);
468 DCHECK_GE(index_size, 2 + vpx_frames.size() * 1);
469 uint16_t clear_bytes =
static_cast<uint16_t
>(index_size);
470 uint32_t cipher_bytes = 0;
471 decrypt_config->AddSubsample(clear_bytes, cipher_bytes);
476 bool EncryptionHandler::EncryptNalFrame(uint8_t* data,
478 DecryptConfig* decrypt_config) {
479 DCHECK_NE(nalu_length_size_, 0u);
480 DCHECK(header_parser_);
481 const Nalu::CodecType nalu_type =
482 (codec_ == kCodecH265) ? Nalu::kH265 : Nalu::kH264;
483 NaluReader reader(nalu_type, nalu_length_size_, data, data_length);
487 uint64_t accumulated_clear_bytes = 0;
490 NaluReader::Result result;
491 while ((result = reader.Advance(&nalu)) == NaluReader::kOk) {
492 const uint64_t nalu_total_size = nalu.header_size() + nalu.payload_size();
493 if (nalu.is_video_slice() && nalu_total_size >= min_protected_data_size_) {
494 uint64_t current_clear_bytes = leading_clear_bytes_size_;
495 if (current_clear_bytes == 0) {
498 const int64_t video_slice_header_size =
499 header_parser_->GetHeaderSize(nalu);
500 if (video_slice_header_size < 0) {
501 LOG(ERROR) <<
"Failed to read slice header.";
504 current_clear_bytes = nalu.header_size() + video_slice_header_size;
506 uint64_t cipher_bytes = nalu_total_size - current_clear_bytes;
514 if (protection_scheme_ == FOURCC_cbc1 ||
515 protection_scheme_ == FOURCC_cens ||
516 protection_scheme_ == FOURCC_cenc) {
517 const uint16_t misalign_bytes = cipher_bytes % kCencBlockSize;
518 current_clear_bytes += misalign_bytes;
519 cipher_bytes -= misalign_bytes;
522 const uint8_t* nalu_data = nalu.data() + current_clear_bytes;
523 EncryptBytes(const_cast<uint8_t*>(nalu_data), cipher_bytes);
526 accumulated_clear_bytes + nalu_length_size_ + current_clear_bytes,
527 cipher_bytes, decrypt_config);
528 accumulated_clear_bytes = 0;
531 accumulated_clear_bytes += nalu_length_size_ + nalu_total_size;
534 if (result != NaluReader::kEOStream) {
535 LOG(ERROR) <<
"Failed to parse NAL units.";
538 AddSubsample(accumulated_clear_bytes, 0, decrypt_config);
542 void EncryptionHandler::EncryptBytes(uint8_t* data,
size_t size) {
545 CHECK(encryptor_->Crypt(data, size, data));
548 void EncryptionHandler::InjectVpxParserForTesting(
549 std::unique_ptr<VPxParser> vpx_parser) {
550 vpx_parser_ = std::move(vpx_parser);
553 void EncryptionHandler::InjectVideoSliceHeaderParserForTesting(
554 std::unique_ptr<VideoSliceHeaderParser> header_parser) {
555 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.