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. | 19 uint32 AesDecryptor::next_session_id_ = 1; |
20 static const char kInitialCounter[] = "0000000000000000"; | |
21 | 20 |
22 uint32 AesDecryptor::next_session_id_ = 1; | 21 enum ClearBytesBufferSel { |
| 22 kSrcContainsClearBytes, |
| 23 kDstContainsClearBytes, |
| 24 }; |
| 25 |
| 26 static void CopySubsamples(const std::vector<SubsampleEntry>& subsamples, |
| 27 const ClearBytesBufferSel sel, |
| 28 const uint8* src, |
| 29 uint8* dst) { |
| 30 for (size_t i = 0; i < subsamples.size(); i++) { |
| 31 const SubsampleEntry& subsample = subsamples[i]; |
| 32 if (sel == kSrcContainsClearBytes) { |
| 33 src += subsample.clear_bytes; |
| 34 } else { |
| 35 dst += subsample.clear_bytes; |
| 36 } |
| 37 memcpy(dst, src, subsample.cypher_bytes); |
| 38 src += subsample.cypher_bytes; |
| 39 dst += subsample.cypher_bytes; |
| 40 } |
| 41 } |
23 | 42 |
24 // Decrypt |input| using |key|. | 43 // Decrypt |input| using |key|. |
25 // Return a DecoderBuffer with the decrypted data if decryption succeeded. | 44 // Return a DecoderBuffer with the decrypted data if decryption succeeded. |
26 // Return NULL if decryption failed. | 45 // Return NULL if decryption failed. |
27 static scoped_refptr<DecoderBuffer> DecryptData(const DecoderBuffer& input, | 46 static scoped_refptr<DecoderBuffer> DecryptData(const DecoderBuffer& input, |
28 crypto::SymmetricKey* key) { | 47 crypto::SymmetricKey* key) { |
29 CHECK(input.GetDataSize()); | 48 CHECK(input.GetDataSize()); |
30 CHECK(key); | 49 CHECK(key); |
31 | 50 |
32 // Initialize encryption data. | 51 // Initialize encryption data. |
33 // The IV must be exactly as long as the cipher block size. | 52 // The IV must be exactly as long as the cipher block size. |
| 53 const std::string& iv = input.GetDecryptConfig()->iv(); |
34 crypto::Encryptor encryptor; | 54 crypto::Encryptor encryptor; |
35 if (!encryptor.Init(key, crypto::Encryptor::CBC, kInitialCounter)) { | 55 if (input.GetDecryptConfig()->use_cbc()) { |
36 DVLOG(1) << "Could not initialize encryptor."; | 56 if (!encryptor.Init(key, crypto::Encryptor::CBC, iv)) { |
| 57 DVLOG(1) << "Could not initialize encryptor."; |
| 58 return NULL; |
| 59 } |
| 60 } else { |
| 61 if (!encryptor.Init(key, crypto::Encryptor::CTR, base::StringPiece()) || |
| 62 !encryptor.SetCounter(iv)) { |
| 63 DVLOG(1) << "Could not initialize encryptor."; |
| 64 return NULL; |
| 65 } |
| 66 } |
| 67 |
| 68 if (input.GetDecryptConfig()->subsamples().empty()) { |
| 69 std::string decrypted_text; |
| 70 base::StringPiece encrypted_text( |
| 71 reinterpret_cast<const char*>(input.GetData()), |
| 72 input.GetDataSize()); |
| 73 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { |
| 74 DVLOG(1) << "Could not decrypt data."; |
| 75 return NULL; |
| 76 } |
| 77 |
| 78 // TODO(xhwang): Find a way to avoid this data copy. |
| 79 return DecoderBuffer::CopyFrom( |
| 80 reinterpret_cast<const uint8*>(decrypted_text.data()), |
| 81 decrypted_text.size()); |
| 82 } |
| 83 |
| 84 const std::vector<SubsampleEntry>& subsamples = |
| 85 input.GetDecryptConfig()->subsamples(); |
| 86 |
| 87 int total_clear_size = 0; |
| 88 int total_encrypted_size = 0; |
| 89 for (size_t i = 0; i < subsamples.size(); i++) { |
| 90 total_clear_size += subsamples[i].clear_bytes; |
| 91 total_encrypted_size += subsamples[i].cypher_bytes; |
| 92 } |
| 93 if (total_clear_size + total_encrypted_size != input.GetDataSize()) { |
| 94 DVLOG(1) << "Subsample sizes do not equal input size"; |
37 return NULL; | 95 return NULL; |
38 } | 96 } |
39 | 97 |
| 98 // The encrypted portions of all subsamples must form a contiguous block, |
| 99 // such that an encrypted subsample that ends away from a block boundary is |
| 100 // immediately followed by the start of the next encrypted subsample. We |
| 101 // copy all encrypted subsamples to a contiguous buffer, decrypt them, then |
| 102 // copy the decrypted bytes over the encrypted bytes in the output. |
| 103 // TODO(strobe): attempt to reduce number of memory copies |
| 104 scoped_array<uint8> encrypted_bytes( |
| 105 new uint8[total_encrypted_size]); |
| 106 CopySubsamples(subsamples, kSrcContainsClearBytes, |
| 107 input.GetData(), encrypted_bytes.get()); |
| 108 |
40 std::string decrypted_text; | 109 std::string decrypted_text; |
41 base::StringPiece encrypted_text( | 110 base::StringPiece encrypted_text( |
42 reinterpret_cast<const char*>(input.GetData()), | 111 reinterpret_cast<const char*>(encrypted_bytes.get()), |
43 input.GetDataSize()); | 112 total_encrypted_size); |
44 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { | 113 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { |
45 DVLOG(1) << "Could not decrypt data."; | 114 DVLOG(1) << "Could not decrypt data."; |
46 return NULL; | 115 return NULL; |
47 } | 116 } |
48 | 117 |
49 // TODO(xhwang): Find a way to avoid this data copy. | 118 scoped_refptr<DecoderBuffer> output = DecoderBuffer::CopyFrom( |
50 return DecoderBuffer::CopyFrom( | 119 input.GetData(), input.GetDataSize()); |
51 reinterpret_cast<const uint8*>(decrypted_text.data()), | 120 CopySubsamples(subsamples, kDstContainsClearBytes, |
52 decrypted_text.size()); | 121 reinterpret_cast<const uint8*>(decrypted_text.data()), |
| 122 output->GetWritableData()); |
| 123 return output; |
53 } | 124 } |
54 | 125 |
55 AesDecryptor::AesDecryptor(DecryptorClient* client) | 126 AesDecryptor::AesDecryptor(DecryptorClient* client) |
56 : client_(client) { | 127 : client_(client) { |
57 } | 128 } |
58 | 129 |
59 AesDecryptor::~AesDecryptor() { | 130 AesDecryptor::~AesDecryptor() { |
60 STLDeleteValues(&key_map_); | 131 STLDeleteValues(&key_map_); |
61 } | 132 } |
62 | 133 |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 decrypt_cb.Run(kError, NULL); | 232 decrypt_cb.Run(kError, NULL); |
162 return; | 233 return; |
163 } | 234 } |
164 | 235 |
165 decrypted->SetTimestamp(encrypted->GetTimestamp()); | 236 decrypted->SetTimestamp(encrypted->GetTimestamp()); |
166 decrypted->SetDuration(encrypted->GetDuration()); | 237 decrypted->SetDuration(encrypted->GetDuration()); |
167 decrypt_cb.Run(kSuccess, decrypted); | 238 decrypt_cb.Run(kSuccess, decrypted); |
168 } | 239 } |
169 | 240 |
170 } // namespace media | 241 } // namespace media |
OLD | NEW |