Gazell Pairing

The Gazell pairing library enables applications to use the Gazell Link Layer to provide a secure wireless link between Gazell nodes. The library is customized for pairing a Device (for example, a mouse, keyboard, or remote control) with a Host (typically a USB dongle) using Gazell.

Overview

Gazell Pairing determines the channel set used by Gazell. See the Gazell Pairing user guide for more information, such as the features of this library.

This library is used in the Gazell Dynamic Pairing Host and Gazell Dynamic Pairing Device samples.’

Requirements

The Gazell Pairing library requires the same resources as the Gazell Link Layer.

In addition, the Gazell Pairing library also employs three nRF52 Series peripherals:

  • Random Number Generator, for generating keys and tokens.

  • AES Electronic Codebook (ECB), for encryption and decryption.

  • Non-Volatile Memory Controller (NVMC), for storing of pairing parameters.

In addition, Gazell Pairing requires the Gazell Link Layer resource of two pipes: one for pairing and one for encrypted data transmission.

Since Gazell Pairing requires exclusive access to pipes 0 and GZP_DATA_PIPE (default pipe 1), it must control the internal Gazell Link Layer variables base_address_0, base_address_1 and prefix_address_byte for pipes GZP_PAIRING_PIPE (always pipe 0) and GZP_DATA_PIPE (configurable).

  • The main application can use the pipes 2-7.

  • The base_address_1 applies to these pipes.

  • Gazell Pairing must also determine whether the RX pipes 0 and 1 are enabled.

Note

Make sure not to affect the rx_enabled status of these pipes.

Do not access the following:

Configuration

Complete the following steps for configuration:

  1. The prerequisite Gazell Link Layer should be enabled as described in the Gazell Link Layer Configuration section.

  2. Set the CONFIG_GAZELL_PAIRING Kconfig option to enable the Gazell Pairing.

  3. Select the role by either of the following Kconfig options:

    1. CONFIG_GAZELL_PAIRING_DEVICE - Device.

    2. CONFIG_GAZELL_PAIRING_HOST - Host.

To support persistent storage of pairing data, set the CONFIG_GAZELL_PAIRING_SETTINGS Kconfig option.

To support encryption, set the CONFIG_GAZELL_PAIRING_CRYPT Kconfig option.

API documentation

Header file: include/gzp.h and include/gzp_config.h
Source file: subsys/gazell/
group gzp

Typedefs

enum gzp_key_select

Enumerator used for selecting the key to be used for encryption.

Values:

enumerator GZP_ID_EXCHANGE

“Secret key” only

enumerator GZP_KEY_EXCHANGE

“Secret key” and “Host ID”

enumerator GZP_DATA_EXCHANGE

“Dynamic key” and “Host ID”

enum gzp_cmd

Enumerator used in the first payload byte of each packet to indicate the packet type.

Values:

enumerator GZP_CMD_HOST_ADDRESS_REQ

Host address request

enumerator GZP_CMD_HOST_ADDRESS_FETCH

Host address fetch

enumerator GZP_CMD_HOST_ID_REQ

Host ID request

enumerator GZP_CMD_HOST_ID_FETCH

Host ID fetch request

enumerator GZP_CMD_KEY_UPDATE_PREPARE

Key update prepare

enumerator GZP_CMD_KEY_UPDATE

Key update

enumerator GZP_CMD_ENCRYPTED_USER_DATA

Encrypted user data

enumerator GZP_CMD_FETCH_RESP

Fetch response

enumerator GZP_CMD_HOST_ADDRESS_RESP

Host address response

enumerator GZP_CMD_HOST_ID_FETCH_RESP

Host ID fetch response

enumerator GZP_CMD_KEY_UPDATE_PREPARE_RESP

Key update prepare

enumerator GZP_CMD_ENCRYPTED_USER_DATA_RESP

Encrypted user data response

enum gzp_id_req_res

Enumerator used to identify the state of the current Host ID request.

Values:

