Browse Source

Worked in changes for review #5

master
Christian Pape 7 years ago
parent
commit
efe8c7793e
  1. 4
      1-introduction.tex
  2. 12
      2-related-work.tex
  3. 4
      3-environment.tex
  4. 6
      5-concept.tex
  5. 42
      6-1-build_and_deploy.tex
  6. 11
      6-2-update_mechanism.tex
  7. 4
      IEEEtran.bst
  8. 58
      esper-ota.bib
  9. 6
      esper-ota.tex

4
1-introduction.tex

@ -15,11 +15,11 @@ In addition, such an interface should provide mechanisms to check which firmware
Even if systems are equipped with an interface for applying updates, the maintenance cost can still be enormous if an administrator has to interact with each device physically and the systems are located in areas where reachability is limited.
If a system is already able to communicate over a network interface, this can be leveraged to apply updates on these system - this is typically referred to as \textit{Over the Air (OTA)}.
By reusing the existing communication channels, the dedicated update interface can be omitted which leads to smaller packaging and reduces production cost.
By reusing the existing communication channels, the dedicated update interface can be omitted, which leads to smaller packaging and reduces production cost.
It also decreases the maintenance cost drastically, because updates can be triggered remotely.
\textit{OTA} updates enable administrators to apply automation methods on the update process allowing to roll out new releases and fixes in a controlled fashion.
As an example, updates can be done on test-devices first, followed by security-critical deployments and subordinate ones can be delayed to times when the device is not utilized.
Further, a feedback channel which provides information about the update status of a devices allows administrators to apply monitoring techniques ensuring all updates are installed and devices are in the desired state.
Further, a feedback channel, which provides information about the update status of a devices allows administrators to apply monitoring techniques ensuring all updates are installed and devices are in the desired state.
The remaining part of this paper is laid out as follows.
Section \ref{related} discusses related work.

12
2-related-work.tex

@ -1,13 +1,3 @@
\section{Related Work}\label{related}
Wireless sensor and actor networks are crucial elements of today's effort to support and implement \textit{Industry 4.0} architectures and modern manufacturing processes.
Small programmable logic controllers (PLC) and cloud computing are enabler but also drivers of these new manufacturing paradigms \cite{Nigappa:2016eb}.
Thus, the networked interconnection of everyday objects, the automation of home appliances and environmental metering and monitoring based on sensors and actors controlled by \textit{ESP8266} PLCs are subject of current research.
In \cite{DiNisio:2015fg} a low-cost multipurpose wireless sensor network using \textit{ESP8266} PLCs is introduced.
The usage of \textit{ESP8266} PLCs for sensor networks is discussed in \cite{Thaker:2016fi}.
The article \cite{Kodali:2016hc} presents a home automation solution based on \textit{MQTT} with \textit{ESP8266}-driven sensors and actors.
The control of smart bulbs with PLCs is summarized in \cite{Walia:2016bj}.
Unfortunately, software update mechanisms are not addressed in these publications.
Generic approaches of decentralized software updates in IoT environments are introduced in \cite{Weisbach:2016bs} and \cite{Ruckebusch:2016vo}.
The \textit{Over the Air} programming capabilities of the \textit{ESP8266} PLCs are described in \cite{Gore:2016ue}.
Wireless sensor and actor networks are a crucial elements of today's effort to support and implement \textit{Industry 4.0} architectures and modern manufacturing processes. Small programmable logic controllers (PLC) and cloud computing are enabler but also drivers of these new manufacturing paradigms\cite{Nigappa:2016eb}. Thus, the networked interconnection of everyday objects, the automation of home appliances and environmental metering and monitoring based on sensor and actor networks controlled by ESP-based chipsets are subject of current research. In \cite{DiNisio:2015fg}, a low-cost multipurpose wireless sensor network using \textit{ESP8266} PLCs is introduced. The usage of \textit{ESP8266} PLCs in combination with Raspberry PI acting as base station for the sensors is discussed in \cite{Thaker:2016fi}. The article \cite{Kodali:2016hc} presents a home automation solution based on a \textit{MQTT} message queue with \textit{ESP8266}-based sensors and actors. The control of smart bulbs with PLCs is summarized in \cite{Walia:2016bj}. Unfortunately, soft ware update mechanisms are not addressed in these publications. The importance of regular security updates for today's infrastructures is summarized in \cite{beresford2016whack}. An approach of decentralized software updates in Contiki-based IoT environments are introduced in \cite{Ruckebusch:2016vo}. In \cite{Weisbach:2016bs}, a software update solution for devices able to execute a Java Virtual Machine (JVM) is introduced. Both solutions are not applicable for small MCU devices. In \cite{Mansour:2012fu}, a diagnoses and update system for embedded software of electronics control units in vehicles is introduced. Secure firmware updates targeted for the automotive industry is introduced in \cite{Nilsson:2008ik}. Furthermore, a secure The \textit{Over the Air} programming capabilities of the \textit{ESP8266} PLCs are described in \cite{Gore:2016ue}.

