Chromium Code Reviews| 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 "base/logging.h" | 7 #include "base/logging.h" |
| 8 #include "base/stl_util.h" | 8 #include "base/stl_util.h" |
| 9 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
| 10 #include "base/string_piece.h" | 10 #include "base/string_piece.h" |
| 11 #include "crypto/encryptor.h" | 11 #include "crypto/encryptor.h" |
| 12 #include "crypto/symmetric_key.h" | 12 #include "crypto/symmetric_key.h" |
| 13 #include "media/base/decoder_buffer.h" | 13 #include "media/base/decoder_buffer.h" |
| 14 #include "media/base/decrypt_config.h" | 14 #include "media/base/decrypt_config.h" |
| 15 #include "media/base/decryptor_client.h" | 15 #include "media/base/decryptor_client.h" |
| 16 | 16 |
| 17 namespace media { | 17 namespace media { |
| 18 | 18 |
| 19 // TODO(xhwang): Get real IV from frames. | |
| 20 static const char kInitialCounter[] = "0000000000000000"; | |
| 21 | |
| 22 uint32 AesDecryptor::next_session_id_ = 1; | 19 uint32 AesDecryptor::next_session_id_ = 1; |
| 23 | 20 |
| 24 // Decrypt |input| using |key|. | 21 // Decrypt |input| using |key|. |
| 25 // Return a DecoderBuffer with the decrypted data if decryption succeeded. | 22 // Return a DecoderBuffer with the decrypted data if decryption succeeded. |
| 26 // Return NULL if decryption failed. | 23 // Return NULL if decryption failed. |
| 27 static scoped_refptr<DecoderBuffer> DecryptData(const DecoderBuffer& input, | 24 static scoped_refptr<DecoderBuffer> DecryptData(const DecoderBuffer& input, |
| 28 crypto::SymmetricKey* key) { | 25 crypto::SymmetricKey* key) { |
| 29 CHECK(input.GetDataSize()); | 26 CHECK(input.GetDataSize()); |
| 30 CHECK(key); | 27 CHECK(key); |
| 31 | 28 |
| 29 base::StringPiece iv( | |
| 30 reinterpret_cast<const char*>(input.GetDecryptConfig()->iv()), | |
| 31 input.GetDecryptConfig()->iv_size()); | |
|
xhwang
2012/06/27 19:37:43
Life will be easier here if we use std::string for
strobe_
2012/07/13 00:47:07
Done.
| |
| 32 | |
| 32 // Initialize encryption data. | 33 // Initialize encryption data. |
| 33 // The IV must be exactly as long as the cipher block size. | 34 // The IV must be exactly as long as the cipher block size. |
| 34 crypto::Encryptor encryptor; | 35 crypto::Encryptor encryptor; |
| 35 if (!encryptor.Init(key, crypto::Encryptor::CBC, kInitialCounter)) { | 36 if (input.GetDecryptConfig()->use_cbc()) { |
| 36 DVLOG(1) << "Could not initialize encryptor."; | 37 if (!encryptor.Init(key, crypto::Encryptor::CBC, iv)) { |
| 37 return NULL; | 38 DVLOG(1) << "Could not initialize encryptor."; |
| 39 return NULL; | |
| 40 } | |
| 41 } else { | |
| 42 if (!encryptor.Init(key, crypto::Encryptor::CTR, base::StringPiece()) || | |
| 43 !encryptor.SetCounter(iv)) { | |
| 44 DVLOG(1) << "Could not initialize encryptor."; | |
| 45 return NULL; | |
| 46 } | |
| 38 } | 47 } |
| 39 | 48 |
| 40 std::string decrypted_text; | 49 if (!input.GetDecryptConfig()->subsamples().empty()) { |
| 41 base::StringPiece encrypted_text( | 50 // XXX(strobe): factor out and test before final commit |
|
ddorwin
2012/07/03 21:03:47
XXX? TODO?
strobe_
2012/07/13 00:47:07
Done.
| |
| 42 reinterpret_cast<const char*>(input.GetData()), | 51 const std::vector<SubsampleEntry> subsamples = |
|
ddorwin
2012/07/03 21:03:47
const ref instead of copying
strobe_
2012/07/13 00:47:07
Done.
| |
| 43 input.GetDataSize()); | 52 input.GetDecryptConfig()->subsamples(); |
| 44 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { | 53 |
| 45 DVLOG(1) << "Could not decrypt data."; | 54 int total_encrypted_subsample_size = 0; |
| 46 return NULL; | 55 for (size_t i = 0; i < subsamples.size(); i++) |
| 56 total_encrypted_subsample_size += subsamples[i].cypher_bytes; | |
| 57 | |
| 58 if (total_encrypted_subsample_size > input.GetDataSize()) { | |
|
ddorwin
2012/07/03 21:03:47
Should we also check that enc plus unenc are == da
strobe_
2012/07/13 00:47:07
Done.
| |
| 59 DVLOG(1) << "Subsample encrypted size larger than input size"; | |
| 60 return NULL; | |
| 61 } | |
| 62 | |
| 63 // The encrypted portion of each subsample must form a contiguous block, | |
|
ddorwin
2012/07/03 21:03:47
This line seems to discuss a single subsample rath
strobe_
2012/07/13 00:47:07
Done.
| |
| 64 // such that an encrypted subsample that ends away from a block boundary is | |
| 65 // immediately followed by the start of the next encrypted subsample. We | |
| 66 // copy all encrypted subsamples to a contiguous buffer, decrypt them, then | |
| 67 // copy the decrypted bytes over the encrypted bytes in the output. | |
| 68 // TODO(strobe): attempt to reduce number of memory copies | |
| 69 scoped_array<uint8> encrypted_bytes( | |
| 70 new uint8[total_encrypted_subsample_size]); | |
| 71 int in_pos = 0, out_pos = 0; | |
|
xhwang
2012/06/27 19:37:43
Prefer to declaring variables on separate lines. I
strobe_
2012/07/13 00:47:07
Done.
| |
| 72 for (size_t i = 0; i < subsamples.size(); i++) { | |
| 73 const SubsampleEntry& subsample = subsamples[i]; | |
| 74 in_pos += subsample.clear_bytes; | |
| 75 if (in_pos + subsample.cypher_bytes > input.GetDataSize()) { | |
| 76 DVLOG(1) << "Subsample total size larger than input size"; | |
| 77 return NULL; | |
| 78 } | |
| 79 memcpy(encrypted_bytes.get() + out_pos, input.GetData() + in_pos, | |
| 80 subsample.cypher_bytes); | |
| 81 in_pos += subsample.cypher_bytes; | |
| 82 out_pos += subsample.cypher_bytes; | |
| 83 } | |
| 84 | |
| 85 std::string decrypted_text; | |
| 86 base::StringPiece encrypted_text( | |
| 87 reinterpret_cast<const char*>(encrypted_bytes.get()), | |
| 88 total_encrypted_subsample_size); | |
| 89 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { | |
| 90 DVLOG(1) << "Could not decrypt data."; | |
| 91 return NULL; | |
| 92 } | |
| 93 | |
| 94 scoped_refptr<DecoderBuffer> output = DecoderBuffer::CopyFrom( | |
| 95 input.GetData(), input.GetDataSize()); | |
| 96 in_pos = 0; | |
| 97 out_pos = 0; | |
| 98 for (size_t i = 0; i < subsamples.size(); i++) { | |
| 99 const SubsampleEntry& subsample = subsamples[i]; | |
| 100 out_pos += subsample.clear_bytes; | |
| 101 memcpy(output->GetWritableData() + out_pos, | |
| 102 reinterpret_cast<const uint8*>(decrypted_text.data()) + in_pos, | |
| 103 subsample.cypher_bytes); | |
| 104 in_pos += subsample.cypher_bytes; | |
| 105 out_pos += subsample.cypher_bytes; | |
|
xhwang
2012/06/27 19:37:43
This part is so similar to the block starting from
strobe_
2012/07/13 00:47:07
Done.
| |
| 106 } | |
| 107 return output; | |
| 108 } else { | |
|
xhwang
2012/06/27 19:37:43
nit: we don't need this "else" since "if" will alw
strobe_
2012/07/13 00:47:07
Done.
| |
| 109 std::string decrypted_text; | |
| 110 base::StringPiece encrypted_text( | |
| 111 reinterpret_cast<const char*>(input.GetData()), | |
| 112 input.GetDataSize()); | |
| 113 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { | |
| 114 DVLOG(1) << "Could not decrypt data."; | |
| 115 return NULL; | |
| 116 } | |
| 117 | |
| 118 // TODO(xhwang): Find a way to avoid this data copy. | |
| 119 return DecoderBuffer::CopyFrom( | |
| 120 reinterpret_cast<const uint8*>(decrypted_text.data()), | |
| 121 decrypted_text.size()); | |
| 47 } | 122 } |
| 48 | |
| 49 // TODO(xhwang): Find a way to avoid this data copy. | |
| 50 return DecoderBuffer::CopyFrom( | |
| 51 reinterpret_cast<const uint8*>(decrypted_text.data()), | |
| 52 decrypted_text.size()); | |
| 53 } | 123 } |
| 54 | 124 |
| 55 AesDecryptor::AesDecryptor(DecryptorClient* client) | 125 AesDecryptor::AesDecryptor(DecryptorClient* client) |
| 56 : client_(client) { | 126 : client_(client) { |
| 57 } | 127 } |
| 58 | 128 |
| 59 AesDecryptor::~AesDecryptor() { | 129 AesDecryptor::~AesDecryptor() { |
| 60 STLDeleteValues(&key_map_); | 130 STLDeleteValues(&key_map_); |
| 61 } | 131 } |
| 62 | 132 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 155 | 225 |
| 156 if (decrypted) { | 226 if (decrypted) { |
| 157 decrypted->SetTimestamp(encrypted->GetTimestamp()); | 227 decrypted->SetTimestamp(encrypted->GetTimestamp()); |
| 158 decrypted->SetDuration(encrypted->GetDuration()); | 228 decrypted->SetDuration(encrypted->GetDuration()); |
| 159 } | 229 } |
| 160 | 230 |
| 161 return decrypted; | 231 return decrypted; |
| 162 } | 232 } |
| 163 | 233 |
| 164 } // namespace media | 234 } // namespace media |
| OLD | NEW |