enumerator GZP_ID_RESP_PENDING

ID response pending

enumerator GZP_ID_RESP_GRANTED

ID response granted

enumerator GZP_ID_RESP_REJECTED

ID response rejected

enumerator GZP_ID_RESP_FAILED

ID response failed

enumerator GZP_ID_RESP_NO_REQUEST

Default value. No ID request has yet been received.

typedef void (*gzp_tx_result_callback)(bool success, uint32_t pipe, const nrf_gzll_device_tx_info_t *tx_info)

Callback function for reporting packet transmit result

Param success:

is the packet transmit result.

Param pipe:

is the pipe.

Param tx_info:

struct is the information about the packet transmission.

typedef void (*gzp_address_req_callback)(bool result, void *context)

Callback function for reporting “system address” request result

Param result:

corresponds to gzp_address_req_send() return value.

Param context:

pointer to the user context.

typedef void (*gzp_id_req_callback)(enum gzp_id_req_res result, void *context)

Callback function for reporting Host ID request result

Param result:

corresponds to gzp_id_req_send() return value.

Param context:

pointer to the user context.

typedef void (*gzp_crypt_data_send_callback)(bool result, void *context)

Callback function for reporting encrypted user data transmit result

Param result:

corresponds to gzp_crypt_data_send() return value.

Param context:

pointer to the user context.

Misc. function prototypes

void gzp_crypt_set_session_token(const uint8_t *token)

Set the session token.

Parameters:
  • token – Pointer to the session token to set.

void gzp_crypt_get_session_token(uint8_t *dst_token)

Get the session token.

Parameters:
  • dst_token – Pointer to write the session token.

void gzp_crypt_set_dyn_key(const uint8_t *dyn_key)

Set the dynamic key.

Parameters:
  • dyn_key – Pointer to the dynamic key to set.

void gzp_crypt_get_dyn_key(uint8_t *dst_key)

Get the dynamic key.

Parameters:
  • dst_key – Pointer to write the dynamic key too.

void gzp_set_host_id(const uint8_t *src)

Set the Host ID.

Parameters:
  • src – Pointer to the Host ID to set.

void gzp_get_host_id(uint8_t *dst)

Get the Host ID.

Parameters:
  • dst – Pointer to write the Host ID to.

void gzp_crypt_select_key(enum gzp_key_select key_select)

Selecting what key-set that should be used when encrypting data using gzp_crypt().

Parameters:
  • key_select – Key-set to use.

void gzp_crypt(uint8_t *dst, const uint8_t *src, uint8_t length)

Encypt / decrypt data.

The current “session token” will be used as initialization vector (IV). The AES key to be used is selected by gzp_crypt_select_key(). AES is a symmetric encryption scheme, this function can be used to perform both encryption and decryption.

Parameters:
  • dst – Destination to write encrypted data to. Should be 16 bytes long.

  • src – Source data to encrypt.

  • length – Length in bytes of src.

bool gzp_validate_id(const uint8_t *src_id)

Compare the *src_id with a pre-defined validation ID.

Parameters:
  • src_id – Pointer to the source validation ID to compare to.

Return values:
  • true – If *src_id equals the pre-defined ID.

  • false – If *src_id does not equal the pre-defined ID.

void gzp_add_validation_id(uint8_t *dst_id)

Add the pre-defined validation ID to dst_id. GZP_VALIDATION_ID_LENGTH bytes will be added.

Parameters:
  • dst_id – Pointer to add the GZP validation ID to.

void gzp_random_numbers_generate(uint8_t *dst, uint8_t n)

Generate random bytes.

Parameters:
  • dst – Destination to write the random bytes to.

  • n – Number of bytes to generate.

bool gzp_update_radio_params(const uint8_t *system_address)

Update the channel table and the system address.

The channel table is updated to pseudo-random set generated using the system address. The channel table still includes GZP_CHANNEL_MAX and GZP_CHANNEL_MIN. The system address is applied to base address 1 and therefore applies to pipes 1-7.