4
3-environment.tex

@ -12,10 +12,10 @@ According to the manufacturer, the ESP8266 is among the most integrated WiFi-cap
While at the beginning of this research, mostly \textit{ESP-01s} \cite{ESP-01s} boards in combination with self-developed power supplies and use-case specific hardware components were deployed, \textit{Sonoff} \cite{sonoff} wireless smart switches product series offered by \textit{ITEAD} have been integrated quickly.
The firmware for all of the \textit{ESP8266}-based devices in the hackerspace has been implemented using a common software platform, referred to as \textit{ESPer}.
\textit{Sming}, which in turn is based on the open-source SDK for \textit{ESP8266}, provides the base library for this framework.
\textit{Sming}, which in turn is based on the open-source software development kit (SDK) for \textit{ESP8266}, provides the base library for this framework.
It integrates a lot of other software components and provides all kinds of functionality shared by all devices, allowing to reuse parts of the source code in multiple devices.
For communication with the controller, the \textit{MQTT} \cite{MQTT} protocol is used.
For communication with the controller, the \textit{Message Queue Telemetry Transport (MQTT)} \cite{MQTT} protocol is used.
It provides a lightweight messaging mechanism implementing the publish-subscribe pattern that allows devices to listen for commands and publish their current state to the controller and other interested parties.
The controller software has out-of-the-box support for this protocol, which allows easy integration of all different device types using the same patterns.

6
5-concept.tex

@ -14,7 +14,7 @@ From there, the continuous integration (CI) system is responsible for automatica
It is also in charge of assembling and publishing meta-information consisting of version number and cryptographic signature required for the update process.
The CI systems is described in detail in the following section.
Updates to the devices firmware are either triggered actively (i.e., manual or by the CI) or on a regular schedule by the devices themselves.
This process is described in section \ref{flashlayout}.
This process is described in Section \ref{flashlayout}.
For monitoring and maintenance purposes, each device publishes a set of information to a well-known \textit{MQTT} topic after connecting to the network.
Beside data like device type, chip and flash ID, the published data includes details about the bootloader, SDK and firmware version as well as relevant details from the bootloader configuration, like the currently booted ROM slot and the default ROM slot to boot from.
@ -38,10 +38,10 @@ Device specific code is organized in a sub-folder for each device type.
To build the software, a \textit{Makefile} \cite{make} is used, which provides a simple way for reproducible builds.
Whenever a new build is started, the build system scans for all device specific folders and calls the build process for each of them.
After the build of the firmware has finished, the build system also creates a file for each device type, containing the build version and cryptographic signatures of the corresponding firmware images.
To avoid interferences between different build environments, and to roll out new versions as quickly as possible, the code has been integrated into a CI system which is also responsible for publishing the resulting firmware images to the firmware server queried during updates, and for notifying the devices to check for an update.
To avoid interferences between different build environments, and to roll out new versions as quickly as possible, the code has been integrated into a CI system, which is also responsible for publishing the resulting firmware images to the firmware server queried during updates, and for notifying the devices to check for an update.
\subsection{Device setup and flash layout}\label{flashlayout}
Microcontroller boards based on the \textit{ESP8266} MCU are mostly following the same layout: the MCU is attached to a flash chip which contains the bootloader, firmware and other application data.
Microcontroller boards based on the \textit{ESP8266} MCU are mostly following the same layout: the MCU is attached to a flash chip, which contains the bootloader, firmware and other application data.
The memory mapping mechanism of the MCU allows only a single page of 1 MB of flash to be mapped at the same time \cite{ESP8266_Memory_Map} and the selected range must be aligned to 1 MB blocks.
As the firmware image to download and install possibly exceeds the size of free memory heap space, the received data must be written to flash directly.

