Zigbee Install Code

1 Introduction

Link keys are used to encrypt/decrypt the communication between each two devices. The network security depends on the robustness of the link keys. Default global preconfigured link key Zigbee 09 is generally used in home automation applications. The problem is that the same link key is used for all the nodes, and this is a security leak. For maximizing security, Zigbee 3.0 provides install code out of band process to create preconfigured link keys that are unique between the trust center and each joining device.

2 Install code

An installation code or install code in the context of Zigbee 3.0 devices is a security mechanism designed to protect the network during the initial setup phase. This 16-byte random value, generated during manufacturing, is used to create a preconfigured link key through the use of an AES-MMO (Matyas-Meyer-Oseas) hash function. The preconfigured link key serves as the foundation for encrypting the network key, enhancing the security of device communication within the Zigbee network.
To facilitate a secure and out-of-band method of transferring this code, it is mostly printed on the device itself or provided via a barcode or QR code.
The support for installation codes is a mandatory requirement for all Zigbee 3.0 devices, underlining the importance of security in Zigbee network.

Joining network process using install code
Conectivity InstallCode.png

After joining successfully the network, Zigbee requires that the device request a new link key from the Trust Center.
Note that for Smart Energy, this step is done with a specific process known as CBKE (Certificate-Based Key Establishment).

3 Trust center (ZC) install code process

The trust center should decide whether a joining node must use the default link key or an install code link key depending on the value of bdbJoinUsesInstallCodeKey. If bdbJoinUsesInstallCodeKey is FALSE, the Trust Center permits a node to join its network without having a corresponding install code link key. If bdbJoinUsesInstallCodeKey is TRUE, the trust center only permits a node to join its network if a corresponding install code link key associated with the node has been preinstalled before the node joins. The trust center must add an entry into its link key table based on joining device EUI64 address.
To improve Zigbee network security, it is better to form Zigbee network with a NULL preconfigured link key. (const uint8_t sec_key_null [ZB_SEC_KEYSIZE] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};)

As a result, only devices for which an entry was added to TC link key table could join the network.

/* Attempt to join a Zigbee network */
ZbStartupConfigGetProDefaults(&config);

/* Set the centralized network */
APP_DBG("Network config : APP_STARTUP_CENTRALIZED_COORDINATOR");
config.startupControl = ZbStartTypeForm;

/* Using the NULL preconfigured Link Key */
memcpy(config.security.preconfiguredLinkKey, sec_key_null, ZB_SEC_KEYSIZE);

config.channelList.count = 1;
config.channelList.list[0].page = 0;
config.channelList.list[0].channelMask = 1 << CHANNEL; /*Channel in use */

/* Using ZbStartupWait (blocking) */
status = ZbStartupWait(zigbee_app_info.zb, &config);

Enable install code:

uint32_t tcPolicy = 0;
ZbApsGet(zigbee_app_info.zb, ZB_APS_IB_ID_TRUST_CENTER_POLICY, &tcPolicy, sizeof(tcPolicy));
tcPolicy |= (ZB_APSME_POLICY_IC_SUPPORTED | ZB_APSME_POLICY_TCLK_UPDATE_REQUIRED | ZB_APSME_POLICY_TC_POLICY_CHANGE);
ZbApsSet(zigbee_app_info.zb, ZB_APS_IB_ID_TRUST_CENTER_POLICY, &tcPolicy, sizeof(tcPolicy));

Add dedicated preconfigured link key for joining device with EUI64 address ieeeAddr:

struct ZbApsmeAddKeyReqT addKeyReq;
struct ZbApsmeAddKeyConfT addKeyConf;
memset(&addKeyReq, 0, sizeof(addKeyReq));

addKeyReq.keyType = ZB_SEC_KEYTYPE_TC_LINK;
addKeyReq.keySeqNumber = 0;
addKeyReq.partnerAddr = ieeeAddr;

memcpy(addKeyReq.key, XXX_LinkKey, ZB_SEC_KEYSIZE);
ZbApsmeAddKeyReq(zigbee_app_info.zb, &addKeyReq, &addKeyConf);
Trust Center Install Code installation
Conectivity InstallCodeTrustCenter.png

4 Joining device install code process

Configure joining device with the same preconfigured link key:

/* Attempt to join a zigbee network */
ZbStartupConfigGetProDefaults(&config);

/* Set the centralized network */
APP_DBG("Network config : APP_STARTUP_CENTRALIZED_ROUTER");
config.startupControl = ZbStartTypeJoin;

/* Using the same preconfigured link key as the one configured on trust center */
memcpy(config.security.preconfiguredLinkKey, XXX_LinkKey, ZB_SEC_KEYSIZE);
config.channelList.count = 1;
config.channelList.list[0].page = 0;
config.channelList.list[0].channelMask = 1 << CHANNEL; /*Channel in use */

/* Using ZbStartupWait (blocking) */
status = ZbStartupWait(zigbee_app_info.zb, &config);
Node install code steps
Connectivity InstallCodeNode.png