Shaka Packager SDK
raw_key_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/raw_key_source.h"
8 
9 #include <algorithm>
10 #include "packager/base/logging.h"
11 #include "packager/base/strings/string_number_conversions.h"
12 #include "packager/media/base/key_source.h"
13 #include "packager/status_macros.h"
14 
15 namespace {
16 const char kEmptyDrmLabel[] = "";
17 } // namespace
18 
19 namespace shaka {
20 namespace media {
21 
22 RawKeySource::~RawKeySource() {}
23 
24 Status RawKeySource::FetchKeys(EmeInitDataType init_data_type,
25  const std::vector<uint8_t>& init_data) {
26  // Do nothing for raw key encryption/decryption.
27  return Status::OK;
28 }
29 
30 Status RawKeySource::GetKey(const std::string& stream_label,
31  EncryptionKey* key) {
32  DCHECK(key);
33  // Try to find the key with label |stream_label|. If it is not available,
34  // fall back to the default empty label if it is available.
35  auto iter = encryption_key_map_.find(stream_label);
36  if (iter == encryption_key_map_.end()) {
37  iter = encryption_key_map_.find(kEmptyDrmLabel);
38  if (iter == encryption_key_map_.end()) {
39  return Status(error::NOT_FOUND,
40  "Key for '" + stream_label + "' was not found.");
41  }
42  }
43  *key = *iter->second;
44  return Status::OK;
45 }
46 
47 Status RawKeySource::GetKey(const std::vector<uint8_t>& key_id,
48  EncryptionKey* key) {
49  DCHECK(key);
50  for (const auto& pair : encryption_key_map_) {
51  if (pair.second->key_id == key_id) {
52  *key = *pair.second;
53  return Status::OK;
54  }
55  }
56  return Status(error::INTERNAL_ERROR,
57  "Key for key_id=" + base::HexEncode(&key_id[0], key_id.size()) +
58  " was not found.");
59 }
60 
61 Status RawKeySource::GetCryptoPeriodKey(uint32_t crypto_period_index,
62  const std::string& stream_label,
63  EncryptionKey* key) {
64  RETURN_IF_ERROR(GetKey(stream_label, key));
65 
66  // A naive key rotation algorithm is implemented here by left rotating the
67  // key, key_id and pssh. Note that this implementation is only intended for
68  // testing purpose. The actual key rotation algorithm can be much more
69  // complicated.
70  LOG(WARNING)
71  << "This naive key rotation algorithm should not be used in production.";
72  std::rotate(key->key_id.begin(),
73  key->key_id.begin() + (crypto_period_index % key->key_id.size()),
74  key->key_id.end());
75  std::rotate(key->key.begin(),
76  key->key.begin() + (crypto_period_index % key->key.size()),
77  key->key.end());
78 
79  // Clear |key->key_system_info| to prepare for update. The original
80  // |key_system_info| is saved as it may still be useful later.
81  std::vector<ProtectionSystemSpecificInfo> original_key_system_info;
82  key->key_system_info.swap(original_key_system_info);
83 
84  EncryptionKeyMap encryption_key_map;
85  encryption_key_map[stream_label].reset(new EncryptionKey(*key));
86  RETURN_IF_ERROR(UpdateProtectionSystemInfo(&encryption_key_map));
87  key->key_system_info = encryption_key_map[stream_label]->key_system_info;
88 
89  // It is possible that the generated |key_system_info| is empty. This happens
90  // when RawKeyParams.pssh is specified. Restore the original key system info
91  // in this case.
92  if (key->key_system_info.empty())
93  key->key_system_info.swap(original_key_system_info);
94 
95  return Status::OK;
96 }
97 
98 std::unique_ptr<RawKeySource> RawKeySource::Create(const RawKeyParams& raw_key,
99  int protection_systems_flags,
100  FourCC protection_scheme) {
101  std::vector<ProtectionSystemSpecificInfo> key_system_info;
102  bool pssh_provided = false;
103  if (!raw_key.pssh.empty()) {
104  pssh_provided = true;
106  raw_key.pssh.data(), raw_key.pssh.size(), &key_system_info)) {
107  LOG(ERROR) << "--pssh argument should be full PSSH boxes.";
108  return std::unique_ptr<RawKeySource>();
109  }
110  }
111 
112  EncryptionKeyMap encryption_key_map;
113  for (const auto& entry : raw_key.key_map) {
114  const std::string& drm_label = entry.first;
115  const RawKeyParams::KeyInfo& key_pair = entry.second;
116 
117  if (key_pair.key_id.size() != 16) {
118  LOG(ERROR) << "Invalid key ID size '" << key_pair.key_id.size()
119  << "', must be 16 bytes.";
120  return std::unique_ptr<RawKeySource>();
121  }
122  if (key_pair.key.size() != 16) {
123  // CENC only supports AES-128, i.e. 16 bytes.
124  LOG(ERROR) << "Invalid key size '" << key_pair.key.size()
125  << "', must be 16 bytes.";
126  return std::unique_ptr<RawKeySource>();
127  }
128 
129  std::unique_ptr<EncryptionKey> encryption_key(new EncryptionKey);
130  encryption_key->key_id = key_pair.key_id;
131  encryption_key->key = key_pair.key;
132  encryption_key->iv = raw_key.iv;
133  encryption_key->key_system_info = key_system_info;
134  encryption_key_map[drm_label] = std::move(encryption_key);
135  }
136 
137  // Generate common protection system if no other protection system is
138  // specified.
139  if (!pssh_provided && protection_systems_flags == NO_PROTECTION_SYSTEM_FLAG) {
140  protection_systems_flags = COMMON_PROTECTION_SYSTEM_FLAG;
141  }
142 
143  return std::unique_ptr<RawKeySource>(
144  new RawKeySource(std::move(encryption_key_map), protection_systems_flags,
145  protection_scheme));
146 }
147 
148 RawKeySource::RawKeySource()
149  : KeySource(NO_PROTECTION_SYSTEM_FLAG, FOURCC_NULL) {}
150 
151 RawKeySource::RawKeySource(EncryptionKeyMap&& encryption_key_map,
152  int protection_systems_flags,
153  FourCC protection_scheme)
154  : KeySource(protection_systems_flags, protection_scheme),
155  encryption_key_map_(std::move(encryption_key_map)) {
156  UpdateProtectionSystemInfo(&encryption_key_map_);
157 }
158 
159 } // namespace media
160 } // namespace shaka
Status GetCryptoPeriodKey(uint32_t crypto_period_index, const std::string &stream_label, EncryptionKey *key) override
static std::unique_ptr< RawKeySource > Create(const RawKeyParams &raw_key, int protection_system_flags, FourCC protection_scheme)
All the methods that are virtual are virtual for mocking.
Status UpdateProtectionSystemInfo(EncryptionKeyMap *encryption_key_map)
Definition: key_source.cc:47
Raw key encryption/decryption parameters, i.e. with key parameters provided.
Definition: crypto_params.h:86
std::map< StreamLabel, KeyInfo > key_map
std::vector< uint8_t > iv
Definition: crypto_params.h:90
A key source that uses raw keys for encryption.
Status GetKey(const std::string &stream_label, EncryptionKey *key) override
KeySource is responsible for encryption key acquisition.
Definition: key_source.h:48
std::vector< uint8_t > pssh
Definition: crypto_params.h:94
Status FetchKeys(EmeInitDataType init_data_type, const std::vector< uint8_t > &init_data) override
static bool ParseBoxes(const uint8_t *data, size_t data_size, std::vector< ProtectionSystemSpecificInfo > *pssh_boxes)