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/video_stream_info.h"
19 #include "packager/media/codecs/video_slice_header_parser.h"
20 #include "packager/media/codecs/vp8_parser.h"
21 #include "packager/media/codecs/vp9_parser.h"
27 const size_t kCencBlockSize = 16u;
30 const uint8_t kKeyRotationDefaultKeyId[] = {
31 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
36 void AddSubsample(uint64_t clear_bytes,
37 uint64_t cipher_bytes,
38 DecryptConfig* decrypt_config) {
39 CHECK_LT(cipher_bytes, std::numeric_limits<uint32_t>::max());
40 const uint64_t kUInt16Max = std::numeric_limits<uint16_t>::max();
41 while (clear_bytes > kUInt16Max) {
42 decrypt_config->AddSubsample(kUInt16Max, 0);
43 clear_bytes -= kUInt16Max;
46 if (clear_bytes > 0 || cipher_bytes > 0)
47 decrypt_config->AddSubsample(clear_bytes, cipher_bytes);
50 uint8_t GetNaluLengthSize(
const StreamInfo& stream_info) {
51 if (stream_info.stream_type() != kStreamVideo)
54 const VideoStreamInfo& video_stream_info =
55 static_cast<const VideoStreamInfo&
>(stream_info);
56 return video_stream_info.nalu_length_size();
59 std::string GetStreamLabelForEncryption(
60 const StreamInfo& stream_info,
61 const std::function<std::string(
62 const EncryptionParams::EncryptedStreamAttributes& stream_attributes)>&
64 EncryptionParams::EncryptedStreamAttributes stream_attributes;
65 if (stream_info.stream_type() == kStreamAudio) {
66 stream_attributes.stream_type =
67 EncryptionParams::EncryptedStreamAttributes::kAudio;
68 }
else if (stream_info.stream_type() == kStreamVideo) {
69 const VideoStreamInfo& video_stream_info =
70 static_cast<const VideoStreamInfo&
>(stream_info);
71 stream_attributes.stream_type =
72 EncryptionParams::EncryptedStreamAttributes::kVideo;
73 stream_attributes.oneof.video.width = video_stream_info.width();
74 stream_attributes.oneof.video.height = video_stream_info.height();
76 return stream_label_func(stream_attributes);
80 EncryptionHandler::EncryptionHandler(
const EncryptionParams& encryption_params,
81 KeySource* key_source)
82 : encryption_params_(encryption_params),
84 static_cast<FourCC>(encryption_params.protection_scheme)),
85 key_source_(key_source) {}
87 EncryptionHandler::~EncryptionHandler() {}
91 return Status(error::INVALID_ARGUMENT,
"Stream label function not set.");
93 if (num_input_streams() != 1 || next_output_stream_index() != 1) {
94 return Status(error::INVALID_ARGUMENT,
95 "Expects exactly one input and output.");
102 switch (stream_data->stream_data_type) {
103 case StreamDataType::kStreamInfo:
104 status = ProcessStreamInfo(stream_data->stream_info.get());
106 case StreamDataType::kSegmentInfo: {
107 SegmentInfo* segment_info = stream_data->segment_info.get();
108 segment_info->is_encrypted = remaining_clear_lead_ <= 0;
110 const bool key_rotation_enabled = crypto_period_duration_ != 0;
111 if (key_rotation_enabled)
112 segment_info->key_rotation_encryption_config = encryption_config_;
113 if (!segment_info->is_subsegment) {
114 if (key_rotation_enabled)
115 check_new_crypto_period_ =
true;
116 if (remaining_clear_lead_ > 0)
117 remaining_clear_lead_ -= segment_info->duration;
121 case StreamDataType::kMediaSample:
122 status = ProcessMediaSample(stream_data->media_sample.get());
125 VLOG(3) <<
"Stream data type "
126 <<
static_cast<int>(stream_data->stream_data_type) <<
" ignored.";
129 return status.ok() ?
Dispatch(std::move(stream_data)) : status;
132 Status EncryptionHandler::ProcessStreamInfo(
StreamInfo* stream_info) {
133 if (stream_info->is_encrypted()) {
134 return Status(error::INVALID_ARGUMENT,
135 "Input stream is already encrypted.");
138 remaining_clear_lead_ =
140 crypto_period_duration_ =
141 encryption_params_.crypto_period_duration_in_seconds *
142 stream_info->time_scale();
143 codec_ = stream_info->codec();
144 nalu_length_size_ = GetNaluLengthSize(*stream_info);
145 stream_label_ = GetStreamLabelForEncryption(
150 vpx_parser_.reset(
new VP9Parser);
153 header_parser_.reset(
new H264VideoSliceHeaderParser);
156 header_parser_.reset(
new H265VideoSliceHeaderParser);
160 if (nalu_length_size_ > 0) {
161 LOG(WARNING) <<
"Unknown video codec '" << codec_ <<
"'";
162 return Status(error::ENCRYPTION_FAILURE,
"Unknown video codec.");
165 if (header_parser_) {
166 CHECK_NE(nalu_length_size_, 0u) <<
"AnnexB stream is not supported yet";
167 if (!header_parser_->Initialize(stream_info->codec_config())) {
168 return Status(error::ENCRYPTION_FAILURE,
169 "Fail to read SPS and PPS data.");
173 Status status = SetupProtectionPattern(stream_info->stream_type());
177 EncryptionKey encryption_key;
178 const bool key_rotation_enabled = crypto_period_duration_ != 0;
179 if (key_rotation_enabled) {
180 check_new_crypto_period_ =
true;
182 encryption_key.key_id.assign(
183 kKeyRotationDefaultKeyId,
184 kKeyRotationDefaultKeyId +
sizeof(kKeyRotationDefaultKeyId));
187 encryption_key.key = encryption_key.key_id;
189 status = key_source_->
GetKey(stream_label_, &encryption_key);
193 if (!CreateEncryptor(encryption_key))
194 return Status(error::ENCRYPTION_FAILURE,
"Failed to create encryptor");
196 stream_info->set_is_encrypted(
true);
198 stream_info->set_encryption_config(*encryption_config_);
202 Status EncryptionHandler::ProcessMediaSample(MediaSample* sample) {
206 std::vector<VPxFrameInfo> vpx_frames;
208 !vpx_parser_->Parse(sample->data(), sample->data_size(), &vpx_frames)) {
209 return Status(error::ENCRYPTION_FAILURE,
"Failed to parse vpx frame.");
215 if (check_new_crypto_period_) {
216 const int64_t current_crypto_period_index =
217 sample->dts() / crypto_period_duration_;
218 if (current_crypto_period_index != prev_crypto_period_index_) {
219 EncryptionKey encryption_key;
221 current_crypto_period_index, stream_label_, &encryption_key);
224 if (!CreateEncryptor(encryption_key))
225 return Status(error::ENCRYPTION_FAILURE,
"Failed to create encryptor");
226 prev_crypto_period_index_ = current_crypto_period_index;
228 check_new_crypto_period_ =
false;
231 if (remaining_clear_lead_ > 0)
234 std::unique_ptr<DecryptConfig> decrypt_config(
235 new DecryptConfig(encryption_config_->key_id, encryptor_->iv(),
236 std::vector<SubsampleEntry>(), protection_scheme_,
237 crypt_byte_block_, skip_byte_block_));
240 result = EncryptVpxFrame(vpx_frames, sample, decrypt_config.get());
242 DCHECK_EQ(decrypt_config->GetTotalSizeOfSubsamples(),
243 sample->data_size());
245 }
else if (header_parser_) {
246 result = EncryptNalFrame(sample, decrypt_config.get());
248 DCHECK_EQ(decrypt_config->GetTotalSizeOfSubsamples(),
249 sample->data_size());
252 if (sample->data_size() > leading_clear_bytes_size_) {
253 EncryptBytes(sample->writable_data() + leading_clear_bytes_size_,
254 sample->data_size() - leading_clear_bytes_size_);
258 return Status(error::ENCRYPTION_FAILURE,
"Failed to encrypt samples.");
259 sample->set_is_encrypted(
true);
260 sample->set_decrypt_config(std::move(decrypt_config));
261 encryptor_->UpdateIv();
265 Status EncryptionHandler::SetupProtectionPattern(StreamType stream_type) {
266 switch (protection_scheme_) {
267 case kAppleSampleAesProtectionScheme: {
268 const size_t kH264LeadingClearBytesSize = 32u;
269 const size_t kSmallNalUnitSize = 32u + 16u;
270 const size_t kAudioLeadingClearBytesSize = 16u;
274 crypt_byte_block_ = 1u;
275 skip_byte_block_ = 9u;
276 leading_clear_bytes_size_ = kH264LeadingClearBytesSize;
277 min_protected_data_size_ = kSmallNalUnitSize + 1u;
280 FALLTHROUGH_INTENDED;
286 crypt_byte_block_ = 0u;
287 skip_byte_block_ = 0u;
288 leading_clear_bytes_size_ = kAudioLeadingClearBytesSize;
289 min_protected_data_size_ = leading_clear_bytes_size_ + 1u;
292 return Status(error::ENCRYPTION_FAILURE,
293 "Only AAC/AC3 and H264 are supported in Sample AES.");
298 FALLTHROUGH_INTENDED;
300 if (stream_type == kStreamVideo) {
302 crypt_byte_block_ = 1u;
303 skip_byte_block_ = 9u;
313 crypt_byte_block_ = 1u;
314 skip_byte_block_ = 0u;
319 crypt_byte_block_ = 0u;
320 skip_byte_block_ = 0u;
325 bool EncryptionHandler::CreateEncryptor(
const EncryptionKey& encryption_key) {
326 std::unique_ptr<AesCryptor> encryptor;
327 switch (protection_scheme_) {
329 encryptor.reset(
new AesCtrEncryptor);
332 encryptor.reset(
new AesCbcEncryptor(kNoPadding));
335 encryptor.reset(
new AesPatternCryptor(
336 crypt_byte_block_, skip_byte_block_,
338 AesCryptor::kDontUseConstantIv,
339 std::unique_ptr<AesCryptor>(
new AesCtrEncryptor())));
342 encryptor.reset(
new AesPatternCryptor(
343 crypt_byte_block_, skip_byte_block_,
345 AesCryptor::kUseConstantIv,
346 std::unique_ptr<AesCryptor>(
new AesCbcEncryptor(kNoPadding))));
348 case kAppleSampleAesProtectionScheme:
349 if (crypt_byte_block_ == 0 && skip_byte_block_ == 0) {
351 new AesCbcEncryptor(kNoPadding, AesCryptor::kUseConstantIv));
353 encryptor.reset(
new AesPatternCryptor(
354 crypt_byte_block_, skip_byte_block_,
356 AesCryptor::kUseConstantIv,
357 std::unique_ptr<AesCryptor>(
new AesCbcEncryptor(kNoPadding))));
361 LOG(ERROR) <<
"Unsupported protection scheme.";
365 std::vector<uint8_t> iv = encryption_key.iv;
368 LOG(ERROR) <<
"Failed to generate random iv.";
372 const bool initialized =
373 encryptor->InitializeWithIv(encryption_key.key, iv);
374 encryptor_ = std::move(encryptor);
376 encryption_config_.reset(
new EncryptionConfig);
377 encryption_config_->protection_scheme = protection_scheme_;
378 encryption_config_->crypt_byte_block = crypt_byte_block_;
379 encryption_config_->skip_byte_block = skip_byte_block_;
380 if (encryptor_->use_constant_iv()) {
381 encryption_config_->per_sample_iv_size = 0;
382 encryption_config_->constant_iv = iv;
384 encryption_config_->per_sample_iv_size =
static_cast<uint8_t
>(iv.size());
386 encryption_config_->key_id = encryption_key.key_id;
387 encryption_config_->key_system_info = encryption_key.key_system_info;
391 bool EncryptionHandler::EncryptVpxFrame(
392 const std::vector<VPxFrameInfo>& vpx_frames,
394 DecryptConfig* decrypt_config) {
395 uint8_t* data = sample->writable_data();
396 for (
const VPxFrameInfo& frame : vpx_frames) {
397 uint16_t clear_bytes =
398 static_cast<uint16_t
>(frame.uncompressed_header_size);
399 uint32_t cipher_bytes =
static_cast<uint32_t
>(
400 frame.frame_size - frame.uncompressed_header_size);
410 const uint16_t misalign_bytes = cipher_bytes % kCencBlockSize;
411 clear_bytes += misalign_bytes;
412 cipher_bytes -= misalign_bytes;
414 decrypt_config->AddSubsample(clear_bytes, cipher_bytes);
415 if (cipher_bytes > 0)
416 EncryptBytes(data + clear_bytes, cipher_bytes);
417 data += frame.frame_size;
420 const bool is_superframe = vpx_frames.size() > 1;
422 size_t index_size = sample->data() + sample->data_size() - data;
423 DCHECK_LE(index_size, 2 + vpx_frames.size() * 4);
424 DCHECK_GE(index_size, 2 + vpx_frames.size() * 1);
425 uint16_t clear_bytes =
static_cast<uint16_t
>(index_size);
426 uint32_t cipher_bytes = 0;
427 decrypt_config->AddSubsample(clear_bytes, cipher_bytes);
432 bool EncryptionHandler::EncryptNalFrame(MediaSample* sample,
433 DecryptConfig* decrypt_config) {
434 DCHECK_NE(nalu_length_size_, 0u);
435 DCHECK(header_parser_);
436 const Nalu::CodecType nalu_type =
437 (codec_ == kCodecH265) ? Nalu::kH265 : Nalu::kH264;
438 NaluReader reader(nalu_type, nalu_length_size_, sample->writable_data(),
439 sample->data_size());
443 uint64_t accumulated_clear_bytes = 0;
446 NaluReader::Result result;
447 while ((result = reader.Advance(&nalu)) == NaluReader::kOk) {
448 const uint64_t nalu_total_size = nalu.header_size() + nalu.payload_size();
449 if (nalu.is_video_slice() && nalu_total_size >= min_protected_data_size_) {
450 uint64_t current_clear_bytes = leading_clear_bytes_size_;
451 if (current_clear_bytes == 0) {
454 const int64_t video_slice_header_size =
455 header_parser_->GetHeaderSize(nalu);
456 if (video_slice_header_size < 0) {
457 LOG(ERROR) <<
"Failed to read slice header.";
460 current_clear_bytes = nalu.header_size() + video_slice_header_size;
462 uint64_t cipher_bytes = nalu_total_size - current_clear_bytes;
470 if (protection_scheme_ == FOURCC_cbc1 ||
471 protection_scheme_ == FOURCC_cens ||
472 protection_scheme_ == FOURCC_cenc) {
473 const uint16_t misalign_bytes = cipher_bytes % kCencBlockSize;
474 current_clear_bytes += misalign_bytes;
475 cipher_bytes -= misalign_bytes;
478 const uint8_t* nalu_data = nalu.data() + current_clear_bytes;
479 EncryptBytes(const_cast<uint8_t*>(nalu_data), cipher_bytes);
482 accumulated_clear_bytes + nalu_length_size_ + current_clear_bytes,
483 cipher_bytes, decrypt_config);
484 accumulated_clear_bytes = 0;
487 accumulated_clear_bytes += nalu_length_size_ + nalu_total_size;
490 if (result != NaluReader::kEOStream) {
491 LOG(ERROR) <<
"Failed to parse NAL units.";
494 AddSubsample(accumulated_clear_bytes, 0, decrypt_config);
498 void EncryptionHandler::EncryptBytes(uint8_t* data,
size_t size) {
500 CHECK(encryptor_->Crypt(data, size, data));
503 void EncryptionHandler::InjectVpxParserForTesting(
504 std::unique_ptr<VPxParser> vpx_parser) {
505 vpx_parser_ = std::move(vpx_parser);
508 void EncryptionHandler::InjectVideoSliceHeaderParserForTesting(
509 std::unique_ptr<VideoSliceHeaderParser> header_parser) {
510 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.