================================================================================================================================================

Wednesday, January 26, 2022

String and File Encryption with AES - Code Testing on Raspberry Pi Pico

    


On this page:

Introduction

    Data Encryption has become an absolute necessity in today's world of internet. In embedded systems also, it has become an integrated part due to the wide spread of IoT and other online systems. Sometimes we also need files to be encrypted on local storage like built-in flash or memory cards, etc. to protect certain information. There are various algorithms to encrypt files. Here, we are going to compare some library implementation examples of the most used standard today, AES. 

    The Advance Encryption Standard (AES) is a block cipher, which uses 128 or 192 or 256 bit key to encrypt or decrypt 128 bit (16 byte) block of input data. So, the input file (or data string) is processed in blocks of 16 bytes each, as per the Block Cipher mode of operation (see the wiki here). In addition, based on the mode of operation, Initialization Vector (IV) is also required for AES, which is unique (usually generated run time) for each encryption operation.

    I was checking out some libraries to use for file encryption in a project. So, I decided to test them mainly for the speed of encryption/ decryption, which is the subject of this post. The resultant test codes with terminal outputs are given here. These may serve purpose of example/ demo code for newcomers interested in checking out AES functionality in their programs. For testing these code examples, only hardware required is a Raspberry Pi Pico board and the USB programming cable, and you are ready to go with a laptop/PC loaded with IDE (PlatformIO or Arduino).

    Here, I'm comparing four AES libraries, tested on Raspberry Pi Pico, to check out mainly the speed and code size for the implementation. These four libraries are:


    1. Mbed AES Lib, by Neil Thiessen
    2. Arduino AES Lib, by Matej Sychra
    3. MbedTLS Lib, by ARMmbed
    4. tiny-AES-c Lib, by kokke

    All these libraries are tested here using almost same main code, with same input character string (plain text), same key and same IV. 128-bit and 256-bit AES (CBC mode) testing is done for all libraries. The key in the code is kept 256 bit long, so that the 128/192/256 AES can be selected just by changing a macro in the file. The encryption and decryption times are measured and displayed on terminal.
    Please note that these key and IV are only for the testing only, not for practical usage. In reality, usually the key is secret and IV is different for each string/file.
    The codes are tested in PlatformIO IDE, Raspberry Pi Pico-Arduino platform, which is the Arduino-Mbed package. These codes can be run in Arduino IDE as well, selecting the "Arduino Mbed OS RP2040 Board" in the board manager. The codes can be easily adopted to any other 32bit controller/IDE as well with minimum modifications.

Note: For PlatformIO, create new project and copy the downloaded files (from .zip) into the project folder. In Arduino, use main.cpp as a sketch (after renaming with .ino extension) and put the library files into the library folder of your arduino sketchbook and ignore the platformio.ini file.


