summaryrefslogtreecommitdiff
path: root/chromium/media/cdm/aes_decryptor_unittest.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/cdm/aes_decryptor_unittest.cc')
-rw-r--r--chromium/media/cdm/aes_decryptor_unittest.cc482
1 files changed, 307 insertions, 175 deletions
diff --git a/chromium/media/cdm/aes_decryptor_unittest.cc b/chromium/media/cdm/aes_decryptor_unittest.cc
index a4b865c4690..3076d5a3f2e 100644
--- a/chromium/media/cdm/aes_decryptor_unittest.cc
+++ b/chromium/media/cdm/aes_decryptor_unittest.cc
@@ -26,63 +26,73 @@ MATCHER(IsEmpty, "") { return arg.empty(); }
namespace media {
-static const char kClearKeySystem[] = "org.w3.clearkey";
+const uint8 kOriginalData[] = "Original subsample data.";
+const int kOriginalDataSize = 24;
-static const uint8 kOriginalData[] = "Original subsample data.";
-static const int kOriginalDataSize = 24;
+// In the examples below, 'k'(key) has to be 16 bytes, and will always require
+// 2 bytes of padding. 'kid'(keyid) is variable length, and may require 0, 1,
+// or 2 bytes of padding.
-static const uint8 kKeyId[] = {
- // base64 equivalent is AAECAw==
+const uint8 kKeyId[] = {
+ // base64 equivalent is AAECAw
0x00, 0x01, 0x02, 0x03
};
-static const uint8 kKey[] = {
- // base64 equivalent is BAUGBwgJCgsMDQ4PEBESEw==
- 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
- 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13
-};
+// Key is 0x0405060708090a0b0c0d0e0f10111213,
+// base64 equivalent is BAUGBwgJCgsMDQ4PEBESEw.
+const char kKeyAsJWK[] =
+ "{"
+ " \"keys\": ["
+ " {"
+ " \"kty\": \"oct\","
+ " \"kid\": \"AAECAw\","
+ " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
+ " }"
+ " ]"
+ "}";
-static const char kKeyAsJWK[] =
+// Same kid as kKeyAsJWK, key to decrypt kEncryptedData2
+const char kKeyAlternateAsJWK[] =
"{"
" \"keys\": ["
" {"
" \"kty\": \"oct\","
- " \"kid\": \"AAECAw==\","
- " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw==\""
+ " \"kid\": \"AAECAw\","
+ " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
" }"
" ]"
"}";
-static const char kWrongKeyAsJWK[] =
+const char kWrongKeyAsJWK[] =
"{"
" \"keys\": ["
" {"
" \"kty\": \"oct\","
- " \"kid\": \"AAECAw==\","
- " \"k\": \"7u7u7u7u7u7u7u7u7u7u7g==\""
+ " \"kid\": \"AAECAw\","
+ " \"k\": \"7u7u7u7u7u7u7u7u7u7u7g\""
" }"
" ]"
"}";
-static const char kWrongSizedKeyAsJWK[] =
+const char kWrongSizedKeyAsJWK[] =
"{"
" \"keys\": ["
" {"
" \"kty\": \"oct\","
- " \"kid\": \"AAECAw==\","
- " \"k\": \"AAECAw==\""
+ " \"kid\": \"AAECAw\","
+ " \"k\": \"AAECAw\""
" }"
" ]"
"}";
-static const uint8 kIv[] = {
+const uint8 kIv[] = {
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
// kOriginalData encrypted with kKey and kIv but without any subsamples (or
// equivalently using kSubsampleEntriesCypherOnly).
-static const uint8 kEncryptedData[] = {
+const uint8 kEncryptedData[] = {
0x2f, 0x03, 0x09, 0xef, 0x71, 0xaf, 0x31, 0x16,
0xfa, 0x9d, 0x18, 0x43, 0x1e, 0x96, 0x71, 0xb5,
0xbf, 0xf5, 0x30, 0x53, 0x9a, 0x20, 0xdf, 0x95
@@ -90,40 +100,40 @@ static const uint8 kEncryptedData[] = {
// kOriginalData encrypted with kSubsampleKey and kSubsampleIv using
// kSubsampleEntriesNormal.
-static const uint8 kSubsampleEncryptedData[] = {
+const uint8 kSubsampleEncryptedData[] = {
0x4f, 0x72, 0x09, 0x16, 0x09, 0xe6, 0x79, 0xad,
0x70, 0x73, 0x75, 0x62, 0x09, 0xbb, 0x83, 0x1d,
0x4d, 0x08, 0xd7, 0x78, 0xa4, 0xa7, 0xf1, 0x2e
};
-static const uint8 kOriginalData2[] = "Changed Original data.";
+const uint8 kOriginalData2[] = "Changed Original data.";
-static const uint8 kIv2[] = {
+const uint8 kIv2[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
-static const uint8 kKeyId2[] = {
+const uint8 kKeyId2[] = {
// base64 equivalent is AAECAwQFBgcICQoLDA0ODxAREhM=
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
0x10, 0x11, 0x12, 0x13
};
-static const char kKey2AsJWK[] =
+const char kKey2AsJWK[] =
"{"
" \"keys\": ["
" {"
" \"kty\": \"oct\","
- " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM=\","
- " \"k\": \"FBUWFxgZGhscHR4fICEiIw==\""
+ " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
+ " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
" }"
" ]"
"}";
// 'k' in bytes is x14x15x16x17x18x19x1ax1bx1cx1dx1ex1fx20x21x22x23
-static const uint8 kEncryptedData2[] = {
+const uint8 kEncryptedData2[] = {
0x57, 0x66, 0xf4, 0x12, 0x1a, 0xed, 0xb5, 0x79,
0x1c, 0x8e, 0x25, 0xd7, 0x17, 0xe7, 0x5e, 0x16,
0xe3, 0x40, 0x08, 0x27, 0x11, 0xe9
@@ -133,31 +143,31 @@ static const uint8 kEncryptedData2[] = {
// all entries must be equal to kOriginalDataSize to make the subsample entries
// valid.
-static const SubsampleEntry kSubsampleEntriesNormal[] = {
+const SubsampleEntry kSubsampleEntriesNormal[] = {
{ 2, 7 },
{ 3, 11 },
{ 1, 0 }
};
-static const SubsampleEntry kSubsampleEntriesWrongSize[] = {
+const SubsampleEntry kSubsampleEntriesWrongSize[] = {
{ 3, 6 }, // This entry doesn't match the correct entry.
{ 3, 11 },
{ 1, 0 }
};
-static const SubsampleEntry kSubsampleEntriesInvalidTotalSize[] = {
+const SubsampleEntry kSubsampleEntriesInvalidTotalSize[] = {
{ 1, 1000 }, // This entry is too large.
{ 3, 11 },
{ 1, 0 }
};
-static const SubsampleEntry kSubsampleEntriesClearOnly[] = {
+const SubsampleEntry kSubsampleEntriesClearOnly[] = {
{ 7, 0 },
{ 8, 0 },
{ 9, 0 }
};
-static const SubsampleEntry kSubsampleEntriesCypherOnly[] = {
+const SubsampleEntry kSubsampleEntriesCypherOnly[] = {
{ 0, 6 },
{ 0, 8 },
{ 0, 10 }
@@ -187,10 +197,16 @@ static scoped_refptr<DecoderBuffer> CreateEncryptedBuffer(
class AesDecryptorTest : public testing::Test {
public:
AesDecryptorTest()
- : decryptor_(
- base::Bind(&AesDecryptorTest::KeyAdded, base::Unretained(this)),
- base::Bind(&AesDecryptorTest::KeyError, base::Unretained(this)),
- base::Bind(&AesDecryptorTest::KeyMessage, base::Unretained(this))),
+ : decryptor_(base::Bind(&AesDecryptorTest::OnSessionCreated,
+ base::Unretained(this)),
+ base::Bind(&AesDecryptorTest::OnSessionMessage,
+ base::Unretained(this)),
+ base::Bind(&AesDecryptorTest::OnSessionReady,
+ base::Unretained(this)),
+ base::Bind(&AesDecryptorTest::OnSessionClosed,
+ base::Unretained(this)),
+ base::Bind(&AesDecryptorTest::OnSessionError,
+ base::Unretained(this))),
decrypt_cb_(base::Bind(&AesDecryptorTest::BufferDecrypted,
base::Unretained(this))),
original_data_(kOriginalData, kOriginalData + kOriginalDataSize),
@@ -203,58 +219,52 @@ class AesDecryptorTest : public testing::Test {
iv_(kIv, kIv + arraysize(kIv)),
normal_subsample_entries_(
kSubsampleEntriesNormal,
- kSubsampleEntriesNormal + arraysize(kSubsampleEntriesNormal)) {
+ kSubsampleEntriesNormal + arraysize(kSubsampleEntriesNormal)),
+ next_session_id_(1) {
}
protected:
- void GenerateKeyRequest(const std::vector<uint8>& key_id) {
+ // Creates a new session using |key_id|. Returns the session ID.
+ uint32 CreateSession(const std::vector<uint8>& key_id) {
DCHECK(!key_id.empty());
- EXPECT_CALL(*this, KeyMessage(StrNe(std::string()), key_id, ""))
- .WillOnce(SaveArg<0>(&session_id_string_));
- EXPECT_TRUE(decryptor_.GenerateKeyRequest(
- std::string(), &key_id[0], key_id.size()));
+ uint32 session_id = next_session_id_++;
+ EXPECT_CALL(*this, OnSessionCreated(session_id, StrNe(std::string())));
+ EXPECT_CALL(*this, OnSessionMessage(session_id, key_id, ""));
+ EXPECT_TRUE(decryptor_.CreateSession(
+ session_id, std::string(), &key_id[0], key_id.size()));
+ return session_id;
}
- enum AddKeyExpectation {
- KEY_ADDED,
- KEY_ERROR
- };
-
- void AddRawKeyAndExpect(const std::vector<uint8>& key_id,
- const std::vector<uint8>& key,
- AddKeyExpectation result) {
- // TODO(jrummell): Remove once raw keys no longer supported.
- DCHECK(!key_id.empty());
- DCHECK(!key.empty());
-
- if (result == KEY_ADDED) {
- EXPECT_CALL(*this, KeyAdded(session_id_string_));
- } else if (result == KEY_ERROR) {
- EXPECT_CALL(*this, KeyError(session_id_string_,
- MediaKeys::kUnknownError, 0));
- } else {
- NOTREACHED();
- }
-
- decryptor_.AddKey(&key[0], key.size(), &key_id[0], key_id.size(),
- session_id_string_);
+ // Releases the session specified by |session_id|.
+ void ReleaseSession(uint32 session_id) {
+ EXPECT_CALL(*this, OnSessionClosed(session_id));
+ decryptor_.ReleaseSession(session_id);
}
- void AddKeyAndExpect(const std::string& key, AddKeyExpectation result) {
+ enum UpdateSessionExpectation {
+ SESSION_READY,
+ SESSION_ERROR
+ };
+
+ // Updates the session specified by |session_id| with |key|. |result|
+ // tests that the update succeeds or generates an error.
+ void UpdateSessionAndExpect(uint32 session_id,
+ const std::string& key,
+ UpdateSessionExpectation result) {
DCHECK(!key.empty());
- if (result == KEY_ADDED) {
- EXPECT_CALL(*this, KeyAdded(session_id_string_));
- } else if (result == KEY_ERROR) {
- EXPECT_CALL(*this,
- KeyError(session_id_string_, MediaKeys::kUnknownError, 0));
- } else {
- NOTREACHED();
+ switch (result) {
+ case SESSION_READY:
+ EXPECT_CALL(*this, OnSessionReady(session_id));
+ break;
+ case SESSION_ERROR:
+ EXPECT_CALL(*this,
+ OnSessionError(session_id, MediaKeys::kUnknownError, 0));
+ break;
}
- decryptor_.AddKey(reinterpret_cast<const uint8*>(key.c_str()), key.length(),
- NULL, 0,
- session_id_string_);
+ decryptor_.UpdateSession(
+ session_id, reinterpret_cast<const uint8*>(key.c_str()), key.length());
}
MOCK_METHOD2(BufferDecrypted, void(Decryptor::Status,
@@ -264,7 +274,8 @@ class AesDecryptorTest : public testing::Test {
SUCCESS,
DATA_MISMATCH,
DATA_AND_SIZE_MISMATCH,
- DECRYPT_ERROR
+ DECRYPT_ERROR,
+ NO_KEY
};
void DecryptAndExpect(const scoped_refptr<DecoderBuffer>& encrypted,
@@ -272,12 +283,21 @@ class AesDecryptorTest : public testing::Test {
DecryptExpectation result) {
scoped_refptr<DecoderBuffer> decrypted;
- if (result != DECRYPT_ERROR) {
- EXPECT_CALL(*this, BufferDecrypted(Decryptor::kSuccess, NotNull()))
- .WillOnce(SaveArg<1>(&decrypted));
- } else {
- EXPECT_CALL(*this, BufferDecrypted(Decryptor::kError, IsNull()))
- .WillOnce(SaveArg<1>(&decrypted));
+ switch (result) {
+ case SUCCESS:
+ case DATA_MISMATCH:
+ case DATA_AND_SIZE_MISMATCH:
+ EXPECT_CALL(*this, BufferDecrypted(Decryptor::kSuccess, NotNull()))
+ .WillOnce(SaveArg<1>(&decrypted));
+ break;
+ case DECRYPT_ERROR:
+ EXPECT_CALL(*this, BufferDecrypted(Decryptor::kError, IsNull()))
+ .WillOnce(SaveArg<1>(&decrypted));
+ break;
+ case NO_KEY:
+ EXPECT_CALL(*this, BufferDecrypted(Decryptor::kNoKey, IsNull()))
+ .WillOnce(SaveArg<1>(&decrypted));
+ break;
}
decryptor_.Decrypt(Decryptor::kVideo, encrypted, decrypt_cb_);
@@ -300,20 +320,24 @@ class AesDecryptorTest : public testing::Test {
EXPECT_NE(plain_text.size(), decrypted_text.size());
break;
case DECRYPT_ERROR:
+ case NO_KEY:
EXPECT_TRUE(decrypted_text.empty());
break;
}
}
- MOCK_METHOD1(KeyAdded, void(const std::string&));
- MOCK_METHOD3(KeyError, void(const std::string&,
- MediaKeys::KeyError, int));
- MOCK_METHOD3(KeyMessage, void(const std::string& session_id,
- const std::vector<uint8>& message,
- const std::string& default_url));
+ MOCK_METHOD2(OnSessionCreated,
+ void(uint32 session_id, const std::string& web_session_id));
+ MOCK_METHOD3(OnSessionMessage,
+ void(uint32 session_id,
+ const std::vector<uint8>& message,
+ const std::string& default_url));
+ MOCK_METHOD1(OnSessionReady, void(uint32 session_id));
+ MOCK_METHOD1(OnSessionClosed, void(uint32 session_id));
+ MOCK_METHOD3(OnSessionError,
+ void(uint32 session_id, MediaKeys::KeyError, int system_code));
AesDecryptor decryptor_;
- std::string session_id_string_;
AesDecryptor::DecryptCB decrypt_cb_;
// Constants for testing.
@@ -324,24 +348,46 @@ class AesDecryptorTest : public testing::Test {
const std::vector<uint8> iv_;
const std::vector<SubsampleEntry> normal_subsample_entries_;
const std::vector<SubsampleEntry> no_subsample_entries_;
+
+ // Generate new session ID every time
+ uint32 next_session_id_;
};
-TEST_F(AesDecryptorTest, GenerateKeyRequestWithNullInitData) {
- EXPECT_CALL(*this, KeyMessage(StrNe(std::string()), IsEmpty(), ""));
- EXPECT_TRUE(decryptor_.GenerateKeyRequest(std::string(), NULL, 0));
+TEST_F(AesDecryptorTest, CreateSessionWithNullInitData) {
+ uint32 session_id = 8;
+ EXPECT_CALL(*this, OnSessionMessage(session_id, IsEmpty(), ""));
+ EXPECT_CALL(*this, OnSessionCreated(session_id, StrNe(std::string())));
+ EXPECT_TRUE(decryptor_.CreateSession(session_id, std::string(), NULL, 0));
+}
+
+TEST_F(AesDecryptorTest, MultipleCreateSession) {
+ uint32 session_id1 = 10;
+ EXPECT_CALL(*this, OnSessionMessage(session_id1, IsEmpty(), ""));
+ EXPECT_CALL(*this, OnSessionCreated(session_id1, StrNe(std::string())));
+ EXPECT_TRUE(decryptor_.CreateSession(session_id1, std::string(), NULL, 0));
+
+ uint32 session_id2 = 11;
+ EXPECT_CALL(*this, OnSessionMessage(session_id2, IsEmpty(), ""));
+ EXPECT_CALL(*this, OnSessionCreated(session_id2, StrNe(std::string())));
+ EXPECT_TRUE(decryptor_.CreateSession(session_id2, std::string(), NULL, 0));
+
+ uint32 session_id3 = 23;
+ EXPECT_CALL(*this, OnSessionMessage(session_id3, IsEmpty(), ""));
+ EXPECT_CALL(*this, OnSessionCreated(session_id3, StrNe(std::string())));
+ EXPECT_TRUE(decryptor_.CreateSession(session_id3, std::string(), NULL, 0));
}
TEST_F(AesDecryptorTest, NormalDecryption) {
- GenerateKeyRequest(key_id_);
- AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
+ uint32 session_id = CreateSession(key_id_);
+ UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, 0, no_subsample_entries_);
DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
}
TEST_F(AesDecryptorTest, DecryptionWithOffset) {
- GenerateKeyRequest(key_id_);
- AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
+ uint32 session_id = CreateSession(key_id_);
+ UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, 23, no_subsample_entries_);
DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
@@ -355,8 +401,8 @@ TEST_F(AesDecryptorTest, UnencryptedFrame) {
}
TEST_F(AesDecryptorTest, WrongKey) {
- GenerateKeyRequest(key_id_);
- AddKeyAndExpect(kWrongKeyAsJWK, KEY_ADDED);
+ uint32 session_id = CreateSession(key_id_);
+ UpdateSessionAndExpect(session_id, kWrongKeyAsJWK, SESSION_READY);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, 0, no_subsample_entries_);
DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
@@ -370,37 +416,33 @@ TEST_F(AesDecryptorTest, NoKey) {
}
TEST_F(AesDecryptorTest, KeyReplacement) {
- GenerateKeyRequest(key_id_);
+ uint32 session_id = CreateSession(key_id_);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, 0, no_subsample_entries_);
- AddKeyAndExpect(kWrongKeyAsJWK, KEY_ADDED);
+ UpdateSessionAndExpect(session_id, kWrongKeyAsJWK, SESSION_READY);
ASSERT_NO_FATAL_FAILURE(DecryptAndExpect(
encrypted_buffer, original_data_, DATA_MISMATCH));
- AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
+ UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY);
ASSERT_NO_FATAL_FAILURE(
DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
}
TEST_F(AesDecryptorTest, WrongSizedKey) {
- GenerateKeyRequest(key_id_);
- AddKeyAndExpect(kWrongSizedKeyAsJWK, KEY_ERROR);
-
- // Repeat for a raw key. Use "-1" to create a wrong sized key.
- std::vector<uint8> wrong_sized_key(kKey, kKey + arraysize(kKey) - 1);
- AddRawKeyAndExpect(key_id_, wrong_sized_key, KEY_ERROR);
+ uint32 session_id = CreateSession(key_id_);
+ UpdateSessionAndExpect(session_id, kWrongSizedKeyAsJWK, SESSION_ERROR);
}
TEST_F(AesDecryptorTest, MultipleKeysAndFrames) {
- GenerateKeyRequest(key_id_);
- AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
+ uint32 session_id = CreateSession(key_id_);
+ UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, 10, no_subsample_entries_);
ASSERT_NO_FATAL_FAILURE(
DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
- AddKeyAndExpect(kKey2AsJWK, KEY_ADDED);
+ UpdateSessionAndExpect(session_id, kKey2AsJWK, SESSION_READY);
// The first key is still available after we added a second key.
ASSERT_NO_FATAL_FAILURE(
@@ -422,8 +464,8 @@ TEST_F(AesDecryptorTest, MultipleKeysAndFrames) {
}
TEST_F(AesDecryptorTest, CorruptedIv) {
- GenerateKeyRequest(key_id_);
- AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
+ uint32 session_id = CreateSession(key_id_);
+ UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY);
std::vector<uint8> bad_iv = iv_;
bad_iv[1]++;
@@ -435,8 +477,8 @@ TEST_F(AesDecryptorTest, CorruptedIv) {
}
TEST_F(AesDecryptorTest, CorruptedData) {
- GenerateKeyRequest(key_id_);
- AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
+ uint32 session_id = CreateSession(key_id_);
+ UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY);
std::vector<uint8> bad_data = encrypted_data_;
bad_data[1]++;
@@ -447,16 +489,16 @@ TEST_F(AesDecryptorTest, CorruptedData) {
}
TEST_F(AesDecryptorTest, EncryptedAsUnencryptedFailure) {
- GenerateKeyRequest(key_id_);
- AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
+ uint32 session_id = CreateSession(key_id_);
+ UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, std::vector<uint8>(), 0, no_subsample_entries_);
DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
}
TEST_F(AesDecryptorTest, SubsampleDecryption) {
- GenerateKeyRequest(key_id_);
- AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
+ uint32 session_id = CreateSession(key_id_);
+ UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
subsample_encrypted_data_, key_id_, iv_, 0, normal_subsample_entries_);
DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
@@ -466,16 +508,16 @@ TEST_F(AesDecryptorTest, SubsampleDecryption) {
// expect to encounter this in the wild, but since the DecryptConfig doesn't
// disallow such a configuration, it should be covered.
TEST_F(AesDecryptorTest, SubsampleDecryptionWithOffset) {
- GenerateKeyRequest(key_id_);
- AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
+ uint32 session_id = CreateSession(key_id_);
+ UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
subsample_encrypted_data_, key_id_, iv_, 23, normal_subsample_entries_);
DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
}
TEST_F(AesDecryptorTest, SubsampleWrongSize) {
- GenerateKeyRequest(key_id_);
- AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
+ uint32 session_id = CreateSession(key_id_);
+ UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY);
std::vector<SubsampleEntry> subsample_entries_wrong_size(
kSubsampleEntriesWrongSize,
@@ -487,8 +529,8 @@ TEST_F(AesDecryptorTest, SubsampleWrongSize) {
}
TEST_F(AesDecryptorTest, SubsampleInvalidTotalSize) {
- GenerateKeyRequest(key_id_);
- AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
+ uint32 session_id = CreateSession(key_id_);
+ UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY);
std::vector<SubsampleEntry> subsample_entries_invalid_total_size(
kSubsampleEntriesInvalidTotalSize,
@@ -503,8 +545,8 @@ TEST_F(AesDecryptorTest, SubsampleInvalidTotalSize) {
// No cypher bytes in any of the subsamples.
TEST_F(AesDecryptorTest, SubsampleClearBytesOnly) {
- GenerateKeyRequest(key_id_);
- AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
+ uint32 session_id = CreateSession(key_id_);
+ UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY);
std::vector<SubsampleEntry> clear_only_subsample_entries(
kSubsampleEntriesClearOnly,
@@ -517,8 +559,8 @@ TEST_F(AesDecryptorTest, SubsampleClearBytesOnly) {
// No clear bytes in any of the subsamples.
TEST_F(AesDecryptorTest, SubsampleCypherBytesOnly) {
- GenerateKeyRequest(key_id_);
- AddKeyAndExpect(kKeyAsJWK, KEY_ADDED);
+ uint32 session_id = CreateSession(key_id_);
+ UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY);
std::vector<SubsampleEntry> cypher_only_subsample_entries(
kSubsampleEntriesCypherOnly,
@@ -529,66 +571,151 @@ TEST_F(AesDecryptorTest, SubsampleCypherBytesOnly) {
DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
}
+TEST_F(AesDecryptorTest, ReleaseSession) {
+ uint32 session_id = CreateSession(key_id_);
+ scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
+ encrypted_data_, key_id_, iv_, 0, no_subsample_entries_);
+
+ UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY);
+ ASSERT_NO_FATAL_FAILURE(
+ DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
+
+ ReleaseSession(session_id);
+}
+
+TEST_F(AesDecryptorTest, NoKeyAfterReleaseSession) {
+ uint32 session_id = CreateSession(key_id_);
+ scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
+ encrypted_data_, key_id_, iv_, 0, no_subsample_entries_);
+
+ UpdateSessionAndExpect(session_id, kKeyAsJWK, SESSION_READY);
+ ASSERT_NO_FATAL_FAILURE(
+ DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
+
+ ReleaseSession(session_id);
+ ASSERT_NO_FATAL_FAILURE(
+ DecryptAndExpect(encrypted_buffer, original_data_, NO_KEY));
+}
+
+TEST_F(AesDecryptorTest, LatestKeyUsed) {
+ uint32 session_id1 = CreateSession(key_id_);
+ scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
+ encrypted_data_, key_id_, iv_, 0, no_subsample_entries_);
+
+ // Add alternate key, buffer should not be decoded properly.
+ UpdateSessionAndExpect(session_id1, kKeyAlternateAsJWK, SESSION_READY);
+ ASSERT_NO_FATAL_FAILURE(
+ DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH));
+
+ // Create a second session with a correct key value for key_id_.
+ uint32 session_id2 = CreateSession(key_id_);
+ UpdateSessionAndExpect(session_id2, kKeyAsJWK, SESSION_READY);
+
+ // Should be able to decode with latest key.
+ ASSERT_NO_FATAL_FAILURE(
+ DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
+}
+
+TEST_F(AesDecryptorTest, LatestKeyUsedAfterReleaseSession) {
+ uint32 session_id1 = CreateSession(key_id_);
+ scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
+ encrypted_data_, key_id_, iv_, 0, no_subsample_entries_);
+ UpdateSessionAndExpect(session_id1, kKeyAsJWK, SESSION_READY);
+ ASSERT_NO_FATAL_FAILURE(
+ DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
+
+ // Create a second session with a different key value for key_id_.
+ uint32 session_id2 = CreateSession(key_id_);
+ UpdateSessionAndExpect(session_id2, kKeyAlternateAsJWK, SESSION_READY);
+
+ // Should not be able to decode with new key.
+ ASSERT_NO_FATAL_FAILURE(
+ DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH));
+
+ // Close second session, should revert to original key.
+ ReleaseSession(session_id2);
+ ASSERT_NO_FATAL_FAILURE(
+ DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
+}
+
TEST_F(AesDecryptorTest, JWKKey) {
+ uint32 session_id = CreateSession(key_id_);
+
// Try a simple JWK key (i.e. not in a set)
- const std::string key1 =
+ const std::string kJwkSimple =
"{"
" \"kty\": \"oct\","
- " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM=\","
- " \"k\": \"FBUWFxgZGhscHR4fICEiIw==\""
+ " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
+ " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
"}";
- AddKeyAndExpect(key1, KEY_ERROR);
+ UpdateSessionAndExpect(session_id, kJwkSimple, SESSION_ERROR);
// Try a key list with multiple entries.
- const std::string key2 =
+ const std::string kJwksMultipleEntries =
"{"
" \"keys\": ["
" {"
" \"kty\": \"oct\","
- " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM=\","
- " \"k\": \"FBUWFxgZGhscHR4fICEiIw==\""
+ " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
+ " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
" },"
" {"
" \"kty\": \"oct\","
- " \"kid\": \"JCUmJygpKissLS4vMA==\","
- " \"k\":\"MTIzNDU2Nzg5Ojs8PT4/QA==\""
+ " \"kid\": \"JCUmJygpKissLS4vMA\","
+ " \"k\":\"MTIzNDU2Nzg5Ojs8PT4/QA\""
" }"
" ]"
"}";
- AddKeyAndExpect(key2, KEY_ADDED);
+ UpdateSessionAndExpect(session_id, kJwksMultipleEntries, SESSION_READY);
// Try a key with no spaces and some \n plus additional fields.
- const std::string key3 =
+ const std::string kJwksNoSpaces =
"\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\",\"alg\":\"A128KW\","
- "\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM=\",\"k\":\"GawgguFyGrWKav7AX4VKUg="
- "=\",\"foo\":\"bar\"}]}\n\n";
- AddKeyAndExpect(key3, KEY_ADDED);
+ "\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM\",\"k\":\"GawgguFyGrWKav7AX4VKUg"
+ "\",\"foo\":\"bar\"}]}\n\n";
+ UpdateSessionAndExpect(session_id, kJwksNoSpaces, SESSION_READY);
// Try some non-ASCII characters.
- AddKeyAndExpect("This is not ASCII due to \xff\xfe\xfd in it.", KEY_ERROR);
+ UpdateSessionAndExpect(session_id,
+ "This is not ASCII due to \xff\xfe\xfd in it.",
+ SESSION_ERROR);
// Try a badly formatted key. Assume that the JSON parser is fully tested,
// so we won't try a lot of combinations. However, need a test to ensure
// that the code doesn't crash if invalid JSON received.
- AddKeyAndExpect("This is not a JSON key.", KEY_ERROR);
+ UpdateSessionAndExpect(session_id, "This is not a JSON key.", SESSION_ERROR);
// Try passing some valid JSON that is not a dictionary at the top level.
- AddKeyAndExpect("40", KEY_ERROR);
+ UpdateSessionAndExpect(session_id, "40", SESSION_ERROR);
// Try an empty dictionary.
- AddKeyAndExpect("{ }", KEY_ERROR);
+ UpdateSessionAndExpect(session_id, "{ }", SESSION_ERROR);
// Try an empty 'keys' dictionary.
- AddKeyAndExpect("{ \"keys\": [] }", KEY_ERROR);
+ UpdateSessionAndExpect(session_id, "{ \"keys\": [] }", SESSION_ERROR);
// Try with 'keys' not a dictionary.
- AddKeyAndExpect("{ \"keys\":\"1\" }", KEY_ERROR);
+ UpdateSessionAndExpect(session_id, "{ \"keys\":\"1\" }", SESSION_ERROR);
// Try with 'keys' a list of integers.
- AddKeyAndExpect("{ \"keys\": [ 1, 2, 3 ] }", KEY_ERROR);
+ UpdateSessionAndExpect(
+ session_id, "{ \"keys\": [ 1, 2, 3 ] }", SESSION_ERROR);
+
+ // Try padding(=) at end of 'k' base64 string.
+ const std::string kJwksWithPaddedKey =
+ "{"
+ " \"keys\": ["
+ " {"
+ " \"kty\": \"oct\","
+ " \"kid\": \"AAECAw\","
+ " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw==\""
+ " }"
+ " ]"
+ "}";
+ UpdateSessionAndExpect(session_id, kJwksWithPaddedKey, SESSION_ERROR);
- // Try a key missing padding(=) at end of base64 string.
- const std::string key4 =
+ // Try padding(=) at end of 'kid' base64 string.
+ const std::string kJwksWithPaddedKeyId =
"{"
" \"keys\": ["
" {"
@@ -598,44 +725,49 @@ TEST_F(AesDecryptorTest, JWKKey) {
" }"
" ]"
"}";
- AddKeyAndExpect(key4, KEY_ERROR);
+ UpdateSessionAndExpect(session_id, kJwksWithPaddedKeyId, SESSION_ERROR);
- // Try a key ID missing padding(=) at end of base64 string.
- const std::string key5 =
+ // Try a key with invalid base64 encoding.
+ const std::string kJwksWithInvalidBase64 =
"{"
" \"keys\": ["
" {"
" \"kty\": \"oct\","
- " \"kid\": \"AAECAw\","
- " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw==\""
+ " \"kid\": \"!@#$%^&*()\","
+ " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
" }"
" ]"
"}";
- AddKeyAndExpect(key5, KEY_ERROR);
+ UpdateSessionAndExpect(session_id, kJwksWithInvalidBase64, SESSION_ERROR);
- // Try a key with invalid base64 encoding.
- const std::string key6 =
+ // Try a 3-byte 'kid' where no base64 padding is required.
+ // |kJwksMultipleEntries| above has 2 'kid's that require 1 and 2 padding
+ // bytes. Note that 'k' has to be 16 bytes, so it will always require padding.
+ const std::string kJwksWithNoPadding =
"{"
" \"keys\": ["
" {"
" \"kty\": \"oct\","
- " \"kid\": \"!@#$%^&*()==\","
- " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw==\""
+ " \"kid\": \"Kiss\","
+ " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
" }"
" ]"
"}";
- AddKeyAndExpect(key6, KEY_ERROR);
-}
+ UpdateSessionAndExpect(session_id, kJwksWithNoPadding, SESSION_READY);
-TEST_F(AesDecryptorTest, RawKey) {
- // Verify that v0.1b keys (raw key) is still supported. Raw keys are
- // 16 bytes long. Use the undecoded value of |kKey|.
- GenerateKeyRequest(key_id_);
- AddRawKeyAndExpect(
- key_id_, std::vector<uint8>(kKey, kKey + arraysize(kKey)), KEY_ADDED);
- scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
- encrypted_data_, key_id_, iv_, 0, no_subsample_entries_);
- DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
+ // Empty key id.
+ const std::string kJwksWithEmptyKeyId =
+ "{"
+ " \"keys\": ["
+ " {"
+ " \"kty\": \"oct\","
+ " \"kid\": \"\","
+ " \"k\": \"BAUGBwgJCgsMDQ4PEBESEw\""
+ " }"
+ " ]"
+ "}";
+ UpdateSessionAndExpect(session_id, kJwksWithEmptyKeyId, SESSION_ERROR);
+ ReleaseSession(session_id);
}
} // namespace media