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 "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() { | |
xhwang
2012/06/27 22:38:35
Change to InitCbc(), to be consistent with kCbcEnc
strobe_
2012/07/13 00:47:07
Done.
| |
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 kInitialIv, arraysize(kInitialIv), | |
107 NULL, 0))); | |
108 } | |
109 | |
110 void InitCTRSubsample() { | |
111 encrypted_data_ = DecoderBuffer::CopyFrom( | |
112 kCtrSubsampleEncryptedData, arraysize(kCtrSubsampleEncryptedData)); | |
113 encrypted_data_->SetDecryptConfig( | |
114 scoped_ptr<DecryptConfig>(new DecryptConfig( | |
115 kKeyId1, arraysize(kKeyId1), | |
116 kInitialIv, arraysize(kInitialIv), | |
117 kSubsamples, arraysize(kSubsamples)))); | |
118 } | |
119 | |
58 void GenerateKeyRequest() { | 120 void GenerateKeyRequest() { |
59 EXPECT_CALL(client_, KeyMessageMock(kClearKeySystem, StrNe(std::string()), | 121 EXPECT_CALL(client_, KeyMessageMock(kClearKeySystem, StrNe(std::string()), |
60 NotNull(), Gt(0), "")) | 122 NotNull(), Gt(0), "")) |
61 .WillOnce(SaveArg<1>(&session_id_string_)); | 123 .WillOnce(SaveArg<1>(&session_id_string_)); |
62 decryptor_.GenerateKeyRequest(kClearKeySystem, | 124 decryptor_.GenerateKeyRequest(kClearKeySystem, |
63 kInitData, arraysize(kInitData)); | 125 kInitData, arraysize(kInitData)); |
64 } | 126 } |
65 | 127 |
66 template <int KeyIdSize, int KeySize> | 128 template <int KeyIdSize, int KeySize> |
67 void AddKeyAndExpectToSucceed(const uint8 (&key_id)[KeyIdSize], | 129 void AddKeyAndExpectToSucceed(const uint8 (&key_id)[KeyIdSize], |
68 const uint8 (&key)[KeySize]) { | 130 const uint8 (&key)[KeySize]) { |
69 EXPECT_CALL(client_, KeyAdded(kClearKeySystem, session_id_string_)); | 131 EXPECT_CALL(client_, KeyAdded(kClearKeySystem, session_id_string_)); |
70 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, | 132 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, |
71 session_id_string_); | 133 session_id_string_); |
72 } | 134 } |
73 | 135 |
74 template <int KeyIdSize, int KeySize> | 136 template <int KeyIdSize, int KeySize> |
75 void AddKeyAndExpectToFail(const uint8 (&key_id)[KeyIdSize], | 137 void AddKeyAndExpectToFail(const uint8 (&key_id)[KeyIdSize], |
76 const uint8 (&key)[KeySize]) { | 138 const uint8 (&key)[KeySize]) { |
77 EXPECT_CALL(client_, KeyError(kClearKeySystem, session_id_string_, | 139 EXPECT_CALL(client_, KeyError(kClearKeySystem, session_id_string_, |
78 Decryptor::kUnknownError, 0)); | 140 Decryptor::kUnknownError, 0)); |
79 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, | 141 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, |
80 session_id_string_); | 142 session_id_string_); |
81 } | 143 } |
82 | 144 |
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() { | 145 void DecryptAndExpectToSucceed() { |
90 scoped_refptr<DecoderBuffer> decrypted = | 146 scoped_refptr<DecoderBuffer> decrypted = |
91 decryptor_.Decrypt(encrypted_data_); | 147 decryptor_.Decrypt(encrypted_data_); |
92 ASSERT_TRUE(decrypted); | 148 ASSERT_TRUE(decrypted); |
93 int data_length = sizeof(kOriginalData); | 149 int data_length = sizeof(kOriginalData); |
94 ASSERT_EQ(data_length, decrypted->GetDataSize()); | 150 ASSERT_EQ(data_length, decrypted->GetDataSize()); |
95 EXPECT_EQ(0, memcmp(kOriginalData, decrypted->GetData(), data_length)); | 151 EXPECT_EQ(0, memcmp(kOriginalData, decrypted->GetData(), data_length)); |
96 } | 152 } |
97 | 153 |
154 // This function depends on PKCS#5 verification, which is only performed by | |
155 // CBC. Remove along with CBC. | |
ddorwin
2012/07/03 21:03:47
\nTODO: Remove..
strobe_
2012/07/13 00:47:07
Done.
| |
98 void DecryptAndExpectToFail() { | 156 void DecryptAndExpectToFail() { |
99 scoped_refptr<DecoderBuffer> decrypted = | 157 scoped_refptr<DecoderBuffer> decrypted = |
100 decryptor_.Decrypt(encrypted_data_); | 158 decryptor_.Decrypt(encrypted_data_); |
101 EXPECT_FALSE(decrypted); | 159 ASSERT_FALSE(decrypted); |
160 } | |
161 | |
162 void DecryptAndExpectIncorrectData() { | |
163 scoped_refptr<DecoderBuffer> decrypted = | |
164 decryptor_.Decrypt(encrypted_data_); | |
165 ASSERT_TRUE(decrypted); | |
166 int data_length = sizeof(kOriginalData); | |
167 ASSERT_EQ(data_length, decrypted->GetDataSize()); | |
168 EXPECT_NE(0, memcmp(kOriginalData, decrypted->GetData(), data_length)); | |
102 } | 169 } |
103 | 170 |
104 scoped_refptr<DecoderBuffer> encrypted_data_; | 171 scoped_refptr<DecoderBuffer> encrypted_data_; |
105 MockDecryptorClient client_; | 172 MockDecryptorClient client_; |
106 AesDecryptor decryptor_; | 173 AesDecryptor decryptor_; |
107 std::string session_id_string_; | 174 std::string session_id_string_; |
108 }; | 175 }; |
109 | 176 |
110 TEST_F(AesDecryptorTest, NormalDecryption) { | 177 TEST_F(AesDecryptorTest, NormalDecryption) { |
178 InitCTR(); | |
111 GenerateKeyRequest(); | 179 GenerateKeyRequest(); |
112 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | 180 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); |
113 SetKeyIdForEncryptedData(kKeyId1); | |
114 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | 181 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); |
115 } | 182 } |
116 | 183 |
184 TEST_F(AesDecryptorTest, NormalCBCDecryption) { | |
185 InitCBC(); | |
186 GenerateKeyRequest(); | |
187 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | |
188 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | |
189 } | |
190 | |
191 TEST_F(AesDecryptorTest, NormalCTRSubsampleDecryption) { | |
192 InitCTRSubsample(); | |
193 GenerateKeyRequest(); | |
194 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | |
195 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | |
196 } | |
197 | |
198 // This test relies on CBC verification of PKCS#5 padding, which CTR mode does | |
199 // not expect or verify. It should be removed along with support for CBC. | |
ddorwin
2012/07/03 21:03:47
If you want to remove this one, there should be a
strobe_
2012/07/13 00:47:07
Done.
| |
117 TEST_F(AesDecryptorTest, WrongKey) { | 200 TEST_F(AesDecryptorTest, WrongKey) { |
201 InitCBC(); | |
118 GenerateKeyRequest(); | 202 GenerateKeyRequest(); |
119 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); | 203 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); |
120 SetKeyIdForEncryptedData(kKeyId1); | |
121 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail()); | 204 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail()); |
122 } | 205 } |
123 | 206 |
124 TEST_F(AesDecryptorTest, MultipleKeys) { | 207 TEST_F(AesDecryptorTest, MultipleKeys) { |
208 InitCTR(); | |
125 GenerateKeyRequest(); | 209 GenerateKeyRequest(); |
126 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | 210 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); |
127 AddKeyAndExpectToSucceed(kKeyId2, kWrongKey); | 211 AddKeyAndExpectToSucceed(kKeyId2, kWrongKey); |
128 SetKeyIdForEncryptedData(kKeyId1); | |
129 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | 212 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); |
130 } | 213 } |
131 | 214 |
132 TEST_F(AesDecryptorTest, KeyReplacement) { | 215 TEST_F(AesDecryptorTest, KeyReplacement) { |
216 InitCTR(); | |
133 GenerateKeyRequest(); | 217 GenerateKeyRequest(); |
134 SetKeyIdForEncryptedData(kKeyId1); | |
135 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); | 218 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); |
136 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail()); | 219 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectIncorrectData()); |
137 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | 220 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); |
138 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | 221 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); |
139 } | 222 } |
140 | 223 |
141 TEST_F(AesDecryptorTest, WrongSizedKey) { | 224 TEST_F(AesDecryptorTest, WrongSizedKey) { |
225 InitCTR(); | |
142 GenerateKeyRequest(); | 226 GenerateKeyRequest(); |
143 AddKeyAndExpectToFail(kKeyId1, kWrongSizedKey); | 227 AddKeyAndExpectToFail(kKeyId1, kWrongSizedKey); |
144 } | 228 } |
145 | 229 |
146 } // media | 230 } // media |
OLD | NEW |