Authenticating Devices with no User Interface

Introduction

A common problem with Bluetooth devices is that they often have no user interface, other than the Bluetooth connection, but still need to support authentication. This document shows one method to accomplish this.

Description

The Bluetooth specification determines the pairing mechanism based on the reported I/O capabilities of the two devices. When one of the devices has no I/O capabilities at all, the selected method is JustWorks pairing. This ensures an encrypted connection but does not allow for any authentication and allows any Bluetooth device in range request pairing or bonding. The simplest way around this problem involves only allowing bonding for a short period of time after power-up. This provides a little extra protection because the exposure is limited to the time that the device is bondable. However, this doesn’t prevent a rogue device from connecting. A better method is to use a fixed passkey that is made unique. Bluetooth allows for a 6 digit passkey. Because each device has a unique address, the Bluetooth address, it is possible to create a passcode based on this address. However, the number of device addresses is much larger than the number of passkey combinations so the passkey generated will not be truly unique.

The pairing method can be forced to passkey entry by configuring the peripheral as “display only”. The passkey will have to be shared with the user by some medium such as a printed hard copy.

Implementation

First, get the device’s unique address with the following call.

public_address = gecko_cmd_system_get_bt_address()->address;

Next, make a 32 bit integer from this 6 byte array by hashing the address. The example shown here uses SHA-2/256. The result of the hash is reduced by a modulus of 1 000 000 to produce a six digit passkey. This is done in the attached example with the following call:

passkey = makePasskeyFromAddress(public_address);

it can be set as the system passkey with the following call

gecko_cmd_sm_set_passkey(passkey);

To ensure that the pairing method chosen is the passkey method. This allows the master, such as a mobile phone or tablet, to enter a passkey, which is done with the following call:

gecko_cmd_sm_configure(0x07,sm_io_capability_displayonly);

The flags chosen in the first parameter require MITM protection, bonding for encryption, and LE secure connections.

Now, make the device bondable as shown:

gecko_cmd_sm_set_bondable_mode(1);

For simplicity, the attached example code requests any connection to be secured by calling gecko_cmd_sm_increase_security(). Normally, this is done by giving at least one of the characteristics a property that requires security, such as authenticated_read/authenticated_write.

The limitation of using the Bluetooth public address is that the passkey will always be the same. If it becomes necessary to change the pin, such as in the case of a factory default, it is possible to use a static random address. A static random address can be generated and set as follows :

static void set_random_public_address(){

struct gecko_msg_system_get_random_data_rsp_t *random_rsp;
struct gecko_msg_system_set_identity_address_rsp_t *set_ident_addr;
bd_addr identityAddress;
random_rsp = gecko_cmd_system_get_random_data(6);
memcpy(identityAddress.addr,random_rsp->data.data,sizeof(bd_addr));
/* set uppermost 2 bits to make this a random static address */
identityAddress.addr[5] |= 0xC0;
set_ident_addr = gecko_cmd_system_set_identity_address(identityAddress,le_gap_address_type_random);

}

Setting up

To build this application, mbed TLS is required.

  1. Create an SoC-empty sample app for your desired target.

  2. Copy app.c and app.h from the attachment.

  3. Add the mbed TLS configuration according to .

  4. In addition to adding mbed TLS, also add util/third_party/mbedtls/library/md.c and util/third_party/mbedtls/include/md.h to your project and add the following to definition to your project's copy of mbedtls-config.h:

    #define MBEDTLS_MD_C

  5. Build the project and flash to your target board.

  6. Right-click on the J-Link adapter in SimplicityStudio and select launch console. Select serial1 and place the cursor in the text entry box at the bottom then hit enter.

  7. Connect to the device using Silicon Labs EFRConnect mobile app. Upon connecting, you'll be prompted for a passkey. After entering the passkey, you'll see a message in the serial console indicating that the devices are now bonded.

Source