Search code examples
c++windowsencryptioninitialization-vectorwincrypt

Files not decrypting fully, AES CBC mode. First block not decrpyted. WCAPI


Ok so I have 5 files I am encrypting. I am not setting the IV.

The fist file decrypt's fine,

then the first block of the remaining files is not decrypted.

So the files decrypt 99%.


Ive tried setting the IV to a static value and a random value, same result.

The first file i encrypt does NOT have to be the first file I decrypt for it to be 100% decrypted.

Which leads me to believe it has to do with decryption?


So for encryption I import an aes key to create a key handle.

then I encrypt a file and move to another file using the same key handle...

Should I have a new key handle for every file..?

Is there a function to clear the key handle?


Something is telling me WCAPI is using the last block of the last file as the IV for the next file?

forgive me if i may be misunderstanding something.

Here is the decrypt_file function:

DWORD dwMode = CRYPT_MODE_CBC;

LPVOID aes_key = NULL;
LPVOID tmp_blk_buff = NULL;
DWORD bytes_read = NULL;

BOOL eof = FALSE;

DWORD tmp_blk_buff_size = TMP_BLOCK_BUFFER_SIZE(context->in_size);

tmp_blk_buff = VirtualAlloc(0, tmp_blk_buff_size, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);

Utils::zero_mem(tmp_blk_buff, tmp_blk_buff_size);

LPVOID iv_ = NULL;
iv_ = VirtualAlloc(0, AES_BLOCK_SIZE_, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
Utils::zero_mem(iv_, AES_BLOCK_SIZE_);

/*BYTE iv[AES_BLOCK_SIZE_] = {
    0xAD, 0xAD, 0xAD, 0xAD,
    0xAD, 0xAD, 0xAD, 0xAD,
    0xAD, 0xAD, 0xAD, 0xAD,
    0xAD, 0xAD, 0xAD, 0xAD
};
*/
//  Utils::copy_mem(iv_, AES_BLOCK_SIZE_, iv, AES_BLOCK_SIZE_);


//CryptSetKeyParam(context->aes_hKey, KP_IV, (BYTE*)&iv_, 0);

CryptSetKeyParam(context->aes_hKey, KP_MODE, (BYTE*)&dwMode, 0);

// Encrypt data
do{
    Utils::zero_mem(tmp_blk_buff, tmp_blk_buff_size);
    bytes_read = NULL;

    ReadFile(hFile_in, tmp_blk_buff, AES_BLOCK_SIZE_, &bytes_read, NULL);

    if (bytes_read < AES_BLOCK_SIZE_)
    {
        eof = TRUE;
    }

    if (!CryptDecrypt(context->aes_hKey, NULL, eof, 0,(LPBYTE)tmp_blk_buff, &bytes_read))
    {
        context->last_error = GetLastError();

        eof = TRUE;
    }

    WriteFile(hFile_out, tmp_blk_buff, bytes_read, &bytes_read, NULL);

} while (!eof);

// ===============
//  Zero and Free Allocated memory.
Utils::zero_mem(tmp_blk_buff, tmp_blk_buff_size);
VirtualFree(tmp_blk_buff, tmp_blk_buff_size, MEM_RELEASE);

return (DWORD)1;

Solution

  • I used CryptDuplicateKey with an appropriate call to DestroyKey, that solved my problems.

    Using the duplicated key to set parameters on, keeping the original key un-touched.