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

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

Powered by Google App Engine
This is Rietveld 408576698