.. | ||
components | ||
main | ||
board.jpg | ||
CMakeLists.txt | ||
Doxyfile | ||
Makefile | ||
partitions.csv | ||
README.md | ||
sdkconfig |
README
Introduction
This directory contains source code for the extended-setup of an ESP32 based personal voting machine. The basic-setup consists of a microcontroller board with ESP32 module and 240x320 ILI9341 TFT LCD with Touchscreen Breakout board. The voting client is built to be compatible with the implementation of the IVXV protocol, which is used by the Estonian i-voting system. The proof-of-concept implementation only support Estonian mobile-ID for authenticating the voter and for digitally signing the ballot. ID-card support is not implemented for the proof-of-concept device.
Installation
In this project, ESP-IDF framework is used with Eclipse C/C++ IDE. Check official documentations to set up the environment.
-
Download ESP-IDF framework and toolchain
-
Download this branch and move to desired folder
-
Configure Eclipse
Configuration:
At the end, your voting should look like this:
Before flashing application to board memory, you have to connect screen device and update project configuration. You can either use the sample configuration file or generate your own. Sample configuration file - sdkconfig
is generated for the following configuration schema for DOIT ESP32-DevKit v1 micrcontroller unit:
CLK: 14
MOSI: 13
CS: 15
D\C: 21
Lite: 5
RST: 16
Y+: 32 (A4)
Y-: 25
X+: 26
X-: 33 (A5)
If you're going to generate your own configuration file, type this terminal command
foo@bar:~/OpenVotingClient/client/ make menuconfig
and follow these steps:
- go to Arduino Configuration
, uncheck Autostart Arduino setup and loop on boot
, check Include only specific Arduino libraries
and uncheck all subitems.
- go to Serial flasher config
, check Compressed upload
, set Flash SPI speed
40MHz, Flash size
4MB, 'make monitor' baud rate
115200bps
- go to Partition Table
, select option Custom partition table CSV for Partition Table
, then set Custom partition table CSV
as partitions.csv
- go to Compiler Options
, check Enable C++ expceptions
- go to Component Config
,
- select Bluetooth
, make sure Bluetooth
is unchecked
- select ESP32-specific
, set CPU frequency
240MHz, set Main XTAL frequency
40MHz
- select FreeRTOS
, uncheck Run FreeRTOS only on first core
, set FreeRTOS timer task stack size
8192
- select mbedTLS
, check Enable hardware MPI (bignum) acceleration
and Enable hardware SHA acceleration
- exit and save
Now, you can configure application related data. Again, type make menuconfig
in terminal, and select Open Voting Machine
. Here, set your personal ID code, mobile-ID registered phone number, Wi-Fi name and password, IVXV server details. Also, don't forget to change display related fields if it is different than sample configuration.
Screen and UI
This set-up uses Littlev Graphics Library (LittlevGL) to create UI components and provide user interactivity. ILI9341 screen device is ported to LittlevGL as main screen element. It is possible to replace with any other screen. LittlevGL documentation explains how to use any screen as display element. Connecting screen to microcontroller board should be configured seperately via SPI or I2C bus. All major vendors provide datasheet in which display driver commands and power on sequence is given. In client/components/drv
, there is a template disp_spi.h
for SPI connection. ili9341.c
shows how to use SPI connection and control ILI9341 display driver. Once display is succesfully turned on, it can be ported to LittlevGL using two callbacks. LittlevGL wants to know how to update screen contents. That's why ili9341_flush
method is defined. More detailed explanation is given here: Display interface
Read the documentation and implement flush mechanism for custom display driver. Then, modify client/main/impl/modules/ScreenModule.cpp
file to point correct function for disp_drv
User Input
Similar to porting screen device, LittlevGL allows to port several types of input interfaces to add interactivity. Currently, 4 input device types are supported and one of them is Pointer (touchpad or mouse). Official documentation about each type is given here: Input device interface. Following the same path as in the case of porting display driver, first input device has to be connected and there must be successful connection between device and the board. We used Touchscreen Breakout board that comes with Adafruit ILI9341 display. There are 4 pins to wire: (Y+,X-,Y-,X+). First two of them must be connected to analog pins only. Adafruit provides free open-source touchscreen library using those 4 pins. client/main/impl/TouchModule.cpp
implements LittlevGL API to port touchscreen interface as an input device.
Screen calibration is required when touchscreen doesn't work accurately. To do so, find the coordinates of 4 points close screen edges and then change values of TS_MINX, TS_MAXX, TS_MINY, TS_MAXY.
Server connection and Certificates
IVXV voting server address has to be changed prior to election. During elections server address and encryption certifcate is publicly shared. By default, port number is chosed to be 443 (SSL over TLS). Note that, client application doesn't use HTTPS protocol. Rather, it directly communicates with server over TLS.
By default, microcontrollers come with empty public certificate chain, i.e, there is no certificate to verify tls connections. Therefore, in order to support tls connections to the voting server, server root certificate (server_root_cert.pem
) is required. Similarly, encryption public key (server_public_key.pem
) is required for ElGamal encryption. These two files are embedded in flash as specified in component.mk
:
COMPONENT_EMBED_TXTFILES := server_root_cert.pem server_public_key.pem
If you use other files, do not forget to change names above and below:
extern const uint8_t server_root_cert_pem_start[] asm("_binary_server_root_cert_pem_start");
extern const uint8_t server_root_cert_pem_end[] asm("_binary_server_root_cert_pem_end");
extern const uint8_t server_public_key_pem_start[] asm("_binary_server_public_key_pem_start");
extern const uint8_t server_public_key_pem_end[] asm("_binary_server_public_key_pem_end");
...
RPC::Instance().cfg->cacert_pem_buf = server_root_cert_pem_start,
RPC::Instance().cfg->cacert_pem_bytes = server_root_cert_pem_end - server_root_cert_pem_start;
Build & Run
Either use build target in Eclipse or use terminal commands to build and flash application to ESP32 module.
make flash -j4
To print logs in terminal:
make monitor
Usage
The application follows IVXV protocol as defined in its Documentation Manual. First, you should authorize using mobile-ID, (challenge code will be displayed on screen), then see the list of candidates. Use your finger or stylus to go up or down on screen and choose one candidate. Click on NEXT button to proceed. It will take around half a second to encrypt your electronic ballot. You'll be asked to confirm challenge code again, but this time to digitally sign your ballot using mobile-ID. Upon successful voting, vote verification parameters (session id, randomness used in encryption and vote id) will be converted to QR code. Open Android verification application and scan this QR code to verify your vote. After you're done, click FINISH button to hide QR code.