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