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