\subsection{The update mechanism} The update mechanism is split into four main phases: checking for updates, reprogramming the device, calculating and verifying the cryptographic signature of the updated firmware, and - assuming that the update was successful - reconfiguring the boot process to use the new firmware. \subsubsection{Checking for updates} In order to inform the IoT devices of the availability of a new firmware version, the update server provides a file for each device type containing meta-information about the latest available firmware version. The meta-information file has a simple line oriented ASCII format, which is easy to generate and efficient to parse within the limited constraints of the embedded device. It consists of the version identifier and the cryptographic signatures of both of the firmware binaries. The version identifier can be an arbitrary string as the content is not interpreted semantically but only compared to the version identifier used during build time. The other two lines in the meta-information file provide the hexadecimal representation of the cryptographic signatures, one line for each firmware binary file. These meta-information files are provided by the update server using \textit{HTTP 1.1} \cite{HTTP_1.1} under the following path pattern: \texttt{\$\{DEVICE\}.version} (whereas \texttt{\$\{DEVICE\}} gets replaced by the device type name). Each device queries the update server regularly (initially when the boot process is finished and periodically once an hour) for the currently available firmware version. It uses the \texttt{UPDATER\_URL} option to identify the update server. After the meta-information file has been downloaded successfully, the version identifier is extracted and compared to the version identifier of the running firmware. If the version identifiers differ, the update process is initialized. In cases where the download fails, the update server or network connection is not available, or any other error occurres, another attempt will be made automatically at the next regular interval. In addition to the interval, a special \textit{MQTT} topic shared by all devices is subscribed on device startup: \texttt{\$\{MQTT\_REALM\}/update}. Every time a message is received on this topic, a fetch attempt for the meta-information file is triggered and the process restarts. This allows faster roll-outs of updates and finer control for manual maintenance. \subsubsection{Reprogramming the device} The firmware files provided on the update server are the exact same ones as used to initially flash the chip for the according version. Using the same files for flashing and updating allows better debugging by eliminating errors related to the update process itself and eases development and initial installation. Listing~\ref{lst:choosing_rom} shows the algorithm used to determine the download address and reconfigure the bootloader. The update server provides these files in the exact same way as it provides the meta-information files, but the path pattern differs: the suffixes \texttt{.rom0} and \texttt{.rom1} are used to provide the firmware image files for the first and second slot respectively. For installing a firmware update, the new firmware image file is downloaded using an \textit{HTTP 1.1} \texttt{GET} request. \begin{lstlisting}[caption={Configuring the updater to download the right firmware image and update the booloader accordingly.}, label=lst:choosing_rom, basicstyle=\ttfamily\scriptsize] #define URL_ROM(slot) (( URL "/" DEVICE ".rom" slot )) // Select rom slot to flash const auto& bootconf = rboot_get_config(); // Add items to flash if (bootconf.current_rom == 0) { updater.addItem(bootconf.roms[1], URL_ROM("1")); updater.switchToRom(1); } else { updater.addItem(bootconf.roms[0], URL_ROM("0")); updater.switchToRom(0); } \end{lstlisting} \subsubsection{Verifying the cryptographic signature} While the image is being downloaded, each chunk received in the download stream is used to update the \textit{SHA256} hash before it is written to the flash. When the write has been finished, the next chunk is received and the process continues until all chunks have been received. After the download of a new ROM has been finished successfully, the calculated hash is checked against the cryptographically signed hash provided in the meta-information file triggering the update using the \textit{curve25519} public key provided by the running firmware. Only if the firmware is considered valid, the bootloader configuration is altered to boot into the new ROM slot and the device is rebooted. \subsubsection{Reconfiguring the boot process} For the bootloader, \textit{rBoot}\cite{rBoot} has been choosen as it is integrated within the \textit{Sming} framework and allows to boot to multiple ROM slots. For configuration, an \textit{rBoot} specific structure is placed in the flash at a well-known location directly after the space reserved for the bootloader code. This structure contains, among other things, the target offsets for all known ROMs and the number of the ROM to boot from on next reboot. To calculate the origin of each ROM slot, the available memory of 1 MB is split in half and an offset of the size of the bootloader code and its configuration (0x2010 bytes) is added. For alignment and easy debugging, the second block is shifted by the same amount of bytes as the first block. The gap of 8192 bytes is available to applications to store data, which can persist over application updates. The bootloader knows about the offsets of both ROM slots and is able to boot these. To decide which ROM slot is booted, a default is stored in the configuration area. The bootloader will boot the default ROM slot on normal startup but uses the other ROM slot as fallback if the default ROM slot is corrupted. To switch to the other ROM slot after successful upgrade, the default slot is changed and the device is restarted.