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

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!

Sunday, January 9, 2022

Raspberry Pi Pico - A Tiny Power-Packed Development Board

 




Raspberry Pi Pico is a relatively new, tiny but powerful development board designed by the Raspberry Pi (UK), which is based upon RP2040 microcontroller chip, developed in-house by Raspberry Pi. The microcontroller has dual-core Arm Cortex- M0+ Processor, running at clock up to 133MHz, with 264KB internal RAM and supports up to 16MB of external Flash. Multicore operation is supported by a pair of four entry FIFOs (one in each direction between the cores).

The Pi Pico board has 2MB of on-board QSPI Flash, which is programmable through USB Mass Storage Device mode or using Serial Wire Debug port. It also features wide range of flexible I/Os, like GPIO, UART, I2C, SPI, USB and also Programmable I/O (PIO), which is unique to this board. The board has small footprint with solderable headers. It is very cost-effective, available from large number of vendors, may be available in your nearest electronic shop, too. This opens doors for utilization towards a wide range of applications for novices as well as experts.

Detailed information on Raspberry Pi Pico is available here:

Following image with Pin-diagram of Pi Pico gives idea about various I/Os of the device: (courtesy- Raspberry Pi website):


The Pi Pico can be programmed in C/C++ (SDK support is provided by Raspberry Pi), Arduino or MicroPython. A lot of resources have already been made available in such a short time, for this board. That actually shows the rapid growth of interest in Pi Pico and usage by hobbyists/ professionals together. New libraries, packages and platform supports are getting added at quite a fast pace.

I've liked this board so much that I'm literally hooked to it ๐Ÿ˜Š. The purpose of my this post is just to put up an introduction with resource pointers, which I wanted to do for quite some time, before I start posting experimental codes also, using it.


The Pico-SDK: This is official SDK from Raspberry Pi team, for writing C/C++ or assembly language code for Pi Pico, full with headers, libraries and build system, designed to provide an API and programming environment. Multicore support examples are also given.

Pico-SDK GitHub page provides detailed description and links for documentation for using the SDK projects. The SDK can be easily setup with VS Code for programming the Pi Pico. It also has the example projects to demonstrate the use of SDK for various peripherals/ interfaces of the device.

(You can also visit the wizio-pico project page on github, for faster way of getting started with installation and usage of pico-sdk on PlatformIO with VS Code)


The Pico-Arduino: The addition of the Arduino support has made Pi Pico even more easier to use for any newcomer who wants to get hands-on experience with it. 

There are two packages, shown in Arduino Boards Manager, "Arduino Mbed OS RP2040 Boards" and "Raspberry Pi Pico/RP2040" as shown here:



Both these board support Pico-SDK functions also. Raspberry Pi Pico/RP2040 GitHub page shows detailed information on installation and usage of the package with Arduino. Arduino Pico Document  provides detailed information on writing the code, with examples. This document by Earle F. Philhower, III, is getting updated, like, every other day! :)  This board also supports multicore programming using additional setup() and loop() functions (named setup1() and loop1()).

The  Arduino Mbed OS RP2040 Boards package supports Pico with Mbed RTOS for Arduino. This is really powerful. The Mbed OS is already being used widely in ARM Cortex devices, and support for the same in Pico Arduino makes things even more versatile and mighty by providing access to the various Mbed APIs inside Arduino.

With PlatformIO for VS Code: PlatformIO is a powerful IDE, which can be used for Pi Pico Arduino. The "Raspberry Pi Pico" board is shown in the Board Explorer of PlatformIO home menu. This is same as "Arduino Mbed OS RP2040 Boards" in Arduino IDE. The platfomIO provides professional features of code editing, auto code-completion suggestions / intelliSense, debug options, etc., which are not available currently in Arduino IDE.

Both the above Arduino packages have different default pin assignments for I2C, SPI, etc. Hence, interchangeability of the code has to be properly checked before changing the board setting. As lot of work is currently going on, I suppose there will be a single combined package in the future, which will do away with some of the initial confusion while programming.


Pi Pico with MicroPython: Pi Pico can also be used with MicroPython (or CircuitPython) interpreters, which make programming still easier for newbies who want to avid C/C++, or for programmers already experienced in Python.

Micropython.org page for Pi-Pico provides quick-start reference on installation and usage of micropython on Pi Pico. Also, Raspberry Pi official Datasheet of Python SDK is filled with detailed info on coding with micropython, with examples. This GitHub page also provides ready to use examples in micropython.

Thonny is easy to use, light-weight Python IDE for beginners. The Raspberry Pi page here provides getting started with micropython using Thonny IDE. The Adafruit page provides details on configuring Thonny with CircuitPython for Pi Pico.


Supporting Base Boards: Raspberry Pi Pico is easy to use on breadboard itself for initial prototyping or testing work, great for hobbyists. But if you need some proto board with ready connections for experiments, the Maker Pi Pico Base board looks great. It has got LEDs already mounted on each GPIO pin, providing visual feedback on the code functioning. It has also got other peripherals like microSD card, buzzer (speaker), audio jack, pushbuttons and also connector for ESP32 device for adding WiFi to the project. It's also available online, I think at most places. Here is my board:


You can also opt for a simple GPIO extension boards, like these:



These board are available on amazon, needs to just search for Pi Pico. You'll also get these or similar easily from your local suppliers, too. (In my recent experience during the chip shortage period, I've found getting Pi Pico boards far easier than many other development boards. That's one more incentive to use them!)

Summary:

I hope this gives you the idea of how easy it is to get started with Pi Pico board. The board is really cute, beautifully manufactured! Once you hold it in your hand, may be you'll fall in love with it, too!!๐Ÿ˜Š Small and yet, it is so powerful for such a size! Go ahead and grab one, you won't regret it.! ๐Ÿ‘


Further Reading/ References:

  1. Raspberry Pi Pico Getting Started (Intro to setting up development environment, programming and loading the code into the board)
  2. RP2040 Microcontroller Datasheet (device datasheet of the chip itself)
  3. Pi Pico Board Datasheet (Pico board details with electrical, mechanical specs, powering, components, schematics and application briefs)
  4. Pi Pico Pinout (Pinout with alternative functions)
  5. Pi Pico Hardware Design Reference (Must read before you go ahead with making more hardware connections, other than blinking LEDs!)
  6. Pi Pico C/C++ SDK (C/C++ API function/interface details)
  7. Pi Pico Python SDK  (Python API function/interface details)
  8. Pico-SDK Documentation (doxygen)
  9. Arduino Pico documentation (details of Arduino API implementation)
  10. MicroPython Quick Reference for Pi Pico
  11. Beginner's Guide for R-Pi Pico (A nice starting guide with hardware setup and programming in MicroPython, from seeedstudio.com)

    You can also check out my next post on Raspberry Pi Pico with AES encryption example codes.