Add std::string versions of URLRequestMockHTTPJob::GetMockUrl and GetMockHttpsUrl.
[chromium-blink-merge.git] / media / cdm / aes_decryptor_unittest.cc
blob98965756a78f88f2c89f5a30687f87863e01fe07
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include <string>
6 #include <vector>
8 #include "base/basictypes.h"
9 #include "base/bind.h"
10 #include "base/json/json_reader.h"
11 #include "base/values.h"
12 #include "media/base/cdm_callback_promise.h"
13 #include "media/base/cdm_key_information.h"
14 #include "media/base/decoder_buffer.h"
15 #include "media/base/decrypt_config.h"
16 #include "media/base/mock_filters.h"
17 #include "media/cdm/aes_decryptor.h"
18 #include "testing/gmock/include/gmock/gmock.h"
19 #include "testing/gtest/include/gtest/gtest.h"
20 #include "url/gurl.h"
22 using ::testing::_;
23 using ::testing::Gt;
24 using ::testing::IsNull;
25 using ::testing::NotNull;
26 using ::testing::SaveArg;
27 using ::testing::StrNe;
28 using ::testing::Unused;
30 MATCHER(IsEmpty, "") { return arg.empty(); }
31 MATCHER(IsNotEmpty, "") { return !arg.empty(); }
32 MATCHER(IsJSONDictionary, "") {
33 std::string result(arg.begin(), arg.end());
34 scoped_ptr<base::Value> root(base::JSONReader().ReadToValue(result));
35 return (root.get() && root->GetType() == base::Value::TYPE_DICTIONARY);
38 namespace media {
40 const uint8 kOriginalData[] = "Original subsample data.";
41 const int kOriginalDataSize = 24;
43 // In the examples below, 'k'(key) has to be 16 bytes, and will always require
44 // 2 bytes of padding. 'kid'(keyid) is variable length, and may require 0, 1,
45 // or 2 bytes of padding.
47 const uint8 kKeyId[] = {
48 // base64 equivalent is AAECAw
49 0x00, 0x01, 0x02, 0x03
52 // Key is 0x0405060708090a0b0c0d0e0f10111213,
53 // base64 equivalent is BAUGBwgJCgsMDQ4PEBESEw.
54 const char kKeyAsJWK[] =
55 "{"
56 " \"keys\": ["
57 " {"
58 " \"kty\": \"oct\","
59 " \"alg\": \"A128KW\","
60 " \"kid\": \"AAECAw\","
61 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
62 " }"
63 " ],"
64 " \"type\": \"temporary\""
65 "}";
67 // Same kid as kKeyAsJWK, key to decrypt kEncryptedData2
68 const char kKeyAlternateAsJWK[] =
69 "{"
70 " \"keys\": ["
71 " {"
72 " \"kty\": \"oct\","
73 " \"alg\": \"A128KW\","
74 " \"kid\": \"AAECAw\","
75 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
76 " }"
77 " ]"
78 "}";
80 const char kWrongKeyAsJWK[] =
81 "{"
82 " \"keys\": ["
83 " {"
84 " \"kty\": \"oct\","
85 " \"alg\": \"A128KW\","
86 " \"kid\": \"AAECAw\","
87 " \"k\": \"7u7u7u7u7u7u7u7u7u7u7g\""
88 " }"
89 " ]"
90 "}";
92 const char kWrongSizedKeyAsJWK[] =
93 "{"
94 " \"keys\": ["
95 " {"
96 " \"kty\": \"oct\","
97 " \"alg\": \"A128KW\","
98 " \"kid\": \"AAECAw\","
99 " \"k\": \"AAECAw\""
100 " }"
101 " ]"
102 "}";
104 const uint8 kIv[] = {
105 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
106 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
109 // kOriginalData encrypted with kKey and kIv but without any subsamples (or
110 // equivalently using kSubsampleEntriesCypherOnly).
111 const uint8 kEncryptedData[] = {
112 0x2f, 0x03, 0x09, 0xef, 0x71, 0xaf, 0x31, 0x16,
113 0xfa, 0x9d, 0x18, 0x43, 0x1e, 0x96, 0x71, 0xb5,
114 0xbf, 0xf5, 0x30, 0x53, 0x9a, 0x20, 0xdf, 0x95
117 // kOriginalData encrypted with kSubsampleKey and kSubsampleIv using
118 // kSubsampleEntriesNormal.
119 const uint8 kSubsampleEncryptedData[] = {
120 0x4f, 0x72, 0x09, 0x16, 0x09, 0xe6, 0x79, 0xad,
121 0x70, 0x73, 0x75, 0x62, 0x09, 0xbb, 0x83, 0x1d,
122 0x4d, 0x08, 0xd7, 0x78, 0xa4, 0xa7, 0xf1, 0x2e
125 const uint8 kOriginalData2[] = "Changed Original data.";
127 const uint8 kIv2[] = {
128 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
132 const uint8 kKeyId2[] = {
133 // base64 equivalent is AAECAwQFBgcICQoLDA0ODxAREhM=
134 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
135 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
136 0x10, 0x11, 0x12, 0x13
139 const char kKey2AsJWK[] =
141 " \"keys\": ["
142 " {"
143 " \"kty\": \"oct\","
144 " \"alg\": \"A128KW\","
145 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
146 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
147 " }"
148 " ]"
149 "}";
151 // 'k' in bytes is x14x15x16x17x18x19x1ax1bx1cx1dx1ex1fx20x21x22x23
153 const uint8 kEncryptedData2[] = {
154 0x57, 0x66, 0xf4, 0x12, 0x1a, 0xed, 0xb5, 0x79,
155 0x1c, 0x8e, 0x25, 0xd7, 0x17, 0xe7, 0x5e, 0x16,
156 0xe3, 0x40, 0x08, 0x27, 0x11, 0xe9
159 // Subsample entries for testing. The sum of |cypher_bytes| and |clear_bytes| of
160 // all entries must be equal to kOriginalDataSize to make the subsample entries
161 // valid.
163 const SubsampleEntry kSubsampleEntriesNormal[] = {
164 { 2, 7 },
165 { 3, 11 },
166 { 1, 0 }
169 const SubsampleEntry kSubsampleEntriesWrongSize[] = {
170 { 3, 6 }, // This entry doesn't match the correct entry.
171 { 3, 11 },
172 { 1, 0 }
175 const SubsampleEntry kSubsampleEntriesInvalidTotalSize[] = {
176 { 1, 1000 }, // This entry is too large.
177 { 3, 11 },
178 { 1, 0 }
181 const SubsampleEntry kSubsampleEntriesClearOnly[] = {
182 { 7, 0 },
183 { 8, 0 },
184 { 9, 0 }
187 const SubsampleEntry kSubsampleEntriesCypherOnly[] = {
188 { 0, 6 },
189 { 0, 8 },
190 { 0, 10 }
193 static scoped_refptr<DecoderBuffer> CreateEncryptedBuffer(
194 const std::vector<uint8>& data,
195 const std::vector<uint8>& key_id,
196 const std::vector<uint8>& iv,
197 const std::vector<SubsampleEntry>& subsample_entries) {
198 DCHECK(!data.empty());
199 scoped_refptr<DecoderBuffer> encrypted_buffer(new DecoderBuffer(data.size()));
200 memcpy(encrypted_buffer->writable_data(), &data[0], data.size());
201 CHECK(encrypted_buffer.get());
202 std::string key_id_string(
203 reinterpret_cast<const char*>(key_id.empty() ? NULL : &key_id[0]),
204 key_id.size());
205 std::string iv_string(
206 reinterpret_cast<const char*>(iv.empty() ? NULL : &iv[0]), iv.size());
207 encrypted_buffer->set_decrypt_config(scoped_ptr<DecryptConfig>(
208 new DecryptConfig(key_id_string, iv_string, subsample_entries)));
209 return encrypted_buffer;
212 enum PromiseResult { RESOLVED, REJECTED };
214 class AesDecryptorTest : public testing::Test {
215 public:
216 AesDecryptorTest()
217 : decryptor_(GURL::EmptyGURL(),
218 base::Bind(&AesDecryptorTest::OnSessionMessage,
219 base::Unretained(this)),
220 base::Bind(&AesDecryptorTest::OnSessionClosed,
221 base::Unretained(this)),
222 base::Bind(&AesDecryptorTest::OnSessionKeysChange,
223 base::Unretained(this))),
224 decrypt_cb_(base::Bind(&AesDecryptorTest::BufferDecrypted,
225 base::Unretained(this))),
226 original_data_(kOriginalData, kOriginalData + kOriginalDataSize),
227 encrypted_data_(kEncryptedData,
228 kEncryptedData + arraysize(kEncryptedData)),
229 subsample_encrypted_data_(
230 kSubsampleEncryptedData,
231 kSubsampleEncryptedData + arraysize(kSubsampleEncryptedData)),
232 key_id_(kKeyId, kKeyId + arraysize(kKeyId)),
233 iv_(kIv, kIv + arraysize(kIv)),
234 normal_subsample_entries_(
235 kSubsampleEntriesNormal,
236 kSubsampleEntriesNormal + arraysize(kSubsampleEntriesNormal)) {
239 protected:
240 void OnResolveWithSession(PromiseResult expected_result,
241 const std::string& session_id) {
242 EXPECT_EQ(expected_result, RESOLVED) << "Unexpectedly resolved.";
243 EXPECT_GT(session_id.length(), 0ul);
244 session_id_ = session_id;
247 void OnResolve(PromiseResult expected_result) {
248 EXPECT_EQ(expected_result, RESOLVED) << "Unexpectedly resolved.";
251 void OnReject(PromiseResult expected_result,
252 MediaKeys::Exception exception_code,
253 uint32 system_code,
254 const std::string& error_message) {
255 EXPECT_EQ(expected_result, REJECTED)
256 << "Unexpectedly rejected with message: " << error_message;
259 scoped_ptr<SimpleCdmPromise> CreatePromise(PromiseResult expected_result) {
260 scoped_ptr<SimpleCdmPromise> promise(
261 new CdmCallbackPromise<>(base::Bind(&AesDecryptorTest::OnResolve,
262 base::Unretained(this),
263 expected_result),
264 base::Bind(&AesDecryptorTest::OnReject,
265 base::Unretained(this),
266 expected_result)));
267 return promise.Pass();
270 scoped_ptr<NewSessionCdmPromise> CreateSessionPromise(
271 PromiseResult expected_result) {
272 scoped_ptr<NewSessionCdmPromise> promise(
273 new CdmCallbackPromise<std::string>(
274 base::Bind(&AesDecryptorTest::OnResolveWithSession,
275 base::Unretained(this),
276 expected_result),
277 base::Bind(&AesDecryptorTest::OnReject,
278 base::Unretained(this),
279 expected_result)));
280 return promise.Pass();
283 // Creates a new session using |key_id|. Returns the session ID.
284 std::string CreateSession(const std::vector<uint8>& key_id) {
285 DCHECK(!key_id.empty());
286 EXPECT_CALL(*this, OnSessionMessage(IsNotEmpty(), _, IsJSONDictionary(),
287 GURL::EmptyGURL()));
288 decryptor_.CreateSessionAndGenerateRequest(MediaKeys::TEMPORARY_SESSION,
289 EmeInitDataType::WEBM, key_id,
290 CreateSessionPromise(RESOLVED));
291 // This expects the promise to be called synchronously, which is the case
292 // for AesDecryptor.
293 return session_id_;
296 // Closes the session specified by |session_id|.
297 void CloseSession(const std::string& session_id) {
298 EXPECT_CALL(*this, OnSessionClosed(session_id));
299 decryptor_.CloseSession(session_id, CreatePromise(RESOLVED));
302 // Removes the session specified by |session_id|. This should simply do a
303 // CloseSession().
304 // TODO(jrummell): Clean this up when the prefixed API is removed.
305 // http://crbug.com/249976.
306 void RemoveSession(const std::string& session_id) {
307 EXPECT_CALL(*this, OnSessionClosed(session_id));
308 decryptor_.RemoveSession(session_id, CreatePromise(RESOLVED));
311 MOCK_METHOD2(OnSessionKeysChangeCalled,
312 void(const std::string& session_id,
313 bool has_additional_usable_key));
315 void OnSessionKeysChange(const std::string& session_id,
316 bool has_additional_usable_key,
317 CdmKeysInfo keys_info) {
318 keys_info_.swap(keys_info);
319 OnSessionKeysChangeCalled(session_id, has_additional_usable_key);
322 // Updates the session specified by |session_id| with |key|. |result|
323 // tests that the update succeeds or generates an error.
324 void UpdateSessionAndExpect(std::string session_id,
325 const std::string& key,
326 PromiseResult expected_result,
327 bool new_key_expected) {
328 DCHECK(!key.empty());
330 if (expected_result == RESOLVED) {
331 EXPECT_CALL(*this,
332 OnSessionKeysChangeCalled(session_id, new_key_expected));
333 } else {
334 EXPECT_CALL(*this, OnSessionKeysChangeCalled(_, _)).Times(0);
337 decryptor_.UpdateSession(session_id,
338 std::vector<uint8>(key.begin(), key.end()),
339 CreatePromise(expected_result));
342 bool KeysInfoContains(std::vector<uint8> expected) {
343 for (const auto& key_id : keys_info_) {
344 if (key_id->key_id == expected)
345 return true;
347 return false;
350 MOCK_METHOD2(BufferDecrypted, void(Decryptor::Status,
351 const scoped_refptr<DecoderBuffer>&));
353 enum DecryptExpectation {
354 SUCCESS,
355 DATA_MISMATCH,
356 DATA_AND_SIZE_MISMATCH,
357 DECRYPT_ERROR,
358 NO_KEY
361 void DecryptAndExpect(const scoped_refptr<DecoderBuffer>& encrypted,
362 const std::vector<uint8>& plain_text,
363 DecryptExpectation result) {
364 scoped_refptr<DecoderBuffer> decrypted;
366 switch (result) {
367 case SUCCESS:
368 case DATA_MISMATCH:
369 case DATA_AND_SIZE_MISMATCH:
370 EXPECT_CALL(*this, BufferDecrypted(Decryptor::kSuccess, NotNull()))
371 .WillOnce(SaveArg<1>(&decrypted));
372 break;
373 case DECRYPT_ERROR:
374 EXPECT_CALL(*this, BufferDecrypted(Decryptor::kError, IsNull()))
375 .WillOnce(SaveArg<1>(&decrypted));
376 break;
377 case NO_KEY:
378 EXPECT_CALL(*this, BufferDecrypted(Decryptor::kNoKey, IsNull()))
379 .WillOnce(SaveArg<1>(&decrypted));
380 break;
383 decryptor_.Decrypt(Decryptor::kVideo, encrypted, decrypt_cb_);
385 std::vector<uint8> decrypted_text;
386 if (decrypted.get() && decrypted->data_size()) {
387 decrypted_text.assign(
388 decrypted->data(), decrypted->data() + decrypted->data_size());
391 switch (result) {
392 case SUCCESS:
393 EXPECT_EQ(plain_text, decrypted_text);
394 break;
395 case DATA_MISMATCH:
396 EXPECT_EQ(plain_text.size(), decrypted_text.size());
397 EXPECT_NE(plain_text, decrypted_text);
398 break;
399 case DATA_AND_SIZE_MISMATCH:
400 EXPECT_NE(plain_text.size(), decrypted_text.size());
401 break;
402 case DECRYPT_ERROR:
403 case NO_KEY:
404 EXPECT_TRUE(decrypted_text.empty());
405 break;
409 MOCK_METHOD4(OnSessionMessage,
410 void(const std::string& session_id,
411 MediaKeys::MessageType message_type,
412 const std::vector<uint8>& message,
413 const GURL& legacy_destination_url));
414 MOCK_METHOD1(OnSessionClosed, void(const std::string& session_id));
416 AesDecryptor decryptor_;
417 AesDecryptor::DecryptCB decrypt_cb_;
418 std::string session_id_;
419 CdmKeysInfo keys_info_;
421 // Constants for testing.
422 const std::vector<uint8> original_data_;
423 const std::vector<uint8> encrypted_data_;
424 const std::vector<uint8> subsample_encrypted_data_;
425 const std::vector<uint8> key_id_;
426 const std::vector<uint8> iv_;
427 const std::vector<SubsampleEntry> normal_subsample_entries_;
428 const std::vector<SubsampleEntry> no_subsample_entries_;
431 TEST_F(AesDecryptorTest, CreateSessionWithNullInitData) {
432 EXPECT_CALL(*this,
433 OnSessionMessage(IsNotEmpty(), _, IsEmpty(), GURL::EmptyGURL()));
434 decryptor_.CreateSessionAndGenerateRequest(
435 MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM, std::vector<uint8>(),
436 CreateSessionPromise(RESOLVED));
439 TEST_F(AesDecryptorTest, MultipleCreateSession) {
440 EXPECT_CALL(*this,
441 OnSessionMessage(IsNotEmpty(), _, IsEmpty(), GURL::EmptyGURL()));
442 decryptor_.CreateSessionAndGenerateRequest(
443 MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM, std::vector<uint8>(),
444 CreateSessionPromise(RESOLVED));
446 EXPECT_CALL(*this,
447 OnSessionMessage(IsNotEmpty(), _, IsEmpty(), GURL::EmptyGURL()));
448 decryptor_.CreateSessionAndGenerateRequest(
449 MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM, std::vector<uint8>(),
450 CreateSessionPromise(RESOLVED));
452 EXPECT_CALL(*this,
453 OnSessionMessage(IsNotEmpty(), _, IsEmpty(), GURL::EmptyGURL()));
454 decryptor_.CreateSessionAndGenerateRequest(
455 MediaKeys::TEMPORARY_SESSION, EmeInitDataType::WEBM, std::vector<uint8>(),
456 CreateSessionPromise(RESOLVED));
459 TEST_F(AesDecryptorTest, CreateSessionWithCencInitData) {
460 const uint8 init_data[] = {
461 0x00, 0x00, 0x00, 0x44, // size = 68
462 0x70, 0x73, 0x73, 0x68, // 'pssh'
463 0x01, // version
464 0x00, 0x00, 0x00, // flags
465 0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, // SystemID
466 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B,
467 0x00, 0x00, 0x00, 0x02, // key count
468 0x7E, 0x57, 0x1D, 0x03, 0x7E, 0x57, 0x1D, 0x03, // key1
469 0x7E, 0x57, 0x1D, 0x03, 0x7E, 0x57, 0x1D, 0x03,
470 0x7E, 0x57, 0x1D, 0x04, 0x7E, 0x57, 0x1D, 0x04, // key2
471 0x7E, 0x57, 0x1D, 0x04, 0x7E, 0x57, 0x1D, 0x04,
472 0x00, 0x00, 0x00, 0x00 // datasize
474 #if defined(USE_PROPRIETARY_CODECS)
475 EXPECT_CALL(*this, OnSessionMessage(IsNotEmpty(), _, IsJSONDictionary(),
476 GURL::EmptyGURL()));
477 decryptor_.CreateSessionAndGenerateRequest(
478 MediaKeys::TEMPORARY_SESSION, EmeInitDataType::CENC,
479 std::vector<uint8>(init_data, init_data + arraysize(init_data)),
480 CreateSessionPromise(RESOLVED));
481 #else
482 decryptor_.CreateSessionAndGenerateRequest(
483 MediaKeys::TEMPORARY_SESSION, EmeInitDataType::CENC,
484 std::vector<uint8>(init_data, init_data + arraysize(init_data)),
485 CreateSessionPromise(REJECTED));
486 #endif
489 TEST_F(AesDecryptorTest, CreateSessionWithKeyIdsInitData) {
490 const char init_data[] =
491 "{\"kids\":[\"AQI\",\"AQIDBA\",\"AQIDBAUGBwgJCgsMDQ4PEA\"]}";
493 EXPECT_CALL(*this, OnSessionMessage(IsNotEmpty(), _, IsJSONDictionary(),
494 GURL::EmptyGURL()));
495 decryptor_.CreateSessionAndGenerateRequest(
496 MediaKeys::TEMPORARY_SESSION, EmeInitDataType::KEYIDS,
497 std::vector<uint8>(init_data, init_data + arraysize(init_data) - 1),
498 CreateSessionPromise(RESOLVED));
501 TEST_F(AesDecryptorTest, NormalDecryption) {
502 std::string session_id = CreateSession(key_id_);
503 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
504 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
505 encrypted_data_, key_id_, iv_, no_subsample_entries_);
506 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
509 TEST_F(AesDecryptorTest, UnencryptedFrame) {
510 // An empty iv string signals that the frame is unencrypted.
511 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
512 original_data_, key_id_, std::vector<uint8>(), no_subsample_entries_);
513 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
516 TEST_F(AesDecryptorTest, WrongKey) {
517 std::string session_id = CreateSession(key_id_);
518 UpdateSessionAndExpect(session_id, kWrongKeyAsJWK, RESOLVED, true);
519 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
520 encrypted_data_, key_id_, iv_, no_subsample_entries_);
521 DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
524 TEST_F(AesDecryptorTest, NoKey) {
525 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
526 encrypted_data_, key_id_, iv_, no_subsample_entries_);
527 EXPECT_CALL(*this, BufferDecrypted(AesDecryptor::kNoKey, IsNull()));
528 decryptor_.Decrypt(Decryptor::kVideo, encrypted_buffer, decrypt_cb_);
531 TEST_F(AesDecryptorTest, KeyReplacement) {
532 std::string session_id = CreateSession(key_id_);
533 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
534 encrypted_data_, key_id_, iv_, no_subsample_entries_);
536 UpdateSessionAndExpect(session_id, kWrongKeyAsJWK, RESOLVED, true);
537 ASSERT_NO_FATAL_FAILURE(DecryptAndExpect(
538 encrypted_buffer, original_data_, DATA_MISMATCH));
540 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, false);
541 ASSERT_NO_FATAL_FAILURE(
542 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
545 TEST_F(AesDecryptorTest, WrongSizedKey) {
546 std::string session_id = CreateSession(key_id_);
547 UpdateSessionAndExpect(session_id, kWrongSizedKeyAsJWK, REJECTED, true);
550 TEST_F(AesDecryptorTest, MultipleKeysAndFrames) {
551 std::string session_id = CreateSession(key_id_);
552 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
553 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
554 encrypted_data_, key_id_, iv_, no_subsample_entries_);
555 ASSERT_NO_FATAL_FAILURE(
556 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
558 UpdateSessionAndExpect(session_id, kKey2AsJWK, RESOLVED, true);
560 // The first key is still available after we added a second key.
561 ASSERT_NO_FATAL_FAILURE(
562 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
564 // The second key is also available.
565 encrypted_buffer = CreateEncryptedBuffer(
566 std::vector<uint8>(kEncryptedData2,
567 kEncryptedData2 + arraysize(kEncryptedData2)),
568 std::vector<uint8>(kKeyId2, kKeyId2 + arraysize(kKeyId2)),
569 std::vector<uint8>(kIv2, kIv2 + arraysize(kIv2)),
570 no_subsample_entries_);
571 ASSERT_NO_FATAL_FAILURE(DecryptAndExpect(
572 encrypted_buffer,
573 std::vector<uint8>(kOriginalData2,
574 kOriginalData2 + arraysize(kOriginalData2) - 1),
575 SUCCESS));
578 TEST_F(AesDecryptorTest, CorruptedIv) {
579 std::string session_id = CreateSession(key_id_);
580 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
582 std::vector<uint8> bad_iv = iv_;
583 bad_iv[1]++;
585 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
586 encrypted_data_, key_id_, bad_iv, no_subsample_entries_);
588 DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
591 TEST_F(AesDecryptorTest, CorruptedData) {
592 std::string session_id = CreateSession(key_id_);
593 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
595 std::vector<uint8> bad_data = encrypted_data_;
596 bad_data[1]++;
598 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
599 bad_data, key_id_, iv_, no_subsample_entries_);
600 DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
603 TEST_F(AesDecryptorTest, EncryptedAsUnencryptedFailure) {
604 std::string session_id = CreateSession(key_id_);
605 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
606 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
607 encrypted_data_, key_id_, std::vector<uint8>(), no_subsample_entries_);
608 DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
611 TEST_F(AesDecryptorTest, SubsampleDecryption) {
612 std::string session_id = CreateSession(key_id_);
613 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
614 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
615 subsample_encrypted_data_, key_id_, iv_, normal_subsample_entries_);
616 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
619 // Ensures noninterference of data offset and subsample mechanisms. We never
620 // expect to encounter this in the wild, but since the DecryptConfig doesn't
621 // disallow such a configuration, it should be covered.
622 TEST_F(AesDecryptorTest, SubsampleDecryptionWithOffset) {
623 std::string session_id = CreateSession(key_id_);
624 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
625 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
626 subsample_encrypted_data_, key_id_, iv_, normal_subsample_entries_);
627 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
630 TEST_F(AesDecryptorTest, SubsampleWrongSize) {
631 std::string session_id = CreateSession(key_id_);
632 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
634 std::vector<SubsampleEntry> subsample_entries_wrong_size(
635 kSubsampleEntriesWrongSize,
636 kSubsampleEntriesWrongSize + arraysize(kSubsampleEntriesWrongSize));
638 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
639 subsample_encrypted_data_, key_id_, iv_, subsample_entries_wrong_size);
640 DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
643 TEST_F(AesDecryptorTest, SubsampleInvalidTotalSize) {
644 std::string session_id = CreateSession(key_id_);
645 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
647 std::vector<SubsampleEntry> subsample_entries_invalid_total_size(
648 kSubsampleEntriesInvalidTotalSize,
649 kSubsampleEntriesInvalidTotalSize +
650 arraysize(kSubsampleEntriesInvalidTotalSize));
652 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
653 subsample_encrypted_data_, key_id_, iv_,
654 subsample_entries_invalid_total_size);
655 DecryptAndExpect(encrypted_buffer, original_data_, DECRYPT_ERROR);
658 // No cypher bytes in any of the subsamples.
659 TEST_F(AesDecryptorTest, SubsampleClearBytesOnly) {
660 std::string session_id = CreateSession(key_id_);
661 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
663 std::vector<SubsampleEntry> clear_only_subsample_entries(
664 kSubsampleEntriesClearOnly,
665 kSubsampleEntriesClearOnly + arraysize(kSubsampleEntriesClearOnly));
667 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
668 original_data_, key_id_, iv_, clear_only_subsample_entries);
669 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
672 // No clear bytes in any of the subsamples.
673 TEST_F(AesDecryptorTest, SubsampleCypherBytesOnly) {
674 std::string session_id = CreateSession(key_id_);
675 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
677 std::vector<SubsampleEntry> cypher_only_subsample_entries(
678 kSubsampleEntriesCypherOnly,
679 kSubsampleEntriesCypherOnly + arraysize(kSubsampleEntriesCypherOnly));
681 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
682 encrypted_data_, key_id_, iv_, cypher_only_subsample_entries);
683 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
686 TEST_F(AesDecryptorTest, CloseSession) {
687 std::string session_id = CreateSession(key_id_);
688 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
689 encrypted_data_, key_id_, iv_, no_subsample_entries_);
691 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
692 ASSERT_NO_FATAL_FAILURE(
693 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
695 CloseSession(session_id);
698 TEST_F(AesDecryptorTest, RemoveSession) {
699 // TODO(jrummell): Clean this up when the prefixed API is removed.
700 // http://crbug.com/249976.
701 std::string session_id = CreateSession(key_id_);
702 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
703 encrypted_data_, key_id_, iv_, no_subsample_entries_);
705 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
706 ASSERT_NO_FATAL_FAILURE(
707 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
709 RemoveSession(session_id);
712 TEST_F(AesDecryptorTest, NoKeyAfterCloseSession) {
713 std::string session_id = CreateSession(key_id_);
714 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
715 encrypted_data_, key_id_, iv_, no_subsample_entries_);
717 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
718 ASSERT_NO_FATAL_FAILURE(
719 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
721 CloseSession(session_id);
722 ASSERT_NO_FATAL_FAILURE(
723 DecryptAndExpect(encrypted_buffer, original_data_, NO_KEY));
726 TEST_F(AesDecryptorTest, LatestKeyUsed) {
727 std::string session_id1 = CreateSession(key_id_);
728 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
729 encrypted_data_, key_id_, iv_, no_subsample_entries_);
731 // Add alternate key, buffer should not be decoded properly.
732 UpdateSessionAndExpect(session_id1, kKeyAlternateAsJWK, RESOLVED, true);
733 ASSERT_NO_FATAL_FAILURE(
734 DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH));
736 // Create a second session with a correct key value for key_id_.
737 std::string session_id2 = CreateSession(key_id_);
738 UpdateSessionAndExpect(session_id2, kKeyAsJWK, RESOLVED, true);
740 // Should be able to decode with latest key.
741 ASSERT_NO_FATAL_FAILURE(
742 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
745 TEST_F(AesDecryptorTest, LatestKeyUsedAfterCloseSession) {
746 std::string session_id1 = CreateSession(key_id_);
747 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
748 encrypted_data_, key_id_, iv_, no_subsample_entries_);
749 UpdateSessionAndExpect(session_id1, kKeyAsJWK, RESOLVED, true);
750 ASSERT_NO_FATAL_FAILURE(
751 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
753 // Create a second session with a different key value for key_id_.
754 std::string session_id2 = CreateSession(key_id_);
755 UpdateSessionAndExpect(session_id2, kKeyAlternateAsJWK, RESOLVED, true);
757 // Should not be able to decode with new key.
758 ASSERT_NO_FATAL_FAILURE(
759 DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH));
761 // Close second session, should revert to original key.
762 CloseSession(session_id2);
763 ASSERT_NO_FATAL_FAILURE(
764 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
767 TEST_F(AesDecryptorTest, JWKKey) {
768 std::string session_id = CreateSession(key_id_);
770 // Try a simple JWK key (i.e. not in a set)
771 const std::string kJwkSimple =
773 " \"kty\": \"oct\","
774 " \"alg\": \"A128KW\","
775 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
776 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
777 "}";
778 UpdateSessionAndExpect(session_id, kJwkSimple, REJECTED, true);
780 // Try a key list with multiple entries.
781 const std::string kJwksMultipleEntries =
783 " \"keys\": ["
784 " {"
785 " \"kty\": \"oct\","
786 " \"alg\": \"A128KW\","
787 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
788 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
789 " },"
790 " {"
791 " \"kty\": \"oct\","
792 " \"alg\": \"A128KW\","
793 " \"kid\": \"JCUmJygpKissLS4vMA\","
794 " \"k\":\"MTIzNDU2Nzg5Ojs8PT4_QA\""
795 " }"
796 " ]"
797 "}";
798 UpdateSessionAndExpect(session_id, kJwksMultipleEntries, RESOLVED, true);
800 // Try a key with no spaces and some \n plus additional fields.
801 const std::string kJwksNoSpaces =
802 "\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\",\"alg\":\"A128KW\","
803 "\"kid\":\"AQIDBAUGBwgJCgsMCg4PAA\",\"k\":\"GawgguFyGrWKav7AX4VKUg"
804 "\",\"foo\":\"bar\"}]}\n\n";
805 UpdateSessionAndExpect(session_id, kJwksNoSpaces, RESOLVED, true);
807 // Try some non-ASCII characters.
808 UpdateSessionAndExpect(session_id,
809 "This is not ASCII due to \xff\xfe\xfd in it.",
810 REJECTED, true);
812 // Try a badly formatted key. Assume that the JSON parser is fully tested,
813 // so we won't try a lot of combinations. However, need a test to ensure
814 // that the code doesn't crash if invalid JSON received.
815 UpdateSessionAndExpect(session_id, "This is not a JSON key.", REJECTED, true);
817 // Try passing some valid JSON that is not a dictionary at the top level.
818 UpdateSessionAndExpect(session_id, "40", REJECTED, true);
820 // Try an empty dictionary.
821 UpdateSessionAndExpect(session_id, "{ }", REJECTED, true);
823 // Try an empty 'keys' dictionary.
824 UpdateSessionAndExpect(session_id, "{ \"keys\": [] }", REJECTED, true);
826 // Try with 'keys' not a dictionary.
827 UpdateSessionAndExpect(session_id, "{ \"keys\":\"1\" }", REJECTED, true);
829 // Try with 'keys' a list of integers.
830 UpdateSessionAndExpect(session_id, "{ \"keys\": [ 1, 2, 3 ] }", REJECTED,
831 true);
833 // Try padding(=) at end of 'k' base64 string.
834 const std::string kJwksWithPaddedKey =
836 " \"keys\": ["
837 " {"
838 " \"kty\": \"oct\","
839 " \"alg\": \"A128KW\","
840 " \"kid\": \"AAECAw\","
841 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw==\""
842 " }"
843 " ]"
844 "}";
845 UpdateSessionAndExpect(session_id, kJwksWithPaddedKey, REJECTED, true);
847 // Try padding(=) at end of 'kid' base64 string.
848 const std::string kJwksWithPaddedKeyId =
850 " \"keys\": ["
851 " {"
852 " \"kty\": \"oct\","
853 " \"alg\": \"A128KW\","
854 " \"kid\": \"AAECAw==\","
855 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
856 " }"
857 " ]"
858 "}";
859 UpdateSessionAndExpect(session_id, kJwksWithPaddedKeyId, REJECTED, true);
861 // Try a key with invalid base64 encoding.
862 const std::string kJwksWithInvalidBase64 =
864 " \"keys\": ["
865 " {"
866 " \"kty\": \"oct\","
867 " \"alg\": \"A128KW\","
868 " \"kid\": \"!@#$%^&*()\","
869 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
870 " }"
871 " ]"
872 "}";
873 UpdateSessionAndExpect(session_id, kJwksWithInvalidBase64, REJECTED, true);
875 // Try a 3-byte 'kid' where no base64 padding is required.
876 // |kJwksMultipleEntries| above has 2 'kid's that require 1 and 2 padding
877 // bytes. Note that 'k' has to be 16 bytes, so it will always require padding.
878 const std::string kJwksWithNoPadding =
880 " \"keys\": ["
881 " {"
882 " \"kty\": \"oct\","
883 " \"alg\": \"A128KW\","
884 " \"kid\": \"Kiss\","
885 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
886 " }"
887 " ]"
888 "}";
889 UpdateSessionAndExpect(session_id, kJwksWithNoPadding, RESOLVED, true);
891 // Empty key id.
892 const std::string kJwksWithEmptyKeyId =
894 " \"keys\": ["
895 " {"
896 " \"kty\": \"oct\","
897 " \"alg\": \"A128KW\","
898 " \"kid\": \"\","
899 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
900 " }"
901 " ]"
902 "}";
903 UpdateSessionAndExpect(session_id, kJwksWithEmptyKeyId, REJECTED, true);
904 CloseSession(session_id);
907 TEST_F(AesDecryptorTest, GetKeyIds) {
908 std::vector<uint8> key_id1(kKeyId, kKeyId + arraysize(kKeyId));
909 std::vector<uint8> key_id2(kKeyId2, kKeyId2 + arraysize(kKeyId2));
911 std::string session_id = CreateSession(key_id_);
912 EXPECT_FALSE(KeysInfoContains(key_id1));
913 EXPECT_FALSE(KeysInfoContains(key_id2));
915 // Add 1 key, verify it is returned.
916 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
917 EXPECT_TRUE(KeysInfoContains(key_id1));
918 EXPECT_FALSE(KeysInfoContains(key_id2));
920 // Add second key, verify both IDs returned.
921 UpdateSessionAndExpect(session_id, kKey2AsJWK, RESOLVED, true);
922 EXPECT_TRUE(KeysInfoContains(key_id1));
923 EXPECT_TRUE(KeysInfoContains(key_id2));
926 TEST_F(AesDecryptorTest, NoKeysChangeForSameKey) {
927 std::vector<uint8> key_id(kKeyId, kKeyId + arraysize(kKeyId));
929 std::string session_id = CreateSession(key_id_);
930 EXPECT_FALSE(KeysInfoContains(key_id));
932 // Add key, verify it is returned.
933 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
934 EXPECT_TRUE(KeysInfoContains(key_id));
936 // Add key a second time.
937 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, false);
938 EXPECT_TRUE(KeysInfoContains(key_id));
940 // Create a new session. Add key, should indicate key added for this session.
941 std::string session_id2 = CreateSession(key_id_);
942 UpdateSessionAndExpect(session_id2, kKeyAsJWK, RESOLVED, true);
945 } // namespace media