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[] = { | |
fgalligan1
2012/06/27 00:28:36
s/kCBCEncryptedData/kCbcEncryptedData
strobe_
2012/06/27 02:01:21
Done.
| |
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 |kInitialCtr|. | |
45 static const uint8 kCTREncryptedData[] = { | |
fgalligan1
2012/06/27 00:28:36
s/kCTREncryptedData/kCtrEncryptedData/
strobe_
2012/06/27 02:01:21
Done.
| |
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 // |kCTREncryptedData| is |kOriginalData|, subsampled according to | |
fgalligan1
2012/06/27 00:28:36
kCtrSubsampleEncryptedData
strobe_
2012/06/27 02:01:21
Done.
| |
53 // |kSubsamples|, with ciphered portions encrypted with |kRightKey|, using | |
54 // initial counter |kInitialCtr|. | |
55 static const uint8 kCTRSubsampleEncryptedData[] = { | |
fgalligan1
2012/06/27 00:28:36
s/kCTRSubsampleEncryptedData/kCtrSubsampleEncrypte
strobe_
2012/06/27 02:01:21
Done.
| |
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 kInitialCtr[] = { | |
ddorwin
2012/06/26 06:09:19
Why not call this IV?
strobe_
2012/06/27 02:01:21
Done. (The underlying libraries tend to treat init
| |
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 InitCTR(); |
ddorwin
2012/06/26 06:09:19
I think this is unexpected. Please call it in each
strobe_
2012/06/27 02:01:21
Done.
| |
54 arraysize(kEncryptedData)); | 91 }; |
92 | |
93 protected: | |
94 void InitCBC() { | |
95 encrypted_data_ = DecoderBuffer::CopyFrom( | |
96 kCBCEncryptedData, arraysize(kCBCEncryptedData)); | |
97 encrypted_data_->SetDecryptConfig( | |
98 scoped_ptr<DecryptConfig>(new DecryptConfig( | |
99 kKeyId1, arraysize(kKeyId1)))); | |
55 } | 100 } |
56 | 101 |
57 protected: | 102 void InitCTR() { |
103 encrypted_data_ = DecoderBuffer::CopyFrom( | |
104 kCTREncryptedData, arraysize(kCTREncryptedData)); | |
105 encrypted_data_->SetDecryptConfig( | |
106 scoped_ptr<DecryptConfig>(new DecryptConfig( | |
107 kKeyId1, arraysize(kKeyId1), | |
108 kInitialCtr, arraysize(kInitialCtr)))); | |
109 } | |
110 | |
111 void InitCTRSubsample() { | |
112 encrypted_data_ = DecoderBuffer::CopyFrom( | |
113 kCTRSubsampleEncryptedData, arraysize(kCTRSubsampleEncryptedData)); | |
114 encrypted_data_->SetDecryptConfig( | |
115 scoped_ptr<DecryptConfig>(new DecryptConfig( | |
116 kKeyId1, arraysize(kKeyId1), | |
117 kInitialCtr, arraysize(kInitialCtr), | |
118 kSubsamples, arraysize(kSubsamples)))); | |
119 } | |
120 | |
58 void GenerateKeyRequest() { | 121 void GenerateKeyRequest() { |
59 EXPECT_CALL(client_, KeyMessageMock(kClearKeySystem, StrNe(std::string()), | 122 EXPECT_CALL(client_, KeyMessageMock(kClearKeySystem, StrNe(std::string()), |
60 NotNull(), Gt(0), "")) | 123 NotNull(), Gt(0), "")) |
61 .WillOnce(SaveArg<1>(&session_id_string_)); | 124 .WillOnce(SaveArg<1>(&session_id_string_)); |
62 decryptor_.GenerateKeyRequest(kClearKeySystem, | 125 decryptor_.GenerateKeyRequest(kClearKeySystem, |
63 kInitData, arraysize(kInitData)); | 126 kInitData, arraysize(kInitData)); |
64 } | 127 } |
65 | 128 |
66 template <int KeyIdSize, int KeySize> | 129 template <int KeyIdSize, int KeySize> |
67 void AddKeyAndExpectToSucceed(const uint8 (&key_id)[KeyIdSize], | 130 void AddKeyAndExpectToSucceed(const uint8 (&key_id)[KeyIdSize], |
68 const uint8 (&key)[KeySize]) { | 131 const uint8 (&key)[KeySize]) { |
69 EXPECT_CALL(client_, KeyAdded(kClearKeySystem, session_id_string_)); | 132 EXPECT_CALL(client_, KeyAdded(kClearKeySystem, session_id_string_)); |
70 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, | 133 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, |
71 session_id_string_); | 134 session_id_string_); |
72 } | 135 } |
73 | 136 |
74 template <int KeyIdSize, int KeySize> | 137 template <int KeyIdSize, int KeySize> |
75 void AddKeyAndExpectToFail(const uint8 (&key_id)[KeyIdSize], | 138 void AddKeyAndExpectToFail(const uint8 (&key_id)[KeyIdSize], |
76 const uint8 (&key)[KeySize]) { | 139 const uint8 (&key)[KeySize]) { |
77 EXPECT_CALL(client_, KeyError(kClearKeySystem, session_id_string_, | 140 EXPECT_CALL(client_, KeyError(kClearKeySystem, session_id_string_, |
78 Decryptor::kUnknownError, 0)); | 141 Decryptor::kUnknownError, 0)); |
79 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, | 142 decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize, |
80 session_id_string_); | 143 session_id_string_); |
81 } | 144 } |
82 | 145 |
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() { | 146 void DecryptAndExpectToSucceed() { |
90 scoped_refptr<DecoderBuffer> decrypted = | 147 scoped_refptr<DecoderBuffer> decrypted = |
91 decryptor_.Decrypt(encrypted_data_); | 148 decryptor_.Decrypt(encrypted_data_); |
92 ASSERT_TRUE(decrypted); | 149 ASSERT_TRUE(decrypted); |
93 int data_length = sizeof(kOriginalData); | 150 int data_length = sizeof(kOriginalData); |
94 ASSERT_EQ(data_length, decrypted->GetDataSize()); | 151 ASSERT_EQ(data_length, decrypted->GetDataSize()); |
95 EXPECT_EQ(0, memcmp(kOriginalData, decrypted->GetData(), data_length)); | 152 EXPECT_EQ(0, memcmp(kOriginalData, decrypted->GetData(), data_length)); |
96 } | 153 } |
97 | 154 |
98 void DecryptAndExpectToFail() { | 155 void DecryptAndExpectIncorrectData() { |
99 scoped_refptr<DecoderBuffer> decrypted = | 156 scoped_refptr<DecoderBuffer> decrypted = |
100 decryptor_.Decrypt(encrypted_data_); | 157 decryptor_.Decrypt(encrypted_data_); |
101 EXPECT_FALSE(decrypted); | 158 ASSERT_TRUE(decrypted); |
ddorwin
2012/06/26 06:09:19
Does this pass because you fixed up the padding or
strobe_
2012/06/27 02:01:21
The latter. Our CBC decoder expects PKCS#5 padding
| |
159 int data_length = sizeof(kOriginalData); | |
160 ASSERT_EQ(data_length, decrypted->GetDataSize()); | |
161 EXPECT_NE(0, memcmp(kOriginalData, decrypted->GetData(), data_length)); | |
102 } | 162 } |
103 | 163 |
104 scoped_refptr<DecoderBuffer> encrypted_data_; | 164 scoped_refptr<DecoderBuffer> encrypted_data_; |
105 MockDecryptorClient client_; | 165 MockDecryptorClient client_; |
106 AesDecryptor decryptor_; | 166 AesDecryptor decryptor_; |
107 std::string session_id_string_; | 167 std::string session_id_string_; |
108 }; | 168 }; |
109 | 169 |
110 TEST_F(AesDecryptorTest, NormalDecryption) { | 170 TEST_F(AesDecryptorTest, NormalDecryption) { |
111 GenerateKeyRequest(); | 171 GenerateKeyRequest(); |
112 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | 172 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); |
113 SetKeyIdForEncryptedData(kKeyId1); | |
114 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | 173 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); |
115 } | 174 } |
116 | 175 |
117 TEST_F(AesDecryptorTest, WrongKey) { | 176 TEST_F(AesDecryptorTest, NormalCBCDecryption) { |
177 InitCBC(); | |
178 GenerateKeyRequest(); | |
179 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | |
180 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | |
181 } | |
182 | |
183 TEST_F(AesDecryptorTest, NormalCTRSubsampleDecryption) { | |
184 InitCTRSubsample(); | |
185 GenerateKeyRequest(); | |
186 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | |
187 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | |
188 } | |
189 | |
190 TEST_F(AesDecryptorTest, WrongCBCKey) { | |
ddorwin
2012/06/26 06:09:19
add InitCTRSubsample();
I think you also need a Wr
strobe_
2012/06/27 02:01:21
Not sure where this should go.
| |
118 GenerateKeyRequest(); | 191 GenerateKeyRequest(); |
119 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); | 192 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); |
120 SetKeyIdForEncryptedData(kKeyId1); | 193 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectIncorrectData()); |
121 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail()); | |
122 } | 194 } |
123 | 195 |
124 TEST_F(AesDecryptorTest, MultipleKeys) { | 196 TEST_F(AesDecryptorTest, MultipleKeys) { |
125 GenerateKeyRequest(); | 197 GenerateKeyRequest(); |
126 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | 198 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); |
127 AddKeyAndExpectToSucceed(kKeyId2, kWrongKey); | 199 AddKeyAndExpectToSucceed(kKeyId2, kWrongKey); |
128 SetKeyIdForEncryptedData(kKeyId1); | |
129 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | 200 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); |
130 } | 201 } |
131 | 202 |
132 TEST_F(AesDecryptorTest, KeyReplacement) { | 203 TEST_F(AesDecryptorTest, KeyReplacement) { |
133 GenerateKeyRequest(); | 204 GenerateKeyRequest(); |
134 SetKeyIdForEncryptedData(kKeyId1); | |
135 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); | 205 AddKeyAndExpectToSucceed(kKeyId1, kWrongKey); |
136 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail()); | 206 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectIncorrectData()); |
137 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); | 207 AddKeyAndExpectToSucceed(kKeyId1, kRightKey); |
138 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); | 208 ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed()); |
139 } | 209 } |
140 | 210 |
141 TEST_F(AesDecryptorTest, WrongSizedKey) { | 211 TEST_F(AesDecryptorTest, WrongSizedKey) { |
142 GenerateKeyRequest(); | 212 GenerateKeyRequest(); |
143 AddKeyAndExpectToFail(kKeyId1, kWrongSizedKey); | 213 AddKeyAndExpectToFail(kKeyId1, kWrongSizedKey); |
144 } | 214 } |
145 | 215 |
146 } // media | 216 } // media |
OLD | NEW |