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