Nest Hacking

From Exploitee.rs
Jump to navigationJump to search

Hardware

  • TSL2571 Light-to-Digital Converter

Info

  • /dev/event1 is the knob; /dev/event2 is the button

Nest software

/nestlabs/sbin/nlclient -config /nestlabs/etc/client.config -config /nestlabs/etc/Display/Display-2/client.config

Backplate firmware

Found in /nestlabs/share/bp/data/firmware/nlbpfirmware.plist

There are 6 different firmwares in the file:

  • Backplate 2 vs Backplate 3
  • TFE (BP_D2 for Bp2, AMBER_BP for Bp3) vs BSL
  • For TFE firmwares, hex vs srec (which for some reason DO differ!)

Nest backplate interface

  • Connected on /dev/ttyO2
  • All communications with backplate begin with (d5)d5aa96 (d5 is doubled only for data FROM backplate)
  • Everything is little endian
  • 16-bit command
  • 16-bit data length
  • 16-bit checksum

Monitor:

strace -ff -p $(pidof nlclient) -x -s9999 -e read,write 2>&1 | grep '(54'

Checksum

<Bytes-from-end>.<bit-value> <xor-with>

00.01  2110 (1021)
00.02  4220 (2042: 1021<<1)
00.04  8440 (4084: 2048<<1)
00.08  0881 (8108: 4084<<1)
00.10  3112 (1231: 8108<<1^1021)
00.20  6224 (2462: 1231<<1)
00.40  c448 (48c4: 2462<<1)
00.80  8891 (9188: 48c4<<1)
01.01  3133 (3313: 9188<<1^1021)
01.02  6266
01.04  c4cc
01.08  a989
01.10  7303
01.20  e606
01.40  cc0d
01.80  981b
02.01  3037
02.02  606e
...
03.01  b476
03.02  68ed
03.04  f1ca
03.08  c385
03.10  a71b
03.20  4e37
03.40  9c6e
03.80  38dd
...
07.20  687b

If you compute the contribution of the individual bit changes in the data you end up with the xor table above; byte offset from the end of the data, bit pattern, xor value. Correcting for little endianess in the output you end up with the hex values in parenthesis. The least significant bit is 0x1021 and each subsequent bit is a shift left, if the XOR value has the 0x8000 bit set then it is XORed with 0x1021. This is the CRC-CCITT polynomial.

 8  7  6  5  4  3  2  1  0
d5 aa 96 82 00 02 00 00 00: 08b2
         ||     |
         ||     68ed
         |408b
         20d4
 
08b2: 68ed ^ 408b ^ 20d4

Starting at the least significant bit and filling in the XOR values for each bit gives the above diagram; the diagram stops at the 20d4 XOR value because at that point it matches the final CRC. This tells us that the CRC covers the 6 bytes prior.

#!/usr/bin/env perl
use Digest::CRC qw(crc);
my $data = pack("H*", "820002000000");
printf("%04x\n", crc($data,16,0,0,0,0x1021,0,0));

We can also compute the same CRC in Perl; note the result will be byte swapped since the data encodes the number as little endian.

Command ids

Display to backplate

0082 - FET control
0083 - (every 30 seconds; no data)
008f - FET presence
0090 - (no data)
0098 - (no data)
0099 - (no data)
009b - (no data)
009c - (no data)
009d - (no data)
009e - (no data)
009f - (no data)
00a1 - (16-bit data)
00a2 - (every 30 seconds; no data)
00a3 - (every 30 seconds; no data)
00a4 - (16-bit data)
00b1 - button pressed/unpressed (no data)
00b3 - (32-bit data; always ffffffff?)
00b5 - (16-bit data; always 0f00?)
00b9 - (32-bit data; always 0000ffff?)
00ba - (48-bit data; always 000000000000?)
00c2 - (48-bit data)
00ff - Request info

Backplate to display

