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