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