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 "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 |
OLD | NEW |