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 static void CopySubsamples(const std::vector<SubsampleEntry>& subsamples, |
22 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.
| |
23 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.
| |
24 for (size_t i = 0; i < subsamples.size(); i++) { | |
25 const SubsampleEntry& subsample = subsamples[i]; | |
26 if (src_contains_clear_bytes) { | |
27 src += subsample.clear_bytes; | |
28 } else { | |
29 dst += subsample.clear_bytes; | |
30 } | |
31 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
| |
32 src += subsample.cypher_bytes; | |
33 dst += subsample.cypher_bytes; | |
34 } | |
35 } | |
23 | 36 |
24 // Decrypt |input| using |key|. | 37 // Decrypt |input| using |key|. |
25 // Return a DecoderBuffer with the decrypted data if decryption succeeded. | 38 // Return a DecoderBuffer with the decrypted data if decryption succeeded. |
26 // Return NULL if decryption failed. | 39 // Return NULL if decryption failed. |
27 static scoped_refptr<DecoderBuffer> DecryptData(const DecoderBuffer& input, | 40 static scoped_refptr<DecoderBuffer> DecryptData(const DecoderBuffer& input, |
28 crypto::SymmetricKey* key) { | 41 crypto::SymmetricKey* key) { |
29 CHECK(input.GetDataSize()); | 42 CHECK(input.GetDataSize()); |
30 CHECK(key); | 43 CHECK(key); |
31 | 44 |
32 // Initialize encryption data. | 45 // Initialize encryption data. |
33 // The IV must be exactly as long as the cipher block size. | 46 // The IV must be exactly as long as the cipher block size. |
47 const std::string& iv = input.GetDecryptConfig()->iv(); | |
34 crypto::Encryptor encryptor; | 48 crypto::Encryptor encryptor; |
35 if (!encryptor.Init(key, crypto::Encryptor::CBC, kInitialCounter)) { | 49 if (input.GetDecryptConfig()->use_cbc()) { |
36 DVLOG(1) << "Could not initialize encryptor."; | 50 if (!encryptor.Init(key, crypto::Encryptor::CBC, iv)) { |
37 return NULL; | 51 DVLOG(1) << "Could not initialize encryptor."; |
52 return NULL; | |
53 } | |
54 } else { | |
55 if (!encryptor.Init(key, crypto::Encryptor::CTR, base::StringPiece()) || | |
56 !encryptor.SetCounter(iv)) { | |
57 DVLOG(1) << "Could not initialize encryptor."; | |
58 return NULL; | |
59 } | |
60 } | |
61 | |
62 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.
| |
63 const std::vector<SubsampleEntry>& subsamples = | |
64 input.GetDecryptConfig()->subsamples(); | |
65 | |
66 int total_clear_size = 0; | |
67 int total_encrypted_size = 0; | |
68 for (size_t i = 0; i < subsamples.size(); i++) { | |
69 total_clear_size += subsamples[i].clear_bytes; | |
70 total_encrypted_size += subsamples[i].cypher_bytes; | |
71 } | |
72 if (total_clear_size + total_encrypted_size != input.GetDataSize()) { | |
73 DVLOG(1) << "Subsample sizes do not equal input size"; | |
74 return NULL; | |
75 } | |
76 | |
77 // The encrypted portions of all subsamples must form a contiguous block, | |
78 // such that an encrypted subsample that ends away from a block boundary is | |
79 // immediately followed by the start of the next encrypted subsample. We | |
80 // copy all encrypted subsamples to a contiguous buffer, decrypt them, then | |
81 // copy the decrypted bytes over the encrypted bytes in the output. | |
82 // TODO(strobe): attempt to reduce number of memory copies | |
83 scoped_array<uint8> encrypted_bytes( | |
84 new uint8[total_encrypted_size]); | |
85 CopySubsamples(subsamples, true, input.GetData(), encrypted_bytes.get()); | |
86 | |
87 std::string decrypted_text; | |
88 base::StringPiece encrypted_text( | |
89 reinterpret_cast<const char*>(encrypted_bytes.get()), | |
90 total_encrypted_size); | |
91 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { | |
92 DVLOG(1) << "Could not decrypt data."; | |
93 return NULL; | |
94 } | |
95 | |
96 scoped_refptr<DecoderBuffer> output = DecoderBuffer::CopyFrom( | |
97 input.GetData(), input.GetDataSize()); | |
98 CopySubsamples(subsamples, false, | |
99 reinterpret_cast<const uint8*>(decrypted_text.data()), | |
100 output->GetWritableData()); | |
101 return output; | |
38 } | 102 } |
39 | 103 |
40 std::string decrypted_text; | 104 std::string decrypted_text; |
41 base::StringPiece encrypted_text( | 105 base::StringPiece encrypted_text( |
42 reinterpret_cast<const char*>(input.GetData()), | 106 reinterpret_cast<const char*>(input.GetData()), |
43 input.GetDataSize()); | 107 input.GetDataSize()); |
44 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { | 108 if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) { |
45 DVLOG(1) << "Could not decrypt data."; | 109 DVLOG(1) << "Could not decrypt data."; |
46 return NULL; | 110 return NULL; |
47 } | 111 } |
(...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
155 | 219 |
156 if (decrypted) { | 220 if (decrypted) { |
157 decrypted->SetTimestamp(encrypted->GetTimestamp()); | 221 decrypted->SetTimestamp(encrypted->GetTimestamp()); |
158 decrypted->SetDuration(encrypted->GetDuration()); | 222 decrypted->SetDuration(encrypted->GetDuration()); |
159 } | 223 } |
160 | 224 |
161 return decrypted; | 225 return decrypted; |
162 } | 226 } |
163 | 227 |
164 } // namespace media | 228 } // namespace media |
OLD | NEW |