42
6-1-build_and_deploy.tex

@ -1,17 +1,16 @@
\subsection{Build infrastructure and automatic deployment}
The CI system, which is based on \textit{drone} \cite{drone} allows to execute commands, whenever a new version is published into the projects \textit{Git} repository.
A corresponding \textit{drone} configuration called \texttt{.drone.yml} exists beside the source code (Listing~\ref{lst:drone}).
A corresponding \textit{drone} configuration called \texttt{.drone.yml} exists beside the source code (Figure~\ref{lst:drone}).
Within this configuration file, settings relevant to the build process are provided to the build environment.
First, the \texttt{CONFIG=maglab} option lets the build system use an additional configuration file (\texttt{Configurion.mk.maglab}), which is stored inside the framework repository and provides environment specific information, such as the WiFi SSID.
To keep secrets like the WiFi password and the private key unexposed, it is not written down in the configuration file.
Instead, to include secrets into a build process while allowing to keep the configuration public, \textit{drone} allows to encrypt these with a repository specific key.
Using this method, the secrets are stored as \texttt{.drone.sec} file inside the repository from where they are injected into the build environment.
Also noticeable in Listing~\ref{lst:drone} is the firmware version, which is configured to be the first 8 letters of the \textit{Git} commit hash uniquely identifying a version of the source code.
Also noticeable in Figure~\ref{lst:drone} is the firmware version, which is configured to be the first 8 letters of the \textit{Git} commit hash uniquely identifying a version of the source code.
\begin{lstlisting}[language=,
caption={The \textit{drone} configuration for the \textit{ESPer} project.},
label=lst:drone, basicstyle=\ttfamily\scriptsize]
\begin{figure}[htbp]
\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
build:
image: maglab/sming
environment:
@ -29,6 +28,9 @@ publish:
destination_path: './'
when: branch: master
\end{lstlisting}
\caption{The \textit{drone} configuration for the \textit{ESPer} project.}
\label{lst:drone}
\end{figure}
For deployment, only the master branch is considered.
After a successful build, all distribution files (the firmware image and meta-information files) of all device types are copied to the repository server, from where they are served by a \textit{HTTP 1.1} \cite{HTTP_1.1} server.
@ -42,23 +44,26 @@ A single function \texttt{Device* getDevice()} must be defined exactly once in e
To implement this interface, a static instance of \texttt{Device} is created and returned.
Each \texttt{Device} is populated with device specific \texttt{Feature} instances.
While the \texttt{Feature}-API leverages common run time polymorphism to share functionality between features, the initial \texttt{Device} creation uses compile time polymorphism, which reduces the need for memory management and increases performance by avoiding virtual function tables.
Listing~\ref{lst:create_device_socket} shows the complete device specific code used for a simple power socket, which is mainly confined to the device type and its capabilities (e.g., the GPIO pin numbers to use).
Figure~\ref{lst:create_device_socket} shows the complete device specific code used for a simple power socket, which is mainly confined to the device type and its capabilities (e.g., the GPIO pin numbers to use).
\begin{lstlisting}[caption={Device specific code for a socket driver.},
label=lst:create_device_socket, basicstyle=\ttfamily\scriptsize]
\begin{figure}[htbp]
\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
#include "Device.h"
#include "features/Socket.h"
Device device:
constexpr const char NAME[] = "socket";
constexpr const uint16_t GPIO = 12;
constexpr const uint16_t GPIO = 12; // general purpose I/O
OnOffFeature<NAME, GPIO, false, 1> socket(&device);
Device* getDevice() {
return &device;
}
\end{lstlisting}
\caption{Device specific code for a socket driver.}
\label{lst:create_device_socket}
\end{figure}
The actual compilation of the source code is mainly controlled using two \textit{Makefiles}.
The first one is a helper \textit{Makefile} built to accept a parameter for device type identifiers called \texttt{DEVICE}, and to create its whole output inside a subdirectory specific to the device type.
@ -71,7 +76,7 @@ In addition, the suffix \texttt{/flash} can be used to flash a specific firmware
While building the firmware images for a device, the build environment provides some constants, which are baked into the resulting firmware image.
Beside the environmental configuration like the WiFi credentials, \textit{MQTT} topics and other configurable tweaks, the current device and version identifiers are provided as compile time constants.
In addition, the public key used to verify firmware signatures during updates is derived from the private key and provided as a object file, which is linked into each firmware image (Listing~\ref{lst:public_key_object}).
In addition, the public key used to verify firmware signatures during updates is derived from the private key and provided as a object file, which is linked into each firmware image (Figure~\ref{lst:public_key_object}).
This allows to use all the information inside the code without any overhead while being configurable during build time.
As the \textit{ESP-01s} is only equipped with 1 MB of flash, this means that the whole memory is mapped to a contiguous address space (refer to Section \ref{flashlayout}).
@ -80,10 +85,10 @@ While the firmware is executed without any dynamic linking mechanism and the chi
This arises the need for building two firmware images, one for each target location.
To do so, a linker script for each of the two ROM slots was created, which is used to create two variations of the same firmware, only differing in ROM placement.
The two resulting firmware image files are both provided for download via \textit{HTTP 1.1} - which one to download depends on the target ROM slot and is selected by the device during the update process.
Listing~\ref{lst:linker_script} shows the only difference between the two linker scripts, where \texttt{\$\{SLOT\}} must be replaced with the slot number according to the current build.
Figure~\ref{lst:linker_script} shows the only difference between the two linker scripts, where \texttt{\$\{SLOT\}} must be replaced with the slot number according to the current build.
\begin{lstlisting}[caption={Creating the linker object containing the public key.},
label=lst:public_key_object, basicstyle=\ttfamily\scriptsize]
\begin{figure}[htbp]
\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
update_key_pub.bin:
echo -n "$(UPDATE_KEY)" | \
ecdsakeygen -p | \
@ -94,19 +99,24 @@ update_key_pub.o: update_key_pub.bin
-B xtensa \
-O elf32-xtensa-le $@
\end{lstlisting}
\caption{Creating the linker object containing the public key.}
\label{lst:public_key_object}
\end{figure}
The build process will create the two firmware images, one for each ROM slot, and the meta-information file.
To create the meta-information file, the current version identifier is written to the \texttt{.version} file.
After the build, the signatures for both firmware images are created and attached to the file.
\begin{lstlisting}[language=,
caption={Linker script to build firmware for two ROM slots.},
label=lst:linker_script, basicstyle=\ttfamily\scriptsize]
\begin{figure}[htbp]
\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
irom0_0_seg :
org = ( 0x40200000 // The memory mapping address
+ 0x2010 // Bootloader code and config
+ 1M / 2 * ${SLOT} ), // Offset for the ROM slot
len = ( 1M / 2 - 0x2010 ) // Half ROM size excl. offset
\end{lstlisting}
\caption{Linker script to build firmware for two ROM slots.}
\label{lst:linker_script}
\end{figure}
Due to modern compilers doing link time optimization, the resulting firmware images include only code needed according the actual configuration.

