ArduinoPrimoCoreMbedtls provides functions to access symmetric and asymmetric cryptography algorithms, it is licensed under GPLv2 and Apache 2 License and is maintained by ARM mbed. The library does not have any external dependencies, the compiled binary has a size of 60 KB and requires only 64 KB RAM when executed. This makes it an ideal solution to run on a bare-metal embedded system, such as the Arduino Primo (nRF52832).

Mbedtls needs to be configured for the target, this can be done by deactivating platform unsupported build options. The following configuration options were disabled, because the corresponding (hardware) modules are not present on the traget platform (ARM-based Arduinos): MBEDTLS_NET_C, MBEDTLS_TIMING_C, MBEDTLS_ENTROPY_PLATFORM, MBEDTLS_FS_IO, MBEDTLS_HAVE_TIME_DATE, MBEDTLS_HAVE_TIME

MBEDTLS_NET_C requires the BSD sockets API, which is obviously not present on a bare-metal system. MBEDTLS_TIMING_C, MBEDTLS_HAVE_TIME\_DATE, MBEDTLS_HAVE_TIME need to be deactivated because no RTC is present. MBEDTLS_FS_IO is also not available because a POSIX like filesystem is not present on the Arduinos. MBEDTLS_ENTROPY_PLATFORM is important for random number generation but must be deactivated because it implements a POSIX API and uses /dev/urandom as a seed, which is not present on the Arduino (and on other bare-metal embedded systems). When a RNG (random number generator) is important for the project it must be implemented differently. A lot of ARM based microcontrollers provide embedded hardware RNGs. See my other blogpost to make use of the Arduino Primo RNG.

The sample source code below shows AES cryptography (AES256) and message authentication using HMAC-SHA256:

 

/* @file getting_started_mbedtls_arduino.ino
* by Johannes Kinzig -- https://johanneskinzig.de
*
* Getting satrted with mbedtls on ARM based Arduinos:
* - AES256 encryption/decryption
* - HMAC-SHA256
*
* https://johanneskinzig.de/index.php/systems-engineering/14-getting-started-with-mbedtls-on-arm-based-arduinos
*/


#include "src/lib_mbedtls/md.h"
#include "src/lib_mbedtls/aes.h"

unsigned char key[32];
unsigned char iv_orig[16];// iv is changed during encryption, so we need to keep a copy of the original
unsigned char iv[16];
unsigned char plain[128];
unsigned char plain_again[128];
unsigned char cipher[128];

int i;

void setup() {
Serial.begin(9600);
randomSeed(analogRead(0));

Serial.println("Here we go....mbedtls on Arduino Primo....");
}

