The latest development version of this page may be more current than this released 2.3-beta.2 version.

Provisioning

Provisioning is the process of adding devices to a mesh network. It requires two devices operating in the following roles:

  • The provisioner represents the network owner, and is responsible for adding new nodes to the mesh network.

  • The provisionee is the device that gets added to the network through the Provisioning process. Before the provisioning process starts, the provisionee is an unprovisioned device.

The Provisioning module in the WM IoT SDK Bluetooth Mesh stack supports both the advertiser and GATT bearer for the provisionee role and the Advanced Provisioning Bearer for the provisioner role.

Provisioning process

All Bluetooth Mesh nodes must be provisioned before they can participate in a Bluetooth Mesh network. The Provisioning API provides all the functionality necessary for a device to become a provisioned mesh node. Provisioning is a five-step process, involving the following steps:

  • Beaconing

  • Invitation

  • Public key Exchange

  • Authentication

  • Provisioning data transfer

Beaconing

To initiate the provisioning process, an unconfigured device must first start advertising an unprovisioned beacon. This makes it visible to nearby provisioners, who can initiate provisioning. To indicate that the device needs to be provisioned, call bt_mesh_prov_enable(). The device starts broadcasting the Unprovisioned Beacon with the device UUID and the``OOB information`` field, as specified in the prov parameter passed to:c:func:bt_mesh_init. Additionally, a Uniform Resource Identifier (URI) may be specified, which can point the provisioner to the location of some Out Of Band information, such as the device’s public key or an authentication value database. The URI is advertised in a separate beacon, with a URI hash included in the unprovisioned beacon, to tie the two together.

Uniform Resource Identifier

The Uniform Resource Identifier shall follow the format specified in the Bluetooth Core Specification Supplement. The URI must start with a URI scheme, encoded as a single utf-8 data point, or the special none scheme, encoded as 0x01. The available schemes are listed on the Bluetooth website.

Examples of URI encoding :

URI encoding examples

URI

Encoded

http://example.com

\x16//example.com

https://www.zephyrproject.org/

\x17//www.zephyrproject.org/

just a string

\x01just a string

Provisioning Invitation

The provisioner initiates the Provisioning process by sending a Provisioning invitation. The invitations prompts the provisionee to call attention to itself using the Health Server:ref:bluetooth_mesh_models_health_srv_attention, if available.

The Unprovisioned device automatically responds to the invite by presenting a list of its capabilities, including the supported Out of Band Authentication methods and algorithms.

Public key Exchange

Before the provisioning process can begin, the provisioner and the unprovisioned device exchange public keys, either in-band or Out of Band (OOB).

In-band public key exchange is a part of the provisioning process and always supported by the unprovisioned device and provisioner.

If the application wishes to support public key exchange via OOB, it needs to provide public and private keys to the mesh stack. The unprovisioned device will reflect this in its capabilities. The provisioner obtains the public key via any available OOB mechanism (e.g. the device may advertise a packet containing the public key or it can be encoded in a QR code printed on the device packaging). Note that even if the unprovisioned device has specified the public key for the Out of Band exchange, the provisioner may choose to exchange the public key in-band if it can’t retrieve the public key via OOB mechanism. In this case, a new key pair will be generated by the mesh stack for each Provisioning process.

To enable support of OOB public key on the unprovisioned device side, CONFIG_BT_MESH_PROV_OOB_PUBLIC_KEY needs to be enabled. The application must provide public and private keys before the Provisioning process is started by initializing pointers to bt_mesh_prov.public_key_be and bt_mesh_prov.private_key_be. The keys needs to be provided in big-endian bytes order.

To provide the device’s public key obtained via OOB, call bt_mesh_prov_remote_pub_key_set() on the provisioner side.

Authentication

After the initial exchange, the provisioner selects an Out of Band (OOB) Authentication method. This allows the user to confirm that the device the provisioner connected to is actually the device they intended, and not a malicious third party.

The Provisioning API supports the following authentication methods for the provisionee:

  • Static OOB: An authentication value is assigned to the device during production, which the provisioner can query in some application-specific way.

  • Input OOB: The user inputs the authentication value. The available input actions are listed in bt_mesh_input_action_t.

  • Output OOB: An authentication value is displayed to the user. The available output actions are listed in bt_mesh_output_action_t.