Parameters:
  • system_address – Pointer to the system_address to set.

Return values:
  • true – If the radio parameters were updated successfully.

  • false – If there was an error updated the radio parameters.

void gzp_generate_channels(uint8_t *ch_dst, const uint8_t *address, uint8_t channel_set_size)

Generate a set of channels from a 4 byte address.

Parameters:
  • ch_dst – Destination to write the channel set to. The channel set includes GZP_CHANNEL_MAX and GZP_CHANNEL_MIN.

  • address – Four byte address to generate the channel set from.

  • channel_set_size – Size of the channel set to generate.

void gzp_xor_cipher(uint8_t *dst, const uint8_t *src, const uint8_t *pad, uint8_t length)

Perform an XOR on two byte strings.

Parameters:
  • dst – Destination to write the result to. Should be of size length.

  • src

  • pad

  • length – Number of bytes to perform the XOR operation on.

Common Device and Host functions

void gzp_init(void)

Initialization function. This function initializes the Gazell Pairing Library.

This function must be called before any of the other Gazell Pairing Library functions are used and must be called after gzll_init() is called.

void gzp_erase_pairing_data(void)

Function for erasing all pairing data.

void nrf_gzp_disable_gzll(void)

Disable Gazell and sleep while waiting for nrf_gzll_disabled callback.

void gzp_id_req_cancel(void)

Function for cancelling an ongoing (pending) “Host ID request”.

After calling this function the “Host ID request” status will go to “ID request Idle”.

void nrf_gzp_flush_rx_fifo(uint32_t pipe)

Flush the GZLL RX FIFO for a specific pipe while GZLL is disabled.

Parameters:
  • pipe – Pipe.

Device functions

void gzp_tx_result_callback_register(gzp_tx_result_callback callback)

Function for registering callback to be called on transmit done.

Parameters:
  • callback – is the callback function.

int8_t gzp_get_pairing_status(void)

Function to check whether a Device has existing pairing data, implying that it is paired to a Host.

Return values:
  • -2 – The pairing database is empty.

  • -1 – The device has a system address but no Host ID.

  • >=0 – The device has a system address and Host ID.

bool gzp_address_req_send(void)

Function for sending a “system address” request to a Host.

When calling this function the Device will attempt acquiring the “system address” from any Host within close proximity.

If a host is located within close proximity and pairing is enabled in the Host, a “system address” will be sent in return to the Device.

The new “system address” will apply immediately in the Device, and the new “system address” will be stored in non volatile (NV) memory.

Return values:
  • true – if new “system address” was received from a Host.

  • false – if no “system address” was received from a Host.

void gzp_address_req_send_async(gzp_address_req_callback callback, void *context)

Function for sending a “system address” request to a Host. Asynchronized fashion.

Parameters:
  • callback – is the callback function.

  • context – is a pointer to be passed to the callback function.

enum gzp_id_req_res gzp_id_req_send(void)

Function for sending a “Host ID request” to a Host.

The “Host ID” is needed to be able to send encrypted data using gzp_crypt_data_send().

The request will be sent using the “system address” previously received using gzp_address_req_send().

It is not required that the Host is within close proximity in order to acquire the “Host ID”.

The new “Host ID” will apply immediately for the Device, and the new “Host ID” will be stored in non volatile (NV) memory.

Return values:
  • GZP_ID_RESP_PENDING – if a “Host ID request” has been sent to the Host, but the Host application has not yet decided whether to Grant or Reject the “ID request”.

  • GZP_ID_RESP_GRANTED – if the “Host ID” has been received from the Host. The received “Host ID” will be stored in non volatile memory.

  • GZP_ID_RESP_REJECTED – if the Host application has rejected the “Host ID request”.

  • GZP_ID_RESP_FAILED – if failing to send a request or receive a response from the Host.

void gzp_id_req_send_async(gzp_id_req_callback callback, void *context)