void loop() {

Serial.write("----------------------------AES Encryption/Decryption--------------------\n");
// prepare data, generate according to AES algorithm

// Generate key -- bad way for production, just for testing
Serial.write("Generate key, 256 Bit, 32 Byte\n");

for(i=0; i<sizeof(key); i=i+1) {
key[i]=(char)(90 - random(25));
Serial.write((char)key[i]);
}
Serial.write("\nsize: ");
Serial.print(sizeof(key), DEC);
Serial.write("\n\n");

// Generate IV
Serial.write("Generate IV, 128 Bit, 16 Byte\n");
for(i=0; i<sizeof(iv); i=i+1) {
iv_orig[i]=key[i]=(char)(122 - random(25));
iv[i]=iv_orig[i];
Serial.write((char)iv_orig[i]);
}
Serial.write("\nsize: ");
Serial.print(sizeof(iv), DEC);
Serial.write("\n\n");

// Generate data
Serial.write("Random data, 1024 Bit, 128 Byte - (ascii)\n");

for(i=0; i<sizeof(plain); i=i+1) {
plain[i]=(char)(122 - random(74));
Serial.write((char)plain[i]);
}
Serial.write("\nsize: ");
Serial.print(sizeof(plain), DEC);
Serial.write("\n\n");

// begin encryption
mbedtls_aes_context aes_encrypt, aes_decrypt;
// size of key must be given as 128, 192 or 256 bit
mbedtls_aes_setkey_enc( &aes_encrypt, key, sizeof(key)*8 );
// size of plaintext is given in bytes
mbedtls_aes_crypt_cbc(&aes_encrypt, MBEDTLS_AES_ENCRYPT, sizeof(plain), iv, plain, cipher);

Serial.write("Ciphertext (hex)\n");
for (i=0; i<sizeof(cipher);i=i+1) {
Serial.print((char)cipher[i], HEX);
}
Serial.write("\nsize: ");
Serial.print(sizeof(cipher), DEC);
Serial.write("\n\n");

// begin decryption - size of key must be given as 128, 192 or 256 bit
mbedtls_aes_setkey_dec(&aes_decrypt, key, sizeof(key)*8);
// size of ciphertext is given in bytes
mbedtls_aes_crypt_cbc(&aes_decrypt, MBEDTLS_AES_DECRYPT, sizeof(cipher), iv_orig, cipher, plain_again);

Serial.write("Plaintext (again)\n");
for (i=0; i<sizeof(plain_again);i=i+1) {
Serial.write((char)plain_again[i]);
}
Serial.write("\nsize: ");
Serial.print(sizeof(plain_again), DEC);
Serial.write("\n\n");

Serial.write("------------------------------------------------------------\n");


Serial.write("-------------------------HMAC sha256------------------------\n");

int hmac_1_sha256_success;
int hmac_2_sha256_success;
unsigned char hmac_sha256_output1[32] = ""; // 256/8 = 32
unsigned char hmac_sha256_output2[32] = ""; // 256/8 = 32
unsigned char data_block1[64] = "";
memcpy(data_block1, "WOHVMMXRXDMMVDMRWXNOCYMVBEGBYCILWOHVMMXRXDMMVDMRWXNOCYMVBEGBYCI5", sizeof(data_block1)); // 512/8 = 64
unsigned char data_block2[64] = "";
memcpy(data_block2, "WOHVMMXRXDMMVDMRWXNOCYMVBEGBYCILWOHVMMXRXDMMVDMRWXNOCYMVBEGBYCI5", sizeof(data_block2)); // 512/8 = 64
unsigned char signing_key[32] = "";
memcpy(signing_key, "amdn395h192mfk47flak2932gh46271j", sizeof(signing_key)); // 256/8 = 32
// prepare hmac context
const mbedtls_md_info_t *md_info_sha256_1, *md_info_sha256_2;
md_info_sha256_1 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);
md_info_sha256_2 = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256);

Serial.print("Data-Block-1 - (ascii)\n");
for(i=0;i<sizeof(data_block1);i=i+1){
Serial.print((char)data_block1[i]);
}
Serial.print("\n");

Serial.print("Data-Block-2 - (ascii)\n");
for(i=0;i<sizeof(data_block2);i=i+1){
Serial.print((char)data_block2[i]);
}
Serial.print("\n");

// sign both messages
hmac_1_sha256_success = mbedtls_md_hmac(md_info_sha256_1, signing_key, sizeof(signing_key), data_block1, sizeof(data_block1), hmac_sha256_output1);
hmac_2_sha256_success = mbedtls_md_hmac(md_info_sha256_2, signing_key, sizeof(signing_key), data_block2, sizeof(data_block2), hmac_sha256_output2);

Serial.print("Computing signatures:\n");
Serial.print("Status 1: ");
Serial.print((char)hmac_1_sha256_success, DEC);
Serial.print("\n");
Serial.print("Status 2: ");
Serial.print(hmac_2_sha256_success, DEC);
Serial.print("\n");

Serial.print("Signature-1 (hex):\n");
for(i=0;i<sizeof(hmac_sha256_output1);i=i+1){
Serial.print((char)hmac_sha256_output1[i], HEX); //printf("%x", hmac_sha256_output1[i]);
}
Serial.print("\n");

Serial.print("Signature-2 (hex):\n");
for(i=0;i<sizeof(hmac_sha256_output2);i=i+1){
Serial.print((char)hmac_sha256_output2[i], HEX); //printf("%x", hmac_sha256_output2[i]);
}
Serial.print("\n");


// compare both signatures - http://pubs.opengroup.org/onlinepubs/009695399/functions/memcmp.html
if(memcmp(hmac_sha256_output1, hmac_sha256_output2, sizeof(hmac_sha256_output1)) == 0) {
Serial.print("Signatures are identical!\n");
}
else {
Serial.print("Signatures are NOT identical!\n");
}

Serial.print("---------------------------------------------------------\n");

}

 

The archive below contains the sample project for the Arduino including the mbedtls library: