diff --git a/tdutils/td/utils/crypto.cpp b/tdutils/td/utils/crypto.cpp index 307892f70..036f4ab2f 100644 --- a/tdutils/td/utils/crypto.cpp +++ b/tdutils/td/utils/crypto.cpp @@ -452,6 +452,7 @@ void aes_ige_decrypt(Slice aes_key, MutableSlice aes_iv, Slice from, MutableSlic class AesIgeState::Impl { public: + AesState cbc_state; AesState state; AesBlock encrypted_iv; AesBlock plaintext_iv; @@ -463,6 +464,36 @@ class AesIgeState::Impl { auto in = from.ubegin(); auto out = to.ubegin(); + static constexpr size_t BLOCK_COUNT = 32; + while (len >= BLOCK_COUNT) { + AesBlock data[BLOCK_COUNT]; + AesBlock data_xored[BLOCK_COUNT]; + std::memcpy(data, in, sizeof(data)); + data_xored[0] = data[0]; + data_xored[1] = plaintext_iv ^ data[1]; + for (size_t i = 2; i < BLOCK_COUNT; i++) { + data_xored[i] = data[i - 2] ^ data[i]; + } + + EVP_EncryptInit(cbc_state.impl_->ctx, nullptr, nullptr, encrypted_iv.raw()); + int outlen = 0; + int inlen = static_cast(sizeof(data_xored)); + EVP_EncryptUpdate(cbc_state.impl_->ctx, data_xored[0].raw(), &outlen, data_xored[0].raw(), inlen); + CHECK(outlen == inlen); + + data_xored[0] ^= plaintext_iv; + for (size_t i = 1; i < BLOCK_COUNT; i++) { + data_xored[i] ^= data[i - 1]; + } + plaintext_iv = data[BLOCK_COUNT - 1]; + encrypted_iv = data_xored[BLOCK_COUNT - 1]; + + std::memcpy(out, data_xored, sizeof(data_xored)); + len -= BLOCK_COUNT; + in += AES_BLOCK_SIZE * BLOCK_COUNT; + out += AES_BLOCK_SIZE * BLOCK_COUNT; + } + AesBlock plaintext; while (len) { @@ -517,6 +548,17 @@ void AesIgeState::init(Slice key, Slice iv, bool encrypt) { impl_ = make_unique(); } impl_->state.init(key, encrypt); + if (encrypt) { + auto &impl = impl_->cbc_state.impl_; + if (!impl) { + impl = make_unique(); + impl->ctx = EVP_CIPHER_CTX_new(); + } + + int res = EVP_EncryptInit_ex(impl->ctx, EVP_aes_256_cbc(), nullptr, key.ubegin(), nullptr); + LOG_IF(FATAL, res != 1); + EVP_CIPHER_CTX_set_padding(impl->ctx, 0); + } impl_->encrypted_iv.load(iv.ubegin()); impl_->plaintext_iv.load(iv.ubegin() + AES_BLOCK_SIZE); } diff --git a/tdutils/td/utils/crypto.h b/tdutils/td/utils/crypto.h index b646652eb..e34a25803 100644 --- a/tdutils/td/utils/crypto.h +++ b/tdutils/td/utils/crypto.h @@ -37,6 +37,8 @@ class AesState { private: class Impl; unique_ptr impl_; + + friend class AesIgeState; }; int pq_factorize(Slice pq_str, string *p_str, string *q_str); @@ -44,7 +46,7 @@ int pq_factorize(Slice pq_str, string *p_str, string *q_str); void aes_ige_encrypt(Slice aes_key, MutableSlice aes_iv, Slice from, MutableSlice to); void aes_ige_decrypt(Slice aes_key, MutableSlice aes_iv, Slice from, MutableSlice to); -struct AesIgeState { +class AesIgeState { public: AesIgeState(); AesIgeState(const AesIgeState &from) = delete;