OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/crypto/aes_decryptor.h" | 5 #include "media/crypto/aes_decryptor.h" |
6 | 6 |
| 7 #include <vector> |
| 8 |
7 #include "base/logging.h" | 9 #include "base/logging.h" |
8 #include "base/stl_util.h" | 10 #include "base/stl_util.h" |
9 #include "base/string_number_conversions.h" | 11 #include "base/string_number_conversions.h" |
10 #include "crypto/encryptor.h" | 12 #include "crypto/encryptor.h" |
11 #include "crypto/hmac.h" | 13 #include "crypto/hmac.h" |
12 #include "crypto/symmetric_key.h" | 14 #include "crypto/symmetric_key.h" |
13 #include "media/base/decoder_buffer.h" | 15 #include "media/base/decoder_buffer.h" |
14 #include "media/base/decrypt_config.h" | 16 #include "media/base/decrypt_config.h" |
15 #include "media/base/decryptor_client.h" | 17 #include "media/base/decryptor_client.h" |
16 | 18 |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
77 | 79 |
78 base::StringPiece data_to_check( | 80 base::StringPiece data_to_check( |
79 reinterpret_cast<const char*>(input.GetData()), input.GetDataSize()); | 81 reinterpret_cast<const char*>(input.GetData()), input.GetDataSize()); |
80 | 82 |
81 return hmac.VerifyTruncated(data_to_check, | 83 return hmac.VerifyTruncated(data_to_check, |
82 input.GetDecryptConfig()->checksum()); | 84 input.GetDecryptConfig()->checksum()); |
83 } | 85 } |
84 | 86 |
85 enum ClearBytesBufferSel { | 87 enum ClearBytesBufferSel { |
86 kSrcContainsClearBytes, | 88 kSrcContainsClearBytes, |
87 kDstContainsClearBytes, | 89 kDstContainsClearBytes |
88 }; | 90 }; |
89 | 91 |
90 static void CopySubsamples(const std::vector<SubsampleEntry>& subsamples, | 92 static void CopySubsamples(const std::vector<SubsampleEntry>& subsamples, |
91 const ClearBytesBufferSel sel, | 93 const ClearBytesBufferSel sel, |
92 const uint8* src, | 94 const uint8* src, |
93 uint8* dst) { | 95 uint8* dst) { |
94 for (size_t i = 0; i < subsamples.size(); i++) { | 96 for (size_t i = 0; i < subsamples.size(); i++) { |
95 const SubsampleEntry& subsample = subsamples[i]; | 97 const SubsampleEntry& subsample = subsamples[i]; |
96 if (sel == kSrcContainsClearBytes) { | 98 if (sel == kSrcContainsClearBytes) { |
97 src += subsample.clear_bytes; | 99 src += subsample.clear_bytes; |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
243 client_->KeyError(key_system, session_id, Decryptor::kUnknownError, 0); | 245 client_->KeyError(key_system, session_id, Decryptor::kUnknownError, 0); |
244 return; | 246 return; |
245 } | 247 } |
246 | 248 |
247 if (!decryption_key->Init()) { | 249 if (!decryption_key->Init()) { |
248 DVLOG(1) << "Could not initialize decryption key."; | 250 DVLOG(1) << "Could not initialize decryption key."; |
249 client_->KeyError(key_system, session_id, Decryptor::kUnknownError, 0); | 251 client_->KeyError(key_system, session_id, Decryptor::kUnknownError, 0); |
250 return; | 252 return; |
251 } | 253 } |
252 | 254 |
253 { | 255 SetKey(key_id_string, decryption_key.Pass()); |
254 base::AutoLock auto_lock(key_map_lock_); | |
255 KeyMap::iterator found = key_map_.find(key_id_string); | |
256 if (found != key_map_.end()) { | |
257 delete found->second; | |
258 key_map_.erase(found); | |
259 } | |
260 key_map_[key_id_string] = decryption_key.release(); | |
261 } | |
262 | |
263 client_->KeyAdded(key_system, session_id); | 256 client_->KeyAdded(key_system, session_id); |
264 } | 257 } |
265 | 258 |
266 void AesDecryptor::CancelKeyRequest(const std::string& key_system, | 259 void AesDecryptor::CancelKeyRequest(const std::string& key_system, |
267 const std::string& session_id) { | 260 const std::string& session_id) { |
268 } | 261 } |
269 | 262 |
270 void AesDecryptor::Decrypt(const scoped_refptr<DecoderBuffer>& encrypted, | 263 void AesDecryptor::Decrypt(const scoped_refptr<DecoderBuffer>& encrypted, |
271 const DecryptCB& decrypt_cb) { | 264 const DecryptCB& decrypt_cb) { |
272 CHECK(encrypted->GetDecryptConfig()); | 265 CHECK(encrypted->GetDecryptConfig()); |
273 const std::string& key_id = encrypted->GetDecryptConfig()->key_id(); | 266 const std::string& key_id = encrypted->GetDecryptConfig()->key_id(); |
274 | 267 |
275 DecryptionKey* key = NULL; | 268 DecryptionKey* key = GetKey(key_id); |
276 { | |
277 base::AutoLock auto_lock(key_map_lock_); | |
278 KeyMap::const_iterator found = key_map_.find(key_id); | |
279 if (found != key_map_.end()) | |
280 key = found->second; | |
281 } | |
282 | |
283 if (!key) { | 269 if (!key) { |
284 // TODO(fgalligan): Fire a need_key event here and add a test. | 270 // TODO(xhwang): Fire a need_key event here and add a test. |
285 DVLOG(1) << "Could not find a matching key for given key ID."; | 271 DVLOG(1) << "Could not find a matching key for the given key ID."; |
286 decrypt_cb.Run(kError, NULL); | 272 decrypt_cb.Run(kError, NULL); |
287 return; | 273 return; |
288 } | 274 } |
289 | 275 |
290 int checksum_size = encrypted->GetDecryptConfig()->checksum().size(); | 276 int checksum_size = encrypted->GetDecryptConfig()->checksum().size(); |
291 // According to the WebM encrypted specification, it is an open question | 277 // According to the WebM encrypted specification, it is an open question |
292 // what should happen when a frame fails the integrity check. | 278 // what should happen when a frame fails the integrity check. |
293 // http://wiki.webmproject.org/encryption/webm-encryption-rfc | 279 // http://wiki.webmproject.org/encryption/webm-encryption-rfc |
294 if (checksum_size > 0 && | 280 if (checksum_size > 0 && |
295 !key->hmac_key().empty() && | 281 !key->hmac_key().empty() && |
(...skipping 14 matching lines...) Expand all Loading... |
310 DVLOG(1) << "Decryption failed."; | 296 DVLOG(1) << "Decryption failed."; |
311 decrypt_cb.Run(kError, NULL); | 297 decrypt_cb.Run(kError, NULL); |
312 return; | 298 return; |
313 } | 299 } |
314 | 300 |
315 decrypted->SetTimestamp(encrypted->GetTimestamp()); | 301 decrypted->SetTimestamp(encrypted->GetTimestamp()); |
316 decrypted->SetDuration(encrypted->GetDuration()); | 302 decrypted->SetDuration(encrypted->GetDuration()); |
317 decrypt_cb.Run(kSuccess, decrypted); | 303 decrypt_cb.Run(kSuccess, decrypted); |
318 } | 304 } |
319 | 305 |
320 AesDecryptor::DecryptionKey::DecryptionKey( | 306 void AesDecryptor::SetKey(const std::string& key_id, |
321 const std::string& secret) | 307 scoped_ptr<DecryptionKey> decryption_key) { |
| 308 base::AutoLock auto_lock(key_map_lock_); |
| 309 KeyMap::iterator found = key_map_.find(key_id); |
| 310 if (found != key_map_.end()) { |
| 311 delete found->second; |
| 312 key_map_.erase(found); |
| 313 } |
| 314 key_map_[key_id] = decryption_key.release(); |
| 315 } |
| 316 |
| 317 AesDecryptor::DecryptionKey* AesDecryptor::GetKey( |
| 318 const std::string& key_id) const { |
| 319 base::AutoLock auto_lock(key_map_lock_); |
| 320 KeyMap::const_iterator found = key_map_.find(key_id); |
| 321 if (found == key_map_.end()) |
| 322 return NULL; |
| 323 |
| 324 return found->second; |
| 325 } |
| 326 |
| 327 AesDecryptor::DecryptionKey::DecryptionKey(const std::string& secret) |
322 : secret_(secret) { | 328 : secret_(secret) { |
323 } | 329 } |
324 | 330 |
325 AesDecryptor::DecryptionKey::~DecryptionKey() {} | 331 AesDecryptor::DecryptionKey::~DecryptionKey() {} |
326 | 332 |
327 bool AesDecryptor::DecryptionKey::Init() { | 333 bool AesDecryptor::DecryptionKey::Init() { |
328 CHECK(!secret_.empty()); | 334 CHECK(!secret_.empty()); |
329 decryption_key_.reset( | 335 decryption_key_.reset(crypto::SymmetricKey::Import( |
330 crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, secret_)); | 336 crypto::SymmetricKey::AES, secret_)); |
331 if (!decryption_key_.get()) { | 337 if (!decryption_key_.get()) |
332 return false; | 338 return false; |
333 } | |
334 | 339 |
335 std::string raw_key = DeriveKey(secret_, | 340 std::string raw_key = DeriveKey(secret_, |
336 kWebmEncryptionSeed, | 341 kWebmEncryptionSeed, |
337 secret_.length()); | 342 secret_.length()); |
338 if (raw_key.empty()) { | 343 if (raw_key.empty()) |
339 return false; | 344 return false; |
340 } | 345 |
341 webm_decryption_key_.reset( | 346 webm_decryption_key_.reset(crypto::SymmetricKey::Import( |
342 crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, raw_key)); | 347 crypto::SymmetricKey::AES, raw_key)); |
343 if (!webm_decryption_key_.get()) { | 348 if (!webm_decryption_key_.get()) |
344 return false; | 349 return false; |
345 } | |
346 | 350 |
347 hmac_key_ = DeriveKey(secret_, kWebmHmacSeed, kWebmSha1DigestSize); | 351 hmac_key_ = DeriveKey(secret_, kWebmHmacSeed, kWebmSha1DigestSize); |
348 if (hmac_key_.empty()) { | 352 if (hmac_key_.empty()) |
349 return false; | 353 return false; |
350 } | |
351 | 354 |
352 return true; | 355 return true; |
353 } | 356 } |
354 | 357 |
355 } // namespace media | 358 } // namespace media |
OLD | NEW |