DASH Media Packaging SDK
 All Classes Namespaces Functions Variables Typedefs Enumerator
key_source.cc
1 // Copyright 2014 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/key_source.h"
8 
9 #include "packager/base/strings/string_number_conversions.h"
10 #include "packager/media/base/aes_encryptor.h"
11 #include "packager/media/base/buffer_writer.h"
12 
13 namespace {
14 // TODO(kqyang): Consider making it configurable.
15 const char kDefaultUUID[] = "edef8ba9-79d6-4ace-a3c8-27dcd51d21ed";
16 const char kDefaultSystemName[] = "";
17 } // namespace
18 
19 namespace edash_packager {
20 namespace media {
21 
22 EncryptionKey::EncryptionKey() {}
23 EncryptionKey::~EncryptionKey() {}
24 
25 KeySource::~KeySource() {}
26 
27 Status KeySource::FetchKeys(const std::vector<uint8_t>& content_id,
28  const std::string& policy) {
29  // Do nothing for fixed key encryption/decryption.
30  return Status::OK;
31 }
32 
33 Status KeySource::FetchKeys(const std::vector<uint8_t>& pssh_box) {
34  // Do nothing for fixed key encryption/decryption.
35  return Status::OK;
36 }
37 
38 Status KeySource::FetchKeys(const std::vector<std::vector<uint8_t>>& key_ids) {
39  // Do nothing for fixed key encryption/decryption.
40  return Status::OK;
41 }
42 
43 Status KeySource::FetchKeys(uint32_t asset_id) {
44  // Do nothing for fixed key encryption/decryption.
45  return Status::OK;
46 }
47 
48 Status KeySource::GetKey(TrackType track_type, EncryptionKey* key) {
49  DCHECK(key);
50  DCHECK(encryption_key_);
51  *key = *encryption_key_;
52  return Status::OK;
53 }
54 
55 Status KeySource::GetKey(const std::vector<uint8_t>& key_id,
56  EncryptionKey* key) {
57  DCHECK(key);
58  DCHECK(encryption_key_);
59  if (key_id != encryption_key_->key_id) {
60  return Status(error::NOT_FOUND, std::string("Key for key ID ") +
61  base::HexEncode(&key_id[0], key_id.size()) +
62  " was not found.");
63  }
64  *key = *encryption_key_;
65  return Status::OK;
66 }
67 
68 Status KeySource::GetCryptoPeriodKey(uint32_t crypto_period_index,
69  TrackType track_type,
70  EncryptionKey* key) {
71  *key = *encryption_key_;
72  // A naive key rotation algorithm is implemented here by left rotating the
73  // key, key_id and pssh. Note that this implementation is only intended for
74  // testing purpose. The actual key rotation algorithm can be much more
75  // complicated.
76  LOG(WARNING)
77  << "This naive key rotation algorithm should not be used in production.";
78  std::rotate(key->key_id.begin(),
79  key->key_id.begin() + (crypto_period_index % key->key_id.size()),
80  key->key_id.end());
81  std::rotate(key->key.begin(),
82  key->key.begin() + (crypto_period_index % key->key.size()),
83  key->key.end());
84  const size_t kPsshHeaderSize = 32u;
85  std::vector<uint8_t> pssh_data(key->pssh.begin() + kPsshHeaderSize,
86  key->pssh.end());
87  std::rotate(pssh_data.begin(),
88  pssh_data.begin() + (crypto_period_index % pssh_data.size()),
89  pssh_data.end());
90  key->pssh = PsshBoxFromPsshData(pssh_data);
91  return Status::OK;
92 }
93 
94 std::string KeySource::UUID() {
95  return kDefaultUUID;
96 }
97 
98 std::string KeySource::SystemName() {
99  return kDefaultSystemName;
100 }
101 
102 scoped_ptr<KeySource> KeySource::CreateFromHexStrings(
103  const std::string& key_id_hex,
104  const std::string& key_hex,
105  const std::string& pssh_data_hex,
106  const std::string& iv_hex) {
107  scoped_ptr<EncryptionKey> encryption_key(new EncryptionKey());
108 
109  if (!base::HexStringToBytes(key_id_hex, &encryption_key->key_id)) {
110  LOG(ERROR) << "Cannot parse key_id_hex " << key_id_hex;
111  return scoped_ptr<KeySource>();
112  }
113 
114  if (!base::HexStringToBytes(key_hex, &encryption_key->key)) {
115  LOG(ERROR) << "Cannot parse key_hex " << key_hex;
116  return scoped_ptr<KeySource>();
117  }
118 
119  std::vector<uint8_t> pssh_data;
120  if (!pssh_data_hex.empty() &&
121  !base::HexStringToBytes(pssh_data_hex, &pssh_data)) {
122  LOG(ERROR) << "Cannot parse pssh_hex " << pssh_data_hex;
123  return scoped_ptr<KeySource>();
124  }
125 
126  if (!iv_hex.empty()) {
127  if (!base::HexStringToBytes(iv_hex, &encryption_key->iv)) {
128  LOG(ERROR) << "Cannot parse iv_hex " << iv_hex;
129  return scoped_ptr<KeySource>();
130  }
131  }
132 
133  encryption_key->pssh = PsshBoxFromPsshData(pssh_data);
134  return scoped_ptr<KeySource>(
135  new KeySource(encryption_key.Pass()));
136 }
137 
139  const std::string& track_type_string) {
140  if (track_type_string == "SD")
141  return TRACK_TYPE_SD;
142  if (track_type_string == "HD")
143  return TRACK_TYPE_HD;
144  if (track_type_string == "AUDIO")
145  return TRACK_TYPE_AUDIO;
146  if (track_type_string == "UNSPECIFIED")
147  return TRACK_TYPE_UNSPECIFIED;
148  LOG(WARNING) << "Unexpected track type: " << track_type_string;
149  return TRACK_TYPE_UNKNOWN;
150 }
151 
152 std::string KeySource::TrackTypeToString(TrackType track_type) {
153  switch (track_type) {
154  case TRACK_TYPE_SD:
155  return "SD";
156  case TRACK_TYPE_HD:
157  return "HD";
158  case TRACK_TYPE_AUDIO:
159  return "AUDIO";
160  default:
161  NOTIMPLEMENTED() << "Unknown track type: " << track_type;
162  return "UNKNOWN";
163  }
164 }
165 
166 std::vector<uint8_t> KeySource::PsshBoxFromPsshData(
167  const std::vector<uint8_t>& pssh_data) {
168  const uint8_t kPsshFourCC[] = {'p', 's', 's', 'h'};
169  const uint32_t kVersionAndFlags = 0;
170 
171  const uint32_t pssh_data_size = pssh_data.size();
172  const uint32_t total_size =
173  sizeof(total_size) + sizeof(kPsshFourCC) + sizeof(kVersionAndFlags) +
174  sizeof(kWidevineSystemId) + sizeof(pssh_data_size) + pssh_data_size;
175 
176  BufferWriter writer;
177  writer.AppendInt(total_size);
178  writer.AppendArray(kPsshFourCC, sizeof(kPsshFourCC));
179  writer.AppendInt(kVersionAndFlags);
180  writer.AppendArray(kWidevineSystemId, sizeof(kWidevineSystemId));
181  writer.AppendInt(pssh_data_size);
182  writer.AppendVector(pssh_data);
183  return std::vector<uint8_t>(writer.Buffer(), writer.Buffer() + writer.Size());
184 }
185 
186 KeySource::KeySource() {}
187 KeySource::KeySource(scoped_ptr<EncryptionKey> encryption_key)
188  : encryption_key_(encryption_key.Pass()) {
189  DCHECK(encryption_key_);
190 }
191 
192 } // namespace media
193 } // namespace edash_packager
virtual Status GetKey(TrackType track_type, EncryptionKey *key)
Definition: key_source.cc:48
virtual Status GetCryptoPeriodKey(uint32_t crypto_period_index, TrackType track_type, EncryptionKey *key)
Definition: key_source.cc:68
virtual Status FetchKeys(const std::vector< uint8_t > &content_id, const std::string &policy)
Definition: key_source.cc:27
virtual std::string UUID()
Definition: key_source.cc:94
KeySource is responsible for encryption key acquisition.
Definition: key_source.h:33
static scoped_ptr< KeySource > CreateFromHexStrings(const std::string &key_id_hex, const std::string &key_hex, const std::string &pssh_data_hex, const std::string &iv_hex)
Definition: key_source.cc:102
const uint8_t * Buffer() const
Definition: buffer_writer.h:59
static std::vector< uint8_t > PsshBoxFromPsshData(const std::vector< uint8_t > &pssh_data)
Definition: key_source.cc:166
virtual std::string SystemName()
Definition: key_source.cc:98
static TrackType GetTrackTypeFromString(const std::string &track_type_string)
Convert string representation of track type to enum representation.
Definition: key_source.cc:138
static std::string TrackTypeToString(TrackType track_type)
Convert TrackType to string.
Definition: key_source.cc:152