From 8e65db19b0ff2c0ebf1c0cf764f31048ec5b851c Mon Sep 17 00:00:00 2001 From: geeksville Date: Thu, 18 Jun 2020 11:50:04 -0700 Subject: [PATCH 1/4] Add notes on linux drivers & pins for pinetab #143 --- docs/software/pinetab.md | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 docs/software/pinetab.md diff --git a/docs/software/pinetab.md b/docs/software/pinetab.md new file mode 100644 index 0000000000..7add9e76f6 --- /dev/null +++ b/docs/software/pinetab.md @@ -0,0 +1,15 @@ +# Pinetab + +These are **preliminary** notes on support for Meshtastic in the Pinetab. + +A RF95 is connected via a CS341 USB-SPI chip. + +Pin assignments: +CS0 from RF95 goes to CS0 on CS341 +DIO0 from RF95 goes to INT on CS341 +RST from RF95 goes to RST on CS341 + +This linux driver claims to provide USB-SPI support: https://github.com/gschorcht/spi-ch341-usb +Notes here on using that driver: https://www.linuxquestions.org/questions/linux-hardware-18/ch341-usb-to-spi-adaptor-driver-doesn%27t-work-4175622736/ + +Or if **absolutely** necessary could bitbang: https://www.cnx-software.com/2018/02/16/wch-ch341-usb-to-serial-chip-gets-linux-driver-to-control-gpios-over-usb/ From 6f39f1740f9abe863949c5848229bb511aedd06f Mon Sep 17 00:00:00 2001 From: geeksville Date: Thu, 18 Jun 2020 11:57:29 -0700 Subject: [PATCH 2/4] add pinetab work queue --- docs/software/pinetab.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/docs/software/pinetab.md b/docs/software/pinetab.md index 7add9e76f6..a3ae55c37a 100644 --- a/docs/software/pinetab.md +++ b/docs/software/pinetab.md @@ -13,3 +13,12 @@ This linux driver claims to provide USB-SPI support: https://github.com/gschorch Notes here on using that driver: https://www.linuxquestions.org/questions/linux-hardware-18/ch341-usb-to-spi-adaptor-driver-doesn%27t-work-4175622736/ Or if **absolutely** necessary could bitbang: https://www.cnx-software.com/2018/02/16/wch-ch341-usb-to-serial-chip-gets-linux-driver-to-control-gpios-over-usb/ + +## Task list + +* Port meshtastic to build (under platformio) for a poxix target. spec: no screen, no gpios, sim network interface, posix threads, posix semaphores & queues, IO to the console only +* Test cs341 driver - just test reading/writing a register and detecting interrupts, confirm can see rf95 +* Make a radiolib spi module that targets the cs341 (and builds on linux) +* use new radiolib module to hook pinebook lora to meshtastic, confirm mesh discovery works +* Make a subclass of StreamAPI that works as a posix TCP server +* Use new TCP endpoint from meshtastic-python From 6566c4f15e1e2b1e66cc7451f8e3c72688faf88a Mon Sep 17 00:00:00 2001 From: geeksville Date: Thu, 18 Jun 2020 14:09:13 -0700 Subject: [PATCH 3/4] don't send bogus latitudes --- src/gps/UBloxGPS.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gps/UBloxGPS.cpp b/src/gps/UBloxGPS.cpp index 472dba1c80..1e4bad8bc2 100644 --- a/src/gps/UBloxGPS.cpp +++ b/src/gps/UBloxGPS.cpp @@ -117,7 +117,9 @@ The Unix epoch (or Unix time or POSIX time or Unix timestamp) is the number of s altitude = ublox.getAltitude() / 1000; // in mm convert to meters DEBUG_MSG("new gps pos lat=%f, lon=%f, alt=%d\n", latitude * 1e-7, longitude * 1e-7, altitude); - hasValidLocation = (latitude != 0) && (longitude != 0); // bogus lat lon is reported as 0 or 0 (can be bogus just for one) + // bogus lat lon is reported as 0 or 0 (can be bogus just for one) + // Also: apparently when the GPS is initially reporting lock it can output a bogus latitude > 90 deg! + hasValidLocation = (latitude != 0) && (longitude != 0) && (latitude <= 900000000 && latitude >= -900000000); if (hasValidLocation) { wantNewLocation = false; notifyObservers(NULL); From ea4a678308600b8641e16a9a4f98616fc2eb3040 Mon Sep 17 00:00:00 2001 From: geeksville Date: Fri, 19 Jun 2020 13:27:31 -0700 Subject: [PATCH 4/4] Add reviewer comments on crypto --- docs/software/TODO.md | 21 +++++----------- docs/software/crypto.md | 54 ++++++++++++++++++++++++++-------------- docs/software/pinetab.md | 3 +++ 3 files changed, 45 insertions(+), 33 deletions(-) diff --git a/docs/software/TODO.md b/docs/software/TODO.md index 5c80d8a68f..4794355325 100644 --- a/docs/software/TODO.md +++ b/docs/software/TODO.md @@ -2,37 +2,28 @@ You probably don't care about this section - skip to the next one. +- bluetooth toggle enable stress test, we are not properly restarting our connect - make new android release - check in our modified arduino binaries - post bug on esp32-arduino -- router mode -- let users set arbitary params in android -- encryption review findings writeup +- implement first cut of router mode: preferentially handle flooding, and change sleep and GPS behaviors +- let users set arbitrary params in android - NRF52 BLE support -- DSR # Medium priority -Items to complete before the first beta release. - -- turn on watchdog timer (because lib code seems buggy) -- show battery level as % full -- rx signal measurements -3 marginal, -9 bad, 10 great, -10 means almost unusable. So scale this into % signal strength. preferably as a graph, with an X indicating loss of comms. +Items to complete before 1.0. -# Pre-beta priority - -During the beta timeframe the following improvements 'would be nice' +# Post 1.0 ideas - finish DSR for unicast - check fcc rules on duty cycle. we might not need to freq hop. https://www.sunfiretesting.com/LoRa-FCC-Certification-Guide/ . Might need to add enforcement for europe though. -- pick channel center frequency based on channel name? "dolphin" would hash to 900Mhz, "cat" to 905MHz etc? allows us to hide the concept of channel # from hte user. - make a no bluetooth configured yet screen - include this screen in the loop if the user hasn't yet paired - if radio params change fundamentally, discard the nodedb - re-enable the bluetooth battery level service on the T-BEAM -- implement first cut of router mode: preferentially handle flooding, and change sleep and GPS behaviors - provide generalized (but slow) internet message forwarding service if one of our nodes has internet connectivity (MQTT) [ Not a requirement but a personal interest ] -# Low priority +# Low priority ideas Items after the first final candidate release. diff --git a/docs/software/crypto.md b/docs/software/crypto.md index 755cb33698..6f959bcca0 100644 --- a/docs/software/crypto.md +++ b/docs/software/crypto.md @@ -5,33 +5,51 @@ the project developers are not cryptography experts. Therefore we ask two things - If you are a cryptography expert, please review these notes and our questions below. Can you help us by reviewing our notes below and offering advice? We will happily give as much or as little credit as you wish ;-). -- Consider our existing solution 'alpha' and probably fairly secure against a not particularly aggressive adversary. But until - it is reviewed by someone smarter than us, assume it might have flaws. +- Consider our existing solution 'alpha' and probably fairly secure against a not particularly aggressive adversary +(but we can't yet make a more confident statement). -## Notes on implementation +## Summary of strengths/weaknesses of our current implementation + +Based on comments from reviewers (see below), here's some tips for usage of these radios you know the level of protection offered: + +* It is pretty likely that the AES256 security is implemented 'correctly' and an observer will not be able to decode your messages. +* Warning: If an attacker is able to get one of the radios in their position, they could either a) extract the channel key from that device or b) use that radio to listen to new communications. +* Warning: If an attacker is able to get the "Channel QR code/URL" that you share with others - that attacker could then be able to read any messages sent on the channel (either tommorw or in the past - if they kept a raw copy of those broadcast packets) + +Possible future areas of work (if there is enough interest - post in our [forum](https://meshtastic.discourse.group) if you want this): + +1. Optionally requiring users to provide a PIN to regain access to the mesh. This could be based on: intentionally locking the device, time since last use, or any member could force all members to reauthenticate, +2. Until a device reauthenticates, any other access via BLE or USB would be blocked (this would protect against attackers who are not prepared to write custom software to extract and reverse engineer meshtastic flash memory) +3. Turning on read-back protection in the device fuse-bits (this would extend protection in #2 to block all but **extensively** advanced attacks involving chip disassembly) +4. Time limiting keys used for message transmission and automatically cycling them on a schedule. This would protect past messages from being decoded even if an attacker learns the current key. + +### Notes for reviewers + +If you are reviewing our implementation, this is a brief statement of our method. - We do all crypto at the SubPacket (payload) level only, so that all meshtastic nodes will route for others - even those channels which are encrypted with a different key. - Mostly based on reading [Wikipedia]() and using the modes the ESP32 provides support for in hardware. - We use AES256-CTR as a stream cypher (with zero padding on the last BLOCK) because it is well supported with hardware acceleration. +- Our AES key is 128 or 256 bits, shared as part of the 'Channel' specification. +- The node number concatenated with the packet number is used as the NONCE. This nonce will be stored in flash in the device and should essentially never repeat. If the user makes a new 'Channel' (i.e. picking a new random 256 bit key), the packet number will start at zero. +- The packet number is sent in cleartext with each packet. The node number can be derived from the "from" field of each packet. (Cleartext is acceptable because it merely provides IV for each encryption run) +- Each 16 byte BLOCK for a packet has an incrementing COUNTER. COUNTER starts at zero for the first block of each packet. +- The IV for each block is constructed by concatenating the NONCE as the upper 96 bits of the IV and the COUNTER as the bottom 32 bits. Since our packets are small counter portion will really never be higher than 32 (five bits). -Parameters for our CTR implementation: +### Remaining todo -- Our AES key is 128 or 256 bits, shared as part of the 'Channel' specification. -- Each SubPacket will be sent as a series of 16 byte BLOCKS. -- The node number concatenated with the packet number is used as the NONCE. This counter will be stored in flash in the device and should essentially never repeat. If the user makes a new 'Channel' (i.e. picking a new random 256 bit key), the packet number will start at zero. The packet number is sent - in cleartext with each packet. The node number can be derived from the "from" field of each packet. -- Each BLOCK for a packet has an incrementing COUNTER. COUNTER starts at zero for the first block of each packet. -- The IV for each block is constructed by concatenating the NONCE as the upper 96 bits of the IV and the COUNTER as the bottom 32 bits. Note: since our packets are small counter will really never be higher than 32 (five bits). +- Have the app change the crypto key when the user generates a new channel -``` -You can encrypt separate messages by dividing the nonce_counter buffer in two areas: the first one used for a per-message nonce, handled by yourself, and the second one updated by this function internally. -For example, you might reserve the first 12 bytes for the per-message nonce, and the last 4 bytes for internal use. In that case, before calling this function on a new message you need to set the first 12 bytes of nonce_counter to your chosen nonce value, the last 4 to 0, and nc_off to 0 (which will cause stream_block to be ignored). That way, you can encrypt at most 2**96 messages of up to 2**32 blocks each with the same key. +## Comments from reviewer #1 -The per-message nonce (or information sufficient to reconstruct it) needs to be communicated with the ciphertext and must be unique. The recommended way to ensure uniqueness is to use a message counter. An alternative is to generate random nonces, but this limits the number of messages that can be securely encrypted: for example, with 96-bit random nonces, you should not encrypt more than 2**32 messages with the same key. +This reviewer is a cryptography professional, but would like to remain anonymous. We thank them for their comments ;-): -Note that for both stategies, sizes are measured in blocks and that an AES block is 16 bytes. -``` +I'm assuming that meshtastic is being used to hike in places where someone capable is trying to break it - like you were going to walk around DefCon using these. I spent about an hour reviewing the encryption, and have the following notes: -## Remaining todo +* The write-up isn't quite as clear as the code. +* The code is using AES-CTR mode correctly to ensure confidentiality. +* The comment for initNonce really covers the necessary information. +* I think the bigger encryption question is "what does the encryption need to do"? As it stands, an attacker who has yet to capture any of the devices cannot reasonably capture text or location data. An attacker who captures any device in the channel/mesh can read everything going to that device, everything stored on that device, and any other communication within the channel that they captured in encrypted form. If that capability basically matches your expectations, it is suitable for whatever adventures this was intended for, then, based on information publicly available or widely disclosed, the encryption is good. If those properties are distressing (like, device history is deliberately limited and you don't want a device captured today to endanger the information sent over the channel yesterday) we could talk about ways to achieve that (most likely synchronizing time and replacing the key with its own SHA256 every X hours, and ensuring the old key is not retained unnecessarily). +* Two other things to keep in mind are that AES-CTR does not itself provide authenticity (e.g. an attacker can flip bits in replaying data and scramble the resulting plaintext), and that the current scheme gives some hints about transmission in the size. So, if you worry about an adversary deliberately messing-up messages or knowing the length of a text message, it looks like those might be possible. -- Have the app change the crypto key when the user generates a new channel +I'm guessing that the network behaves somewhat like a store-and-forward network - or, at least, that the goal is to avoid establishing a two-way connection to transmit data. I'm afraid I haven't worked with mesh networks much, but remember studying them briefly in school about ten years ago. \ No newline at end of file diff --git a/docs/software/pinetab.md b/docs/software/pinetab.md index a3ae55c37a..46d934a57f 100644 --- a/docs/software/pinetab.md +++ b/docs/software/pinetab.md @@ -17,6 +17,9 @@ Or if **absolutely** necessary could bitbang: https://www.cnx-software.com/2018/ ## Task list * Port meshtastic to build (under platformio) for a poxix target. spec: no screen, no gpios, sim network interface, posix threads, posix semaphores & queues, IO to the console only +Use ARM linux: https://platformio.org/platforms/linux_arm +And linux native: https://platformio.org/platforms/native + * Test cs341 driver - just test reading/writing a register and detecting interrupts, confirm can see rf95 * Make a radiolib spi module that targets the cs341 (and builds on linux) * use new radiolib module to hook pinebook lora to meshtastic, confirm mesh discovery works