IOTA Masked Authenticated Messaging on OpenSTLinux
This is the third tutorial on my series of IOTA based projects on OpenEmbedded hardware. It is another Proof of Concept meant to show the exciting possibilities that the meta-iota OE layer create.
This time I decided to move in the direction of Industrial IoT Hardware. STMicroelectronics is a leading Integrated Device Manufacturer delivering solutions that are key to Smart Driving, Smart Industry, Smart Home & City and Smart Things. The IOTA Foundation recenlty published “IOTA Links with STMicroelectronics to Accelerate IoT Technology Integration”. The cornerstone of this cooperation was the integration of the IOTA Tangle into STM32Cube expansion software for the industry-leading STM32 32-bit MCU (Cortex-M*) ecosystem, the X-CUBE-IOTA1. And now meta-iota is adding a new path for this collaboration, for the OpenSTLinux side of things. OpenSTLinux is a Linux distribution based on the OpenEmbedded build framework, and you can find information about it on its official OpenSTLinux Wiki.
So let’s talk about the hardware. The STM32MP157C-DK2 Discovery Kit leverages the capabilities of STM32MP1 Series microprocessors to allow users easily develop OpenSTLinux applications for the ARM Dual Cortex A7 main processor, as well as STM32CubeMP1 software for the Cortex M4 coprocessor. While the X-CUBE-IOTA1 toolkit is useful for the M4 coprocessor, we’re going to focus on the OpenSTLinux of the Cortex A7.
For this Proof of Concept, we’re going to send Masked Authenticated Messages (MAM) from OpenSTLinux into the Tangle. We will use the MAM examples provided in the EnTangle’d repository, although I’m hosting them in my own repository to ease the integration into its BitBake recipe.
MAM is the result of a research collaboration between the IOTA Foundation and the Belarusian State University (BSU). In a nutshell, MAM acts as a second layer data communication protocol that adds functionality to send and receive encrypted data streams over the Tangle. MAM aims at the important need for integrity and privacy in the IoT industry because how the IOTA consensus protocol encapsulates those message streams. For more in-depth explanations of MAM, please refer to:
- Introducing Masked Authenticated Messaging, by Paul Handy
- IOTA: MAM Eloquently Explained, by ABmushi
- IOTA tutorial 19: Masked Authenticated Messaging, by Mobilefish
- MAM Update: C Libraries and Release, by Aaron Alsop
- How is authenthicity and confidentiality maintained for MAM channels on the IOTA Tangle? by Marius Ødegard
For this tutorial we will take a different workflow, when compared to the previous ones. Instead of building a whole image, we will use the stock distribution provided by ST with the board. It already contains a prebuilt image of the OpenSTLinux distribution. You can also download it from ST’s website and flash it into the SD card. We will build .deb
packages of entangled-mam-examples and its dependencies, and install them on the OpenSTLinux environment.
Preparing the STM32MP157C-DK2 board
When you purchase the STM32MP157C-DK2 board, it comes with an SD Card pre-flashed with OpenSTLinux. But you can always follow the steps described in the Getting Started section of the STM32 MPU Wiki to get OpenSTLinux installed in the SD Card of the board.
Start by connecting minicom to the /dev/ttyACM0
device so you can interact with the board via UART through the ST-LINK/V2–1 cable (microUSB). Make sure the board has an Ethernet cable connected to your LAN router. After turning the board on, wait until Linux finishes booting up, and then find out the board’s local IPv4 address with the ifconfig
command (look for eth0
device). In my case, it’s 10.0.0.111
.
BitBaking the .deb packages
Now we’re going to use BitBake to generate .deb packages of entangled-mam-examples and its dependencies. We’re going to set everything up so the resulting packages are matching with the OpenSTLinux distribution running on the board, so we can install them with the dpkg package manager.
1. Prepare your workstation for Yocto/OpenEmbedded development. Refer to Yocto’s official documentation for more details on setting up.
Assuming you are using Ubuntu 18.04:
$ sudo apt-get install sed wget curl cvs subversion git-core coreutils unzip texi2html texinfo docbook-utils gawk python-pysqlite2 diffstat help2man make gcc build-essential g++ desktop-file-utils chrpath libxml2-utils xmlto docbook bsdmainutils iputils-ping cpio python-wand python-pycryptopp python-crypto libsdl1.2-dev xterm corkscrew nfs-common nfs-kernel-server device-tree-compiler mercurial u-boot-tools libarchive-zip-perl ncurses-dev bc linux-headers-generic gcc-multilib libncurses5-dev libncursesw5-dev lrzsz dos2unix lib32ncurses5 repo libssl-dev
2. Clone and initialize the repositories for OpenSTLinux. We are using Google’s repo tool for that:
$ mkdir ${HOME}/stm32
$ cd ${HOME}/stm32
$ repo init -u https://github.com/STMicroelectronics/oe-manifest.git -b refs/tags/openstlinux-4.19-thud-mp1-19-02-20 && repo sync
$ ls layers/
meta-openembedded meta-qt5 meta-st meta-timesys openembedded-core
3. Clone meta-iota
into the layers
subdirectory:
$ cd ${HOME}/stm32/layers
$ git clone https://github.com/bernardoaraujor/meta-iota.git
$ ls
meta-iota meta-qt5 meta-timesys
meta-openembedded meta-st openembedded-core
4. Start the build environment:
$ cd ${HOME}/stm32/
$ DISTRO=openstlinux-weston MACHINE=stm32mp1-disco source layers/meta-st/scripts/envsetup.sh
5. Add meta-iota
to the BASELAYERS
variable of conf/bblayers.conf
. This will inform BitBake that we will also work with the meta-iota
layer.
...
BASELAYERS ?= " \
${OEROOT}/layers/meta-openembedded/meta-oe \
${OEROOT}/layers/meta-openembedded/meta-gnome \
${OEROOT}/layers/meta-openembedded/meta-xfce \
${OEROOT}/layers/meta-openembedded/meta-initramfs \
${OEROOT}/layers/meta-openembedded/meta-multimedia \
${OEROOT}/layers/meta-openembedded/meta-networking \
${OEROOT}/layers/meta-openembedded/meta-webserver \
${OEROOT}/layers/meta-openembedded/meta-filesystems \
${OEROOT}/layers/meta-openembedded/meta-perl \
${OEROOT}/layers/meta-openembedded/meta-python \
${OEROOT}/layers/meta-iota/meta-tangle \
"
...
7. Start building the entangled-mam-examples
package:
$ bitbake entangled-mam-examples
Grab a coffee and watch BitBake do its magic. This will probably take a while.
8. Copy the packages from tmp-glibc/deploy/deb/cortexa7t2hf-neon-vfpv4
to the board (entangled-mam-examples and its dependencies):
$ cd tmp-glibc/deploy/deb/cortexa7t2hf-neon-vfpv4
$ scp entangled-mam-examples_git-r0_armhf.deb \
libcjson1_1.7.10-r0_armhf.deb \
libhttp-parser2.8_2.8.1-r0_armhf.deb \
mbedtls_2.13.0-r0_armhf.deb \
root@10.0.0.111:/home/root
9. On the ssh connection with the board, install the packages into OpenSTLinux with the dpkg
utility:
# dpkg -i libcjson1_1.7.10-r0_armhf.deb
# dpkg -i libhttp-parser2.8_2.8.1-r0_armhf.deb
# dpkg -i mbedtls_2.13.0-r0_armhf.deb
# dpkg -i entangled-mam-examples_git-r0_armhf.deb
Running the MAM examples on OpenSTLinux
It’s finally time to run the MAM examples on OpenSTLinux! Run the following commands on the ssh connection with the board.
1. First, let’s create a disposable random seed. Remember, this is just an illustrative example! Seeds should never be exposed in plaintext, source code, or command line history! This example code is just meant to show how the MAM library is used, and real production scenarios must handle seeds with the appropriate security measures.
# cat /dev/urandom |tr -dc A-Z9|head -c${1:-81}
ARDNWTPEAYOYQRDYPUACNWIWZPP9AHADVAJEAUBKDTLDMMHRNTLLHCSN9ODRFL9PHBTWQAXICOPS9YBII
2. Let’s run the send-header example. This command will send a header, meaning it will declare a new message. These are the parameters that the executable expects:
# iota_mam_send_header
usage: send-header <host> <port> <seed> <msg_public_key_type> (0 - on channel, 1 - on endpoint, 2 - announce channel, 3 - announce endpoint)
So let’s use 174.141.204.79
as host (node address), 14265
as port (HTTP API), ARDNWTPEAYOYQRDYPUACNWIWZPP9AHADVAJEAUBKDTLDMMHRNTLLHCSN9ODRFL9PHBTWQAXICOPS9YBII
as seed, and 0
for public key type.
# iota_mam_send_header 174.141.204.79 14265 ARDNWTPEAYOYQRDYPUACNWIWZPP9AHADVAJEAUBKDTLDMMHRNTLLHCSN9ODRFL9PHBTWQAXICOPS9YBII 0
Address: CDNOAZAEOSKUIKMOGDBYYZHOB9ARPNQDCKHAPEVSMSV9UWCSAHUBZKDNICCDEFZAMTYPAEZJJ9BETYOMN
Message ID: IONONZOXVGTNGVEOCXPUI
Bundle: XXEKIDKRCHEJNJJOPBVNNJRODSZV9IINGIILTZTLJL9VGGTWSAGCTRYYCXXAYFTUNLLURUQEYELYY9GIC
3. Now, let’s run the send-packet example. This command will send a packet to the message we created with the previous send-header example. These are the parameters that the executable expects:
# iota_mam_send_packet
usage: send-packet <host> <port> <seed> <msg_id> <payload> <last_packet>
So let’s use 174.141.204.79
as host, 14265
as port, ARDNWTPEAYOYQRDYPUACNWIWZPP9AHADVAJEAUBKDTLDMMHRNTLLHCSN9ODRFL9PHBTWQAXICOPS9YBII
as seed, the same msg_id
we got from running send-header (IONONZOXVGTNGVEOCXPUI
), "Test123"
for payload, and yes
for last packet (meaning we won’t send any other packets to this message).
# iota_mam_send_packet 174.141.204.79 14265 ARDNWTPEAYOYQRDYPUACNWIWZPP9AHADVAJEAUBKDTLDMMHRNTLLHCSN9ODRFL9PHBTWQAXICOPS9YBII IONONZOXVGTNGVEOCXPUI "Test123" yes
Bundle: XVKUDVIDIKQBBPEOFLKWYBVJDGLXGEKKACG9KFJZTWUULGNUEBYFHYYEPRCBNQT9KIZZXHJXDEE9JZKKW
4. Now let’s run the send-msg example. This command will send a header followed by a packet, which is the same behavior as running send-header and send-packet in sequence. These are the parameters that the executable expects:
# iota_mam_send_msg
usage: send-msg <host> <port> <seed> <payload> <last_packet>
So let’s use 174.141.204.79
as host, 14265
as port, ARDNWTPEAYOYQRDYPUACNWIWZPP9AHADVAJEAUBKDTLDMMHRNTLLHCSN9ODRFL9PHBTWQAXICOPS9YBII
as seed, (IONONZOXVGTNGVEOCXPUI
), "Test123"
for payload, and yes
for last packet.
# iota_mam_send_msg 174.141.204.79 14265 ARDNWTPEAYOYQRDYPUACNWIWZPP9AHADVAJEAUBKDTLDMMHRNTLLHCSN9ODRFL9PHBTWQAXICOPS9YBII "Test123" yes
Address: CDNOAZAEOSKUIKMOGDBYYZHOB9ARPNQDCKHAPEVSMSV9UWCSAHUBZKDNICCDEFZAMTYPAEZJJ9BETYOMN
Message ID: IONONZOXVGTNGVEOCXPUI
Bundle: SLPCJIRDW9KUGPBXOFD99YIWPIAJKLQXHJOIPTDAEDHVEQVKRFETSABQZEGDWKAVEFZOU9YXVIS9NLGZX
5. Finally, let’s run the recv example. This command will read the message from some specific bundle. These are the parameters that the executable expects:
# iota_mam_recv
usage: recv <host> <port> <bundle> <chid> (optional)
Let’s use 174.141.204.79
as host, 14265
as port, the same bundle that was output from the last send-msg example (SLPCJIRDW9KUGPBXOFD99YIWPIAJKLQXHJOIPTDAEDHVEQVKRFETSABQZEGDWKAVEFZOU9YXVIS9NLGZX
), and nothing for chid
since it’s optional.
# # iota_mam_recv 174.141.204.79 14265 SLPCJIRDW9KUGPBXOFD99YIWPIAJKLQXHJOIPTDAEDHVEQVKRFETSABQZEGDWKAVEFZOU9YXVIS9NLGZX
Payload: Test123
And voilà! We got the same payload ("Test123"
) that we had sent with send_msg!
Conclusion
This was another article to show the possibilities of the meta-iota OpenEmbedded layer.
I wanted to show how hardware that is commonly used for Industrial IoT applications can interact with the Tangle, this time by sending Masked Authenticated Messages. Like all the other tutorials, there should be enough flexibility so the steps listed here could be easily adapted into other kinds of hardware supported by the Yocto Project and OpenEmbedded.
If you have any questions or feedback, feel free to write a comment below, DM me on Discord (Bernardo [IF]#8478) or send me an email (bernardo.araujo@iota.org).