Problem using AESLib

I created some functions for AESLib

#include "AESLib.h"


byte aes_key[] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C };

// General initialization vector (same as in node-js example) (you must use your own IV's in production for full security!!!)
byte aes_iv[N_BLOCK] = { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA };
byte enc_iv[N_BLOCK] = { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA };


void CRYPTO_Init(void) 
{
  gen_iv(aes_iv);
  set_paddingmode((paddingMode)0);
}


void CRYPTO_Encrypt(const char* msg, int msg_len, char* encrypted, byte iv[])
{
  int cipherlength = AESLib_get_cipher_length(msg_len);

  encrypt((byte*)msg, msg_len, encrypted, aes_key, sizeof(aes_key), iv);
     
}

void CRYPTO_Decrypt(char* msg, uint16_t msg_len, char* decrypted, byte iv[])
{
   decrypt((byte*)msg, msg_len, decrypted, aes_key, sizeof(aes_key), iv);
}

Now I test it

uint32_t COM_Crypto(uint32_t argc, char** args)
{
    if (argc == 0)
         return MSG_MIS_ARG;
    
    int msg_len = strlen(args[1]);
    char encrypted[128 + 1];
    char decrypted[2*(128 + 1)];
     byte iv[] = { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA };
    
    CRYPTO_Encrypt(args[1], msg_len, encrypted, iv);
    USART_SendString(SYS_USART, encrypted);
    USART_SendString(SYS_USART,"\r");
    
    msg_len = strlen(encrypted);
    CRYPTO_Decrypt(encrypted, msg_len, decrypted, iv);
    USART_SendString(SYS_USART, decrypted);
    
    return MSG_OK;
}

I see encrypted data but when I decrypt it back I get gibberish. What do I do wrong?

You should try resetting your Intialization Vector (IV) before decrypting. It is possible that this array was modified during encryption.

uint32_t COM_Crypto(uint32_t argc, char** args)
{
  if (argc == 0)
    return MSG_MIS_ARG;

  int msg_len = strlen(args[1]);
  char encrypted[128 + 1];
  char decrypted[2 * (128 + 1)];
  const byte iv_content[] = { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA };
  const byte iv_size = sizeof iv_content;
  byte iv[iv_size];

  memcpy(iv, iv_content, iv_size); // https://www.cplusplus.com/reference/cstring/memcpy/
  CRYPTO_Encrypt(args[1], msg_len, encrypted, iv);
  USART_SendString(SYS_USART, encrypted);
  USART_SendString(SYS_USART, "\r");

  memcpy(iv, iv_content, iv_size); // https://www.cplusplus.com/reference/cstring/memcpy/
  msg_len = strlen(encrypted);
  CRYPTO_Decrypt(encrypted, msg_len, decrypted, iv);
  USART_SendString(SYS_USART, decrypted);

  return MSG_OK;
}

I did so but still no good. Every function call I see a different encrypted string, is it normal? The key and iv always the same.

Post a full sketch and clickable link to the library you use

ESP communicates with other micro controller. So I ported the library in order they'll have the common encryption/decryption algorithm.
AESLib.zip (17.8 KB)

Before you do decryption, it is necessary to prepare the key first. The term is "key scheduling"

The key is static in the crypto.c

byte aes_key[] = { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C };

Does not matter. Unless its done automatically by the library, you have to calculate the "round keys" first before decryption. Might want to check the library for that.

How do we do that? It's not mentioned in the examples.

Not sure. Maybe look at the library source code for hints.

What is the format of "encrypted" after "args[1]" (should this be args[0]?) has been encrypted? If USART_SendString expects a null-terminated char array and "encrypted" is binary, this is a problem that must be fixed.

it's a command I get from a terminal.
For example I type crypto text_to_encrypt so args[0] = crypto (it jumps to COM_Crypto function) and args[1] = text_to_encryp - string argument to encrypt.

When encrypting, the output is a multiple of a constant block size which is not necessarily equal to the input string. Try this (untested code):

const uint8_t IV_SIZE = 16;
const uint8_t INIT_VECTOR[IV_SIZE] = { 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA };

char message[] = "Hello world";
uint8_t encrypted[32], decrypted[32], iv[IV_SIZE];
uint16_t enc_size, dec_size;

memcpy(iv, INIT_VECTOR, IV_SIZE);
enc_size = CRYPTO_Encrypt(message, strlen(message), encrypted, iv);

memcpy(iv, INIT_VECTOR, IV_SIZE);
dec_size = CRYPTO_Decrypt(encrypted, enc_size, decrypted, iv);

decrypted[dec_size] = 0; //Null terminate
Serial.println((char*)decrypted);

