Commit 4d83add3 authored by jrummell's avatar jrummell Committed by Commit bot

Properly determine if a new key was added in AesDecryptor::Update()

BUG=448219
TEST=new test passes

Review URL: https://codereview.chromium.org/1002193005

Cr-Commit-Position: refs/heads/master@{#320958}
parent 1edacadd
...@@ -334,6 +334,7 @@ void AesDecryptor::UpdateSession(const std::string& session_id, ...@@ -334,6 +334,7 @@ void AesDecryptor::UpdateSession(const std::string& session_id,
return; return;
} }
bool key_added = false;
for (KeyIdAndKeyPairs::iterator it = keys.begin(); it != keys.end(); ++it) { for (KeyIdAndKeyPairs::iterator it = keys.begin(); it != keys.end(); ++it) {
if (it->second.length() != if (it->second.length() !=
static_cast<size_t>(DecryptConfig::kDecryptionKeySize)) { static_cast<size_t>(DecryptConfig::kDecryptionKeySize)) {
...@@ -341,6 +342,12 @@ void AesDecryptor::UpdateSession(const std::string& session_id, ...@@ -341,6 +342,12 @@ void AesDecryptor::UpdateSession(const std::string& session_id,
promise->reject(INVALID_ACCESS_ERROR, 0, "Invalid key length."); promise->reject(INVALID_ACCESS_ERROR, 0, "Invalid key length.");
return; return;
} }
// If this key_id doesn't currently exist in this session,
// a new key is added.
if (!HasKey(session_id, it->first))
key_added = true;
if (!AddDecryptionKey(session_id, it->first, it->second)) { if (!AddDecryptionKey(session_id, it->first, it->second)) {
promise->reject(INVALID_ACCESS_ERROR, 0, "Unable to add key."); promise->reject(INVALID_ACCESS_ERROR, 0, "Unable to add key.");
return; return;
...@@ -374,9 +381,7 @@ void AesDecryptor::UpdateSession(const std::string& session_id, ...@@ -374,9 +381,7 @@ void AesDecryptor::UpdateSession(const std::string& session_id,
} }
} }
// Assume that at least 1 new key has been successfully added and thus session_keys_change_cb_.Run(session_id, key_added, keys_info.Pass());
// sending true for |has_additional_usable_key|. http://crbug.com/448219.
session_keys_change_cb_.Run(session_id, true, keys_info.Pass());
} }
void AesDecryptor::CloseSession(const std::string& session_id, void AesDecryptor::CloseSession(const std::string& session_id,
...@@ -546,6 +551,16 @@ AesDecryptor::DecryptionKey* AesDecryptor::GetKey( ...@@ -546,6 +551,16 @@ AesDecryptor::DecryptionKey* AesDecryptor::GetKey(
return key_id_found->second->LatestDecryptionKey(); return key_id_found->second->LatestDecryptionKey();
} }
bool AesDecryptor::HasKey(const std::string& session_id,
const std::string& key_id) {
base::AutoLock auto_lock(key_map_lock_);
KeyIdToSessionKeysMap::const_iterator key_id_found = key_map_.find(key_id);
if (key_id_found == key_map_.end())
return false;
return key_id_found->second->Contains(session_id);
}
void AesDecryptor::DeleteKeysForSession(const std::string& session_id) { void AesDecryptor::DeleteKeysForSession(const std::string& session_id) {
base::AutoLock auto_lock(key_map_lock_); base::AutoLock auto_lock(key_map_lock_);
......
...@@ -126,6 +126,9 @@ class MEDIA_EXPORT AesDecryptor : public MediaKeys, ...@@ -126,6 +126,9 @@ class MEDIA_EXPORT AesDecryptor : public MediaKeys,
// the key. Returns NULL if no key is associated with |key_id|. // the key. Returns NULL if no key is associated with |key_id|.
DecryptionKey* GetKey(const std::string& key_id) const; DecryptionKey* GetKey(const std::string& key_id) const;
// Determines if |key_id| is already specified for |session_id|.
bool HasKey(const std::string& session_id, const std::string& key_id);
// Deletes all keys associated with |session_id|. // Deletes all keys associated with |session_id|.
void DeleteKeysForSession(const std::string& session_id); void DeleteKeysForSession(const std::string& session_id);
......
...@@ -323,11 +323,13 @@ class AesDecryptorTest : public testing::Test { ...@@ -323,11 +323,13 @@ class AesDecryptorTest : public testing::Test {
// tests that the update succeeds or generates an error. // tests that the update succeeds or generates an error.
void UpdateSessionAndExpect(std::string session_id, void UpdateSessionAndExpect(std::string session_id,
const std::string& key, const std::string& key,
PromiseResult expected_result) { PromiseResult expected_result,
bool new_key_expected) {
DCHECK(!key.empty()); DCHECK(!key.empty());
if (expected_result == RESOLVED) { if (expected_result == RESOLVED) {
EXPECT_CALL(*this, OnSessionKeysChangeCalled(session_id, true)); EXPECT_CALL(*this,
OnSessionKeysChangeCalled(session_id, new_key_expected));
} else { } else {
EXPECT_CALL(*this, OnSessionKeysChangeCalled(_, _)).Times(0); EXPECT_CALL(*this, OnSessionKeysChangeCalled(_, _)).Times(0);
} }
...@@ -491,7 +493,7 @@ TEST_F(AesDecryptorTest, CreateSessionWithKeyIdsInitData) { ...@@ -491,7 +493,7 @@ TEST_F(AesDecryptorTest, CreateSessionWithKeyIdsInitData) {
TEST_F(AesDecryptorTest, NormalDecryption) { TEST_F(AesDecryptorTest, NormalDecryption) {
std::string session_id = CreateSession(key_id_); std::string session_id = CreateSession(key_id_);
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, no_subsample_entries_); encrypted_data_, key_id_, iv_, no_subsample_entries_);
DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS); DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
...@@ -506,7 +508,7 @@ TEST_F(AesDecryptorTest, UnencryptedFrame) { ...@@ -506,7 +508,7 @@ TEST_F(AesDecryptorTest, UnencryptedFrame) {
TEST_F(AesDecryptorTest, WrongKey) { TEST_F(AesDecryptorTest, WrongKey) {
std::string session_id = CreateSession(key_id_); std::string session_id = CreateSession(key_id_);
UpdateSessionAndExpect(session_id, kWrongKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kWrongKeyAsJWK, RESOLVED, true);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, no_subsample_entries_); encrypted_data_, key_id_, iv_, no_subsample_entries_);
DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH); DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
...@@ -524,29 +526,29 @@ TEST_F(AesDecryptorTest, KeyReplacement) { ...@@ -524,29 +526,29 @@ TEST_F(AesDecryptorTest, KeyReplacement) {
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, no_subsample_entries_); encrypted_data_, key_id_, iv_, no_subsample_entries_);
UpdateSessionAndExpect(session_id, kWrongKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kWrongKeyAsJWK, RESOLVED, true);
ASSERT_NO_FATAL_FAILURE(DecryptAndExpect( ASSERT_NO_FATAL_FAILURE(DecryptAndExpect(
encrypted_buffer, original_data_, DATA_MISMATCH)); encrypted_buffer, original_data_, DATA_MISMATCH));
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, false);
ASSERT_NO_FATAL_FAILURE( ASSERT_NO_FATAL_FAILURE(
DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS)); DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
} }
TEST_F(AesDecryptorTest, WrongSizedKey) { TEST_F(AesDecryptorTest, WrongSizedKey) {
std::string session_id = CreateSession(key_id_); std::string session_id = CreateSession(key_id_);
UpdateSessionAndExpect(session_id, kWrongSizedKeyAsJWK, REJECTED); UpdateSessionAndExpect(session_id, kWrongSizedKeyAsJWK, REJECTED, true);
} }
TEST_F(AesDecryptorTest, MultipleKeysAndFrames) { TEST_F(AesDecryptorTest, MultipleKeysAndFrames) {
std::string session_id = CreateSession(key_id_); std::string session_id = CreateSession(key_id_);
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, no_subsample_entries_); encrypted_data_, key_id_, iv_, no_subsample_entries_);
ASSERT_NO_FATAL_FAILURE( ASSERT_NO_FATAL_FAILURE(
DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS)); DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
UpdateSessionAndExpect(session_id, kKey2AsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKey2AsJWK, RESOLVED, true);
// The first key is still available after we added a second key. // The first key is still available after we added a second key.
ASSERT_NO_FATAL_FAILURE( ASSERT_NO_FATAL_FAILURE(
...@@ -568,7 +570,7 @@ TEST_F(AesDecryptorTest, MultipleKeysAndFrames) { ...@@ -568,7 +570,7 @@ TEST_F(AesDecryptorTest, MultipleKeysAndFrames) {
TEST_F(AesDecryptorTest, CorruptedIv) { TEST_F(AesDecryptorTest, CorruptedIv) {
std::string session_id = CreateSession(key_id_); std::string session_id = CreateSession(key_id_);
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
std::vector<uint8> bad_iv = iv_; std::vector<uint8> bad_iv = iv_;
bad_iv[1]++; bad_iv[1]++;
...@@ -581,7 +583,7 @@ TEST_F(AesDecryptorTest, CorruptedIv) { ...@@ -581,7 +583,7 @@ TEST_F(AesDecryptorTest, CorruptedIv) {
TEST_F(AesDecryptorTest, CorruptedData) { TEST_F(AesDecryptorTest, CorruptedData) {
std::string session_id = CreateSession(key_id_); std::string session_id = CreateSession(key_id_);
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
std::vector<uint8> bad_data = encrypted_data_; std::vector<uint8> bad_data = encrypted_data_;
bad_data[1]++; bad_data[1]++;
...@@ -593,7 +595,7 @@ TEST_F(AesDecryptorTest, CorruptedData) { ...@@ -593,7 +595,7 @@ TEST_F(AesDecryptorTest, CorruptedData) {
TEST_F(AesDecryptorTest, EncryptedAsUnencryptedFailure) { TEST_F(AesDecryptorTest, EncryptedAsUnencryptedFailure) {
std::string session_id = CreateSession(key_id_); std::string session_id = CreateSession(key_id_);
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, std::vector<uint8>(), no_subsample_entries_); encrypted_data_, key_id_, std::vector<uint8>(), no_subsample_entries_);
DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH); DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH);
...@@ -601,7 +603,7 @@ TEST_F(AesDecryptorTest, EncryptedAsUnencryptedFailure) { ...@@ -601,7 +603,7 @@ TEST_F(AesDecryptorTest, EncryptedAsUnencryptedFailure) {
TEST_F(AesDecryptorTest, SubsampleDecryption) { TEST_F(AesDecryptorTest, SubsampleDecryption) {
std::string session_id = CreateSession(key_id_); std::string session_id = CreateSession(key_id_);
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
subsample_encrypted_data_, key_id_, iv_, normal_subsample_entries_); subsample_encrypted_data_, key_id_, iv_, normal_subsample_entries_);
DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS); DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
...@@ -612,7 +614,7 @@ TEST_F(AesDecryptorTest, SubsampleDecryption) { ...@@ -612,7 +614,7 @@ TEST_F(AesDecryptorTest, SubsampleDecryption) {
// disallow such a configuration, it should be covered. // disallow such a configuration, it should be covered.
TEST_F(AesDecryptorTest, SubsampleDecryptionWithOffset) { TEST_F(AesDecryptorTest, SubsampleDecryptionWithOffset) {
std::string session_id = CreateSession(key_id_); std::string session_id = CreateSession(key_id_);
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
subsample_encrypted_data_, key_id_, iv_, normal_subsample_entries_); subsample_encrypted_data_, key_id_, iv_, normal_subsample_entries_);
DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS); DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS);
...@@ -620,7 +622,7 @@ TEST_F(AesDecryptorTest, SubsampleDecryptionWithOffset) { ...@@ -620,7 +622,7 @@ TEST_F(AesDecryptorTest, SubsampleDecryptionWithOffset) {
TEST_F(AesDecryptorTest, SubsampleWrongSize) { TEST_F(AesDecryptorTest, SubsampleWrongSize) {
std::string session_id = CreateSession(key_id_); std::string session_id = CreateSession(key_id_);
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
std::vector<SubsampleEntry> subsample_entries_wrong_size( std::vector<SubsampleEntry> subsample_entries_wrong_size(
kSubsampleEntriesWrongSize, kSubsampleEntriesWrongSize,
...@@ -633,7 +635,7 @@ TEST_F(AesDecryptorTest, SubsampleWrongSize) { ...@@ -633,7 +635,7 @@ TEST_F(AesDecryptorTest, SubsampleWrongSize) {
TEST_F(AesDecryptorTest, SubsampleInvalidTotalSize) { TEST_F(AesDecryptorTest, SubsampleInvalidTotalSize) {
std::string session_id = CreateSession(key_id_); std::string session_id = CreateSession(key_id_);
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
std::vector<SubsampleEntry> subsample_entries_invalid_total_size( std::vector<SubsampleEntry> subsample_entries_invalid_total_size(
kSubsampleEntriesInvalidTotalSize, kSubsampleEntriesInvalidTotalSize,
...@@ -649,7 +651,7 @@ TEST_F(AesDecryptorTest, SubsampleInvalidTotalSize) { ...@@ -649,7 +651,7 @@ TEST_F(AesDecryptorTest, SubsampleInvalidTotalSize) {
// No cypher bytes in any of the subsamples. // No cypher bytes in any of the subsamples.
TEST_F(AesDecryptorTest, SubsampleClearBytesOnly) { TEST_F(AesDecryptorTest, SubsampleClearBytesOnly) {
std::string session_id = CreateSession(key_id_); std::string session_id = CreateSession(key_id_);
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
std::vector<SubsampleEntry> clear_only_subsample_entries( std::vector<SubsampleEntry> clear_only_subsample_entries(
kSubsampleEntriesClearOnly, kSubsampleEntriesClearOnly,
...@@ -663,7 +665,7 @@ TEST_F(AesDecryptorTest, SubsampleClearBytesOnly) { ...@@ -663,7 +665,7 @@ TEST_F(AesDecryptorTest, SubsampleClearBytesOnly) {
// No clear bytes in any of the subsamples. // No clear bytes in any of the subsamples.
TEST_F(AesDecryptorTest, SubsampleCypherBytesOnly) { TEST_F(AesDecryptorTest, SubsampleCypherBytesOnly) {
std::string session_id = CreateSession(key_id_); std::string session_id = CreateSession(key_id_);
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
std::vector<SubsampleEntry> cypher_only_subsample_entries( std::vector<SubsampleEntry> cypher_only_subsample_entries(
kSubsampleEntriesCypherOnly, kSubsampleEntriesCypherOnly,
...@@ -679,7 +681,7 @@ TEST_F(AesDecryptorTest, CloseSession) { ...@@ -679,7 +681,7 @@ TEST_F(AesDecryptorTest, CloseSession) {
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, no_subsample_entries_); encrypted_data_, key_id_, iv_, no_subsample_entries_);
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
ASSERT_NO_FATAL_FAILURE( ASSERT_NO_FATAL_FAILURE(
DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS)); DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
...@@ -693,7 +695,7 @@ TEST_F(AesDecryptorTest, RemoveSession) { ...@@ -693,7 +695,7 @@ TEST_F(AesDecryptorTest, RemoveSession) {
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, no_subsample_entries_); encrypted_data_, key_id_, iv_, no_subsample_entries_);
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
ASSERT_NO_FATAL_FAILURE( ASSERT_NO_FATAL_FAILURE(
DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS)); DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
...@@ -705,7 +707,7 @@ TEST_F(AesDecryptorTest, NoKeyAfterCloseSession) { ...@@ -705,7 +707,7 @@ TEST_F(AesDecryptorTest, NoKeyAfterCloseSession) {
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, no_subsample_entries_); encrypted_data_, key_id_, iv_, no_subsample_entries_);
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
ASSERT_NO_FATAL_FAILURE( ASSERT_NO_FATAL_FAILURE(
DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS)); DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
...@@ -720,13 +722,13 @@ TEST_F(AesDecryptorTest, LatestKeyUsed) { ...@@ -720,13 +722,13 @@ TEST_F(AesDecryptorTest, LatestKeyUsed) {
encrypted_data_, key_id_, iv_, no_subsample_entries_); encrypted_data_, key_id_, iv_, no_subsample_entries_);
// Add alternate key, buffer should not be decoded properly. // Add alternate key, buffer should not be decoded properly.
UpdateSessionAndExpect(session_id1, kKeyAlternateAsJWK, RESOLVED); UpdateSessionAndExpect(session_id1, kKeyAlternateAsJWK, RESOLVED, true);
ASSERT_NO_FATAL_FAILURE( ASSERT_NO_FATAL_FAILURE(
DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH)); DecryptAndExpect(encrypted_buffer, original_data_, DATA_MISMATCH));
// Create a second session with a correct key value for key_id_. // Create a second session with a correct key value for key_id_.
std::string session_id2 = CreateSession(key_id_); std::string session_id2 = CreateSession(key_id_);
UpdateSessionAndExpect(session_id2, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id2, kKeyAsJWK, RESOLVED, true);
// Should be able to decode with latest key. // Should be able to decode with latest key.
ASSERT_NO_FATAL_FAILURE( ASSERT_NO_FATAL_FAILURE(
...@@ -737,13 +739,13 @@ TEST_F(AesDecryptorTest, LatestKeyUsedAfterCloseSession) { ...@@ -737,13 +739,13 @@ TEST_F(AesDecryptorTest, LatestKeyUsedAfterCloseSession) {
std::string session_id1 = CreateSession(key_id_); std::string session_id1 = CreateSession(key_id_);
scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer( scoped_refptr<DecoderBuffer> encrypted_buffer = CreateEncryptedBuffer(
encrypted_data_, key_id_, iv_, no_subsample_entries_); encrypted_data_, key_id_, iv_, no_subsample_entries_);
UpdateSessionAndExpect(session_id1, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id1, kKeyAsJWK, RESOLVED, true);
ASSERT_NO_FATAL_FAILURE( ASSERT_NO_FATAL_FAILURE(
DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS)); DecryptAndExpect(encrypted_buffer, original_data_, SUCCESS));
// Create a second session with a different key value for key_id_. // Create a second session with a different key value for key_id_.
std::string session_id2 = CreateSession(key_id_); std::string session_id2 = CreateSession(key_id_);
UpdateSessionAndExpect(session_id2, kKeyAlternateAsJWK, RESOLVED); UpdateSessionAndExpect(session_id2, kKeyAlternateAsJWK, RESOLVED, true);
// Should not be able to decode with new key. // Should not be able to decode with new key.
ASSERT_NO_FATAL_FAILURE( ASSERT_NO_FATAL_FAILURE(
...@@ -766,7 +768,7 @@ TEST_F(AesDecryptorTest, JWKKey) { ...@@ -766,7 +768,7 @@ TEST_F(AesDecryptorTest, JWKKey) {
" \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\"," " \"kid\": \"AAECAwQFBgcICQoLDA0ODxAREhM\","
" \"k\": \"FBUWFxgZGhscHR4fICEiIw\"" " \"k\": \"FBUWFxgZGhscHR4fICEiIw\""
"}"; "}";
UpdateSessionAndExpect(session_id, kJwkSimple, REJECTED); UpdateSessionAndExpect(session_id, kJwkSimple, REJECTED, true);
// Try a key list with multiple entries. // Try a key list with multiple entries.
const std::string kJwksMultipleEntries = const std::string kJwksMultipleEntries =
...@@ -786,38 +788,40 @@ TEST_F(AesDecryptorTest, JWKKey) { ...@@ -786,38 +788,40 @@ TEST_F(AesDecryptorTest, JWKKey) {
" }" " }"
" ]" " ]"
"}"; "}";
UpdateSessionAndExpect(session_id, kJwksMultipleEntries, RESOLVED); UpdateSessionAndExpect(session_id, kJwksMultipleEntries, RESOLVED, true);
// Try a key with no spaces and some \n plus additional fields. // Try a key with no spaces and some \n plus additional fields.
const std::string kJwksNoSpaces = const std::string kJwksNoSpaces =
"\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\",\"alg\":\"A128KW\"," "\n\n{\"something\":1,\"keys\":[{\n\n\"kty\":\"oct\",\"alg\":\"A128KW\","
"\"kid\":\"AAECAwQFBgcICQoLDA0ODxAREhM\",\"k\":\"GawgguFyGrWKav7AX4VKUg" "\"kid\":\"AQIDBAUGBwgJCgsMCg4PAA\",\"k\":\"GawgguFyGrWKav7AX4VKUg"
"\",\"foo\":\"bar\"}]}\n\n"; "\",\"foo\":\"bar\"}]}\n\n";
UpdateSessionAndExpect(session_id, kJwksNoSpaces, RESOLVED); UpdateSessionAndExpect(session_id, kJwksNoSpaces, RESOLVED, true);
// Try some non-ASCII characters. // Try some non-ASCII characters.
UpdateSessionAndExpect( UpdateSessionAndExpect(session_id,
session_id, "This is not ASCII due to \xff\xfe\xfd in it.", REJECTED); "This is not ASCII due to \xff\xfe\xfd in it.",
REJECTED, true);
// Try a badly formatted key. Assume that the JSON parser is fully tested, // 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 // 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. // that the code doesn't crash if invalid JSON received.
UpdateSessionAndExpect(session_id, "This is not a JSON key.", REJECTED); UpdateSessionAndExpect(session_id, "This is not a JSON key.", REJECTED, true);
// Try passing some valid JSON that is not a dictionary at the top level. // Try passing some valid JSON that is not a dictionary at the top level.
UpdateSessionAndExpect(session_id, "40", REJECTED); UpdateSessionAndExpect(session_id, "40", REJECTED, true);
// Try an empty dictionary. // Try an empty dictionary.
UpdateSessionAndExpect(session_id, "{ }", REJECTED); UpdateSessionAndExpect(session_id, "{ }", REJECTED, true);
// Try an empty 'keys' dictionary. // Try an empty 'keys' dictionary.
UpdateSessionAndExpect(session_id, "{ \"keys\": [] }", REJECTED); UpdateSessionAndExpect(session_id, "{ \"keys\": [] }", REJECTED, true);
// Try with 'keys' not a dictionary. // Try with 'keys' not a dictionary.
UpdateSessionAndExpect(session_id, "{ \"keys\":\"1\" }", REJECTED); UpdateSessionAndExpect(session_id, "{ \"keys\":\"1\" }", REJECTED, true);
// Try with 'keys' a list of integers. // Try with 'keys' a list of integers.
UpdateSessionAndExpect(session_id, "{ \"keys\": [ 1, 2, 3 ] }", REJECTED); UpdateSessionAndExpect(session_id, "{ \"keys\": [ 1, 2, 3 ] }", REJECTED,
true);
// Try padding(=) at end of 'k' base64 string. // Try padding(=) at end of 'k' base64 string.
const std::string kJwksWithPaddedKey = const std::string kJwksWithPaddedKey =
...@@ -831,7 +835,7 @@ TEST_F(AesDecryptorTest, JWKKey) { ...@@ -831,7 +835,7 @@ TEST_F(AesDecryptorTest, JWKKey) {
" }" " }"
" ]" " ]"
"}"; "}";
UpdateSessionAndExpect(session_id, kJwksWithPaddedKey, REJECTED); UpdateSessionAndExpect(session_id, kJwksWithPaddedKey, REJECTED, true);
// Try padding(=) at end of 'kid' base64 string. // Try padding(=) at end of 'kid' base64 string.
const std::string kJwksWithPaddedKeyId = const std::string kJwksWithPaddedKeyId =
...@@ -845,7 +849,7 @@ TEST_F(AesDecryptorTest, JWKKey) { ...@@ -845,7 +849,7 @@ TEST_F(AesDecryptorTest, JWKKey) {
" }" " }"
" ]" " ]"
"}"; "}";
UpdateSessionAndExpect(session_id, kJwksWithPaddedKeyId, REJECTED); UpdateSessionAndExpect(session_id, kJwksWithPaddedKeyId, REJECTED, true);
// Try a key with invalid base64 encoding. // Try a key with invalid base64 encoding.
const std::string kJwksWithInvalidBase64 = const std::string kJwksWithInvalidBase64 =
...@@ -859,7 +863,7 @@ TEST_F(AesDecryptorTest, JWKKey) { ...@@ -859,7 +863,7 @@ TEST_F(AesDecryptorTest, JWKKey) {
" }" " }"
" ]" " ]"
"}"; "}";
UpdateSessionAndExpect(session_id, kJwksWithInvalidBase64, REJECTED); UpdateSessionAndExpect(session_id, kJwksWithInvalidBase64, REJECTED, true);
// Try a 3-byte 'kid' where no base64 padding is required. // Try a 3-byte 'kid' where no base64 padding is required.
// |kJwksMultipleEntries| above has 2 'kid's that require 1 and 2 padding // |kJwksMultipleEntries| above has 2 'kid's that require 1 and 2 padding
...@@ -875,7 +879,7 @@ TEST_F(AesDecryptorTest, JWKKey) { ...@@ -875,7 +879,7 @@ TEST_F(AesDecryptorTest, JWKKey) {
" }" " }"
" ]" " ]"
"}"; "}";
UpdateSessionAndExpect(session_id, kJwksWithNoPadding, RESOLVED); UpdateSessionAndExpect(session_id, kJwksWithNoPadding, RESOLVED, true);
// Empty key id. // Empty key id.
const std::string kJwksWithEmptyKeyId = const std::string kJwksWithEmptyKeyId =
...@@ -889,7 +893,7 @@ TEST_F(AesDecryptorTest, JWKKey) { ...@@ -889,7 +893,7 @@ TEST_F(AesDecryptorTest, JWKKey) {
" }" " }"
" ]" " ]"
"}"; "}";
UpdateSessionAndExpect(session_id, kJwksWithEmptyKeyId, REJECTED); UpdateSessionAndExpect(session_id, kJwksWithEmptyKeyId, REJECTED, true);
CloseSession(session_id); CloseSession(session_id);
} }
...@@ -902,14 +906,33 @@ TEST_F(AesDecryptorTest, GetKeyIds) { ...@@ -902,14 +906,33 @@ TEST_F(AesDecryptorTest, GetKeyIds) {
EXPECT_FALSE(KeysInfoContains(key_id2)); EXPECT_FALSE(KeysInfoContains(key_id2));
// Add 1 key, verify it is returned. // Add 1 key, verify it is returned.
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
EXPECT_TRUE(KeysInfoContains(key_id1)); EXPECT_TRUE(KeysInfoContains(key_id1));
EXPECT_FALSE(KeysInfoContains(key_id2)); EXPECT_FALSE(KeysInfoContains(key_id2));
// Add second key, verify both IDs returned. // Add second key, verify both IDs returned.
UpdateSessionAndExpect(session_id, kKey2AsJWK, RESOLVED); UpdateSessionAndExpect(session_id, kKey2AsJWK, RESOLVED, true);
EXPECT_TRUE(KeysInfoContains(key_id1)); EXPECT_TRUE(KeysInfoContains(key_id1));
EXPECT_TRUE(KeysInfoContains(key_id2)); EXPECT_TRUE(KeysInfoContains(key_id2));
} }
TEST_F(AesDecryptorTest, NoKeysChangeForSameKey) {
std::vector<uint8> key_id(kKeyId, kKeyId + arraysize(kKeyId));
std::string session_id = CreateSession(key_id_);
EXPECT_FALSE(KeysInfoContains(key_id));
// Add key, verify it is returned.
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, true);
EXPECT_TRUE(KeysInfoContains(key_id));
// Add key a second time.
UpdateSessionAndExpect(session_id, kKeyAsJWK, RESOLVED, false);
EXPECT_TRUE(KeysInfoContains(key_id));
// Create a new session. Add key, should indicate key added for this session.
std::string session_id2 = CreateSession(key_id_);
UpdateSessionAndExpect(session_id2, kKeyAsJWK, RESOLVED, true);
}
} // namespace media } // namespace media
...@@ -302,6 +302,12 @@ class KeyProvidingApp : public FakeEncryptedMedia::AppBase { ...@@ -302,6 +302,12 @@ class KeyProvidingApp : public FakeEncryptedMedia::AppBase {
void OnEncryptedMediaInitData(const std::string& init_data_type, void OnEncryptedMediaInitData(const std::string& init_data_type,
const std::vector<uint8>& init_data, const std::vector<uint8>& init_data,
AesDecryptor* decryptor) override { AesDecryptor* decryptor) override {
// Since only 1 session is created, skip the request if the |init_data|
// has been seen before (no need to add the same key again).
if (init_data == prev_init_data_)
return;
prev_init_data_ = init_data;
if (current_session_id_.empty()) { if (current_session_id_.empty()) {
if (init_data_type == kCencInitDataType) { if (init_data_type == kCencInitDataType) {
// Since the 'cenc' files are not created with proper 'pssh' boxes, // Since the 'cenc' files are not created with proper 'pssh' boxes,
...@@ -340,6 +346,7 @@ class KeyProvidingApp : public FakeEncryptedMedia::AppBase { ...@@ -340,6 +346,7 @@ class KeyProvidingApp : public FakeEncryptedMedia::AppBase {
} }
std::string current_session_id_; std::string current_session_id_;
std::vector<uint8> prev_init_data_;
}; };
class RotatingKeyProvidingApp : public KeyProvidingApp { class RotatingKeyProvidingApp : public KeyProvidingApp {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment