Other Parts Discussed in Thread: Z-STACK
Hi,
is there an implementation of the Device specific link key joining process which comes with the 3.0 version for the 1.2.2 HA Stack?
Regards,
Philipp
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Install codes are specific to the Zigbee 3.0 Specification: www.ti.com/.../swra615.pdf
I would doubt that there is enough flash memory to even implement a custom DSLK process. You could alternatively hard-code the ZC NV while programming and perform a secure rejoin, this wouldn't be on the CC2630 as it can only operate as a ZED. On a similar topic would be white/blacklisting: http://wiki.tiprocessors.com/index.php/Black_list_implementation
Regards,
Ryan
Part Number: CC2630
Hi,
is it possible to read/write the TrustCenterLinkKey from the Application using zclport_readNV/zclport_writeNV?
Regards,
Philipp
Correct me if I'm wrong but as of my understanding the difference between GLK and DSLK is which key is used for the decryption of the Transport Key(NWK) command. The GLK is saved in the flash of the CC2630 at ZCD_NV_TCLK_TABLE_START. So if I could get the DSLK which i calculated from the Installation Code on another chip over SPI to the CC2630 and overwrite the GLK which is the default TCLK with it I would be able to decrypt the NWK key which is used for all communication after the joining?
Would this be enough for complete DSLK and is this possible?
Regards,
Philipp
Read works but isn't returning anything. The variable is still full of 0. When i try a write I get the return value NV_ITEM_UNINIT. Does that mean I need to do an init on the Address?
Regards,
Philipp
I found the Zstackapi functions for setting the TCLK and would now like to use them because it's the cleaner solution. While i can erase and read the TCLK for my IEEE Adress i cant write my own generated one. At the first read i received the GLK which is correct then I erased it wrote my own and read it. The response was all zeros which means the write was not successful. But all function calls return success. I'm calling these function during the zstack initialization before the DevStartReq. I atteched a screenshot of the watch with my write Request(pReq) and the read response (getRsp). Do you know a reason why write wouldnt work in this case?
Yes this is working correctly because at first the GLK was readable and after remove only 0x00.
static void TempSensor_initializeZStack(void) { const unsigned char * ieeeFlashAddr = (void *) 0x500012F0; uint8_t newTCLinkKey[SEC_KEY_LEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,\ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 }; zstack_secApsLinkKeyRemoveReq_t rReq = {0}; rReq.tcLinkKey = true; memcpy(&(rReq.ieeeAddr),ieeeFlashAddr,8); zstack_ZStatusValues ret = Zstackapi_secApsLinkKeyRemoveReq(ztsEntity, &rReq); zstack_secApsLinkKeySetReq_t pReq = {0}; pReq.tcLinkKey = true; memcpy(&(pReq.ieeeAddr),ieeeFlashAddr,8); memcpy(&(pReq.key), &(newTCLinkKey), SEC_KEY_LEN); ret = Zstackapi_secApsLinkKeySetReq(ztsEntity, &pReq); zstack_secApsLinkKeyGetReq_t getReq = {0}; getReq.tcLinkKey = true; memcpy(&(getReq.ieeeAddr),ieeeFlashAddr,8); zstack_secApsLinkKeyGetRsp_t getRsp; ret = Zstackapi_secApsLinkKeyGetReq(ztsEntity, &getReq, &getRsp); // Initialize the ZStack Thread bool startDev = true; // default to start the ZStack thread // Setup the endpoints TempSensor_registerEndpoints(); // Setup indications from ZStack TempSensor_setupZStackIndications(); if(startDev) { zstack_devStartReq_t startReq = {0}; // Start the ZStack Thread startReq.startDelay = 0; (void)Zstackapi_DevStartReq(ztsEntity, &startReq); } // Register the ZCL General Cluster Library callback functions zclGeneral_RegisterCmdCallbacks(MSTI_EP, &cmdCallbacks); // Register the application's attribute list zcl_registerAttrList(MSTI_EP, MSTI_MAX_ATTRIBUTES, ztsAttrs);
I tried this at first but reading for IEEE address of 0xFFFFFFFFFFFFFFFF only returned a random key while the read for my address returned the GLK which i wanted to overwrite, so this seemed to be the correct way to do it.
I don't get the question because I use this function to set the key, or what do you mean?
Regards,
Philipp
It is necessary to also make some fixes in file zstacktask.c
Function processSecApsLinkKeyGetReq Change verification of result to true instead of 0
-- if ( osal_memcmp( pPtr->pReq->ieeeAddr, tcLinkKey.extAddr, Z_EXTADDR_LEN ) == 0)
++ if ( osal_memcmp( pPtr->pReq->ieeeAddr, tcLinkKey.extAddr, Z_EXTADDR_LEN ) == true )
Function processSecApsLinkKeySetReq
Change verifications of result to true instead of 0 and remove verification of y > 0 to allow writing the first entry
-- if ( osal_memcmp( pPtr->pReq->ieeeAddr, tcLinkKey.extAddr, Z_EXTADDR_LEN ) == 0)
++ if ( osal_memcmp( pPtr->pReq->ieeeAddr, tcLinkKey.extAddr, Z_EXTADDR_LEN ) == true )
-- else if ( (y == 0) && (osal_memcmp( pPtr->pReq->ieeeAddr, dummyKey, Z_EXTADDR_LEN ) == 0) )
++ else if ( (y == 0) && (osal_memcmp( pPtr->pReq->ieeeAddr, dummyKey, Z_EXTADDR_LEN ) == true) )
-- if ( y > 0 )
++
Function processSecApsLinkKeyRemoveReq Change verification of result to true instead of 0
-- if ( osal_memcmp( pPtr->pReq->ieeeAddr, tcLinkKey.extAddr, Z_EXTADDR_LEN ) == 0)
++ if ( osal_memcmp( pPtr->pReq->ieeeAddr, tcLinkKey.extAddr, Z_EXTADDR_LEN ) == true )
Hi,
I implemented the workaround as you suggested but the results aren't as expected. The code is the same as in my previously posted snippet. Writing the key returns a status of 0x09 and when i try to read it to make sure it was correctly written the returned value is not the key that i wrote. I then tried to just read the key after a erase of the flash memory. This should have returned the DEFAULT_TC_LINK_KEY as defined in nwk_globals.h but returned with a key not matching anything i have seen (see picture). How should the API behave after this workaround?
Regards,
Philipp
Hi Philipp,
The issue with your code is that you are looking to remove get, set and remove the key with ieeeFlashAddr equal to (
void
*) 0x500012F0. TCLK is stored in ZCD_NV_TCLK_TABLE_START NV item with IEEE address value of 0xFFFFFFFFFFFFFFFF in APSME_TCLinkKeyInit(), this is in ZDSecMgr.c, so you need that value to initially manipulate this element with the get, set or remove API's, then the API's will store your new key with IEEE value of 0x0000000000000000. I made some changes to your code to make it work with the provided API's. You still need the fixes provided by Dalila.
Use the next code to test the API's:
uint8_t ieeeFlashAddr[Z_EXTADDR_LEN]; uint8_t newTCLinkKey[SEC_KEY_LEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,\ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 }; zstack_secApsLinkKeyGetReq_t getReq = {0}; zstack_secApsLinkKeyGetRsp_t getRsp; zstack_secApsLinkKeyRemoveReq_t rReq = {0}; zstack_secApsLinkKeySetReq_t pReq = {0}; zstack_ZStatusValues ret; memset(ieeeFlashAddr, 0xFF, Z_EXTADDR_LEN); getReq.tcLinkKey = true; memcpy(&(getReq.ieeeAddr),ieeeFlashAddr,Z_EXTADDR_LEN); ret = Zstackapi_secApsLinkKeyGetReq(ztsEntity, &getReq, &getRsp); rReq.tcLinkKey = true; memcpy(&(rReq.ieeeAddr),ieeeFlashAddr,Z_EXTADDR_LEN); ret = Zstackapi_secApsLinkKeyRemoveReq(ztsEntity, &rReq); memset(ieeeFlashAddr, 0x00, Z_EXTADDR_LEN); pReq.tcLinkKey = true; memcpy(&(pReq.ieeeAddr),ieeeFlashAddr,Z_EXTADDR_LEN); memcpy(&(pReq.key), &(newTCLinkKey), SEC_KEY_LEN); ret = Zstackapi_secApsLinkKeySetReq(ztsEntity, &pReq); getReq.tcLinkKey = true; memcpy(&(getReq.ieeeAddr),ieeeFlashAddr,Z_EXTADDR_LEN); ret = Zstackapi_secApsLinkKeyGetReq(ztsEntity, &getReq, &getRsp);
So the API's work as expected you just need to take care of the IEEE you are using to request the TCLK.
Regards,
Hi Jose,
Thanks these changes from you work. Though the Problem I'm facing now is that while I'm able to write the key, the joining of a Network which is encrypting the NWK key with the same TCLK that I wrote to the memory using this API doesn't work. The sniffer shows that a NKW key is transmitted but the z-stack seems like it is not able to decrypt. It sends out a few data requests but stops after a few seconds indicating that in ran into an exception. Besides that it never sends a Device Announce Broadcast. I thought about it like it is defined in Z-Stack 3 Dev Guide Chapter 10.5.2. The Coordinator is encrypting with a key derived from an installation code and the joining device has the same key now as the TCLK. The same concept as normal but with a custom key and not the GLK. After the NWK key exchange the communication should be entirely encrypted with it but it doesn't seem I ever get there. Is there something missing in my concept?
Regards,
Philipp
Hi Ryan,
I converted the File, once with forced Ubiqua DC format and once conform to original Daintree specification.
Regards,
Philipp
The Device is a Telegesis ETRX3USB+8M with a Firmware based on the stack version EmberZNet 5.4.0.
From the sniffer log is clear that the Zigbee coordinator is sending the transport key encrypted with the default TCLK 5A:69:67:42:65:65:41:6C:6C:69:61:6E:63:65:30:39 (look at packet 21). Since you have changed the default TCLK of your End Device to 10:0F:0E:0D:0C:0B:0A:09:08:07:06:05:04:03:02:01 this device is not able to decrypt the transport key frame and the association process cannot be completed. You need to change the default TCLK of coordinator as well.
My bad I sent the wrong logs. These are the ones with the NWK key correctly encrypted. We used the following key in the code:
uint8_t newTCLinkKey[SEC_KEY_LEN] = { 0x64, 0xE9, 0x12, 0x9D, 0xE2, 0x7C, 0xE3, 0x85,\
0x8E, 0x4C, 0xE1, 0x23, 0xF9, 0x8C, 0x72, 0x86 };
And the same can be seen as encryption for the NWK key in the logs.
I'm not able to decrypt the trasport key frame on packet 56 in the log with this TCLK. Can you double check the value of the key for coordinator.
Hi Ryan,
I tested this again and faced the same problem. I'm able to join the network with another device, but not using the aforementioned setup. I attached a screenshot from the sniffer log with the decrypted NWK-Key package. I'm not sure why you are not possible to decrypt the packet with the key I sent.
This is the current code I have for setting the TCLK:
uint8_t ieeeFlashAddr[Z_EXTADDR_LEN];
uint8_t newTCLinkKey[SEC_KEY_LEN] = { 0x64, 0xE9, 0x12, 0x9D, 0xE2, 0x7C, 0xE3, 0x85,\
0x8E, 0x4C, 0xE1, 0x23, 0xF9, 0x8C, 0x72, 0x86 };
zstack_secApsLinkKeyGetReq_t getReq = {0};
zstack_secApsLinkKeyGetRsp_t getRsp;
zstack_secApsLinkKeyRemoveReq_t rReq = {0};
zstack_secApsLinkKeySetReq_t pReq = {0};
zstack_ZStatusValues ret;
memset(ieeeFlashAddr, 0xFF, Z_EXTADDR_LEN);
getReq.tcLinkKey = true;
memcpy(&(getReq.ieeeAddr),ieeeFlashAddr,Z_EXTADDR_LEN);
ret = Zstackapi_secApsLinkKeyGetReq(ztsEntity,
&getReq,
&getRsp);
rReq.tcLinkKey = true;
memcpy(&(rReq.ieeeAddr),ieeeFlashAddr,Z_EXTADDR_LEN);
ret = Zstackapi_secApsLinkKeyRemoveReq(ztsEntity, &rReq);
memset(ieeeFlashAddr, 0x00, Z_EXTADDR_LEN);
pReq.tcLinkKey = true;
memcpy(&(pReq.ieeeAddr),ieeeFlashAddr,Z_EXTADDR_LEN);
memcpy(&(pReq.key), &(newTCLinkKey), SEC_KEY_LEN);
ret = Zstackapi_secApsLinkKeySetReq(ztsEntity, &pReq);
getReq.tcLinkKey = true;
memcpy(&(getReq.ieeeAddr),ieeeFlashAddr,Z_EXTADDR_LEN);
ret = Zstackapi_secApsLinkKeyGetReq(ztsEntity,
&getReq,
&getRsp);
Could it be that the order of the newTCLinkKey is wrong. Maybe it needs to be in reverse order?
Is there some sort of possibility to detect where the error is happening by debugging the CC2630?
Regards,
Philipp
Can you share the .dcf logs of this new tests? I need the logs in order to help you.
The logs show the same results as the ones I sent you before. Because of that I haven't saved them. If necessary I can redo the tests though.
I did the tests again and those are the results. Is the format correct for you?
Hi Philipp,
I just noticed that there is a typo in the code that sets the key:
uint8_t ieeeFlashAddr[Z_EXTADDR_LEN]; uint8_t newTCLinkKey[SEC_KEY_LEN] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,\ 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10 }; zstack_secApsLinkKeyGetReq_t getReq = {0}; zstack_secApsLinkKeyGetRsp_t getRsp; zstack_secApsLinkKeyRemoveReq_t rReq = {0}; zstack_secApsLinkKeySetReq_t pReq = {0}; zstack_ZStatusValues ret; memset(ieeeFlashAddr, 0xFF, Z_EXTADDR_LEN); getReq.tcLinkKey = true; memcpy(&(getReq.ieeeAddr),ieeeFlashAddr,Z_EXTADDR_LEN); ret = Zstackapi_secApsLinkKeyGetReq(ztsEntity, &getReq, &getRsp); rReq.tcLinkKey = true; memcpy(&(rReq.ieeeAddr),ieeeFlashAddr,Z_EXTADDR_LEN); ret = Zstackapi_secApsLinkKeyRemoveReq(ztsEntity, &rReq); memset(ieeeFlashAddr, 0xFF, Z_EXTADDR_LEN); // Changed memset from 0x00 to 0xFF pReq.tcLinkKey = true; memcpy(&(pReq.ieeeAddr),ieeeFlashAddr,Z_EXTADDR_LEN); memcpy(&(pReq.key), &(newTCLinkKey), SEC_KEY_LEN); ret = Zstackapi_secApsLinkKeySetReq(ztsEntity, &pReq); getReq.tcLinkKey = true; memcpy(&(getReq.ieeeAddr),ieeeFlashAddr,Z_EXTADDR_LEN); ret = Zstackapi_secApsLinkKeyGetReq(ztsEntity, &getReq, &getRsp);
Ieee address needs to be 0xFFFFFFFFFFFFFFFF for Zstackapi_secApsLinkKeySetReq(), I just noticed this typo, sorry about that.
Now you will be able to decrypt the transport key an see something like this.
Hi Jose,
when I try to write to 0xFF I get a zstack_ZStatusValues of 0x09 returned. This value is not defined in the Enum, thus I'm not sure what this error means.
Regards,
Philipp