OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "media/cdm/json_web_key.h" | 5 #include "media/cdm/json_web_key.h" |
6 | 6 |
7 #include "base/base64.h" | 7 #include "base/base64.h" |
8 #include "base/json/json_reader.h" | 8 #include "base/json/json_reader.h" |
9 #include "base/json/json_string_value_serializer.h" | 9 #include "base/json/json_string_value_serializer.h" |
10 #include "base/json/string_escape.h" | 10 #include "base/json/string_escape.h" |
11 #include "base/logging.h" | 11 #include "base/logging.h" |
12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
13 #include "base/strings/string_number_conversions.h" | |
13 #include "base/strings/string_util.h" | 14 #include "base/strings/string_util.h" |
14 #include "base/values.h" | 15 #include "base/values.h" |
15 | 16 |
16 namespace media { | 17 namespace media { |
17 | 18 |
18 const char kKeysTag[] = "keys"; | 19 const char kKeysTag[] = "keys"; |
19 const char kKeyTypeTag[] = "kty"; | 20 const char kKeyTypeTag[] = "kty"; |
20 const char kKeyTypeOct[] = "oct"; // Octet sequence. | 21 const char kKeyTypeOct[] = "oct"; // Octet sequence. |
21 const char kAlgTag[] = "alg"; | 22 const char kAlgTag[] = "alg"; |
22 const char kAlgA128KW[] = "A128KW"; // AES key wrap using a 128-bit key. | 23 const char kAlgA128KW[] = "A128KW"; // AES key wrap using a 128-bit key. |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
81 | 82 |
82 std::string decoded_text; | 83 std::string decoded_text; |
83 if (!base::Base64Decode(modified_text, &decoded_text)) { | 84 if (!base::Base64Decode(modified_text, &decoded_text)) { |
84 DVLOG(1) << "Base64 decoding failed on: " << modified_text; | 85 DVLOG(1) << "Base64 decoding failed on: " << modified_text; |
85 return std::string(); | 86 return std::string(); |
86 } | 87 } |
87 | 88 |
88 return decoded_text; | 89 return decoded_text; |
89 } | 90 } |
90 | 91 |
92 static std::string ShortenTo64Characters(const std::string& input) { | |
93 if (input.length() <= 64u) | |
94 return input; | |
95 | |
96 std::string result = input.substr(0, 61); | |
97 result.append("..."); | |
98 return result; | |
99 } | |
100 | |
91 std::string GenerateJWKSet(const uint8* key, int key_length, | 101 std::string GenerateJWKSet(const uint8* key, int key_length, |
92 const uint8* key_id, int key_id_length) { | 102 const uint8* key_id, int key_id_length) { |
93 // Both |key| and |key_id| need to be base64 encoded strings in the JWK. | 103 // Both |key| and |key_id| need to be base64 encoded strings in the JWK. |
94 std::string key_base64 = EncodeBase64Url(key, key_length); | 104 std::string key_base64 = EncodeBase64Url(key, key_length); |
95 std::string key_id_base64 = EncodeBase64Url(key_id, key_id_length); | 105 std::string key_id_base64 = EncodeBase64Url(key_id, key_id_length); |
96 | 106 |
97 // Create the JWK, and wrap it into a JWK Set. | 107 // Create the JWK, and wrap it into a JWK Set. |
98 scoped_ptr<base::DictionaryValue> jwk(new base::DictionaryValue()); | 108 scoped_ptr<base::DictionaryValue> jwk(new base::DictionaryValue()); |
99 jwk->SetString(kKeyTypeTag, kKeyTypeOct); | 109 jwk->SetString(kKeyTypeTag, kKeyTypeOct); |
100 jwk->SetString(kAlgTag, kAlgA128KW); | 110 jwk->SetString(kAlgTag, kAlgA128KW); |
(...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
219 } else { | 229 } else { |
220 DVLOG(1) << "Invalid '" << kTypeTag << "' value: " << session_type_id; | 230 DVLOG(1) << "Invalid '" << kTypeTag << "' value: " << session_type_id; |
221 return false; | 231 return false; |
222 } | 232 } |
223 | 233 |
224 // All done. | 234 // All done. |
225 keys->swap(local_keys); | 235 keys->swap(local_keys); |
226 return true; | 236 return true; |
227 } | 237 } |
228 | 238 |
239 bool ExtractKeyIdsFromKeyIdsInitData(const std::string& input, | |
240 KeyIdList* key_ids, | |
241 std::string* error_message) { | |
242 if (!base::IsStringASCII(input)) { | |
243 error_message->assign("Non ASCII: "); | |
244 error_message->append(ShortenTo64Characters(input)); | |
sandersd (OOO until July 31)
2015/03/04 01:39:24
I'm not too happy with this implementation when we
jrummell
2015/03/04 22:37:16
Found a routine to escape non-ASCII characters, so
| |
245 return false; | |
246 } | |
247 | |
248 scoped_ptr<base::Value> root(base::JSONReader().ReadToValue(input)); | |
249 if (!root.get() || root->GetType() != base::Value::TYPE_DICTIONARY) { | |
250 error_message->assign("Not valid JSON: "); | |
251 error_message->append(ShortenTo64Characters(input)); | |
252 return false; | |
253 } | |
254 | |
255 // Locate the set from the dictionary. | |
256 base::DictionaryValue* dictionary = | |
257 static_cast<base::DictionaryValue*>(root.get()); | |
258 base::ListValue* list_val = NULL; | |
259 if (!dictionary->GetList(kKeyIdsTag, &list_val)) { | |
260 error_message->assign("Missing '"); | |
261 error_message->append(kKeyIdsTag); | |
262 error_message->append("' parameter or not a list"); | |
263 return false; | |
264 } | |
265 | |
266 // Create a local list of key ids, so that |key_ids| only gets updated on | |
267 // success. | |
268 KeyIdList local_key_ids; | |
269 for (size_t i = 0; i < list_val->GetSize(); ++i) { | |
270 std::string encoded_key_id; | |
271 if (!list_val->GetString(i, &encoded_key_id)) { | |
272 error_message->assign("'"); | |
273 error_message->append(kKeyIdsTag); | |
274 error_message->append("'["); | |
275 error_message->append(base::UintToString(i)); | |
276 error_message->append("] is not string."); | |
277 return false; | |
278 } | |
279 | |
280 // Key ID is a base64-encoded string, so decode it. | |
281 std::string raw_key_id = DecodeBase64Url(encoded_key_id); | |
282 if (raw_key_id.empty()) { | |
283 error_message->assign("'"); | |
284 error_message->append(kKeyIdsTag); | |
285 error_message->append("'["); | |
286 error_message->append(base::UintToString(i)); | |
287 error_message->append("] is not valid base64url encoded. Value: "); | |
288 error_message->append(ShortenTo64Characters(encoded_key_id)); | |
289 return false; | |
290 } | |
291 | |
292 // Add the decoded key ID to the list. | |
293 local_key_ids.push_back(std::vector<uint8>( | |
294 raw_key_id.data(), raw_key_id.data() + raw_key_id.length())); | |
295 } | |
296 | |
297 // All done. | |
298 key_ids->swap(local_key_ids); | |
299 error_message->clear(); | |
300 return true; | |
301 } | |
302 | |
229 void CreateLicenseRequest(const KeyIdList& key_ids, | 303 void CreateLicenseRequest(const KeyIdList& key_ids, |
230 MediaKeys::SessionType session_type, | 304 MediaKeys::SessionType session_type, |
231 std::vector<uint8>* license) { | 305 std::vector<uint8>* license) { |
232 // Create the license request. | 306 // Create the license request. |
233 scoped_ptr<base::DictionaryValue> request(new base::DictionaryValue()); | 307 scoped_ptr<base::DictionaryValue> request(new base::DictionaryValue()); |
234 scoped_ptr<base::ListValue> list(new base::ListValue()); | 308 scoped_ptr<base::ListValue> list(new base::ListValue()); |
235 for (const auto& key_id : key_ids) | 309 for (const auto& key_id : key_ids) |
236 list->AppendString(EncodeBase64Url(&key_id[0], key_id.size())); | 310 list->AppendString(EncodeBase64Url(&key_id[0], key_id.size())); |
237 request->Set(kKeyIdsTag, list.release()); | 311 request->Set(kKeyIdsTag, list.release()); |
238 | 312 |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
300 DVLOG(1) << "Invalid '" << kKeyIdsTag << "' value: " << encoded_key; | 374 DVLOG(1) << "Invalid '" << kKeyIdsTag << "' value: " << encoded_key; |
301 return false; | 375 return false; |
302 } | 376 } |
303 | 377 |
304 std::vector<uint8> result(decoded_string.begin(), decoded_string.end()); | 378 std::vector<uint8> result(decoded_string.begin(), decoded_string.end()); |
305 first_key->swap(result); | 379 first_key->swap(result); |
306 return true; | 380 return true; |
307 } | 381 } |
308 | 382 |
309 } // namespace media | 383 } // namespace media |
OLD | NEW |