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.
8 #include "base/basictypes.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"
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
);
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
[] =
60 " \"alg\": \"A128KW\","
61 " \"kid\": \"AAECAw\","
62 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
65 " \"type\": \"temporary\""
68 // Same kid as kKeyAsJWK, key to decrypt kEncryptedData2
69 const char kKeyAlternateAsJWK
[] =
74 " \"alg\": \"A128KW\","
75 " \"kid\": \"AAECAw\","
76 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
81 const char kWrongKeyAsJWK
[] =
86 " \"alg\": \"A128KW\","
87 " \"kid\": \"AAECAw\","
88 " \"k\": \"7u7u7u7u7u7u7u7u7u7u7g\""
93 const char kWrongSizedKeyAsJWK
[] =
98 " \"alg\": \"A128KW\","
99 " \"kid\": \"AAECAw\","
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
[] =
145 " \"alg\": \"A128KW\","
146 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
147 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
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
164 const SubsampleEntry kSubsampleEntriesNormal
[] = {
170 const SubsampleEntry kSubsampleEntriesWrongSize
[] = {
171 { 3, 6 }, // This entry doesn't match the correct entry.
176 const SubsampleEntry kSubsampleEntriesInvalidTotalSize
[] = {
177 { 1, 1000 }, // This entry is too large.
182 const SubsampleEntry kSubsampleEntriesClearOnly
[] = {
188 const SubsampleEntry kSubsampleEntriesCypherOnly
[] = {
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]),
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
{
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
)) {
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
,
254 const std::string
& error_message
) {
255 EXPECT_EQ(expected_result
, REJECTED
) << "Unexpectedly rejected.";
258 scoped_ptr
<SimpleCdmPromise
> CreatePromise(PromiseResult expected_result
) {
259 scoped_ptr
<SimpleCdmPromise
> promise(
260 new CdmCallbackPromise
<>(base::Bind(&AesDecryptorTest::OnResolve
,
261 base::Unretained(this),
263 base::Bind(&AesDecryptorTest::OnReject
,
264 base::Unretained(this),
266 return promise
.Pass();
269 scoped_ptr
<NewSessionCdmPromise
> CreateSessionPromise(
270 PromiseResult expected_result
) {
271 scoped_ptr
<NewSessionCdmPromise
> promise(
272 new CdmCallbackPromise
<std::string
>(
273 base::Bind(&AesDecryptorTest::OnResolveWithSession
,
274 base::Unretained(this),
276 base::Bind(&AesDecryptorTest::OnReject
,
277 base::Unretained(this),
279 return promise
.Pass();
282 // Creates a new session using |key_id|. Returns the session ID.
283 std::string
CreateSession(const std::vector
<uint8
>& key_id
) {
284 DCHECK(!key_id
.empty());
285 EXPECT_CALL(*this, OnSessionMessage(IsNotEmpty(), _
, IsJSONDictionary(),
287 decryptor_
.CreateSessionAndGenerateRequest(
288 MediaKeys::TEMPORARY_SESSION
, "webm", &key_id
[0], key_id
.size(),
289 CreateSessionPromise(RESOLVED
));
290 // This expects the promise to be called synchronously, which is the case
295 // Closes the session specified by |session_id|.
296 void CloseSession(const std::string
& session_id
) {
297 EXPECT_CALL(*this, OnSessionClosed(session_id
));
298 decryptor_
.CloseSession(session_id
, CreatePromise(RESOLVED
));
301 // Removes the session specified by |session_id|. This should simply do a
303 // TODO(jrummell): Clean this up when the prefixed API is removed.
304 // http://crbug.com/249976.
305 void RemoveSession(const std::string
& session_id
) {
306 EXPECT_CALL(*this, OnSessionClosed(session_id
));
307 decryptor_
.RemoveSession(session_id
, CreatePromise(RESOLVED
));
310 MOCK_METHOD2(OnSessionKeysChangeCalled
,
311 void(const std::string
& session_id
,
312 bool has_additional_usable_key
));
314 void OnSessionKeysChange(const std::string
& session_id
,
315 bool has_additional_usable_key
,
316 CdmKeysInfo keys_info
) {
317 keys_info_
.swap(keys_info
);
318 OnSessionKeysChangeCalled(session_id
, has_additional_usable_key
);
321 // Updates the session specified by |session_id| with |key|. |result|
322 // tests that the update succeeds or generates an error.
323 void UpdateSessionAndExpect(std::string session_id
,
324 const std::string
& key
,
325 PromiseResult expected_result
) {
326 DCHECK(!key
.empty());
328 if (expected_result
== RESOLVED
) {
329 EXPECT_CALL(*this, OnSessionKeysChangeCalled(session_id
, true));
331 EXPECT_CALL(*this, OnSessionKeysChangeCalled(_
, _
)).Times(0);
334 decryptor_
.UpdateSession(session_id
,
335 reinterpret_cast<const uint8
*>(key
.c_str()),
337 CreatePromise(expected_result
));
340 bool KeysInfoContains(std::vector
<uint8
> expected
) {
341 for (const auto& key_id
: keys_info_
) {
342 if (key_id
->key_id
== expected
)
348 MOCK_METHOD2(BufferDecrypted
, void(Decryptor::Status
,
349 const scoped_refptr
<DecoderBuffer
>&));
351 enum DecryptExpectation
{
354 DATA_AND_SIZE_MISMATCH
,
359 void DecryptAndExpect(const scoped_refptr
<DecoderBuffer
>& encrypted
,
360 const std::vector
<uint8
>& plain_text
,
361 DecryptExpectation result
) {
362 scoped_refptr
<DecoderBuffer
> decrypted
;
367 case DATA_AND_SIZE_MISMATCH
:
368 EXPECT_CALL(*this, BufferDecrypted(Decryptor::kSuccess
, NotNull()))
369 .WillOnce(SaveArg
<1>(&decrypted
));
372 EXPECT_CALL(*this, BufferDecrypted(Decryptor::kError
, IsNull()))
373 .WillOnce(SaveArg
<1>(&decrypted
));
376 EXPECT_CALL(*this, BufferDecrypted(Decryptor::kNoKey
, IsNull()))
377 .WillOnce(SaveArg
<1>(&decrypted
));
381 decryptor_
.Decrypt(Decryptor::kVideo
, encrypted
, decrypt_cb_
);
383 std::vector
<uint8
> decrypted_text
;
384 if (decrypted
.get() && decrypted
->data_size()) {
385 decrypted_text
.assign(
386 decrypted
->data(), decrypted
->data() + decrypted
->data_size());
391 EXPECT_EQ(plain_text
, decrypted_text
);
394 EXPECT_EQ(plain_text
.size(), decrypted_text
.size());
395 EXPECT_NE(plain_text
, decrypted_text
);
397 case DATA_AND_SIZE_MISMATCH
:
398 EXPECT_NE(plain_text
.size(), decrypted_text
.size());
402 EXPECT_TRUE(decrypted_text
.empty());
407 MOCK_METHOD4(OnSessionMessage
,
408 void(const std::string
& session_id
,
409 MediaKeys::MessageType message_type
,
410 const std::vector
<uint8
>& message
,
411 const GURL
& legacy_destination_url
));
412 MOCK_METHOD1(OnSessionClosed
, void(const std::string
& session_id
));
414 AesDecryptor decryptor_
;
415 AesDecryptor::DecryptCB decrypt_cb_
;
416 std::string session_id_
;
417 CdmKeysInfo keys_info_
;
419 // Constants for testing.
420 const std::vector
<uint8
> original_data_
;
421 const std::vector
<uint8
> encrypted_data_
;
422 const std::vector
<uint8
> subsample_encrypted_data_
;
423 const std::vector
<uint8
> key_id_
;
424 const std::vector
<uint8
> iv_
;
425 const std::vector
<SubsampleEntry
> normal_subsample_entries_
;
426 const std::vector
<SubsampleEntry
> no_subsample_entries_
;
429 TEST_F(AesDecryptorTest
, CreateSessionWithNullInitData
) {
431 OnSessionMessage(IsNotEmpty(), _
, IsEmpty(), GURL::EmptyGURL()));
432 decryptor_
.CreateSessionAndGenerateRequest(MediaKeys::TEMPORARY_SESSION
,
434 CreateSessionPromise(RESOLVED
));
437 TEST_F(AesDecryptorTest
, MultipleCreateSession
) {
439 OnSessionMessage(IsNotEmpty(), _
, IsEmpty(), GURL::EmptyGURL()));
440 decryptor_
.CreateSessionAndGenerateRequest(MediaKeys::TEMPORARY_SESSION
,
442 CreateSessionPromise(RESOLVED
));
445 OnSessionMessage(IsNotEmpty(), _
, IsEmpty(), GURL::EmptyGURL()));
446 decryptor_
.CreateSessionAndGenerateRequest(MediaKeys::TEMPORARY_SESSION
,
448 CreateSessionPromise(RESOLVED
));
451 OnSessionMessage(IsNotEmpty(), _
, IsEmpty(), GURL::EmptyGURL()));
452 decryptor_
.CreateSessionAndGenerateRequest(MediaKeys::TEMPORARY_SESSION
,
454 CreateSessionPromise(RESOLVED
));
457 TEST_F(AesDecryptorTest
, NormalDecryption
) {
458 std::string session_id
= CreateSession(key_id_
);
459 UpdateSessionAndExpect(session_id
, kKeyAsJWK
, RESOLVED
);
460 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
461 encrypted_data_
, key_id_
, iv_
, no_subsample_entries_
);
462 DecryptAndExpect(encrypted_buffer
, original_data_
, SUCCESS
);
465 TEST_F(AesDecryptorTest
, UnencryptedFrame
) {
466 // An empty iv string signals that the frame is unencrypted.
467 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
468 original_data_
, key_id_
, std::vector
<uint8
>(), no_subsample_entries_
);
469 DecryptAndExpect(encrypted_buffer
, original_data_
, SUCCESS
);
472 TEST_F(AesDecryptorTest
, WrongKey
) {
473 std::string session_id
= CreateSession(key_id_
);
474 UpdateSessionAndExpect(session_id
, kWrongKeyAsJWK
, RESOLVED
);
475 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
476 encrypted_data_
, key_id_
, iv_
, no_subsample_entries_
);
477 DecryptAndExpect(encrypted_buffer
, original_data_
, DATA_MISMATCH
);
480 TEST_F(AesDecryptorTest
, NoKey
) {
481 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
482 encrypted_data_
, key_id_
, iv_
, no_subsample_entries_
);
483 EXPECT_CALL(*this, BufferDecrypted(AesDecryptor::kNoKey
, IsNull()));
484 decryptor_
.Decrypt(Decryptor::kVideo
, encrypted_buffer
, decrypt_cb_
);
487 TEST_F(AesDecryptorTest
, KeyReplacement
) {
488 std::string session_id
= CreateSession(key_id_
);
489 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
490 encrypted_data_
, key_id_
, iv_
, no_subsample_entries_
);
492 UpdateSessionAndExpect(session_id
, kWrongKeyAsJWK
, RESOLVED
);
493 ASSERT_NO_FATAL_FAILURE(DecryptAndExpect(
494 encrypted_buffer
, original_data_
, DATA_MISMATCH
));
496 UpdateSessionAndExpect(session_id
, kKeyAsJWK
, RESOLVED
);
497 ASSERT_NO_FATAL_FAILURE(
498 DecryptAndExpect(encrypted_buffer
, original_data_
, SUCCESS
));
501 TEST_F(AesDecryptorTest
, WrongSizedKey
) {
502 std::string session_id
= CreateSession(key_id_
);
503 UpdateSessionAndExpect(session_id
, kWrongSizedKeyAsJWK
, REJECTED
);
506 TEST_F(AesDecryptorTest
, MultipleKeysAndFrames
) {
507 std::string session_id
= CreateSession(key_id_
);
508 UpdateSessionAndExpect(session_id
, kKeyAsJWK
, RESOLVED
);
509 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
510 encrypted_data_
, key_id_
, iv_
, no_subsample_entries_
);
511 ASSERT_NO_FATAL_FAILURE(
512 DecryptAndExpect(encrypted_buffer
, original_data_
, SUCCESS
));
514 UpdateSessionAndExpect(session_id
, kKey2AsJWK
, RESOLVED
);
516 // The first key is still available after we added a second key.
517 ASSERT_NO_FATAL_FAILURE(
518 DecryptAndExpect(encrypted_buffer
, original_data_
, SUCCESS
));
520 // The second key is also available.
521 encrypted_buffer
= CreateEncryptedBuffer(
522 std::vector
<uint8
>(kEncryptedData2
,
523 kEncryptedData2
+ arraysize(kEncryptedData2
)),
524 std::vector
<uint8
>(kKeyId2
, kKeyId2
+ arraysize(kKeyId2
)),
525 std::vector
<uint8
>(kIv2
, kIv2
+ arraysize(kIv2
)),
526 no_subsample_entries_
);
527 ASSERT_NO_FATAL_FAILURE(DecryptAndExpect(
529 std::vector
<uint8
>(kOriginalData2
,
530 kOriginalData2
+ arraysize(kOriginalData2
) - 1),
534 TEST_F(AesDecryptorTest
, CorruptedIv
) {
535 std::string session_id
= CreateSession(key_id_
);
536 UpdateSessionAndExpect(session_id
, kKeyAsJWK
, RESOLVED
);
538 std::vector
<uint8
> bad_iv
= iv_
;
541 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
542 encrypted_data_
, key_id_
, bad_iv
, no_subsample_entries_
);
544 DecryptAndExpect(encrypted_buffer
, original_data_
, DATA_MISMATCH
);
547 TEST_F(AesDecryptorTest
, CorruptedData
) {
548 std::string session_id
= CreateSession(key_id_
);
549 UpdateSessionAndExpect(session_id
, kKeyAsJWK
, RESOLVED
);
551 std::vector
<uint8
> bad_data
= encrypted_data_
;
554 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
555 bad_data
, key_id_
, iv_
, no_subsample_entries_
);
556 DecryptAndExpect(encrypted_buffer
, original_data_
, DATA_MISMATCH
);
559 TEST_F(AesDecryptorTest
, EncryptedAsUnencryptedFailure
) {
560 std::string session_id
= CreateSession(key_id_
);
561 UpdateSessionAndExpect(session_id
, kKeyAsJWK
, RESOLVED
);
562 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
563 encrypted_data_
, key_id_
, std::vector
<uint8
>(), no_subsample_entries_
);
564 DecryptAndExpect(encrypted_buffer
, original_data_
, DATA_MISMATCH
);
567 TEST_F(AesDecryptorTest
, SubsampleDecryption
) {
568 std::string session_id
= CreateSession(key_id_
);
569 UpdateSessionAndExpect(session_id
, kKeyAsJWK
, RESOLVED
);
570 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
571 subsample_encrypted_data_
, key_id_
, iv_
, normal_subsample_entries_
);
572 DecryptAndExpect(encrypted_buffer
, original_data_
, SUCCESS
);
575 // Ensures noninterference of data offset and subsample mechanisms. We never
576 // expect to encounter this in the wild, but since the DecryptConfig doesn't
577 // disallow such a configuration, it should be covered.
578 TEST_F(AesDecryptorTest
, SubsampleDecryptionWithOffset
) {
579 std::string session_id
= CreateSession(key_id_
);
580 UpdateSessionAndExpect(session_id
, kKeyAsJWK
, RESOLVED
);
581 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
582 subsample_encrypted_data_
, key_id_
, iv_
, normal_subsample_entries_
);
583 DecryptAndExpect(encrypted_buffer
, original_data_
, SUCCESS
);
586 TEST_F(AesDecryptorTest
, SubsampleWrongSize
) {
587 std::string session_id
= CreateSession(key_id_
);
588 UpdateSessionAndExpect(session_id
, kKeyAsJWK
, RESOLVED
);
590 std::vector
<SubsampleEntry
> subsample_entries_wrong_size(
591 kSubsampleEntriesWrongSize
,
592 kSubsampleEntriesWrongSize
+ arraysize(kSubsampleEntriesWrongSize
));
594 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
595 subsample_encrypted_data_
, key_id_
, iv_
, subsample_entries_wrong_size
);
596 DecryptAndExpect(encrypted_buffer
, original_data_
, DATA_MISMATCH
);
599 TEST_F(AesDecryptorTest
, SubsampleInvalidTotalSize
) {
600 std::string session_id
= CreateSession(key_id_
);
601 UpdateSessionAndExpect(session_id
, kKeyAsJWK
, RESOLVED
);
603 std::vector
<SubsampleEntry
> subsample_entries_invalid_total_size(
604 kSubsampleEntriesInvalidTotalSize
,
605 kSubsampleEntriesInvalidTotalSize
+
606 arraysize(kSubsampleEntriesInvalidTotalSize
));
608 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
609 subsample_encrypted_data_
, key_id_
, iv_
,
610 subsample_entries_invalid_total_size
);
611 DecryptAndExpect(encrypted_buffer
, original_data_
, DECRYPT_ERROR
);
614 // No cypher bytes in any of the subsamples.
615 TEST_F(AesDecryptorTest
, SubsampleClearBytesOnly
) {
616 std::string session_id
= CreateSession(key_id_
);
617 UpdateSessionAndExpect(session_id
, kKeyAsJWK
, RESOLVED
);
619 std::vector
<SubsampleEntry
> clear_only_subsample_entries(
620 kSubsampleEntriesClearOnly
,
621 kSubsampleEntriesClearOnly
+ arraysize(kSubsampleEntriesClearOnly
));
623 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
624 original_data_
, key_id_
, iv_
, clear_only_subsample_entries
);
625 DecryptAndExpect(encrypted_buffer
, original_data_
, SUCCESS
);
628 // No clear bytes in any of the subsamples.
629 TEST_F(AesDecryptorTest
, SubsampleCypherBytesOnly
) {
630 std::string session_id
= CreateSession(key_id_
);
631 UpdateSessionAndExpect(session_id
, kKeyAsJWK
, RESOLVED
);
633 std::vector
<SubsampleEntry
> cypher_only_subsample_entries(
634 kSubsampleEntriesCypherOnly
,
635 kSubsampleEntriesCypherOnly
+ arraysize(kSubsampleEntriesCypherOnly
));
637 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
638 encrypted_data_
, key_id_
, iv_
, cypher_only_subsample_entries
);
639 DecryptAndExpect(encrypted_buffer
, original_data_
, SUCCESS
);
642 TEST_F(AesDecryptorTest
, CloseSession
) {
643 std::string session_id
= CreateSession(key_id_
);
644 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
645 encrypted_data_
, key_id_
, iv_
, no_subsample_entries_
);
647 UpdateSessionAndExpect(session_id
, kKeyAsJWK
, RESOLVED
);
648 ASSERT_NO_FATAL_FAILURE(
649 DecryptAndExpect(encrypted_buffer
, original_data_
, SUCCESS
));
651 CloseSession(session_id
);
654 TEST_F(AesDecryptorTest
, RemoveSession
) {
655 // TODO(jrummell): Clean this up when the prefixed API is removed.
656 // http://crbug.com/249976.
657 std::string session_id
= CreateSession(key_id_
);
658 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
659 encrypted_data_
, key_id_
, iv_
, no_subsample_entries_
);
661 UpdateSessionAndExpect(session_id
, kKeyAsJWK
, RESOLVED
);
662 ASSERT_NO_FATAL_FAILURE(
663 DecryptAndExpect(encrypted_buffer
, original_data_
, SUCCESS
));
665 RemoveSession(session_id
);
668 TEST_F(AesDecryptorTest
, NoKeyAfterCloseSession
) {
669 std::string session_id
= CreateSession(key_id_
);
670 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
671 encrypted_data_
, key_id_
, iv_
, no_subsample_entries_
);
673 UpdateSessionAndExpect(session_id
, kKeyAsJWK
, RESOLVED
);
674 ASSERT_NO_FATAL_FAILURE(
675 DecryptAndExpect(encrypted_buffer
, original_data_
, SUCCESS
));
677 CloseSession(session_id
);
678 ASSERT_NO_FATAL_FAILURE(
679 DecryptAndExpect(encrypted_buffer
, original_data_
, NO_KEY
));
682 TEST_F(AesDecryptorTest
, LatestKeyUsed
) {
683 std::string session_id1
= CreateSession(key_id_
);
684 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
685 encrypted_data_
, key_id_
, iv_
, no_subsample_entries_
);
687 // Add alternate key, buffer should not be decoded properly.
688 UpdateSessionAndExpect(session_id1
, kKeyAlternateAsJWK
, RESOLVED
);
689 ASSERT_NO_FATAL_FAILURE(
690 DecryptAndExpect(encrypted_buffer
, original_data_
, DATA_MISMATCH
));
692 // Create a second session with a correct key value for key_id_.
693 std::string session_id2
= CreateSession(key_id_
);
694 UpdateSessionAndExpect(session_id2
, kKeyAsJWK
, RESOLVED
);
696 // Should be able to decode with latest key.
697 ASSERT_NO_FATAL_FAILURE(
698 DecryptAndExpect(encrypted_buffer
, original_data_
, SUCCESS
));
701 TEST_F(AesDecryptorTest
, LatestKeyUsedAfterCloseSession
) {
702 std::string session_id1
= CreateSession(key_id_
);
703 scoped_refptr
<DecoderBuffer
> encrypted_buffer
= CreateEncryptedBuffer(
704 encrypted_data_
, key_id_
, iv_
, no_subsample_entries_
);
705 UpdateSessionAndExpect(session_id1
, kKeyAsJWK
, RESOLVED
);
706 ASSERT_NO_FATAL_FAILURE(
707 DecryptAndExpect(encrypted_buffer
, original_data_
, SUCCESS
));
709 // Create a second session with a different key value for key_id_.
710 std::string session_id2
= CreateSession(key_id_
);
711 UpdateSessionAndExpect(session_id2
, kKeyAlternateAsJWK
, RESOLVED
);
713 // Should not be able to decode with new key.
714 ASSERT_NO_FATAL_FAILURE(
715 DecryptAndExpect(encrypted_buffer
, original_data_
, DATA_MISMATCH
));
717 // Close second session, should revert to original key.
718 CloseSession(session_id2
);
719 ASSERT_NO_FATAL_FAILURE(
720 DecryptAndExpect(encrypted_buffer
, original_data_
, SUCCESS
));
723 TEST_F(AesDecryptorTest
, JWKKey
) {
724 std::string session_id
= CreateSession(key_id_
);
726 // Try a simple JWK key (i.e. not in a set)
727 const std::string kJwkSimple
=
730 " \"alg\": \"A128KW\","
731 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
732 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
734 UpdateSessionAndExpect(session_id
, kJwkSimple
, REJECTED
);
736 // Try a key list with multiple entries.
737 const std::string kJwksMultipleEntries
=
742 " \"alg\": \"A128KW\","
743 " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
744 " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
748 " \"alg\": \"A128KW\","
749 " \"kid\": \"JCUmJygpKissLS4vMA\","
750 " \"k\":\"MTIzNDU2Nzg5Ojs8PT4_QA\""
754 UpdateSessionAndExpect(session_id
, kJwksMultipleEntries
, RESOLVED
);
756 // Try a key with no spaces and some \n plus additional fields.
757 const std::string kJwksNoSpaces
=
758 "\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\",\"alg\":\"A128KW\","
759 "\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM\",\"k\":\"GawgguFyGrWKav7AX4VKUg"
760 "\",\"foo\":\"bar\"}]}\n\n";
761 UpdateSessionAndExpect(session_id
, kJwksNoSpaces
, RESOLVED
);
763 // Try some non-ASCII characters.
764 UpdateSessionAndExpect(
765 session_id
, "This is not ASCII due to \xff\xfe\xfd in it.", REJECTED
);
767 // Try a badly formatted key. Assume that the JSON parser is fully tested,
768 // so we won't try a lot of combinations. However, need a test to ensure
769 // that the code doesn't crash if invalid JSON received.
770 UpdateSessionAndExpect(session_id
, "This is not a JSON key.", REJECTED
);
772 // Try passing some valid JSON that is not a dictionary at the top level.
773 UpdateSessionAndExpect(session_id
, "40", REJECTED
);
775 // Try an empty dictionary.
776 UpdateSessionAndExpect(session_id
, "{ }", REJECTED
);
778 // Try an empty 'keys' dictionary.
779 UpdateSessionAndExpect(session_id
, "{ \"keys\": [] }", REJECTED
);
781 // Try with 'keys' not a dictionary.
782 UpdateSessionAndExpect(session_id
, "{ \"keys\":\"1\" }", REJECTED
);
784 // Try with 'keys' a list of integers.
785 UpdateSessionAndExpect(session_id
, "{ \"keys\": [ 1, 2, 3 ] }", REJECTED
);
787 // Try padding(=) at end of 'k' base64 string.
788 const std::string kJwksWithPaddedKey
=
793 " \"alg\": \"A128KW\","
794 " \"kid\": \"AAECAw\","
795 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw==\""
799 UpdateSessionAndExpect(session_id
, kJwksWithPaddedKey
, REJECTED
);
801 // Try padding(=) at end of 'kid' base64 string.
802 const std::string kJwksWithPaddedKeyId
=
807 " \"alg\": \"A128KW\","
808 " \"kid\": \"AAECAw==\","
809 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
813 UpdateSessionAndExpect(session_id
, kJwksWithPaddedKeyId
, REJECTED
);
815 // Try a key with invalid base64 encoding.
816 const std::string kJwksWithInvalidBase64
=
821 " \"alg\": \"A128KW\","
822 " \"kid\": \"!@#$%^&*()\","
823 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
827 UpdateSessionAndExpect(session_id
, kJwksWithInvalidBase64
, REJECTED
);
829 // Try a 3-byte 'kid' where no base64 padding is required.
830 // |kJwksMultipleEntries| above has 2 'kid's that require 1 and 2 padding
831 // bytes. Note that 'k' has to be 16 bytes, so it will always require padding.
832 const std::string kJwksWithNoPadding
=
837 " \"alg\": \"A128KW\","
838 " \"kid\": \"Kiss\","
839 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
843 UpdateSessionAndExpect(session_id
, kJwksWithNoPadding
, RESOLVED
);
846 const std::string kJwksWithEmptyKeyId
=
851 " \"alg\": \"A128KW\","
853 " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
857 UpdateSessionAndExpect(session_id
, kJwksWithEmptyKeyId
, REJECTED
);
858 CloseSession(session_id
);
861 TEST_F(AesDecryptorTest
, GetKeyIds
) {
862 std::vector
<uint8
> key_id1(kKeyId
, kKeyId
+ arraysize(kKeyId
));
863 std::vector
<uint8
> key_id2(kKeyId2
, kKeyId2
+ arraysize(kKeyId2
));
865 std::string session_id
= CreateSession(key_id_
);
866 EXPECT_FALSE(KeysInfoContains(key_id1
));
867 EXPECT_FALSE(KeysInfoContains(key_id2
));
869 // Add 1 key, verify it is returned.
870 UpdateSessionAndExpect(session_id
, kKeyAsJWK
, RESOLVED
);
871 EXPECT_TRUE(KeysInfoContains(key_id1
));
872 EXPECT_FALSE(KeysInfoContains(key_id2
));
874 // Add second key, verify both IDs returned.
875 UpdateSessionAndExpect(session_id
, kKey2AsJWK
, RESOLVED
);
876 EXPECT_TRUE(KeysInfoContains(key_id1
));
877 EXPECT_TRUE(KeysInfoContains(key_id2
));