Skip to content

Commit

Permalink
Implement AES IGE encrypt using AES CBC.
Browse files Browse the repository at this point in the history
GitOrigin-RevId: ca803ca847a9c44e70687ade0f1ea25c0ee0ebb2
  • Loading branch information
levlam committed Jun 16, 2020
1 parent 3442a88 commit f3ebae2
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 1 deletion.
42 changes: 42 additions & 0 deletions tdutils/td/utils/crypto.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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<int>(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) {
Expand Down Expand Up @@ -517,6 +548,17 @@ void AesIgeState::init(Slice key, Slice iv, bool encrypt) {
impl_ = make_unique<Impl>();
}
impl_->state.init(key, encrypt);
if (encrypt) {
auto &impl = impl_->cbc_state.impl_;
if (!impl) {
impl = make_unique<AesState::Impl>();
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);
}
Expand Down
4 changes: 3 additions & 1 deletion tdutils/td/utils/crypto.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,16 @@ class AesState {
private:
class Impl;
unique_ptr<Impl> impl_;

friend class AesIgeState;
};

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;
Expand Down

0 comments on commit f3ebae2

Please sign in to comment.