summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorjln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-18 04:05:31 +0000
committerjln@chromium.org <jln@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-07-18 04:05:31 +0000
commit108c4926024c1901bd66f54115ec9dbe216baed1 (patch)
tree9df382ae57fb917fb47ee81d1f70d421b813b753 /media
parentbd4c0d288bb658922ffde085030d3ce4ca7bd057 (diff)
downloadchromium_src-108c4926024c1901bd66f54115ec9dbe216baed1.zip
chromium_src-108c4926024c1901bd66f54115ec9dbe216baed1.tar.gz
chromium_src-108c4926024c1901bd66f54115ec9dbe216baed1.tar.bz2
Revert 147169 - Add support for encrypted WebM files as defined in the RFC.
The WebM parser now reads the HMAC and IV from every encrypted Block and stores that information in the DecryptorConfig object. Added two new elements ContentEncAESSettings and AESSettingsCipherMode used by encrypted WebM files. BUG=119845 TEST=media_unittests --gtest_filter=HmacAesDecryptorTest Review URL: https://chromiumcodereview.appspot.com/10535029 TBR=fgalligan@chromium.org Review URL: https://chromiumcodereview.appspot.com/10807003 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@147172 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'media')
-rw-r--r--media/base/decrypt_config.cc20
-rw-r--r--media/base/decrypt_config.h39
-rw-r--r--media/crypto/aes_decryptor.cc186
-rw-r--r--media/crypto/aes_decryptor.h46
-rw-r--r--media/crypto/aes_decryptor_unittest.cc368
-rw-r--r--media/filters/ffmpeg_video_decoder_unittest.cc87
-rw-r--r--media/filters/pipeline_integration_test.cc16
-rw-r--r--media/webm/webm_cluster_parser.cc43
-rw-r--r--media/webm/webm_cluster_parser.h4
-rw-r--r--media/webm/webm_constants.h7
-rw-r--r--media/webm/webm_content_encodings.cc3
-rw-r--r--media/webm/webm_content_encodings.h9
-rw-r--r--media/webm/webm_content_encodings_client.cc29
-rw-r--r--media/webm/webm_parser.cc9
-rw-r--r--media/webm/webm_stream_parser.cc1
15 files changed, 138 insertions, 729 deletions
diff --git a/media/base/decrypt_config.cc b/media/base/decrypt_config.cc
index fb502df..9ae5f19 100644
--- a/media/base/decrypt_config.cc
+++ b/media/base/decrypt_config.cc
@@ -8,25 +8,11 @@
namespace media {
-DecryptConfig::DecryptConfig(const uint8* key_id, int key_id_size,
- const uint8* iv, int iv_size,
- const uint8* checksum, int checksum_size,
- int encrypted_frame_offset)
- : key_id_(new uint8[key_id_size]),
- key_id_size_(key_id_size),
- iv_(new uint8[iv_size]),
- iv_size_(iv_size),
- checksum_(checksum_size > 0 ? new uint8[checksum_size] : NULL),
- checksum_size_(checksum_size),
- encrypted_frame_offset_(encrypted_frame_offset) {
+DecryptConfig::DecryptConfig(const uint8* key_id, int key_id_size)
+ : key_id_size_(key_id_size) {
CHECK_GT(key_id_size, 0);
- CHECK_EQ(iv_size, DecryptConfig::kDecryptionKeySize);
- CHECK_GE(checksum_size, 0);
- CHECK_GE(encrypted_frame_offset, 0);
+ key_id_.reset(new uint8[key_id_size]);
memcpy(key_id_.get(), key_id, key_id_size);
- memcpy(iv_.get(), iv, iv_size);
- if (checksum_size > 0)
- memcpy(checksum_.get(), checksum, checksum_size);
}
DecryptConfig::~DecryptConfig() {}
diff --git a/media/base/decrypt_config.h b/media/base/decrypt_config.h
index 68a3fbd..5fca787 100644
--- a/media/base/decrypt_config.h
+++ b/media/base/decrypt_config.h
@@ -11,49 +11,18 @@
namespace media {
-// Contains all information that a decryptor needs to decrypt a frame.
+// Contains all information that a decryptor needs to decrypt.
class MEDIA_EXPORT DecryptConfig {
public:
- // Keys are always 128 bits.
- static const int kDecryptionKeySize = 16;
-
- // |key_id| is the ID that references the decryption key for this frame. |iv|
- // is the initialization vector defined by the encrypted format. Currently
- // |iv_size| must be 16 bytes as defined by WebM and ISO. |checksum| is the
- // hash value of the encrypted buffer. |checksum| is defined by the
- // encrypted format and may be NULL. |encrypted_frame_offset| is the offset
- // into the encrypted buffer that the encrypted frame starts. The class
- // will copy the data from |key_id|, |iv|, and |checksum|.
- DecryptConfig(const uint8* key_id, int key_id_size,
- const uint8* iv, int iv_size,
- const uint8* checksum, int checksum_size,
- int encrypted_frame_offset);
+ explicit DecryptConfig(const uint8* key_id, int key_id_size);
~DecryptConfig();
const uint8* key_id() const { return key_id_.get(); }
int key_id_size() const { return key_id_size_; }
- const uint8* iv() const { return iv_.get(); }
- int iv_size() const { return iv_size_; }
- const uint8* checksum() const { return checksum_.get(); }
- int checksum_size() const { return checksum_size_; }
- int encrypted_frame_offset() const { return encrypted_frame_offset_; }
private:
- const scoped_array<uint8> key_id_;
- const int key_id_size_;
-
- // Initialization vector.
- const scoped_array<uint8> iv_;
- const int iv_size_;
-
- // Checksum of the data to be verified before decrypting the data. This may
- // be NULL for some formats.
- const scoped_array<uint8> checksum_;
- const int checksum_size_;
-
- // This is the offset in bytes to where the encrypted data starts within
- // the input buffer.
- const int encrypted_frame_offset_;
+ scoped_array<uint8> key_id_;
+ int key_id_size_;
DISALLOW_COPY_AND_ASSIGN(DecryptConfig);
};
diff --git a/media/crypto/aes_decryptor.cc b/media/crypto/aes_decryptor.cc
index e69f406..f677f0d 100644
--- a/media/crypto/aes_decryptor.cc
+++ b/media/crypto/aes_decryptor.cc
@@ -7,8 +7,8 @@
#include "base/logging.h"
#include "base/stl_util.h"
#include "base/string_number_conversions.h"
+#include "base/string_piece.h"
#include "crypto/encryptor.h"
-#include "crypto/hmac.h"
#include "crypto/symmetric_key.h"
#include "media/base/decoder_buffer.h"
#include "media/base/decrypt_config.h"
@@ -16,111 +16,31 @@
namespace media {
-// The size is from the WebM encrypted specification. Current encrypted WebM
-// request for comments specification is here
-// http://wiki.webmproject.org/encryption/webm-encryption-rfc
-static const int kWebmSha1DigestSize = 20;
-static const char kWebmHmacSeed[] = "hmac-key";
-static const char kWebmEncryptionSeed[] = "encryption-key";
+// TODO(xhwang): Get real IV from frames.
+static const char kInitialCounter[] = "0000000000000000";
uint32 AesDecryptor::next_session_id_ = 1;
-// Derives a key using SHA1 HMAC. |secret| is the base secret to derive
-// the key from. |seed| is the known message to the HMAC algorithm. |key_size|
-// is how many bytes are returned in the key. Returns a string containing the
-// key on success. Returns an empty string on failure.
-static std::string DeriveKey(const base::StringPiece& secret,
- const base::StringPiece& seed,
- int key_size) {
- CHECK(!secret.empty());
- CHECK(!seed.empty());
- CHECK_GT(key_size, 0);
-
- crypto::HMAC hmac(crypto::HMAC::SHA1);
- if (!hmac.Init(secret)) {
- DVLOG(1) << "Could not initialize HMAC with secret data.";
- return std::string();
- }
-
- scoped_array<uint8> calculated_hmac(new uint8[hmac.DigestLength()]);
- if (!hmac.Sign(seed, calculated_hmac.get(), hmac.DigestLength())) {
- DVLOG(1) << "Could not calculate HMAC.";
- return std::string();
- }
-
- return std::string(reinterpret_cast<const char*>(calculated_hmac.get()),
- key_size);
-}
-
-// Checks data in |input| matches the HMAC in |input|. The check is using the
-// SHA1 algorithm. |hmac_key| is the key of the HMAC algorithm. Returns true if
-// the integrity check passes.
-static bool CheckData(const DecoderBuffer& input,
- const base::StringPiece& hmac_key) {
- CHECK(input.GetDataSize());
- CHECK(input.GetDecryptConfig());
- CHECK_GT(input.GetDecryptConfig()->checksum_size(), 0);
- CHECK(!hmac_key.empty());
-
- crypto::HMAC hmac(crypto::HMAC::SHA1);
- if (!hmac.Init(hmac_key))
- return false;
-
- // The HMAC covers the IV and the frame data.
- base::StringPiece data_to_check(
- reinterpret_cast<const char*>(input.GetData()), input.GetDataSize());
-
- scoped_array<uint8> calculated_hmac(new uint8[hmac.DigestLength()]);
- if (!hmac.Sign(data_to_check, calculated_hmac.get(), hmac.DigestLength()))
- return false;
-
- DCHECK(input.GetDecryptConfig()->checksum_size() <=
- static_cast<int>(hmac.DigestLength()));
- if (memcmp(input.GetDecryptConfig()->checksum(),
- calculated_hmac.get(),
- input.GetDecryptConfig()->checksum_size()) != 0)
- return false;
- return true;
-}
-
-// Decrypts |input| using |key|. |encrypted_data_offset| is the number of bytes
-// into |input| that the encrypted data starts.
-// Returns a DecoderBuffer with the decrypted data if decryption succeeded or
-// NULL if decryption failed.
+// Decrypt |input| using |key|.
+// Return a DecoderBuffer with the decrypted data if decryption succeeded.
+// Return NULL if decryption failed.
static scoped_refptr<DecoderBuffer> DecryptData(const DecoderBuffer& input,
- crypto::SymmetricKey* key,
- int encrypted_data_offset) {
+ crypto::SymmetricKey* key) {
CHECK(input.GetDataSize());
- CHECK(input.GetDecryptConfig());
CHECK(key);
- // Initialize decryptor.
+ // Initialize encryption data.
+ // The IV must be exactly as long as the cipher block size.
crypto::Encryptor encryptor;
- if (!encryptor.Init(key, crypto::Encryptor::CTR, "")) {
- DVLOG(1) << "Could not initialize decryptor.";
- return NULL;
- }
-
- DCHECK_EQ(input.GetDecryptConfig()->iv_size(),
- DecryptConfig::kDecryptionKeySize);
- // Set the counter block.
- base::StringPiece counter_block(
- reinterpret_cast<const char*>(input.GetDecryptConfig()->iv()),
- input.GetDecryptConfig()->iv_size());
- if (counter_block.empty()) {
- DVLOG(1) << "Could not generate counter block.";
- return NULL;
- }
- if (!encryptor.SetCounter(counter_block)) {
- DVLOG(1) << "Could not set counter block.";
+ if (!encryptor.Init(key, crypto::Encryptor::CBC, kInitialCounter)) {
+ DVLOG(1) << "Could not initialize encryptor.";
return NULL;
}
std::string decrypted_text;
- const char* frame =
- reinterpret_cast<const char*>(input.GetData() + encrypted_data_offset);
- int frame_size = input.GetDataSize() - encrypted_data_offset;
- base::StringPiece encrypted_text(frame, frame_size);
+ base::StringPiece encrypted_text(
+ reinterpret_cast<const char*>(input.GetData()),
+ input.GetDataSize());
if (!encryptor.Decrypt(encrypted_text, &decrypted_text)) {
DVLOG(1) << "Could not decrypt data.";
return NULL;
@@ -165,7 +85,9 @@ void AesDecryptor::AddKey(const std::string& key_system,
// TODO(xhwang): Add |session_id| check after we figure out how:
// https://www.w3.org/Bugs/Public/show_bug.cgi?id=16550
- if (key_length != DecryptConfig::kDecryptionKeySize) {
+
+ const int kSupportedKeyLength = 16; // 128-bit key.
+ if (key_length != kSupportedKeyLength) {
DVLOG(1) << "Invalid key length: " << key_length;
client_->KeyError(key_system, session_id, Decryptor::kUnknownError, 0);
return;
@@ -184,17 +106,10 @@ void AesDecryptor::AddKey(const std::string& key_system,
std::string key_id_string(reinterpret_cast<const char*>(init_data),
init_data_length);
std::string key_string(reinterpret_cast<const char*>(key) , key_length);
- scoped_ptr<DecryptionKey> decryption_key(new DecryptionKey(key_string));
- if (!decryption_key.get()) {
- DVLOG(1) << "Could not create key.";
- client_->KeyError(key_system, session_id, Decryptor::kUnknownError, 0);
- return;
- }
-
- // TODO(fgalligan): When ISO is added we will need to figure out how to
- // detect if the encrypted data will contain an HMAC.
- if (!decryption_key->Init(true)) {
- DVLOG(1) << "Could not initialize decryption key.";
+ crypto::SymmetricKey* symmetric_key = crypto::SymmetricKey::Import(
+ crypto::SymmetricKey::AES, key_string);
+ if (!symmetric_key) {
+ DVLOG(1) << "Could not import key.";
client_->KeyError(key_system, session_id, Decryptor::kUnknownError, 0);
return;
}
@@ -206,7 +121,7 @@ void AesDecryptor::AddKey(const std::string& key_system,
delete found->second;
key_map_.erase(found);
}
- key_map_[key_id_string] = decryption_key.release();
+ key_map_[key_id_string] = symmetric_key;
}
client_->KeyAdded(key_system, session_id);
@@ -225,7 +140,7 @@ void AesDecryptor::Decrypt(const scoped_refptr<DecoderBuffer>& encrypted,
// TODO(xhwang): Avoid always constructing a string with StringPiece?
std::string key_id_string(reinterpret_cast<const char*>(key_id), key_id_size);
- DecryptionKey* key = NULL;
+ crypto::SymmetricKey* key = NULL;
{
base::AutoLock auto_lock(key_map_lock_);
KeyMap::const_iterator found = key_map_.find(key_id_string);
@@ -234,28 +149,13 @@ void AesDecryptor::Decrypt(const scoped_refptr<DecoderBuffer>& encrypted,
}
if (!key) {
- // TODO(fgalligan): Fire a need_key event here and add a test.
DVLOG(1) << "Could not find a matching key for given key ID.";
decrypt_cb.Run(kError, NULL);
return;
}
- int checksum_size = encrypted->GetDecryptConfig()->checksum_size();
- // According to the WebM encrypted specification, it is an open question
- // what should happen when a frame fails the integrity check.
- // http://wiki.webmproject.org/encryption/webm-encryption-rfc
- if (checksum_size > 0 &&
- !key->hmac_key().empty() &&
- !CheckData(*encrypted, key->hmac_key())) {
- DVLOG(1) << "Integrity check failed.";
- decrypt_cb.Run(kError, NULL);
- return;
- }
+ scoped_refptr<DecoderBuffer> decrypted = DecryptData(*encrypted, key);
- scoped_refptr<DecoderBuffer> decrypted =
- DecryptData(*encrypted,
- key->decryption_key(),
- encrypted->GetDecryptConfig()->encrypted_frame_offset());
if (!decrypted) {
DVLOG(1) << "Decryption failed.";
decrypt_cb.Run(kError, NULL);
@@ -267,42 +167,4 @@ void AesDecryptor::Decrypt(const scoped_refptr<DecoderBuffer>& encrypted,
decrypt_cb.Run(kSuccess, decrypted);
}
-AesDecryptor::DecryptionKey::DecryptionKey(
- const std::string& secret)
- : secret_(secret) {
-}
-
-AesDecryptor::DecryptionKey::~DecryptionKey() {}
-
-bool AesDecryptor::DecryptionKey::Init(bool derive_webm_keys) {
- CHECK(!secret_.empty());
-
- if (derive_webm_keys) {
- std::string raw_key = DeriveKey(secret_,
- kWebmEncryptionSeed,
- secret_.length());
- if (raw_key.empty()) {
- return false;
- }
- decryption_key_.reset(
- crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, raw_key));
- if (!decryption_key_.get()) {
- return false;
- }
-
- hmac_key_ = DeriveKey(secret_, kWebmHmacSeed, kWebmSha1DigestSize);
- if (hmac_key_.empty()) {
- return false;
- }
- return true;
- }
-
- decryption_key_.reset(
- crypto::SymmetricKey::Import(crypto::SymmetricKey::AES, secret_));
- if (!decryption_key_.get()) {
- return false;
- }
- return true;
-}
-
} // namespace media
diff --git a/media/crypto/aes_decryptor.h b/media/crypto/aes_decryptor.h
index 224035c..6d0bf47 100644
--- a/media/crypto/aes_decryptor.h
+++ b/media/crypto/aes_decryptor.h
@@ -10,8 +10,6 @@
#include "base/basictypes.h"
#include "base/hash_tables.h"
#include "base/memory/ref_counted.h"
-#include "base/memory/scoped_ptr.h"
-#include "base/string_piece.h"
#include "base/synchronization/lock.h"
#include "media/base/decryptor.h"
#include "media/base/media_export.h"
@@ -24,9 +22,7 @@ namespace media {
class DecryptorClient;
-// Decrypts an AES encrypted buffer into an unencrypted buffer. The AES
-// encryption must be CTR with a key size of 128bits. Optionally checks the
-// integrity of the encrypted data.
+// Decryptor implementation that decrypts AES-encrypted buffer.
class MEDIA_EXPORT AesDecryptor : public Decryptor {
public:
// The AesDecryptor does not take ownership of the |client|. The |client|
@@ -46,49 +42,13 @@ class MEDIA_EXPORT AesDecryptor : public Decryptor {
const std::string& session_id) OVERRIDE;
virtual void CancelKeyRequest(const std::string& key_system,
const std::string& session_id) OVERRIDE;
- // Decrypts |encrypted| buffer. |encrypted| should not be NULL. |encrypted|
- // will signal if an integrity check must be performed before decryption.
- // Returns a DecoderBuffer with the decrypted data if the decryption
- // succeeded through |decrypt_cb|.
virtual void Decrypt(const scoped_refptr<DecoderBuffer>& encrypted,
const DecryptCB& decrypt_cb) OVERRIDE;
private:
- // Helper class that manages the decryption key and HMAC key. The HMAC key
- // may be NULL.
- class DecryptionKey {
- public:
- explicit DecryptionKey(const std::string& secret);
- ~DecryptionKey();
-
- // Creates the encryption key and HMAC. If |derive_webm_keys| is true then
- // the object will derive the decryption key and the HMAC key from
- // |secret_|.
- bool Init(bool derive_webm_keys);
-
- crypto::SymmetricKey* decryption_key() { return decryption_key_.get(); }
- base::StringPiece hmac_key() { return base::StringPiece(hmac_key_); }
-
- private:
- // The base secret that is used to derive the decryption key and optionally
- // the HMAC key.
- const std::string secret_;
-
- // The key used to decrypt the data.
- scoped_ptr<crypto::SymmetricKey> decryption_key_;
-
- // The key used to perform the integrity check. Currently the HMAC key is
- // defined by the WebM encrypted specification. Current encrypted WebM
- // request for comments specification is here
- // http://wiki.webmproject.org/encryption/webm-encryption-rfc
- std::string hmac_key_;
-
- DISALLOW_COPY_AND_ASSIGN(DecryptionKey);
- };
-
- // KeyMap owns the DecryptionKey* and must delete them when they are
+ // KeyMap owns the crypto::SymmetricKey* and must delete them when they are
// not needed any more.
- typedef base::hash_map<std::string, DecryptionKey*> KeyMap;
+ typedef base::hash_map<std::string, crypto::SymmetricKey*> KeyMap;
// Since only Decrypt() is called off the renderer thread, we only need to
// protect |key_map_|, the only member variable that is shared between
diff --git a/media/crypto/aes_decryptor_unittest.cc b/media/crypto/aes_decryptor_unittest.cc
index 34354a4..3d9d983 100644
--- a/media/crypto/aes_decryptor_unittest.cc
+++ b/media/crypto/aes_decryptor_unittest.cc
@@ -6,12 +6,10 @@
#include "base/basictypes.h"
#include "base/bind.h"
-#include "base/sys_byteorder.h"
#include "media/base/decoder_buffer.h"
#include "media/base/decrypt_config.h"
#include "media/base/mock_filters.h"
#include "media/crypto/aes_decryptor.h"
-#include "media/webm/webm_constants.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -24,123 +22,32 @@ using ::testing::StrNe;
namespace media {
-// |encrypted_data| is encrypted from |plain_text| using |key|. |key_id| is
-// used to distinguish |key|.
-struct WebmEncryptedData {
- uint8 plain_text[32];
- int plain_text_size;
- uint8 key_id[32];
- int key_id_size;
- uint8 key[32];
- int key_size;
- uint8 encrypted_data[64];
- int encrypted_data_size;
-};
-
static const char kClearKeySystem[] = "org.w3.clearkey";
-
-// Frames 0 & 1 are encrypted with the same key. Frame 2 is encrypted with a
-// different key.
-const WebmEncryptedData kWebmEncryptedFrames[] = {
- {
- // plaintext
- "Original data.", 14,
- // key_id
- { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13,
- }, 20,
- // key
- { 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
- 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
- }, 16,
- // encrypted_data
- { 0xfb, 0xe7, 0x1d, 0xbb, 0x4c, 0x23, 0xce, 0xba,
- 0xcc, 0xf8, 0xda, 0xc0, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x99, 0xaa, 0xff, 0xb7,
- 0x74, 0x02, 0x4e, 0x1c, 0x75, 0x3d, 0xee, 0xcb,
- 0x64, 0xf7,
- }, 34,
- },
- {
- // plaintext
- "Changed Original data.", 22,
- // key_id
- { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
- 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
- 0x10, 0x11, 0x12, 0x13,
- }, 20,
- // key
- { 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b,
- 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
- }, 16,
- // encrypted_data
- { 0x43, 0xe4, 0x78, 0x7a, 0x43, 0xe1, 0x49, 0xbb,
- 0x44, 0x38, 0xdf, 0xfc, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0xec, 0x8e, 0x87, 0x21,
- 0xd3, 0xb9, 0x1c, 0x61, 0xf6, 0x5a, 0x60, 0xaa,
- 0x07, 0x0e, 0x96, 0xd0, 0x54, 0x5d, 0x35, 0x9a,
- 0x4a, 0xd3,
- }, 42,
- },
- {
- // plaintext
- "Original data.", 14,
- // key_id
- { 0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
- 0x2c, 0x2d, 0x2e, 0x2f, 0x30,
- }, 13,
- // key
- { 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38,
- 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f, 0x40,
- }, 16,
- // encrypted_data
- { 0xd9, 0x43, 0x30, 0xfd, 0x82, 0x77, 0x62, 0x04,
- 0x08, 0xc2, 0x48, 0x89, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x01, 0x48, 0x5e, 0x4a, 0x41,
- 0x2a, 0x8b, 0xf4, 0xc6, 0x47, 0x54, 0x90, 0x34,
- 0xf4, 0x8b,
- }, 34,
- },
+static const uint8 kInitData[] = { 0x69, 0x6e, 0x69, 0x74 };
+// |kEncryptedData| is encrypted from |kOriginalData| using |kRightKey|.
+// Modifying any of these independently would fail the test.
+static const uint8 kOriginalData[] = {
+ 0x4f, 0x72, 0x69, 0x67, 0x69, 0x6e, 0x61, 0x6c,
+ 0x20, 0x64, 0x61, 0x74, 0x61, 0x2e
};
-
-static const uint8 kWebmWrongKey[] = {
+static const uint8 kEncryptedData[] = {
+ 0x82, 0x3A, 0x76, 0x92, 0xEC, 0x7F, 0xF8, 0x85,
+ 0xEC, 0x23, 0x52, 0xFB, 0x19, 0xB1, 0xB9, 0x09
+};
+static const uint8 kRightKey[] = {
+ 0x41, 0x20, 0x77, 0x6f, 0x6e, 0x64, 0x65, 0x72,
+ 0x66, 0x75, 0x6c, 0x20, 0x6b, 0x65, 0x79, 0x21
+};
+static const uint8 kWrongKey[] = {
0x49, 0x27, 0x6d, 0x20, 0x61, 0x20, 0x77, 0x72,
0x6f, 0x6e, 0x67, 0x20, 0x6b, 0x65, 0x79, 0x2e
};
-static const uint8 kWebmWrongSizedKey[] = { 0x20, 0x20 };
-
-// This is the encrypted data from frame 0 of |kWebmEncryptedFrames| except
-// byte 0 is changed from 0xfb to 0xfc. Bytes 0-11 of WebM encrypted data
-// contains the HMAC.
-static const unsigned char kWebmFrame0HmacDataChanged[] = {
- 0xfc, 0xe7, 0x1d, 0xbb, 0x4c, 0x23, 0xce, 0xba,
- 0xcc, 0xf8, 0xda, 0xc0, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x99, 0xaa, 0xff, 0xb7,
- 0x74, 0x02, 0x4e, 0x1c, 0x75, 0x3d, 0xee, 0xcb,
- 0x64, 0xf7
+static const uint8 kWrongSizedKey[] = { 0x20, 0x20 };
+static const uint8 kKeyId1[] = {
+ 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44, 0x20, 0x31
};
-
-// This is the encrypted data from frame 0 of |kWebmEncryptedFrames| except
-// byte 12 is changed from 0xff to 0x0f. Bytes 12-19 of WebM encrypted data
-// contains the IV.
-static const unsigned char kWebmFrame0IvDataChanged[] = {
- 0xfb, 0xe7, 0x1d, 0xbb, 0x4c, 0x23, 0xce, 0xba,
- 0xcc, 0xf8, 0xda, 0xc0, 0x0f, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x99, 0xaa, 0xff, 0xb7,
- 0x74, 0x02, 0x4e, 0x1c, 0x75, 0x3d, 0xee, 0xcb,
- 0x64, 0xf7
-};
-
-// This is the encrypted data from frame 0 of |kWebmEncryptedFrames| except
-// byte 33 is changed from 0xf7 to 0xf8. Bytes 20+ of WebM encrypted data
-// contains the encrypted frame.
-static const unsigned char kWebmFrame0FrameDataChanged[] = {
- 0xfb, 0xe7, 0x1d, 0xbb, 0x4c, 0x23, 0xce, 0xba,
- 0xcc, 0xf8, 0xda, 0xc0, 0xff, 0xff, 0xff, 0xff,
- 0xff, 0xff, 0xff, 0xff, 0x99, 0xaa, 0xff, 0xb7,
- 0x74, 0x02, 0x4e, 0x1c, 0x75, 0x3d, 0xee, 0xcb,
- 0x64, 0xf8
+static const uint8 kKeyId2[] = {
+ 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44, 0x20, 0x32
};
class AesDecryptorTest : public testing::Test {
@@ -149,103 +56,60 @@ class AesDecryptorTest : public testing::Test {
: decryptor_(&client_),
decrypt_cb_(base::Bind(&AesDecryptorTest::BufferDecrypted,
base::Unretained(this))) {
+ encrypted_data_ = DecoderBuffer::CopyFrom(kEncryptedData,
+ arraysize(kEncryptedData));
}
protected:
- // Returns a 16 byte CTR counter block. The CTR counter block format is a
- // CTR IV appended with a CTR block counter. |iv| is a CTR IV. |iv_size| is
- // the size of |iv| in bytes.
- static std::string GenerateCounterBlock(const uint8* iv, int iv_size) {
- const int kDecryptionKeySize = 16;
- CHECK_GT(iv_size, 0);
- CHECK_LE(iv_size, kDecryptionKeySize);
- char counter_block_data[kDecryptionKeySize];
-
- // Set the IV.
- memcpy(counter_block_data, iv, iv_size);
-
- // Set block counter to all 0's.
- memset(counter_block_data + iv_size, 0, kDecryptionKeySize - iv_size);
-
- return std::string(counter_block_data, kDecryptionKeySize);
- }
-
- // Creates a WebM encrypted buffer that the demuxer would pass to the
- // decryptor. |data| is the payload of a WebM encrypted Block. |key_id| is
- // initialization data from the WebM file. Every encrypted Block has
- // an HMAC and IV prepended to an encrypted frame. Current encrypted WebM
- // request for comments specification is here
- // http://wiki.webmproject.org/encryption/webm-encryption-rfc
- scoped_refptr<DecoderBuffer> CreateWebMEncryptedBuffer(const uint8* data,
- int data_size,
- const uint8* key_id,
- int key_id_size) {
- scoped_refptr<DecoderBuffer> encrypted_buffer = DecoderBuffer::CopyFrom(
- data + kWebMHmacSize, data_size - kWebMHmacSize);
- CHECK(encrypted_buffer);
-
- uint64 network_iv;
- memcpy(&network_iv, data + kWebMHmacSize, sizeof(network_iv));
- const uint64 iv = base::NetToHost64(network_iv);
- std::string webm_iv =
- GenerateCounterBlock(reinterpret_cast<const uint8*>(&iv), sizeof(iv));
- encrypted_buffer->SetDecryptConfig(
- scoped_ptr<DecryptConfig>(new DecryptConfig(
- key_id, key_id_size,
- reinterpret_cast<const uint8*>(webm_iv.data()), webm_iv.size(),
- data, kWebMHmacSize,
- sizeof(iv))));
- return encrypted_buffer;
- }
-
- void GenerateKeyRequest(const uint8* key_id, int key_id_size) {
+ void GenerateKeyRequest() {
EXPECT_CALL(client_, KeyMessageMock(kClearKeySystem, StrNe(std::string()),
NotNull(), Gt(0), ""))
.WillOnce(SaveArg<1>(&session_id_string_));
- decryptor_.GenerateKeyRequest(kClearKeySystem, key_id, key_id_size);
+ decryptor_.GenerateKeyRequest(kClearKeySystem,
+ kInitData, arraysize(kInitData));
}
- void AddKeyAndExpectToSucceed(const uint8* key_id, int key_id_size,
- const uint8* key, int key_size) {
+ template <int KeyIdSize, int KeySize>
+ void AddKeyAndExpectToSucceed(const uint8 (&key_id)[KeyIdSize],
+ const uint8 (&key)[KeySize]) {
EXPECT_CALL(client_, KeyAdded(kClearKeySystem, session_id_string_));
- decryptor_.AddKey(kClearKeySystem, key, key_size, key_id, key_id_size,
+ decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize,
session_id_string_);
}
- void AddKeyAndExpectToFail(const uint8* key_id, int key_id_size,
- const uint8* key, int key_size) {
+ template <int KeyIdSize, int KeySize>
+ void AddKeyAndExpectToFail(const uint8 (&key_id)[KeyIdSize],
+ const uint8 (&key)[KeySize]) {
EXPECT_CALL(client_, KeyError(kClearKeySystem, session_id_string_,
Decryptor::kUnknownError, 0));
- decryptor_.AddKey(kClearKeySystem, key, key_size, key_id, key_id_size,
+ decryptor_.AddKey(kClearKeySystem, key, KeySize, key_id, KeyIdSize,
session_id_string_);
}
+ template <int KeyIdSize>
+ void SetKeyIdForEncryptedData(const uint8 (&key_id)[KeyIdSize]) {
+ encrypted_data_->SetDecryptConfig(
+ scoped_ptr<DecryptConfig>(new DecryptConfig(key_id, KeyIdSize)));
+ }
+
MOCK_METHOD2(BufferDecrypted, void(Decryptor::DecryptStatus,
const scoped_refptr<DecoderBuffer>&));
- void DecryptAndExpectToSucceed(const uint8* data, int data_size,
- const uint8* plain_text,
- int plain_text_size,
- const uint8* key_id, int key_id_size) {
- scoped_refptr<DecoderBuffer> encrypted_data =
- CreateWebMEncryptedBuffer(data, data_size, key_id, key_id_size);
+ void DecryptAndExpectToSucceed() {
scoped_refptr<DecoderBuffer> decrypted;
EXPECT_CALL(*this, BufferDecrypted(AesDecryptor::kSuccess, NotNull()))
.WillOnce(SaveArg<1>(&decrypted));
- decryptor_.Decrypt(encrypted_data, decrypt_cb_);
+ decryptor_.Decrypt(encrypted_data_, decrypt_cb_);
ASSERT_TRUE(decrypted);
- ASSERT_EQ(plain_text_size, decrypted->GetDataSize());
- EXPECT_EQ(0, memcmp(plain_text, decrypted->GetData(), plain_text_size));
+ int data_length = sizeof(kOriginalData);
+ ASSERT_EQ(data_length, decrypted->GetDataSize());
+ EXPECT_EQ(0, memcmp(kOriginalData, decrypted->GetData(), data_length));
}
- void DecryptAndExpectToFail(const uint8* data, int data_size,
- const uint8* plain_text, int plain_text_size,
- const uint8* key_id, int key_id_size) {
- scoped_refptr<DecoderBuffer> encrypted_data =
- CreateWebMEncryptedBuffer(data, data_size, key_id, key_id_size);
+ void DecryptAndExpectToFail() {
EXPECT_CALL(*this, BufferDecrypted(AesDecryptor::kError, IsNull()));
- decryptor_.Decrypt(encrypted_data, decrypt_cb_);
+ decryptor_.Decrypt(encrypted_data_, decrypt_cb_);
}
scoped_refptr<DecoderBuffer> encrypted_data_;
@@ -256,129 +120,39 @@ class AesDecryptorTest : public testing::Test {
};
TEST_F(AesDecryptorTest, NormalDecryption) {
- const WebmEncryptedData& frame = kWebmEncryptedFrames[0];
- GenerateKeyRequest(frame.key_id, frame.key_id_size);
- AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
- frame.key, frame.key_size);
- ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed(frame.encrypted_data,
- frame.encrypted_data_size,
- frame.plain_text,
- frame.plain_text_size,
- frame.key_id,
- frame.key_id_size));
+ GenerateKeyRequest();
+ AddKeyAndExpectToSucceed(kKeyId1, kRightKey);
+ SetKeyIdForEncryptedData(kKeyId1);
+ ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed());
}
TEST_F(AesDecryptorTest, WrongKey) {
- const WebmEncryptedData& frame = kWebmEncryptedFrames[0];
- GenerateKeyRequest(frame.key_id, frame.key_id_size);
- AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
- kWebmWrongKey, arraysize(kWebmWrongKey));
- ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail(frame.encrypted_data,
- frame.encrypted_data_size,
- frame.plain_text,
- frame.plain_text_size,
- frame.key_id,
- frame.key_id_size));
-}
-
-TEST_F(AesDecryptorTest, KeyReplacement) {
- const WebmEncryptedData& frame = kWebmEncryptedFrames[0];
- GenerateKeyRequest(frame.key_id, frame.key_id_size);
- AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
- kWebmWrongKey, arraysize(kWebmWrongKey));
- ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail(frame.encrypted_data,
- frame.encrypted_data_size,
- frame.plain_text,
- frame.plain_text_size,
- frame.key_id,
- frame.key_id_size));
- AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
- frame.key, frame.key_size);
- ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed(frame.encrypted_data,
- frame.encrypted_data_size,
- frame.plain_text,
- frame.plain_text_size,
- frame.key_id,
- frame.key_id_size));
-}
-
-TEST_F(AesDecryptorTest, WrongSizedKey) {
- const WebmEncryptedData& frame = kWebmEncryptedFrames[0];
- GenerateKeyRequest(frame.key_id, frame.key_id_size);
- AddKeyAndExpectToFail(frame.key_id, frame.key_id_size,
- kWebmWrongSizedKey, arraysize(kWebmWrongSizedKey));
-}
-
-TEST_F(AesDecryptorTest, MultipleKeysAndFrames) {
- const WebmEncryptedData& frame = kWebmEncryptedFrames[0];
- GenerateKeyRequest(frame.key_id, frame.key_id_size);
- AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
- frame.key, frame.key_size);
- ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed(frame.encrypted_data,
- frame.encrypted_data_size,
- frame.plain_text,
- frame.plain_text_size,
- frame.key_id,
- frame.key_id_size));
-
- const WebmEncryptedData& frame2 = kWebmEncryptedFrames[2];
- GenerateKeyRequest(frame2.key_id, frame2.key_id_size);
- AddKeyAndExpectToSucceed(frame2.key_id, frame2.key_id_size,
- frame2.key, frame2.key_size);
-
- const WebmEncryptedData& frame1 = kWebmEncryptedFrames[1];
- ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed(frame1.encrypted_data,
- frame1.encrypted_data_size,
- frame1.plain_text,
- frame1.plain_text_size,
- frame1.key_id,
- frame1.key_id_size));
-
- ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed(frame2.encrypted_data,
- frame2.encrypted_data_size,
- frame2.plain_text,
- frame2.plain_text_size,
- frame2.key_id,
- frame2.key_id_size));
+ GenerateKeyRequest();
+ AddKeyAndExpectToSucceed(kKeyId1, kWrongKey);
+ SetKeyIdForEncryptedData(kKeyId1);
+ ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail());
}
-TEST_F(AesDecryptorTest, HmacCheckFailure) {
- const WebmEncryptedData& frame = kWebmEncryptedFrames[0];
- GenerateKeyRequest(frame.key_id, frame.key_id_size);
- AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
- frame.key, frame.key_size);
- ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail(kWebmFrame0HmacDataChanged,
- frame.encrypted_data_size,
- frame.plain_text,
- frame.plain_text_size,
- frame.key_id,
- frame.key_id_size));
+TEST_F(AesDecryptorTest, MultipleKeys) {
+ GenerateKeyRequest();
+ AddKeyAndExpectToSucceed(kKeyId1, kRightKey);
+ AddKeyAndExpectToSucceed(kKeyId2, kWrongKey);
+ SetKeyIdForEncryptedData(kKeyId1);
+ ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed());
}
-TEST_F(AesDecryptorTest, IvCheckFailure) {
- const WebmEncryptedData& frame = kWebmEncryptedFrames[0];
- GenerateKeyRequest(frame.key_id, frame.key_id_size);
- AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
- frame.key, frame.key_size);
- ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail(kWebmFrame0IvDataChanged,
- frame.encrypted_data_size,
- frame.plain_text,
- frame.plain_text_size,
- frame.key_id,
- frame.key_id_size));
+TEST_F(AesDecryptorTest, KeyReplacement) {
+ GenerateKeyRequest();
+ SetKeyIdForEncryptedData(kKeyId1);
+ AddKeyAndExpectToSucceed(kKeyId1, kWrongKey);
+ ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail());
+ AddKeyAndExpectToSucceed(kKeyId1, kRightKey);
+ ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToSucceed());
}
-TEST_F(AesDecryptorTest, DataCheckFailure) {
- const WebmEncryptedData& frame = kWebmEncryptedFrames[0];
- GenerateKeyRequest(frame.key_id, frame.key_id_size);
- AddKeyAndExpectToSucceed(frame.key_id, frame.key_id_size,
- frame.key, frame.key_size);
- ASSERT_NO_FATAL_FAILURE(DecryptAndExpectToFail(kWebmFrame0FrameDataChanged,
- frame.encrypted_data_size,
- frame.plain_text,
- frame.plain_text_size,
- frame.key_id,
- frame.key_id_size));
+TEST_F(AesDecryptorTest, WrongSizedKey) {
+ GenerateKeyRequest();
+ AddKeyAndExpectToFail(kKeyId1, kWrongSizedKey);
}
-} // namespace media
+} // media
diff --git a/media/filters/ffmpeg_video_decoder_unittest.cc b/media/filters/ffmpeg_video_decoder_unittest.cc
index b60dce9..0131826 100644
--- a/media/filters/ffmpeg_video_decoder_unittest.cc
+++ b/media/filters/ffmpeg_video_decoder_unittest.cc
@@ -43,24 +43,17 @@ static const gfx::Rect kVisibleRect(320, 240);
static const gfx::Size kNaturalSize(522, 288);
static const AVRational kFrameRate = { 100, 1 };
static const AVRational kAspectRatio = { 1, 1 };
-
static const char kClearKeySystem[] = "org.w3.clearkey";
static const uint8 kInitData[] = { 0x69, 0x6e, 0x69, 0x74 };
-static const uint8 kWrongSecret[] = {
+static const uint8 kRightKey[] = {
+ 0x41, 0x20, 0x77, 0x6f, 0x6e, 0x64, 0x65, 0x72,
+ 0x66, 0x75, 0x6c, 0x20, 0x6b, 0x65, 0x79, 0x21
+};
+static const uint8 kWrongKey[] = {
0x49, 0x27, 0x6d, 0x20, 0x61, 0x20, 0x77, 0x72,
0x6f, 0x6e, 0x67, 0x20, 0x6b, 0x65, 0x79, 0x2e
};
static const uint8 kKeyId[] = { 0x4b, 0x65, 0x79, 0x20, 0x49, 0x44 };
-static const uint8 kSecretKey[] = {
- 0xfb, 0x67, 0x8a, 0x91, 0x19, 0x12, 0x7b, 0x6b,
- 0x0b, 0x63, 0x11, 0xf8, 0x6f, 0xe1, 0xc4, 0x2d
-};
-
-static const uint64 kIv = 3735928559;
-static const uint8 kHmac[] = {
- 0x16, 0xc0, 0x65, 0x1f, 0xf8, 0x0b, 0x36, 0x16,
- 0xb8, 0x32, 0x35, 0x56
-};
ACTION_P(ReturnBuffer, buffer) {
arg0.Run(buffer ? DemuxerStream::kOk : DemuxerStream::kAborted, buffer);
@@ -84,13 +77,8 @@ class FFmpegVideoDecoderTest : public testing::Test {
end_of_stream_buffer_ = DecoderBuffer::CreateEOSBuffer();
i_frame_buffer_ = ReadTestDataFile("vp8-I-frame-320x240");
corrupt_i_frame_buffer_ = ReadTestDataFile("vp8-corrupt-I-frame");
- {
- scoped_refptr<DecoderBuffer> temp_buffer = ReadTestDataFile(
- "vp8-encrypted-I-frame-320x240");
- encrypted_i_frame_buffer_ = DecoderBuffer::CopyFrom(
- temp_buffer->GetData() + arraysize(kHmac),
- temp_buffer->GetDataSize() - arraysize(kHmac));
- }
+ encrypted_i_frame_buffer_ = ReadTestDataFile(
+ "vp8-encrypted-I-frame-320x240");
config_.Initialize(kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN,
kVideoFormat, kCodedSize, kVisibleRect,
@@ -219,24 +207,6 @@ class FFmpegVideoDecoderTest : public testing::Test {
message_loop_.RunAllPending();
}
- // Generates a 16 byte CTR counter block. The CTR counter block format is a
- // CTR IV appended with a CTR block counter. |iv| is an 8 byte CTR IV.
- static scoped_array<uint8> GenerateCounterBlock(uint64 iv) {
- scoped_array<uint8> counter_block_data(
- new uint8[DecryptConfig::kDecryptionKeySize]);
-
- // Set the IV.
- memcpy(counter_block_data.get(), &iv, sizeof(iv));
-
- // Set block counter to all 0's.
- memset(counter_block_data.get() + sizeof(iv),
- 0,
- DecryptConfig::kDecryptionKeySize - sizeof(iv));
-
- return counter_block_data.Pass();
- }
-
-
MOCK_METHOD2(FrameReady, void(VideoDecoder::DecoderStatus,
const scoped_refptr<VideoFrame>&));
@@ -418,9 +388,7 @@ TEST_F(FFmpegVideoDecoderTest, DecodeFrame_SmallerHeight) {
DecodeIFrameThenTestFile("vp8-I-frame-320x120", 320, 120);
}
-// TODO(fgalligan): Enable test when encrypted test data is updated and new
-// decryption code is landed. http://crbug.com/132801
-TEST_F(FFmpegVideoDecoderTest, DISABLED_DecodeEncryptedFrame_Normal) {
+TEST_F(FFmpegVideoDecoderTest, DecodeEncryptedFrame_Normal) {
Initialize();
std::string sessing_id_string;
EXPECT_CALL(decryptor_client_,
@@ -430,18 +398,12 @@ TEST_F(FFmpegVideoDecoderTest, DISABLED_DecodeEncryptedFrame_Normal) {
decryptor_->GenerateKeyRequest(kClearKeySystem,
kInitData, arraysize(kInitData));
EXPECT_CALL(decryptor_client_, KeyAdded(kClearKeySystem, sessing_id_string));
- decryptor_->AddKey(kClearKeySystem, kSecretKey, arraysize(kSecretKey),
+ decryptor_->AddKey(kClearKeySystem, kRightKey, arraysize(kRightKey),
kKeyId, arraysize(kKeyId), sessing_id_string);
// Simulate decoding a single encrypted frame.
- scoped_array<uint8> counter_block(GenerateCounterBlock(kIv));
encrypted_i_frame_buffer_->SetDecryptConfig(scoped_ptr<DecryptConfig>(
- new DecryptConfig(
- kKeyId, arraysize(kKeyId),
- counter_block.get(), DecryptConfig::kDecryptionKeySize,
- kHmac, arraysize(kHmac),
- sizeof(kIv))));
-
+ new DecryptConfig(kKeyId, arraysize(kKeyId))));
VideoDecoder::DecoderStatus status;
scoped_refptr<VideoFrame> video_frame;
DecodeSingleFrame(encrypted_i_frame_buffer_, &status, &video_frame);
@@ -456,13 +418,8 @@ TEST_F(FFmpegVideoDecoderTest, DecodeEncryptedFrame_NoKey) {
Initialize();
// Simulate decoding a single encrypted frame.
- scoped_array<uint8> counter_block(GenerateCounterBlock(kIv));
encrypted_i_frame_buffer_->SetDecryptConfig(scoped_ptr<DecryptConfig>(
- new DecryptConfig(
- kKeyId, arraysize(kKeyId),
- counter_block.get(), DecryptConfig::kDecryptionKeySize,
- kHmac, arraysize(kHmac),
- sizeof(kIv))));
+ new DecryptConfig(kKeyId, arraysize(kKeyId))));
EXPECT_CALL(*demuxer_, Read(_))
.WillRepeatedly(ReturnBuffer(encrypted_i_frame_buffer_));
@@ -482,27 +439,31 @@ TEST_F(FFmpegVideoDecoderTest, DecodeEncryptedFrame_NoKey) {
TEST_F(FFmpegVideoDecoderTest, DecodeEncryptedFrame_WrongKey) {
Initialize();
EXPECT_CALL(decryptor_client_, KeyAdded("", ""));
- decryptor_->AddKey("", kWrongSecret, arraysize(kWrongSecret),
+ decryptor_->AddKey("", kWrongKey, arraysize(kWrongKey),
kKeyId, arraysize(kKeyId), "");
- // Simulate decoding a single encrypted frame.
- scoped_array<uint8> counter_block(GenerateCounterBlock(kIv));
encrypted_i_frame_buffer_->SetDecryptConfig(scoped_ptr<DecryptConfig>(
- new DecryptConfig(
- kKeyId, arraysize(kKeyId),
- counter_block.get(), DecryptConfig::kDecryptionKeySize,
- kHmac, arraysize(kHmac),
- sizeof(kIv))));
-
+ new DecryptConfig(kKeyId, arraysize(kKeyId))));
EXPECT_CALL(*demuxer_, Read(_))
.WillRepeatedly(ReturnBuffer(encrypted_i_frame_buffer_));
+ // Using the wrong key on some platforms doesn't cause an decryption error but
+ // actually attempts to decode the content, however we're unable to
+ // distinguish between the two (see http://crbug.com/124434).
+#if defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
+ EXPECT_CALL(statistics_cb_, OnStatistics(_));
+#endif
+
// Our read should still get satisfied with end of stream frame during an
// error.
VideoDecoder::DecoderStatus status;
scoped_refptr<VideoFrame> video_frame;
Read(&status, &video_frame);
+#if defined(USE_NSS) || defined(OS_WIN) || defined(OS_MACOSX)
+ EXPECT_EQ(VideoDecoder::kDecodeError, status);
+#else
EXPECT_EQ(VideoDecoder::kDecryptError, status);
+#endif
EXPECT_FALSE(video_frame);
message_loop_.RunAllPending();
diff --git a/media/filters/pipeline_integration_test.cc b/media/filters/pipeline_integration_test.cc
index cae8b78..c207858 100644
--- a/media/filters/pipeline_integration_test.cc
+++ b/media/filters/pipeline_integration_test.cc
@@ -18,12 +18,6 @@ static const char kSourceId[] = "SourceId";
static const char kClearKeySystem[] = "org.w3.clearkey";
static const uint8 kInitData[] = { 0x69, 0x6e, 0x69, 0x74 };
-// Key used to encrypt video track in test file "bear-320x240-encrypted.webm".
-static const uint8 kSecretKey[] = {
- 0xfb, 0x67, 0x8a, 0x91, 0x19, 0x12, 0x7b, 0x6b,
- 0x0b, 0x63, 0x11, 0xf8, 0x6f, 0xe1, 0xc4, 0x2d
-};
-
// Helper class that emulates calls made on the ChunkDemuxer by the
// Media Source API.
class MockMediaSource : public ChunkDemuxerClient {
@@ -102,7 +96,7 @@ class MockMediaSource : public ChunkDemuxerClient {
virtual void DemuxerNeedKey(scoped_array<uint8> init_data,
int init_data_size) {
DCHECK(init_data.get());
- DCHECK_GT(init_data_size, 0);
+ DCHECK_EQ(init_data_size, 16);
DCHECK(decryptor_client_);
decryptor_client_->NeedKey("", "", init_data.Pass(), init_data_size);
}
@@ -172,7 +166,9 @@ class FakeDecryptorClient : public DecryptorClient {
EXPECT_FALSE(current_key_system_.empty());
EXPECT_FALSE(current_session_id_.empty());
- decryptor_.AddKey(current_key_system_, kSecretKey, arraysize(kSecretKey),
+ // In test file bear-320x240-encrypted.webm, the decryption key is equal to
+ // |init_data|.
+ decryptor_.AddKey(current_key_system_, init_data.get(), init_data_length,
init_data.get(), init_data_length, current_session_id_);
}
@@ -284,9 +280,7 @@ TEST_F(PipelineIntegrationTest, BasicPlayback_MediaSource) {
Stop();
}
-// TODO(fgalligan): Enable test when encrypted test data is updated and new
-// decryption code is landed. http://crbug.com/132801
-TEST_F(PipelineIntegrationTest, DISABLED_EncryptedPlayback) {
+TEST_F(PipelineIntegrationTest, EncryptedPlayback) {
MockMediaSource source("bear-320x240-encrypted.webm", 219726, true, true);
FakeDecryptorClient encrypted_media;
StartPipelineWithEncryptedMedia(&source, &encrypted_media);
diff --git a/media/webm/webm_cluster_parser.cc b/media/webm/webm_cluster_parser.cc
index 20d131e..c5a2fdc 100644
--- a/media/webm/webm_cluster_parser.cc
+++ b/media/webm/webm_cluster_parser.cc
@@ -5,31 +5,12 @@
#include "media/webm/webm_cluster_parser.h"
#include "base/logging.h"
-#include "base/sys_byteorder.h"
#include "media/base/data_buffer.h"
#include "media/base/decrypt_config.h"
#include "media/webm/webm_constants.h"
namespace media {
-// Generates a 16 byte CTR counter block. The CTR counter block format is a
-// CTR IV appended with a CTR block counter. |iv| is an 8 byte CTR IV.
-// Always returns a valid pointer to a buffer of kDecryptionKeySize bytes.
-static scoped_array<uint8> GenerateCounterBlock(uint64 iv) {
- scoped_array<uint8> counter_block_data(
- new uint8[DecryptConfig::kDecryptionKeySize]);
-
- // Set the IV.
- memcpy(counter_block_data.get(), &iv, sizeof(iv));
-
- // Set block counter to all 0's.
- memset(counter_block_data.get() + sizeof(iv),
- 0,
- DecryptConfig::kDecryptionKeySize - sizeof(iv));
-
- return counter_block_data.Pass();
-}
-
WebMClusterParser::WebMClusterParser(int64 timecode_scale,
int audio_track_num,
int video_track_num,
@@ -212,33 +193,15 @@ bool WebMClusterParser::OnBlock(int track_num, int timecode,
base::TimeDelta timestamp = base::TimeDelta::FromMicroseconds(
(cluster_timecode_ + timecode) * timecode_multiplier_);
- // Every encrypted Block has an HMAC and IV prepended to it. Current encrypted
- // WebM request for comments specification is here
- // http://wiki.webmproject.org/encryption/webm-encryption-rfc
- bool encrypted = track_num == video_.track_num() &&
- video_encryption_key_id_.get();
- // If encrypted skip past the HMAC. Encrypted buffers must include the IV and
- // the encrypted frame because the decryptor will verify this data before
- // decryption. The HMAC and IV will be copied into DecryptConfig.
- int offset = (encrypted) ? kWebMHmacSize : 0;
-
// The first bit of the flags is set when the block contains only keyframes.
// http://www.matroska.org/technical/specs/index.html
bool is_keyframe = (flags & 0x80) != 0;
scoped_refptr<StreamParserBuffer> buffer =
- StreamParserBuffer::CopyFrom(data + offset, size - offset, is_keyframe);
-
- if (encrypted) {
- uint64 network_iv;
- memcpy(&network_iv, data + kWebMHmacSize, sizeof(network_iv));
- const uint64 iv = base::NetToHost64(network_iv);
+ StreamParserBuffer::CopyFrom(data, size, is_keyframe);
- scoped_array<uint8> counter_block(GenerateCounterBlock(iv));
+ if (track_num == video_.track_num() && video_encryption_key_id_.get()) {
buffer->SetDecryptConfig(scoped_ptr<DecryptConfig>(new DecryptConfig(
- video_encryption_key_id_.get(), video_encryption_key_id_size_,
- counter_block.get(), DecryptConfig::kDecryptionKeySize,
- data, kWebMHmacSize,
- sizeof(iv))));
+ video_encryption_key_id_.get(), video_encryption_key_id_size_)));
}
buffer->SetTimestamp(timestamp);
diff --git a/media/webm/webm_cluster_parser.h b/media/webm/webm_cluster_parser.h
index 2bdb1e7..0af0361 100644
--- a/media/webm/webm_cluster_parser.h
+++ b/media/webm/webm_cluster_parser.h
@@ -19,10 +19,6 @@ class MEDIA_EXPORT WebMClusterParser : public WebMParserClient {
public:
typedef std::deque<scoped_refptr<StreamParserBuffer> > BufferQueue;
- // Size is defined by the WebM encryption specification.
- // http://wiki.webmproject.org/encryption/webm-encryption-rfc
- static const int kIvSize = 8;
-
WebMClusterParser(int64 timecode_scale,
int audio_track_num,
int video_track_num,
diff --git a/media/webm/webm_constants.h b/media/webm/webm_constants.h
index 93041b2..b6ba0a2 100644
--- a/media/webm/webm_constants.h
+++ b/media/webm/webm_constants.h
@@ -12,7 +12,6 @@ namespace media {
// WebM element IDs.
// This is a subset of the IDs in the Matroska spec.
// http://www.matroska.org/technical/specs/index.html
-const int kWebMIdAESSettingsCipherMode = 0x47E8;
const int kWebMIdAspectRatioType = 0x54B3;
const int kWebMIdAttachedFile = 0x61A7;
const int kWebMIdAttachmentLink = 0x7446;
@@ -63,7 +62,6 @@ const int kWebMIdColorSpace = 0x2EB524;
const int kWebMIdContentCompAlgo = 0x4254;
const int kWebMIdContentCompression = 0x5034;
const int kWebMIdContentCompSettings = 0x4255;
-const int kWebMIdContentEncAESSettings = 0x47E7;
const int kWebMIdContentEncAlgo = 0x47E1;
const int kWebMIdContentEncKeyID = 0x47E2;
const int kWebMIdContentEncoding = 0x6240;
@@ -199,11 +197,6 @@ const int64 kWebMUnknownSize = GG_LONGLONG(0x00FFFFFFFFFFFFFF);
const uint8 kWebMFlagKeyframe = 0x80;
-// The size is from the WebM encrypted specification. Current encrypted WebM
-// request for comments specification is here
-// http://wiki.webmproject.org/encryption/webm-encryption-rfc
-const int kWebMHmacSize = 12;
-
} // namespace media
#endif // MEDIA_WEBM_WEBM_CONSTANTS_H_
diff --git a/media/webm/webm_content_encodings.cc b/media/webm/webm_content_encodings.cc
index 540ac99..a5b7bfe 100644
--- a/media/webm/webm_content_encodings.cc
+++ b/media/webm/webm_content_encodings.cc
@@ -12,8 +12,7 @@ ContentEncoding::ContentEncoding()
scope_(kScopeInvalid),
type_(kTypeInvalid),
encryption_algo_(kEncAlgoInvalid),
- encryption_key_id_size_(0),
- cipher_mode_(kCipherModeInvalid) {
+ encryption_key_id_size_(0) {
}
ContentEncoding::~ContentEncoding() {}
diff --git a/media/webm/webm_content_encodings.h b/media/webm/webm_content_encodings.h
index ea903d8..2947a26 100644
--- a/media/webm/webm_content_encodings.h
+++ b/media/webm/webm_content_encodings.h
@@ -42,11 +42,6 @@ class MEDIA_EXPORT ContentEncoding {
kEncAlgoAes = 5,
};
- enum CipherMode {
- kCipherModeInvalid = 0,
- kCipherModeCtr = 1,
- };
-
ContentEncoding();
~ContentEncoding();
@@ -69,9 +64,6 @@ class MEDIA_EXPORT ContentEncoding {
void SetEncryptionKeyId(const uint8* encryption_key_id, int size);
- CipherMode cipher_mode() const { return cipher_mode_; }
- void set_cipher_mode(CipherMode mode) { cipher_mode_ = mode; }
-
private:
int64 order_;
Scope scope_;
@@ -79,7 +71,6 @@ class MEDIA_EXPORT ContentEncoding {
EncryptionAlgo encryption_algo_;
scoped_array<uint8> encryption_key_id_;
int encryption_key_id_size_;
- CipherMode cipher_mode_;
DISALLOW_COPY_AND_ASSIGN(ContentEncoding);
};
diff --git a/media/webm/webm_content_encodings_client.cc b/media/webm/webm_content_encodings_client.cc
index a24b4bf..086f85b 100644
--- a/media/webm/webm_content_encodings_client.cc
+++ b/media/webm/webm_content_encodings_client.cc
@@ -50,11 +50,6 @@ WebMParserClient* WebMContentEncodingsClient::OnListStart(int id) {
return this;
}
- if (id == kWebMIdContentEncAESSettings) {
- DCHECK(cur_content_encoding_.get());
- return this;
- }
-
// This should not happen if WebMListParser is working properly.
DCHECK(false);
return NULL;
@@ -126,13 +121,6 @@ bool WebMContentEncodingsClient::OnListEnd(int id) {
return true;
}
- if (id == kWebMIdContentEncAESSettings) {
- if (cur_content_encoding_->cipher_mode() ==
- ContentEncoding::kCipherModeInvalid)
- cur_content_encoding_->set_cipher_mode(ContentEncoding::kCipherModeCtr);
- return true;
- }
-
// This should not happen if WebMListParser is working properly.
DCHECK(false);
return false;
@@ -218,23 +206,6 @@ bool WebMContentEncodingsClient::OnUInt(int id, int64 val) {
return true;
}
- if (id == kWebMIdAESSettingsCipherMode) {
- if (cur_content_encoding_->cipher_mode() !=
- ContentEncoding::kCipherModeInvalid) {
- DVLOG(1) << "Unexpected multiple AESSettingsCipherMode.";
- return false;
- }
-
- if (val != ContentEncoding::kCipherModeCtr) {
- DVLOG(1) << "Unexpected AESSettingsCipherMode " << val << ".";
- return false;
- }
-
- cur_content_encoding_->set_cipher_mode(
- static_cast<ContentEncoding::CipherMode>(val));
- return true;
- }
-
// This should not happen if WebMListParser is working properly.
DCHECK(false);
return false;
diff --git a/media/webm/webm_parser.cc b/media/webm/webm_parser.cc
index 9952efa..28c847b 100644
--- a/media/webm/webm_parser.cc
+++ b/media/webm/webm_parser.cc
@@ -7,9 +7,6 @@
// This file contains code to parse WebM file elements. It was created
// from information in the Matroska spec.
// http://www.matroska.org/technical/specs/index.html
-// This file contains code for encrypted WebM. Current WebM
-// encrypted request for comments specification is here
-// http://wiki.webmproject.org/encryption/webm-encryption-rfc
#include <iomanip>
@@ -235,7 +232,6 @@ static const ElementIdInfo kContentCompressionIds[] = {
};
static const ElementIdInfo kContentEncryptionIds[] = {
- {LIST, kWebMIdContentEncAESSettings},
{UINT, kWebMIdContentEncAlgo},
{BINARY, kWebMIdContentEncKeyID},
{BINARY, kWebMIdContentSignature},
@@ -244,10 +240,6 @@ static const ElementIdInfo kContentEncryptionIds[] = {
{UINT, kWebMIdContentSigHashAlgo},
};
-static const ElementIdInfo kContentEncAESSettingsIds[] = {
- {UINT, kWebMIdAESSettingsCipherMode},
-};
-
static const ElementIdInfo kCuesIds[] = {
{LIST, kWebMIdCuePoint},
};
@@ -384,7 +376,6 @@ static const ListElementInfo kListElementInfo[] = {
LIST_ELEMENT_INFO(kWebMIdContentEncoding, 4, kContentEncodingIds),
LIST_ELEMENT_INFO(kWebMIdContentCompression, 5, kContentCompressionIds),
LIST_ELEMENT_INFO(kWebMIdContentEncryption, 5, kContentEncryptionIds),
- LIST_ELEMENT_INFO(kWebMIdContentEncAESSettings, 6, kContentEncAESSettingsIds),
LIST_ELEMENT_INFO(kWebMIdCues, 1, kCuesIds),
LIST_ELEMENT_INFO(kWebMIdCuePoint, 2, kCuePointIds),
LIST_ELEMENT_INFO(kWebMIdCueTrackPositions, 3, kCueTrackPositionsIds),
diff --git a/media/webm/webm_stream_parser.cc b/media/webm/webm_stream_parser.cc
index d141bfd..602d227 100644
--- a/media/webm/webm_stream_parser.cc
+++ b/media/webm/webm_stream_parser.cc
@@ -352,7 +352,6 @@ int WebMStreamParser::ParseInfoAndTracks(const uint8* data, int size) {
if (tracks_parser.video_encryption_key_id()) {
int key_id_size = tracks_parser.video_encryption_key_id_size();
CHECK_GT(key_id_size, 0);
- CHECK_LT(key_id_size, 2048);
scoped_array<uint8> key_id(new uint8[key_id_size]);
memcpy(key_id.get(), tracks_parser.video_encryption_key_id(), key_id_size);
need_key_cb_.Run(key_id.Pass(), key_id_size);