The application must provide callbacks for the supported authentication methods in bt_mesh_prov, as well as enabling the supported actions in bt_mesh_prov.output_actions and bt_mesh_prov.input_actions.

When an Output OOB action is selected, the authentication value should be presented to the user when the output callback is called, and remain until the bt_mesh_prov.input_complete or bt_mesh_prov.complete callback is called. If the action is blink, beep or vibrate, the sequence should be repeated after a delay of three seconds or more.

When an Input OOB action is selected, the user should be prompted when the application receives the bt_mesh_prov.input callback. The user response should be fed back to the Provisioning API through bt_mesh_input_string() or bt_mesh_input_number(). If no user response is recorded within 60 seconds, the Provisioning process is aborted.

If Provisionee wants to mandate OOB authentication, it must use the BT_MESH_ECDH_P256_HMAC_SHA256_AES_CCM algorithm.

Data Transfer

After successfully authenticating the device, the provisioner transfers the provisioning data:

  • Unicast address

  • A network key

  • IV Index

  • Network flags

    • Key refresh

    • IV update

Additionally, a device key is generated for the node. All this data is stored by the mesh stack, and the provisioning bt_mesh_prov.complete callback gets called.

Provisioning Security

Depending on the choice of public key exchange mechanism and authentication method, the provisioning process can be secure or insecure.

On May 24th 2021, ANSSI disclosed a set of vulnerabilities in the Bluetooth Mesh provisioning protocol that showcased how the low entropy provided by the Blink, Vibrate, Push, Twist and Input/Output numeric OOB methods could be exploited in impersonation and MITM attacks. In response, the Bluetooth SIG has reclassified these OOB methods as insecure in the Bluetooth Mesh Profile Specification v1.0.1 erratum 16350, as AuthValue may be brute forced in real time. To ensure secure provisioning, applications should use a static OOB value and OOB public key transfer.

API Reference

group bt_mesh_prov

Provisioning.

Typedefs

typedef enum bt_mesh_output_auth_action bt_mesh_output_action_t

Available Provisioning output authentication actions.

typedef enum bt_mesh_input_auth_action bt_mesh_input_action_t

Available Provisioning input authentication actions.

typedef enum bt_mesh_prov_bearer bt_mesh_prov_bearer_t

Available Provisioning bearers.

typedef enum bt_mesh_prov_oob_info_location bt_mesh_prov_oob_info_t

Out of Band information location.

Enums

enum bt_mesh_prov_authentication_alg

Available authentication algorithms.

Values:

enumerator BT_MESH_PROV_AUTH_CMAC_AES128_AES_CCM
enumerator BT_MESH_PROV_AUTH_HMAC_SHA256_AES_CCM
enum bt_mesh_oob_type

OOB Type field values.

Values:

enumerator BT_MESH_STATIC_OOB_AVAILABLE

Static OOB information available

enumerator BT_MESH_OOB_AUTH_REQUIRED

OOB authentication required

enum bt_mesh_output_auth_action

Available Provisioning output authentication actions.

Values:

enumerator BT_MESH_NO_OUTPUT
enumerator BT_MESH_BLINK

Blink

enumerator BT_MESH_BEEP

Beep

enumerator BT_MESH_VIBRATE

Vibrate

enumerator BT_MESH_DISPLAY_NUMBER

Output numeric

enumerator BT_MESH_DISPLAY_STRING

Output alphanumeric

enum bt_mesh_input_auth_action

Available Provisioning input authentication actions.

Values:

enumerator BT_MESH_NO_INPUT
enumerator BT_MESH_PUSH

Push

enumerator BT_MESH_TWIST

Twist

enumerator BT_MESH_ENTER_NUMBER

Input number

enumerator BT_MESH_ENTER_STRING

Input alphanumeric

enum bt_mesh_prov_bearer

Available Provisioning bearers.

Values:

enumerator BT_MESH_PROV_ADV

PB-ADV bearer

enumerator BT_MESH_PROV_GATT

PB-GATT bearer

enumerator BT_MESH_PROV_REMOTE

PB-Remote bearer

enum bt_mesh_prov_oob_info_location

Out of Band information location.

Values:

enumerator BT_MESH_PROV_OOB_OTHER

Other

