@madpilot rants

Garage Door Opener – Signing a binary using axTLS

Comparing the SHA256 of a file after it has been uploaded allows us to check that it hasn’t changed. This doesn’t tell us if the file has been tampered with though – it would be easy enough for a someone to change the binary, and then change the hash so it matches.

To check the file was created by the person who said it was created by, we need to verify a cryptographic signature. The steps are fairly simple:

  1. We upload the new binary, our public key and the signature file.
  2. We check that the public key has been signed by a trusted certificate authority – if this fails, the CA can’t vouch for the person signing it, so we shouldn’t trust it.
  3. We decrypt the signature file using the public key. This is the original SHA256 hash of the binary. If we can’t decrypt it, we can’t compare the hashes
  4. We SHA256 the binary ourselves
  5. We compare the hash we computed with the file that was uploaded. If the two hashes match, then the binary hasn’t been tampered with, and we can trust it.

I took the previous POC code, and extended it to do just that.

I’ve covered generating a certificate authority before, as well as generating a certificate. The last bit to do is to sign out binary. Again, using OpenSSL:

openssl dgst -sha256 -sign cert/developer.key.pem -out data/sig256 data/data.txt

Garage Door Opener – Signing Over-the-Air updates

The garage door opener has been running pretty well for the past couple of months, but I still have some work to do. I haven’t built out the configuration interface yet, and it turns out that if Home Assistant restarts, it forgets the last open state, so with out opening and closing the door again, I don’t know the state of the door.

This means I need to update the firmware.

The ESP8266 has facilities to do Over-the-Air (OTA) updates, however it doesn’t verify that the uploaded binary has been compiled by the person the device thinks it has. The easiest way to do this is to create a digest hash of the file and sign it. Then the device can verify the hash and check the signature matches.

There is an issue to implement this on the ESP8266 Github page, so I thought I would have a look at implementing something.

The first step is to be able to compare a hash. I decided to use the AxTLS library, as it has already been used for the SSL encryption on the device. After a google search, I found this page that outlines has to verify a SHA1 + RSA signature.

I simply pulled the sha1.c file (renamed it sha1.cpp), and created a sha1.h file that defines the functions in the cpp file. Next I created a test file, and hashed it using openssl:

openssl dgst -sha1 -binary -out hash data.txt

I then uploaded the files to the ESP8266 SPIFFS filesystem, and wrote some quick POC code.

The computed hash matches the supplied hash. Step 1 complete!

The next step will be to generate a signed digest, and decrypt that.

Reverse engineering a Fujitsu Air Conditioner Unit – The protocol from the outdoor unit

So, I think I’ve worked out the meaning of the bitstream coming from the outdoor unit!

On my day off, I took the unit of the wall, got me some coffee and setup shop in the hallway, oscilloscope in hand.

I must admit, I’m still getting used to using the oscilloscope and I’m sure there is a far better way to do what I’m trying to do, but I found that if I probe the RX pin on the CPU, with the ‘scope set to single trigger mode and keep hitting the start button, I’d eventually align the waveform at the start of the cycle. After that I used the onscreen rulers to work out the gaps between the pulses. I then wrote them down in to this spreadsheet. I’d change a setting, take a new set of readings, and repeat until I had covered enough states that I could get a complete picture of what was going on.

Looking at the data, I could start to see some patterns.

  1. The shortest spacing was around 2ms (some longer; some shorter)
  2. The RX pin is idle low, and there is always a high transition to represent the start bit
  3. There seems to be a low transition to represent a stop bit
  4. There is 9 bits between the start and stop bit (except for the last set)

It’s starting to look like a straight up serial transmission, except the idle state, start and stop bits are inverted, so unfortunately the built in serial protocol decoder wouldn’t read it.

Next I need to find the bits that change between each state.

The power bit was pretty obvious: there was only one bit that was different when the power was off – the 68th bit.