Function for sending a “Host ID request” to a Host. Asynchronized fashion.

Parameters:
  • callback – is the callback function.

  • context – is a pointer to be passed to the callback function.

bool gzp_crypt_data_send(const uint8_t *src, uint8_t length)

Function for sending encrypted user data to the Host.

Before any data can be sent the Device must acquire both the Host’s “system address” by using gzp_address_req_send() and the “Host ID” by using gzp_id_req_send().

Parameters:
  • src – is a pointer to the data packet to be sent.

  • length – is the length of the data packet to be sent.

Return values:
  • true – if the data was successfully transmitted and decrypted by the Host.

  • false – if data transmission failed or Host failed to decryption data correctly.

void gzp_crypt_data_send_async(const uint8_t *src, uint8_t length, gzp_crypt_data_send_callback callback, void *context)

Function for sending encrypted user data to the Host. Asynchronized fashion.

Parameters:
  • src – is a pointer to the data packet to be sent.

  • length – is the length of the data packet to be sent.

  • callback – is the callback function.

  • context – is a pointer to be passed to the callback function.

Host functions

void gzp_pairing_enable(bool enable)

Function for enabling/disabling pairing in a host. When pairing is enabled the host will be monitoring for “system address” and “Host ID” requests from Devices.

A “system address request” received from a Device will always be granted. When a “host ID request” has been received, the Host application have to grant, reject or cancel this by using one of the following functions:

Parameters:
  • enable

    • true enables pairing.

    • false disables pairing.

void gzp_host_execute(void)

Execute the Gazell Pairing Library Host operation.

This function must be called regularly by the Host application.

bool gzp_address_exchanged(void)

Address exchanged check.

Return values:
  • true – If a “system address” was delivered to a requesting Device during the previous call to gzp_host_execute();

  • false – Otherwise.

bool gzp_id_req_received(void)

Function for checking if a “Host ID request” has been received from a Device.

If a request has been received, the Pairing library will enter “ID request pending” state.

The application is responsible for responding to this request by calling one of the following functions:

Return values:
  • true – if a “Host ID request” has been received (internal state is “ID request pending”)

  • false – if no “Host ID request” has been received (internal state is “ID request idle”)

void gzp_id_req_reject(void)

Function for rejecting the previously received “Host ID request”. This function should be called only when a “Host ID request” has been received (internal state is “ID request pending”).

The internal state of the Pairing library will remain “ID request pending” until the a “reject” message has been successfully transmitted to the requesting Device. After this the internal state will change to “ID request idle”.

void gzp_id_req_grant(void)

Function for granting the previously received “Host ID request”. This function should be called only when a “Host ID request” has been received (internal state is “ID request pending”).

The internal state of the Pairing library will remain “ID request pending” until the “Host ID” has been successfully transmitted to the requesting Device. After this the internal state will change to “ID request idle”.

bool gzp_crypt_user_data_received(void)

Check if user data has been received.

Return values:
  • true – If encrypted user data has been received.

  • false – Otherwise.

bool gzp_crypt_user_data_read(uint8_t *dst, uint8_t *length)

Function for reading encrypted user data.

Note that the read user data will be automatically decrypted. Only data that was decrypted correctly will be presented.

Parameters:
  • dst – is a pointer to where the received data will be written.

  • length – is a pointer for returning the number of bytes received. Only 1 byte will be writtem to length*.

Return values:
  • true – if data has been received and is written to dst*

  • false – if no data has been received.

void gzll_rx_start(void)

Function emulating behavior of gzll_rx_start() in legeacy nRF24xx Gazell library.

This function sets Gazell in Host mode and starts reception (enable).

Pairing configuration defines

GZP_PAIRING_PIPE

Pipe reserved for initial pairing communication.

GZP_DATA_PIPE

Pipe reserved for GZP encrypted data communication (one pipe only).

GZP_TX_RX_TRANS_DELAY

Time to wait between request and fetch packets in RX_PERIODS (2 timeslot periods)

