4. Securing your application using Legacy Pairing

Let’s take a look now on how we can enable the security features of your DA14585/DA14586 or DA14531 device using Dialog’s SDK6. The first use case that we will demonstrate is the setup of a peripheral that uses the Passkey Pairing and Just Works procedure using LE Legacy Pairing.

4.1. First steps and project structure

Go to the SDK 6.0.12 folder that you have downloaded on your hard drive and navigate to the projects/target_apps/ble_examples/ble_app_security/Keil_5 folder. In there open the ble_app_security.uvprojx Keil project. This software example project already has a custom server implemented which uses the BLE security features, and we will use it as our basis for this tutorial.

You can see the project file structure on the left edge of your IDE.


Figure 11 The BLE Security Application project

You can see that there are two types of folders included in the project, some that their name begins with “sdk_” and some that begin with “user_”. User code is developed under the folders beginning with “user_” and all of our modifications will be on these files, but we will also take a look at some SDK functions when this will benefit our understanding. These folders are:

  • user_config/, contains most configuration files.

  • da1458x_config_advanced.h holds advanced configuration settings.

  • da1458x_config_basic.h holds basic configuration settings.

  • user_callback_config.h appoints the callback functions that handle various events or operations.

  • user_profiles_config.h defines which BLE profiles (Bluetooth SIG adopted or custom ones) will be included in the user’s application. Each macro denotes the respective BLE profile that will be included.

  • user_modules_config.h defines which application modules are included or excluded from the user’s application. Define each macro to 0 if it’s included, or to 1 if it’s excluded. An important point to note is that these settings have no effect if the respective module is a BLE profile that it is not used in the user’s application.

  • user_config.h holds advertising parameters, connection parameters, compile-time security parameters, etc.

  • user_periph_setup.h defines hardware related settings relative to the used Development Kit.

  • user_platform/, contains the implementation of target related functions and especially configuration and initialization of peripheral devices in file user_periph_setup.c.

  • user_custom_profile/, contains our BLE server’s database declaration and configuration parameters.

  • user_app/, holds the user’s implementation of handling BLE events and any additional application code.

In the following figure you see the message flow diagram between the Server Application entity, the Custom Profile Service and the Remote Client.

Custom Service message flow diagram

Figure 12 Custom Service message flow diagram

When our device boots, the Custom Profile app initiates the service database creation of the Custom Profile. The creation of the database is confirmed and awaits for a client to connect. When the Remote Client connects, the service gets enabled and the Remote Client can now initiate requests to our server. In the above use case, the Remote Client requests to write to characteristic 1. This is indicated by the Custom Profile to the user application, which updates the value of characteristic 1. Finally our remote client disconnects, and this disables the Custom Profile Service, which in turn indicates that to the user application.

4.2. Modifying the firmware

  1. Open the file da1458x_config_advanced.c. Change the default Bluetooth Device Address. This address has to be unique in a BLE piconet.

    #define CFG_NVDS_TAG_BD_ADDRESS             {0x05, 0x00, 0x70, 0xCA, 0xEA, 0x80}
  2. Navigate to user_modules_config.h, then check and define DLG_CUST1 and DLG_SEC module in your application code.

    #define EXCLUDE_DLG_CUSTS1          (0) // This module will be included
    #define EXCLUDE_DLG_SEC             (0)
  3. Define the Custom Profile associated code in your application, by defining the macro CFG_PRF_CUST1 in user_profiles_config.h.

    #define CFG_PRF_CUST1
  4. Open the file user_config/user_config.h and make the next changes:

    • Set the sleep mode.

      static const sleep_state_t app_default_sleep_mode = ARCH_SLEEP_OFF;
    • Set the advertising data.

      #define USER_ADVERTISE_DATA         ("\x03"\
    • Configure the device name.

      #define USER_DEVICE_NAME        "DLG-SECURITY"
    • Define the address mode as a public Bluetooh device address


We will now continue with the security related changes in our application.

  1. Enable the application security flag in da145x_config_basic.h file.

    #define CFG_APP_SECURITY
  2. Go to file user_config/user_profiles_config.h and enable access to the profile characteristics using an authenticated link.


    In case you will be using the Just Works association model, you have to define this to

  3. In the same file, enable the UART output functionality by defining CFG_PRINTF.

    #define CFG_PRINTF

    By defining this, you will enable the generation of a random number for the passkey. In case you want to use a predefined passkey, you would have to undefine the CFG_PRINTF macro and set your passkey in the user_security.h header file:

    #define APP_SECURITY_MITM_PASSKEY_VAL    (123456)
  4. Open the user_config.h file and make sure the next configuration is enabled:

    • Set the capabilities of the device as one that has only a display. This will invoke the Passkey Pairing procedure.


      In case you would like to use the Just Works association model, define the I/O capabilities of the device as one with no input and no output.

    • The out-of-band information exchange won’t be used.

    • For the authentication requirements, we will require bonding and MITM protection

    • For the device security requirements, we want to use an encrypted link with user authentication for the Passkey association model


      In case you will be using the Just Works association model, you should define the above macro as

    • Define the LTK length to the default size, which is 16 bytes

    • In the key distribution phase, we will distribute the LTK, CSRK, and IDK. We will cover signing and address resolution in more detail in the next tutorial.