11
6-2-update_mechanism.tex

@ -22,10 +22,10 @@ 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.
Figure~\ref{lst:choosing_rom} shows the algorithm used to determine the download address and reconfigure the bootloader.
\begin{lstlisting}[caption={Configuring the updater to download the right firmware image and update the booloader accordingly.},
label=lst:choosing_rom, basicstyle=\ttfamily\scriptsize]
\begin{figure}[htbp]
\begin{lstlisting}[basicstyle=\ttfamily\scriptsize]
#define URL_ROM(slot) (( URL "/" DEVICE ".rom" slot ))
// Select rom slot to flash
@ -40,6 +40,9 @@ if (bootconf.current_rom == 0) {
updater.switchToRom(0);
}
\end{lstlisting}
\caption{Configuring the updater to download the right firmware image and update the booloader accordingly.}
\label{lst:choosing_rom}
\end{figure}
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{.rom\{0,1\}} 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.
@ -49,7 +52,7 @@ While the image is being downloaded, each chunk received in the download stream
When the write has been finished, the next chunk is received and the process continues until all chunks have been processed.
After downloading the new firmware image has been finished successfully, the calculated hash is checked against the signature of the according firmware image.
Therefore the cryptographically signed hash, which was provided in the meta-information file triggering the update, is verified against the \textit{Curve25519} public key stored as a constant in the running firmware.
Therefore, the cryptographically signed hash, which was provided in the meta-information file triggering the update, is verified against the \textit{Curve25519} public key stored as a constant in the running firmware.
Only if the checksum matches the provided signature, the firmware is considered valid and the process is continued.
\subsubsection{Reconfiguring the boot process}

