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 <string> | 5 #include <string> |
6 | 6 |
7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
8 #include "base/bind.h" | 8 #include "base/bind.h" |
9 #include "base/sys_byteorder.h" | 9 #include "base/sys_byteorder.h" |
10 #include "media/base/decoder_buffer.h" | 10 #include "media/base/decoder_buffer.h" |
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
136 // byte 33 is changed from 0xf7 to 0xf8. Bytes 20+ of WebM encrypted data | 136 // byte 33 is changed from 0xf7 to 0xf8. Bytes 20+ of WebM encrypted data |
137 // contains the encrypted frame. | 137 // contains the encrypted frame. |
138 static const unsigned char kWebmFrame0FrameDataChanged[] = { | 138 static const unsigned char kWebmFrame0FrameDataChanged[] = { |
139 0xfb, 0xe7, 0x1d, 0xbb, 0x4c, 0x23, 0xce, 0xba, | 139 0xfb, 0xe7, 0x1d, 0xbb, 0x4c, 0x23, 0xce, 0xba, |
140 0xcc, 0xf8, 0xda, 0xc0, 0xff, 0xff, 0xff, 0xff, | 140 0xcc, 0xf8, 0xda, 0xc0, 0xff, 0xff, 0xff, 0xff, |
141 0xff, 0xff, 0xff, 0xff, 0x99, 0xaa, 0xff, 0xb7, | 141 0xff, 0xff, 0xff, 0xff, 0x99, 0xaa, 0xff, 0xb7, |
142 0x74, 0x02, 0x4e, 0x1c, 0x75, 0x3d, 0xee, 0xcb, | 142 0x74, 0x02, 0x4e, 0x1c, 0x75, 0x3d, 0xee, 0xcb, |
143 0x64, 0xf8 | 143 0x64, 0xf8 |
144 }; | 144 }; |
145 | 145 |
| 146 // Returns a 16 byte CTR counter block. The CTR counter block format is a |
| 147 // CTR IV appended with a CTR block counter. |iv| is a CTR IV. |iv_size| is |
| 148 // the size of |iv| in bytes. |
| 149 static std::string GenerateCounterBlock(const uint8* iv, int iv_size) { |
| 150 const int kDecryptionKeySize = 16; |
| 151 CHECK_GT(iv_size, 0); |
| 152 CHECK_LE(iv_size, kDecryptionKeySize); |
| 153 char counter_block_data[kDecryptionKeySize]; |
| 154 |
| 155 // Set the IV. |
| 156 memcpy(counter_block_data, iv, iv_size); |
| 157 |
| 158 // Set block counter to all 0's. |
| 159 memset(counter_block_data + iv_size, 0, kDecryptionKeySize - iv_size); |
| 160 |
| 161 return std::string(counter_block_data, kDecryptionKeySize); |
| 162 } |
| 163 |
| 164 // Creates a WebM encrypted buffer that the demuxer would pass to the |
| 165 // decryptor. |data| is the payload of a WebM encrypted Block. |key_id| is |
| 166 // initialization data from the WebM file. Every encrypted Block has |
| 167 // an HMAC and IV prepended to an encrypted frame. Current encrypted WebM |
| 168 // request for comments specification is here: |
| 169 // http://wiki.webmproject.org/encryption/webm-encryption-rfc |
| 170 static scoped_refptr<DecoderBuffer> CreateWebMEncryptedBuffer( |
| 171 const uint8* data, int data_size, |
| 172 const uint8* key_id, int key_id_size) { |
| 173 scoped_refptr<DecoderBuffer> encrypted_buffer = DecoderBuffer::CopyFrom( |
| 174 data + kWebMHmacSize, data_size - kWebMHmacSize); |
| 175 CHECK(encrypted_buffer); |
| 176 |
| 177 uint64 network_iv; |
| 178 memcpy(&network_iv, data + kWebMHmacSize, sizeof(network_iv)); |
| 179 const uint64 iv = base::NetToHost64(network_iv); |
| 180 std::string webm_iv = GenerateCounterBlock( |
| 181 reinterpret_cast<const uint8*>(&iv), sizeof(iv)); |
| 182 encrypted_buffer->SetDecryptConfig( |
| 183 scoped_ptr<DecryptConfig>( |
| 184 new DecryptConfig(key_id, key_id_size, |
| 185 reinterpret_cast<const uint8*>(webm_iv.data()), |
| 186 webm_iv.size(), data, kWebMHmacSize, sizeof(iv)))); |
| 187 return encrypted_buffer; |
| 188 } |
| 189 |
146 class AesDecryptorTest : public testing::Test { | 190 class AesDecryptorTest : public testing::Test { |
147 public: | 191 public: |
148 AesDecryptorTest() | 192 AesDecryptorTest() |
149 : decryptor_(&client_), | 193 : decryptor_(&client_), |
150 decrypt_cb_(base::Bind(&AesDecryptorTest::BufferDecrypted, | 194 decrypt_cb_(base::Bind(&AesDecryptorTest::BufferDecrypted, |
151 base::Unretained(this))) { | 195 base::Unretained(this))) { |
152 } | 196 } |
153 | 197 |
154 protected: | 198 protected: |
155 // Returns a 16 byte CTR counter block. The CTR counter block format is a | |
156 // CTR IV appended with a CTR block counter. |iv| is a CTR IV. |iv_size| is | |
157 // the size of |iv| in bytes. | |
158 static std::string GenerateCounterBlock(const uint8* iv, int iv_size) { | |
159 const int kDecryptionKeySize = 16; | |
160 CHECK_GT(iv_size, 0); | |
161 CHECK_LE(iv_size, kDecryptionKeySize); | |
162 char counter_block_data[kDecryptionKeySize]; | |
163 | |
164 // Set the IV. | |
165 memcpy(counter_block_data, iv, iv_size); | |
166 | |
167 // Set block counter to all 0's. | |
168 memset(counter_block_data + iv_size, 0, kDecryptionKeySize - iv_size); | |
169 | |
170 return std::string(counter_block_data, kDecryptionKeySize); | |
171 } | |
172 | |
173 // Creates a WebM encrypted buffer that the demuxer would pass to the | |
174 // decryptor. |data| is the payload of a WebM encrypted Block. |key_id| is | |
175 // initialization data from the WebM file. Every encrypted Block has | |
176 // an HMAC and IV prepended to an encrypted frame. Current encrypted WebM | |
177 // request for comments specification is here | |
178 // http://wiki.webmproject.org/encryption/webm-encryption-rfc | |
179 scoped_refptr<DecoderBuffer> CreateWebMEncryptedBuffer(const uint8* data, | |
180 int data_size, | |
181 const uint8* key_id, | |
182 int key_id_size) { | |
183 scoped_refptr<DecoderBuffer> encrypted_buffer = DecoderBuffer::CopyFrom( | |
184 data + kWebMHmacSize, data_size - kWebMHmacSize); | |
185 CHECK(encrypted_buffer); | |
186 | |
187 uint64 network_iv; | |
188 memcpy(&network_iv, data + kWebMHmacSize, sizeof(network_iv)); | |
189 const uint64 iv = base::NetToHost64(network_iv); | |
190 std::string webm_iv = | |
191 GenerateCounterBlock(reinterpret_cast<const uint8*>(&iv), sizeof(iv)); | |
192 encrypted_buffer->SetDecryptConfig( | |
193 scoped_ptr<DecryptConfig>(new DecryptConfig( | |
194 key_id, key_id_size, | |
195 reinterpret_cast<const uint8*>(webm_iv.data()), webm_iv.size(), | |
196 data, kWebMHmacSize, | |
197 sizeof(iv)))); | |
198 return encrypted_buffer; | |
199 } | |
200 | |
201 void GenerateKeyRequest(const uint8* key_id, int key_id_size) { | 199 void GenerateKeyRequest(const uint8* key_id, int key_id_size) { |
202 EXPECT_CALL(client_, KeyMessageMock(kClearKeySystem, StrNe(std::string()), | 200 EXPECT_CALL(client_, KeyMessageMock(kClearKeySystem, StrNe(std::string()), |
203 NotNull(), Gt(0), "")) | 201 NotNull(), Gt(0), "")) |
204 .WillOnce(SaveArg<1>(&session_id_string_)); | 202 .WillOnce(SaveArg<1>(&session_id_string_)); |
205 decryptor_.GenerateKeyRequest(kClearKeySystem, key_id, key_id_size); | 203 decryptor_.GenerateKeyRequest(kClearKeySystem, key_id, key_id_size); |
206 } | 204 } |
207 | 205 |
208 void AddKeyAndExpectToSucceed(const uint8* key_id, int key_id_size, | 206 void AddKeyAndExpectToSucceed(const uint8* key_id, int key_id_size, |
209 const uint8* key, int key_size) { | 207 const uint8* key, int key_size) { |
210 EXPECT_CALL(client_, KeyAdded(kClearKeySystem, session_id_string_)); | 208 EXPECT_CALL(client_, KeyAdded(kClearKeySystem, session_id_string_)); |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 CreateWebMEncryptedBuffer(data, data_size, key_id, key_id_size); | 244 CreateWebMEncryptedBuffer(data, data_size, key_id, key_id_size); |
247 EXPECT_CALL(*this, BufferDecrypted(AesDecryptor::kError, IsNull())); | 245 EXPECT_CALL(*this, BufferDecrypted(AesDecryptor::kError, IsNull())); |
248 decryptor_.Decrypt(encrypted_data, decrypt_cb_); | 246 decryptor_.Decrypt(encrypted_data, decrypt_cb_); |
249 } | 247 } |
250 | 248 |
251 scoped_refptr<DecoderBuffer> encrypted_data_; | 249 scoped_refptr<DecoderBuffer> encrypted_data_; |
252 MockDecryptorClient client_; | 250 MockDecryptorClient client_; |
253 AesDecryptor decryptor_; | 251 AesDecryptor decryptor_; |
254 std::string session_id_string_; | 252 std::string session_id_string_; |
255 AesDecryptor::DecryptCB decrypt_cb_; | 253 AesDecryptor::DecryptCB decrypt_cb_; |
| 254 |
| 255 private: |
| 256 DISALLOW_COPY_AND_ASSIGN(AesDecryptorTest); |
256 }; | 257 }; |
257 | 258 |
258 TEST_F(AesDecryptorTest, NormalDecryption) { | 259 TEST_F(AesDecryptorTest, NormalDecryption) { |
259 const WebmEncryptedData& frame = kWebmEncryptedFrames[0]; | 260 const WebmEncryptedData& frame = kWebmEncryptedFrames[0]; |
260 GenerateKeyRequest(frame.key_id, frame.key_id_size); | 261 GenerateKeyRequest(frame.key_id, frame.key_id_size); |
261 AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size, | 262 AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size, |
262 frame.key, frame.key_size); | 263 frame.key, frame.key_size); |
263 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed(frame.encrypted_data, | 264 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed(frame.encrypted_data, |
264 frame.encrypted_data_size, | 265 frame.encrypted_data_size, |
265 frame.plain_text, | 266 frame.plain_text, |
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
375 frame.key, frame.key_size); | 376 frame.key, frame.key_size); |
376 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail(kWebmFrame0FrameDataChanged, | 377 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail(kWebmFrame0FrameDataChanged, |
377 frame.encrypted_data_size, | 378 frame.encrypted_data_size, |
378 frame.plain_text, | 379 frame.plain_text, |
379 frame.plain_text_size, | 380 frame.plain_text_size, |
380 frame.key_id, | 381 frame.key_id, |
381 frame.key_id_size)); | 382 frame.key_id_size)); |
382 } | 383 } |
383 | 384 |
384 } // namespace media | 385 } // namespace media |
OLD | NEW |