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.

ble_app_profile

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"\
                                            ADV_TYPE_COMPLETE_LIST_16BIT_SERVICE_IDS\
                                            ADV_UUID_DEVICE_INFORMATION_SERVICE\
                                            "\x11"\
                                            ADV_TYPE_COMPLETE_LIST_128BIT_SERVICE_IDS\
                                            "\x59\x5A\x08\xE4\x86\x2A\x9E\x8F\xE9\x11\xBC\x7C\x98\x43\x42\x18")
      
    • Configure the device name.

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

      #define USER_CFG_ADDRESS_MODE       APP_CFG_ADDR_PUB
      

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.

    #define APP_CUSTS1_SEC_REQ  SRV_PERM_AUTH
    

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

    #define APP_CUSTS1_SEC_REQ  SRV_PERM_UNAUTH
    
  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.

      #define USER_CFG_FEAT_IO_CAP    GAP_IO_CAP_DISPLAY_ONLY
      

      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.

      #define USER_CFG_FEAT_IO_CAP    GAP_IO_CAP_NO_INPUT_NO_OUTPUT
      
    • The out-of-band information exchange won’t be used.

      #define USER_CFG_FEAT_OOB       GAP_OOB_AUTH_DATA_NOT_PRESENT
      
    • For the authentication requirements, we will require bonding and MITM protection

      #define USER_CFG_FEAT_AUTH_REQ  (GAP_AUTH_BOND | GAP_AUTH_MITM)
      
    • For the device security requirements, we want to use an encrypted link with user authentication for the Passkey association model

      #define USER_CFG_FEAT_SEC_REQ   GAP_SEC1_AUTH_PAIR_ENC
      

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

      #define USER_CFG_FEAT_SEC_REQ   GAP_SEC1_NOAUTH_PAIR_ENC
      
    • Define the LTK length to the default size, which is 16 bytes

      #define USER_CFG_FEAT_KEY_SIZE  KEY_LEN
      
    • 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.

      #define USER_CFG_FEAT_RESP_KDIST (GAP_KDIST_ENCKEY | GAP_KDIST_IDKEY | GAP_KDIST_SIGNKEY)
      

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.

_images/target.png

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,
#if (BLE_APP_SEC)
   .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.

_images/security_msg_flow_diag.png

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.

_images/hw_config.png

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.

_images/hw_config_58x.png

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.

_images/serial_port.png

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.

_images/putty_config.png

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

    _images/debug.png

    Figure 19 Start a debug session

    _images/run.png

    Figure 20 Run the example

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

    _images/device_list.jpg

    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.

    _images/pairing_request.jpg

    Figure 22 Entering the passkey

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

    _images/enter_passkey.png

    Figure 23 Displaying the passkey

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

    _images/sniffer_trace.png

    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.