Implement MoveFileLocal (with creating a snapshot).
[chromium-blink-merge.git] / media / cdm / aes_decryptor_unittest.cc
blob8ca39408511bf87bb7a7e88057ffc0af1c63fb8b
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"
21 using ::testing::_;
22 using ::testing::Gt;
23 using ::testing::IsNull;
24 using ::testing::NotNull;
25 using ::testing::SaveArg;
26 using ::testing::StrNe;
27 using ::testing::Unused;
29 MATCHER(IsEmpty, "") { return arg.empty(); }
30 MATCHER(IsNotEmpty, "") { return !arg.empty(); }
31 MATCHER(IsJSONDictionary, "") {
32 std::string result(arg.begin(), arg.end());
33 scoped_ptr<base::Value> root(base::JSONReader().ReadToValue(result));
34 return (root.get() && root->GetType() == base::Value::TYPE_DICTIONARY);
37 class GURL;
39 namespace media {
41 const uint8 kOriginalData[] = "Original subsample data.";
42 const int kOriginalDataSize = 24;
44 // In the examples below, 'k'(key) has to be 16 bytes, and will always require
45 // 2 bytes of padding. 'kid'(keyid) is variable length, and may require 0, 1,
46 // or 2 bytes of padding.
48 const uint8 kKeyId[] = {
49 // base64 equivalent is AAECAw
50 0x00, 0x01, 0x02, 0x03
53 // Key is 0x0405060708090a0b0c0d0e0f10111213,
54 // base64 equivalent is BAUGBwgJCgsMDQ4PEBESEw.
55 const char kKeyAsJWK[] =
56 "{"
57 " \"keys\": ["
58 " {"
59 " \"kty\": \"oct\","
60 " \"alg\": \"A128KW\","
61 " \"kid\": \"AAECAw\","
62 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
63 " }"
64 " ],"
65 " \"type\": \"temporary\""
66 "}";
68 // Same kid as kKeyAsJWK, key to decrypt kEncryptedData2
69 const char kKeyAlternateAsJWK[] =
70 "{"
71 " \"keys\": ["
72 " {"
73 " \"kty\": \"oct\","
74 " \"alg\": \"A128KW\","
75 " \"kid\": \"AAECAw\","
76 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
77 " }"
78 " ]"
79 "}";
81 const char kWrongKeyAsJWK[] =
82 "{"
83 " \"keys\": ["
84 " {"
85 " \"kty\": \"oct\","
86 " \"alg\": \"A128KW\","
87 " \"kid\": \"AAECAw\","
88 " \"k\": \"7u7u7u7u7u7u7u7u7u7u7g\""
89 " }"
90 " ]"
91 "}";
93 const char kWrongSizedKeyAsJWK[] =
94 "{"
95 " \"keys\": ["
96 " {"
97 " \"kty\": \"oct\","
98 " \"alg\": \"A128KW\","
99 " \"kid\": \"AAECAw\","
100 " \"k\": \"AAECAw\""
101 " }"
102 " ]"
103 "}";
105 const uint8 kIv[] = {
106 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
107 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
110 // kOriginalData encrypted with kKey and kIv but without any subsamples (or
111 // equivalently using kSubsampleEntriesCypherOnly).
112 const uint8 kEncryptedData[] = {
113 0x2f, 0x03, 0x09, 0xef, 0x71, 0xaf, 0x31, 0x16,
114 0xfa, 0x9d, 0x18, 0x43, 0x1e, 0x96, 0x71, 0xb5,
115 0xbf, 0xf5, 0x30, 0x53, 0x9a, 0x20, 0xdf, 0x95
118 // kOriginalData encrypted with kSubsampleKey and kSubsampleIv using
119 // kSubsampleEntriesNormal.
120 const uint8 kSubsampleEncryptedData[] = {
121 0x4f, 0x72, 0x09, 0x16, 0x09, 0xe6, 0x79, 0xad,
122 0x70, 0x73, 0x75, 0x62, 0x09, 0xbb, 0x83, 0x1d,
123 0x4d, 0x08, 0xd7, 0x78, 0xa4, 0xa7, 0xf1, 0x2e
126 const uint8 kOriginalData2[] = "Changed Original data.";
128 const uint8 kIv2[] = {
129 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
130 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
133 const uint8 kKeyId2[] = {
134 // base64 equivalent is AAECAwQFBgcICQoLDA0ODxAREhM=
135 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
136 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
137 0x10, 0x11, 0x12, 0x13
140 const char kKey2AsJWK[] =
142 " \"keys\": ["
143 " {"
144 " \"kty\": \"oct\","
145 " \"alg\": \"A128KW\","
146 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
147 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
148 " }"
149 " ]"
150 "}";
152 // 'k' in bytes is x14x15x16x17x18x19x1ax1bx1cx1dx1ex1fx20x21x22x23
154 const uint8 kEncryptedData2[] = {
155 0x57, 0x66, 0xf4, 0x12, 0x1a, 0xed, 0xb5, 0x79,
156 0x1c, 0x8e, 0x25, 0xd7, 0x17, 0xe7, 0x5e, 0x16,
157 0xe3, 0x40, 0x08, 0x27, 0x11, 0xe9
160 // Subsample entries for testing. The sum of |cypher_bytes| and |clear_bytes| of
161 // all entries must be equal to kOriginalDataSize to make the subsample entries
162 // valid.
164 const SubsampleEntry kSubsampleEntriesNormal[] = {
165 { 2, 7 },
166 { 3, 11 },
167 { 1, 0 }
170 const SubsampleEntry kSubsampleEntriesWrongSize[] = {
171 { 3, 6 }, // This entry doesn't match the correct entry.
172 { 3, 11 },
173 { 1, 0 }
176 const SubsampleEntry kSubsampleEntriesInvalidTotalSize[] = {
177 { 1, 1000 }, // This entry is too large.
178 { 3, 11 },
179 { 1, 0 }
182 const SubsampleEntry kSubsampleEntriesClearOnly[] = {
183 { 7, 0 },
184 { 8, 0 },
185 { 9, 0 }
188 const SubsampleEntry kSubsampleEntriesCypherOnly[] = {
189 { 0, 6 },
190 { 0, 8 },
191 { 0, 10 }
194 static scoped_refptr<DecoderBuffer> CreateEncryptedBuffer(
195 const std::vector<uint8>& data,
196 const std::vector<uint8>& key_id,
197 const std::vector<uint8>& iv,
198 const std::vector<SubsampleEntry>& subsample_entries) {
199 DCHECK(!data.empty());
200 scoped_refptr<DecoderBuffer> encrypted_buffer(new DecoderBuffer(data.size()));
201 memcpy(encrypted_buffer->writable_data(), &data[0], data.size());
202 CHECK(encrypted_buffer.get());
203 std::string key_id_string(
204 reinterpret_cast<const char*>(key_id.empty() ? NULL : &key_id[0]),
205 key_id.size());
206 std::string iv_string(
207 reinterpret_cast<const char*>(iv.empty() ? NULL : &iv[0]), iv.size());
208 encrypted_buffer->set_decrypt_config(scoped_ptr<DecryptConfig>(
209 new DecryptConfig(key_id_string, iv_string, subsample_entries)));
210 return encrypted_buffer;
213 enum PromiseResult { RESOLVED, REJECTED };
215 class AesDecryptorTest : public testing::Test {
216 public:
217 AesDecryptorTest()
218 : decryptor_(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(
289 MediaKeys::TEMPORARY_SESSION, "webm", &key_id[0], key_id.size(),
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 DCHECK(!key.empty());
329 if (expected_result == RESOLVED) {
330 EXPECT_CALL(*this, OnSessionKeysChangeCalled(session_id, true));
331 } else {
332 EXPECT_CALL(*this, OnSessionKeysChangeCalled(_, _)).Times(0);
335 decryptor_.UpdateSession(session_id,
336 reinterpret_cast<const uint8*>(key.c_str()),
337 key.length(),
338 CreatePromise(expected_result));
341 bool KeysInfoContains(std::vector<uint8> expected) {
342 for (const auto& key_id : keys_info_) {
343 if (key_id->key_id == expected)
344 return true;
346 return false;
349 MOCK_METHOD2(BufferDecrypted, void(Decryptor::Status,
350 const scoped_refptr<DecoderBuffer>&));
352 enum DecryptExpectation {
353 SUCCESS,
354 DATA_MISMATCH,
355 DATA_AND_SIZE_MISMATCH,
356 DECRYPT_ERROR,
357 NO_KEY
360 void DecryptAndExpect(const scoped_refptr<DecoderBuffer>& encrypted,
361 const std::vector<uint8>& plain_text,
362 DecryptExpectation result) {
363 scoped_refptr<DecoderBuffer> decrypted;
365 switch (result) {
366 case SUCCESS:
367 case DATA_MISMATCH:
368 case DATA_AND_SIZE_MISMATCH:
369 EXPECT_CALL(*this, BufferDecrypted(Decryptor::kSuccess, NotNull()))
370 .WillOnce(SaveArg<1>(&decrypted));
371 break;
372 case DECRYPT_ERROR:
373 EXPECT_CALL(*this, BufferDecrypted(Decryptor::kError, IsNull()))
374 .WillOnce(SaveArg<1>(&decrypted));
375 break;
376 case NO_KEY:
377 EXPECT_CALL(*this, BufferDecrypted(Decryptor::kNoKey, IsNull()))
378 .WillOnce(SaveArg<1>(&decrypted));
379 break;
382 decryptor_.Decrypt(Decryptor::kVideo, encrypted, decrypt_cb_);
384 std::vector<uint8> decrypted_text;
385 if (decrypted.get() && decrypted->data_size()) {
386 decrypted_text.assign(
387 decrypted->data(), decrypted->data() + decrypted->data_size());
390 switch (result) {
391 case SUCCESS:
392 EXPECT_EQ(plain_text, decrypted_text);
393 break;
394 case DATA_MISMATCH:
395 EXPECT_EQ(plain_text.size(), decrypted_text.size());
396 EXPECT_NE(plain_text, decrypted_text);
397 break;
398 case DATA_AND_SIZE_MISMATCH:
399 EXPECT_NE(plain_text.size(), decrypted_text.size());
400 break;
401 case DECRYPT_ERROR:
402 case NO_KEY:
403 EXPECT_TRUE(decrypted_text.empty());
404 break;
408 MOCK_METHOD4(OnSessionMessage,
409 void(const std::string& session_id,
410 MediaKeys::MessageType message_type,
411 const std::vector<uint8>& message,
412 const GURL& legacy_destination_url));
413 MOCK_METHOD1(OnSessionClosed, void(const std::string& session_id));
415 AesDecryptor decryptor_;
416 AesDecryptor::DecryptCB decrypt_cb_;
417 std::string session_id_;
418 CdmKeysInfo keys_info_;
420 // Constants for testing.
421 const std::vector<uint8> original_data_;
422 const std::vector<uint8> encrypted_data_;
423 const std::vector<uint8> subsample_encrypted_data_;
424 const std::vector<uint8> key_id_;
425 const std::vector<uint8> iv_;
426 const std::vector<SubsampleEntry> normal_subsample_entries_;
427 const std::vector<SubsampleEntry> no_subsample_entries_;
430 TEST_F(AesDecryptorTest, CreateSessionWithNullInitData) {
431 EXPECT_CALL(*this,
432 OnSessionMessage(IsNotEmpty(), _, IsEmpty(), GURL::EmptyGURL()));
433 decryptor_.CreateSessionAndGenerateRequest(MediaKeys::TEMPORARY_SESSION,
434 "webm", NULL, 0,
435 CreateSessionPromise(RESOLVED));
438 TEST_F(AesDecryptorTest, MultipleCreateSession) {
439 EXPECT_CALL(*this,
440 OnSessionMessage(IsNotEmpty(), _, IsEmpty(), GURL::EmptyGURL()));
441 decryptor_.CreateSessionAndGenerateRequest(MediaKeys::TEMPORARY_SESSION,
442 "webm", NULL, 0,
443 CreateSessionPromise(RESOLVED));
445 EXPECT_CALL(*this,
446 OnSessionMessage(IsNotEmpty(), _, IsEmpty(), GURL::EmptyGURL()));
447 decryptor_.CreateSessionAndGenerateRequest(MediaKeys::TEMPORARY_SESSION,
448 "webm", NULL, 0,
449 CreateSessionPromise(RESOLVED));
451 EXPECT_CALL(*this,
452 OnSessionMessage(IsNotEmpty(), _, IsEmpty(), GURL::EmptyGURL()));
453 decryptor_.CreateSessionAndGenerateRequest(MediaKeys::TEMPORARY_SESSION,
454 "webm", NULL, 0,
455 CreateSessionPromise(RESOLVED));
458 TEST_F(AesDecryptorTest, CreateSessionWithCencInitData) {
459 const uint8 init_data[] = {
460 0x00, 0x00, 0x00, 0x44, // size = 68
461 0x70, 0x73, 0x73, 0x68, // 'pssh'
462 0x01, // version
463 0x00, 0x00, 0x00, // flags
464 0x10, 0x77, 0xEF, 0xEC, 0xC0, 0xB2, 0x4D, 0x02, // SystemID
465 0xAC, 0xE3, 0x3C, 0x1E, 0x52, 0xE2, 0xFB, 0x4B,
466 0x00, 0x00, 0x00, 0x02, // key count
467 0x7E, 0x57, 0x1D, 0x03, 0x7E, 0x57, 0x1D, 0x03, // key1
468 0x7E, 0x57, 0x1D, 0x03, 0x7E, 0x57, 0x1D, 0x03,
469 0x7E, 0x57, 0x1D, 0x04, 0x7E, 0x57, 0x1D, 0x04, // key2
470 0x7E, 0x57, 0x1D, 0x04, 0x7E, 0x57, 0x1D, 0x04,
471 0x00, 0x00, 0x00, 0x00 // datasize
473 EXPECT_CALL(*this, OnSessionMessage(IsNotEmpty(), _, IsJSONDictionary(),
474 GURL::EmptyGURL()));
475 decryptor_.CreateSessionAndGenerateRequest(
476 MediaKeys::TEMPORARY_SESSION, "cenc", init_data, arraysize(init_data),
477 CreateSessionPromise(RESOLVED));
480 TEST_F(AesDecryptorTest, CreateSessionWithKeyIdsInitData) {
481 const char init_data[] =
482 "{\"kids\":[\"AQI\",\"AQIDBA\",\"AQIDBAUGBwgJCgsMDQ4PEA\"]}";
484 EXPECT_CALL(*this, OnSessionMessage(IsNotEmpty(), _, IsJSONDictionary(),
485 GURL::EmptyGURL()));
486 decryptor_.CreateSessionAndGenerateRequest(
487 MediaKeys::TEMPORARY_SESSION, "keyids",
488 reinterpret_cast<const uint8*>(init_data), arraysize(init_data) - 1,
489 CreateSessionPromise(RESOLVED));
492 TEST_F(AesDecryptorTest, NormalDecryption) {
493 std::string session_id = CreateSession(key_id_);
494 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
495 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
496 encrypted_data_, key_id_, iv_, no_subsample_entries_);
497 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
500 TEST_F(AesDecryptorTest, UnencryptedFrame) {
501 // An empty iv string signals that the frame is unencrypted.
502 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
503 original_data_, key_id_, std::vector<uint8>(), no_subsample_entries_);
504 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
507 TEST_F(AesDecryptorTest, WrongKey) {
508 std::string session_id = CreateSession(key_id_);
509 UpdateSessionAndExpect(session_id, kWrongKeyAsJWK, RESOLVED);
510 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
511 encrypted_data_, key_id_, iv_, no_subsample_entries_);
512 DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
515 TEST_F(AesDecryptorTest, NoKey) {
516 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
517 encrypted_data_, key_id_, iv_, no_subsample_entries_);
518 EXPECT_CALL(*this, BufferDecrypted(AesDecryptor::kNoKey, IsNull()));
519 decryptor_.Decrypt(Decryptor::kVideo, encrypted_buffer, decrypt_cb_);
522 TEST_F(AesDecryptorTest, KeyReplacement) {
523 std::string session_id = CreateSession(key_id_);
524 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
525 encrypted_data_, key_id_, iv_, no_subsample_entries_);
527 UpdateSessionAndExpect(session_id, kWrongKeyAsJWK, RESOLVED);
528 ASSERT_NO_FATAL_FAILURE(DecryptAndExpect(
529 encrypted_buffer, original_data_, DATA_MISMATCH));
531 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
532 ASSERT_NO_FATAL_FAILURE(
533 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
536 TEST_F(AesDecryptorTest, WrongSizedKey) {
537 std::string session_id = CreateSession(key_id_);
538 UpdateSessionAndExpect(session_id, kWrongSizedKeyAsJWK, REJECTED);
541 TEST_F(AesDecryptorTest, MultipleKeysAndFrames) {
542 std::string session_id = CreateSession(key_id_);
543 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
544 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
545 encrypted_data_, key_id_, iv_, no_subsample_entries_);
546 ASSERT_NO_FATAL_FAILURE(
547 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
549 UpdateSessionAndExpect(session_id, kKey2AsJWK, RESOLVED);
551 // The first key is still available after we added a second key.
552 ASSERT_NO_FATAL_FAILURE(
553 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
555 // The second key is also available.
556 encrypted_buffer = CreateEncryptedBuffer(
557 std::vector<uint8>(kEncryptedData2,
558 kEncryptedData2 + arraysize(kEncryptedData2)),
559 std::vector<uint8>(kKeyId2, kKeyId2 + arraysize(kKeyId2)),
560 std::vector<uint8>(kIv2, kIv2 + arraysize(kIv2)),
561 no_subsample_entries_);
562 ASSERT_NO_FATAL_FAILURE(DecryptAndExpect(
563 encrypted_buffer,
564 std::vector<uint8>(kOriginalData2,
565 kOriginalData2 + arraysize(kOriginalData2) - 1),
566 SUCCESS));
569 TEST_F(AesDecryptorTest, CorruptedIv) {
570 std::string session_id = CreateSession(key_id_);
571 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
573 std::vector<uint8> bad_iv = iv_;
574 bad_iv[1]++;
576 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
577 encrypted_data_, key_id_, bad_iv, no_subsample_entries_);
579 DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
582 TEST_F(AesDecryptorTest, CorruptedData) {
583 std::string session_id = CreateSession(key_id_);
584 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
586 std::vector<uint8> bad_data = encrypted_data_;
587 bad_data[1]++;
589 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
590 bad_data, key_id_, iv_, no_subsample_entries_);
591 DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
594 TEST_F(AesDecryptorTest, EncryptedAsUnencryptedFailure) {
595 std::string session_id = CreateSession(key_id_);
596 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
597 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
598 encrypted_data_, key_id_, std::vector<uint8>(), no_subsample_entries_);
599 DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
602 TEST_F(AesDecryptorTest, SubsampleDecryption) {
603 std::string session_id = CreateSession(key_id_);
604 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
605 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
606 subsample_encrypted_data_, key_id_, iv_, normal_subsample_entries_);
607 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
610 // Ensures noninterference of data offset and subsample mechanisms. We never
611 // expect to encounter this in the wild, but since the DecryptConfig doesn't
612 // disallow such a configuration, it should be covered.
613 TEST_F(AesDecryptorTest, SubsampleDecryptionWithOffset) {
614 std::string session_id = CreateSession(key_id_);
615 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
616 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
617 subsample_encrypted_data_, key_id_, iv_, normal_subsample_entries_);
618 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
621 TEST_F(AesDecryptorTest, SubsampleWrongSize) {
622 std::string session_id = CreateSession(key_id_);
623 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
625 std::vector<SubsampleEntry> subsample_entries_wrong_size(
626 kSubsampleEntriesWrongSize,
627 kSubsampleEntriesWrongSize + arraysize(kSubsampleEntriesWrongSize));
629 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
630 subsample_encrypted_data_, key_id_, iv_, subsample_entries_wrong_size);
631 DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
634 TEST_F(AesDecryptorTest, SubsampleInvalidTotalSize) {
635 std::string session_id = CreateSession(key_id_);
636 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
638 std::vector<SubsampleEntry> subsample_entries_invalid_total_size(
639 kSubsampleEntriesInvalidTotalSize,
640 kSubsampleEntriesInvalidTotalSize +
641 arraysize(kSubsampleEntriesInvalidTotalSize));
643 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
644 subsample_encrypted_data_, key_id_, iv_,
645 subsample_entries_invalid_total_size);
646 DecryptAndExpect(encrypted_buffer, original_data_, DECRYPT_ERROR);
649 // No cypher bytes in any of the subsamples.
650 TEST_F(AesDecryptorTest, SubsampleClearBytesOnly) {
651 std::string session_id = CreateSession(key_id_);
652 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
654 std::vector<SubsampleEntry> clear_only_subsample_entries(
655 kSubsampleEntriesClearOnly,
656 kSubsampleEntriesClearOnly + arraysize(kSubsampleEntriesClearOnly));
658 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
659 original_data_, key_id_, iv_, clear_only_subsample_entries);
660 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
663 // No clear bytes in any of the subsamples.
664 TEST_F(AesDecryptorTest, SubsampleCypherBytesOnly) {
665 std::string session_id = CreateSession(key_id_);
666 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
668 std::vector<SubsampleEntry> cypher_only_subsample_entries(
669 kSubsampleEntriesCypherOnly,
670 kSubsampleEntriesCypherOnly + arraysize(kSubsampleEntriesCypherOnly));
672 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
673 encrypted_data_, key_id_, iv_, cypher_only_subsample_entries);
674 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
677 TEST_F(AesDecryptorTest, CloseSession) {
678 std::string session_id = CreateSession(key_id_);
679 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
680 encrypted_data_, key_id_, iv_, no_subsample_entries_);
682 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
683 ASSERT_NO_FATAL_FAILURE(
684 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
686 CloseSession(session_id);
689 TEST_F(AesDecryptorTest, RemoveSession) {
690 // TODO(jrummell): Clean this up when the prefixed API is removed.
691 // http://crbug.com/249976.
692 std::string session_id = CreateSession(key_id_);
693 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
694 encrypted_data_, key_id_, iv_, no_subsample_entries_);
696 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
697 ASSERT_NO_FATAL_FAILURE(
698 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
700 RemoveSession(session_id);
703 TEST_F(AesDecryptorTest, NoKeyAfterCloseSession) {
704 std::string session_id = CreateSession(key_id_);
705 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
706 encrypted_data_, key_id_, iv_, no_subsample_entries_);
708 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
709 ASSERT_NO_FATAL_FAILURE(
710 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
712 CloseSession(session_id);
713 ASSERT_NO_FATAL_FAILURE(
714 DecryptAndExpect(encrypted_buffer, original_data_, NO_KEY));
717 TEST_F(AesDecryptorTest, LatestKeyUsed) {
718 std::string session_id1 = CreateSession(key_id_);
719 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
720 encrypted_data_, key_id_, iv_, no_subsample_entries_);
722 // Add alternate key, buffer should not be decoded properly.
723 UpdateSessionAndExpect(session_id1, kKeyAlternateAsJWK, RESOLVED);
724 ASSERT_NO_FATAL_FAILURE(
725 DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH));
727 // Create a second session with a correct key value for key_id_.
728 std::string session_id2 = CreateSession(key_id_);
729 UpdateSessionAndExpect(session_id2, kKeyAsJWK, RESOLVED);
731 // Should be able to decode with latest key.
732 ASSERT_NO_FATAL_FAILURE(
733 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
736 TEST_F(AesDecryptorTest, LatestKeyUsedAfterCloseSession) {
737 std::string session_id1 = CreateSession(key_id_);
738 scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
739 encrypted_data_, key_id_, iv_, no_subsample_entries_);
740 UpdateSessionAndExpect(session_id1, kKeyAsJWK, RESOLVED);
741 ASSERT_NO_FATAL_FAILURE(
742 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
744 // Create a second session with a different key value for key_id_.
745 std::string session_id2 = CreateSession(key_id_);
746 UpdateSessionAndExpect(session_id2, kKeyAlternateAsJWK, RESOLVED);
748 // Should not be able to decode with new key.
749 ASSERT_NO_FATAL_FAILURE(
750 DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH));
752 // Close second session, should revert to original key.
753 CloseSession(session_id2);
754 ASSERT_NO_FATAL_FAILURE(
755 DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
758 TEST_F(AesDecryptorTest, JWKKey) {
759 std::string session_id = CreateSession(key_id_);
761 // Try a simple JWK key (i.e. not in a set)
762 const std::string kJwkSimple =
764 " \"kty\": \"oct\","
765 " \"alg\": \"A128KW\","
766 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
767 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
768 "}";
769 UpdateSessionAndExpect(session_id, kJwkSimple, REJECTED);
771 // Try a key list with multiple entries.
772 const std::string kJwksMultipleEntries =
774 " \"keys\": ["
775 " {"
776 " \"kty\": \"oct\","
777 " \"alg\": \"A128KW\","
778 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
779 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
780 " },"
781 " {"
782 " \"kty\": \"oct\","
783 " \"alg\": \"A128KW\","
784 " \"kid\": \"JCUmJygpKissLS4vMA\","
785 " \"k\":\"MTIzNDU2Nzg5Ojs8PT4_QA\""
786 " }"
787 " ]"
788 "}";
789 UpdateSessionAndExpect(session_id, kJwksMultipleEntries, RESOLVED);
791 // Try a key with no spaces and some \n plus additional fields.
792 const std::string kJwksNoSpaces =
793 "\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\",\"alg\":\"A128KW\","
794 "\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM\",\"k\":\"GawgguFyGrWKav7AX4VKUg"
795 "\",\"foo\":\"bar\"}]}\n\n";
796 UpdateSessionAndExpect(session_id, kJwksNoSpaces, RESOLVED);
798 // Try some non-ASCII characters.
799 UpdateSessionAndExpect(
800 session_id, "This is not ASCII due to \xff\xfe\xfd in it.", REJECTED);
802 // Try a badly formatted key. Assume that the JSON parser is fully tested,
803 // so we won't try a lot of combinations. However, need a test to ensure
804 // that the code doesn't crash if invalid JSON received.
805 UpdateSessionAndExpect(session_id, "This is not a JSON key.", REJECTED);
807 // Try passing some valid JSON that is not a dictionary at the top level.
808 UpdateSessionAndExpect(session_id, "40", REJECTED);
810 // Try an empty dictionary.
811 UpdateSessionAndExpect(session_id, "{ }", REJECTED);
813 // Try an empty 'keys' dictionary.
814 UpdateSessionAndExpect(session_id, "{ \"keys\": [] }", REJECTED);
816 // Try with 'keys' not a dictionary.
817 UpdateSessionAndExpect(session_id, "{ \"keys\":\"1\" }", REJECTED);
819 // Try with 'keys' a list of integers.
820 UpdateSessionAndExpect(session_id, "{ \"keys\": [ 1, 2, 3 ] }", REJECTED);
822 // Try padding(=) at end of 'k' base64 string.
823 const std::string kJwksWithPaddedKey =
825 " \"keys\": ["
826 " {"
827 " \"kty\": \"oct\","
828 " \"alg\": \"A128KW\","
829 " \"kid\": \"AAECAw\","
830 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw==\""
831 " }"
832 " ]"
833 "}";
834 UpdateSessionAndExpect(session_id, kJwksWithPaddedKey, REJECTED);
836 // Try padding(=) at end of 'kid' base64 string.
837 const std::string kJwksWithPaddedKeyId =
839 " \"keys\": ["
840 " {"
841 " \"kty\": \"oct\","
842 " \"alg\": \"A128KW\","
843 " \"kid\": \"AAECAw==\","
844 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
845 " }"
846 " ]"
847 "}";
848 UpdateSessionAndExpect(session_id, kJwksWithPaddedKeyId, REJECTED);
850 // Try a key with invalid base64 encoding.
851 const std::string kJwksWithInvalidBase64 =
853 " \"keys\": ["
854 " {"
855 " \"kty\": \"oct\","
856 " \"alg\": \"A128KW\","
857 " \"kid\": \"!@#$%^&*()\","
858 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
859 " }"
860 " ]"
861 "}";
862 UpdateSessionAndExpect(session_id, kJwksWithInvalidBase64, REJECTED);
864 // Try a 3-byte 'kid' where no base64 padding is required.
865 // |kJwksMultipleEntries| above has 2 'kid's that require 1 and 2 padding
866 // bytes. Note that 'k' has to be 16 bytes, so it will always require padding.
867 const std::string kJwksWithNoPadding =
869 " \"keys\": ["
870 " {"
871 " \"kty\": \"oct\","
872 " \"alg\": \"A128KW\","
873 " \"kid\": \"Kiss\","
874 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
875 " }"
876 " ]"
877 "}";
878 UpdateSessionAndExpect(session_id, kJwksWithNoPadding, RESOLVED);
880 // Empty key id.
881 const std::string kJwksWithEmptyKeyId =
883 " \"keys\": ["
884 " {"
885 " \"kty\": \"oct\","
886 " \"alg\": \"A128KW\","
887 " \"kid\": \"\","
888 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
889 " }"
890 " ]"
891 "}";
892 UpdateSessionAndExpect(session_id, kJwksWithEmptyKeyId, REJECTED);
893 CloseSession(session_id);
896 TEST_F(AesDecryptorTest, GetKeyIds) {
897 std::vector<uint8> key_id1(kKeyId, kKeyId + arraysize(kKeyId));
898 std::vector<uint8> key_id2(kKeyId2, kKeyId2 + arraysize(kKeyId2));
900 std::string session_id = CreateSession(key_id_);
901 EXPECT_FALSE(KeysInfoContains(key_id1));
902 EXPECT_FALSE(KeysInfoContains(key_id2));
904 // Add 1 key, verify it is returned.
905 UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
906 EXPECT_TRUE(KeysInfoContains(key_id1));
907 EXPECT_FALSE(KeysInfoContains(key_id2));
909 // Add second key, verify both IDs returned.
910 UpdateSessionAndExpect(session_id, kKey2AsJWK, RESOLVED);
911 EXPECT_TRUE(KeysInfoContains(key_id1));
912 EXPECT_TRUE(KeysInfoContains(key_id2));
915 } // namespace media