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/aes_decryptor.h" | 5 #include "media/cdm/aes_decryptor.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <list> | 8 #include <list> |
9 #include <utility> | 9 #include <utility> |
10 #include <vector> | 10 #include <vector> |
11 | 11 |
12 #include "base/logging.h" | 12 #include "base/logging.h" |
13 #include "base/macros.h" | 13 #include "base/macros.h" |
14 #include "base/stl_util.h" | 14 #include "base/stl_util.h" |
15 #include "base/strings/string_number_conversions.h" | 15 #include "base/strings/string_number_conversions.h" |
16 #include "crypto/encryptor.h" | 16 #include "crypto/encryptor.h" |
17 #include "crypto/symmetric_key.h" | 17 #include "crypto/symmetric_key.h" |
18 #include "media/base/audio_decoder_config.h" | 18 #include "media/base/audio_decoder_config.h" |
19 #include "media/base/cdm_key_information.h" | 19 #include "media/base/cdm_key_information.h" |
20 #include "media/base/cdm_promise.h" | 20 #include "media/base/cdm_promise.h" |
21 #include "media/base/decoder_buffer.h" | 21 #include "media/base/decoder_buffer.h" |
22 #include "media/base/decrypt_config.h" | 22 #include "media/base/decrypt_config.h" |
| 23 #include "media/base/limits.h" |
23 #include "media/base/video_decoder_config.h" | 24 #include "media/base/video_decoder_config.h" |
24 #include "media/base/video_frame.h" | 25 #include "media/base/video_frame.h" |
25 #include "media/cdm/json_web_key.h" | 26 #include "media/cdm/json_web_key.h" |
26 | 27 |
27 #if defined(USE_PROPRIETARY_CODECS) | 28 #if defined(USE_PROPRIETARY_CODECS) |
28 #include "media/cdm/cenc_utils.h" | 29 #include "media/cdm/cenc_utils.h" |
29 #endif | 30 #endif |
30 | 31 |
31 namespace media { | 32 namespace media { |
32 | 33 |
(...skipping 228 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
261 EmeInitDataType init_data_type, | 262 EmeInitDataType init_data_type, |
262 const std::vector<uint8_t>& init_data, | 263 const std::vector<uint8_t>& init_data, |
263 std::unique_ptr<NewSessionCdmPromise> promise) { | 264 std::unique_ptr<NewSessionCdmPromise> promise) { |
264 std::string session_id(base::UintToString(next_session_id_++)); | 265 std::string session_id(base::UintToString(next_session_id_++)); |
265 valid_sessions_.insert(session_id); | 266 valid_sessions_.insert(session_id); |
266 | 267 |
267 // For now, the AesDecryptor does not care about |session_type|. | 268 // For now, the AesDecryptor does not care about |session_type|. |
268 // TODO(jrummell): Validate |session_type|. | 269 // TODO(jrummell): Validate |session_type|. |
269 | 270 |
270 std::vector<uint8_t> message; | 271 std::vector<uint8_t> message; |
271 // TODO(jrummell): Since unprefixed will never send NULL, remove this check | 272 std::vector<std::vector<uint8_t>> keys; |
272 // when prefixed EME is removed (http://crbug.com/249976). | 273 switch (init_data_type) { |
273 if (!init_data.empty()) { | 274 case EmeInitDataType::WEBM: |
274 std::vector<std::vector<uint8_t>> keys; | 275 // |init_data| is simply the key needed. |
275 switch (init_data_type) { | 276 if (init_data.size() < limits::kMinKeyIdLength || |
276 case EmeInitDataType::WEBM: | 277 init_data.size() > limits::kMaxKeyIdLength) { |
277 // |init_data| is simply the key needed. | 278 promise->reject(NOT_SUPPORTED_ERROR, 0, "Incorrect length"); |
278 keys.push_back(init_data); | 279 return; |
279 break; | 280 } |
280 case EmeInitDataType::CENC: | 281 keys.push_back(init_data); |
| 282 break; |
| 283 case EmeInitDataType::CENC: |
281 #if defined(USE_PROPRIETARY_CODECS) | 284 #if defined(USE_PROPRIETARY_CODECS) |
282 // |init_data| is a set of 0 or more concatenated 'pssh' boxes. | 285 // |init_data| is a set of 0 or more concatenated 'pssh' boxes. |
283 if (!GetKeyIdsForCommonSystemId(init_data, &keys)) { | 286 if (!GetKeyIdsForCommonSystemId(init_data, &keys)) { |
284 promise->reject(NOT_SUPPORTED_ERROR, 0, | 287 promise->reject(NOT_SUPPORTED_ERROR, 0, "No supported PSSH box found."); |
285 "No supported PSSH box found."); | 288 return; |
286 return; | 289 } |
287 } | 290 break; |
288 break; | |
289 #else | 291 #else |
290 promise->reject(NOT_SUPPORTED_ERROR, 0, | 292 promise->reject(NOT_SUPPORTED_ERROR, 0, |
291 "Initialization data type CENC is not supported."); | 293 "Initialization data type CENC is not supported."); |
| 294 return; |
| 295 #endif |
| 296 case EmeInitDataType::KEYIDS: { |
| 297 std::string init_data_string(init_data.begin(), init_data.end()); |
| 298 std::string error_message; |
| 299 if (!ExtractKeyIdsFromKeyIdsInitData(init_data_string, &keys, |
| 300 &error_message)) { |
| 301 promise->reject(NOT_SUPPORTED_ERROR, 0, error_message); |
292 return; | 302 return; |
293 #endif | |
294 case EmeInitDataType::KEYIDS: { | |
295 std::string init_data_string(init_data.begin(), init_data.end()); | |
296 std::string error_message; | |
297 if (!ExtractKeyIdsFromKeyIdsInitData(init_data_string, &keys, | |
298 &error_message)) { | |
299 promise->reject(NOT_SUPPORTED_ERROR, 0, error_message); | |
300 return; | |
301 } | |
302 break; | |
303 } | 303 } |
304 default: | 304 break; |
305 NOTREACHED(); | |
306 promise->reject(NOT_SUPPORTED_ERROR, 0, | |
307 "init_data_type not supported."); | |
308 return; | |
309 } | 305 } |
310 CreateLicenseRequest(keys, session_type, &message); | 306 default: |
| 307 NOTREACHED(); |
| 308 promise->reject(NOT_SUPPORTED_ERROR, 0, "init_data_type not supported."); |
| 309 return; |
311 } | 310 } |
| 311 CreateLicenseRequest(keys, session_type, &message); |
312 | 312 |
313 promise->resolve(session_id); | 313 promise->resolve(session_id); |
314 | 314 |
315 // No URL needed for license requests. | 315 // No URL needed for license requests. |
316 GURL empty_gurl; | 316 GURL empty_gurl; |
317 session_message_cb_.Run(session_id, LICENSE_REQUEST, message, empty_gurl); | 317 session_message_cb_.Run(session_id, LICENSE_REQUEST, message, empty_gurl); |
318 } | 318 } |
319 | 319 |
320 void AesDecryptor::LoadSession(SessionType session_type, | 320 void AesDecryptor::LoadSession(SessionType session_type, |
321 const std::string& session_id, | 321 const std::string& session_id, |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
416 session_keys_change_cb_.Run(session_id, false, CdmKeysInfo()); | 416 session_keys_change_cb_.Run(session_id, false, CdmKeysInfo()); |
417 | 417 |
418 // Update expiration time to NaN. (http://crbug.com/624192) | 418 // Update expiration time to NaN. (http://crbug.com/624192) |
419 | 419 |
420 // Resolve the closed attribute. | 420 // Resolve the closed attribute. |
421 session_closed_cb_.Run(session_id); | 421 session_closed_cb_.Run(session_id); |
422 } | 422 } |
423 | 423 |
424 void AesDecryptor::RemoveSession(const std::string& session_id, | 424 void AesDecryptor::RemoveSession(const std::string& session_id, |
425 std::unique_ptr<SimpleCdmPromise> promise) { | 425 std::unique_ptr<SimpleCdmPromise> promise) { |
426 // AesDecryptor doesn't keep any persistent data, so this should be | 426 NOTIMPLEMENTED() << "Need to address https://crbug.com/616166."; |
427 // NOT_REACHED(). | |
428 // TODO(jrummell): Make sure persistent session types are rejected. | |
429 // http://crbug.com/384152. | |
430 // | |
431 // However, v0.1b calls to CancelKeyRequest() will call this, so close the | |
432 // session, if it exists. | |
433 // TODO(jrummell): Remove the close() call when prefixed EME is removed. | |
434 // http://crbug.com/249976. | |
435 if (valid_sessions_.find(session_id) != valid_sessions_.end()) { | |
436 CloseSession(session_id, std::move(promise)); | |
437 return; | |
438 } | |
439 | |
440 promise->reject(INVALID_ACCESS_ERROR, 0, "Session does not exist."); | 427 promise->reject(INVALID_ACCESS_ERROR, 0, "Session does not exist."); |
441 } | 428 } |
442 | 429 |
443 CdmContext* AesDecryptor::GetCdmContext() { | 430 CdmContext* AesDecryptor::GetCdmContext() { |
444 return this; | 431 return this; |
445 } | 432 } |
446 | 433 |
447 Decryptor* AesDecryptor::GetDecryptor() { | 434 Decryptor* AesDecryptor::GetDecryptor() { |
448 return this; | 435 return this; |
449 } | 436 } |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
614 bool AesDecryptor::DecryptionKey::Init() { | 601 bool AesDecryptor::DecryptionKey::Init() { |
615 CHECK(!secret_.empty()); | 602 CHECK(!secret_.empty()); |
616 decryption_key_ = | 603 decryption_key_ = |
617 crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, secret_); | 604 crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, secret_); |
618 if (!decryption_key_) | 605 if (!decryption_key_) |
619 return false; | 606 return false; |
620 return true; | 607 return true; |
621 } | 608 } |
622 | 609 |
623 } // namespace media | 610 } // namespace media |
OLD | NEW |