Data Encryption with Arduino Portenta H7

Hello, I'm struggling on creating an encrypted file and append data to it.
I'm trying with one of the many samples (like https://www.dfrobot.com/blog-1001.html)
but it seems working only with small strings.

here a sample:

#include <mbedtls/aes.h>
#include <FATFileSystem.h>
#include <SDMMCBlockDevice.h>
#include <iostream>

using namespace std;
SDMMCBlockDevice block_device;
mbed::FATFileSystem fs("fs");

void encrypt(char *plainText, unsigned char *outputBuffer) {
  unsigned char IV[16] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  const unsigned char KEY[16] = { 0x23, 0x13, 0x4d, 0x20, 0x88, 0xf3, 0xCf, 0x73, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00 };

  mbedtls_aes_context aes;

  mbedtls_aes_init(&aes);
  mbedtls_aes_setkey_enc(&aes, KEY, 128);
  mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, 64, IV, (const unsigned char *)plainText, outputBuffer);
  mbedtls_aes_free(&aes);
}

void decrypt(char *chipherText, unsigned char *outputBuffer) {
  unsigned char IV[16] = { 0x00, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
  const unsigned char KEY[16] = { 0x23, 0x13, 0x4d, 0x20, 0x88, 0xf3, 0xCf, 0x73, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00 };

  mbedtls_aes_context aes;

  mbedtls_aes_init(&aes);
  mbedtls_aes_setkey_dec(&aes, KEY, 128);
  mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, 64, IV, (const unsigned char *)chipherText, outputBuffer);
  mbedtls_aes_free(&aes);
}


void WriteToEncryptedFile(const char *fileName, String planiText) {
  FILE *f = fopen(fileName, "a");
  if (f) {
    int str_len1 = planiText.length() + 1;
    int currIndex = 0;
    int chunkSize = 16;
    char char_array1[chunkSize];
    unsigned char cipherTextOutput[chunkSize];
    do {
      planiText.toCharArray(char_array1, chunkSize, currIndex);
      encrypt(char_array1, cipherTextOutput);

      for (int i = 0; i < chunkSize; i++) {
        Serial.print(cipherTextOutput[i], HEX);
      }
      Serial.println("");

      fprintf(f, "%s", cipherTextOutput);
      currIndex += chunkSize;
    } while(currIndex < str_len1);

    fclose(f);
  }
}


void setup() {
  Serial.begin(9600);
  while (!Serial)
    ;

  String path = "/fs/crypt.txt";

  Serial.println("Mounting SDCARD...");
  int err = fs.mount(&block_device);
  if (err)  // Reformat if we can't mount the filesystem this should only happen on the first boot
  {
    Serial.println("No filesystem found, formatting... ");
    err = fs.reformat(&block_device);
  }a
  if (err) {
    Serial.println("Error formatting SDCARD ");
    while (1)
      ;
  }
  Serial.println("create file");

  FILE *f0 = fopen(path.c_str(), "w");
  if (f0) {
    fprintf(f0, "");
    fclose(f0);
  }

  WriteToEncryptedFile(path.c_str(), "this is a long string this is a long string this is a long string this is a long string this is a long string this is a long string this is a long string ");
  Serial.println("");

  WriteToEncryptedFile(path.c_str(), "char_array2");
  Serial.println("");

  WriteToEncryptedFile(path.c_str(), "STOP");
  Serial.println("");
}

void loop() {
}
1 Like

you don't have to define the key/IV locally in each function, you can do it globally like

unsigned char IV[16] = { 0x00, 0x01, 0x02, 0x02, 0x04, 0x05, 0x06, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
const unsigned char KEY[16] = { 0x23, 0x13, 0x4d, 0x20, 0x88, 0xf3, 0xCf, 0x73, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x07, 0x00 };

and in encrypt() / decrypt() you simply clone them using memcpy() like

  uint8_t keyLocal[16], ivLocal[16];
  memcpy(keyLocal, KEY, 16);
  memcpy(ivLocal, IV, 16);

finally you invoke them with

 mbedtls_aes_setkey_enc(&aes, keyLocal, 128);

because you haven't issued any kind of padding before encryption

your encryption should look like

void encrypt(char *plainText, unsigned char *outputBuffer) {

  int i;
  // PKCS#7 Padding (Encryption), Block Size : 16
  int len = sizeof(plainText);
  int n_blocks = len / 16 + 1;
  uint8_t n_padding = n_blocks * 16 - len;
  uint8_t data_[n_blocks * 16];
  memcpy(data_, plainText, len);
  for (i = len; i < n_blocks * 16; i++) {
    data_[i] = n_padding;
  }


  uint8_t keyLocal[16], ivLocal[16];
  memcpy(keyLocal, KEY, 16);
  memcpy(ivLocal, IV, 16);

  mbedtls_aes_context aes;
  mbedtls_aes_init(&aes);
  mbedtls_aes_setkey_enc(&aes, keyLocal, 128);
  mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, n_blocks * 16, ivLocal, (const unsigned char *)plainText, outputBuffer);
  mbedtls_aes_free(&aes);
}

to understand how PKCS#7 Padding works, you really want to go through this