EDIT: And remember that "USART_SendString()" takes a null-terminated string, "encrypted" must be encoded to something like base64 before it is transmitted, otherwise you may get garbage out the other end.

Thank you.
What should I return for enc_size, dec_size? How do I calculate it?

What do you mean? "enc_size" is the size of the encrypted data which is returned by "CRYPTO_Encrypt" and "dec_size" is the same but for decryption. The size of the initialization vector is (usually) the same as the block size used by the encryption routine and thus you can calculate the size of the encrypted data with:

msg_len = strlen(message);
num_blocks = msg_len / BLOCK_SIZE;
if (msg_len % block_size > 0) num_blocks++;
encrypted_size = num_blocks * BLOCK_SIZE;

Decrypted size will never exceed encrypted size and the actual size of the decrypted data will be returned by the decryption function.

for what's is worth, I've been playing with this library

if you run the following code

#include <AESLib.h>   // https://github.com/DavyLandman/AESLib
// you can verify the result using  https://cryptii.com/pipes/aes-encryption


uint8_t key128bits[] = "@McQfTjWnZr4u7x!";  // KEEP SECRET !
uint8_t iv128bits[] = "0124356789ABCDEF";   // NO NEED TO KEEP SECRET

const uint16_t maxMessageSize = 16u * 16u; // message size + 1 needs to be a multiple of 16
char message[maxMessageSize];
static_assert(maxMessageSize % 16 == 0, "message size + 1 needs to be a multiple of 16");

void printHex(uint8_t aByte)
{
  if (aByte < 0x10) Serial.write('0');
  Serial.print(aByte, HEX);
}

void hexDump(const void* payload, uint16_t payloadSize, bool eightCols = true)
{
  for (uint16_t i = 0; i < payloadSize; i++) {
    printHex((uint8_t) * (((const uint8_t *) payload) + i));
    Serial.write(((eightCols &&  (i + 1) % 8 == 0)) ? '\n' : ' ');
  }
  Serial.println();
}

void encodePayload(void* payload, uint16_t payloadSize)
{
  aes128_cbc_enc(key128bits, iv128bits, payload, payloadSize);
}

void decodePayload(void* payload, uint16_t payloadSize)
{
  aes128_cbc_dec(key128bits, iv128bits, payload, payloadSize);
}

void setup() {
  Serial.begin(115200);
  Serial.println();

  Serial.print(F("Key:\t")); hexDump(key128bits, 16, false);
  Serial.print(F("IV:\t"));  hexDump(iv128bits,  16, false);
  Serial.println();

  // reset the buffer to full 0 (just to ensure we have a clean slate)
  memset(message, 0, sizeof(message));

  // copy payload into the message
  strncpy((char*) message, "A Secret Message that willl need to be encoded, including UTF8 chars éàçöê€", maxMessageSize - 1); // -1 to keep a trailing NULL char and thus a cString

  // calculate the size of the payload, needs to be a multiple of 16
  uint16_t messageSize = strlen(message) + 1; // +1 to grab the trailing '\0'
  if ((messageSize % 16) != 0) messageSize = 16 * ((messageSize / 16) + 1);

  if (messageSize > maxMessageSize) Serial.println("Message too long.");
  else {
    Serial.print(F("Message to encode: ["));
    Serial.print(message);
    Serial.println(F("]\n"));

    encodePayload(message, messageSize);
    Serial.println(F("Hex dump of coded Message: "));
    hexDump(message, messageSize);

    decodePayload(message, messageSize);
    Serial.print(F("Decoded Message: ["));
    Serial.print(message);
    Serial.println(F("]\n"));
  }
}

void loop() {}

Serial Monitor (@ 115200 bauds) will show

Key: 40 4D 63 51 66 54 6A 57 6E 5A 72 34 75 37 78 21
IV: 30 31 32 34 33 35 36 37 38 39 41 42 43 44 45 46

Message to encode: [A Secret Message that willl need to be encoded, including UTF8 chars éàçöê€]

Hex dump of coded Message:
F8 D7 AC A3 54 BF 8F 2E
BD 8C D5 DE 6E 5D 4C D5
70 C3 EE A7 1C 24 51 1C
01 B7 04 3E CF 47 15 C0
62 04 89 F0 C1 A7 C0 B0
91 09 69 11 3D 9A 45 70
A7 FA 9A B8 40 73 42 35
CE 25 99 90 A8 4B 8B 10
BF D3 B6 AE C3 DF 10 76
8A 51 E7 1E BE 4A 9A D3
35 07 C9 3C 41 DB 88 8D
EF F2 5B 33 16 79 E1 98

Decoded Message: [A Secret Message that willl need to be encoded, including UTF8 chars éàçöê€]

seems it works.

I see. Thank you. I was trying to use the default library but in case of no success I'll move to this one.