4
IEEEtran.bst

@ -131,7 +131,7 @@ FUNCTION {default.is.use.paper} { #1 }
% #0 turns off the forced use of "et al."
% #1 enables
FUNCTION {default.is.forced.et.al} { #0 }
FUNCTION {default.is.forced.et.al} { #1 }
% The maximum number of names that can be present beyond which an "et al."
% usage is forced. Be sure that num.names.shown.with.forced.et.al (below)
@ -139,7 +139,7 @@ FUNCTION {default.is.forced.et.al} { #0 }
% Note: There are many instances of references in IEEE journals which have
% a very large number of authors as well as instances in which "et al." is
% used profusely.
FUNCTION {default.max.num.names.before.forced.et.al} { #10 }
FUNCTION {default.max.num.names.before.forced.et.al} { #5 }
% The number of names that will be shown with a forced "et al.".
% Must be less than or equal to max.num.names.before.forced.et.al

58
esper-ota.bib

@ -1,85 +1,85 @@
@MISC(ESP8266,
author="ESPRESSIF",
title="{ESP8266} Overview",
note={{URL: }\url{http://www.espressif.com/en/products/hardware/esp8266ex/overview}, 2017.05.22},
note={{URL: }\url{http://www.espressif.com/en/products/hardware/esp8266ex/overview}, [accessed: 2017.05.22]},
)
@MISC(maglab,
author="{Magrathea Laboratories e.V.}",
title="Magrathea Laboratories - Creating new Worlds",
note={{URL: }\url{https://maglab.space/}, 2017.05.22}
note={{URL: }\url{https://maglab.space/}, [accessed: 2017.05.22]}
)
@MISC(HASS,
author="{Home Assistant}",
title="Awaken your home",
note={\url{http://home-assistant.io/}, 2017.05.22}
note={\url{http://home-assistant.io/}, [accessed: 2017.05.22]}
)
@MISC(ESPer,
author="ESPer",
title="ESPer - Space Automation Firmware for ESP8266",
note={{URL: }\url{https://git.maglab.space/esper/esper}, 2017.05.22}
note={{URL: }\url{https://git.maglab.space/esper/esper}, [accessed: 2017.05.22]}
)
@MISC(ESP-01s,
author="SparkFun",
title="{WiFi Module - ESP8266}",
note={{URL: }\url{https://www.sparkfun.com/products/13678}, 2017.05.22}
note={{URL: }\url{https://www.sparkfun.com/products/13678}, [accessed: 2017.05.22]}
)
@MICS(Sming,
author="Sming",
title="{Sming - Open Source framework for high efficiency native ESP8266 development}",
note={{URL: }\url{http://sminghub.github.io/Sming/about/}, 2017.05.22}
note={{URL: }\url{http://sminghub.github.io/Sming/about/}, [accessed: 2017.05.22]}
)
@MISC(make,
author="{The IEEE and The Open Group}",
title="The Open Group Base Specifications Issue 6 - make - maintain, update, and regenerate groups of programs",
note={{URL: }\url{http://pubs.opengroup.org/onlinepubs/009695399/utilities/make.html}, 2017.05.22}
note={{URL: }\url{http://pubs.opengroup.org/onlinepubs/009695399/utilities/make.html}, [accessed: 2017.05.22]}
)
@MISC(MQTT,
author="{OASIS Standard Incorporating}",
title="MQTT Version 3.1.1 Plus Errata 01",
note={{URL: }\url{http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html}, 2017.05.22}
note={{URL: }\url{http://docs.oasis-open.org/mqtt/mqtt/v3.1.1/errata01/os/mqtt-v3.1.1-errata01-os-complete.html}, [accessed: 2017.05.22]}
)
@MISC(HTTP_1.1,
author="{The Internet Society}",
title="Hypertext Transfer Protocol -- HTTP/1.1",
note={{URL: }\url{https://www.w3.org/Protocols/rfc2616/rfc2616.html}, 2017.05.22}
note={{URL: }\url{https://www.w3.org/Protocols/rfc2616/rfc2616.html}, [accessed: 2017.05.22]}
)
@MISC(ESP8266_Memory_Map,
author="{ESP8266 community wiki}",
title="ESP8266 Memory Map",
note={{URL: }\url{http://www.esp8266.com/wiki/doku.php?id=esp8266_memory_map}, 2017.05.22}
note={{URL: }\url{http://www.esp8266.com/wiki/doku.php?id=esp8266_memory_map}, [accessed: 2017.05.22]}
)
@MISC(rBoot,
author="Richard Antony Burton",
title="An open source bootloader for the ESP8266",
note={{URL: }\url{https://github.com/raburton/rboot}, 2017.05.22}
note={{URL: }\url{https://github.com/raburton/rboot}, [accessed: 2017.05.22]}
)
@MICS(drone,
author="Drone",
title="Drone is a Continuous Delivery platform built on Docker, written in Go",
note={{URL: }\url{https://github.com/drone/drone}, 2017.05.22}
note={{URL: }\url{https://github.com/drone/drone}, [accessed: 2017.05.22]}
)
@MICS(git,
author={{git -- everything-is-local}},
title="git - a free and open source distributed version control system",
note={{URL: }\url{https://git-scm.com}, 2017.05.22}
note={{URL: }\url{https://git-scm.com}, [accessed: 2017.05.22]}
)
@MICS(sonoff,
author={{ITEAD}},
title="Sonoff Smart-home",
note={{URL: }\url{https://www.itead.cc/smart-home.html}, 2017.05.22}
note={{URL: }\url{https://www.itead.cc/smart-home.html}, [accessed: 2017.05.22]}
)
@article{Ruckebusch:2016vo,
@ -182,7 +182,7 @@ publisher = {IEEE}
month = {February},
publisher = {Federal Office for Information Security, P.O.B. 20 03 63, 53133 Bonn, Germany},
institution = {Federal Office for Information Security},
note={{URL: }\url{https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TG02102/BSI-TR-02102-1.pdf}, 2017.05.22}
note={{URL: }\url{https://www.bsi.bund.de/SharedDocs/Downloads/EN/BSI/Publications/TechGuidelines/TG02102/BSI-TR-02102-1.pdf}, [accessed: 2017.05.22]}
)
@inproceedings{bernstein2006curve25519,
@ -193,3 +193,31 @@ publisher = {IEEE}
year={2006},
organization={Springer}
}
@inproceedings{Mansour:2012fu,
author = {Mansour, Karim and Farag, Wael and ElHelw, Mohamed},
title = {{AiroDiag: A sophisticated tool that diagnoses and updates vehicles software over air}},
booktitle = {2012 IEEE International Electric Vehicle Conference (IEVC)},
year = {2012},
pages = {1--7},
publisher = {IEEE}
}
@inproceedings{Nilsson:2008ik,
author = {Nilsson, D K and Larson, U E},
title = {{Secure Firmware Updates over the Air in Intelligent Vehicles}},
booktitle = {ICC 2008 - 2008 IEEE International Conference on Communications Workshops},
year = {2008},
pages = {380--384},
publisher = {IEEE}
}
@inproceedings{beresford2016whack,
title={Whack-A-Mole Security: Incentivising the Production, Delivery and Installation of Security Updates},
author={Beresford, Alastair R},
booktitle={IMPS@ ESSoS},
pages={9--10},
year={2016}
}

6
esper-ota.tex

@ -352,17 +352,19 @@
language=c++,
columns=flexible,
basicstyle={\small\ttfamily},
frame=tb,
frame=single,
keepspaces=true,
breaklines=true,
breakatwhitespace=true,
}
\setlength{\belowcaptionskip}{-5pt}
% correct bad hyphenation here
\hyphenation{op-tical net-works semi-conduc-tor}
%\parskip 6pt plus 2pt minus 1pt
\parskip 3pt plus 2pt minus 1pt
\parskip 2pt plus 1pt minus 1pt
\pagestyle{empty}
\begin{document}

Loading…
Cancel
Save