Chromium Code Reviews| Index: media/crypto/aes_decryptor.cc |
| diff --git a/media/crypto/aes_decryptor.cc b/media/crypto/aes_decryptor.cc |
| index 129bc330131585c2a77a66dc7ab8b96fb96c76e6..8910d278945e5bd8d149c7003705e450428c5ff1 100644 |
| --- a/media/crypto/aes_decryptor.cc |
| +++ b/media/crypto/aes_decryptor.cc |
| @@ -16,11 +16,24 @@ |
| namespace media { |
| -// TODO(xhwang): Get real IV from frames. |
| -static const char kInitialCounter[] = "0000000000000000"; |
| - |
| uint32 AesDecryptor::next_session_id_ = 1; |
| +static void CopySubsamples(const std::vector<SubsampleEntry>& subsamples, |
| + const bool src_contains_clear_bytes, |
|
ddorwin
2012/07/17 01:14:21
Consider an enum since it's not clear that false m
strobe_
2012/07/19 02:43:35
Done.
|
| + const uint8* src, uint8* dst) { |
|
ddorwin
2012/07/17 01:14:21
same line only for call sites, not defn/decl.
strobe_
2012/07/19 02:43:35
Done.
|
| + for (size_t i = 0; i < subsamples.size(); i++) { |
| + const SubsampleEntry& subsample = subsamples[i]; |
| + if (src_contains_clear_bytes) { |
| + src += subsample.clear_bytes; |
| + } else { |
| + dst += subsample.clear_bytes; |
| + } |
| + memcpy(dst, src, subsample.cypher_bytes); |
|
ddorwin
2012/07/17 01:14:21
Should we verify we don't exceed either buffer siz
strobe_
2012/07/19 02:43:35
Since this is a static internal helper function, i
|
| + src += subsample.cypher_bytes; |
| + dst += subsample.cypher_bytes; |
| + } |
| +} |
| + |
| // Decrypt |input| using |key|. |
| // Return a DecoderBuffer with the decrypted data if decryption succeeded. |
| // Return NULL if decryption failed. |
| @@ -31,10 +44,61 @@ static scoped_refptr<DecoderBuffer> DecryptData(const DecoderBuffer& input, |
| // Initialize encryption data. |
| // The IV must be exactly as long as the cipher block size. |
| + const std::string& iv = input.GetDecryptConfig()->iv(); |
| crypto::Encryptor encryptor; |
| - if (!encryptor.Init(key, crypto::Encryptor::CBC, kInitialCounter)) { |
| - DVLOG(1) << "Could not initialize encryptor."; |
| - return NULL; |
| + if (input.GetDecryptConfig()->use_cbc()) { |
| + if (!encryptor.Init(key, crypto::Encryptor::CBC, iv)) { |
| + DVLOG(1) << "Could not initialize encryptor."; |
| + return NULL; |
| + } |
| + } else { |
| + if (!encryptor.Init(key, crypto::Encryptor::CTR, base::StringPiece()) || |
| + !encryptor.SetCounter(iv)) { |
| + DVLOG(1) << "Could not initialize encryptor."; |
| + return NULL; |
| + } |
| + } |
| + |
| + if (!input.GetDecryptConfig()->subsamples().empty()) { |
|
ddorwin
2012/07/17 01:14:21
Prefer positive logic (unless there's a good reaso
strobe_
2012/07/19 02:43:35
Done.
|
| + const std::vector<SubsampleEntry>& subsamples = |
| + input.GetDecryptConfig()->subsamples(); |
| + |
| + int total_clear_size = 0; |
| + int total_encrypted_size = 0; |
| + for (size_t i = 0; i < subsamples.size(); i++) { |
| + total_clear_size += subsamples[i].clear_bytes; |
| + total_encrypted_size += subsamples[i].cypher_bytes; |
| + } |
| + if (total_clear_size + total_encrypted_size != input.GetDataSize()) { |
| + DVLOG(1) << "Subsample sizes do not equal input size"; |
| + return NULL; |
| + } |
| + |
| + // The encrypted portions of all subsamples must form a contiguous block, |
| + // such that an encrypted subsample that ends away from a block boundary is |
| + // immediately followed by the start of the next encrypted subsample. We |
| + // copy all encrypted subsamples to a contiguous buffer, decrypt them, then |
| + // copy the decrypted bytes over the encrypted bytes in the output. |
| + // TODO(strobe): attempt to reduce number of memory copies |
| + scoped_array<uint8> encrypted_bytes( |
| + new uint8[total_encrypted_size]); |
| + CopySubsamples(subsamples, true, input.GetData(), encrypted_bytes.get()); |
| + |
| + std::string decrypted_text; |
| + base::StringPiece encrypted_text( |
| + reinterpret_cast<const char*>(encrypted_bytes.get()), |
| + total_encrypted_size); |
| + if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { |
| + DVLOG(1) << "Could not decrypt data."; |
| + return NULL; |
| + } |
| + |
| + scoped_refptr<DecoderBuffer> output = DecoderBuffer::CopyFrom( |
| + input.GetData(), input.GetDataSize()); |
| + CopySubsamples(subsamples, false, |
| + reinterpret_cast<const uint8*>(decrypted_text.data()), |
| + output->GetWritableData()); |
| + return output; |
| } |
| std::string decrypted_text; |