Best practices for adding/storing LoraWAN creds on Arduinos


(Pomplesiegel) #1

Hello Everyone,

I have gotten my Adafruit Feather M0 900Mhz LORA microcontroller working + OTAA activating + uploading data to TTN and everything is going swimmingly. However there is one issue on my mind:

Currently my APPEUI[8], DEVEUI[8] and APPKEY[16] are hard-coded source code which is then compiled and flashed into the Feather. This works fine for one unit, but if I had 10 or 50 for an internal product or experiment, each unit would have a different set of source code because of these changes to a few lines of code.

I realize this is normally the place of EEPROM (or simulated EEPROM) to separate the compiled code from the individualized storage of each microcontroller. However the Feather has no EEPROM, so I would have to add that as well (not a huge deal). But before I go down that road:

What I’m asking is: How are people normally solving this problem on Arduinos of:

  • Easily inserting individual unique EUIs and keys into each microcontroller
  • Storing this information on micros like the Feather
  • Storing these keys in some sort of encrypted format, so someone couldn’t easily retrieve them.

Perhaps I’m missing something!

Thank you so much for the great support of this forum. LoraWAN + TTN is so fun.

Best,
Michael


(Bialy) #2

Hi,

You have several options:

  • emulate eeprom - samd core
  • use internal unique id for some keys - samd core
  • modify linker scripts to separate the area for keys and firmware - samd and avr cores
  • use external specilized chip like ATECC508A

In arduinos (samd or avr core) to protect firmware you should set the flag responsible for security/read protection.

Hope that help :slight_smile:


(Pomplesiegel) #3

Hello @bialy,
Thank you so much for your response! I imagine I will need the flexibility to program these keys into the arduino through a method like modifying the linker scripts.

Do you know how to set that flag for security/read protection within the Arduino environment? Could you provide a link regarding how to accomplish this?

Thanks again!


(Bialy) #4

Small example regarding linker - https://mcuoneclipse.com/2016/11/01/getting-the-memory-range-of-sections-with-gnu-linker-files/

Regarding the security, You will need to check specific processor documentation. For AVR you will need programmer for ARM you can program flags using openocd.

Just to give you some tips, Arduino is for hobby use (IDE on the first place), if you plan to build something more professional you will need to go deeper into the hardware and software.


(alanp) #5

I have not used it myself but the FlashStorage library is for SAMD chips.
https://github.com/cmaglie/FlashStorage


(Pomplesiegel) #6

Thanks @alanp. Yes! Coincidentally I did a proof of concept with this today and think it will work well. The final element is protecting the data.
Only bummer is that even a minor FW update would wipe out the stored keys. Not sure if there’s a way around that…


(Bialy) #7

As I wrote previously, you will need modify linker script and define your own section somewhere in flash.
Try to find examples without world arduino more like eq. gcc linker scripts arm :slight_smile:
for avr - https://www.nongnu.org/avr-libc/user-manual/mem_sections.html


(Pomplesiegel) #8

@bialy, got it. I just meant that in regard to the FlashStorage library.

However, I am now considering ditching this platform altogether and going over to an Arduino Pro Mini + RFM95, and eventually to just the Atmega 328P with the arduino bootloader. Thoughts on this approach?

Thanks again!


(Bialy) #9

If you are new in Lora and micro-controllers is ok as a starting point.

Some disadvantages of Pro Mini based on atmega328:

  • only 32k flash shared with the bootloader. I think you will stick with LMIC.
    You will have no space for official Lorawan stack from semtech.
  • programming EEPROM - you must modify Arduino bootloader, to program without the serial programmer.
  • to burn bootloader you need to purchase the serial programmer
  • to change security flags and others settings you need to purchase the serial programmer
  • no simple and cheap debugging

props:

  • simple core
  • lots of libraries and examples
  • cheap
  • suitable for most personal projects

(Bialy) #10

example how to create section for samd21g18a - search for file *.ld

 /* Memory Spaces Definitions */
