Device key helper library

I made a library that can automatically save and restore Particle device keys. No more fast blinking cyan (possibly with red or orange blinks) and having to particle keys doctor with a laptop and USB (hopefully)!

The library and documentation are here:

The library needs a place to store the backup keys. The amount of space you need varies depending on the type of device:

  • For Wi-Fi devices (Photon, P1): 1608 bytes
  • For cellular devices (Electron, E series): 328 bytes

There’s an option to use the EEPROM emulation. This isn’t the best choice as it’s also in the STM32 flash and could be corrupted, and also especially for Wi-Fi devices, most of it would be used up by the saved keys.

Here’s an example of saving the keys to offset 100 in the EEPROM, however:

#include "Particle.h"

#include "DeviceKeyHelperRK.h"

SYSTEM_MODE(SEMI_AUTOMATIC);

SerialLogHandler logHandler;

// Save and restore the device keys in EEPROM at offset 100 in the EEPROM
DeviceKeyHelperEEPROM deviceKeyHelper(100);

void setup() {

    // You must call this from setup to start monitoring for keys errors
    deviceKeyHelper.startMonitor();

    // You either need to use SYSTEM_THREAD(ENABLED) or SYSTEM_MODE(SEMI_AUTOMATIC) because
    // in thread disabled AUTOMATIC mode, setup() isn't called until cloud connected and the
    // code to monitor the connection would never be started via startMonitor().
    Particle.connect();
}

void loop() {

}

Other storage medium include:

SpiffsParticleRK

The SpiffsParticleRK library supports SPI-connected NOR flash chips. These are typically tiny 8-SOIC surface mount chips, intended to be included on your own circuit board. There are also breadboard adapters that are available.

The chips are really inexpensive, less than US$0.50 in single quantities for a 1 Mbyte flash. They’re available in sizes up to 16 Mbyte.

SPI flash is less expensive than SD cards, and do not need an adapter or card slot. Of course they’re not removable.

The underlying SpiFlashRK library library supports SPI NOR flash from

P1 using flashee-eeprom

If you are already using flashee-eeprom to store files in the P1 external flash, you can easily add support for saving keys in it as well.

// Check the device public and private keys against the keys stored in the file "keys"
DeviceKeyHelperFlasheeFile deviceKeyHelper("keys");

SdFat

If you are using SdFat, with an SD card, it’s as easy as:

#include "Particle.h"

// Make sure you include SdFat.h before DeviceKeyHelperRK.h, otherwise you won't have support for SdFat
#include "SdFat.h"

#include "DeviceKeyHelperRK.h"

SYSTEM_MODE(SEMI_AUTOMATIC);

SerialLogHandler logHandler;

// Primary SPI with DMA
// SCK => A3, MISO => A4, MOSI => A5, SS => A2 (default)
SdFat sd;
const uint8_t chipSelect = A2;

// Secondary SPI with DMA
// SCK => D4, MISO => D3, MOSI => D2, SS => D1
// SdFat sd(1);
// const uint8_t chipSelect = D1;

DeviceKeyHelperSdFat deviceKeyHelper("keys");

void setup() {
    Serial.begin();

    if (sd.begin(chipSelect, SPI_HALF_SPEED)) {
        // If the file system was mounted, enable monitoring for keys errors
        deviceKeyHelper.startMonitor();
    }
    else {
        Log.info("failed to initialize SD card");
    }

    // You either need to use SYSTEM_THREAD(ENABLED) or SYSTEM_MODE(SEMI_AUTOMATIC) because
    // in thread disabled AUTOMATIC mode, setup() isn't called until cloud connected and the
    // code to monitor the connection would never be started via startMonitor().
    Particle.connect();
}

void loop() {
}

MB85RC256V I2C FRAM

The MB85RC256V 32 Kbyte ferro-electric non-volatile FRAM is another place you can store your keys.

MB85RC256V fram(Wire, 0);

// Store the device keys starting at address 1000 in the FRAM
DeviceKeyHelperFRAM deviceKeyHelper(fram, 1000);

And your own

You can easily add other storage medium without having to modify the library, too. Just add functions or C++11 lambdas for loading and storing a block of data and the library takes care of everything else.

7 Likes

I’m excited to get a chance to evaluate this as I suspect this is going to be invaluable!

Thanks Rick!

Hi,

I added Device Key helper (as per the simple example) to an app on a Boron 2g/3g (OS 2.01) being deployed in another country.

Log.info returned the message: “bad magic bytes or size magic= …l size= …” .

But then DeviceKey helper saved the keys to EEPROM. Does this mean the saved keys are truncated? The Boron is connecting as before and I’m not seeing any more Log.info messages on startup. I’m assuming the copied keys are passing the test?

The Boron is configured as:

"SYSTEM_THREAD(ENABLED);
SYSTEM_MODE(SEMI_AUTOMATIC);

DeviceKeyHelperEEPROM deviceKeyHelper(100);

STARTUP(
System.enableFeature(FEATURE_RETAINED_MEMORY);"

That just means the EEPROM had not been previously set up as device key storage, so the previous contents were replaced. This is normal the first time you run the software to save the current device keys.

1 Like

Thanks much appreciated. Another super helpful library. It would be awesome to have a feather with a hardware watchdog and two FRAM chips. A small FRAM for the keys and a larger one for a publish queue. Basically some of your previous feather boards mashed together.