diff options
Diffstat (limited to 'media/crypto')
-rw-r--r-- | media/crypto/DEPS | 3 | ||||
-rw-r--r-- | media/crypto/aes_decryptor.cc | 78 | ||||
-rw-r--r-- | media/crypto/aes_decryptor.h | 32 | ||||
-rw-r--r-- | media/crypto/aes_decryptor_unittest.cc | 56 |
4 files changed, 169 insertions, 0 deletions
diff --git a/media/crypto/DEPS b/media/crypto/DEPS new file mode 100644 index 0000000..4ef4138 --- /dev/null +++ b/media/crypto/DEPS @@ -0,0 +1,3 @@ +include_rules = [ + "+crypto", +] diff --git a/media/crypto/aes_decryptor.cc b/media/crypto/aes_decryptor.cc new file mode 100644 index 0000000..8e83daf --- /dev/null +++ b/media/crypto/aes_decryptor.cc @@ -0,0 +1,78 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "media/crypto/aes_decryptor.h" + +#include <string> + +#include "base/logging.h" +#include "crypto/encryptor.h" +#include "crypto/symmetric_key.h" +#include "media/base/buffers.h" +#include "media/base/data_buffer.h" +#include "media/base/decrypt_config.h" + +namespace media { + +static const char* kInitialCounter = "0000000000000000"; + +// Decrypts |input| using |raw_key|, which is the binary data for the decryption +// key. +// Return a scoped_refptr to a Buffer object with the decrypted data on success. +// Return a scoped_refptr to NULL if the data could not be decrypted. +// TODO(xhwang): Both the input and output are copied! Any performance concern? +static scoped_refptr<Buffer> DecryptData(const Buffer& input, + const uint8* raw_key, + int raw_key_size) { + CHECK(raw_key && raw_key_size > 0); + CHECK(input.GetDataSize()); + + scoped_ptr<crypto::SymmetricKey> key(crypto::SymmetricKey::Import( + crypto::SymmetricKey::AES, + std::string(reinterpret_cast<const char*>(raw_key), raw_key_size))); + if (!key.get()) { + DVLOG(1) << "Could not import key."; + return NULL; + } + + // Initialize encryption data. + // The IV must be exactly as long as the cipher block size. + crypto::Encryptor encryptor; + if (!encryptor.Init(key.get(), crypto::Encryptor::CBC, kInitialCounter)) { + DVLOG(1) << "Could not initialize encryptor."; + return NULL; + } + + std::string decrypt_text; + std::string encrypted_text(reinterpret_cast<const char*>(input.GetData()), + input.GetDataSize()); + if (!encryptor.Decrypt(encrypted_text, &decrypt_text)) { + DVLOG(1) << "Could not decrypt data."; + return NULL; + } + + return DataBuffer::CopyFrom( + reinterpret_cast<const uint8*>(decrypt_text.data()), + decrypt_text.size()); +} + +AesDecryptor::AesDecryptor() {} + +scoped_refptr<Buffer> AesDecryptor::Decrypt( + const scoped_refptr<Buffer>& encrypted) { + CHECK(encrypted->GetDecryptConfig()); + + // For now, the key is the key ID. + const uint8* key = encrypted->GetDecryptConfig()->key_id(); + int key_size = encrypted->GetDecryptConfig()->key_id_size(); + scoped_refptr<Buffer> decrypted = DecryptData(*encrypted, key, key_size); + if (decrypted) { + decrypted->SetTimestamp(encrypted->GetTimestamp()); + decrypted->SetDuration(encrypted->GetDuration()); + } + + return decrypted; +} + +} // namespace media diff --git a/media/crypto/aes_decryptor.h b/media/crypto/aes_decryptor.h new file mode 100644 index 0000000..32d6802 --- /dev/null +++ b/media/crypto/aes_decryptor.h @@ -0,0 +1,32 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef MEDIA_CRYPTO_AES_DECRYPTOR_H_ +#define MEDIA_CRYPTO_AES_DECRYPTOR_H_ + +#include "base/basictypes.h" +#include "base/memory/ref_counted.h" +#include "media/base/media_export.h" + +namespace media { + +class Buffer; + +// Decrypts AES encrypted buffer into unencrypted buffer. +class MEDIA_EXPORT AesDecryptor { + public: + AesDecryptor(); + + // Decrypt |input| buffer. The |input| should not be NULL. + // Return a Buffer that contains decrypted data if decryption succeeded. + // Return NULL if decryption failed. + scoped_refptr<Buffer> Decrypt(const scoped_refptr<Buffer>& input); + + private: + DISALLOW_COPY_AND_ASSIGN(AesDecryptor); +}; + +} // namespace media + +#endif // MEDIA_CRYPTO_AES_DECRYPTOR_H_ diff --git a/media/crypto/aes_decryptor_unittest.cc b/media/crypto/aes_decryptor_unittest.cc new file mode 100644 index 0000000..0143bd0 --- /dev/null +++ b/media/crypto/aes_decryptor_unittest.cc @@ -0,0 +1,56 @@ +// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include <string> + +#include "media/base/data_buffer.h" +#include "media/base/decrypt_config.h" +#include "media/crypto/aes_decryptor.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +// |kEncryptedDataHex| is encrypted from |kOriginalData| using |kRawKey|, whose +// length is |kKeySize|. Modifying any of these independently would fail the +// test. +static const char kOriginalData[] = "Original data."; +static const int kEncryptedDataSize = 16; +static const unsigned char kEncryptedData[] = + "\x82\x3A\x76\x92\xEC\x7F\xF8\x85\xEC\x23\x52\xFB\x19\xB1\xB9\x09"; +static const int kKeySize = 16; +static const unsigned char kRawKey[] = "A wonderful key!"; +static const unsigned char kWrongKey[] = "I'm a wrong key."; + +class AesDecryptorTest : public testing::Test { + public: + AesDecryptorTest() { + encrypted_data_ = DataBuffer::CopyFrom(kEncryptedData, kEncryptedDataSize); + } + + protected: + void SetKey(const uint8* key, int key_size) { + encrypted_data_->SetDecryptConfig( + scoped_ptr<DecryptConfig>(new DecryptConfig(key, key_size))); + } + + scoped_refptr<DataBuffer> encrypted_data_; + AesDecryptor decryptor_; +}; + +TEST_F(AesDecryptorTest, NormalDecryption) { + SetKey(kRawKey, kKeySize); + scoped_refptr<Buffer> decrypted_data = decryptor_.Decrypt(encrypted_data_); + ASSERT_TRUE(decrypted_data.get()); + size_t data_length = sizeof(kOriginalData) - 1; + ASSERT_EQ(data_length, decrypted_data->GetDataSize()); + ASSERT_EQ(0, memcmp(kOriginalData, decrypted_data->GetData(), data_length)); +} + +TEST_F(AesDecryptorTest, WrongKey) { + SetKey(kWrongKey, kKeySize); + scoped_refptr<Buffer> decrypted_data = decryptor_.Decrypt(encrypted_data_); + EXPECT_FALSE(decrypted_data.get()); +} + +} // media |