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> |
(...skipping 29 matching lines...) Expand all Loading... |
40 typedef std::list<std::pair<std::string, DecryptionKey*> > KeyList; | 40 typedef std::list<std::pair<std::string, DecryptionKey*> > KeyList; |
41 | 41 |
42 public: | 42 public: |
43 SessionIdDecryptionKeyMap() {} | 43 SessionIdDecryptionKeyMap() {} |
44 ~SessionIdDecryptionKeyMap() { STLDeleteValues(&key_list_); } | 44 ~SessionIdDecryptionKeyMap() { STLDeleteValues(&key_list_); } |
45 | 45 |
46 // Replaces value if |session_id| is already present, or adds it if not. | 46 // Replaces value if |session_id| is already present, or adds it if not. |
47 // This |decryption_key| becomes the latest until another insertion or | 47 // This |decryption_key| becomes the latest until another insertion or |
48 // |session_id| is erased. | 48 // |session_id| is erased. |
49 void Insert(const std::string& session_id, | 49 void Insert(const std::string& session_id, |
50 scoped_ptr<DecryptionKey> decryption_key); | 50 std::unique_ptr<DecryptionKey> decryption_key); |
51 | 51 |
52 // Deletes the entry for |session_id| if present. | 52 // Deletes the entry for |session_id| if present. |
53 void Erase(const std::string& session_id); | 53 void Erase(const std::string& session_id); |
54 | 54 |
55 // Returns whether the list is empty | 55 // Returns whether the list is empty |
56 bool Empty() const { return key_list_.empty(); } | 56 bool Empty() const { return key_list_.empty(); } |
57 | 57 |
58 // Returns the last inserted DecryptionKey. | 58 // Returns the last inserted DecryptionKey. |
59 DecryptionKey* LatestDecryptionKey() { | 59 DecryptionKey* LatestDecryptionKey() { |
60 DCHECK(!key_list_.empty()); | 60 DCHECK(!key_list_.empty()); |
(...skipping 11 matching lines...) Expand all Loading... |
72 // Deletes the entry pointed to by |position|. | 72 // Deletes the entry pointed to by |position|. |
73 void Erase(KeyList::iterator position); | 73 void Erase(KeyList::iterator position); |
74 | 74 |
75 KeyList key_list_; | 75 KeyList key_list_; |
76 | 76 |
77 DISALLOW_COPY_AND_ASSIGN(SessionIdDecryptionKeyMap); | 77 DISALLOW_COPY_AND_ASSIGN(SessionIdDecryptionKeyMap); |
78 }; | 78 }; |
79 | 79 |
80 void AesDecryptor::SessionIdDecryptionKeyMap::Insert( | 80 void AesDecryptor::SessionIdDecryptionKeyMap::Insert( |
81 const std::string& session_id, | 81 const std::string& session_id, |
82 scoped_ptr<DecryptionKey> decryption_key) { | 82 std::unique_ptr<DecryptionKey> decryption_key) { |
83 KeyList::iterator it = Find(session_id); | 83 KeyList::iterator it = Find(session_id); |
84 if (it != key_list_.end()) | 84 if (it != key_list_.end()) |
85 Erase(it); | 85 Erase(it); |
86 DecryptionKey* raw_ptr = decryption_key.release(); | 86 DecryptionKey* raw_ptr = decryption_key.release(); |
87 key_list_.push_front(std::make_pair(session_id, raw_ptr)); | 87 key_list_.push_front(std::make_pair(session_id, raw_ptr)); |
88 } | 88 } |
89 | 89 |
90 void AesDecryptor::SessionIdDecryptionKeyMap::Erase( | 90 void AesDecryptor::SessionIdDecryptionKeyMap::Erase( |
91 const std::string& session_id) { | 91 const std::string& session_id) { |
92 KeyList::iterator it = Find(session_id); | 92 KeyList::iterator it = Find(session_id); |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
201 return DecoderBuffer::CopyFrom(reinterpret_cast<const uint8_t*>(sample), | 201 return DecoderBuffer::CopyFrom(reinterpret_cast<const uint8_t*>(sample), |
202 sample_size); | 202 sample_size); |
203 } | 203 } |
204 | 204 |
205 // The encrypted portions of all subsamples must form a contiguous block, | 205 // The encrypted portions of all subsamples must form a contiguous block, |
206 // such that an encrypted subsample that ends away from a block boundary is | 206 // such that an encrypted subsample that ends away from a block boundary is |
207 // immediately followed by the start of the next encrypted subsample. We | 207 // immediately followed by the start of the next encrypted subsample. We |
208 // copy all encrypted subsamples to a contiguous buffer, decrypt them, then | 208 // copy all encrypted subsamples to a contiguous buffer, decrypt them, then |
209 // copy the decrypted bytes over the encrypted bytes in the output. | 209 // copy the decrypted bytes over the encrypted bytes in the output. |
210 // TODO(strobe): attempt to reduce number of memory copies | 210 // TODO(strobe): attempt to reduce number of memory copies |
211 scoped_ptr<uint8_t[]> encrypted_bytes(new uint8_t[total_encrypted_size]); | 211 std::unique_ptr<uint8_t[]> encrypted_bytes(new uint8_t[total_encrypted_size]); |
212 CopySubsamples(subsamples, kSrcContainsClearBytes, | 212 CopySubsamples(subsamples, kSrcContainsClearBytes, |
213 reinterpret_cast<const uint8_t*>(sample), | 213 reinterpret_cast<const uint8_t*>(sample), |
214 encrypted_bytes.get()); | 214 encrypted_bytes.get()); |
215 | 215 |
216 base::StringPiece encrypted_text( | 216 base::StringPiece encrypted_text( |
217 reinterpret_cast<const char*>(encrypted_bytes.get()), | 217 reinterpret_cast<const char*>(encrypted_bytes.get()), |
218 total_encrypted_size); | 218 total_encrypted_size); |
219 std::string decrypted_text; | 219 std::string decrypted_text; |
220 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { | 220 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { |
221 DVLOG(1) << "Could not decrypt data."; | 221 DVLOG(1) << "Could not decrypt data."; |
(...skipping 20 matching lines...) Expand all Loading... |
242 // with |security_origin|. | 242 // with |security_origin|. |
243 DCHECK(!session_message_cb_.is_null()); | 243 DCHECK(!session_message_cb_.is_null()); |
244 DCHECK(!session_closed_cb_.is_null()); | 244 DCHECK(!session_closed_cb_.is_null()); |
245 DCHECK(!session_keys_change_cb_.is_null()); | 245 DCHECK(!session_keys_change_cb_.is_null()); |
246 } | 246 } |
247 | 247 |
248 AesDecryptor::~AesDecryptor() { | 248 AesDecryptor::~AesDecryptor() { |
249 key_map_.clear(); | 249 key_map_.clear(); |
250 } | 250 } |
251 | 251 |
252 void AesDecryptor::SetServerCertificate(const std::vector<uint8_t>& certificate, | 252 void AesDecryptor::SetServerCertificate( |
253 scoped_ptr<SimpleCdmPromise> promise) { | 253 const std::vector<uint8_t>& certificate, |
| 254 std::unique_ptr<SimpleCdmPromise> promise) { |
254 promise->reject( | 255 promise->reject( |
255 NOT_SUPPORTED_ERROR, 0, "SetServerCertificate() is not supported."); | 256 NOT_SUPPORTED_ERROR, 0, "SetServerCertificate() is not supported."); |
256 } | 257 } |
257 | 258 |
258 void AesDecryptor::CreateSessionAndGenerateRequest( | 259 void AesDecryptor::CreateSessionAndGenerateRequest( |
259 SessionType session_type, | 260 SessionType session_type, |
260 EmeInitDataType init_data_type, | 261 EmeInitDataType init_data_type, |
261 const std::vector<uint8_t>& init_data, | 262 const std::vector<uint8_t>& init_data, |
262 scoped_ptr<NewSessionCdmPromise> promise) { | 263 std::unique_ptr<NewSessionCdmPromise> promise) { |
263 std::string session_id(base::UintToString(next_session_id_++)); | 264 std::string session_id(base::UintToString(next_session_id_++)); |
264 valid_sessions_.insert(session_id); | 265 valid_sessions_.insert(session_id); |
265 | 266 |
266 // For now, the AesDecryptor does not care about |session_type|. | 267 // For now, the AesDecryptor does not care about |session_type|. |
267 // TODO(jrummell): Validate |session_type|. | 268 // TODO(jrummell): Validate |session_type|. |
268 | 269 |
269 std::vector<uint8_t> message; | 270 std::vector<uint8_t> message; |
270 // TODO(jrummell): Since unprefixed will never send NULL, remove this check | 271 // TODO(jrummell): Since unprefixed will never send NULL, remove this check |
271 // when prefixed EME is removed (http://crbug.com/249976). | 272 // when prefixed EME is removed (http://crbug.com/249976). |
272 if (!init_data.empty()) { | 273 if (!init_data.empty()) { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
311 | 312 |
312 promise->resolve(session_id); | 313 promise->resolve(session_id); |
313 | 314 |
314 // No URL needed for license requests. | 315 // No URL needed for license requests. |
315 GURL empty_gurl; | 316 GURL empty_gurl; |
316 session_message_cb_.Run(session_id, LICENSE_REQUEST, message, empty_gurl); | 317 session_message_cb_.Run(session_id, LICENSE_REQUEST, message, empty_gurl); |
317 } | 318 } |
318 | 319 |
319 void AesDecryptor::LoadSession(SessionType session_type, | 320 void AesDecryptor::LoadSession(SessionType session_type, |
320 const std::string& session_id, | 321 const std::string& session_id, |
321 scoped_ptr<NewSessionCdmPromise> promise) { | 322 std::unique_ptr<NewSessionCdmPromise> promise) { |
322 // TODO(xhwang): Change this to NOTREACHED() when blink checks for key systems | 323 // TODO(xhwang): Change this to NOTREACHED() when blink checks for key systems |
323 // that do not support loadSession. See http://crbug.com/342481 | 324 // that do not support loadSession. See http://crbug.com/342481 |
324 promise->reject(NOT_SUPPORTED_ERROR, 0, "LoadSession() is not supported."); | 325 promise->reject(NOT_SUPPORTED_ERROR, 0, "LoadSession() is not supported."); |
325 } | 326 } |
326 | 327 |
327 void AesDecryptor::UpdateSession(const std::string& session_id, | 328 void AesDecryptor::UpdateSession(const std::string& session_id, |
328 const std::vector<uint8_t>& response, | 329 const std::vector<uint8_t>& response, |
329 scoped_ptr<SimpleCdmPromise> promise) { | 330 std::unique_ptr<SimpleCdmPromise> promise) { |
330 CHECK(!response.empty()); | 331 CHECK(!response.empty()); |
331 | 332 |
332 // TODO(jrummell): Convert back to a DCHECK once prefixed EME is removed. | 333 // TODO(jrummell): Convert back to a DCHECK once prefixed EME is removed. |
333 if (valid_sessions_.find(session_id) == valid_sessions_.end()) { | 334 if (valid_sessions_.find(session_id) == valid_sessions_.end()) { |
334 promise->reject(INVALID_ACCESS_ERROR, 0, "Session does not exist."); | 335 promise->reject(INVALID_ACCESS_ERROR, 0, "Session does not exist."); |
335 return; | 336 return; |
336 } | 337 } |
337 | 338 |
338 std::string key_string(response.begin(), response.end()); | 339 std::string key_string(response.begin(), response.end()); |
339 | 340 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
393 keys_info.push_back( | 394 keys_info.push_back( |
394 new CdmKeyInformation(item.first, CdmKeyInformation::USABLE, 0)); | 395 new CdmKeyInformation(item.first, CdmKeyInformation::USABLE, 0)); |
395 } | 396 } |
396 } | 397 } |
397 } | 398 } |
398 | 399 |
399 session_keys_change_cb_.Run(session_id, key_added, std::move(keys_info)); | 400 session_keys_change_cb_.Run(session_id, key_added, std::move(keys_info)); |
400 } | 401 } |
401 | 402 |
402 void AesDecryptor::CloseSession(const std::string& session_id, | 403 void AesDecryptor::CloseSession(const std::string& session_id, |
403 scoped_ptr<SimpleCdmPromise> promise) { | 404 std::unique_ptr<SimpleCdmPromise> promise) { |
404 // Validate that this is a reference to an active session and then forget it. | 405 // Validate that this is a reference to an active session and then forget it. |
405 std::set<std::string>::iterator it = valid_sessions_.find(session_id); | 406 std::set<std::string>::iterator it = valid_sessions_.find(session_id); |
406 DCHECK(it != valid_sessions_.end()); | 407 DCHECK(it != valid_sessions_.end()); |
407 | 408 |
408 valid_sessions_.erase(it); | 409 valid_sessions_.erase(it); |
409 | 410 |
410 // Close the session. | 411 // Close the session. |
411 DeleteKeysForSession(session_id); | 412 DeleteKeysForSession(session_id); |
412 promise->resolve(); | 413 promise->resolve(); |
413 session_closed_cb_.Run(session_id); | 414 session_closed_cb_.Run(session_id); |
414 } | 415 } |
415 | 416 |
416 void AesDecryptor::RemoveSession(const std::string& session_id, | 417 void AesDecryptor::RemoveSession(const std::string& session_id, |
417 scoped_ptr<SimpleCdmPromise> promise) { | 418 std::unique_ptr<SimpleCdmPromise> promise) { |
418 // AesDecryptor doesn't keep any persistent data, so this should be | 419 // AesDecryptor doesn't keep any persistent data, so this should be |
419 // NOT_REACHED(). | 420 // NOT_REACHED(). |
420 // TODO(jrummell): Make sure persistent session types are rejected. | 421 // TODO(jrummell): Make sure persistent session types are rejected. |
421 // http://crbug.com/384152. | 422 // http://crbug.com/384152. |
422 // | 423 // |
423 // However, v0.1b calls to CancelKeyRequest() will call this, so close the | 424 // However, v0.1b calls to CancelKeyRequest() will call this, so close the |
424 // session, if it exists. | 425 // session, if it exists. |
425 // TODO(jrummell): Remove the close() call when prefixed EME is removed. | 426 // TODO(jrummell): Remove the close() call when prefixed EME is removed. |
426 // http://crbug.com/249976. | 427 // http://crbug.com/249976. |
427 if (valid_sessions_.find(session_id) != valid_sessions_.end()) { | 428 if (valid_sessions_.find(session_id) != valid_sessions_.end()) { |
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
528 | 529 |
529 void AesDecryptor::DeinitializeDecoder(StreamType stream_type) { | 530 void AesDecryptor::DeinitializeDecoder(StreamType stream_type) { |
530 // AesDecryptor does not support audio/video decoding, but since this can be | 531 // AesDecryptor does not support audio/video decoding, but since this can be |
531 // called any time after InitializeAudioDecoder/InitializeVideoDecoder, | 532 // called any time after InitializeAudioDecoder/InitializeVideoDecoder, |
532 // nothing to be done here. | 533 // nothing to be done here. |
533 } | 534 } |
534 | 535 |
535 bool AesDecryptor::AddDecryptionKey(const std::string& session_id, | 536 bool AesDecryptor::AddDecryptionKey(const std::string& session_id, |
536 const std::string& key_id, | 537 const std::string& key_id, |
537 const std::string& key_string) { | 538 const std::string& key_string) { |
538 scoped_ptr<DecryptionKey> decryption_key(new DecryptionKey(key_string)); | 539 std::unique_ptr<DecryptionKey> decryption_key(new DecryptionKey(key_string)); |
539 if (!decryption_key->Init()) { | 540 if (!decryption_key->Init()) { |
540 DVLOG(1) << "Could not initialize decryption key."; | 541 DVLOG(1) << "Could not initialize decryption key."; |
541 return false; | 542 return false; |
542 } | 543 } |
543 | 544 |
544 base::AutoLock auto_lock(key_map_lock_); | 545 base::AutoLock auto_lock(key_map_lock_); |
545 KeyIdToSessionKeysMap::iterator key_id_entry = key_map_.find(key_id); | 546 KeyIdToSessionKeysMap::iterator key_id_entry = key_map_.find(key_id); |
546 if (key_id_entry != key_map_.end()) { | 547 if (key_id_entry != key_map_.end()) { |
547 key_id_entry->second->Insert(session_id, std::move(decryption_key)); | 548 key_id_entry->second->Insert(session_id, std::move(decryption_key)); |
548 return true; | 549 return true; |
549 } | 550 } |
550 | 551 |
551 // |key_id| not found, so need to create new entry. | 552 // |key_id| not found, so need to create new entry. |
552 scoped_ptr<SessionIdDecryptionKeyMap> inner_map( | 553 std::unique_ptr<SessionIdDecryptionKeyMap> inner_map( |
553 new SessionIdDecryptionKeyMap()); | 554 new SessionIdDecryptionKeyMap()); |
554 inner_map->Insert(session_id, std::move(decryption_key)); | 555 inner_map->Insert(session_id, std::move(decryption_key)); |
555 key_map_.add(key_id, std::move(inner_map)); | 556 key_map_.add(key_id, std::move(inner_map)); |
556 return true; | 557 return true; |
557 } | 558 } |
558 | 559 |
559 AesDecryptor::DecryptionKey* AesDecryptor::GetKey_Locked( | 560 AesDecryptor::DecryptionKey* AesDecryptor::GetKey_Locked( |
560 const std::string& key_id) const { | 561 const std::string& key_id) const { |
561 key_map_lock_.AssertAcquired(); | 562 key_map_lock_.AssertAcquired(); |
562 KeyIdToSessionKeysMap::const_iterator key_id_found = key_map_.find(key_id); | 563 KeyIdToSessionKeysMap::const_iterator key_id_found = key_map_.find(key_id); |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
607 bool AesDecryptor::DecryptionKey::Init() { | 608 bool AesDecryptor::DecryptionKey::Init() { |
608 CHECK(!secret_.empty()); | 609 CHECK(!secret_.empty()); |
609 decryption_key_.reset(crypto::SymmetricKey::Import( | 610 decryption_key_.reset(crypto::SymmetricKey::Import( |
610 crypto::SymmetricKey::AES, secret_)); | 611 crypto::SymmetricKey::AES, secret_)); |
611 if (!decryption_key_) | 612 if (!decryption_key_) |
612 return false; | 613 return false; |
613 return true; | 614 return true; |
614 } | 615 } |
615 | 616 |
616 } // namespace media | 617 } // namespace media |
OLD | NEW |