enumerator BT_MESH_PROV_OOB_URI

Electronic / URI

enumerator BT_MESH_PROV_OOB_2D_CODE

2D machine-readable code

enumerator BT_MESH_PROV_OOB_BAR_CODE

Bar Code

enumerator BT_MESH_PROV_OOB_NFC

Near Field Communication (NFC)

enumerator BT_MESH_PROV_OOB_NUMBER

Number

enumerator BT_MESH_PROV_OOB_STRING

String

enumerator BT_MESH_PROV_OOB_CERTIFICATE

Support for certificate-based provisioning

enumerator BT_MESH_PROV_OOB_RECORDS

Support for provisioning records

enumerator BT_MESH_PROV_OOB_ON_BOX

On box

enumerator BT_MESH_PROV_OOB_IN_BOX

Inside box

enumerator BT_MESH_PROV_OOB_ON_PAPER

On piece of paper

enumerator BT_MESH_PROV_OOB_IN_MANUAL

Inside manual

enumerator BT_MESH_PROV_OOB_ON_DEV

On device

Functions

int bt_mesh_input_string(const char *str)

Provide provisioning input OOB string.

This is intended to be called after the bt_mesh_prov input callback has been called with BT_MESH_ENTER_STRING as the action.

Parameters:

str – String.

Returns:

Zero on success or (negative) error code otherwise.

int bt_mesh_input_number(uint32_t num)

Provide provisioning input OOB number.

This is intended to be called after the bt_mesh_prov input callback has been called with BT_MESH_ENTER_NUMBER as the action.

Parameters:

num – Number.

Returns:

Zero on success or (negative) error code otherwise.

int bt_mesh_prov_remote_pub_key_set(const uint8_t public_key[64])

Provide Device public key.

Parameters:

public_key – Device public key in big-endian.

Returns:

Zero on success or (negative) error code otherwise.

int bt_mesh_auth_method_set_input(bt_mesh_input_action_t action, uint8_t size)

Use Input OOB authentication.

Provisioner only.

Instruct the unprovisioned device to use the specified Input OOB authentication action. When using BT_MESH_PUSH, BT_MESH_TWIST or BT_MESH_ENTER_NUMBER, the bt_mesh_prov::output_number callback is called with a random number that has to be entered on the unprovisioned device.

When using BT_MESH_ENTER_STRING, the bt_mesh_prov::output_string callback is called with a random string that has to be entered on the unprovisioned device.

Parameters:
  • action – Authentication action used by the unprovisioned device.

  • size – Authentication size.

Returns:

Zero on success or (negative) error code otherwise.

int bt_mesh_auth_method_set_output(bt_mesh_output_action_t action, uint8_t size)

Use Output OOB authentication.

Provisioner only.

Instruct the unprovisioned device to use the specified Output OOB authentication action. The bt_mesh_prov::input callback will be called.

When using BT_MESH_BLINK, BT_MESH_BEEP, BT_MESH_VIBRATE or BT_MESH_DISPLAY_NUMBER, and the application has to call bt_mesh_input_number with the random number indicated by the unprovisioned device.

When using BT_MESH_DISPLAY_STRING, the application has to call bt_mesh_input_string with the random string displayed by the unprovisioned device.

Parameters:
  • action – Authentication action used by the unprovisioned device.

  • size – Authentication size.

Returns:

Zero on success or (negative) error code otherwise.

int bt_mesh_auth_method_set_static(const uint8_t *static_val, uint8_t size)

Use static OOB authentication.

Provisioner only.

Instruct the unprovisioned device to use static OOB authentication, and use the given static authentication value when provisioning.

Parameters:
  • static_val – Static OOB value.

  • size – Static OOB value size.

Returns:

Zero on success or (negative) error code otherwise.

int bt_mesh_auth_method_set_none(void)

Don’t use OOB authentication.

Provisioner only.

Don’t use any authentication when provisioning new devices. This is the default behavior.

Warning

Not using any authentication exposes the mesh network to impersonation attacks, where attackers can pretend to be the unprovisioned device to gain access to the network. Authentication is strongly encouraged.

Returns:

Zero on success or (negative) error code otherwise.

int bt_mesh_prov_enable(bt_mesh_prov_bearer_t bearers)

Enable specific provisioning bearers.

