Ruuvi Firmware 2.3.0-beta - DFU service closed by default?

As noted by @fejesjoco, current Ruuvi FW 2.2.2 is connectable by default and can be updated by anyone remotely without physical interaction from anyone else. This has been a requested feature for some applications where access to RuuviTags is difficult, for example when tags are installed within walls or floors.

As Ruuvi packages are signed with public key with it’s private pair published, anyone can create packages on RuuvITags - as intended. However this creates a security issue, as it is possible to create intentionally bricking packets.

Ruuvi FW 2.3.0-beta is not connectable by default, and it becomes connectable for 30 seconds after NFC scan.

Please discuss: Which behavior suits your use better? Should the default be non-connectable and become connectable after some action, or connectable and become non-connectable after some action?

For the distributed firmware, making it MORE difficult to upload new firmware would not be beneficial.
“anyone” would need to have the desire to modify the firmware and have proximity to the tag. Even within walls or floors(really?) the tag can be easily destroyed with a drill or hammer or just stolen!

Surely a user concerned about having their tag hijacked or destroyed is going to write their own firmware.

Thinking like that leads to “Internet of Things” becoming “Internet of Sh***” :neutral_face: . Security should come first and foremost, and enabled by default.

1 Like

I mentioned in another topic that I was confused by versioning. It seemed like 2.2.2 uses raw V2 (format 5) but 2.3.0 still uses raw V1 (format 3). Can you confirm which one it is?

In my opinion; non-connectable by default, and temporarily connectable after some action (I’d prefer nfc or button). Reasons:

  • Security (as mentioned earlier)
  • Battery consumption, being connectible consumes a lot of battery as the radio needs to be awake to listen for connection attempts (shorter battery life by default doesn’t give a good first impression either)
  • Non-techy users probably never have a need to connect anyway, just get the data from advertisements (eddystone url or raw with apps)

On the other hand, there could be multiple versions of the firmware released with different defaults, set by precompiler directives perhaps (this approach would also allow, for example, using the same codebase for either rawv1 or rawv2 builds).
Building multiple times with different parameters would be an automatic process for CI builds so no extra work/overhead there. Though my opinion above still stands for what would be best “the default”.

2.x.y should always be V2. I’ll need to check that I didn’t do anything silly with git when I made the change

True, the send-listen-send consumes a lot more power.

Adding v1 to 2.x branch would be really quick to do, I’ll get it done sometime over next week and add some flag to application_config.h for it

This is an interesting idea, I think I’ll implement it in the 3.x branch

IT devices should never be distributed with an insecure configuration - we’ve been bitten by this in the past, from wifi routers to voting machines. Many users will never set a password or change a default one, and flashing a new firmware will surely pose an even higher barrier.

And I would even argue against NFC: It may not-be-as-near-as-you-think with larger and more powerful antennas, and it will be another frustration for some iOS users.

I would go with physical access, like pressing a button: Secure enough for many to most use cases, easy to understand with no uncertainties an no time limit to work against, and no extra hardware or device capabilities required.

Why not having it non-connectable by default and use e.g. serial number as a key to make it connectable for updates? This would be similar than connecting to certain WLAN routers. This would need adding a serial number in the memory of each unit plus print it on the unit itself. Probably too much additional work for manufacturing? Alternatively the FW could be personalized by a serial number for each unit with a special tool for those who need this feature.
I believe this would help maintenance work a lot when updates are needed for units in difficult locations. But in order to save power, listening, if someone is “knocking the door”, should happen only very seldom.

Thank you everyone,

The serial number cannot be entered before the tag is connectable, but requiring it as a key would definitely add to security. It would require some work on the code and probably won’t be implemented in 2.x branch, but maybe somewhere along the line of 3.x.

Nordic Semi has already considered this and they ship each device with a burned-in unique ID. Right now this ID is readable via GATT and NFC. This of course is a bit problematic: If the GATT security key can be read over GATT, it’s not much of a security key. On the other hand, not everyone has a NFC-reader enabled device.

I think the conclusion from discussion is: Tags should be in non-connectable mode until user has taken some action which shows they have physical access to the device. Maybe this will be revisited later on if the tags have built-in logging or some other feature which makes connections more useable for everyday scenarios.

I’ll have the release updated this week and clarify the versioning int the readme while I’m at it.

What is status of this (security) feature?

As of 3.30.0:

  • Tag can be connected to for reading logged data
  • DFU service is disabled by default
  • DFU service becomes enabled for the next connection after NFC scan or button press

We’re also considering adding an unlock code which could be sent over GATT to enable the DFU service, but right now physical access is required to update the app

2 Likes