GZP_SYSTEM_ADDRESS_WIDTH

Must equal Gazell base address length.

GZP_VALIDATION_ID

Validation ID. Required to be shared by Host and Device. Not a secret.

GZP_VALIDATION_ID_LENGTH

Validation ID length in bytes.

GZP_HOST_ID_LENGTH

Host ID length in bytes.

GZP_SESSION_TOKEN_LENGTH

Session token length in bytes.

GZP_DYN_KEY_LENGTH

Dynamic key length in bytes.

GZP_HOST_RX_POWER_THRESHOLD

RSSI threshold for when signal strength in RX packet power is high enough.

Device -> Host packet definitions

GZP_CMD_HOST_ADDRESS_REQ_PAYLOAD_LENGTH

“Host address request” packet, payload length

GZP_CMD_HOST_ADDRESS_FETCH_PAYLOAD_LENGTH

“Host address fetch” packet, payload length

GZP_CMD_HOST_ID_REQ_SESSION_TOKEN

“Host ID request” packet, session token position

GZP_CMD_HOST_ID_REQ_PAYLOAD_LENGTH
GZP_CMD_HOST_ID_FETCH_VALIDATION_ID

“Host ID fetch” packet

GZP_CMD_HOST_ID_FETCH_PAYLOAD_LENGTH

“Host ID fetch” payload length

GZP_CMD_KEY_UPDATE_PREPARE_PAYLOAD_LENGTH

“Key update prepare” payload length

GZP_CMD_KEY_UPDATE_VALIDATION_ID

“Key update” packet, validation ID position

GZP_CMD_KEY_UPDATE_NEW_KEY

“Key update” packet, new key position

GZP_CMD_KEY_UPDATE_PAYLOAD_LENGTH

“Key update” packet, payload length

GZP_CMD_ENCRYPTED_USER_DATA_VALIDATION_ID

“Encrypted user data” packet, validation ID position

GZP_CMD_ENCRYPTED_USER_DATA_PAYLOAD

“Encrypted user data” packet, user data position

GZP_ENCRYPTED_USER_DATA_PACKET_OVERHEAD

“Encrypted user data” packet, packet overhead length

GZP_ENCRYPTED_USER_DATA_MAX_LENGTH

“Encrypted user data” packet, max payload length

GZP_CMD_FETCH_RESP_PAYLOAD_LENGTH

General “fetch response” packet, payload_length

Host -> Device packet definitions

GZP_CMD_HOST_ADDRESS_RESP_ADDRESS

“Host address fetch” response packet, address position

GZP_CMD_HOST_ADDRESS_RESP_PAYLOAD_LENGTH

“Host address fetch” response packet, payload length

GZP_CMD_HOST_ID_FETCH_RESP_VALIDATION_ID

“Host ID fetch” response packet, validation ID position

GZP_CMD_HOST_ID_FETCH_RESP_STATUS

“Host ID fetch” response packet, status position

GZP_CMD_HOST_ID_FETCH_RESP_HOST_ID

“Host ID fetch” response packet, Host ID position

GZP_CMD_HOST_ID_FETCH_RESP_PAYLOAD_LENGTH

“Host ID fetch” response packet, payload length

GZP_CMD_KEY_UPDATE_PREPARE_RESP_SESSION_TOKEN

“Key update prepare” response packet, session token position

GZP_CMD_KEY_UPDATE_PREPARE_RESP_PAYLOAD_LENGTH

“Key update prepare” response packet, payload length position

GZP_CMD_ENCRYPTED_USER_DATA_RESP_SESSION_TOKEN

“Encrypted user data” response packet, session token position

GZP_CMD_ENCRYPTED_USER_DATA_RESP_VALIDATION_ID

“Encrypted user data” response packet, validation ID position

GZP_CMD_ENCRYPTED_USER_DATA_RESP_PAYLOAD_LENGTH

“Encrypted user data” response packet, payload length position