MEMORY
{
 rom      (rx)  : ORIGIN = 0x00000000+0x2000, LENGTH = 0x00040000-0x2040
 new entry->> rom-sec  (rx)  : ORIGIN = 0x00040000-0x2040, LENGTH = 0x40
 ram      (rwx) : ORIGIN = 0x20000000, LENGTH = 0x00008000
}
......
/* Section Definitions */
SECTIONS
{
 .....
.text :{...}
.sec-keys : /*custom section*/
    {
        . = ALIGN(4);
        __sec-keys_start__= .;
        KEEP( *(.sec-keys*)) /* keep my data even if not referenced */
        __sec-keys_end__ = .;
    } > rom-sec

Usage of custom section:

__attribute__((__section__(".sec-keys"))) const char textsecret[4] = {30,31,32,33};

(Mikael Falkvidd) #11

If there was a way around that, it would be easy to write a firmware that fetched the key and printed it on serial, resulting in devulging the key which would render the protection useless. So let’s hope there is no way around that.


(Pomplesiegel) #12

Yes, indeed! I’m curious if there is an elegant way to store the key in an encrypted (or at least obfuscated) manner in the flash or EEPROM to prevent someone from accessing it in a manner like this with a custom program. @mfalkvidd Any thoughts?


(Arinze Izukanne) #13

Its is one thing for a person to retrieve the stored bytes from EEPROM and another to determine what the string of bytes mean. I do not assume you want to store the definition of the keys in EEPROM as well. Where keys contain an easily recognizable pattern, you may write bytes into specific locations in EEPROM and have your script read the right locations and reconstruct.

Personally, for projects, using ATMEGA328P or 32u4, where I want to implement the same code on multiple devices, I recently began to store the DEVEUI and APPKEY in EEPROM first, with one sketch, and then a different sketch is loaded into the devices which reads the required keys from the locations on startup.

If you do this, meaning the keys are no longer stored in flash (aka Program Memory), you will need to change lines in the sketch calling “memcpy_P” to call “memcpy” instead. Using LMIC the following lines will be affected.

`void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}`

`void os_getDevKey (u1_t* buf) {  memcpy_P(buf, APPKEY, 16);}`

has to be changed to

`void os_getDevEui (u1_t* buf) { memcpy(buf, DEVEUI, 8);}`

`void os_getDevKey (u1_t* buf) {  memcpy(buf, APPKEY, 16);}`

(Pomplesiegel) #14

@aizukanne, absolutely. However, if the keys were to be stored in the EEPROM (only 1-2kB total) and you were to put them in contiguous arrays, would it not be obvious what they are to a trained observer? Perhaps the whole EEPROM could be seeded with random data first?

I’m just thinking that if someone printed the EEPROM and saw a repetitive value like

0x00
0x00
0x00
0x00

0x25
0x18
(remainder of key)

they might know what they’re looking at :wink:
Thoughts?


(Arinze Izukanne) #15

Possibly, but only if there are specific bytes that are easily recognizable. DEVEUI has 8 bytes while the APPKEY has 16. If you read the first 24 bytes of EEPROM, can you tell if the first 8 are the DEVEUI or the last 8?

However, as I said you can decide not to store the byte sequence as is and for example, interleave the DEVEUI bytes with the APPKEY bytes for example…

APPKEY[16] = {0xA0,0xA1,0xA2,0xA3,0xA4,0xA5,0xA6,0xA7,0xA8,0xA9,0xAA,0xAB,0xAC,0xAD,0xAE,0xAF}
DEVEUI[8] = {0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD7}

In EEPROM store {0xA0,0xA1,0xD7,0xA2,0xA3,0xD6.0xA4,0xA5,0xD5,0xA6,0xA7,0xD4,0xA8,0xA9,0xD3,0xAA,0xAB,0xD2,0xAC,0xAD,0xD1,0xAE,0xAF,0xD0}

That should make it almost impossible to decipher except for someone who knows the cipher.


(Amedee) #16

Security by obscurity:thinking:


(Bialy) #17

If you are using arduino/avr please be familiar with avr fuses - http://www.engbedded.com/fusecalc/
and documentation http://ww1.microchip.com/downloads/en/DeviceDoc/ATmega48A-PA-88A-PA-168A-PA-328-P-DS-DS40002061A.pdf read chapter "28.1 Program And Data Memory Lock Bits"

To prevent from reading your device you will have to set fuses ex. (LB1 and LB2 - to secure flash and eeprom).
A Chip erase using the ISP will clear the lock bits, unless you will disable this feature by fuses.
So using AVR you can secure your device from reading flash and eeprom - this is what you are looking for, I think.

In arm cores you can program fuses from flash program level - great benefit. To prevent from erasing keys use modified linkers script - example is attached above.
You can even use FlashStorage just add attribute which define custom section, after that flashing will not affect on that separated area for keys.


(Pomplesiegel) #18

Absolutely!


(Pomplesiegel) #19

OK! I think this would accomplish what we’re discussing for AVR, as the EEPROM and flash would be erased upon a new firmware flash. I suppose the only advantage is exactly that: each new firmware upload would wipe the EEPROM if it’s protected. Correct?


(Bialy) #20

If you are in development/testing phase you could set fuse EESAVE - Preserve EEPROM memory through the Chip Erase cycle; [EESAVE=0].
When fw is completed in each new device you just need to lock the chip after flashing. If you plan to upgrade flash you can also set EESAVE to preserve content of the eeprom.