DASH Media Packaging SDK
 All Classes Namespaces Functions Variables Typedefs 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 edash_packager {
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, kChainAcrossCalls));
50  break;
51  case FOURCC_cens:
52  aes_decryptor.reset(
53  new AesPatternCryptor(decrypt_config->crypt_byte_block(),
54  decrypt_config->skip_byte_block(),
55  AesPatternCryptor::kDontUseConstantIv,
56  scoped_ptr<AesCryptor>(new AesCtrDecryptor)));
57  break;
58  case FOURCC_cbcs:
59  aes_decryptor.reset(
60  new AesPatternCryptor(decrypt_config->crypt_byte_block(),
61  decrypt_config->skip_byte_block(),
62  AesPatternCryptor::kUseConstantIv,
63  scoped_ptr<AesCryptor>(new AesCbcDecryptor(
64  kNoPadding, kChainAcrossCalls))));
65  break;
66  default:
67  LOG(ERROR) << "Unsupported protection scheme: "
68  << decrypt_config->protection_scheme();
69  return false;
70  }
71 
72  if (!aes_decryptor->InitializeWithIv(key.key, decrypt_config->iv())) {
73  LOG(ERROR) << "Failed to initialize AesDecryptor for decryption.";
74  return false;
75  }
76  decryptor = aes_decryptor.release();
77  decryptor_map_[decrypt_config->key_id()] = decryptor;
78  } else {
79  decryptor = found->second;
80  }
81  if (!decryptor->SetIv(decrypt_config->iv())) {
82  LOG(ERROR) << "Invalid initialization vector.";
83  return false;
84  }
85 
86  if (decrypt_config->subsamples().empty()) {
87  // Sample not encrypted using subsample encryption. Decrypt whole.
88  if (!decryptor->Crypt(buffer, buffer_size, buffer)) {
89  LOG(ERROR) << "Error during bulk sample decryption.";
90  return false;
91  }
92  return true;
93  }
94 
95  // Subsample decryption.
96  const std::vector<SubsampleEntry>& subsamples = decrypt_config->subsamples();
97  uint8_t* current_ptr = buffer;
98  const uint8_t* const buffer_end = buffer + buffer_size;
99  for (const auto& subsample : subsamples) {
100  if ((current_ptr + subsample.clear_bytes + subsample.cipher_bytes) >
101  buffer_end) {
102  LOG(ERROR) << "Subsamples overflow sample buffer.";
103  return false;
104  }
105  current_ptr += subsample.clear_bytes;
106  if (!decryptor->Crypt(current_ptr, subsample.cipher_bytes, current_ptr)) {
107  LOG(ERROR) << "Error decrypting subsample buffer.";
108  return false;
109  }
110  current_ptr += subsample.cipher_bytes;
111  }
112  return true;
113 }
114 
115 } // namespace media
116 } // namespace edash_packager
virtual Status GetKey(TrackType track_type, EncryptionKey *key)=0