1. Introduction
The Zigbee Smart Energy (SE) profile is a framework specifically designed for energy management applications. Devices following the SE profile can interoperate in energy management systems, providing utilities and consumers with tools to monitor and optimize energy usage.
Because of the type of data and control within the SE network, application security is a key requirement. The application will use link keys which are optional in the ZigBee and ZigBee Pro stack profiles but are required within a SE network.
In this page, we will detail what is required for SE devices and will give and example of usage.
2. Installation Code
Installation Code or Install Code is one of the requirements used to establish the preconfigured link key of a device in a SE network.
During the manufacturing process, a random Installation Code is created for each of the SE devices. The associated Pre-configured Link Key is derived using the hashing function Matyas-Meyer Oseas (MMO) and programmed in the device.
More information about the Installation Code can be found in the Zigbee Install Code.
Link keys of the devices that need to join the network should be added to the Trust Center using the following API:
/* On Trust Center, add a TC Link Key derived from the given install code */
ZbSecAddDeviceLinkKeyByInstallCode( stZigbeeAppInfo.pstZigbee, dlPartnerExtendedAdress, (uint8_t *)szLinkKeyInstallCode , ZB_SEC_KEYSIZE + 2 );
3. Zigbee Key Establishment (ZKE) cluster
ZKE cluster is a cluster for managing secure communication in ZigBee. It’s used to establish a shared secret key between two devices, which can then be used to encrypt and decrypt messages exchanged between them.
The ZKE cluster uses a combination of asymmetric and symmetric key cryptography to establish and distribute keys. At the end of the process, both nodes will have shared secret key. It is used to encrypt and decrypt messages exchanged between them.
Key agreement scheme is the process of establishing the shared secret key without sending it over the air. It is done between an Initiator, who starts the process, and a Responder.
There are 2 types of key agreement:
- Symmetric Key Key Establishment (SKKE).
- Public Key Key Establishment (PKKE).
PKKE involves the exchange of public keys, which can be static (long-term) or ephemeral (temporary), to mutually authenticate devices and establish a shared secret key for secure communications.
The device's static public key can be transported independently, so relying on an implicit trust, or as part of a implicit certificate signed by a Certificate Authority (CA), which is called Certificate-Based Key Establishment (CBKE).
If using CBKE, static public keys Su and Sv are exchanged and verified using the CA's public key.
In Zigbee Smart Energy, CBKE is a critical component for ensuring that the devices are who they claim to be.
The following Figure illustrates the 5 steps of PKKE process.
General Exchange for PKKE |
---|
4. Certificate-Based Key Establishment (CBKE)
The Certificate-Based Key-Establishment (CBKE) is considered to be a variant of PKKE.
The Certificate-Based Key-Establishment (CBKE) solution uses public-key technology with digital certificates and root keys. Each device has a static public key and a digital certificate that is signed by a Certificate Authority (CA).
Certificates provide a mechanism for cryptographically binding a public key to a device's identity and characteristics.
"The CBKE cluster is allocated automatically at startup when either suite 1, suite 2 or both suites are enabled, and certificates are defined in the ZbStartupCbkeT fields of ZbStartupT."
The Keep Alive cluster is created automatically by the stack when CBKE is used. It is part of the mechanism by which smart energy devices detect loss of communication with the trust center. This loss of communication results in a sequence of retries, network rejoin attempts, and ultimately an attempt to join a new trust center (TCSO).
5. CBKE Application
5.1. Application configuration
In a Normal Scenario the Coordinator act as a Trust Center and CBKE is activated by filling CBKE startup configuration at both sides, End device and the coordinator.
The CBKE startup Configurations are filled in the struct ZbStartupCbkeT of struct ZbStartupT used for startup. Some important fields of ZbStartupCbkeT are defined as follows:
/** CBKE configuration parameters for ZbStartup. This configuration is only
* applicable if the 'suite_mask' is non-zero. */
struct ZbStartupCbkeT {
uint8_t endpoint;
/**< Endpoint to assign ZCL Key Exchange cluster. Default is ZB_ENDPOINT_CBKE_DEFAULT (240) */
uint16_t deviceId;
/**< Device Id to assign to the endpoint created for the ZCL Key Exchange cluster.
* Default is ZCL_DEVICE_METER */
uint16_t suite_mask;
/**< The Key Exchange suite bitmask. E.g. ZCL_KEY_SUITE_CBKE2_ECMQV for CBKE version 2 (cbke_v2). */
struct ZbZclCbkeInfoT cbke_v1;
/**< CBKE version 1 certificate and security keys configuration.
* Only applicable if ZCL_KEY_SUITE_CBKE_ECMQV is set in suite_mask. */
struct ZbZclCbke2InfoT cbke_v2;
/**< CBKE version 2 certificate and security keys configuration.
* Only applicable if ZCL_KEY_SUITE_CBKE2_ECMQV is set in suite_mask. */
...
};
The Configurations are filled on the End Device side as follows:
/* Default configuration for Smart Energy*/
ZbStartupConfigGetProSeDefaults( pstConfig );
/* Using the preconfigured Link Key derived from the given install code*/
memcpy( pstConfig->security.preconfiguredLinkKey, stZigbeeAppInfo.szLinkKey, ZB_SEC_KEYSIZE );
/* Update CBKE Certificate & Keys */
pstConfig->security.cbke.deviceId = APP_ZIGBEE_DEVICE_ID;
pstConfig->security.cbke.endpoint = ZB_ENDPOINT_CBKE_DEFAULT; //Optional
pstConfig->security.cbke.suite_mask = APPLICATION_KEY_SUITE;
/* Update Keep Alive Server*/
pstConfig->security.cbke.tc_keepalive_server_enable = false;
pstConfig->security.cbke.tc_keepalive_base = ZCL_KEEPALIVE_SERVER_BASE_DEFAULT; //Optional
pstConfig->security.cbke.tc_keepalive_jitter = ZCL_KEEPALIVE_SERVER_JITTER_DEFAULT; //Optional
pstConfig->security.cbke.tcso_callback = APP_ZIGBEE_tcso_cb; //Optional
pstConfig->security.cbke.tcso_arg = NULL; //Optional
#ifdef APPLICATION_USE_CBKE2
memcpy( pstConfig->security.cbke.cbke_v2.cert, szZibgeeCbkeCert2, CBKE2_CERTIFICATE_SIZE );
memcpy( pstConfig->security.cbke.cbke_v2.keys.publicCaKey, szZibgeeCbkeCaPublic2, CBKE2_COMPRESSED_PUBLIC_KEY_SIZE );
memcpy( pstConfig->security.cbke.cbke_v2.keys.privateKey, szZibgeeCbkePrivate2, CBKE2_PRIVATE_KEY_SIZE );
#else // APPLICATION_USE_CBKE2
memcpy( pstConfig->security.cbke.cbke_v1.cert, szZibgeeCbkeCert1, CBKE_CERTIFICATE_SIZE );
memcpy( pstConfig->security.cbke.cbke_v1.keys.publicCaKey, szZibgeeCbkeCaPublic1, CBKE_COMPRESSED_PUBLIC_KEY_SIZE );
memcpy( pstConfig->security.cbke.cbke_v1.keys.privateKey, szZibgeeCbkePrivate1, CBKE_PRIVATE_KEY_SIZE );
#endif // APPLICATION_USE_CBKE2
The Configurations are filled on the coordinator side as follows:
/* Default configuration for Smart Energy*/
ZbStartupConfigGetProSeDefaults( pstConfig );
/* Update CBKE Certificate & Keys */
pstConfig->security.trustCenterAddress = dlZigbeeExtendedAdress;
pstConfig->security.cbke.deviceId = APP_ZIGBEE_DEVICE_ID;
pstConfig->security.cbke.endpoint = ZB_ENDPOINT_CBKE_DEFAULT; //Optional
pstConfig->security.cbke.suite_mask = APPLICATION_KEY_SUITE;
/* Update Keep Alive Server */
pstConfig->security.cbke.tc_keepalive_base = ZCL_KEEPALIVE_SERVER_BASE_DEFAULT; //Optional
pstConfig->security.cbke.tc_keepalive_jitter = ZCL_KEEPALIVE_SERVER_JITTER_DEFAULT;//Optional
pstConfig->security.cbke.tc_keepalive_server_enable = true;
pstConfig->security.cbke.tcso_callback = APP_ZIGBEE_tcso_cb; //Optional
pstConfig->security.cbke.tcso_arg = NULL; //Optional
#ifdef APPLICATION_USE_CBKE2
memcpy( pstConfig->security.cbke.cbke_v2.cert, szZibgeeCbkeCert2, CBKE2_CERTIFICATE_SIZE );
memcpy( pstConfig->security.cbke.cbke_v2.keys.publicCaKey, szZibgeeCbkeCaPublic2, CBKE2_COMPRESSED_PUBLIC_KEY_SIZE );
memcpy( pstConfig->security.cbke.cbke_v2.keys.privateKey, szZibgeeCbkePrivate2, CBKE2_PRIVATE_KEY_SIZE );
#else // APPLICATION_USE_CBKE2
memcpy( pstConfig->security.cbke.cbke_v1.cert, szZibgeeCbkeCert1, CBKE_CERTIFICATE_SIZE );
memcpy( pstConfig->security.cbke.cbke_v1.keys.publicCaKey, szZibgeeCbkeCaPublic1, CBKE_COMPRESSED_PUBLIC_KEY_SIZE );
memcpy( pstConfig->security.cbke.cbke_v1.keys.privateKey, szZibgeeCbkePrivate1, CBKE_PRIVATE_KEY_SIZE );
#endif // APPLICATION_USE_CBKE2
5.2. Application scenario
As explained, CBKE is used to generate the Trust Center Link Key, which is used for encrypting the messages between the Coordinator (Trust Center) and the End Device. The whole CBKE Key Establishment procedure can be summarized as follows:
Step 1: Generating the Certificates by the Certification Authority, for Both Coordinator and End Device.
Step 2: Activate CBKE on both ends by filling CBKE startup Configurations.
Step 3: Start the key Establishment procedure.
Step 4: Exchange the Message Authentication Codes (MACs) between the Two Ends for results verification.
5.3. Dynamic CBKE Activation
In some scenarios, it is desirable for a SE End device to control when to trigger the CBKE Key Establishment Procedure. This procedure is not mandatory during the initial joining process. Instead, a preconfigured link key with the TC will be used until the CBKE Key Establishment Procedure is invoked by the application after joining the network. Additionally, the SE End device may update the CBKE certificates and other configurations after joining the network, especially if the certificates have expired or if the server requests a renewal.
We call this feature Dynamic CBKE Activation (DCA). DCA is supported by our Zigbee Stack Implementation and we will give how to use it.
5.3.1. How to use it ?