We can now build the software example. Choose your target in the drop-down box shown below and then hit the Build button or press F7.


Figure 13 Choose your target device and build the example

4.3. Message flow

Before running the example we will take a moment to see on a higher level view how it works. All BLE events are processed using the following callbacks, which are assigned in the file user_callback_config.h.

   static const struct app_callbacks user_app_callbacks = {
   .app_on_connection                  = user_app_connection,
   .app_on_disconnect                  = user_app_disconnect,
   .app_on_update_params_rejected      = NULL,
   .app_on_update_params_complete      = NULL,
   .app_on_set_dev_config_complete     = default_app_on_set_dev_config_complete,
   .app_on_adv_nonconn_complete        = NULL,
   .app_on_adv_undirect_complete       = user_app_adv_undirect_complete,
   .app_on_adv_direct_complete         = NULL,
   .app_on_db_init_complete            = default_app_on_db_init_complete,
   .app_on_scanning_completed          = NULL,
   .app_on_adv_report_ind              = NULL,
   .app_on_get_dev_name                = default_app_on_get_dev_name,
   .app_on_get_dev_appearance          = default_app_on_get_dev_appearance,
   .app_on_get_dev_slv_pref_params     = default_app_on_get_dev_slv_pref_params,
   .app_on_set_dev_info                = default_app_on_set_dev_info,
   .app_on_data_length_change          = NULL,
   .app_on_update_params_request       = default_app_update_params_request,
   .app_on_generate_static_random_addr = default_app_generate_unique_static_random_addr,
   .app_on_svc_changed_cfg_ind         = NULL,
   .app_on_get_peer_features           = NULL,
   .app_on_pairing_request             = default_app_on_pairing_request,
   .app_on_tk_exch                     = user_app_on_tk_exch,
   .app_on_irk_exch                    = NULL,
   .app_on_csrk_exch                   = default_app_on_csrk_exch,
   .app_on_ltk_exch                    = default_app_on_ltk_exch,
   .app_on_pairing_succeeded           = default_app_on_pairing_succeeded,
   .app_on_encrypt_ind                 = NULL,
   .app_on_encrypt_req_ind             = default_app_on_encrypt_req_ind,
   .app_on_security_req_ind            = NULL,
   .app_on_addr_solved_ind             = default_app_on_addr_solved_ind,
   .app_on_addr_resolve_failed         = default_app_on_addr_resolve_failed,
   .app_on_ral_cmp_evt                 = default_app_on_ral_cmp_evt,
   .app_on_ral_size_ind                = NULL,
   .app_on_ral_addr_ind                = NULL,
#endif // (BLE_APP_SEC)

By defining CFG_APP_SECURITY, the BLE_APP_SEC guard gets defined and the latter block of code will be compiled. The user can utilize Dialog’s SDK6 default handlers, or provide their own implementation without sacrificing modularity of their code and call the default handlers when appropriate. The function invocations that take place between different software entities can be seen in the next message flow diagram.


Figure 14 Security message flow diagram

4.4. Running the example

4.4.1. Using the UART

We will use the UART peripheral of our device to print the number for the pairing. If you are targetting a DA14531 device, on your DA145xx hardware kit connect the left pin of the UTX jumper connector to the P26 pin, as shown in the following figure.


Figure 15 Hardware configuration for UART transmit on DA14531

In case you own a DA14585 or DA14586 device, configure the hardware as shown in the following figure.


Figure 16 Hardware configuration for UART transmit on DA1458x

Next, we have to find out our serial port. Right click on “My Computer” and click “Manage”. Under “Ports” you will find two more ports that have been enumerated when you plugged in your device. Keep in mind the one with the lowest number.


Figure 17 Finding out the right port

Open up your serial port terminal. Set the serial port to the one you have identified in the previous step, and enter the parameters that you can see in the following figure.


Figure 18 Serial port configuration

4.4.2. Running the example

  1. In Keil, run a debug session and in the next workspace run the example


    Figure 19 Start a debug session


    Figure 20 Run the example

  2. Open the Lightblue App on your smartphone and locate the DLG-SECURITY device.


    Figure 21 Locate the DLG-SECURITY device

  3. Tap on the device name. The app will connect with your device and the Pairing Feature Exchange will start. When the I/O Capabilities have been exchanged, you’ll be asked to accept pairing the device with your phone by entering the PIN. In LE legacy pairing, Authenticated man-in-the-middle (MITM) protection is only obtained by using the passkey entry pairing method or may be obtained using the out of band pairing method. The GATT database will be discovered without having the devices bonded, but when you try to access (read or write) a Characteristic, the Bonding procedure will start.


    Figure 22 Entering the passkey

  4. Your device on your serial terminal will display the passkey. Enter the passkey to authorize the pairing procedure.


    Figure 23 Displaying the passkey

  5. Below you can see a Bluetooth sniffer trace of the Pairing procedure exchanged messages.


    Figure 24 Security Manager Protocol message exchange

With these simple steps you have enabled security on your connection using the LE Legacy pairing. In the next pages we will talk about privacy in BLE and the access rights of your resources.