Replies: 2 comments 6 replies
-
The problem that you are observing is most certainly due to the wrong set of keys being used. The FUOTA server implementation that you reference is using an hard coded The issue is that To obtain the When using LoRaWAN 1.1.x versions of the protocol the As As you can see every end-device will have a different The referenced FUOTA server example as is will only work for a single device in the Multicast group as each end-device will have a different I don't know how to create a multicast channel under TTN network server however, I assume that you need to provide the following elements to create one:
In order to obtain the right
I quickly wrote a Python script which generates the different keys for 1.0.x and 1.1.x version of the LoRaWAN specification.
The Python script is as follows. You may need to install following python packages prior to be able to run the script. $ pip install pycryptodome pycryptodomex semantic_version Script: Click to expand!
from Crypto.Hash import CMAC
from Crypto.Cipher import AES
import semantic_version
def decrypt(buffer: bytearray, root_key: bytes) -> bytearray:
cipher = AES.new(root_key, AES.MODE_ECB)
return cipher.decrypt(buffer)
def lorawan_derive_key(buffer: bytearray, root_key: bytes) -> bytearray:
cipher = AES.new(root_key, AES.MODE_ECB)
return cipher.encrypt(buffer)
def lorawan_derive_mc_root_key(lorawan_version: semantic_version.Version, root_key: str) -> str:
key_in = bytes.fromhex(root_key)
comp_base = bytearray(16)
if lorawan_version.minor == 1:
comp_base[0] = 0x20
key_out = lorawan_derive_key(comp_base, key_in)
return "".join("{:02X}".format(x) for x in key_out)
def lorawan_derive_mc_ke_key(root_key: str) -> str:
key_in = bytes.fromhex(root_key)
comp_base = bytearray(16)
key_out = lorawan_derive_key(comp_base, key_in)
return "".join("{:02X}".format(x) for x in key_out)
def lorawan_derive_mc_session_key_pair(mc_addr: int, root_key: str):
key_in = bytes.fromhex(root_key)
comp_base_app_s = bytearray(16)
comp_base_nwk_s = bytearray(16)
comp_base_app_s[0] = 0x01
comp_base_app_s[1] = mc_addr & 0xFF
comp_base_app_s[2] = (mc_addr >> 8) & 0xFF
comp_base_app_s[3] = (mc_addr >> 16) & 0xFF
comp_base_app_s[4] = (mc_addr >> 24) & 0xFF
comp_base_nwk_s[0] = 0x02
comp_base_nwk_s[1] = mc_addr & 0xFF
comp_base_nwk_s[2] = (mc_addr >> 8) & 0xFF
comp_base_nwk_s[3] = (mc_addr >> 16) & 0xFF
comp_base_nwk_s[4] = (mc_addr >> 24) & 0xFF
app_s_key = lorawan_derive_key(comp_base_app_s, key_in)
nwk_s_key = lorawan_derive_key(comp_base_nwk_s, key_in)
return "".join("{:02X}".format(x) for x in app_s_key), "".join("{:02X}".format(x) for x in nwk_s_key)
if __name__ == "__main__":
lorawan_version = semantic_version.Version("1.0.4")
# Inputs
app_key: str = "000102030405060708090A0B0C0D0E0F"
mc_key = "0102030405060708090A0B0C0D0E0F10"
mc_addr = 0x1FFFFFF
# Outputs
mc_root_key = lorawan_derive_mc_root_key(lorawan_version, app_key)
mc_ke_key = lorawan_derive_mc_ke_key(mc_root_key)
mc_key_encrypted = "".join("{:02X}".format(x) for x in decrypt(bytes.fromhex(mc_key), bytes.fromhex(mc_ke_key)))
mc_app_s_key, mc_nwk_s_key = lorawan_derive_mc_session_key_pair(mc_addr, mc_key)
print("LoRaWAN " + str(lorawan_version))
print("AppKey : " + app_key)
print(f"McAddr : 0x{mc_addr:08X}")
print("McRootKey : " + mc_root_key)
print("McKeKey : " + mc_ke_key)
print("McKey : " + mc_key)
print("McKeyEncrypted : " + mc_key_encrypted)
print("McAppSKey : " + mc_app_s_key)
print("McNwkSKey : " + mc_nwk_s_key)
print()
lorawan_version = semantic_version.Version("1.1.0")
# Inputs
app_key: str = "000102030405060708090A0B0C0D0E0F"
mc_key = "0102030405060708090A0B0C0D0E0F10"
mc_addr = 0x1FFFFFF
# Outputs
mc_root_key = lorawan_derive_mc_root_key(lorawan_version, app_key)
mc_ke_key = lorawan_derive_mc_ke_key(mc_root_key)
mc_key_encrypted = "".join("{:02X}".format(x) for x in decrypt(bytes.fromhex(mc_key), bytes.fromhex(mc_ke_key)))
mc_app_s_key, mc_nwk_s_key = lorawan_derive_mc_session_key_pair(mc_addr, mc_key)
print("LoRaWAN " + str(lorawan_version))
print("AppKey : " + app_key)
print(f"McAddr : 0x{mc_addr:08X}")
print("McRootKey : " + mc_root_key)
print("McKeKey : " + mc_ke_key)
print("McKey : " + mc_key)
print("McKeyEncrypted : " + mc_key_encrypted)
print("McAppSKey : " + mc_app_s_key)
print("McNwkSKey : " + mc_nwk_s_key) Note: I have successfully tested the operation with a 1.0.x and 1.1.x LoRaWAN end-device using a similar FUOTA application server on top of a ChirpStack network server. In order to have a fully operational FUOTA server some more work is required as the provided example only supports a single end-device with a specific The topics to work on that I currently see are:
|
Beta Was this translation helpful? Give feedback.
-
@mluis1 big thanks for your detailed reply! It is still not working with my setup. I'll try to explain it here in detail:
On the things stack I added a normal device:and a multicast device:On the node I edited the se-identity file as follows:Click to expand!
#define LORAWAN_DEVICE_EUI { 0x88 , 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88 }
#define LORAWAN_JOIN_EUI { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }
#define SECURE_ELEMENT_PIN { 0x00, 0x00, 0x00, 0x00 }
#define STATIC_DEVICE_ADDRESS 0
#define LORAWAN_DEVICE_ADDRESS ( uint32_t )0x11111111
#define SOFT_SE_KEY_LIST \
{ \
{ \
/*! \
* Application root key \
* WARNING: FOR 1.0.x DEVICES IT IS THE \ref LORAWAN_GEN_APP_KEY \
*/ \
.KeyID = APP_KEY, \
.KeyValue = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F }, \
}, \
{ \
/*! \
* Network root key \
* WARNING: FOR 1.0.x DEVICES IT IS THE \ref LORAWAN_APP_KEY \
*/ \
.KeyID = NWK_KEY, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, \
}, \
{ \
/*! \
* Join session integrity key (Dynamically updated) \
* WARNING: NOT USED FOR 1.0.x DEVICES \
*/ \
.KeyID = J_S_INT_KEY, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Join session encryption key (Dynamically updated) \
* WARNING: NOT USED FOR 1.0.x DEVICES \
*/ \
.KeyID = J_S_ENC_KEY, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Forwarding Network session integrity key \
* WARNING: NWK_S_KEY FOR 1.0.x DEVICES
* 0xff, 0x70, 0x1d, 0x83, 0x68, 0xa4, 0xc6, 0x58, 0x60, 0x48, 0xff, 0xa2, 0x9d, 0x8a, 0xe0, 0x10 \
*/ \
.KeyID = F_NWK_S_INT_KEY, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Serving Network session integrity key \
* WARNING: NOT USED FOR 1.0.x DEVICES. MUST BE THE SAME AS \ref LORAWAN_F_NWK_S_INT_KEY \
*/ \
.KeyID = S_NWK_S_INT_KEY, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, \
}, \
{ \
/*! \
* Network session encryption key \
* WARNING: NOT USED FOR 1.0.x DEVICES. MUST BE THE SAME AS \ref LORAWAN_F_NWK_S_INT_KEY \
*/ \
.KeyID = NWK_S_ENC_KEY, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, \
}, \
{ \
/*! \
* Application session key
* 0xf7, 0xd9, 0x66, 0x7a, 0xcd, 0x8e, 0xb1, 0xdd, 0xe3, 0x80, 0x75, 0x1a, 0x85, 0x93, 0xea, 0xec \
*/ \
.KeyID = APP_S_KEY, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast root key (Dynamically updated) \
*/ \
.KeyID = MC_ROOT_KEY, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast key encryption key (Dynamically updated) \
*/ \
.KeyID = MC_KE_KEY, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #0 root key (Dynamically updated) \
*/ \
.KeyID = MC_KEY_0, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #0 application session key (Dynamically updated) \
*/ \
.KeyID = MC_APP_S_KEY_0, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #0 network session key (Dynamically updated) \
*/ \
.KeyID = MC_NWK_S_KEY_0, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #1 root key (Dynamically updated) \
*/ \
.KeyID = MC_KEY_1, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #1 application session key (Dynamically updated) \
*/ \
.KeyID = MC_APP_S_KEY_1, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #1 network session key (Dynamically updated) \
*/ \
.KeyID = MC_NWK_S_KEY_1, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #2 root key (Dynamically updated) \
*/ \
.KeyID = MC_KEY_2, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #2 application session key (Dynamically updated) \
*/ \
.KeyID = MC_APP_S_KEY_2, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #2 network session key (Dynamically updated) \
*/ \
.KeyID = MC_NWK_S_KEY_2, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #3 root key (Dynamically updated) \
*/ \
.KeyID = MC_KEY_3, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #3 application session key (Dynamically updated) \
*/ \
.KeyID = MC_APP_S_KEY_3, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* Multicast group #3 network session key (Dynamically updated) \
*/ \
.KeyID = MC_NWK_S_KEY_3, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
{ \
/*! \
* All zeros key. (ClassB usage)(constant) \
*/ \
.KeyID = SLOT_RAND_ZERO_KEY, \
.KeyValue = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \
0x00 }, \
}, \
}, Then I start the process and in the Log of the node you can see, that the setup of the multicast session and framgneted data block transport happens but as soon as the node should receive multicast fragments nothing happens:Click to expand!
On the application server you can see that the data are sent:like also on the gateway-server:but the node receives nothing. Also an added brakepoint at the beginning of : Sorry for how it is edited.. it somehow didn't edit code block wright here.. Do you have an Idea whats happening? It is correct to send the McKeyEncrypted : 582D3B83EAD518707219832B39093DE9 during the multicast setup? In the Log of the node he declares it as the McKey, which is a little bit confusing.
|
Beta Was this translation helpful? Give feedback.
-
Hi,
At the moment I'm trying to set up a FUOTA session at my labor enviroment at the university,
I'm using TheThingsStack network server and this FUOTA server implementation:
https://github.com/elsalahy/test-fuota-server
For the node the LoRaMAC-node FUOTA example with the mac version 1.1.0 is used.
Class C, EU863-870
All the published example for the ClockSync, Multicast and fragmented data block transport are using the mac version 1.0.3.
The clock sync and fragmented data block trasnport works fine but the multicast session doesn't work because the node falls in a mic_fail error when receiving a multicast downlink. I think its because of wrong keys provided. So it receives the downlink and the MC device address is correct but the calculation of the mic fails.
Could anyone give me a example key set-up for the se-identity.h file for a multicast session and how the multicast device on the network server has to be configured?
Or maybe list some keypoint what keys I have to set up for the lorawan mac version 1.1.0 on the node and on the server for a multicast session?
Best regards Corsin Obrist
Beta Was this translation helpful? Give feedback.
All reactions