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