05/24/2018 at 09:04 •
Over the past week I added security features to the PTR firmware. Until now it was possible for anyone with a DTMF capable radio to issue commands to any PTR node within range. I wanted to prevent unauthorized control of my devices (however unlikely that may be) so I added one-time-password authentication to the protocol.
Amateur radio laws in the U.S. prohibit the obscuring of messages, but permit the use of access security mechanisms as long as the meaning of the underlying message being transmitted remains intelligible. To meet this requirement I implemented HOTP based authentication compatible with RFC 4226. HOTP utilizes a shared secret key and a counter to generate a sequence of one-time-use passwords that can be sent "in the clear" alongside the command messages of the push to reboot protocol.
The use of HOTP authentication in the PTR protocol is very simple. A controller radio issues a 6-digit one-time-password (OTP) to all nodes on the same frequency. When a node receives an OTP it checks it against a set of locally generated OTPs for a match. If a valid OTP is entered the node "unlocks" and interprets subsequent command messages that are sent within a fixed time window. This authentication provides minimal security without sacrificing the ability to use the protocol from a radio keypad.
HOTP requires a secret be shared between client and the authenticating party. This secret can be entered into the serial interface of a node as a base 32 or hexadecimal string. The following is a screenshot of a dummy code being entered into the serial interface:
I ended up implementing all of the HOTP algorithms (SHA1, HMAC, base 32, and hex) from scratch to meet the memory requirements of the ATmega328. This added some development time, but the trade-off was more C experience and a codebase that has no external dependencies aside from avr-libc. I chose HOTP over TOTP because the ATmega doesn't have a real time clock and I didn't want to add anymore hardware to the project than I had to. I also took the opportunity to write tests for all of the algorithms and other bits of portable code in the project to ensure my implementations were correct.
Because the authentication is RFC 4226 compatible, common applications like Google Authenticator can be used to generate one-time passwords. I successfully used Authenticator to generate codes and send commands to my prototype. I plan to provide a video demonstration of this once I finish the PTR hardware prototype.
Security was the biggest hurdle in this project to date. Now that the hard code is written I can focus on finishing the simple hardware features that remain: a TX radio interface and local controls to override each outlet on a node.
04/29/2018 at 01:26 •
I finished a couple more features to the PTR firmware this week. The primary feature added was a command line interface for managing device settings over USB serial. Currently this interface supports setting and showing individual values, showing all values, resetting all values to default, and showing help and version screens. Configurable values are node number, reboot duration, and call duration. The following is a screenshot of the output of the
helpcommand in Minicom:
Initially this was useless because a power cycle knocked out all settings as they were stored in RAM. To fix this I added code to save the configuration to the ATmega's EEPROM memory whenever a value is changed. The current firmware also stores the state of the node's ports after a command is completed. This allows the device to restore to the previous state in the case of a power failure or equipment migration.
Along the way I learned more about the architecture of the ATmega. After I added the initial command line code, the firmware's data segment bloated to over 1kB. I did some research and found this was expected behavior because the AVR utilizes a modified Harvard architecture. Constant and literal values are copied to RAM on startup which causes a ton of memory to be wasted if these values are large. I was able to overcome this limitation by using the macros in AVR Libc's pgmspace.h to store string literals in program space. Avr Libc provides several string functions that operate on strings stored in program space natively, so converting the existing code was very straightforward.
There is still much to be added before an initial release can be made. My next task is going to be to create a transmit interface for the PTR controller so confirmation tones can be sent back to the controller radio.
04/24/2018 at 14:22 •
Yesterday I tested a cheap radio with the Push to Reboot prototype. Until now I have been testing the prototype using a DTMF generator app on my phone and a standard 3.5mm TRS auxiliary cable. I switched to a 3.5mm to 2.5mm cable and attached the output of an Amcrest ATR-22 directly to the input of the DTMF module. I hit a couple snags along the way, but nothing came up that wasn't too easy to fix.
The radio I attached to the node prototype is one I snagged on Amazon for about $15 (I bought a 2-pack for 30$). I chose this radio because it was cheap and had FCC certs, but any radio with a "Kenwood" headset pinout should work. I used the keypad of my TYT MD-380 to send DTMF tones to the ATR-22, but the DTMF module showed no input. I double checked the schematic of the radio's headset and DTMF module and found an issue. I got the schematic of the headset connector from the The (Chinese) Radio Documentation Project and the schematic of the module from a product page I found.
The radio uses the tip of the audio connector for audio while the module uses the ring. It is simple to modify the module to make the two compatible: the module needs to be rewired to receive audio in the tip of the TRS connector instead of the sleeve. The module I received uses a connector with exposed contacts. I used a pair of diagonal cutters to remove the middle contact then bridged the tip and sleeve pads on the underside of the board with solder.
After this modification the DTMF module started receiving audio. I entered a few test commands on the keypad of the MD-380 at close range and all worked perfectly. After testing with the keypad I loaded up several commands as PTT-IDs to be sent on key-up of the PTT button. To my surprise most commands sent this way were ignored by the node. I removed the cables from the ATR-22 and listened to the tones sent by the MD-380 directly. For some reason the MD-380 does not always send DTMF tones correctly when they are sent as PTT-IDs. Almost every transmission was missing at least 1 DTMF digit and some transmissions didn't send DTMF tones at all. I tried repeating the test after creating a fresh codeplug and reverting to a stock firmware, but nothing fixed the issue. I can only assume this is a bug in the current MD-380 firmware (v13.20).
Aside from finding a bug in my radio this test was a success. I found a receiving setup that only required minimal modification of the DTMF module and allows me to use standard audio jumper cables. Now that a radio is attached I can get to work on a transmitting interface for sending confirmation tones.
04/20/2018 at 03:09 •
Today I added some core features to the PTR firmware. I made a more complete driver for the MT8870 DTMF decoder module that only accepts messages that start with
*and end with
#. I added a couple of other features like a character timeout and bad message rejection to simplify other parts of the firmware that handle the DTMF input. I also started a basic driver for the SainSmart 4-channel 5V relay module that I added to control small AC loads. This driver is dead simple; it abstracts the inverted logic of the module to make higher level code simpler.
The biggest feature I added was command processing. The current firmware is capable of fully controlling the relay module via the DTMF command protocol described in an earlier log. Command processing is fully functional, but the firmware still lacks many base features. Right now settings like node number, reboot duration, and call duration are hard coded. In the future these settings and others will be set by a computer via USB serial interface. The current firmware also lacks any sort of persistence of state to EEPROM. Port state needs to be stored and restored at startup so correct operation can be restored in the case of a power fault.
I'll be working on the mentioned features and more this coming week. I'm also planning to experiment with real radios instead of simulating a radio link with my phone. Using real radios means I can also start work on the interface to send audio from node to controller. There is much to be done.
04/18/2018 at 18:55 •
When I was brainstorming for this project I debated using a dedicated DTMF decoder IC or decoding tones using software and digital signal processing. The microcontroller I'll be using for this project is an Arduino Nano clone which is based on an ATmega328P microcontroller. This microcontroller has a couple of libraries available for DTMF decoding, but I can't find any such libraries that include tests or evidence that they work reliably in the real world. I decided to take the easy way out and buy a few DTMF decoder modules that use the MT8870D decoder IC.
I ordered the modules from Amazon, but the same blue module seems to be available from a variety of online sellers. For some reason all the modules I've seen have the pins installed "upside down". I'm not sure what the logic behind this was, but it makes prototyping a bit more difficult. I corrected this issue by removing the pins and installing them on the bottom of the boards so I can easily use the modules on breadboard and perfboard. To the left is a module as it is assembled, to the right is a module that I modified.
I was curious about what all the extra interface circuitry was on the module, so I looked up a schematic for the module and hit up the chip's datasheet. I found the schematic for the module by Googling and ended up at this product page. It turns out the MT8870D can be configured for a wide variety of use cases that can affect the timing of DTMF digits. The module utilizes an example circuit exactly as it appears in the datasheet.
The table at the end of the datasheet indicates that the example configuration should accept 40ms mark and space durations and reject any durations that are less than 20ms. I plugged the module into a breadboard and verified this was the case using and Android app called ToneDef. After I wired up the module I created a firmware repository on GitLab and hacked together a simple driver to echo received digits over the serial line.
I have only done basic testing, but the MT8870 module seems to be working very well. I may try to release a version of the firmware in the future where DTMF decoding is done in software, but for now the low cost and high accuracy of the decoder modules is very attractive.
04/15/2018 at 18:02 •
In the last log I started to define a simple protocol that fits in a 5 character DTMF PTT-ID. I have since thought of some additions that would make the protocol more useful and secure. I'm using this log to capture some of these ideas and open them for discussion/suggestion.
Each node has an ID number assigned to it. This ID was defined as zero-indexed in the last log, but I think it would be more intuitive to reserve ID 0 for a special case and start node and port numbering at 1. One-indexed addressing would mean node 1 and port 1 would have address 1 instead of 0 which (to me) feels more natural when using a numerical keypad. The use of 0 would then be to multicast a command to all nodes or an action to all ports. For example, the command
*00A#would now perform action A on all ports of all nodes. To addess the first port of the first node (as in the last log) the command would be
I've mentioned "actions" for ports, but until now I haven't defined any. Actions are assigned to the DTMF letter digits A, B, C, and D. The commands containing these actions will most likely be programmed as PTT-IDs, but theres a chance at some point they will be keyed in manually. I have assigned verbs to each action to make programming and manual keying easier.
Action Verb Description A Activate Turn the port(s) on. B (re)Boot Turn the port(s) off for 5 seconds, then on. C Call Turn the port(s) on for 5 seconds, then off. D Deactivate Turn the port(s) off.
After expanding the capabilities of the controller to deactivate all devices on multiple nodes I started to worry a bit about security. The ability to multicast is very useful and very dangerous. Without safeguards in place any radio owner is able to control the power of any device they can find. This is obviously no good, so some form of authentication must be used.
After looking around for existing telecommand authentication methods I found a very interesting video about telecommand using authenticated APRS messages. The method described is a form of time-based one-time password (TOTP) algorithm. The general idea is to send a token from sender to receiver that verifies the identity the sender. A secret like a password is held secretly by both the sender and receiver. This secret is salted with the current timestamp and hashed to create a token which is then sent from the sender to the receiver. When the receiver receives the token it generates a new token using the same process and compares the two. These two tokens will only match if the secret and timestamp matches on both ends. The token is time-sensitive and secret-based meaning the secret must be known to create it and it cannot be reused after a short period of time by a third party.
I really like the method described in the talk by K7UDR because it's a standard that is currently in use. There is, however, one small problem with the proposed method. Both the sender and receiver must have accurate and synchronized time sources. This means the use of a real time clock and/or the use of network time synchronization. I would like to avoid the extra complexity and additional hardware that would be necessary when using time-based token generation. After searching a bit more I found another algorithm that generates something called an HMAC-based one-time password (HOTP). Like a TOTP, an HOTP is generated using a changing salt to prevent replay attacks, but unlike a TOTP an HOTP doesn't require a time source to be generated. An HOTP is generated using a counter that is incremented by both sender and receiver after every successful authentication. I think this is a good compromise for the application because it allows some security without increasing the cost of each node being built.
I wanted to get these ideas out and written down before working on any software or hardware. I think this protocol will be convenient and secure, but there are probably a lot of issues I haven't thought of. The DTMF boards have arrived from Amazon so I get started on a basic firmware while I think of more protocol ideas.
04/13/2018 at 21:37 •
I recently purchased a SharkRF openSPOT to feed my hardware addiction. Initially I installed it next to my computer and the rest of the IP networking equipment, but after a few days of playing I wanted to see if I could access it from a nearby park. I decided to increase elevation and add an external antenna, but to do so I had to move the setup to my attic. I managed to stuff the openSPOT, a wireless router, and some power supplies into a cheap plastic ammo can that lives happily upstairs for now.
Through testing and fiddling with the network I managed to climb up the rickety ladder to the attic at least a half dozen times. Each time I ascended I wondered how many more trips I would get away with before the folding ladder decided it wanted to become a set of individual ladders and leave me at the bottom. I also wondered how long it would be before I walked all the way to the park only to realize the network equipment was unresponsive.
After thinking for a while I came up with an idea to remotely control outlets by (ab)using a feature called PTT-ID (ANI) that is built into many handheld radios. PTT-ID enables the radio to self identify before and/or after each transmission by sending out a 5 digit code as DTMF tones. This code is intended to be decoded by other radios to identify the transmitting party, but it can be used to send any arbitrary string of DTMF codes to other radios.
The idea I came up with consists of a "controller" radio that is programmed to broadcast DTMF commands and one or several "nodes" that receive and interpret the sent commands. Each node consists of a UHF handheld radio attached to a microcontroller that sets the state of relay-controlled outlets when a command is received. Each outlet is referred to as a "port" on the node. The controller and all nodes operate on a single frequency (simplex) and use a simple addressing scheme to determine which node acts on a broadcasted command.
The format of the commands sent by the controller is simple:
Where "node" and "port" are a single digit numbers and "action" is a digit in "A, B, C, D". Asterisk and pound are used as delimiters to reduce the chance of a non-controller DTMF transmission being interpreted as a command. For example, if you wanted the first outlet on the first node to perform the "A" action you would send the command
*00A#. After performing the action, the node would respond with a confirmation tone to indicate a command was received and an action was performed.
Right now this is all just an idea. I have ordered a DTMF decoder and relay board from Amazon and now I'm playing the waiting game. Once the parts arrive I can prototype a couple of nodes and start experimenting with the cheap radios I have laying around.