Shaka Packager SDK
Loading...
Searching...
No Matches
sample_aes_ec3_cryptor.cc
1// Copyright 2018 Google LLC. All rights reserved.
2//
3// Use of this source code is governed by a BSD-style
4// license that can be found in the LICENSE file or at
5// https://developers.google.com/open-source/licenses/bsd
6
7#include <packager/media/crypto/sample_aes_ec3_cryptor.h>
8
9#include <algorithm>
10#include <cstddef>
11#include <cstdint>
12#include <cstring>
13#include <ios>
14#include <memory>
15#include <utility>
16#include <vector>
17
18#include <absl/log/check.h>
19#include <absl/log/log.h>
20
21#include <packager/media/base/aes_cryptor.h>
22#include <packager/media/base/buffer_reader.h>
23
24namespace shaka {
25namespace media {
26namespace {
27
28bool ExtractEac3SyncframeSizes(const uint8_t* source,
29 size_t source_size,
30 std::vector<size_t>* syncframe_sizes) {
31 DCHECK(source);
32 DCHECK(syncframe_sizes);
33
34 syncframe_sizes->clear();
35 BufferReader frame(source, source_size);
36 // ASTC Standard A/52:2012 Annex E: Enhanced AC-3.
37 while (frame.HasBytes(1)) {
38 uint16_t syncword;
39 if (!frame.Read2(&syncword)) {
40 LOG(ERROR) << "Not enough bytes for syncword.";
41 return false;
42 }
43 if (syncword != 0x0B77) {
44 LOG(ERROR) << "Invalid E-AC3 frame. Seeing 0x" << std::hex << syncword
45 << std::dec
46 << ". The sync frame does not start with "
47 "the valid syncword 0x0B77.";
48 return false;
49 }
50 uint16_t stream_type_and_syncframe_size;
51 if (!frame.Read2(&stream_type_and_syncframe_size)) {
52 LOG(ERROR) << "Not enough bytes for syncframe size.";
53 return false;
54 }
55 // frmsiz = least significant 11 bits. syncframe_size is (frmsiz + 1) * 2.
56 const size_t syncframe_size =
57 ((stream_type_and_syncframe_size & 0x7FF) + 1) * 2;
58 if (!frame.SkipBytes(syncframe_size - sizeof(syncword) -
59 sizeof(stream_type_and_syncframe_size))) {
60 LOG(ERROR) << "Not enough bytes for syncframe. Expecting "
61 << syncframe_size << " bytes.";
62 return false;
63 }
64 syncframe_sizes->push_back(syncframe_size);
65 }
66 return true;
67}
68
69} // namespace
70
71SampleAesEc3Cryptor::SampleAesEc3Cryptor(std::unique_ptr<AesCryptor> cryptor)
72 : AesCryptor(AesCryptor::kUseConstantIv), cryptor_(std::move(cryptor)) {
73 DCHECK(cryptor_);
74 DCHECK(!cryptor_->use_constant_iv());
75}
76
77bool SampleAesEc3Cryptor::InitializeWithIv(const std::vector<uint8_t>& key,
78 const std::vector<uint8_t>& iv) {
79 return SetIv(iv) && cryptor_->InitializeWithIv(key, iv);
80}
81
82bool SampleAesEc3Cryptor::CryptInternal(const uint8_t* text,
83 size_t text_size,
84 uint8_t* crypt_text,
85 size_t* crypt_text_size) {
86 // |crypt_text_size| is the same as |text_size|.
87 if (*crypt_text_size < text_size) {
88 LOG(ERROR) << "Expecting output size of at least " << text_size
89 << " bytes.";
90 return false;
91 }
92 *crypt_text_size = text_size;
93
94 std::vector<size_t> syncframe_sizes;
95 if (!ExtractEac3SyncframeSizes(text, text_size, &syncframe_sizes))
96 return false;
97
98 // MPEG-2 Stream Encryption Format for HTTP Live Streaming 2.3.1.3 Enhanced
99 // AC-3: The first 16 bytes, starting with the syncframe() header, are not
100 // encrypted.
101 const size_t kLeadingClearBytesSize = 16u;
102
103 for (size_t syncframe_size : syncframe_sizes) {
104 memcpy(crypt_text, text, std::min(syncframe_size, kLeadingClearBytesSize));
105 if (syncframe_size > kLeadingClearBytesSize) {
106 // The residual block is left untouched (copied without
107 // encryption/decryption). No need to do special handling here.
108 if (!cryptor_->Crypt(text + kLeadingClearBytesSize,
109 syncframe_size - kLeadingClearBytesSize,
110 crypt_text + kLeadingClearBytesSize)) {
111 return false;
112 }
113 }
114 text += syncframe_size;
115 crypt_text += syncframe_size;
116 }
117 return true;
118}
119
120void SampleAesEc3Cryptor::SetIvInternal() {
121 CHECK(cryptor_->SetIv(iv()));
122}
123
124} // namespace media
125} // namespace shaka
bool SetIv(const std::vector< uint8_t > &iv)
const std::vector< uint8_t > & iv() const
Definition aes_cryptor.h:86
SampleAesEc3Cryptor(std::unique_ptr< AesCryptor > cryptor)
bool InitializeWithIv(const std::vector< uint8_t > &key, const std::vector< uint8_t > &iv) override
All the methods that are virtual are virtual for mocking.