This article is about a demonstration made for a public workshop in 2019 in collaboration with NXP. The demonstration shows the A71CH Secure Element of NXP in combination with Toradex's Colibri iMX6ULL and Torizon. It includes a secure client - server communication, with authentication of the client, for a secure and integer file download. The given use case shows how a docker container can be exchanged with a file from a server, using the implemented secure file download. With this, one can go through different code segments in the demo code and see how the A71CH Secure Element can be used, either directly or with the provided OpenSSL engine.
This article complies to the Typographic Conventions for Torizon Documentation.
Note: The demo itself can also be used with other Toradex modules. Just ensure to use the proper I2C and proper SDK to the module. Note: The demo was made with A71CH Host Library v01.06.00 and TorizonCore 0.3a1
When will this secure docker container update fail?
Clone the GIT repository of this demonstration into the local workspace.
$ git clone https://github.com/toradex/a71ch-demo.git
Go to NXP's A71CH Secure Element product page and download the Host Software Package from "Tools & Software". Distribute the files of the corresponding folders to the related folders in the local repository (doc, hostLib and linux). Note: Download the "(Bash Installer for e.g. Linux or Cygwin)"-Version to work on a Linux Host machine.
After cloning the GIT repository and downloading the host software package, the local workspace should look similar to this:
$ tree -L 2
.
├── doc
│ ├── a71chDoxy
│ └── A71CH_HostLibrary_documentation.html
├── hostLib
│ ├── a71ch
│ ├── api
│ ├── CMakeLists.txt
│ ├── embSeEngine
│ ├── libCommon
│ ├── platform
│ ├── rjct
│ ├── ToolchainFile_imx6.cmake
│ └── tstUtil
├── linux
│ ├── buildA71CH.sh
│ ├── Makefile_A71CH
│ └── packageA71chOpenSslEngine.sh
├── README.md
└── toradex
├── certs
├── files
├── target
└── webserver
First enable the proper toolchain for the target: Note: Refer to the article of Linux SDKs if you don't know which toolchain to use.
$ source /usr/local/oecore-x86_64/environment-setup-armv7at2hf-neon-angstrom-linux-gnueabi
First one can build the configuration tool for the A71CH called a71chConfig_i2c_imx
by entering following line:
$ cd linux
$ make -f Makefile_A71CH default app=A71CH_CONFIG conn=i2c platf=imx
Second we want to build the specific OpenSSL engine (in the same folder) with the follwing command:
$ make -f Makefile_A71CH engine app=A71CH_ENGINE conn=i2c platf=imx
Next we want to create the library files which we need for the demo. For this, one need to create the build folder, create the make files using cmake and build the libraries using make.
$ cd ../hostLib/
$ mkdir build
$ cd build/
$ cmake -DUSE_SMCOM_I2C=ON ../
$ make
NXP provides a script in their host library to the A71CH Secure Element module. One can either edit the script and change the properties of the X.509 certificate which gets generated, or take the default values and run it directly. The script is located under hostLib/embSeEngine/a71chDemo/scripts/tlsCreateCredentialsRunOnClientOnce.sh
After creating the certificates copy them to the proper location.
Following files from hostLib/embSeEngine/a71chDemo/ecc
need to be copied to toradex/certs/
:
Following files from hostLib/embSeEngine/a71chDemo/ecc
need to be copied to the client to ~/eccKeys/
:
For the provisioning of the A71CH Secure Element, the configuration application (a71chConfig_i2c_imx
) which we compiled in the section Building of the libraries and the A71CH tools is required. Copy this tool to the target.
NXP provides a script to do the provisioning of the A71CH Secure Element. Copy the script located under hostLib/embSeEngine/a71chDemo/scripts/tlsPrepareClient.sh
to the target module. Check the references to the cert-files in the shell-script and change them to where ever the cert-files are stored. The path of client_key_ref
points to the location where the reference key should be stored in future and the file itself does not exist yet (will be created with the provisioning). Please also check the location of the probeExec
which should point to the copied a71chConfig_i2c_imx
.
For the provisioning of the A71CH Secure Element, one should connect the A71CH properly and ensure that the module is in Debug Mode. If the module is not in debug mode, one could use the config-utility to configure it. If everything is okay, run the script.
Copy the following files compiled in the section Building of the libraries and the A71CH tools to the target under /usr/lib/
:
Also copy the OpenSSL configuration to the target. The configuration from the A71CH is located under hostLib/embSeEngine/info/opensslA71CH_i2c.cnf
and needs to be copied to the target under /etc/ssl/
.
Warning: Torizon uses OSTree on it's filesystem, which is not intended to be changed or be extended with other libraries without committing a new tree. For the purpose of this straight forward demo, we ignore this fact and just copy these files into the filesystem tree under /ostree/deploy/torizon/deploy/<tree hash>/path/to/file
.
Note: There is also a folder /usr/etc/
which is part of a feature from OSTree. One can ignore that. For more information have a look on the OSTree docs.
The A71CH software package makes use of the specific openssl version 1.0.2. One need to ensure that the target has this version of the OpenSSL library available. To build this specific version of libssl for Torizon, make use of OpenEmbedded. To setup the environment of OpenEmbedded and build OpenSSL for Torizon, follow this article. Build the specific libssl.so.1.0.2 with following command and copy the built library to the target in /usr/lib/
as well.
$ MACHINE=colibri-imx6ull source setup-environment build-colibri-imx6ull
$ bitbake openssl10
Warning: Torizon uses OSTree on it's filesystem, which is not intended to be changed or be extended with other libraries without committing a new tree. For the purpose of this straight forward demo, we ignore this fact and just copy these files into the filesystem tree under /ostree/deploy/torizon/deploy/<tree hash>/path/to/file
.
The demo application runs on the target side as an application written in C, which is controlling and executing the secure download of a file from the server. Also there is a shell-script, which is asking for parameters, starting the secure download-application and importing the file into docker. The application files for the target are located in toradex/target/
. To build the C-application, introduce the proper toolchain like in section Building of the libraries and the A71CH tools and run make
.
$ cd toradex/target/
$ source /usr/local/oecore-x86_64/environment-setup-armv7at2hf-neon-angstrom-linux-gnueabi
$ make
Copy the a71chtdx
and the update.sh
to the target.
The demo consists of a server and a client part. If the preperation is done properly, one should be able to run the demo now.
To start the python webserver, just head to toradex/webserver
and start the webserver with python3 webserver.py
. All files which should be accessable from the client should be located in the folder toradex/files
.
Note: One may have to install some additional python3 packages on the host system.
To run the update on the client, one may first have to create different versions of docker images (to see that the update actually works). One could do this by use the export command of docker and create a new image out of an existing one and apply slight changes for different versions. See https://docs.docker.com/engine/reference/commandline/export/ for more details.
Warning: Be aware that the download size of the image is limited to 100MB. This is hard coded in the a71chtdx.c. If bigger files want to be downloaded, one can adjust the memory allocation of the read buffer.
With the update script, one is also able to remove an existing image simultaneously to the update. The issuer of the command will be asked for an image ID before the update starts. One can also leave this blank, but then no existing Docker image will be removed.
The update itself uses docker import to create a new image out of a tar. This means, one need to ensure that the tar-file is properly exported from a docker container and that it is possible to import it.
The following figure describes the application flow of this demonstration. While omitting the context of the SSL/TLS handshake and the bash script on the target, the figure shows the application flow of the secure client and the web server, including the authentication process and file download.
To use another I2C device, one needs to change the device in the hardcoded file under hostLib/platform/imx/i2c_a7.c
.
static char devName[] = "/dev/i2c-1"; // Change this when connecting to another host i2c master port
Due to the simplicity of the demonstration, the secure file download application is in one file without any header files or external functions. Additionally, also the file download is pretty simple only using SSL_read
instead of any other library functions. In regards to this, it doesn't make sense to download huge files this way and the max file size which could be transfered is estimated with 100MB. If one would like to extend this, one can change the read buffer size in the file toradex/target/a71chtdx.c
on line 875:
/* Receive data from server, extract the required information and store the file on the host. */ readBufferSize = 104857600 * sizeof(char); //100M readBuffer = (char*) malloc(readBufferSize); unsigned int filesize = 0;