Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Side by Side Diff: media/crypto/aes_decryptor_unittest.cc

Issue 10651006: Add Common Encryption support to BMFF, including subsample decryption. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Address phantom comments Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 "media/base/decoder_buffer.h" 9 #include "media/base/decoder_buffer.h"
10 #include "media/base/decrypt_config.h" 10 #include "media/base/decrypt_config.h"
11 #include "media/base/mock_filters.h" 11 #include "media/base/mock_filters.h"
12 #include "media/crypto/aes_decryptor.h" 12 #include "media/crypto/aes_decryptor.h"
13 #include "testing/gmock/include/gmock/gmock.h" 13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h" 14 #include "testing/gtest/include/gtest/gtest.h"
15 15
16 using ::testing::_; 16 using ::testing::_;
17 using ::testing::Gt; 17 using ::testing::Gt;
18 using ::testing::IsNull; 18 using ::testing::IsNull;
19 using ::testing::NotNull; 19 using ::testing::NotNull;
20 using ::testing::SaveArg; 20 using ::testing::SaveArg;
21 using ::testing::StrNe; 21 using ::testing::StrNe;
22 22
23 namespace media { 23 namespace media {
24 24
25 static const char kClearKeySystem[] = "org.w3.clearkey"; 25 static const char kClearKeySystem[] = "org.w3.clearkey";
26 static const uint8 kInitData[] = { 0x69, 0x6e, 0x69, 0x74 }; 26 static const uint8 kInitData[] = { 0x69, 0x6e, 0x69, 0x74 };
27 // |kEncryptedData| is encrypted from |kOriginalData| using |kRightKey|.
28 // Modifying any of these independently would fail the test.
29 static const uint8 kOriginalData[] = { 27 static const uint8 kOriginalData[] = {
30 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c, 28 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c,
31 0x20, 0x64, 0x61, 0x74, 0x61, 0x2e 29 0x20, 0x64, 0x61, 0x74, 0x61, 0x2e, 0x20, 0x33,
30 0x30, 0x20, 0x62, 0x79, 0x74, 0x65, 0x73, 0x20,
31 0x6f, 0x66, 0x20, 0x69, 0x74, 0x2e
32 }; 32 };
33 static const uint8 kEncryptedData[] = { 33
34 0x82, 0x3A, 0x76, 0x92, 0xEC, 0x7F, 0xF8, 0x85, 34 // |kCbcEncryptedData| is |kOriginalData| encrypted with |kRightKey| and the
35 0xEC, 0x23, 0x52, 0xFB, 0x19, 0xB1, 0xB9, 0x09 35 // default IV embedded in aes_decryptor.cc.
36 //
37 // TODO(strobe): CBC is only used for an early draft of WebM encryption.
38 // Remove when https://chromiumcodereview.appspot.com/10535029 lands.
39 static const uint8 kCbcEncryptedData[] = {
40 0x16, 0xeb, 0x06, 0xf8, 0x99, 0x87, 0xce, 0x09,
41 0x0e, 0x91, 0x5a, 0xa3, 0x88, 0xc3, 0x5b, 0xf5,
42 0xe9, 0xac, 0x40, 0x53, 0x95, 0x85, 0x5f, 0x09,
43 0x3d, 0xa0, 0x4f, 0xbe, 0x66, 0xf5, 0x15, 0xb5
36 }; 44 };
45
46 // |kCtrEncryptedData| is |kOriginalData| encrypted with |kRightKey|, using
47 // initial counter |kInitialIv|.
48 static const uint8 kCtrEncryptedData[] = {
49 0x06, 0x53, 0x1d, 0x16, 0x67, 0xd4, 0x2d, 0x5c,
50 0xa8, 0xba, 0x3b, 0x82, 0xc4, 0xdc, 0x14, 0x89,
51 0xea, 0x2e, 0x8c, 0x64, 0x4c, 0x4b, 0x6b, 0xda,
52 0x39, 0xbb, 0xe8, 0xc1, 0x25, 0x35
53 };
54
55 // |kCtrSubsampleEncryptedData| is |kOriginalData|, subsampled according to
56 // |kSubsamples|, with ciphered portions encrypted with |kRightKey|, using
57 // initial counter |kInitialIv|.
58 static const uint8 kCtrSubsampleEncryptedData[] = {
59 0x4f, 0x72, 0x69, 0x2e, 0x48, 0x1a, 0x10, 0x62,
60 0x20, 0xde, 0x2d, 0x44, 0xe9, 0xf0, 0x7a, 0xc5,
61 0x95, 0xd2, 0x56, 0xc3, 0xae, 0x6b, 0x9d, 0x3d,
62 0x57, 0x48, 0x38, 0x93, 0x74, 0x2e
63 };
64
37 static const uint8 kRightKey[] = { 65 static const uint8 kRightKey[] = {
38 0x41, 0x20, 0x77, 0x6f, 0x6e, 0x64, 0x65, 0x72, 66 0x41, 0x20, 0x77, 0x6f, 0x6e, 0x64, 0x65, 0x72,
39 0x66, 0x75, 0x6c, 0x20, 0x6b, 0x65, 0x79, 0x21 67 0x66, 0x75, 0x6c, 0x20, 0x6b, 0x65, 0x79, 0x21
40 }; 68 };
41 static const uint8 kWrongKey[] = { 69 static const uint8 kWrongKey[] = {
42 0x49, 0x27, 0x6d, 0x20, 0x61, 0x20, 0x77, 0x72, 70 0x49, 0x27, 0x6d, 0x20, 0x61, 0x20, 0x77, 0x72,
43 0x6f, 0x6e, 0x67, 0x20, 0x6b, 0x65, 0x79, 0x2e 71 0x6f, 0x6e, 0x67, 0x20, 0x6b, 0x65, 0x79, 0x2e
44 }; 72 };
45 static const uint8 kWrongSizedKey[] = { 0x20, 0x20 }; 73 static const uint8 kWrongSizedKey[] = { 0x20, 0x20 };
46 static const uint8 kKeyId1[] = { 74 static const uint8 kKeyId1[] = {
47 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44, 0x20, 0x31 75 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44, 0x20, 0x31
48 }; 76 };
49 static const uint8 kKeyId2[] = { 77 static const uint8 kKeyId2[] = {
50 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44, 0x20, 0x32 78 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44, 0x20, 0x32
51 }; 79 };
80 static const uint8 kInitialIv[] = {
81 0x41, 0x54, 0x65, 0x73, 0x74, 0x49, 0x56, 0x31,
82 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
83 };
84 static const SubsampleEntry kSubsamples[] = {
85 { 3, 5 },
86 { 1, 19 },
87 { 2, 0 }
88 };
52 89
53 class AesDecryptorTest : public testing::Test { 90 class AesDecryptorTest : public testing::Test {
54 public: 91 public:
55 AesDecryptorTest() 92 AesDecryptorTest()
56 : decryptor_(&client_), 93 : decryptor_(&client_),
57 decrypt_cb_(base::Bind(&AesDecryptorTest::BufferDecrypted, 94 decrypt_cb_(base::Bind(&AesDecryptorTest::BufferDecrypted,
58 base::Unretained(this))) { 95 base::Unretained(this))) {
59 encrypted_data_ = DecoderBuffer::CopyFrom(kEncryptedData,
60 arraysize(kEncryptedData));
61 } 96 }
62 97
63 protected: 98 protected:
99 void InitCbc() {
100 encrypted_data_ = DecoderBuffer::CopyFrom(
101 kCbcEncryptedData, arraysize(kCbcEncryptedData));
102 encrypted_data_->SetDecryptConfig(
103 scoped_ptr<DecryptConfig>(new DecryptConfig(
104 kKeyId1, arraysize(kKeyId1))));
105 }
106
107 void InitCtr() {
108 encrypted_data_ = DecoderBuffer::CopyFrom(
109 kCtrEncryptedData, arraysize(kCtrEncryptedData));
110 encrypted_data_->SetDecryptConfig(
111 scoped_ptr<DecryptConfig>(new DecryptConfig(
112 kKeyId1, arraysize(kKeyId1),
113 std::string(kInitialIv, kInitialIv + arraysize(kInitialIv)),
114 std::vector<SubsampleEntry>())));
115 }
116
117 void InitCtrSubsample() {
118 encrypted_data_ = DecoderBuffer::CopyFrom(
119 kCtrSubsampleEncryptedData, arraysize(kCtrSubsampleEncryptedData));
120 std::vector<SubsampleEntry> subsamples(
121 kSubsamples, kSubsamples + arraysize(kSubsamples));
122 encrypted_data_->SetDecryptConfig(
123 scoped_ptr<DecryptConfig>(new DecryptConfig(
124 kKeyId1, arraysize(kKeyId1),
125 std::string(kInitialIv, kInitialIv + arraysize(kInitialIv)),
126 subsamples)));
127 }
128
64 void GenerateKeyRequest() { 129 void GenerateKeyRequest() {
65 EXPECT_CALL(client_, KeyMessageMock(kClearKeySystem, StrNe(std::string()), 130 EXPECT_CALL(client_, KeyMessageMock(kClearKeySystem, StrNe(std::string()),
66 NotNull(), Gt(0), "")) 131 NotNull(), Gt(0), ""))
67 .WillOnce(SaveArg<1>(&session_id_string_)); 132 .WillOnce(SaveArg<1>(&session_id_string_));
68 decryptor_.GenerateKeyRequest(kClearKeySystem, 133 decryptor_.GenerateKeyRequest(kClearKeySystem,
69 kInitData, arraysize(kInitData)); 134 kInitData, arraysize(kInitData));
70 } 135 }
71 136
72 template <int KeyIdSize, int KeySize> 137 template <int KeyIdSize, int KeySize>
73 void AddKeyAndExpectToSucceed(const uint8 (&key_id)[KeyIdSize], 138 void AddKeyAndExpectToSucceed(const uint8 (&key_id)[KeyIdSize],
74 const uint8 (&key)[KeySize]) { 139 const uint8 (&key)[KeySize]) {
75 EXPECT_CALL(client_, KeyAdded(kClearKeySystem, session_id_string_)); 140 EXPECT_CALL(client_, KeyAdded(kClearKeySystem, session_id_string_));
76 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, 141 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize,
77 session_id_string_); 142 session_id_string_);
78 } 143 }
79 144
80 template <int KeyIdSize, int KeySize> 145 template <int KeyIdSize, int KeySize>
81 void AddKeyAndExpectToFail(const uint8 (&key_id)[KeyIdSize], 146 void AddKeyAndExpectToFail(const uint8 (&key_id)[KeyIdSize],
82 const uint8 (&key)[KeySize]) { 147 const uint8 (&key)[KeySize]) {
83 EXPECT_CALL(client_, KeyError(kClearKeySystem, session_id_string_, 148 EXPECT_CALL(client_, KeyError(kClearKeySystem, session_id_string_,
84 Decryptor::kUnknownError, 0)); 149 Decryptor::kUnknownError, 0));
85 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, 150 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize,
86 session_id_string_); 151 session_id_string_);
87 } 152 }
88 153
89 template <int KeyIdSize>
90 void SetKeyIdForEncryptedData(const uint8 (&key_id)[KeyIdSize]) {
91 encrypted_data_->SetDecryptConfig(
92 scoped_ptr<DecryptConfig>(new DecryptConfig(key_id, KeyIdSize)));
93 }
94
95 MOCK_METHOD2(BufferDecrypted, void(Decryptor::DecryptStatus, 154 MOCK_METHOD2(BufferDecrypted, void(Decryptor::DecryptStatus,
96 const scoped_refptr<DecoderBuffer>&)); 155 const scoped_refptr<DecoderBuffer>&));
97 156
98 void DecryptAndExpectToSucceed() { 157 void DecryptAndExpectToSucceed() {
99 scoped_refptr<DecoderBuffer> decrypted; 158 scoped_refptr<DecoderBuffer> decrypted;
100 EXPECT_CALL(*this, BufferDecrypted(AesDecryptor::kSuccess, NotNull())) 159 EXPECT_CALL(*this, BufferDecrypted(AesDecryptor::kSuccess, NotNull()))
101 .WillOnce(SaveArg<1>(&decrypted)); 160 .WillOnce(SaveArg<1>(&decrypted));
102 161
103 decryptor_.Decrypt(encrypted_data_, decrypt_cb_); 162 decryptor_.Decrypt(encrypted_data_, decrypt_cb_);
104 ASSERT_TRUE(decrypted); 163 ASSERT_TRUE(decrypted);
105 int data_length = sizeof(kOriginalData); 164 int data_length = sizeof(kOriginalData);
106 ASSERT_EQ(data_length, decrypted->GetDataSize()); 165 ASSERT_EQ(data_length, decrypted->GetDataSize());
107 EXPECT_EQ(0, memcmp(kOriginalData, decrypted->GetData(), data_length)); 166 EXPECT_EQ(0, memcmp(kOriginalData, decrypted->GetData(), data_length));
108 } 167 }
109 168
169 // This function depends on PKCS#5 verification, which is only performed by
170 // CBC.
171 // TODO(strobe): Remove along with CBC.
110 void DecryptAndExpectToFail() { 172 void DecryptAndExpectToFail() {
111 EXPECT_CALL(*this, BufferDecrypted(AesDecryptor::kError, IsNull())); 173 EXPECT_CALL(*this, BufferDecrypted(AesDecryptor::kError, IsNull()));
112 decryptor_.Decrypt(encrypted_data_, decrypt_cb_); 174 decryptor_.Decrypt(encrypted_data_, decrypt_cb_);
113 } 175 }
114 176
177 void DecryptAndExpectIncorrectData() {
178 scoped_refptr<DecoderBuffer> decrypted;
179 EXPECT_CALL(*this, BufferDecrypted(AesDecryptor::kSuccess, NotNull()))
180 .WillOnce(SaveArg<1>(&decrypted));
181
182 decryptor_.Decrypt(encrypted_data_, decrypt_cb_);
183 ASSERT_TRUE(decrypted);
184 int data_length = sizeof(kOriginalData);
185 ASSERT_EQ(data_length, decrypted->GetDataSize());
186 EXPECT_NE(0, memcmp(kOriginalData, decrypted->GetData(), data_length));
187 }
188
115 scoped_refptr<DecoderBuffer> encrypted_data_; 189 scoped_refptr<DecoderBuffer> encrypted_data_;
116 MockDecryptorClient client_; 190 MockDecryptorClient client_;
117 AesDecryptor decryptor_; 191 AesDecryptor decryptor_;
118 std::string session_id_string_; 192 std::string session_id_string_;
119 AesDecryptor::DecryptCB decrypt_cb_; 193 AesDecryptor::DecryptCB decrypt_cb_;
120 }; 194 };
121 195
122 TEST_F(AesDecryptorTest, NormalDecryption) { 196 TEST_F(AesDecryptorTest, NormalDecryption) {
197 InitCtr();
123 GenerateKeyRequest(); 198 GenerateKeyRequest();
124 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); 199 AddKeyAndExpectToSucceed(kKeyId1, kRightKey);
125 SetKeyIdForEncryptedData(kKeyId1);
126 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); 200 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed());
127 } 201 }
128 202
203 TEST_F(AesDecryptorTest, NormalCbcDecryption) {
204 InitCbc();
205 GenerateKeyRequest();
206 AddKeyAndExpectToSucceed(kKeyId1, kRightKey);
207 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed());
208 }
209
210 TEST_F(AesDecryptorTest, NormalCtrSubsampleDecryption) {
211 InitCtrSubsample();
212 GenerateKeyRequest();
213 AddKeyAndExpectToSucceed(kKeyId1, kRightKey);
214 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed());
215 }
216
217 TEST_F(AesDecryptorTest, WrongSubsampleSize) {
218 InitCtrSubsample();
219 const DecryptConfig& config = *encrypted_data_->GetDecryptConfig();
220 std::vector<SubsampleEntry> subsamples = config.subsamples();
221 subsamples[0].clear_bytes += 2;
222 encrypted_data_->SetDecryptConfig(
223 scoped_ptr<DecryptConfig>(new DecryptConfig(
224 config.key_id(), config.key_id_size(),
225 config.iv(), subsamples)));
226 GenerateKeyRequest();
227 AddKeyAndExpectToSucceed(kKeyId1, kRightKey);
228 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail());
229 }
230
129 TEST_F(AesDecryptorTest, WrongKey) { 231 TEST_F(AesDecryptorTest, WrongKey) {
232 InitCtr();
130 GenerateKeyRequest(); 233 GenerateKeyRequest();
131 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); 234 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey);
132 SetKeyIdForEncryptedData(kKeyId1); 235 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectIncorrectData());
236 }
237
238 // This test relies on CBC verification of PKCS#5 padding, which CTR mode does
239 // not expect or verify.
240 // TODO(strobe): Remove along with CBC.
241 TEST_F(AesDecryptorTest, WrongCbcKey) {
242 InitCbc();
243 GenerateKeyRequest();
244 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey);
133 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail()); 245 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail());
134 } 246 }
135 247
136 TEST_F(AesDecryptorTest, MultipleKeys) { 248 TEST_F(AesDecryptorTest, MultipleKeys) {
249 InitCtr();
137 GenerateKeyRequest(); 250 GenerateKeyRequest();
138 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); 251 AddKeyAndExpectToSucceed(kKeyId1, kRightKey);
139 AddKeyAndExpectToSucceed(kKeyId2, kWrongKey); 252 AddKeyAndExpectToSucceed(kKeyId2, kWrongKey);
140 SetKeyIdForEncryptedData(kKeyId1);
141 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); 253 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed());
142 } 254 }
143 255
144 TEST_F(AesDecryptorTest, KeyReplacement) { 256 TEST_F(AesDecryptorTest, KeyReplacement) {
257 InitCtr();
145 GenerateKeyRequest(); 258 GenerateKeyRequest();
146 SetKeyIdForEncryptedData(kKeyId1);
147 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); 259 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey);
148 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail()); 260 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectIncorrectData());
149 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); 261 AddKeyAndExpectToSucceed(kKeyId1, kRightKey);
150 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); 262 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed());
151 } 263 }
152 264
153 TEST_F(AesDecryptorTest, WrongSizedKey) { 265 TEST_F(AesDecryptorTest, WrongSizedKey) {
266 InitCtr();
154 GenerateKeyRequest(); 267 GenerateKeyRequest();
155 AddKeyAndExpectToFail(kKeyId1, kWrongSizedKey); 268 AddKeyAndExpectToFail(kKeyId1, kWrongSizedKey);
156 } 269 }
157 270
158 } // media 271 } // media
OLDNEW
« no previous file with comments | « media/crypto/aes_decryptor.cc ('k') | media/mp4/avc.h » ('j') | media/mp4/box_definitions.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698