0001 - (message from backplate; ASCII)
0002 - Temperature reading (twice every 30 seconds; 32-bit data)
0004 - FET presence
0005 - (32-bit data)
0007 - (every second; 16-bit data)
0009 - FET presence
000a - (every second; 16-bit data)
000b - Backplate state
000c - (16-bit values: pir, px1, px1 divisor, px2, px2 divisor, alir, av)
0010 - (24-bit data)
0014 - (16-bit data)
0018 - (48-bit data)
0019 - (52-BYTE data)
001b - (24-bit data)
001c - (24-bit data)
001d - (16-bit data)
001e - (13-BYTE data)
001f - (128-bit data)
0022 - (every 30 seconds; 4, 8, 20, 28, 36, 56, 60, 54, 68, 72, or 176 byte data)
0023 - (6, 12, 30, 42, 54, 78, 84, 90, 96, 102, 108, 144, or 150 byte data)
0025 - (2, 4, 12, 14, 20, or 24 byte data)
0027 - (8, 16, 48, 56, 80, or 96 byte data)
0029 - (6, 12, 36, 42, 60, or 72 byte data)
002b - (8, 16, 24, 32, 40, 128, or 152 byte data)
002f - (every 30 seconds; 16-bit data; "end of buffers ACK" log msg)

Backplate state

Data:

  • 8-bit "state"
  • 8-bit "flags"
  • 8-bit "px0" (may be wider?)
  • 40-bit UNKNOWN (includes at least "p2" and "voc")
  • 16-bit centi-volts "vi"
  • 16-bit milli-volts "vo"
  • 16-bit milli-volts "vb"
  • 8-bit ("pins" or "wires")
  • 8-bit ("wires" or "pins")
  • 16-bit UNKNOWN

FET control

Turn on  W1: d5aa96 8200 0200 00 01 29a2
Turn off W1: d5aa96 8200 0200 00 00 08b2
Turn on  Y1: d5aa96 8200 0200 01 01 1891
Turn off Y1: d5aa96 8200 0200 01 00 3981
Turn on  G : d5aa96 8200 0200 02 01 4bc4
Turn off G : d5aa96 8200 0200 02 00 6ad4
Turn on  OB: d5aa96 8200 0200 03 01 7af7
Turn off OB: d5aa96 8200 0200 03 00 5be7
Turn on  W2: d5aa96 8200 0200 04 01 ed6e
Turn off W2: d5aa96 8200 0200 04 00 cc7e
Turn on  Y2: d5aa96 8200 0200 07 01 be3b
Turn off Y2: d5aa96 8200 0200 07 00 9f2b
Turn on  * : d5aa96 8200 0200 0b 01 d37e
Turn off * : d5aa96 8200 0200 0b 00 f26e

For the sake of documentation, we will refer to the unique id numbers for each wire as "wire id numbers". So wire id 0 is W1, wire id 1 is Y1, wire id B is *, etc.

FET presence

The backplate will, at least upon connection, send information about which FETs have a wire present. This data is received with command ids 0004 and 0009, in that order. Each sensor is represented by one byte which is either 00 (not present) or 01 (present).

The content of 0004 is in order of the "wire id numbers" used for control: W1, Y1, G, OB, W2, ?0, ?0, Y2, ?1, ?1, ?0, *, ?0

The content of 0009 is arranged differently and has 2 more values: W1, Y1, ?1, ?1, ?0, G, OB, W2, ?0, Y2, ?0, *, ?0, ?0, ?0

After these are received, the display sends back command 008f with the exact data from message 0004. Message 008f does not itself receive any response.

Temperature reading

The backplate will send message 0002 every 30 seconds. The data contains two 16-bit numbers, which nlclient logs in decimal. The first number is the temperature in centi-celcius. The second number is the humidity in per-millis.

Request info

At least upon connection, the display sends message 00ff to the backplate to request information. This takes just under half a second, so it may trigger some initialisation as well.

The backplate answers with:

0001 msg "<version> <build timestamp "YYYY-MM-DD HH:MM:SS"> K"
0004 FET presence
0009 FET presence
0001 msg "*sense 06d1 06d0 0001 0001 0000 0000 0000 0001 06d9 06d8 06d8; detect 09d3 065c"
0001 msg "BRK"

Run BeagleBone/Debian programs

ln -s . /lib/arm-linux-gnueabihf
ln -s ld-2.11.1.so /lib/ld-linux-armhf.so.3