Looking at the rest of that byte, there was a pattern developing in the next 3 bits – they seemed to change when the settings changed. Taking LSB first, Fan only mode is represented by 0x01, Humidity mode (Yeah – I don’t know what that is either) is 0x02, Cool mode is 0x03, Heat mode is 0x04 and Auto mode is 0x05. The next three bits represent the fan speed: Auto 0x00, Speed 2: 0x02, Speed 3: 0x03, Speed 4: 0x04. But was was the ninth bit?

Having a think about serial, it’s could a parity bit. By summing the number of bits, it became pretty obvious it was odd parity. I checked this against the other bytes, and it checked out – now we are getting somewhere!

Looking at the next byte, it was clear it was changing with the temperature. I purposely looked at the lowest possible setting for the temperature (15deg) and the highest (30deg) and it was here I was lead down the garden path a little. Reading up on other people’s efforts at reverse engineering air conditioner units, this is a fairly common range. Many of the IR transmitters represent this as a 4 bit number, where 0x0 is 15 and 0xF 30. Unfortunately, I couldn’t for the life of me work out how that mapped to the numbers I was seeing.

It turns out, this system uses a 5 bit number – feasibly being able to represent 0 – 31 degrees. Bits 6 and 7 are always 0, and bit 8 is the “economy” settings.

There is four unknown bytes, and one block that seems to be make up of 5 bytes. My guess is one of the unknown bytes is reserved for errors, and one is a serial number of some sort. I have no clue what the other two could be for, and I’m quite confused by the last, short byte.

But this is definitely progress!

I did a final check the get some timing on what is transmitted, and there seems to be three windows of roughly 212ms each. The first from the outdoor unit, the second transmitted by the remote control, and I’m guessing the third is for a slave unit.

To build a test harness, I’ll need to bit-bang the data for 212ms, then set the line to high impedance for 424ms. This will hopefully allow me to get the remote control to work on my bench. Once I can get the remote to work, I can analyse what it is doing. Next, I’ll simulate that as well, then set the remote to slave mode and work out that part of the protocol. Once I have the three parts of the protocol nutted out, I can just simulate the outdoor unit, connect the spare remote controller as master, and the microcontroller will become the slave. Easy!

Reverse engineering a Fujitsu Air Conditioner Unit – Baseline communication

I took the remote unit off the wall again, and this time removed the signal wire fro the remote and attached it to my Oscilloscope.

And this is signal that comes from the outdoor unit.

I’m not sure if I stuffed up my reading the last time, but it looks like the pulse width is 2ms.

Really, I needed to replay this and see if I could get my test unit to initialise. I thought about using an Ardiuno, so I googled bit banging serial to see the best way to do it. One of the results that caught my eye was another Hackaday article entitled “Introduction to FTDI bitbang mode“. I had literally just cleaned up my workbench and found a FTDI module. Perfect!

I knocked up a little circuit that drove a transistor from 0V to 12V, and adapted the code from the article to control the FTDI modules CTS line. I had to reduce the sleep time to 1.8ms to adjust for kernel context switches (I’m guessing) while talking to the adapter. I got it pretty close to 2ms though.

I wired it up to the controller, and got one step closer – now instead of timing out and flashing C0 12, it just sits flashing “9C” forever.

My guess? This communication protocol works on one-wire – I’m not releasing the line, so the remote never gets a chance to send a response. It looks like I’ll need some sort of tri-state buffer, so I can set the line to high-impedance after I’ve sent the preamble.

