aesaes-gcm

aes_cbc_encrypt() not correctly decrypting data


My goal is to not use the EVP functions from OpenSSL. I know this is possible because I basically broke down thousands of lines of C code for the key derivation to a standalone embedded program and it was not easy.

But now I would like to actually encrypt/decrypt data. The two functions are assembly routines found in /crypto/aes/aesni-x86_64.s, actually. I'm just a bit burned out from reading more code. I'm looking for the direct functions that just do the encryption using the AES_256_CBC cipher or AES_256_GCM. I found the aes_gcm_encrypt in crypto/modes/aesni-gcm-x86_64.s

This code takes the string in in and encrypts it to tmp, then decrypts it back to out but it doesn't actually decrypt correctly. Any ideas? Am I missing other routines before using the actual assembly functions? And if so, can someone just point me to where that is?

#include <stdio.h>
#include <string.h>
#include <openssl/aes.h>

int aesni_set_encrypt_key(const unsigned char *userKey, const int bits, AES_KEY *key);
int aesni_set_decrypt_key(const unsigned char *userKey, int bits,
                          AES_KEY *key);
void aesni_cbc_encrypt(const unsigned char *in,
                       unsigned char *out,
                       size_t length,
                       const AES_KEY *key, unsigned char *ivec, int enc);

int main()
{
    int i;
    unsigned char key[] = "\xE0\xE6\x0C\x86\xF1\x10\xF5\x3A\x4E\x65\x88\x79\x74\xB1\x4E\x3D\x06\x22\x9D\xB9\x4E\x26\x25\xBE\xD1\x18\x2B\x56\x73\xAB\x44\xF3";
    unsigned char iv[]  = "\x06\x22\x9D\xB9\x4E\x26\x25\xBE\xD1\x18\x2B\x56\x73\xAB\x44\xF3";
    unsigned char in[]  = "\x64\x6f\x20\x77\x68\x61\x74\x63\x68\x61\x20\x68\x61\x66\x74\x61";
    unsigned char out[16];
    unsigned char tmp[16];

    // print plaintext
    size_t blksz = 16;
    for (i=0;i<blksz;i++)
        printf("%02x ", in[i]);
    puts("");

    AES_KEY ks;
    aesni_set_encrypt_key(key, 256, &ks);
    aesni_cbc_encrypt(in, tmp, blksz, &ks, iv, 1); // 1 = encrypt

    // print ciphertext
    for (i=0;i<blksz;i++)
        printf("%02x ", tmp[i]);
    puts("");


    // decrypt

    aesni_set_decrypt_key(key, 256, &ks);
    aesni_cbc_encrypt(tmp, out, blksz, &ks, iv, 0); // 0 = decrypt

    // print decrypted plaintext
    for (i=0;i<blksz;i++)
        printf("%02x ", out[i]);
    puts("");

    return 0;

}

Solution

  • I'm going to answer this question using the first comment made by Dave Thompson.

    "That function updates the IV (to allow chained operation) so you decrypt with a different=wrong IV giving a wrong result. You need to either reinitialize the IV before decrypting, or use a copy of the IV not the original for your function calls. (PS: the fact the ivec parameter is NOT declared pointer-to-const hints at this.)"