More cleanups in AesEncryptor and AesDecryptor
- Create AesCryptor class as the common base - AesCryptor::Crypt function will serve as an Encrypt function for encryptor and a Decrypt function for Decryptor. Change-Id: Ie91fb14964b5091786705bf510656f40d73af160
This commit is contained in:
parent
e92556658e
commit
5fc09763ce
|
@ -0,0 +1,59 @@
|
|||
// Copyright 2016 Google Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#include "packager/media/base/aes_cryptor.h"
|
||||
|
||||
#include <openssl/aes.h>
|
||||
|
||||
#include "packager/base/logging.h"
|
||||
#include "packager/base/stl_util.h"
|
||||
|
||||
namespace edash_packager {
|
||||
namespace media {
|
||||
|
||||
AesCryptor::AesCryptor() : aes_key_(new AES_KEY) {}
|
||||
AesCryptor::~AesCryptor() {}
|
||||
|
||||
bool AesCryptor::Crypt(const std::vector<uint8_t>& text,
|
||||
std::vector<uint8_t>* crypt_text) {
|
||||
// Save text size to make it work for in-place conversion, since the
|
||||
// next statement will update the text size.
|
||||
const size_t text_size = text.size();
|
||||
crypt_text->resize(text_size + NumPaddingBytes(text_size));
|
||||
size_t crypt_text_size = crypt_text->size();
|
||||
if (!CryptInternal(text.data(), text_size, crypt_text->data(),
|
||||
&crypt_text_size)) {
|
||||
return false;
|
||||
}
|
||||
DCHECK_LE(crypt_text_size, crypt_text->size());
|
||||
crypt_text->resize(crypt_text_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AesCryptor::Crypt(const std::string& text, std::string* crypt_text) {
|
||||
// Save text size to make it work for in-place conversion, since the
|
||||
// next statement will update the text size.
|
||||
const size_t text_size = text.size();
|
||||
crypt_text->resize(text_size + NumPaddingBytes(text_size));
|
||||
size_t crypt_text_size = crypt_text->size();
|
||||
if (!CryptInternal(reinterpret_cast<const uint8_t*>(text.data()), text_size,
|
||||
reinterpret_cast<uint8_t*>(string_as_array(crypt_text)),
|
||||
&crypt_text_size))
|
||||
return false;
|
||||
DCHECK_LE(crypt_text_size, crypt_text->size());
|
||||
crypt_text->resize(crypt_text_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
size_t AesCryptor::NumPaddingBytes(size_t size) const {
|
||||
// No padding by default.
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace media
|
||||
} // namespace edash_packager
|
||||
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
// Copyright 2016 Google Inc. All rights reserved.
|
||||
//
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file or at
|
||||
// https://developers.google.com/open-source/licenses/bsd
|
||||
|
||||
#ifndef PACKAGER_MEDIA_BASE_AES_CRYPTOR_H_
|
||||
#define PACKAGER_MEDIA_BASE_AES_CRYPTOR_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "packager/base/macros.h"
|
||||
#include "packager/base/memory/scoped_ptr.h"
|
||||
|
||||
struct aes_key_st;
|
||||
typedef struct aes_key_st AES_KEY;
|
||||
|
||||
namespace edash_packager {
|
||||
namespace media {
|
||||
|
||||
// AES cryptor interface. Inherited by various AES encryptor and decryptor
|
||||
// implementations.
|
||||
class AesCryptor {
|
||||
public:
|
||||
AesCryptor();
|
||||
virtual ~AesCryptor();
|
||||
|
||||
/// Initialize the cryptor with specified key and IV.
|
||||
/// @return true on successful initialization, false otherwise.
|
||||
virtual bool InitializeWithIv(const std::vector<uint8_t>& key,
|
||||
const std::vector<uint8_t>& iv) = 0;
|
||||
|
||||
/// @name Various forms of crypt (Encrypt/Decrypt) calls.
|
||||
/// It is an Encrypt function for encryptor and a Decrypt function for
|
||||
/// decryptor. The text and crypt_text pointers can be the same address for
|
||||
/// in place encryption/decryption.
|
||||
/// @{
|
||||
bool Crypt(const std::vector<uint8_t>& text,
|
||||
std::vector<uint8_t>* crypt_text);
|
||||
bool Crypt(const std::string& text, std::string* crypt_text);
|
||||
/// @param crypt_text should have at least @a text_size bytes.
|
||||
bool Crypt(const uint8_t* text, size_t text_size, uint8_t* crypt_text) {
|
||||
size_t crypt_text_size = text_size;
|
||||
return CryptInternal(text, text_size, crypt_text, &crypt_text_size);
|
||||
}
|
||||
/// @}
|
||||
|
||||
/// Set IV.
|
||||
/// @return true if successful, false if the input is invalid.
|
||||
virtual bool SetIv(const std::vector<uint8_t>& iv) = 0;
|
||||
|
||||
/// Update IV for next sample. As recommended in ISO/IEC 23001-7: IV need to
|
||||
/// be updated per sample for CENC.
|
||||
/// This is used by encryptors only.
|
||||
virtual void UpdateIv() = 0;
|
||||
|
||||
/// @return The current iv.
|
||||
const std::vector<uint8_t>& iv() const { return iv_; }
|
||||
|
||||
protected:
|
||||
void set_iv(const std::vector<uint8_t>& iv) { iv_ = iv; }
|
||||
const AES_KEY* aes_key() const { return aes_key_.get(); }
|
||||
AES_KEY* mutable_aes_key() { return aes_key_.get(); }
|
||||
|
||||
private:
|
||||
// Internal implementation of crypt function.
|
||||
// |text| points to the input text.
|
||||
// |text_size| is the size of input text.
|
||||
// |crypt_text| points to the output encrypted or decrypted text, depends on
|
||||
// whether it is an encryption or decryption. |text| and |crypt_text| can
|
||||
// point to the same address for in place encryption/decryption.
|
||||
// |crypt_text_size| contains the size of |crypt_text| and it will be updated
|
||||
// to contain the actual encrypted/decrypted size for |crypt_text| on success.
|
||||
// Return false if the input |crypt_text_size| is not large enough to hold the
|
||||
// output |crypt_text| or if there is any error in encryption/decryption.
|
||||
virtual bool CryptInternal(const uint8_t* text,
|
||||
size_t text_size,
|
||||
uint8_t* crypt_text,
|
||||
size_t* crypt_text_size) = 0;
|
||||
|
||||
// |size| specifies the input text size.
|
||||
// Return the number of padding bytes needed.
|
||||
// Note: No paddings should be needed except for pkcs5-cbc encryptor.
|
||||
virtual size_t NumPaddingBytes(size_t size) const;
|
||||
|
||||
// Initialization vector, with size 8 or 16.
|
||||
std::vector<uint8_t> iv_;
|
||||
// Openssl AES_KEY.
|
||||
scoped_ptr<AES_KEY> aes_key_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AesCryptor);
|
||||
};
|
||||
|
||||
} // namespace media
|
||||
} // namespace edash_packager
|
||||
|
||||
#endif // PACKAGER_MEDIA_BASE_AES_CRYPTOR_H_
|
||||
|
||||
|
|
@ -159,22 +159,22 @@ class AesCtrEncryptorTest : public testing::Test {
|
|||
|
||||
TEST_F(AesCtrEncryptorTest, NistTestCase) {
|
||||
std::vector<uint8_t> encrypted;
|
||||
EXPECT_TRUE(encryptor_.Encrypt(plaintext_, &encrypted));
|
||||
ASSERT_TRUE(encryptor_.Crypt(plaintext_, &encrypted));
|
||||
EXPECT_EQ(ciphertext_, encrypted);
|
||||
|
||||
EXPECT_TRUE(decryptor_.SetIv(iv_));
|
||||
ASSERT_TRUE(decryptor_.SetIv(iv_));
|
||||
std::vector<uint8_t> decrypted;
|
||||
EXPECT_TRUE(decryptor_.Decrypt(encrypted, &decrypted));
|
||||
ASSERT_TRUE(decryptor_.Crypt(encrypted, &decrypted));
|
||||
EXPECT_EQ(plaintext_, decrypted);
|
||||
}
|
||||
|
||||
TEST_F(AesCtrEncryptorTest, NistTestCaseInplaceEncryptionDecryption) {
|
||||
std::vector<uint8_t> buffer = plaintext_;
|
||||
EXPECT_TRUE(encryptor_.Encrypt(&buffer[0], buffer.size(), &buffer[0]));
|
||||
ASSERT_TRUE(encryptor_.Crypt(&buffer[0], buffer.size(), &buffer[0]));
|
||||
EXPECT_EQ(ciphertext_, buffer);
|
||||
|
||||
EXPECT_TRUE(decryptor_.SetIv(iv_));
|
||||
EXPECT_TRUE(decryptor_.Decrypt(&buffer[0], buffer.size(), &buffer[0]));
|
||||
ASSERT_TRUE(decryptor_.SetIv(iv_));
|
||||
ASSERT_TRUE(decryptor_.Crypt(&buffer[0], buffer.size(), &buffer[0]));
|
||||
EXPECT_EQ(plaintext_, buffer);
|
||||
}
|
||||
|
||||
|
@ -184,13 +184,13 @@ TEST_F(AesCtrEncryptorTest, EncryptDecryptString) {
|
|||
"82E3AD1EF90C5CC09EB37F1B9EFBD99016441A1C15123F0777CD57BB993E14DA02";
|
||||
|
||||
std::string ciphertext;
|
||||
EXPECT_TRUE(encryptor_.Encrypt(kPlaintext, &ciphertext));
|
||||
ASSERT_TRUE(encryptor_.Crypt(kPlaintext, &ciphertext));
|
||||
EXPECT_EQ(kExpectedCiphertextInHex,
|
||||
base::HexEncode(ciphertext.data(), ciphertext.size()));
|
||||
|
||||
std::string decrypted;
|
||||
EXPECT_TRUE(decryptor_.SetIv(iv_));
|
||||
EXPECT_TRUE(decryptor_.Decrypt(ciphertext, &decrypted));
|
||||
ASSERT_TRUE(decryptor_.SetIv(iv_));
|
||||
ASSERT_TRUE(decryptor_.Crypt(ciphertext, &decrypted));
|
||||
EXPECT_EQ(kPlaintext, decrypted);
|
||||
}
|
||||
|
||||
|
@ -202,7 +202,7 @@ TEST_F(AesCtrEncryptorTest, 128BitIVBoundaryCaseEncryption) {
|
|||
kIv128Max64 + arraysize(kIv128Max64));
|
||||
ASSERT_TRUE(encryptor_.InitializeWithIv(key_, iv_max64));
|
||||
std::vector<uint8_t> encrypted;
|
||||
EXPECT_TRUE(encryptor_.Encrypt(plaintext_, &encrypted));
|
||||
ASSERT_TRUE(encryptor_.Crypt(plaintext_, &encrypted));
|
||||
|
||||
std::vector<uint8_t> iv_one_and_three(
|
||||
kIv128OneAndThree, kIv128OneAndThree + arraysize(kIv128OneAndThree));
|
||||
|
@ -211,12 +211,12 @@ TEST_F(AesCtrEncryptorTest, 128BitIVBoundaryCaseEncryption) {
|
|||
|
||||
ASSERT_TRUE(encryptor_.InitializeWithIv(key_, iv_max64));
|
||||
std::vector<uint8_t> encrypted_verify(plaintext_.size(), 0);
|
||||
EXPECT_TRUE(
|
||||
encryptor_.Encrypt(&plaintext_[0], kAesBlockSize, &encrypted_verify[0]));
|
||||
ASSERT_TRUE(
|
||||
encryptor_.Crypt(&plaintext_[0], kAesBlockSize, &encrypted_verify[0]));
|
||||
std::vector<uint8_t> iv_zero(kIv128Zero, kIv128Zero + arraysize(kIv128Zero));
|
||||
ASSERT_TRUE(encryptor_.InitializeWithIv(key_, iv_zero));
|
||||
EXPECT_TRUE(encryptor_.Encrypt(&plaintext_[kAesBlockSize], kAesBlockSize * 3,
|
||||
&encrypted_verify[kAesBlockSize]));
|
||||
ASSERT_TRUE(encryptor_.Crypt(&plaintext_[kAesBlockSize], kAesBlockSize * 3,
|
||||
&encrypted_verify[kAesBlockSize]));
|
||||
EXPECT_EQ(encrypted, encrypted_verify);
|
||||
}
|
||||
|
||||
|
@ -224,8 +224,8 @@ TEST_F(AesCtrEncryptorTest, InitWithRandomIv) {
|
|||
const uint8_t kIvSize = 8;
|
||||
ASSERT_TRUE(encryptor_.InitializeWithRandomIv(key_, kIvSize));
|
||||
ASSERT_EQ(kIvSize, encryptor_.iv().size());
|
||||
LOG(INFO) << "Random IV: " << base::HexEncode(&encryptor_.iv()[0],
|
||||
encryptor_.iv().size());
|
||||
LOG(INFO) << "Random IV: "
|
||||
<< base::HexEncode(&encryptor_.iv()[0], encryptor_.iv().size());
|
||||
}
|
||||
|
||||
TEST_F(AesCtrEncryptorTest, UnsupportedKeySize) {
|
||||
|
@ -252,19 +252,17 @@ TEST_P(AesCtrEncryptorSubsampleTest, NistTestCaseSubsamples) {
|
|||
std::vector<uint8_t> encrypted(plaintext_.size(), 0);
|
||||
for (uint32_t i = 0, offset = 0; i < test_case->subsample_count; ++i) {
|
||||
uint32_t len = test_case->subsample_sizes[i];
|
||||
EXPECT_TRUE(
|
||||
encryptor_.Encrypt(&plaintext_[offset], len, &encrypted[offset]));
|
||||
ASSERT_TRUE(encryptor_.Crypt(&plaintext_[offset], len, &encrypted[offset]));
|
||||
offset += len;
|
||||
EXPECT_EQ(offset % kAesBlockSize, encryptor_.block_offset());
|
||||
}
|
||||
EXPECT_EQ(ciphertext_, encrypted);
|
||||
|
||||
EXPECT_TRUE(decryptor_.SetIv(iv_));
|
||||
ASSERT_TRUE(decryptor_.SetIv(iv_));
|
||||
std::vector<uint8_t> decrypted(encrypted.size(), 0);
|
||||
for (uint32_t i = 0, offset = 0; i < test_case->subsample_count; ++i) {
|
||||
uint32_t len = test_case->subsample_sizes[i];
|
||||
EXPECT_TRUE(
|
||||
decryptor_.Decrypt(&encrypted[offset], len, &decrypted[offset]));
|
||||
ASSERT_TRUE(decryptor_.Crypt(&encrypted[offset], len, &decrypted[offset]));
|
||||
offset += len;
|
||||
EXPECT_EQ(offset % kAesBlockSize, decryptor_.block_offset());
|
||||
}
|
||||
|
@ -291,7 +289,7 @@ TEST_P(AesCtrEncryptorIvTest, IvTest) {
|
|||
ASSERT_TRUE(encryptor.InitializeWithIv(key, iv_test));
|
||||
|
||||
std::vector<uint8_t> encrypted;
|
||||
EXPECT_TRUE(encryptor.Encrypt(plaintext, &encrypted));
|
||||
ASSERT_TRUE(encryptor.Crypt(plaintext, &encrypted));
|
||||
encryptor.UpdateIv();
|
||||
EXPECT_EQ(iv_expected, encryptor.iv());
|
||||
}
|
||||
|
@ -300,9 +298,9 @@ INSTANTIATE_TEST_CASE_P(IvTestCases,
|
|||
AesCtrEncryptorIvTest,
|
||||
::testing::ValuesIn(kIvTestCases));
|
||||
|
||||
class AesCbcEncryptDecryptTest {
|
||||
class AesCbcTest : public ::testing::Test {
|
||||
public:
|
||||
AesCbcEncryptDecryptTest()
|
||||
AesCbcTest()
|
||||
: encryptor_(new AesCbcEncryptor(kPkcs5Padding, !kChainAcrossCalls)),
|
||||
decryptor_(new AesCbcDecryptor(kPkcs5Padding, !kChainAcrossCalls)),
|
||||
key_(kAesKey, kAesKey + arraysize(kAesKey)),
|
||||
|
@ -330,11 +328,11 @@ class AesCbcEncryptDecryptTest {
|
|||
ASSERT_TRUE(decryptor_->InitializeWithIv(key_, iv_));
|
||||
|
||||
T encrypted;
|
||||
EXPECT_TRUE(encryptor_->Encrypt(plaintext, &encrypted));
|
||||
ASSERT_TRUE(encryptor_->Crypt(plaintext, &encrypted));
|
||||
EXPECT_EQ(expected_ciphertext, encrypted);
|
||||
|
||||
T decrypted;
|
||||
EXPECT_TRUE(decryptor_->Decrypt(encrypted, &decrypted));
|
||||
ASSERT_TRUE(decryptor_->Crypt(encrypted, &decrypted));
|
||||
EXPECT_EQ(plaintext, decrypted);
|
||||
}
|
||||
|
||||
|
@ -345,9 +343,9 @@ class AesCbcEncryptDecryptTest {
|
|||
ASSERT_TRUE(decryptor_->InitializeWithIv(key_, iv_));
|
||||
|
||||
T buffer(plaintext);
|
||||
EXPECT_TRUE(encryptor_->Encrypt(buffer, &buffer));
|
||||
ASSERT_TRUE(encryptor_->Crypt(buffer, &buffer));
|
||||
EXPECT_EQ(expected_ciphertext, buffer);
|
||||
EXPECT_TRUE(decryptor_->Decrypt(buffer, &buffer));
|
||||
ASSERT_TRUE(decryptor_->Crypt(buffer, &buffer));
|
||||
EXPECT_EQ(plaintext, buffer);
|
||||
}
|
||||
|
||||
|
@ -357,8 +355,6 @@ class AesCbcEncryptDecryptTest {
|
|||
std::vector<uint8_t> iv_;
|
||||
};
|
||||
|
||||
class AesCbcTest : public AesCbcEncryptDecryptTest, public testing::Test {};
|
||||
|
||||
TEST_F(AesCbcTest, Aes256CbcPkcs5) {
|
||||
// NIST SP 800-38A test vector F.2.5 CBC-AES256.Encrypt.
|
||||
static const uint8_t kAesCbcKey[] = {
|
||||
|
@ -462,22 +458,22 @@ TEST_F(AesCbcTest, NoPaddingNoChainAcrossCalls) {
|
|||
ASSERT_TRUE(encryptor.InitializeWithIv(key_, iv_));
|
||||
|
||||
std::vector<uint8_t> encrypted;
|
||||
ASSERT_TRUE(encryptor.Encrypt(plaintext, &encrypted));
|
||||
ASSERT_TRUE(encryptor.Crypt(plaintext, &encrypted));
|
||||
EXPECT_EQ(ciphertext, encrypted);
|
||||
// Iv should not have been updated.
|
||||
EXPECT_EQ(iv_, encryptor.iv());
|
||||
ASSERT_TRUE(encryptor.Encrypt(plaintext, &encrypted));
|
||||
ASSERT_TRUE(encryptor.Crypt(plaintext, &encrypted));
|
||||
EXPECT_EQ(ciphertext, encrypted);
|
||||
|
||||
AesCbcDecryptor decryptor(kNoPadding, !kChainAcrossCalls);
|
||||
ASSERT_TRUE(decryptor.InitializeWithIv(key_, iv_));
|
||||
|
||||
std::vector<uint8_t> decrypted;
|
||||
ASSERT_TRUE(decryptor.Decrypt(ciphertext, &decrypted));
|
||||
ASSERT_TRUE(decryptor.Crypt(ciphertext, &decrypted));
|
||||
EXPECT_EQ(plaintext, decrypted);
|
||||
// Iv should not have been updated.
|
||||
EXPECT_EQ(iv_, encryptor.iv());
|
||||
ASSERT_TRUE(decryptor.Decrypt(ciphertext, &decrypted));
|
||||
ASSERT_TRUE(decryptor.Crypt(ciphertext, &decrypted));
|
||||
EXPECT_EQ(plaintext, decrypted);
|
||||
}
|
||||
|
||||
|
@ -506,24 +502,24 @@ TEST_F(AesCbcTest, NoPaddingChainAcrossCalls) {
|
|||
ASSERT_TRUE(encryptor.InitializeWithIv(key_, iv_));
|
||||
|
||||
std::vector<uint8_t> encrypted;
|
||||
ASSERT_TRUE(encryptor.Encrypt(plaintext, &encrypted));
|
||||
ASSERT_TRUE(encryptor.Crypt(plaintext, &encrypted));
|
||||
EXPECT_EQ(ciphertext, encrypted);
|
||||
// Iv should have been updated.
|
||||
EXPECT_NE(iv_, encryptor.iv());
|
||||
// If run encrypt again, the result will be different.
|
||||
ASSERT_TRUE(encryptor.Encrypt(plaintext, &encrypted));
|
||||
ASSERT_TRUE(encryptor.Crypt(plaintext, &encrypted));
|
||||
EXPECT_EQ(ciphertext2, encrypted);
|
||||
|
||||
AesCbcDecryptor decryptor(kNoPadding, kChainAcrossCalls);
|
||||
ASSERT_TRUE(decryptor.InitializeWithIv(key_, iv_));
|
||||
|
||||
std::vector<uint8_t> decrypted;
|
||||
ASSERT_TRUE(decryptor.Decrypt(ciphertext, &decrypted));
|
||||
ASSERT_TRUE(decryptor.Crypt(ciphertext, &decrypted));
|
||||
EXPECT_EQ(plaintext, decrypted);
|
||||
// Iv should have been updated.
|
||||
EXPECT_NE(iv_, encryptor.iv());
|
||||
// If run decrypt on ciphertext2 now, it will return the original plaintext.
|
||||
ASSERT_TRUE(decryptor.Decrypt(ciphertext2, &decrypted));
|
||||
ASSERT_TRUE(decryptor.Crypt(ciphertext2, &decrypted));
|
||||
EXPECT_EQ(plaintext, decrypted);
|
||||
}
|
||||
|
||||
|
@ -540,13 +536,13 @@ TEST_F(AesCbcTest, UnsupportedIvSize) {
|
|||
TEST_F(AesCbcTest, Pkcs5CipherTextNotMultipleOfBlockSize) {
|
||||
std::string plaintext;
|
||||
ASSERT_TRUE(decryptor_->InitializeWithIv(key_, iv_));
|
||||
EXPECT_FALSE(decryptor_->Decrypt("1", &plaintext));
|
||||
EXPECT_FALSE(decryptor_->Crypt("1", &plaintext));
|
||||
}
|
||||
|
||||
TEST_F(AesCbcTest, Pkcs5CipherTextEmpty) {
|
||||
std::string plaintext;
|
||||
ASSERT_TRUE(decryptor_->InitializeWithIv(key_, iv_));
|
||||
EXPECT_FALSE(decryptor_->Decrypt("", &plaintext));
|
||||
EXPECT_FALSE(decryptor_->Crypt("", &plaintext));
|
||||
}
|
||||
|
||||
struct CbcTestCase {
|
||||
|
@ -585,8 +581,8 @@ const CbcTestCase kCbcTestCases[] = {
|
|||
};
|
||||
|
||||
class AesCbcCryptorVerificationTest
|
||||
: public AesCbcEncryptDecryptTest,
|
||||
public ::testing::TestWithParam<CbcTestCase> {};
|
||||
: public AesCbcTest,
|
||||
public ::testing::WithParamInterface<CbcTestCase> {};
|
||||
|
||||
TEST_P(AesCbcCryptorVerificationTest, EncryptDecryptTest) {
|
||||
encryptor_.reset(
|
|
@ -7,8 +7,6 @@
|
|||
#include "packager/media/base/aes_decryptor.h"
|
||||
|
||||
#include <openssl/aes.h>
|
||||
#include <openssl/err.h>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
#include "packager/base/logging.h"
|
||||
|
||||
|
@ -24,60 +22,6 @@ bool IsKeySizeValidForAes(size_t key_size) {
|
|||
namespace edash_packager {
|
||||
namespace media {
|
||||
|
||||
AesDecryptor::AesDecryptor() {}
|
||||
AesDecryptor::~AesDecryptor() {}
|
||||
|
||||
bool AesDecryptor::Decrypt(const std::vector<uint8_t>& ciphertext,
|
||||
std::vector<uint8_t>* plaintext) {
|
||||
DCHECK(plaintext);
|
||||
plaintext->resize(ciphertext.size());
|
||||
size_t plaintext_size;
|
||||
if (!DecryptInternal(ciphertext.data(), ciphertext.size(), plaintext->data(),
|
||||
&plaintext_size))
|
||||
return false;
|
||||
plaintext->resize(plaintext_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AesDecryptor::Decrypt(const std::string& ciphertext,
|
||||
std::string* plaintext) {
|
||||
DCHECK(plaintext);
|
||||
plaintext->resize(ciphertext.size());
|
||||
size_t plaintext_size;
|
||||
if (!DecryptInternal(reinterpret_cast<const uint8_t*>(ciphertext.data()),
|
||||
ciphertext.size(),
|
||||
reinterpret_cast<uint8_t*>(string_as_array(plaintext)),
|
||||
&plaintext_size))
|
||||
return false;
|
||||
plaintext->resize(plaintext_size);
|
||||
return true;
|
||||
}
|
||||
|
||||
AesCtrDecryptor::AesCtrDecryptor() {}
|
||||
|
||||
AesCtrDecryptor::~AesCtrDecryptor() {}
|
||||
|
||||
bool AesCtrDecryptor::InitializeWithIv(const std::vector<uint8_t>& key,
|
||||
const std::vector<uint8_t>& iv) {
|
||||
encryptor_.reset(new AesCtrEncryptor);
|
||||
return encryptor_->InitializeWithIv(key, iv);
|
||||
}
|
||||
|
||||
bool AesCtrDecryptor::SetIv(const std::vector<uint8_t>& iv) {
|
||||
DCHECK(encryptor_);
|
||||
return encryptor_->SetIv(iv);
|
||||
}
|
||||
|
||||
bool AesCtrDecryptor::DecryptInternal(const uint8_t* ciphertext,
|
||||
size_t ciphertext_size,
|
||||
uint8_t* plaintext,
|
||||
size_t* plaintext_size) {
|
||||
DCHECK(encryptor_);
|
||||
*plaintext_size = ciphertext_size;
|
||||
// For AES CTR, encryption and decryption are identical.
|
||||
return encryptor_->Encrypt(ciphertext, ciphertext_size, plaintext);
|
||||
}
|
||||
|
||||
AesCbcDecryptor::AesCbcDecryptor(CbcPaddingScheme padding_scheme,
|
||||
bool chain_across_calls)
|
||||
: padding_scheme_(padding_scheme),
|
||||
|
@ -87,6 +31,7 @@ AesCbcDecryptor::AesCbcDecryptor(CbcPaddingScheme padding_scheme,
|
|||
"sense if the padding_scheme is kNoPadding.";
|
||||
}
|
||||
}
|
||||
|
||||
AesCbcDecryptor::~AesCbcDecryptor() {}
|
||||
|
||||
bool AesCbcDecryptor::InitializeWithIv(const std::vector<uint8_t>& key,
|
||||
|
@ -96,9 +41,8 @@ bool AesCbcDecryptor::InitializeWithIv(const std::vector<uint8_t>& key,
|
|||
return false;
|
||||
}
|
||||
|
||||
aes_key_.reset(new AES_KEY());
|
||||
CHECK_EQ(AES_set_decrypt_key(key.data(), key.size() * 8, aes_key_.get()), 0);
|
||||
|
||||
CHECK_EQ(AES_set_decrypt_key(key.data(), key.size() * 8, mutable_aes_key()),
|
||||
0);
|
||||
return SetIv(iv);
|
||||
}
|
||||
|
||||
|
@ -108,36 +52,43 @@ bool AesCbcDecryptor::SetIv(const std::vector<uint8_t>& iv) {
|
|||
return false;
|
||||
}
|
||||
|
||||
iv_ = iv;
|
||||
set_iv(iv);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AesCbcDecryptor::DecryptInternal(const uint8_t* ciphertext,
|
||||
size_t ciphertext_size,
|
||||
uint8_t* plaintext,
|
||||
size_t* plaintext_size) {
|
||||
bool AesCbcDecryptor::CryptInternal(const uint8_t* ciphertext,
|
||||
size_t ciphertext_size,
|
||||
uint8_t* plaintext,
|
||||
size_t* plaintext_size) {
|
||||
DCHECK(plaintext_size);
|
||||
DCHECK(aes_key_);
|
||||
DCHECK(aes_key());
|
||||
// Plaintext size is the same as ciphertext size except for pkcs5 padding.
|
||||
// Will update later if using pkcs5 padding.
|
||||
// Will update later if using pkcs5 padding. For pkcs5 padding, we still
|
||||
// need at least |ciphertext_size| bytes for intermediate operation.
|
||||
if (*plaintext_size < ciphertext_size) {
|
||||
LOG(ERROR) << "Expecting output size of at least " << ciphertext_size
|
||||
<< " bytes.";
|
||||
return false;
|
||||
}
|
||||
*plaintext_size = ciphertext_size;
|
||||
|
||||
if (ciphertext_size == 0) {
|
||||
if (padding_scheme_ == kPkcs5Padding) {
|
||||
LOG(ERROR) << "Expected ciphertext to be at least " << AES_BLOCK_SIZE
|
||||
<< " bytes with Pkcs5 padding";
|
||||
<< " bytes with Pkcs5 padding.";
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
DCHECK(plaintext);
|
||||
|
||||
std::vector<uint8_t> local_iv(iv_);
|
||||
std::vector<uint8_t> local_iv(iv());
|
||||
const size_t residual_block_size = ciphertext_size % AES_BLOCK_SIZE;
|
||||
if (residual_block_size == 0) {
|
||||
AES_cbc_encrypt(ciphertext, plaintext, ciphertext_size, aes_key_.get(),
|
||||
AES_cbc_encrypt(ciphertext, plaintext, ciphertext_size, aes_key(),
|
||||
local_iv.data(), AES_DECRYPT);
|
||||
if (chain_across_calls_)
|
||||
iv_ = local_iv;
|
||||
set_iv(local_iv);
|
||||
if (padding_scheme_ != kPkcs5Padding)
|
||||
return true;
|
||||
|
||||
|
@ -167,8 +118,8 @@ bool AesCbcDecryptor::DecryptInternal(const uint8_t* ciphertext,
|
|||
// AES-CBC decrypt everything up to the next-to-last full block.
|
||||
const size_t cbc_size = ciphertext_size - residual_block_size;
|
||||
if (cbc_size > AES_BLOCK_SIZE) {
|
||||
AES_cbc_encrypt(ciphertext, plaintext, cbc_size - AES_BLOCK_SIZE,
|
||||
aes_key_.get(), local_iv.data(), AES_DECRYPT);
|
||||
AES_cbc_encrypt(ciphertext, plaintext, cbc_size - AES_BLOCK_SIZE, aes_key(),
|
||||
local_iv.data(), AES_DECRYPT);
|
||||
}
|
||||
|
||||
const uint8_t* next_to_last_ciphertext_block =
|
||||
|
@ -186,7 +137,7 @@ bool AesCbcDecryptor::DecryptInternal(const uint8_t* ciphertext,
|
|||
// Decrypt the next-to-last block using the IV determined above. This decrypts
|
||||
// the residual block bits.
|
||||
AES_cbc_encrypt(next_to_last_ciphertext_block, next_to_last_plaintext_block,
|
||||
AES_BLOCK_SIZE, aes_key_.get(), last_iv.data(), AES_DECRYPT);
|
||||
AES_BLOCK_SIZE, aes_key(), last_iv.data(), AES_DECRYPT);
|
||||
|
||||
// Swap back the residual block bits and the next-to-last block.
|
||||
if (plaintext == ciphertext) {
|
||||
|
@ -202,7 +153,7 @@ bool AesCbcDecryptor::DecryptInternal(const uint8_t* ciphertext,
|
|||
|
||||
// Decrypt the next-to-last full block.
|
||||
AES_cbc_encrypt(next_to_last_plaintext_block, next_to_last_plaintext_block,
|
||||
AES_BLOCK_SIZE, aes_key_.get(), local_iv.data(), AES_DECRYPT);
|
||||
AES_BLOCK_SIZE, aes_key(), local_iv.data(), AES_DECRYPT);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -6,98 +6,23 @@
|
|||
//
|
||||
// AES Decryptor implementation using openssl.
|
||||
|
||||
#ifndef MEDIA_BASE_AES_DECRYPTOR_H_
|
||||
#define MEDIA_BASE_AES_DECRYPTOR_H_
|
||||
#ifndef PACKAGER_MEDIA_BASE_AES_DECRYPTOR_H_
|
||||
#define PACKAGER_MEDIA_BASE_AES_DECRYPTOR_H_
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "packager/base/memory/scoped_ptr.h"
|
||||
#include "packager/base/stl_util.h"
|
||||
#include "packager/base/macros.h"
|
||||
#include "packager/media/base/aes_cryptor.h"
|
||||
#include "packager/media/base/aes_encryptor.h"
|
||||
|
||||
struct aes_key_st;
|
||||
typedef struct aes_key_st AES_KEY;
|
||||
|
||||
namespace edash_packager {
|
||||
namespace media {
|
||||
|
||||
class AesDecryptor {
|
||||
public:
|
||||
AesDecryptor();
|
||||
virtual ~AesDecryptor();
|
||||
/// For AES-CTR, encryption and decryption are identical.
|
||||
using AesCtrDecryptor = AesCtrEncryptor;
|
||||
|
||||
/// Initialize the decryptor with specified key and IV.
|
||||
/// @return true on successful initialization, false otherwise.
|
||||
virtual bool InitializeWithIv(const std::vector<uint8_t>& key,
|
||||
const std::vector<uint8_t>& iv) = 0;
|
||||
|
||||
/// @name Various forms of decrypt calls.
|
||||
/// The plaintext and ciphertext pointers can be the same address.
|
||||
/// @{
|
||||
bool Decrypt(const std::vector<uint8_t>& ciphertext,
|
||||
std::vector<uint8_t>* plaintext);
|
||||
bool Decrypt(const std::string& ciphertext, std::string* plaintext);
|
||||
bool Decrypt(const uint8_t* ciphertext,
|
||||
size_t ciphertext_size,
|
||||
uint8_t* plaintext) {
|
||||
size_t plaintext_size;
|
||||
return DecryptInternal(ciphertext, ciphertext_size, plaintext,
|
||||
&plaintext_size);
|
||||
}
|
||||
/// @}
|
||||
|
||||
/// Set IV.
|
||||
/// @return true if successful, false if the input is invalid.
|
||||
virtual bool SetIv(const std::vector<uint8_t>& iv) = 0;
|
||||
|
||||
protected:
|
||||
/// Internal implementation of decrypt function.
|
||||
/// @param ciphertext points to the input ciphertext.
|
||||
/// @param ciphertext_size is the input ciphertext size.
|
||||
/// @param[out] plaintext points to the output plaintext. @a plaintext and
|
||||
/// @a ciphertext can point to the same address.
|
||||
/// @param[out] plaintext_size contains the size of plaintext on success.
|
||||
/// It should never be larger than @a ciphertext_size.
|
||||
virtual bool DecryptInternal(const uint8_t* ciphertext,
|
||||
size_t ciphertext_size,
|
||||
uint8_t* plaintext,
|
||||
size_t* plaintext_size) = 0;
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(AesDecryptor);
|
||||
};
|
||||
|
||||
// Class which implements AES-CTR counter-mode decryption.
|
||||
class AesCtrDecryptor : public AesDecryptor {
|
||||
public:
|
||||
AesCtrDecryptor();
|
||||
~AesCtrDecryptor() override;
|
||||
|
||||
/// @name AesDecryptor implementation overrides.
|
||||
/// @{
|
||||
bool InitializeWithIv(const std::vector<uint8_t>& key,
|
||||
const std::vector<uint8_t>& iv) override;
|
||||
|
||||
bool SetIv(const std::vector<uint8_t>& iv) override;
|
||||
/// @}
|
||||
|
||||
uint32_t block_offset() const { return encryptor_->block_offset(); }
|
||||
|
||||
protected:
|
||||
bool DecryptInternal(const uint8_t* ciphertext,
|
||||
size_t ciphertext_size,
|
||||
uint8_t* plaintext,
|
||||
size_t* plaintext_size) override;
|
||||
|
||||
private:
|
||||
scoped_ptr<AesCtrEncryptor> encryptor_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AesCtrDecryptor);
|
||||
};
|
||||
|
||||
// Class which implements AES-CBC (Cipher block chaining) decryption.
|
||||
class AesCbcDecryptor : public AesDecryptor {
|
||||
/// Class which implements AES-CBC (Cipher block chaining) decryption.
|
||||
class AesCbcDecryptor : public AesCryptor {
|
||||
public:
|
||||
/// @param padding_scheme indicates the padding scheme used. Currently
|
||||
/// supported schemes: kNoPadding, kPkcs5Padding, kCtsPadding.
|
||||
|
@ -107,25 +32,22 @@ class AesCbcDecryptor : public AesDecryptor {
|
|||
AesCbcDecryptor(CbcPaddingScheme padding_scheme, bool chain_across_calls);
|
||||
~AesCbcDecryptor() override;
|
||||
|
||||
/// @name AesDecryptor implementation overrides.
|
||||
/// @name AesCryptor implementation overrides.
|
||||
/// @{
|
||||
bool InitializeWithIv(const std::vector<uint8_t>& key,
|
||||
const std::vector<uint8_t>& iv) override;
|
||||
|
||||
bool SetIv(const std::vector<uint8_t>& iv) override;
|
||||
void UpdateIv() override {
|
||||
// Nop for decryptor.
|
||||
}
|
||||
/// @}
|
||||
|
||||
protected:
|
||||
bool DecryptInternal(const uint8_t* ciphertext,
|
||||
size_t ciphertext_size,
|
||||
uint8_t* plaintext,
|
||||
size_t* plaintext_size) override;
|
||||
|
||||
private:
|
||||
// Openssl AES_KEY.
|
||||
scoped_ptr<AES_KEY> aes_key_;
|
||||
// Initialization vector, must be 16 for CBC.
|
||||
std::vector<uint8_t> iv_;
|
||||
bool CryptInternal(const uint8_t* ciphertext,
|
||||
size_t ciphertext_size,
|
||||
uint8_t* plaintext,
|
||||
size_t* plaintext_size) override;
|
||||
|
||||
const CbcPaddingScheme padding_scheme_;
|
||||
const bool chain_across_calls_;
|
||||
|
||||
|
@ -135,4 +57,4 @@ class AesCbcDecryptor : public AesDecryptor {
|
|||
} // namespace media
|
||||
} // namespace edash_packager
|
||||
|
||||
#endif // MEDIA_BASE_AES_DECRYPTOR_H_
|
||||
#endif // PACKAGER_MEDIA_BASE_AES_DECRYPTOR_H_
|
||||
|
|
|
@ -40,9 +40,8 @@ namespace media {
|
|||
AesEncryptor::AesEncryptor() {}
|
||||
AesEncryptor::~AesEncryptor() {}
|
||||
|
||||
bool AesEncryptor::InitializeWithRandomIv(
|
||||
const std::vector<uint8_t>& key,
|
||||
uint8_t iv_size) {
|
||||
bool AesEncryptor::InitializeWithRandomIv(const std::vector<uint8_t>& key,
|
||||
uint8_t iv_size) {
|
||||
std::vector<uint8_t> iv(iv_size, 0);
|
||||
if (RAND_bytes(iv.data(), iv_size) != 1) {
|
||||
LOG(ERROR) << "RAND_bytes failed with error: "
|
||||
|
@ -59,31 +58,11 @@ bool AesEncryptor::InitializeWithIv(const std::vector<uint8_t>& key,
|
|||
return false;
|
||||
}
|
||||
|
||||
aes_key_.reset(new AES_KEY());
|
||||
CHECK_EQ(AES_set_encrypt_key(key.data(), key.size() * 8, aes_key_.get()), 0);
|
||||
CHECK_EQ(AES_set_encrypt_key(key.data(), key.size() * 8, mutable_aes_key()),
|
||||
0);
|
||||
return SetIv(iv);
|
||||
}
|
||||
|
||||
bool AesEncryptor::Encrypt(const std::vector<uint8_t>& plaintext,
|
||||
std::vector<uint8_t>* ciphertext) {
|
||||
// Save plaintext size to make it work for in-place conversion, since the
|
||||
// next statement will update the plaintext size.
|
||||
const size_t plaintext_size = plaintext.size();
|
||||
ciphertext->resize(plaintext_size + NumPaddingBytes(plaintext.size()));
|
||||
return EncryptInternal(plaintext.data(), plaintext_size, ciphertext->data());
|
||||
}
|
||||
|
||||
bool AesEncryptor::Encrypt(const std::string& plaintext,
|
||||
std::string* ciphertext) {
|
||||
// Save plaintext size to make it work for in-place conversion, since the
|
||||
// next statement will update the plaintext size.
|
||||
const size_t plaintext_size = plaintext.size();
|
||||
ciphertext->resize(plaintext_size + NumPaddingBytes(plaintext.size()));
|
||||
return EncryptInternal(
|
||||
reinterpret_cast<const uint8_t*>(plaintext.data()), plaintext_size,
|
||||
reinterpret_cast<uint8_t*>(string_as_array(ciphertext)));
|
||||
}
|
||||
|
||||
AesCtrEncryptor::AesCtrEncryptor()
|
||||
: block_offset_(0),
|
||||
encrypted_counter_(AES_BLOCK_SIZE, 0),
|
||||
|
@ -134,13 +113,22 @@ bool AesCtrEncryptor::SetIv(const std::vector<uint8_t>& iv) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool AesCtrEncryptor::EncryptInternal(const uint8_t* plaintext,
|
||||
size_t plaintext_size,
|
||||
uint8_t* ciphertext) {
|
||||
bool AesCtrEncryptor::CryptInternal(const uint8_t* plaintext,
|
||||
size_t plaintext_size,
|
||||
uint8_t* ciphertext,
|
||||
size_t* ciphertext_size) {
|
||||
DCHECK(plaintext);
|
||||
DCHECK(ciphertext);
|
||||
DCHECK(aes_key());
|
||||
|
||||
// |ciphertext_size| is always the same as |plaintext_size| for counter mode.
|
||||
if (*ciphertext_size < plaintext_size) {
|
||||
LOG(ERROR) << "Expecting output size of at least " << plaintext_size
|
||||
<< " bytes.";
|
||||
return false;
|
||||
}
|
||||
*ciphertext_size = plaintext_size;
|
||||
|
||||
for (size_t i = 0; i < plaintext_size; ++i) {
|
||||
if (block_offset_ == 0) {
|
||||
AES_encrypt(&counter_[0], &encrypted_counter_[0], aes_key());
|
||||
|
@ -158,11 +146,6 @@ bool AesCtrEncryptor::EncryptInternal(const uint8_t* plaintext,
|
|||
return true;
|
||||
}
|
||||
|
||||
size_t AesCtrEncryptor::NumPaddingBytes(size_t size) const {
|
||||
// No padding needed for CTR.
|
||||
return 0;
|
||||
}
|
||||
|
||||
AesCbcEncryptor::AesCbcEncryptor(CbcPaddingScheme padding_scheme,
|
||||
bool chain_across_calls)
|
||||
: padding_scheme_(padding_scheme),
|
||||
|
@ -194,9 +177,10 @@ bool AesCbcEncryptor::SetIv(const std::vector<uint8_t>& iv) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool AesCbcEncryptor::EncryptInternal(const uint8_t* plaintext,
|
||||
size_t plaintext_size,
|
||||
uint8_t* ciphertext) {
|
||||
bool AesCbcEncryptor::CryptInternal(const uint8_t* plaintext,
|
||||
size_t plaintext_size,
|
||||
uint8_t* ciphertext,
|
||||
size_t* ciphertext_size) {
|
||||
DCHECK(aes_key());
|
||||
|
||||
const size_t residual_block_size = plaintext_size % AES_BLOCK_SIZE;
|
||||
|
@ -206,6 +190,15 @@ bool AesCbcEncryptor::EncryptInternal(const uint8_t* plaintext,
|
|||
return false;
|
||||
}
|
||||
|
||||
const size_t num_padding_bytes = NumPaddingBytes(plaintext_size);
|
||||
const size_t required_ciphertext_size = plaintext_size + num_padding_bytes;
|
||||
if (*ciphertext_size < required_ciphertext_size) {
|
||||
LOG(ERROR) << "Expecting output size of at least "
|
||||
<< required_ciphertext_size << " bytes.";
|
||||
return false;
|
||||
}
|
||||
*ciphertext_size = required_ciphertext_size;
|
||||
|
||||
// Encrypt everything but the residual block using CBC.
|
||||
const size_t cbc_size = plaintext_size - residual_block_size;
|
||||
std::vector<uint8_t> local_iv(iv());
|
||||
|
@ -231,13 +224,14 @@ bool AesCbcEncryptor::EncryptInternal(const uint8_t* plaintext,
|
|||
uint8_t* residual_ciphertext_block = ciphertext + cbc_size;
|
||||
|
||||
if (padding_scheme_ == kPkcs5Padding) {
|
||||
const size_t num_padding_bytes = AES_BLOCK_SIZE - residual_block_size;
|
||||
DCHECK_EQ(num_padding_bytes, NumPaddingBytes(plaintext_size));
|
||||
DCHECK_EQ(num_padding_bytes, AES_BLOCK_SIZE - residual_block_size);
|
||||
|
||||
// Pad residue block with PKCS5 padding.
|
||||
residual_block.resize(AES_BLOCK_SIZE, static_cast<char>(num_padding_bytes));
|
||||
AES_cbc_encrypt(residual_block.data(), residual_ciphertext_block,
|
||||
AES_BLOCK_SIZE, aes_key(), local_iv.data(), AES_ENCRYPT);
|
||||
} else {
|
||||
DCHECK_EQ(num_padding_bytes, 0u);
|
||||
DCHECK_EQ(padding_scheme_, kCtsPadding);
|
||||
|
||||
// Zero-pad the residual block and encrypt using CBC.
|
||||
|
|
|
@ -12,77 +12,29 @@
|
|||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "packager/base/macros.h"
|
||||
#include "packager/base/memory/scoped_ptr.h"
|
||||
#include "packager/base/stl_util.h"
|
||||
|
||||
struct aes_key_st;
|
||||
typedef struct aes_key_st AES_KEY;
|
||||
#include "packager/media/base/aes_cryptor.h"
|
||||
|
||||
namespace edash_packager {
|
||||
namespace media {
|
||||
|
||||
class AesEncryptor {
|
||||
class AesEncryptor : public AesCryptor {
|
||||
public:
|
||||
AesEncryptor();
|
||||
virtual ~AesEncryptor();
|
||||
~AesEncryptor() override;
|
||||
|
||||
/// Initialize the encryptor with specified key and a random generated IV
|
||||
/// of the specified size.
|
||||
/// @return true on successful initialization, false otherwise.
|
||||
bool InitializeWithRandomIv(const std::vector<uint8_t>& key,
|
||||
uint8_t iv_size);
|
||||
bool InitializeWithRandomIv(const std::vector<uint8_t>& key, uint8_t iv_size);
|
||||
|
||||
/// Initialize the encryptor with specified key and IV.
|
||||
/// @return true on successful initialization, false otherwise.
|
||||
bool InitializeWithIv(const std::vector<uint8_t>& key,
|
||||
const std::vector<uint8_t>& iv);
|
||||
|
||||
/// @name Various forms of encrypt calls.
|
||||
/// The plaintext and ciphertext pointers can be the same address.
|
||||
bool Encrypt(const std::vector<uint8_t>& plaintext,
|
||||
std::vector<uint8_t>* ciphertext);
|
||||
bool Encrypt(const std::string& plaintext, std::string* ciphertext);
|
||||
bool Encrypt(const uint8_t* plaintext,
|
||||
size_t plaintext_size,
|
||||
uint8_t* ciphertext) {
|
||||
return EncryptInternal(plaintext, plaintext_size, ciphertext);
|
||||
}
|
||||
/// @}
|
||||
|
||||
/// Update IV for next sample.
|
||||
/// As recommended in ISO/IEC FDIS 23001-7:
|
||||
/// IV need to be updated per sample for CENC.
|
||||
virtual void UpdateIv() = 0;
|
||||
|
||||
/// Set IV.
|
||||
/// @return true if successful, false if the input is invalid.
|
||||
virtual bool SetIv(const std::vector<uint8_t>& iv) = 0;
|
||||
|
||||
/// @return The current iv.
|
||||
const std::vector<uint8_t>& iv() const { return iv_; }
|
||||
|
||||
protected:
|
||||
/// Internal implementation of encrypt function.
|
||||
/// @param plaintext points to the input plaintext.
|
||||
/// @param plaintext_size is the size of input plaintext.
|
||||
/// @param[out] ciphertext points to the output ciphertext. @a plaintext and
|
||||
/// @a ciphertext can point to the same address.
|
||||
virtual bool EncryptInternal(const uint8_t* plaintext,
|
||||
size_t plaintext_size,
|
||||
uint8_t* ciphertext) = 0;
|
||||
/// @param size specifies the input plaintext size.
|
||||
/// @returns The number of padding bytes needed for output ciphertext.
|
||||
virtual size_t NumPaddingBytes(size_t size) const = 0;
|
||||
|
||||
void set_iv(const std::vector<uint8_t>& iv) { iv_ = iv; }
|
||||
AES_KEY* aes_key() const { return aes_key_.get(); }
|
||||
const std::vector<uint8_t>& iv) override;
|
||||
|
||||
private:
|
||||
// Initialization vector, with size 8 or 16.
|
||||
std::vector<uint8_t> iv_;
|
||||
// Openssl AES_KEY.
|
||||
scoped_ptr<AES_KEY> aes_key_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(AesEncryptor);
|
||||
};
|
||||
|
||||
|
@ -92,7 +44,7 @@ class AesCtrEncryptor : public AesEncryptor {
|
|||
AesCtrEncryptor();
|
||||
~AesCtrEncryptor() override;
|
||||
|
||||
/// @name AesEncryptor implementation overrides.
|
||||
/// @name AesCryptor implementation overrides.
|
||||
/// @{
|
||||
/// Update IV for next sample. @a block_offset_ is reset to 0.
|
||||
/// As recommended in ISO/IEC FDIS 23001-7: CENC spec,
|
||||
|
@ -105,13 +57,12 @@ class AesCtrEncryptor : public AesEncryptor {
|
|||
|
||||
uint32_t block_offset() const { return block_offset_; }
|
||||
|
||||
protected:
|
||||
bool EncryptInternal(const uint8_t* plaintext,
|
||||
size_t plaintext_size,
|
||||
uint8_t* ciphertext) override;
|
||||
size_t NumPaddingBytes(size_t size) const override;
|
||||
|
||||
private:
|
||||
bool CryptInternal(const uint8_t* plaintext,
|
||||
size_t plaintext_size,
|
||||
uint8_t* ciphertext,
|
||||
size_t* ciphertext_size) override;
|
||||
|
||||
// Current block offset.
|
||||
uint32_t block_offset_;
|
||||
// Current AES-CTR counter.
|
||||
|
@ -143,20 +94,20 @@ class AesCbcEncryptor : public AesEncryptor {
|
|||
AesCbcEncryptor(CbcPaddingScheme padding_scheme, bool chain_across_calls);
|
||||
~AesCbcEncryptor() override;
|
||||
|
||||
/// @name AesEncryptor implementation overrides.
|
||||
/// @name AesCryptor implementation overrides.
|
||||
/// @{
|
||||
void UpdateIv() override;
|
||||
|
||||
bool SetIv(const std::vector<uint8_t>& iv) override;
|
||||
/// @}
|
||||
|
||||
protected:
|
||||
bool EncryptInternal(const uint8_t* plaintext,
|
||||
size_t plaintext_size,
|
||||
uint8_t* ciphertext) override;
|
||||
private:
|
||||
bool CryptInternal(const uint8_t* plaintext,
|
||||
size_t plaintext_size,
|
||||
uint8_t* ciphertext,
|
||||
size_t* ciphertext_size) override;
|
||||
size_t NumPaddingBytes(size_t size) const override;
|
||||
|
||||
private:
|
||||
const CbcPaddingScheme padding_scheme_;
|
||||
const bool chain_across_calls_;
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ bool DecryptorSource::DecryptSampleBuffer(const DecryptConfig* decrypt_config,
|
|||
DCHECK(buffer);
|
||||
|
||||
// Get the decryptor object.
|
||||
AesDecryptor* decryptor;
|
||||
AesCryptor* decryptor;
|
||||
auto found = decryptor_map_.find(decrypt_config->key_id());
|
||||
if (found == decryptor_map_.end()) {
|
||||
// Create new AesDecryptor based on decryption mode.
|
||||
|
@ -38,7 +38,7 @@ bool DecryptorSource::DecryptSampleBuffer(const DecryptConfig* decrypt_config,
|
|||
return false;
|
||||
}
|
||||
|
||||
scoped_ptr<AesDecryptor> aes_decryptor;
|
||||
scoped_ptr<AesCryptor> aes_decryptor;
|
||||
switch (decrypt_config->decryption_mode()) {
|
||||
case kEncryptionModeAesCtr:
|
||||
aes_decryptor.reset(new AesCtrDecryptor);
|
||||
|
@ -68,7 +68,7 @@ bool DecryptorSource::DecryptSampleBuffer(const DecryptConfig* decrypt_config,
|
|||
|
||||
if (decrypt_config->subsamples().empty()) {
|
||||
// Sample not encrypted using subsample encryption. Decrypt whole.
|
||||
if (!decryptor->Decrypt(buffer, buffer_size, buffer)) {
|
||||
if (!decryptor->Crypt(buffer, buffer_size, buffer)) {
|
||||
LOG(ERROR) << "Error during bulk sample decryption.";
|
||||
return false;
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ bool DecryptorSource::DecryptSampleBuffer(const DecryptConfig* decrypt_config,
|
|||
return false;
|
||||
}
|
||||
current_ptr += subsample.clear_bytes;
|
||||
if (!decryptor->Decrypt(current_ptr, subsample.cipher_bytes, current_ptr)) {
|
||||
if (!decryptor->Crypt(current_ptr, subsample.cipher_bytes, current_ptr)) {
|
||||
LOG(ERROR) << "Error decrypting subsample buffer.";
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ class DecryptorSource {
|
|||
|
||||
private:
|
||||
KeySource* key_source_;
|
||||
std::map<std::vector<uint8_t>, AesDecryptor*> decryptor_map_;
|
||||
std::map<std::vector<uint8_t>, AesCryptor*> decryptor_map_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(DecryptorSource);
|
||||
};
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
'target_name': 'media_base',
|
||||
'type': '<(component)',
|
||||
'sources': [
|
||||
'aes_cryptor.cc',
|
||||
'aes_cryptor.h',
|
||||
'aes_decryptor.cc',
|
||||
'aes_decryptor.h',
|
||||
'aes_encryptor.cc',
|
||||
|
@ -113,7 +115,7 @@
|
|||
'target_name': 'media_base_unittest',
|
||||
'type': '<(gtest_target_type)',
|
||||
'sources': [
|
||||
'aes_encryptor_unittest.cc',
|
||||
'aes_cryptor_unittest.cc',
|
||||
'audio_timestamp_helper_unittest.cc',
|
||||
'bit_reader_unittest.cc',
|
||||
'buffer_writer_unittest.cc',
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "packager/media/base/request_signer.h"
|
||||
|
||||
#include "packager/base/logging.h"
|
||||
#include "packager/base/sha1.h"
|
||||
#include "packager/base/strings/string_number_conversions.h"
|
||||
#include "packager/media/base/aes_encryptor.h"
|
||||
|
@ -48,7 +49,7 @@ AesRequestSigner* AesRequestSigner::CreateSigner(const std::string& signer_name,
|
|||
|
||||
bool AesRequestSigner::GenerateSignature(const std::string& message,
|
||||
std::string* signature) {
|
||||
aes_cbc_encryptor_->Encrypt(base::SHA1HashString(message), signature);
|
||||
aes_cbc_encryptor_->Crypt(base::SHA1HashString(message), signature);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -199,7 +199,7 @@ Status EncryptingFragmenter::CreateEncryptor() {
|
|||
|
||||
void EncryptingFragmenter::EncryptBytes(uint8_t* data, uint32_t size) {
|
||||
DCHECK(encryptor_);
|
||||
CHECK(encryptor_->Encrypt(data, size, data));
|
||||
CHECK(encryptor_->Crypt(data, size, data));
|
||||
}
|
||||
|
||||
Status EncryptingFragmenter::EncryptSample(scoped_refptr<MediaSample> sample) {
|
||||
|
|
|
@ -78,7 +78,7 @@ Status Encryptor::EncryptFrame(scoped_refptr<MediaSample> sample,
|
|||
uint8_t* sample_data = sample->writable_data();
|
||||
|
||||
// Encrypt the data in-place.
|
||||
if (!encryptor_->Encrypt(sample_data, sample_size, sample_data)) {
|
||||
if (!encryptor_->Crypt(sample_data, sample_size, sample_data)) {
|
||||
return Status(error::MUXER_FAILURE, "Failed to encrypt the frame.");
|
||||
}
|
||||
|
||||
|
|
|
@ -779,9 +779,9 @@ bool WvmMediaParser::DemuxNextPes(bool is_program_end) {
|
|||
if (!content_decryptor_) {
|
||||
output_encrypted_sample = true;
|
||||
} else {
|
||||
content_decryptor_->Decrypt(&sample_data_[crypto_unit_start_pos_],
|
||||
sample_data_.size() - crypto_unit_start_pos_,
|
||||
&sample_data_[crypto_unit_start_pos_]);
|
||||
content_decryptor_->Crypt(&sample_data_[crypto_unit_start_pos_],
|
||||
sample_data_.size() - crypto_unit_start_pos_,
|
||||
&sample_data_[crypto_unit_start_pos_]);
|
||||
}
|
||||
}
|
||||
// Demux media sample if we are at program end or if we are not at a
|
||||
|
@ -1124,8 +1124,8 @@ bool WvmMediaParser::ProcessEcm() {
|
|||
kEcmFlagsSizeBytes + kEcmContentKeySizeBytes +
|
||||
kEcmPaddingSizeBytes; // flags + contentKey + padding.
|
||||
std::vector<uint8_t> content_key_buffer(content_key_buffer_size);
|
||||
CHECK(asset_decryptor.Decrypt(ecm_data, content_key_buffer_size,
|
||||
content_key_buffer.data()));
|
||||
CHECK(asset_decryptor.Crypt(ecm_data, content_key_buffer_size,
|
||||
content_key_buffer.data()));
|
||||
|
||||
std::vector<uint8_t> decrypted_content_key_vec(
|
||||
content_key_buffer.begin() + 4,
|
||||
|
|
Loading…
Reference in New Issue