I was curious to see if I could get any other clues to the protocol, so I started poking around the big chip on the PCB. One of the pins receives the same signal the signal line does, except it’s inveted and 0-5V! I went and looked up the chip (it’s a UPD78F0393 from NEC – I’m so glad the remote manufacture labelled all their chips nicely), and that pin (#75) is labelled RXD0. That sounds like a serial receive line to me!

Pin 76 is labelled TXD0, which I’m guessing is the transmit line. This should make decoding stuff way easier, because I’ll be able to see what is actually being transmitted and received separately. Win!

I’m going to try and trace out the front-end to this – so far I see a NJM2904 (an op-amp) is on the path – my guess is that is the thing inverting the signal and driving it to 12V. Tracing this circuit out should allow me to build a compatible circuit from my microcontroller.

Reverse engineering a Fujitsu Air Conditioner Unit – A test unit arrives

So my test unit arrived!

I get it on my bench, and test out my theory – if I’m right, it should boot up and start sending commands when the buttons are pressed.

I was wrong.

The unit just sits there flashing “9C” for a couple of minutes, then failing over to a “C0 12” error. The Oscilloscope was no use either – I just saw a constant 12V on the signal wire.

Hmmm.

Looks like I’ll have to pull off the real wall unit.

Using some wire and alligator clips, I extended the wires so I could reach them with the scope.

This time I got somewhere – I could see a signal!

The pulse width is around 1.04ms, going from 12V to 0V. Weird.

I go distracted for a while trying to decode the protocol – is there start bits and stop bits? What about a parity bit?

I knocked together a quick D3 script (I’m a web developer, remember – I use web technology for a lot of this stuff because that is what I’m used to) to display the wave form. First, I wrote a ruby script that created a CSV file of just the transitions. There are two entries for each transition – a 0V and 12V value – so the graph ends up looking like a binary stream.

I then wrote another script that aligned the stream so each pulse was exactly 1.04, and each pulse hight was 12V or 0v. Finally, I scaled everything so the pulse width was 1, as this made reading the graphs easier.

I ended up with some pretty graphs like this:

There was still a problem though – I didn’t have a baseline for the communications.

I knew that the control unit didn’t send any data unless it was connected to the outside unit. I also knew that changing the temperature changed some of the bits in the data stream, so clearly there was some half-duplex serial communication going on. I needed to find out what the outdoor unit sent to initialise the control unit…

Reverse engineering an air-conditioner remote – How does this thing work?

I’ve never done any reverse engineering before, but spurred on by this recent Hackaday article, and this article I found I thought I’d give is a crack.

The first issue: I had no idea what the model number was – it’s not written on the unit, nor on the instruction manual. So I just googled for Fujitsu airconditioner remote, hit image results and looked for one that looked the same. Once I found it and clicked through to the source page, I found out that it is a UTB-YUB/GUB/TUB (There are three model numbers depending on where in the world you are).

I found a supplier on ebay (who was actually Melbourne based), who had a new remote unit for $60, which I bought as I wanted a test unit on my workbench – mainly because trying to test things using the unit on the wall would be really annoying.

While I waited for it to arrive, I continued googling to find as much info as I could about it. Thankfully, a number of airconditioning repair places have their installation manuals online. Reading though the them, it was clear there was a three wires that connect the remote to the outdoor unit – +12V, GND and a signal.

Bingo.

Now, I need to work out what this signal wire does.

My first hypothesis was the remote unit worked a lot like an IR remote – every button press sent the complete state to the outdoor unit. If this was the case, it should just be a matter of hooking up a DSO (I have the LabNation SmartScope), copying the signal and replaying it via a microcontroller.

While I could pull the one off the wall, I patiently waited for my test unit to arrive.

IR-blaster with CEC – Stripping a Raspberry PI

I had a couple of the original Raspberry PIs on my desk, and since they were just sitting gathering dust they seemed like the perfect candidate for this project.

I don’t know why, by the composite port really irks me. I’m never going to use it, and it really juts out, and realistically this was going to be WiFi only, so I could get rid of the network port. Also, plugging in a Wifi adapter made the board unnecessarily long.

Time to trim it down a bit.

First, I removed the composite port by clipping the leads and desoldering the remains.

Then I removed the network plug. The two holes that held it in will come in handy later…

Finally, I removed the USB sockets.

Much neater! And regular shaped. Of course, there is now no way to interface with it. I took a perfectly good USB WiFi module and gutted that.

And then direct soldered it to the PI.

Now I have a minimalist WiFi-enabled RaspberryPI! If I need to make any changes, I just ssh in and do it via command line. If I really need a keyboard, I’ll just put the SD card in another PI that is more fully featured, and do it there.

Next up: the IR blaster board

Garage Door Opener – Yeah. So it works

Garage Door Opener – Hardware test

Even though I still have to complete the captivate portal, and over-the-air updates, It seemed like a good time to wire the controller in and see how it all works off the bench.

It’s a good thing I did, as I discovered a few issues with the board.

Excuse the wiring, it’s just temporary…

Originally, I had two switches: one of when the door was completely open, and one for completely closed. Based on the last state, I could guess whether the door was opening or closing. I must admit, I realised long after I ordered and built the board that I really only needed one switch that indicated the closed position. Good thing really, because the device got completely confused after I installed it.

Back story

Because of the limited number of IO pins on the ESP8266-01, I had to pull some tricks to give me two switches and a relay (I can’t take credit, this is an amalgam of a bunch of stuff I found Googling).

There are 4 GPIOs, two of which are shared with the TX and RX pins on the serial port. To make things even more interesting, GPIO0 needs to be held high on boot, otherwise the device goes in to programming mode.

This means GPIO0 is no good as a switch interface – if there was a power outage and the switch attached to GPIO0 was closed as it rebooted, the device would be stuck in program mode.

Conversely, when the device boots up, there is a bit of chatter on TX, so putting the relay on that would be risky – a reboot could cause the door to trigger, and open it when no one was home.

Wiring the relay to GPIO0 and GPIO2 is quite easy, pull them high with pull-up resistors, then switch them to outputs during the setup phase. Setting them both low at the same time sets the relay up. Pulling GPIO2 up, drives the base of a transistor and energises the relay. While the output of the chip could drive the relay directly, I’m actually using a 12v relay that is driven from the convenient 12V output from the garage door controller, so the transistor is required to switch the higher voltage from the lower 3.3V coming out of the regulator.

The “closed” switch is wired to the RX pin, and the “open” switch is wired to the TX pin. This means that the Serial Port is disabled, which can make debugging difficult, so as I work, I usually disable the switches.

This all worked fine on my bench, but as soon as I installed it the close switch wouldn’t register properly, and I couldn’t work out for the life of me why. I suspect the internal state machine wasn’t transitioning properly, possibly because of contact bounce, but it turns out it didn’t matter – I also found what I would call a show stopper: I discovered that if the TX pin was held high (ie the device booted when the door was open) it would never start.

Not ideal.

In a quick refactor of the code, I disabled the state machine, replacing it with a simpler open/close state – if the “closed” switch is closed, the device reports closed, if it’s open, it reports open. Keep it Simple. Who knew, right? Another nice side effect is I can use Serial.println for debugging again. Bonus.

So that brings the mistake count for that board up to four – thankfully all workaroundable (totally a word)fairly easily:

  1. “Open” switch not needed
  2. TX and RX pins on the FTDI connector are transposed (fixed by modifying my FTDI cable, which I’m sure will come back to bite me at some point)
  3. Originally, the GND for both switches shared a screw terminal, although now I can get rid of the open switch, I can keep the board to five screw terminals.
  4. No room for the heatsink
  5. (Improvement) Add a jumper to switch between using the 5V off the FTDI cable and an external supply – I was using a fly leads soldered to the bottom of the board while testing.

As a PCB board designer, I’m an excellent software engineer.

Garage Door Opener – Storing the configuration II

I wrote about my “generic” config class in a previous build log, and alluded to how I wasn’t really sure it was the best plan of attack.

It wasn’t.

All of the casting was painful, the setup was annoying and unnecessary (From both a memory and CPU time POV) – there was little (if any) advantage in using it.

In the end, I wrote a concrete class with mutators for each attribute. This meant each attribute is already the correct type, so there was no annoying casting, and I could control and optimise the serialisation and deserialisation.

You can see the class on Github.

The mutators are pretty straight forward, as is the serialisation:

The boolean values (as well as encryption mode and mqtt Auth mode) are compacted using bit-masks, effectively fitting five config items into one byte. Next, I store single integer and double integer values (I use doubles for port numbers), and finally strings.

The strings are encoded by putting their length in the first byte, effectively limiting string length to 255 characters, which is fine – DNS names are limited to this, and that is the biggest thing the config will store. It also makes it possible to avoid overruns, as we have an effective upper limit, so if we go past that index, we know something is broken.

Next