Enable one or more provisioning bearers.

Parameters:

bearers – Bit-wise or of provisioning bearers.

Returns:

Zero on success or (negative) error code otherwise.

int bt_mesh_prov_disable(bt_mesh_prov_bearer_t bearers)

Disable specific provisioning bearers.

Disable one or more provisioning bearers.

Parameters:

bearers – Bit-wise or of provisioning bearers.

Returns:

Zero on success or (negative) error code otherwise.

int bt_mesh_provision(const uint8_t net_key[16], uint16_t net_idx, uint8_t flags, uint32_t iv_index, uint16_t addr, const uint8_t dev_key[16])

Provision the local Mesh Node.

This API should normally not be used directly by the application. The only exception is for testing purposes where manual provisioning is desired without an actual external provisioner.

Parameters:
  • net_key – Network Key

  • net_idx – Network Key Index

  • flags – Provisioning Flags

  • iv_index – IV Index

  • addr – Primary element address

  • dev_key – Device Key

Returns:

Zero on success or (negative) error code otherwise.

int bt_mesh_provision_adv(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr, uint8_t attention_duration)

Provision a Mesh Node using PB-ADV.

Parameters:
  • uuid – UUID

  • net_idx – Network Key Index

  • addr – Address to assign to remote device. If addr is 0, the lowest available address will be chosen.

  • attention_duration – The attention duration to be send to remote device

Returns:

Zero on success or (negative) error code otherwise.

int bt_mesh_provision_gatt(const uint8_t uuid[16], uint16_t net_idx, uint16_t addr, uint8_t attention_duration)

Provision a Mesh Node using PB-GATT.

Parameters:
  • uuid – UUID

  • net_idx – Network Key Index

  • addr – Address to assign to remote device. If addr is 0, the lowest available address will be chosen.

  • attention_duration – The attention duration to be send to remote device

Returns:

Zero on success or (negative) error code otherwise.

int bt_mesh_provision_remote(struct bt_mesh_rpr_cli *cli, const struct bt_mesh_rpr_node *srv, const uint8_t uuid[16], uint16_t net_idx, uint16_t addr)

Provision a Mesh Node using PB-Remote.

Parameters:
  • cli – Remote Provisioning Client Model to provision with.

  • srv – Remote Provisioning Server that should be used to tunnel the provisioning.

  • uuid – UUID of the unprovisioned node

  • net_idx – Network Key Index to give to the unprovisioned node.

  • addr – Address to assign to remote device. If addr is 0, the lowest available address will be chosen.

Returns:

Zero on success or (negative) error code otherwise.

int bt_mesh_reprovision_remote(struct bt_mesh_rpr_cli *cli, struct bt_mesh_rpr_node *srv, uint16_t addr, bool comp_change)

Reprovision a Mesh Node using PB-Remote.

Reprovisioning can be used to change the device key, unicast address and composition data of another device. The reprovisioning procedure uses the same protocol as normal provisioning, with the same level of security.

There are three tiers of reprovisioning: 1. Refreshing the device key 2. Refreshing the device key and node address. Composition data may change, including the number of elements. 3. Refreshing the device key and composition data, in case the composition data of the target node changed due to a firmware update or a similar procedure.

The target node indicates that its composition data changed by instantiating its composition data page 128. If the number of elements have changed, it may be necessary to move the unicast address of the target node as well, to avoid overlapping addresses.

Note

Changing the unicast addresses of the target node requires changes to all nodes that publish directly to any of the target node’s models.

Parameters:
  • cli – Remote Provisioning Client Model to provision on

  • srv – Remote Provisioning Server to reprovision

  • addr – Address to assign to remote device. If addr is 0, the lowest available address will be chosen.

  • comp_change – The target node has indicated that its composition data has changed. Note that the target node will reject the update if this isn’t true.

Returns:

Zero on success or (negative) error code otherwise.

bool bt_mesh_is_provisioned(void)

Check if the local node has been provisioned.

This API can be used to check if the local node has been provisioned or not. It can e.g. be helpful to determine if there was a stored network in flash, i.e. if the network was restored after calling settings_load().

Returns:

True if the node is provisioned. False otherwise.

struct bt_mesh_dev_capabilities

Device Capabilities.

struct bt_mesh_prov

Provisioning properties & capabilities.