I am trying to implement AES-128 and AES-256 on an Arduino (Adafruit Feather M0, for any other people using SAMD21 processors!). The encryption and decryption is working, but I am unable to “save” the encrypted value. I believe the example passes a pointer for a char array to void encrypt(), but when using strcpy, strncpy or memcpy to copy over the value from the local char array to the one back in my loop(), the value never actually gets copied over.
Note that the hang only occurs in the void encrypt() method and I wonder if it is due to the encode_base64 line where the example code is casting the data as unsigned char*. I’ve been able to use strcpy, strncpy and memcpy successfully in void decrypt() so all I can think is that it's the unsigned char type.
Though according to this a char is ultimately treated like an unsigned char in standard libraries, which I assume that the strcpy function is part of the standard string library and not something special to Arduino.
I am very new to C/C++ and am nowhere near an expert. I am not quite sure how to get around this issue so I am hoping someone can point me in the right direction.
Code (I included links to the libraries at the top for each #include)
#include <Crypto.h> // https://github.com/intrbiz/arduino-crypto
#include <base64.hpp> // https://github.com/Densaugeo/base64_arduino
#define BLOCK_SIZE 16
uint8_t key[BLOCK_SIZE] = { 0x1C,0x3E,0x4B,0xAF,0x13,0x4A,0x89,0xC3,0xF3,0x87,0x4F,0xBC,0xD7,0xF3, 0x31, 0x31 };
uint8_t iv[BLOCK_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
char plain_text[] = "1234567890ABCDEF1234567890ABCDEF";
void bufferSize(char* text, int &length)
{
int i = strlen(text);
int buf = round(i / BLOCK_SIZE) * BLOCK_SIZE;
length = (buf <= i) ? buf + BLOCK_SIZE : length = buf;
}
void encrypt(char* plain_text, char* output, int length)
{
byte enciphered[length];
// RNG::fill(iv, BLOCK_SIZE); // Using fixed test iv
AES aesEncryptor(key, iv, AES::AES_MODE_128, AES::CIPHER_ENCRYPT);
aesEncryptor.process((uint8_t*)plain_text, enciphered, length);
int encrypted_size = sizeof(enciphered);
char encoded[encrypted_size];
encode_base64(enciphered, encrypted_size, (unsigned char*)encoded);
Serial.print("void encrypt :: Encrypted: ");
Serial.println(encoded);
// strcpy(output, encoded); //- Hangs
// strncpy(output, encoded, strlen((char*)encoded)); - Hangs
// memcpy(output, encoded, strlen((char*)encoded)); - Hangs
}
void decrypt(char* enciphered, char* output, int length)
{
length = length + 1; //re-adjust
char decoded[length];
decode_base64((unsigned char*)enciphered, (unsigned char*)decoded);
bufferSize(enciphered, length);
byte deciphered[length];
AES aesDecryptor(key, iv, AES::AES_MODE_128, AES::CIPHER_DECRYPT);
aesDecryptor.process((uint8_t*)decoded, deciphered, length);
Serial.print("void decrypt :: Decrypted: ");
Serial.println((char*)deciphered);
strcpy(output, (char*)deciphered);
// strncpy(output, (char*)deciphered, strlen((char*)deciphered));
// memcpy(output, (char*)deciphered, strlen((char*)deciphered));
}
void setup() {
Serial.begin(115200);
while (!Serial) {
; //wait
}
Serial.println("AES128-CBC Test :: Starting...");
Serial.print("Plaintext input "); Serial.println(plain_text);
}
void loop() {
Serial.println(" = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = \n");
// Encrypt
int length = 0;
bufferSize(plain_text, length);
// Serial.print("Buffer length: ");
// Serial.println(length);
char encrypted[128];
encrypt(plain_text, encrypted, length);
// Serial.println("");
Serial.print("RETURNED Encrypted Value: ");
Serial.println(encrypted);
// Decrypt
length = 128; // WAS strlen(encrypted);
char decrypted[length];
char testEncryptedPayload[] = "pJUX0k/h/63Jywlyvn7vTMa9NdJF9Mz6JOB1T1gDMq+0NUkNycBR780kMvCYILGP"; // Added for testing purposes
decrypt(testEncryptedPayload, decrypted, length);
Serial.print("RETURNED Decrypted Value: ");
Serial.println(decrypted);
delay(5000);
}
/*
EXAMPLE FROM DOCUMENTATION => loop()
void loop() {
char plain_text[] = "1234567890ABCDEF1234567890ABCDEF";
// Encrypt
int length = 0;
bufferSize(plain_text, length);
char encrypted[length];
encrypt(plain_text, encrypted, length);
Serial.println("");
Serial.print("Encrypted: ");
Serial.println(encrypted);
// Decrypt
length = strlen(encrypted);
char decrypted[length];
decrypt(encrypted, decrypted, length);
Serial.print("Decrypted: ");
Serial.println(decrypted);
delay(5000);
}
*/
Sample Output:
AES128-CBC Test :: Starting...
Plaintext input 1234567890ABCDEF1234567890ABCDEF
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
void encrypt :: Encrypted: pJUX0k/h/63Jywlyvn7vTMa9NdJF9Mz6JOB1T1gDMq/eQVoPjf/UYv+9SuzV8LQa
RETURNED Encrypted Value: L
void decrypt :: Decrypted: 1234567890ABCDEF1234567890ABCDEF
RETURNED Decrypted Value: 1234567890ABCDEF1234567890ABCDEF
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =