libyal / libewf

Libewf is a library to access the Expert Witness Compression Format (EWF)
GNU Lesser General Public License v3.0
267 stars 76 forks source link

AD encryption (decryption) #192

Open Agile86 opened 1 year ago

Agile86 commented 1 year ago

Seems that AD encryption section (it's decryption part) is wrong. Trying to decrypt a simple E01 encrypted file (created with the help of AccessData FTK Imager 4.7.1.2) using password "test" (file attached):

#include <iostream>
#include <fstream>
#include <vector>
#include <cassert>

#include <openssl/evp.h>
#include <openssl/hmac.h>

std::vector<unsigned char> read_at_offset(const char* fn, unsigned offset, size_t size) {
    std::vector<unsigned char> buffer;
    std::ifstream file(fn, std::ios::binary);
    if (!file.is_open()) {
        std::cerr << "Failed to open file " << fn << std::endl;
        return buffer;
    }

    file.seekg(offset, std::ios::beg);

    // read the data
    buffer.resize(size);

    file.read((char*)buffer.data(), buffer.size());
    assert(file.gcount() == buffer.size());
    return buffer;
}

int main()
{
    const char fp[] = "C:/temp/E01/small-enc-pass.E01";
    char pass[] = "test";

    auto iter_count = *(unsigned int*)read_at_offset(fp, 32, 4).data();
    auto salt_len = *(unsigned int*)read_at_offset(fp, 36, 4).data();
    auto key_len = *(unsigned int*)read_at_offset(fp, 40, 4).data();
    auto hmac_len = *(unsigned int*)read_at_offset(fp, 44, 4).data();

    auto salt = read_at_offset(fp, 48, salt_len);
    auto fkey = read_at_offset(fp, 48 + salt_len, key_len);
    auto hmac = read_at_offset(fp, 48 + salt_len + key_len, hmac_len);

    auto pkey = std::vector<unsigned char>(key_len);
    auto success = PKCS5_PBKDF2_HMAC(pass, sizeof(pass)-1, salt.data(), salt.size(), iter_count, EVP_sha512(), pkey.size(), pkey.data());
    assert(success == 1);

    assert(hmac_len == EVP_MAX_MD_SIZE);
    unsigned char hmac_result[EVP_MAX_MD_SIZE];
    HMAC(EVP_sha512(), pkey.data(), pkey.size(), fkey.data(), fkey.size(), hmac_result, &hmac_len);

    assert(EVP_MAX_MD_SIZE == hmac.size());

    for (auto i = 0; i < EVP_MAX_MD_SIZE; i++) {
        printf("%02u\n", hmac[i]);
        printf("%02u\n", hmac_result[i]);
        assert(hmac[i] == hmac_result[i]);
    }

    printf("OK\n");
}
Agile86 commented 1 year ago

test file small-enc-pass.zip

Agile86 commented 1 year ago

An official document, describing AD Image Encryption. AD Image Encryption v1.2.pdf

joachimmetz commented 1 year ago

ah nice find, I'll have a look when time permits.