hpb
hpb

Reputation: 111

CBC encryption in Arduino

Been writing some code to encrypt the SSID of a wifi network and then store it in a file on the Flash memory of TI's CC3200 MCU. The program is being written in Energia which is an IDE identical to the Arduino IDE.

The encryption function (listed here) takes in uint8_t arrays and it looks like this:

void AES128_CBC_encrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);
void AES128_CBC_decrypt_buffer(uint8_t* output, uint8_t* input, uint32_t length, const uint8_t* key, const uint8_t* iv);

Here is a sequence of events:

SSID is stored in a char array > gets encrypted and stored in the enc_ssid buffer > the file operations begin here by deleting an existing file and then creating a new one > Write the enc_ssid to the file > gets read back from the file and then decrypted into another char array.

The problem is that when it gets read back from the file I see weird characters on my Serial monitor (output is also posted towards the end of this Q). What am I doing wrong?

Code:

Serial.begin(115200);
SerFlash.begin(); // Begin the file system library. This also calls WiFi.init().

uint8_t keys[] = {0x18, 0x92, 0xe5, 0xfe, 0x5e, 0x02, 0x92, 0x23, 0x23, 0x9c, 0x9a, 0xfd, 0x59, 0xaf, 0x55, 0x23}; 
uint8_t iv[] = {0xfe, 0x0d, 0x44, 0x18, 0xb3, 0xea, 0xc5, 0x0d, 0xfe, 0xe5, 0xa3, 0x6a, 0x25, 0x72, 0xf1, 0x71};

char ssid[] = "ABCDEFGH";
len_ssid = (sizeof(ssid)/sizeof(ssid[0]));
Serial.print("SSID length: "); Serial.println(len_ssid);
Serial.println();

uint8_t enc_ssid[len_ssid];
char dec_ssid[len_ssid];
uint8_t str_ssid[len_ssid];

// Encrypt the SSID buffer.
AES128_CBC_encrypt_buffer(enc_ssid, (uint8_t*)ssid, len_ssid, keys, iv);

for (int i=0; i<len_ssid; i++)
{
    Serial.print("enc_ssid["); Serial.print(i); Serial.print("]: "); Serial.println(enc_ssid[i]);
}
Serial.println();

// Delete the old SSID file and create a new one.
SerFlash.del("/user/ssid2.txt");
Serial.print("\nDeleting /user/ssid2.txt, return code: "); Serial.println(SerFlash.lastErrorString());
Serial.flush();

// Creates a 32 byte file called ssid2.txt. Returns 0 if successful or a negative number if unsuccessful.
retVal = SerFlash.open("/user/ssid2.txt", FS_MODE_OPEN_CREATE(32, _FS_FILE_OPEN_FLAG_COMMIT));
if (retVal >= 0)
{
  Serial.println("Success creating new ssid file!");
  SerFlash.open("/user/ssid2.txt", FS_MODE_OPEN_WRITE);
  SerFlash.write(enc_ssid, len_ssid);
  SerFlash.close();

  // Verify that the file has indeed been written.
  SerFlash.open("/user/ssid2.txt", FS_MODE_OPEN_READ);
  str_ssid[0] = '\0'; // Init str_ssid in case readBytes doesn't actually do anything (and returns 0)
    size_t read_length = SerFlash.readBytes(str_ssid, len_ssid);
    Serial.print("Read ");
  Serial.print(read_length);
  Serial.println(" bytes from /user/ssid2.txt - contents: ");
  //Serial.println(str_ssid);
  for (int i=0; i<len_ssid; i++)
  {
        Serial.print("file["); Serial.print(i); Serial.print("]: "); Serial.println(str_ssid[i], DEC);
  }
  SerFlash.close();
}
else
{
  Serial.print("Error creating SSID2 file. Error code: "); Serial.println(SerFlash.lastErrorString());
}

// Decrypt the SSID buffer.
AES128_CBC_decrypt_buffer((uint8_t*)dec_ssid, str_ssid, len_ssid, keys, iv);

Serial.println();
for (int i=0; i<len_ssid; i++)
{
    Serial.print("decrypted["); Serial.print(i); Serial.print("]: "); Serial.println(dec_ssid[i]);
}

Here is the Serial output that I see. As is visible, the decrypted should show ABCDEFGH but shows weird characters.

SSID length: 9

enc_ssid[0]: 243
enc_ssid[1]: 97
enc_ssid[2]: 109
enc_ssid[3]: 34
enc_ssid[4]: 188
enc_ssid[5]: 209
enc_ssid[6]: 8
enc_ssid[7]: 136
enc_ssid[8]: 34

Deleting /user/ssid2.txt, return code: SL_FS_OK
Success creating new ssid file!
Read 9 bytes from /user/ssid2.txt - contents: 

file[0]: 243
file[1]: 97
file[2]: 109
file[3]: 34
file[4]: 188
file[5]: 209
file[6]: 8
file[7]: 136
file[8]: 34

decrypted[0]: 7
decrypted[1]: A
decrypted[2]: A
decrypted[3]: ¨
decrypted[4]: Æ
decrypted[5]: 
decrypted[6]: B
decrypted[7]: 
decrypted[8]: É

Upvotes: 0

Views: 506

Answers (1)

slugonamission
slugonamission

Reputation: 9632

Your problem probably stems from the fact that you're only trying to encrypt eight bytes, AES128 works on a 128-bit (16 byte) granularity, and the library doesn't do padding for you. There's this in a comment at the start of the library:

NOTE:   String length must be evenly divisible by 16byte (str_len % 16 == 0)
    You should pad the end of the string with zeros if this is not the case.

Looking at the library, it looks like the library does support encrypting/decrypting an amount of data that is not a multiple of 16B, but the output buffer must be a multiple of 16B in order for this to work correctly (as the author still adds the padding for you). Anyway, the code for AES128_CBC_encrypt_buffer starts with BlockCopy(output, input);, which attempts to copy an entire block (16 bytes) from input to output. As you're only passing in eight byte buffers, this will cause undefined behaviour to occur which could explain what you're seeing.

In short, make your encrypt/decrypt buffers 16 bytes long, and manually set the final eight bytes to zero.

Upvotes: 3

Related Questions