aes_decryptor_unittest.cc revision f8ee788a64d60abd8f2d742a5fdedde054ecd910
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.
4
5#include <string>
6#include <vector>
7
8#include "base/basictypes.h"
9#include "base/bind.h"
10#include "media/base/cdm_promise.h"
11#include "media/base/decoder_buffer.h"
12#include "media/base/decrypt_config.h"
13#include "media/base/mock_filters.h"
14#include "media/cdm/aes_decryptor.h"
15#include "testing/gmock/include/gmock/gmock.h"
16#include "testing/gtest/include/gtest/gtest.h"
17
18using ::testing::_;
19using ::testing::Gt;
20using ::testing::IsNull;
21using ::testing::NotNull;
22using ::testing::SaveArg;
23using ::testing::StrNe;
24
25MATCHER(IsEmpty, "") { return arg.empty(); }
26MATCHER(IsNotEmpty, "") { return !arg.empty(); }
27
28class GURL;
29
30namespace media {
31
32const uint8 kOriginalData[] = "Original subsample data.";
33const int kOriginalDataSize = 24;
34
35// In the examples below, 'k'(key) has to be 16 bytes, and will always require
36// 2 bytes of padding. 'kid'(keyid) is variable length, and may require 0, 1,
37// or 2 bytes of padding.
38
39const uint8 kKeyId[] = {
40    // base64 equivalent is AAECAw
41    0x00, 0x01, 0x02, 0x03
42};
43
44// Key is 0x0405060708090a0b0c0d0e0f10111213,
45// base64 equivalent is BAUGBwgJCgsMDQ4PEBESEw.
46const char kKeyAsJWK[] =
47    "{"
48    "  \"keys\": ["
49    "    {"
50    "      \"kty\": \"oct\","
51    "      \"kid\": \"AAECAw\","
52    "      \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
53    "    }"
54    "  ]"
55    "}";
56
57// Same kid as kKeyAsJWK, key to decrypt kEncryptedData2
58const char kKeyAlternateAsJWK[] =
59    "{"
60    "  \"keys\": ["
61    "    {"
62    "      \"kty\": \"oct\","
63    "      \"kid\": \"AAECAw\","
64    "      \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
65    "    }"
66    "  ]"
67    "}";
68
69const char kWrongKeyAsJWK[] =
70    "{"
71    "  \"keys\": ["
72    "    {"
73    "      \"kty\": \"oct\","
74    "      \"kid\": \"AAECAw\","
75    "      \"k\": \"7u7u7u7u7u7u7u7u7u7u7g\""
76    "    }"
77    "  ]"
78    "}";
79
80const char kWrongSizedKeyAsJWK[] =
81    "{"
82    "  \"keys\": ["
83    "    {"
84    "      \"kty\": \"oct\","
85    "      \"kid\": \"AAECAw\","
86    "      \"k\": \"AAECAw\""
87    "    }"
88    "  ]"
89    "}";
90
91const uint8 kIv[] = {
92  0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
93  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
94};
95
96// kOriginalData encrypted with kKey and kIv but without any subsamples (or
97// equivalently using kSubsampleEntriesCypherOnly).
98const uint8 kEncryptedData[] = {
99  0x2f, 0x03, 0x09, 0xef, 0x71, 0xaf, 0x31, 0x16,
100  0xfa, 0x9d, 0x18, 0x43, 0x1e, 0x96, 0x71, 0xb5,
101  0xbf, 0xf5, 0x30, 0x53, 0x9a, 0x20, 0xdf, 0x95
102};
103
104// kOriginalData encrypted with kSubsampleKey and kSubsampleIv using
105// kSubsampleEntriesNormal.
106const uint8 kSubsampleEncryptedData[] = {
107  0x4f, 0x72, 0x09, 0x16, 0x09, 0xe6, 0x79, 0xad,
108  0x70, 0x73, 0x75, 0x62, 0x09, 0xbb, 0x83, 0x1d,
109  0x4d, 0x08, 0xd7, 0x78, 0xa4, 0xa7, 0xf1, 0x2e
110};
111
112const uint8 kOriginalData2[] = "Changed Original data.";
113
114const uint8 kIv2[] = {
115  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116  0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
117};
118
119const uint8 kKeyId2[] = {
120    // base64 equivalent is AAECAwQFBgcICQoLDA0ODxAREhM=
121    0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
122    0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
123    0x10, 0x11, 0x12, 0x13
124};
125
126const char kKey2AsJWK[] =
127    "{"
128    "  \"keys\": ["
129    "    {"
130    "      \"kty\": \"oct\","
131    "      \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
132    "      \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
133    "    }"
134    "  ]"
135    "}";
136
137// 'k' in bytes is x14x15x16x17x18x19x1ax1bx1cx1dx1ex1fx20x21x22x23
138
139const uint8 kEncryptedData2[] = {
140  0x57, 0x66, 0xf4, 0x12, 0x1a, 0xed, 0xb5, 0x79,
141  0x1c, 0x8e, 0x25, 0xd7, 0x17, 0xe7, 0x5e, 0x16,
142  0xe3, 0x40, 0x08, 0x27, 0x11, 0xe9
143};
144
145// Subsample entries for testing. The sum of |cypher_bytes| and |clear_bytes| of
146// all entries must be equal to kOriginalDataSize to make the subsample entries
147// valid.
148
149const SubsampleEntry kSubsampleEntriesNormal[] = {
150  { 2, 7 },
151  { 3, 11 },
152  { 1, 0 }
153};
154
155const SubsampleEntry kSubsampleEntriesWrongSize[] = {
156  { 3, 6 }, // This entry doesn't match the correct entry.
157  { 3, 11 },
158  { 1, 0 }
159};
160
161const SubsampleEntry kSubsampleEntriesInvalidTotalSize[] = {
162  { 1, 1000 }, // This entry is too large.
163  { 3, 11 },
164  { 1, 0 }
165};
166
167const SubsampleEntry kSubsampleEntriesClearOnly[] = {
168  { 7, 0 },
169  { 8, 0 },
170  { 9, 0 }
171};
172
173const SubsampleEntry kSubsampleEntriesCypherOnly[] = {
174  { 0, 6 },
175  { 0, 8 },
176  { 0, 10 }
177};
178
179static scoped_refptr<DecoderBuffer> CreateEncryptedBuffer(
180    const std::vector<uint8>& data,
181    const std::vector<uint8>& key_id,
182    const std::vector<uint8>& iv,
183    const std::vector<SubsampleEntry>& subsample_entries) {
184  DCHECK(!data.empty());
185  scoped_refptr<DecoderBuffer> encrypted_buffer(new DecoderBuffer(data.size()));
186  memcpy(encrypted_buffer->writable_data(), &data[0], data.size());
187  CHECK(encrypted_buffer.get());
188  std::string key_id_string(
189      reinterpret_cast<const char*>(key_id.empty() ? NULL : &key_id[0]),
190      key_id.size());
191  std::string iv_string(
192      reinterpret_cast<const char*>(iv.empty() ? NULL : &iv[0]), iv.size());
193  encrypted_buffer->set_decrypt_config(scoped_ptr<DecryptConfig>(
194      new DecryptConfig(key_id_string, iv_string, subsample_entries)));
195  return encrypted_buffer;
196}
197
198enum PromiseResult { RESOLVED, REJECTED };
199
200class AesDecryptorTest : public testing::Test {
201 public:
202  AesDecryptorTest()
203      : decryptor_(base::Bind(&AesDecryptorTest::OnSessionMessage,
204                              base::Unretained(this)),
205                   base::Bind(&AesDecryptorTest::OnSessionClosed,
206                              base::Unretained(this))),
207        decrypt_cb_(base::Bind(&AesDecryptorTest::BufferDecrypted,
208                               base::Unretained(this))),
209        original_data_(kOriginalData, kOriginalData + kOriginalDataSize),
210        encrypted_data_(kEncryptedData,
211                        kEncryptedData + arraysize(kEncryptedData)),
212        subsample_encrypted_data_(
213            kSubsampleEncryptedData,
214            kSubsampleEncryptedData + arraysize(kSubsampleEncryptedData)),
215        key_id_(kKeyId, kKeyId + arraysize(kKeyId)),
216        iv_(kIv, kIv + arraysize(kIv)),
217        normal_subsample_entries_(
218            kSubsampleEntriesNormal,
219            kSubsampleEntriesNormal + arraysize(kSubsampleEntriesNormal)) {
220  }
221
222 protected:
223  void OnResolveWithSession(PromiseResult expected,
224                            const std::string& web_session_id) {
225    EXPECT_EQ(expected, RESOLVED);
226    EXPECT_GT(web_session_id.length(), 0ul);
227    web_session_id_ = web_session_id;
228  }
229
230  void OnResolve(PromiseResult expected) {
231    EXPECT_EQ(expected, RESOLVED);
232  }
233
234  void OnReject(PromiseResult expected,
235                MediaKeys::Exception exception_code,
236                uint32 system_code,
237                const std::string& error_message) {
238    EXPECT_EQ(expected, REJECTED);
239  }
240
241  scoped_ptr<SimpleCdmPromise> CreatePromise(PromiseResult expected) {
242    scoped_ptr<SimpleCdmPromise> promise(new SimpleCdmPromise(
243        base::Bind(
244            &AesDecryptorTest::OnResolve, base::Unretained(this), expected),
245        base::Bind(
246            &AesDecryptorTest::OnReject, base::Unretained(this), expected)));
247    return promise.Pass();
248  }
249
250  scoped_ptr<NewSessionCdmPromise> CreateSessionPromise(
251      PromiseResult expected) {
252    scoped_ptr<NewSessionCdmPromise> promise(new NewSessionCdmPromise(
253        base::Bind(&AesDecryptorTest::OnResolveWithSession,
254                   base::Unretained(this),
255                   expected),
256        base::Bind(
257            &AesDecryptorTest::OnReject, base::Unretained(this), expected)));
258    return promise.Pass();
259  }
260
261  // Creates a new session using |key_id|. Returns the session ID.
262  std::string CreateSession(const std::vector<uint8>& key_id) {
263    DCHECK(!key_id.empty());
264    EXPECT_CALL(*this,
265                OnSessionMessage(IsNotEmpty(), key_id, GURL::EmptyGURL()));
266    decryptor_.CreateSession(std::string(),
267                             &key_id[0],
268                             key_id.size(),
269                             MediaKeys::TEMPORARY_SESSION,
270                             CreateSessionPromise(RESOLVED));
271    // This expects the promise to be called synchronously, which is the case
272    // for AesDecryptor.
273    return web_session_id_;
274  }
275
276  // Releases the session specified by |session_id|.
277  void ReleaseSession(const std::string& session_id) {
278    EXPECT_CALL(*this, OnSessionClosed(session_id));
279    decryptor_.ReleaseSession(session_id, CreatePromise(RESOLVED));
280  }
281
282  // Updates the session specified by |session_id| with |key|. |result|
283  // tests that the update succeeds or generates an error.
284  void UpdateSessionAndExpect(std::string session_id,
285                              const std::string& key,
286                              PromiseResult result) {
287    DCHECK(!key.empty());
288
289    decryptor_.UpdateSession(session_id,
290                             reinterpret_cast<const uint8*>(key.c_str()),
291                             key.length(),
292                             CreatePromise(result));
293  }
294
295  MOCK_METHOD2(BufferDecrypted, void(Decryptor::Status,
296                                     const scoped_refptr<DecoderBuffer>&));
297
298  enum DecryptExpectation {
299    SUCCESS,
300    DATA_MISMATCH,
301    DATA_AND_SIZE_MISMATCH,
302    DECRYPT_ERROR,
303    NO_KEY
304  };
305
306  void DecryptAndExpect(const scoped_refptr<DecoderBuffer>& encrypted,
307                        const std::vector<uint8>& plain_text,
308                        DecryptExpectation result) {
309    scoped_refptr<DecoderBuffer> decrypted;
310
311    switch (result) {
312      case SUCCESS:
313      case DATA_MISMATCH:
314      case DATA_AND_SIZE_MISMATCH:
315        EXPECT_CALL(*this, BufferDecrypted(Decryptor::kSuccess, NotNull()))
316            .WillOnce(SaveArg<1>(&decrypted));
317        break;
318      case DECRYPT_ERROR:
319        EXPECT_CALL(*this, BufferDecrypted(Decryptor::kError, IsNull()))
320            .WillOnce(SaveArg<1>(&decrypted));
321        break;
322      case NO_KEY:
323        EXPECT_CALL(*this, BufferDecrypted(Decryptor::kNoKey, IsNull()))
324            .WillOnce(SaveArg<1>(&decrypted));
325        break;
326    }
327
328    decryptor_.Decrypt(Decryptor::kVideo, encrypted, decrypt_cb_);
329
330    std::vector<uint8> decrypted_text;
331    if (decrypted && decrypted->data_size()) {
332      decrypted_text.assign(
333        decrypted->data(), decrypted->data() + decrypted->data_size());
334    }
335
336    switch (result) {
337      case SUCCESS:
338        EXPECT_EQ(plain_text, decrypted_text);
339        break;
340      case DATA_MISMATCH:
341        EXPECT_EQ(plain_text.size(), decrypted_text.size());
342        EXPECT_NE(plain_text, decrypted_text);
343        break;
344      case DATA_AND_SIZE_MISMATCH:
345        EXPECT_NE(plain_text.size(), decrypted_text.size());
346        break;
347      case DECRYPT_ERROR:
348      case NO_KEY:
349        EXPECT_TRUE(decrypted_text.empty());
350        break;
351    }
352  }
353
354  MOCK_METHOD3(OnSessionMessage,
355               void(const std::string& web_session_id,
356                    const std::vector<uint8>& message,
357                    const GURL& destination_url));
358  MOCK_METHOD1(OnSessionClosed, void(const std::string& web_session_id));
359
360  AesDecryptor decryptor_;
361  AesDecryptor::DecryptCB decrypt_cb_;
362  std::string web_session_id_;
363
364  // Constants for testing.
365  const std::vector<uint8> original_data_;
366  const std::vector<uint8> encrypted_data_;
367  const std::vector<uint8> subsample_encrypted_data_;
368  const std::vector<uint8> key_id_;
369  const std::vector<uint8> iv_;
370  const std::vector<SubsampleEntry> normal_subsample_entries_;
371  const std::vector<SubsampleEntry> no_subsample_entries_;
372};
373
374TEST_F(AesDecryptorTest, CreateSessionWithNullInitData) {
375  EXPECT_CALL(*this,
376              OnSessionMessage(IsNotEmpty(), IsEmpty(), GURL::EmptyGURL()));
377  decryptor_.CreateSession(std::string(),
378                           NULL,
379                           0,
380                           MediaKeys::TEMPORARY_SESSION,
381                           CreateSessionPromise(RESOLVED));
382}
383
384TEST_F(AesDecryptorTest, MultipleCreateSession) {
385  EXPECT_CALL(*this,
386              OnSessionMessage(IsNotEmpty(), IsEmpty(), GURL::EmptyGURL()));
387  decryptor_.CreateSession(std::string(),
388                           NULL,
389                           0,
390                           MediaKeys::TEMPORARY_SESSION,
391                           CreateSessionPromise(RESOLVED));
392
393  EXPECT_CALL(*this,
394              OnSessionMessage(IsNotEmpty(), IsEmpty(), GURL::EmptyGURL()));
395  decryptor_.CreateSession(std::string(),
396                           NULL,
397                           0,
398                           MediaKeys::TEMPORARY_SESSION,
399                           CreateSessionPromise(RESOLVED));
400
401  EXPECT_CALL(*this,
402              OnSessionMessage(IsNotEmpty(), IsEmpty(), GURL::EmptyGURL()));
403  decryptor_.CreateSession(std::string(),
404                           NULL,
405                           0,
406                           MediaKeys::TEMPORARY_SESSION,
407                           CreateSessionPromise(RESOLVED));
408}
409
410TEST_F(AesDecryptorTest, NormalDecryption) {
411  std::string session_id = CreateSession(key_id_);
412  UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
413  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
414      encrypted_data_, key_id_, iv_, no_subsample_entries_);
415  DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
416}
417
418TEST_F(AesDecryptorTest, UnencryptedFrame) {
419  // An empty iv string signals that the frame is unencrypted.
420  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
421      original_data_, key_id_, std::vector<uint8>(), no_subsample_entries_);
422  DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
423}
424
425TEST_F(AesDecryptorTest, WrongKey) {
426  std::string session_id = CreateSession(key_id_);
427  UpdateSessionAndExpect(session_id, kWrongKeyAsJWK, RESOLVED);
428  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
429      encrypted_data_, key_id_, iv_, no_subsample_entries_);
430  DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
431}
432
433TEST_F(AesDecryptorTest, NoKey) {
434  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
435      encrypted_data_, key_id_, iv_, no_subsample_entries_);
436  EXPECT_CALL(*this, BufferDecrypted(AesDecryptor::kNoKey, IsNull()));
437  decryptor_.Decrypt(Decryptor::kVideo, encrypted_buffer, decrypt_cb_);
438}
439
440TEST_F(AesDecryptorTest, KeyReplacement) {
441  std::string session_id = CreateSession(key_id_);
442  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
443      encrypted_data_, key_id_, iv_, no_subsample_entries_);
444
445  UpdateSessionAndExpect(session_id, kWrongKeyAsJWK, RESOLVED);
446  ASSERT_NO_FATAL_FAILURE(DecryptAndExpect(
447      encrypted_buffer, original_data_, DATA_MISMATCH));
448
449  UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
450  ASSERT_NO_FATAL_FAILURE(
451      DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
452}
453
454TEST_F(AesDecryptorTest, WrongSizedKey) {
455  std::string session_id = CreateSession(key_id_);
456  UpdateSessionAndExpect(session_id, kWrongSizedKeyAsJWK, REJECTED);
457}
458
459TEST_F(AesDecryptorTest, MultipleKeysAndFrames) {
460  std::string session_id = CreateSession(key_id_);
461  UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
462  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
463      encrypted_data_, key_id_, iv_, no_subsample_entries_);
464  ASSERT_NO_FATAL_FAILURE(
465      DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
466
467  UpdateSessionAndExpect(session_id, kKey2AsJWK, RESOLVED);
468
469  // The first key is still available after we added a second key.
470  ASSERT_NO_FATAL_FAILURE(
471      DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
472
473  // The second key is also available.
474  encrypted_buffer = CreateEncryptedBuffer(
475      std::vector<uint8>(kEncryptedData2,
476                         kEncryptedData2 + arraysize(kEncryptedData2)),
477      std::vector<uint8>(kKeyId2, kKeyId2 + arraysize(kKeyId2)),
478      std::vector<uint8>(kIv2, kIv2 + arraysize(kIv2)),
479      no_subsample_entries_);
480  ASSERT_NO_FATAL_FAILURE(DecryptAndExpect(
481      encrypted_buffer,
482      std::vector<uint8>(kOriginalData2,
483                         kOriginalData2 + arraysize(kOriginalData2) - 1),
484      SUCCESS));
485}
486
487TEST_F(AesDecryptorTest, CorruptedIv) {
488  std::string session_id = CreateSession(key_id_);
489  UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
490
491  std::vector<uint8> bad_iv = iv_;
492  bad_iv[1]++;
493
494  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
495      encrypted_data_, key_id_, bad_iv, no_subsample_entries_);
496
497  DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
498}
499
500TEST_F(AesDecryptorTest, CorruptedData) {
501  std::string session_id = CreateSession(key_id_);
502  UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
503
504  std::vector<uint8> bad_data = encrypted_data_;
505  bad_data[1]++;
506
507  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
508      bad_data, key_id_, iv_, no_subsample_entries_);
509  DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
510}
511
512TEST_F(AesDecryptorTest, EncryptedAsUnencryptedFailure) {
513  std::string session_id = CreateSession(key_id_);
514  UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
515  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
516      encrypted_data_, key_id_, std::vector<uint8>(), no_subsample_entries_);
517  DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
518}
519
520TEST_F(AesDecryptorTest, SubsampleDecryption) {
521  std::string session_id = CreateSession(key_id_);
522  UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
523  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
524      subsample_encrypted_data_, key_id_, iv_, normal_subsample_entries_);
525  DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
526}
527
528// Ensures noninterference of data offset and subsample mechanisms. We never
529// expect to encounter this in the wild, but since the DecryptConfig doesn't
530// disallow such a configuration, it should be covered.
531TEST_F(AesDecryptorTest, SubsampleDecryptionWithOffset) {
532  std::string session_id = CreateSession(key_id_);
533  UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
534  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
535      subsample_encrypted_data_, key_id_, iv_, normal_subsample_entries_);
536  DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
537}
538
539TEST_F(AesDecryptorTest, SubsampleWrongSize) {
540  std::string session_id = CreateSession(key_id_);
541  UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
542
543  std::vector<SubsampleEntry> subsample_entries_wrong_size(
544      kSubsampleEntriesWrongSize,
545      kSubsampleEntriesWrongSize + arraysize(kSubsampleEntriesWrongSize));
546
547  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
548      subsample_encrypted_data_, key_id_, iv_, subsample_entries_wrong_size);
549  DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
550}
551
552TEST_F(AesDecryptorTest, SubsampleInvalidTotalSize) {
553  std::string session_id = CreateSession(key_id_);
554  UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
555
556  std::vector<SubsampleEntry> subsample_entries_invalid_total_size(
557      kSubsampleEntriesInvalidTotalSize,
558      kSubsampleEntriesInvalidTotalSize +
559          arraysize(kSubsampleEntriesInvalidTotalSize));
560
561  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
562      subsample_encrypted_data_, key_id_, iv_,
563      subsample_entries_invalid_total_size);
564  DecryptAndExpect(encrypted_buffer, original_data_, DECRYPT_ERROR);
565}
566
567// No cypher bytes in any of the subsamples.
568TEST_F(AesDecryptorTest, SubsampleClearBytesOnly) {
569  std::string session_id = CreateSession(key_id_);
570  UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
571
572  std::vector<SubsampleEntry> clear_only_subsample_entries(
573      kSubsampleEntriesClearOnly,
574      kSubsampleEntriesClearOnly + arraysize(kSubsampleEntriesClearOnly));
575
576  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
577      original_data_, key_id_, iv_, clear_only_subsample_entries);
578  DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
579}
580
581// No clear bytes in any of the subsamples.
582TEST_F(AesDecryptorTest, SubsampleCypherBytesOnly) {
583  std::string session_id = CreateSession(key_id_);
584  UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
585
586  std::vector<SubsampleEntry> cypher_only_subsample_entries(
587      kSubsampleEntriesCypherOnly,
588      kSubsampleEntriesCypherOnly + arraysize(kSubsampleEntriesCypherOnly));
589
590  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
591      encrypted_data_, key_id_, iv_, cypher_only_subsample_entries);
592  DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
593}
594
595TEST_F(AesDecryptorTest, ReleaseSession) {
596  std::string session_id = CreateSession(key_id_);
597  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
598      encrypted_data_, key_id_, iv_, no_subsample_entries_);
599
600  UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
601  ASSERT_NO_FATAL_FAILURE(
602      DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
603
604  ReleaseSession(session_id);
605}
606
607TEST_F(AesDecryptorTest, NoKeyAfterReleaseSession) {
608  std::string session_id = CreateSession(key_id_);
609  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
610      encrypted_data_, key_id_, iv_, no_subsample_entries_);
611
612  UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED);
613  ASSERT_NO_FATAL_FAILURE(
614      DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
615
616  ReleaseSession(session_id);
617  ASSERT_NO_FATAL_FAILURE(
618      DecryptAndExpect(encrypted_buffer, original_data_, NO_KEY));
619}
620
621TEST_F(AesDecryptorTest, LatestKeyUsed) {
622  std::string session_id1 = CreateSession(key_id_);
623  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
624      encrypted_data_, key_id_, iv_, no_subsample_entries_);
625
626  // Add alternate key, buffer should not be decoded properly.
627  UpdateSessionAndExpect(session_id1, kKeyAlternateAsJWK, RESOLVED);
628  ASSERT_NO_FATAL_FAILURE(
629      DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH));
630
631  // Create a second session with a correct key value for key_id_.
632  std::string session_id2 = CreateSession(key_id_);
633  UpdateSessionAndExpect(session_id2, kKeyAsJWK, RESOLVED);
634
635  // Should be able to decode with latest key.
636  ASSERT_NO_FATAL_FAILURE(
637      DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
638}
639
640TEST_F(AesDecryptorTest, LatestKeyUsedAfterReleaseSession) {
641  std::string session_id1 = CreateSession(key_id_);
642  scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
643      encrypted_data_, key_id_, iv_, no_subsample_entries_);
644  UpdateSessionAndExpect(session_id1, kKeyAsJWK, RESOLVED);
645  ASSERT_NO_FATAL_FAILURE(
646      DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
647
648  // Create a second session with a different key value for key_id_.
649  std::string session_id2 = CreateSession(key_id_);
650  UpdateSessionAndExpect(session_id2, kKeyAlternateAsJWK, RESOLVED);
651
652  // Should not be able to decode with new key.
653  ASSERT_NO_FATAL_FAILURE(
654      DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH));
655
656  // Close second session, should revert to original key.
657  ReleaseSession(session_id2);
658  ASSERT_NO_FATAL_FAILURE(
659      DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
660}
661
662TEST_F(AesDecryptorTest, JWKKey) {
663  std::string session_id = CreateSession(key_id_);
664
665  // Try a simple JWK key (i.e. not in a set)
666  const std::string kJwkSimple =
667      "{"
668      "  \"kty\": \"oct\","
669      "  \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
670      "  \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
671      "}";
672  UpdateSessionAndExpect(session_id, kJwkSimple, REJECTED);
673
674  // Try a key list with multiple entries.
675  const std::string kJwksMultipleEntries =
676      "{"
677      "  \"keys\": ["
678      "    {"
679      "      \"kty\": \"oct\","
680      "      \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
681      "      \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
682      "    },"
683      "    {"
684      "      \"kty\": \"oct\","
685      "      \"kid\": \"JCUmJygpKissLS4vMA\","
686      "      \"k\":\"MTIzNDU2Nzg5Ojs8PT4/QA\""
687      "    }"
688      "  ]"
689      "}";
690  UpdateSessionAndExpect(session_id, kJwksMultipleEntries, RESOLVED);
691
692  // Try a key with no spaces and some \n plus additional fields.
693  const std::string kJwksNoSpaces =
694      "\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\",\"alg\":\"A128KW\","
695      "\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM\",\"k\":\"GawgguFyGrWKav7AX4VKUg"
696      "\",\"foo\":\"bar\"}]}\n\n";
697  UpdateSessionAndExpect(session_id, kJwksNoSpaces, RESOLVED);
698
699  // Try some non-ASCII characters.
700  UpdateSessionAndExpect(
701      session_id, "This is not ASCII due to \xff\xfe\xfd in it.", REJECTED);
702
703  // Try a badly formatted key. Assume that the JSON parser is fully tested,
704  // so we won't try a lot of combinations. However, need a test to ensure
705  // that the code doesn't crash if invalid JSON received.
706  UpdateSessionAndExpect(session_id, "This is not a JSON key.", REJECTED);
707
708  // Try passing some valid JSON that is not a dictionary at the top level.
709  UpdateSessionAndExpect(session_id, "40", REJECTED);
710
711  // Try an empty dictionary.
712  UpdateSessionAndExpect(session_id, "{ }", REJECTED);
713
714  // Try an empty 'keys' dictionary.
715  UpdateSessionAndExpect(session_id, "{ \"keys\": [] }", REJECTED);
716
717  // Try with 'keys' not a dictionary.
718  UpdateSessionAndExpect(session_id, "{ \"keys\":\"1\" }", REJECTED);
719
720  // Try with 'keys' a list of integers.
721  UpdateSessionAndExpect(session_id, "{ \"keys\": [ 1, 2, 3 ] }", REJECTED);
722
723  // Try padding(=) at end of 'k' base64 string.
724  const std::string kJwksWithPaddedKey =
725      "{"
726      "  \"keys\": ["
727      "    {"
728      "      \"kty\": \"oct\","
729      "      \"kid\": \"AAECAw\","
730      "      \"k\": \"BAUGBwgJCgsMDQ4PEBESEw==\""
731      "    }"
732      "  ]"
733      "}";
734  UpdateSessionAndExpect(session_id, kJwksWithPaddedKey, REJECTED);
735
736  // Try padding(=) at end of 'kid' base64 string.
737  const std::string kJwksWithPaddedKeyId =
738      "{"
739      "  \"keys\": ["
740      "    {"
741      "      \"kty\": \"oct\","
742      "      \"kid\": \"AAECAw==\","
743      "      \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
744      "    }"
745      "  ]"
746      "}";
747  UpdateSessionAndExpect(session_id, kJwksWithPaddedKeyId, REJECTED);
748
749  // Try a key with invalid base64 encoding.
750  const std::string kJwksWithInvalidBase64 =
751      "{"
752      "  \"keys\": ["
753      "    {"
754      "      \"kty\": \"oct\","
755      "      \"kid\": \"!@#$%^&*()\","
756      "      \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
757      "    }"
758      "  ]"
759      "}";
760  UpdateSessionAndExpect(session_id, kJwksWithInvalidBase64, REJECTED);
761
762  // Try a 3-byte 'kid' where no base64 padding is required.
763  // |kJwksMultipleEntries| above has 2 'kid's that require 1 and 2 padding
764  // bytes. Note that 'k' has to be 16 bytes, so it will always require padding.
765  const std::string kJwksWithNoPadding =
766      "{"
767      "  \"keys\": ["
768      "    {"
769      "      \"kty\": \"oct\","
770      "      \"kid\": \"Kiss\","
771      "      \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
772      "    }"
773      "  ]"
774      "}";
775  UpdateSessionAndExpect(session_id, kJwksWithNoPadding, RESOLVED);
776
777  // Empty key id.
778  const std::string kJwksWithEmptyKeyId =
779      "{"
780      "  \"keys\": ["
781      "    {"
782      "      \"kty\": \"oct\","
783      "      \"kid\": \"\","
784      "      \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
785      "    }"
786      "  ]"
787      "}";
788  UpdateSessionAndExpect(session_id, kJwksWithEmptyKeyId, REJECTED);
789  ReleaseSession(session_id);
790}
791
792}  // namespace media
793