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