Shaka Packager SDK
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends
decryptor_source.cc
1 // Copyright 2016 Google Inc. 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/base/decryptor_source.h"
8 
9 #include "packager/base/logging.h"
10 #include "packager/media/base/aes_decryptor.h"
11 #include "packager/media/base/aes_pattern_cryptor.h"
12 
13 namespace shaka {
14 namespace media {
15 
16 DecryptorSource::DecryptorSource(KeySource* key_source)
17  : key_source_(key_source) {
18  CHECK(key_source);
19 }
20 DecryptorSource::~DecryptorSource() {}
21 
22 bool DecryptorSource::DecryptSampleBuffer(const DecryptConfig* decrypt_config,
23  uint8_t* buffer,
24  size_t buffer_size) {
25  DCHECK(decrypt_config);
26  DCHECK(buffer);
27 
28  // Get the decryptor object.
29  AesCryptor* decryptor = nullptr;
30  auto found = decryptor_map_.find(decrypt_config->key_id());
31  if (found == decryptor_map_.end()) {
32  // Create new AesDecryptor based on decryption mode.
33  EncryptionKey key;
34  Status status(key_source_->GetKey(decrypt_config->key_id(), &key));
35  if (!status.ok()) {
36  LOG(ERROR) << "Error retrieving decryption key: " << status;
37  return false;
38  }
39 
40  std::unique_ptr<AesCryptor> aes_decryptor;
41  switch (decrypt_config->protection_scheme()) {
42  case FOURCC_cenc:
43  aes_decryptor.reset(new AesCtrDecryptor);
44  break;
45  case FOURCC_cbc1:
46  aes_decryptor.reset(new AesCbcDecryptor(kNoPadding));
47  break;
48  case FOURCC_cens:
49  aes_decryptor.reset(new AesPatternCryptor(
50  decrypt_config->crypt_byte_block(),
51  decrypt_config->skip_byte_block(),
53  AesCryptor::kDontUseConstantIv,
54  std::unique_ptr<AesCryptor>(new AesCtrDecryptor())));
55  break;
56  case FOURCC_cbcs:
57  aes_decryptor.reset(new AesPatternCryptor(
58  decrypt_config->crypt_byte_block(),
59  decrypt_config->skip_byte_block(),
61  AesCryptor::kUseConstantIv,
62  std::unique_ptr<AesCryptor>(new AesCbcDecryptor(kNoPadding))));
63  break;
64  default:
65  LOG(ERROR) << "Unsupported protection scheme: "
66  << decrypt_config->protection_scheme();
67  return false;
68  }
69 
70  if (!aes_decryptor->InitializeWithIv(key.key, decrypt_config->iv())) {
71  LOG(ERROR) << "Failed to initialize AesDecryptor for decryption.";
72  return false;
73  }
74  decryptor = aes_decryptor.get();
75  decryptor_map_[decrypt_config->key_id()] = std::move(aes_decryptor);
76  } else {
77  decryptor = found->second.get();
78  }
79  if (!decryptor->SetIv(decrypt_config->iv())) {
80  LOG(ERROR) << "Invalid initialization vector.";
81  return false;
82  }
83 
84  if (decrypt_config->subsamples().empty()) {
85  // Sample not encrypted using subsample encryption. Decrypt whole.
86  if (!decryptor->Crypt(buffer, buffer_size, buffer)) {
87  LOG(ERROR) << "Error during bulk sample decryption.";
88  return false;
89  }
90  return true;
91  }
92 
93  // Subsample decryption.
94  const std::vector<SubsampleEntry>& subsamples = decrypt_config->subsamples();
95  uint8_t* current_ptr = buffer;
96  const uint8_t* const buffer_end = buffer + buffer_size;
97  for (const auto& subsample : subsamples) {
98  if ((current_ptr + subsample.clear_bytes + subsample.cipher_bytes) >
99  buffer_end) {
100  LOG(ERROR) << "Subsamples overflow sample buffer.";
101  return false;
102  }
103  current_ptr += subsample.clear_bytes;
104  if (!decryptor->Crypt(current_ptr, subsample.cipher_bytes, current_ptr)) {
105  LOG(ERROR) << "Error decrypting subsample buffer.";
106  return false;
107  }
108  current_ptr += subsample.cipher_bytes;
109  }
110  return true;
111 }
112 
113 } // namespace media
114 } // namespace shaka
virtual Status GetKey(const std::string &stream_label, EncryptionKey *key)=0