-
AVR SPI Slave
02/07/2019 at 18:32 • 0 commentsAVR SPI Slave
Copyright (c) 2019 Warren Taylor.
Disclaimer
The following documentation in no way guarantees a secure system.
Overview
The original plan was to connect peripherals directly to the ESP8266 data pins but I ran out of pins very quickly. Since I had an unused ATmega168 lying around I though "what the heck" and connected the two chips via SPI with the ESP8266 as the master and the ATmega as the slave. In additions to providing a larger number of data pins this scheme also provided 5v tolerance.
This AVR SPI Slave simply receives a byte value from the controlling ESP8266 and then sets the output of Port D to this by value. In other words the ESP8266 is setting the eight Port D output pins via SPI. That's all.
However, a huge advantage for the future is that with a bit more programming in the ESP8266 the AVR can be programmed Over-the-Air, which means it can be made to do anything.
This in not an Arduino Sketch. This is very simple native AVR firmware. Why? Because I didn't know how easy native AVR programming was until I tried it.
The source for this project can be found at https://github.com/tsi-software/Secure_ESP8266_MQTT_poc
Requirements
- ATmega168 (or similar)
- avr-gcc
- AVR ISP (In-System Programming) device
Wiring up the AVR
I’m going to defer to two other web sites that do an excellent job of describing how to wire-up and program the AVR.
- http://ediy.com.my/index.php/projects/item/86-minimal-arduino-with-8mhz-internal-clock
- http://www.ladyada.net/learn/avr/index.html
Programming the AVR
Connect you development computer to the ATmega168 as described above. Then, from this "avr_spi_slave" directory, run:
make program_fuses make program
Note: "make program_fuses" only needs to be run once, not each time the source file changes.
AVR References
- http://ediy.com.my/index.php/projects/item/86-minimal-arduino-with-8mhz-internal-clock
- http://www.ladyada.net/learn/avr/index.html
- https://en.wikipedia.org/wiki/AVR_microcontrollers
- https://www.arduino.cc/en/Tutorial/ArduinoISP
- https://www.arduino.cc/en/Main.ArduinoISP
- http://maxembedded.com/2015/06/setting-up-avr-gcc-toolchain-on-linux-and-mac-os-x/
- https://www.microchip.com/mplab/avr-support/avr-and-arm-toolchains-c-compilers
- https://gcc.gnu.org/wiki/avr-gcc
- https://www.nongnu.org/avr-libc/
- http://www.engbedded.com/fusecalc/
-
Secure ESP8266 MQTT Client
02/07/2019 at 18:21 • 2 commentsSecure ESP8266 MQTT Client
Copyright (c) 2019-2020 Warren Taylor.
There are many tutorials on how to program the ESP8266 as an MQTT Client using the Arduino libraries. But it's hard to find a single source clearly describing how to program the ESP8266 as a secure MQTT Client. As a long time software engineer I know how important security is these days.
This project uses the ESP8266 Arduino Core library and board specifications
The source for this project can be found at https://github.com/tsi-software/Secure_ESP8266_MQTT_poc
Disclaimer
The following documentation in no way guarantees a secure system
Security First
At a high level of abstraction secure connections for ESP8266 devices are straight forward when using the arduino-esp8266 BearSSL::WiFiClientSecure class. This is because the BearSSL::WiFiClientSecure class extends from the insecure arduino-esp8266 WiFiClient class. What gets complicated is properly initializing a BearSSL::WiFiClientSecure object, which is what this project focuses on. Once the secure initialization is done the remaining code is implemented mostly the same as the insecure WiFiClient class, of which there are many examples.
ArduinoOTA
The ArduinoOTA library was initially used but later removed from this code because there did not appear to be sufficient resources in the ESP8266 to have a secure connection open by both the MQTT Broker and ArduinoOTA at the same time. In the future, Secure OTA will be implemented differently in order to coexist with Secure MQTT.
Source Files
secure_esp8266_mqtt_client.ino
This is the top level application source code that:
- Connects to the WAP (Wireless Access Point - a.k.a. Wifi Router).
- Securely connects to the MQTT Broker.
- Subscribes to the desired MQTT topics.
- Handles incoming MQTT messages.
- Controls ESP8266 Chip Level Data Pins.
- Configures and manages communications over SPI (Serial Peripheral Interface) with connected ATmega168. An ATmega168 is used because it has 5V tolerant pins.
SetupWifi.cpp and SetupWifi.h
This SetupWifi class handles the security and encapsulates the arduino-esp8266 BearSSL::WiFiClientSecure object. This class holds the ssid and password of the Wifi Router and implements the code to connect to that router. This class also holds the ca_cert, client_cert, and client_key used to make secure connections using the BearSSL::WiFiClientSecure class. These certificates and keys were generated when creating the MQTT Keys and Certificates in the Server Setup. Another detail handled by this class, that is not at first obvious, is accurately setting the ESP8266 clock. This is needed because security certificates can, and should, have an expiry date, which is very important in order to prevent old and possibly compromised certificates from being reused. Additionally, UTC (a.k.a. Zulu time) is the internal standard used throughout this project both for consistency and to avoid potential errors arising from differing time zones and daylight savings time.
secure_credentials.h
This file contains a copy of the required certificates and keys that were generated when creating the MQTT Keys and Certificates in the Server Setup.
Storing credentials in source code in considered both insecure and bad practice! One of the main reasons for this is because source code that is committed to your revision control system becomes openly accessible (the opposite of secure). In a subsequent version of this project "secure_credentials.h" will be removed and replaced with a method of securely injecting credentials into the target devices.
AsyncWait.h
AsyncWait.h is code that is independent of security but still worth mentioning here. One of my prime directives is to never write blocking code (code that waits for something to happen but also prevents any other code from executing). AsyncWait allows me to write code in one place that waits for a duration of time but still allows the main loop() to continue processing. I think I may write an entirely separate blog on this topic.
Zones.h
This is application level code, which is independent of security and, therefore, not discussed here.
globals.h
This is application level code, which is independent of security and, therefore, not discussed here.
Hardware Schematics
Future Features
OTA (Over-the-Air) Updates
Future versions of this ESP8266 MQTT Client will have secure OTA updates enabled. The ESP8266 will be updated in a manner similar to that of the ArduinoOTA code but instead using the existing secure MQTT connection in order to keep memory use minimal. The AVR SPI Slave will be updated over-the-air by using the ESP8266 as an AVR ISP (In-System Programming) device. Again using the existing secure MQTT connection in order to keep memory use minimal.
MQTT Client References
- https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/readme.html
- https://arduino-esp8266.readthedocs.io/en/latest/esp8266wifi/bearssl-client-secure-class.html
- https://github.com/esp8266/Arduino/blob/master/doc/esp8266wifi/bearssl-client-secure-class.rst
- https://github.com/esp8266/Arduino/tree/master/libraries/ESP8266WiFi/examples
- https://github.com/esp8266/Arduino/blob/master/libraries/ESP8266WiFi/src/WiFiClientSecureBearSSL.h
- https://pubsubclient.knolleary.net/
-
Secure MQTT Broker setup
02/01/2019 at 22:57 • 6 commentsMQTT Broker secure setup
Copyright (c) 2019-2023 Warren Taylor.
Here are the basics of how to install, configure, and secure the “Mosquitto” MQTT Broker on an already properly configured and running installation of OpenWRT. However, the MQTT Broker can run on any computer on a local area network (LAN). You could even run it on a Raspberry PI if performance isn’t a strict requirement. So the following instruction should be adaptable to most modern operating systems.
Disclaimer
The following documentation in no way guarantees a secure system.
Install Mosquitto Broker and Client
With ssh (or similar) log into your OpenWRT router.
ssh root@your-router-hostname opkg install mosquitto-ssl mosquitto-client-ssl libmosquitto-ssl
Create "mosquitto" user if it does not already exist
useradd -M mosquitto usermod -L mosquitto
Create a directory to securely hold your certificates
(Keys and Certificates can be generate on any computer as long as the required files are securely copied to the server and all keys are securely stored.)
mkdir /root/mosquitto chmod go-rwx /root/mosquitto chown mosquitto:mosquitto /root/mosquitto cd /root/mosquitto
Creating the MQTT Keys and Certificates
The documentation below talks a lot about Keys, Certificates, Certificate Authorities, etc... Rather than trying to rewrite the very good documentation others have already put a great deal of effort into, I refer you to some of their work:
- SSL and SSL Certificates Explained For Beginners
- Introduction to MQTT Security Mechanisms
- Mosquitto SSL Configuration -MQTT TLS Security
- Securing a Mosquitto Server
NEVER use the same key and certificate to secure more than one device. If one device becomes compromised then all devices secured with the same key and certificate are also compromised. When generating your credentials it is important to use different subject parameters for your CA, server and client certificates. Every time you are prompted for the CN (Common Name), enter your same server hostname. If you don't know your exact hostname then run something like:
uci show system
Create an X509 CA key and certificate for self-signing
(Determine and securely store a PEM Pass Phrase, which is used to protect your CA Key)
openssl req -new -x509 -days 365 -extensions v3_ca -keyout mosq_ca.key -out mosq_ca.crt -subj "/C=CA/ST=BC/L=your-city/O=ca.your-domain.com/OU=ca/CN=your-hostname/emailAddress=your@email.com"
Subject Parameters:
- C - Country
- ST - State
- L - City
- O - Organization
- OU - Organization Unit
- CN - Common Name (eg: the main domain the certificate should cover)
- emailAddress - main administrative point of contact for the certificate
To verify:
openssl x509 -in mosq_ca.crt -noout -text
Generate the MQTT Server private key
openssl genrsa -out mosq_serv.key 2048
Generate the MQTT Server self-signed certificate
openssl req -new -key mosq_serv.key -out mosq_serv.csr -subj "/C=your-country/ST=your-state/L=your-city/O=server.your-domain.com/OU=server/CN=your-hostname/emailAddress=your@email.com"
Generate the CA signed certificate to use in the MQTT Mosquitto Server
openssl x509 -req -in mosq_serv.csr -CA mosq_ca.crt -CAkey mosq_ca.key -CAcreateserial -out mosq_serv.crt -days 365
Generate the MQTT Client private key
openssl genrsa -out mosq_client.key 2048
Generate the MQTT Client self-signed certificate
openssl req -new -key mosq_client.key -out mosq_client.csr -subj "/C=your-country/ST=your-state/L=your-city/O=client.your-domain.com/OU=client/CN=your-hostname/emailAddress=your@email.com"
Generate the CA signed certificate to use in the MQTT Client
openssl x509 -req -in mosq_client.csr -CA mosq_ca.crt -CAkey mosq_ca.key -CAcreateserial -out mosq_client.crt -days 365
Increase the security of the files just created
chmod go-rwx /root/mosquitto/* chown mosquitto:mosquitto /root/mosquitto/*
Mosquitto server config
/etc/mosquitto/mosquitto.conf
port 8883 cafile /etc/mosquitto/mosq_ca.crt keyfile /etc/mosquitto/mosq_serv.key certfile /etc/mosquitto/mosq_serv.crt protocol mqtt tls_version tlsv1.2 require_certificate true
Copy the necessary certificates and key
cp /root/mosquitto/mosq_ca.crt /etc/mosquitto/mosq_ca.crt cp /root/mosquitto/mosq_serv.key /etc/mosquitto/mosq_serv.key cp /root/mosquitto/mosq_serv.crt /etc/mosquitto/mosq_serv.crt
Restart the Mosquitto Broker
service mosquitto stop service mosquitto start
Run a quick test
The following command should turn on zone 2 for 2 minutes (i.e. 120 seconds). Try running it now, even if the MQTT client has not yet been setup, in order to check for any errors that may occur on the server side.
mosquitto_pub -h your-hostname -p 8883 --cafile mosq_ca.crt --cert mosq_serv.crt --key mosq_serv.key --debug --topic irrigation/zone/on -m "2 120"
Error: The connection was refused.
If you are using a newer version of the Mosquitto Broker
you may get the following error messages:Client (null) sending CONNECT Client (null) received CONNACK (5) Connection error: Connection Refused: not authorised. Error: The connection was refused.
The quick solution is to update mosquitto.conf with the following line and then Restart the Mosquitto Broker:
allow_anonymous true
However, this solution is a "double edge sword". Sure, it gets things running but you may now be less secure than you require. A more complicated configuration could include:
... allow_anonymous false use_identity_as_username true ...
Or even require user name and password in addition to using security certificates and keys.
There are many more Mosquitto Security related configuration settings but I cannot tell you what to do because everyones security requirements are different and these are getting into complicated configurations that are beyond the scope of this project.
MQTT Server References