| 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 |