Case 1: Mbed AES Lib (by Neil Thiessen)

    This library is posted in the Mbed repository, as a light-weight AES implementation with Cipher Block Chaining and Ciphertext Stealing (url: https://os.mbed.com/users/neilt6/code/AES/). 
(I had done minor modifications, mainly defining char as uint8_t, in the variable/function declarations to remove some compiler errors/warnings, during earlier testing on Mbed-Studio IDE. The same files have been used here). 
    (AES-128/192/256 option is selected here by setting AES::KEY_XXX, where XXX is the 128/192/256, in the arguments of the function aes.setup(), before encrypt and decrypt functions)

Code (aesTest1):


Results

Compiler Output:
RAM: [== ] 15.2% (used 41076 bytes from 270336 bytes) Flash: [ ] 0.2% (used 4134 bytes from 2097152 bytes)

Terminal Output (AES-128):
INPUT: AES_Test_1 - Hello! Testing AES Encryption here Cipher Text: D56B041BF7AEEA37818A98F224F38376ECB83D9F56A3354A64DFFA05D87704F7E4B86DF2E64197B66843BE995B Encryption Time (us): 1305 Plain Text: AES_Test_1 - Hello! Testing AES Encryption here Decryption Time (us): 2337 SUCCESS

Terminal Output (AES-256):
INPUT: AES_Test_1 - Hello! Testing AES Encryption here Cipher Text: ACAC7D235752782F65C4C9ABB5AA5BD60D2B5DECDD0E94035CA2B49785C295132885FD282A96C32C7A95184931ED4E Encryption Time (us): 1842 Plain Text: AES_Test_1 - Hello! Testing AES Encryption here Decryption Time (us): 3338 SUCCESS

Download Code files:
  • aesTest1.zip (main.cpp, AES_lib.cpp, AES_lib.h and platformio.ini)    

Case 2: Arduino AESLib Library (by Matej Sychra)

     This library is part of Arduino libraries (AESLib - Arduino Reference), as an ESP32/ESP8266 library for Arduino IDE to wrap AES encryption with Base64 support. This works on Pi Pico as well. Repository url is: https://github.com/suculent/thinx-aes-lib. The library files are used as downloaded without any changes.
     (AES-128/192/256 option is selected here by setting AES_XXX, where XXX is the 128/192/256, in the arguments of the function calls aesLib.encrypt64() and aesLib.decrypt64(). Appropriate macros are already defined at the top part of the code).

Code (aesTest2):


Results

Compiler Output:
RAM: [== ] 17.4% (used 47100 bytes from 270336 bytes) Flash: [ ] 0.2% (used 4546 bytes from 2097152 bytes)

Terminal Output (AES-128):
INPUT: AES_Test_2 - Hello! Testing AES Encryption here Cipher Text: 6368354D2F51637A744E694D7A344D4B4F67382B6230467A58752F53624636516979577A6371756C7A545430344E422B41747A5861364D6E5370774962452F766A356663575369335576645A794B765562795372337366455A78484856754F59674D5167736E4674372B6B3D Encryption Time (us): 456 Plain Text: AES_Test_2 - Hello! Testing AES Encryption here Decryption Time (us): 820 SUCCESS

Terminal Output (AES-256):
INPUT: AES_Test_2 - Hello! Testing AES Encryption here Cipher Text: 43304A6C774347356D7745484D3534666D4537792B6F4132494342354858734C724C5663705645666D36772B6F677058736C4A474374767973694A6C714E5961546F375532476737516752376936364861683557783173364C746243726E41757130334546622F38725A303D Encryption Time (us): 604 Plain Text: AES_Test_2 - Hello! Testing AES Encryption here Decryption Time (us): 1093 SUCCESS

Download Code files:
  • aesTest2.zip (main.cpp, AESLib library folder and platformio.ini) 

Case 3: MbedTLS Library (by ARMmbed)

     Mbed TLS is a C library that implements cryptographic primitives, X.509 certificate manipulation and the SSL/TLS and DTLS protocols. Its small code footprint makes it suitable for embedded systems. (Ref: https://github.com/ARMmbed/mbedtls). We are using here only the AES functions of this library. As this library is part of the Mbed-OS, no need to separately download/add, we just need to include the relevant file in the code and call the functions.
     (AES-128/192/256 option is selected here by setting AES_XXX, where XXX is the 128/192/256, in the arguments of the function calls mbedtls_aes_setkey_enc() and mbedtls_aes_setkey_dec(). Appropriate macros are already defined at the top part of the code). 

Code (aesTest3):


Results

Compiler Output:
RAM: [== ] 15.3% (used 41320 bytes from 270336 bytes) Flash: [ ] 0.2% (used 4082 bytes from 2097152 bytes)

Terminal Output (AES-128):
INPUT: AES_Test_3 - Hello! Testing AES Encryption here Cipher Text: FB934B82E7CA12EAD35C017948AB881A3CEAB6A58C1BED4B2C1CF6D9B79F2EF691488A1E98D6F36CB51EE15F0FFAE42 Encryption Time (us): 170 Plain Text: AES_Test_3 - Hello! Testing AES Encryption here Decryption Time (us): 161 SUCCESS

Terminal Output (AES-256):
INPUT: AES_Test_3 - Hello! Testing AES Encryption here Cipher Text: 22BFF69B724C3F5CCDCA0D930823F2662ED857E0F1617808AAEA51F7592E6B3F72B262D801AF52FE4911B3B2B Encryption Time (us): 215 Plain Text: AES_Test_3 - Hello! Testing AES Encryption here Decryption Time (us): 207 SUCCESS


Download Code files:
(Note: While testing in Arduino IDE, if you are not using"Arduino Mbed OS RP2040 Board" in the board manager, you will need to download the mbedtls library as well and put it in the library folder for this code to work).

Case 4: tiny-AES Library (by kokke)

    This is a small and portable implementation of the AES ECBCTR and CBC encryption algorithms written in C (Ref: https://github.com/kokke/tiny-AES-c). 
      (AES-128/192/256 option is selected here by defining the symbols AES128 or AES192 or AES256 inaes.h. Default setting AES128 is already defined there.

Code (aesTest4):


Results

Compiler Output:
RAM: [== ] 15.1% (used 41000 bytes from 270336 bytes) Flash: [ ] 0.2% (used 4082 bytes from 2097152 bytes)

Terminal Output (AES-128):
INPUT: AES_Test_4 - Hello! Testing AES Encryption here Cipher Text: 997E26867A8D10145EDA12F1FBBE45B2794929C45E2086F6172801AB0ABE711AEE0EBF548A958B928E851BF96E5A4 Encryption Time (us): 246 Plain Text: AES_Test_4 - Hello! Testing AES Encryption here Decryption Time (us): 463 SUCCESS

Terminal Output (AES-256):
INPUT: AES_Test_4 - Hello! Testing AES Encryption here Cipher Text: 2461EC62971158335F198DE6A3478E9B459A1AED7BFF647BAAF031B132EF094BE4C9B3EEA2177D52858FF329ED7662 Encryption Time (us): 345 Plain Text: AES_Test_4 - Hello! Testing AES Encryption here Decryption Time (us): 622 SUCCESS


Download Code files:
  • aesTest4.zip (main.cpp, tiny-AES library folder and platformio.ini) 


Sr.

No.

Library

AES-128 Time (µs)

AES-256 Time (µs)

Pi-Pico Usage (KB)

Encrypt

Decrypt

Encrypt

Decrypt

RAM

FLASH

1.

Mbed AES lib,

by Neil T.

1305

2337

1842

3338

41.076

4.134

2.

Arduino AESLib,

by Matej S.

456

820

604

1093

47.100

4.546

3.

MbedTLS,

by ARMmbed

170

161

215

207

41.320

4.082

4.

tiny-AES,

by kokke

246

463

345

622

41.000

4.082



    From the above comparison, it is clearly seen that the No.3, MbedTLS AES, is fastest among all the four. Flash and RAM consumption is also low. (Note: In these examples, major chunk of RAM, >40KB, is occupied by the background processes of Mbed OS itself).
    MbedTLS is also feature-rich, when you go further into encryption, for applications like IoT. It's a good library to practice with, for future expansion of the hobby projects. Considering that, I'm also adding here an example of encrypting/ decrypting a file using MbedTLS functions.


    Here, we're going to encrypt and decrypt a small file from the on-board Flash memory of Pi Pico. LittleFileSystem and BlockDevice (FlashIAPBlockDevice) libraries built into the Mbed-OS are used here for creating and accessing the files. As onboard memory is used, no extra component is required apart from Pi Pico + Programming cable setup used in the above AES examples. 
    The file encryption/ decryption function (fileAES()) is adopted from the main() function of crypt_and_hash.c file of mbedtls library. 

    While encrypting, this function reads the input file (plain text) and AES key, generates Initialization Vector (IV), then hashes the IV and AES key together to setup AES context and generate HMAC (Hash Message Authentication Code). Then it carries out encryption (cipher update) block-by-block (block size: 128 bits/16 bytes). The output file (named here as cipherFile.aes) is created in the format: 
    Output File: IV (16 bytes) + encrypted file blocks + HMAC/Hash (64 bytes)

    While decrypting, the cipher file is input along with the AES key, the IV is read from cipher file, the hashing is done similar to as done during encryption, then decryption is carried out block-by-block, and finally the Hash is compared with what is stored in the cipher file to confirm the validity of decrypted output file. 
    The AES key is declared in the main.cpp file for the demo purpose, not for use in actual project. A fixed text string is used repeatedly for creating the input file. These can be modified in the main.cpp.

Code (littleFsAes):

    Following is the main file where filesystem is mounted and input (with data to be ecrypted), cipher (empty) and output(empty) files are created. After creating these files, the fileAES function is called with arguments for encryption and then decryption. The time is measured in miliseconds to display on terminal. The file system used here is LittleFileSystem from Mbed-OS. The input and output files can be printed on terminal by enabling the relevant commented out section of the code.

main.cpp


Following is the header file for using with fileAES.cpp.

fileAES.h


    Following is the fileAES.cpp file where fileAES() function is implemented. This file is originally taken from MbedTLS library, crypt_and_hash.c. Minor modifications are done to convert existing main() function in it into fileAES() function, which is called from main() function given above. As file access functions of the original file are same in LittleFS as well, modifications are minimum. 

fileAES.cpp

Results

Compiler Output:
RAM: [== ] 15.3% (used 41380 bytes from 270336 bytes) Flash: [ ] 0.2% (used 4534 bytes from 2097152 bytes)

Terminal Output (Input File with 10 lines, 630 Bytes):
AES File Encryption (using Mbedtls) on Raspberry Pi Pico (mbed-arduino) Flash BD Initialized! FileSystem mounted! File Size (W): 630 Encryption Done, Time taken: 2343 ms Decryption Done, Time taken: 2338 ms Example Done!

Terminal Output  (Input File with 100 lines, 6300 Bytes):
AES File Encryption (using Mbedtls) on Raspberry Pi Pico (mbed-arduino) Flash BD Initialized! FileSystem mounted! File Size (W): 6300 Encryption Done, Time taken: 2425 ms Decryption Done, Time taken: 2429 ms Example Done!

    File size here is in Bytes. The increased file size does not increase the time significantly for small file size, as the AES context setup part dominates the time taken  as compared to the time taken in encryption/ decryption. Also, the Flash memory is faster. When the file is stored in external memory devices like SD card, the serial interface speed as well as the device library being used affect the encryption/ decryption time w.r.t. change in the file size. 

Download Code files:

    If you have more jobs to be done which are time critical, the time consuming job of file encryption/ decryption can be given to the second core of Pi Pico, which will significantly free up the first core. In my future post, I'll add the code examples for file encryption on SD cards as well as the multicore implementation.

Happy coding!

4 comments:

Elizabeth Johanson said...

Thank you so much for this code testing on Raspberry Pi Pico as I am a computer science student and I was here searching for the masters dissertation proposal help for myself because these complex topics create so much difficulty for myself.

Nick Hunter said...

I am in my last year of software engineering. This coding information is helpful for me. Since I need to complete lots of programming assignments, I like to spend my spare time on programming blogs and tutorials. I find this post very helpful and will be sharing this with my friends. In addition, I was looking for the best dissertation writing services for my sister.

oliver jake said...

Very interesting blog. I also want to introduce my website to students here if you're student and thinking can I Hire Someone To Take My Online Exam , Yes of course you can by visiting DO MY EXAM NOW. Get good grades by taking our online exam help and impress your teachers. Say goodbye to your tensions now!

Ravinder said...

https://www.startupicons.in/future-of-digital-marketing/

Visualize yourself in the next ten years. You may not read this in the written format, rather you may hear it as narrative audio in the background with you in your favourite virtual ocean. It might seem not to happen now, but it will be true soon. Yes, digital marketing will make everything possible. It is beyond imagination. Do you want to know how? Read ahead and get to know the future of digital marketing.