c++aesmbedtls

How to properly use the aes cbc api from mbedtls


My current approach doesn't even produce the correct encrypted data as checked against golang's aes implementation. It also doesn't decrypt back to the original plaintext, but that's expected if the encryption step isn't working correctly. My best guess is that I'm misusing the api somehow. This is a self-contained example and can run as is.

#include <mbedtls/aes.h>

#include <vector>

void LogVec(const std::vector<uint8_t>& bin)
{
    printf("(size: %i) ", bin.size());
    printf("{");
    for (auto& b : bin)
    {
        printf("%#02x, ", b);
    }
    printf("}\n");
}

mbedtls_aes_context AesContext;

std::vector<uint8_t> EncryptAes(std::vector<uint8_t>& iv, std::vector<uint8_t>& data)
{
    std::vector<uint8_t> ivCpy(iv);

    uint8_t padByte = 16 - (data.size() % 16);
    for (int i = 0; i < padByte; i++)
        data.push_back(padByte);

    std::vector<uint8_t> ret(data.size());
    mbedtls_aes_crypt_cbc(&AesContext, MBEDTLS_AES_ENCRYPT, data.size(), ivCpy.data(), data.data(), ret.data());

    return ret;
}

std::vector<uint8_t> DecryptAes(const std::vector<uint8_t>& iv, std::vector<uint8_t>& data)
{
    std::vector<uint8_t> ivCpy(iv);

    std::vector<uint8_t> ret(data.size());
    mbedtls_aes_crypt_cbc(&AesContext, MBEDTLS_AES_DECRYPT, data.size(), ivCpy.data(), data.data(), ret.data());

    ret.resize(ret.size() - ret[ret.size() - 1]);
    
    return ret;
}

int main() 
{
    mbedtls_aes_init(&AesContext);

    std::vector<uint8_t> data = { 0x3b, 0xb1, 0x99, 0x3, 0x67, 0xf3, 0x2e, 0x1f, 0x00, 0x67, 0x38, 0xc9, 0x53, 0x92, 0xa4 };

    std::vector<uint8_t> key = { 0x15, 0x1, 0xc0, 0xd0, 0xe4, 0xfd, 0xdf, 0xd7, 0x7a, 0x65, 0xf1, 0x2f, 0x45, 0x61, 0xb, 
        0x59, 0xd9, 0xa, 0x9c, 0x61, 0xc, 0x4, 0x76, 0xdb, 0xb, 0xbe, 0x9e, 0xe4, 0x7f, 0x8d, 0xe1, 0x46 };

    std::vector<uint8_t> iv = { 0xa2, 0x78, 0xc9, 0xa4, 0xd8, 0x34, 0x88, 0x9b, 0x28, 0xdc, 0xb9, 0xe2, 0xc0, 0x58, 0x8c, 0xbc };

    mbedtls_aes_setkey_enc(&AesContext, key.data(), 256);
    mbedtls_aes_setkey_dec(&AesContext, key.data(), 256);

    std::vector<uint8_t> dataEnc = EncryptAes(iv, data);
    printf("Encrypted data: ");
    LogVec(dataEnc);

    //std::vector<uint8_t> dataDec = DecryptAes(iv, dataEnc);
    //printf("Decrypted data: ");
    //LogVec(dataDec);

    getchar();
    return 1;
}

Output:

Encrypted data: (size: 16) {0x5d, 0x1c, 0x9, 0x2e, 0x92, 0x8e, 0x24, 0x43, 0xfa, 0xaf, 0xb3, 0xf5, 0x37, 0x8, 0x99, 0x93, }

Expected output from using the same key, iv, data in golang:

Encrypted: 34730cba3543e5facf4b94ba9dc8a275

Solution

  • Before calling mbedtls_aes_crypt_cbc to encrypt you should call mbedtls_aes_setkey_enc and before calling mbedtls_aes_crypt_cbc to decrypt you should call mbedtls_aes_setkey_dec. When both are called at initialization like in your code, the latter call to setkey_dec will overwrite important data in the context structure set by setkey_enc required for encryption.