Activate BLE Bonding and security with Button and show special services

schluesselmeister
Posts: 2
Joined: Tue Apr 23, 2019 5:41 pm

Activate BLE Bonding and security with Button and show special services

Postby schluesselmeister » Tue Apr 23, 2019 5:52 pm

Hello,

i am trying to build a device with esp32 and connect this via BLE to Android/iOS. I will build a custom iOS/Android App.

I'd like to send some basic informtion about the device to all users who might be in range of the esp32. These user are allowed to read/write some information. They do not need to bond.

some users are allowed to read/write special services/characteristics. i have no display but one button(for testing i use the hall sensor) at my esp. so my plan is: if a users presses this button, he is allowed to bond within 10 seconds.

i modified public examples. but i did not manage to activate bonding only for 10 seconds. so i build a work around within the "onConfirmPIN". this is not very nice, because on android the user is show a message "is pin XYZ shown on device"

so my questions are:

A) is there a nice way to activate bonding for 10 seconds after button is pressed?
B) how can i define services/characteristics with are only available for bonded clients?

THANKS a lot in advance for your feedback

here my current code:

Code: Select all

/*
    Based on Neil Kolban example for IDF: https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLE%20Tests/SampleServer.cpp
    Ported to Arduino ESP32 by Evandro Copercini
*/

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEServer.h>

// See the following for generating UUIDs:
// https://www.uuidgenerator.net/

#define SERVICE_UUID        "4fafc201-1fb5-459e-8fcc-c5c9c331914b"
#define CHARACTERISTIC_UUID "beb5483e-36e1-4688-b7f5-ea07361b26a8"

#define LOOP_DELAY 100


float blePairTimeOut = 0;

class MySecurity : public BLESecurityCallbacks {
  
  bool onConfirmPIN(uint32_t pin){
    Serial.println("onConfirmPIN");
    if (blePairTimeOut > 0){
      return true;  
    }
    else{
      return false;
    }
  }
  
  uint32_t onPassKeyRequest(){
    Serial.println("onPassKeyRequest");
        ESP_LOGI(LOG_TAG, "PassKeyRequest");
    return 133700;
  }

  void onPassKeyNotify(uint32_t pass_key){
    Serial.println("onPassKeyNotify");
        ESP_LOGI(LOG_TAG, "On passkey Notify number:%d", pass_key);
  }

  bool onSecurityRequest(){
    Serial.println("onSecurityRequest");
      ESP_LOGI(LOG_TAG, "On Security Request");
    return true;
  }

  void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl){
    Serial.println("onAuthenticationComplete");
    ESP_LOGI(LOG_TAG, "Starting BLE work!");
    if(cmpl.success){
      Serial.println("onAuthenticationComplete -> success");
      uint16_t length;
      esp_ble_gap_get_whitelist_size(&length);
      ESP_LOGD(LOG_TAG, "size: %d", length);
    }
    else{
      Serial.println("onAuthenticationComplete -> fail");
    }
  }
};

void setup() {
    

    
  Serial.begin(115200);
  Serial.println("Starting BLE work!");

  BLEDevice::init("ESP32 TW");
  BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT);
  /*
   * Required in authentication process to provide displaying and/or input passkey or yes/no butttons confirmation
   */
  BLEDevice::setSecurityCallbacks(new MySecurity());
  BLEServer *pServer = BLEDevice::createServer();
  
  //public services
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE
                                       );

  pCharacteristic->setValue("Hello World says Neil");
  pCharacteristic->setCallbacks("
  pService->start();
  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();



  
  BLESecurity *pSecurity = new BLESecurity();
  pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_MITM_BOND); //ESP_LE_AUTH_REQ_SC_ONLY
  pSecurity->setCapability(ESP_IO_CAP_KBDISP);
  pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
  Serial.println("Characteristic defined! Now you can read it in your phone!");
}

void loop() {
  // put your main code here, to run repeatedly:
    int val = hallRead();
  // print the results to the serial monitor:
  //Serial.print("sensor = ");
  
  if (val > 100 ) {
    // turn LED on:
    Serial.println("BLE ACTIVE");
    blePairTimeOut = 10;
    
  } else {
    // turn LED off:
  }
  
  delay(LOOP_DELAY);
  if (blePairTimeOut > 0){
    blePairTimeOut = blePairTimeOut - LOOP_DELAY/1000;
  }
}

chegewara
Posts: 2376
Joined: Wed Jun 14, 2017 9:00 pm

Re: Activate BLE Bonding and security with Button and show special services

Postby chegewara » Thu Apr 25, 2019 10:04 pm

Hi,
there is no easy way to activate bonding for only 10 seconds. When you are using pairing with YES/NO or pin then you have 30 seconds to input pin or confirm pairing, this is by bluetooth specs. What you could try to do is to use that button to confirm pairing with YES/NO, but it will be used not before pairing starts, but when pairing is already processing.

To setup characteristic to be accessed only by paired/bonded devices you have to use setAccessPermissions() on such characteristics:
https://github.com/nkolban/esp32-snippe ... stic.h#L84

degill
Posts: 5
Joined: Mon Apr 29, 2019 11:17 am

Re: Activate BLE Bonding and security with Button and show special services

Postby degill » Mon Apr 29, 2019 11:27 am

chegewara wrote:
Thu Apr 25, 2019 10:04 pm
Hi,
there is no easy way to activate bonding for only 10 seconds. When you are using pairing with YES/NO or pin then you have 30 seconds to input pin or confirm pairing, this is by bluetooth specs. What you could try to do is to use that button to confirm pairing with YES/NO, but it will be used not before pairing starts, but when pairing is already processing.
Hey there, I am working with schluesselmeister :)

Here are some additional info and clarifications about the device schluesselmeister described. The final design of the device should be as follows:

1. The physical device does only has a single button - no display and no keyboard, except for this one button.
2. It has one service with a handful of characteristics.
3. The characteristics can be read, written to and notifications can be enabled.
4. For security reasons the characteristics should only be readable or writeable after pairing/bonding. Same goes for enabling notifiations to be notified about changes to the characteristic.
5. Only after pressing the button pairing/bonding should be enabled for `X` seconds (the 10 seconds stated by schluesselmeister were just an example).

@chegewara Can you elaborate on what you mean by "confirm pairing with YES/NO". I could not find a callback method to be asked to confirm pairing. What should I use as the device capabilities in this case?

chegewara
Posts: 2376
Joined: Wed Jun 14, 2017 9:00 pm

Re: Activate BLE Bonding and security with Button and show special services

Postby chegewara » Wed May 01, 2019 9:18 am

"confirm pairing with YES/NO" is used when both devices have display and keyboard capability.

degill
Posts: 5
Joined: Mon Apr 29, 2019 11:17 am

Re: Activate BLE Bonding and security with Button and show special services

Postby degill » Thu May 02, 2019 8:51 am

I still don't quite get how to achieve our goal :?

The design of the two devices in our scenario are as follows:

1. BLE device with only one button and no display - we program this one
2. Smartphone

We don't want anyone nearby to be able to pair with the BLE device and then read/write. We only want people with physical access to the device to be able to pair with the device for a short limited amount of time (e.g. X seconds) and then be able to read/write. Also we want users to be able to connect to the device when they have already paired/bonded with it.

There are three areas we looked at:

1. We looked at the following function, but it gets never called:

Code: Select all

 bool onSecurityRequest() {
    Serial.println("onSecurityRequest");
    return true;
}
We thought that we could return true only within X seconds after the button was pressed. But as I said, it never gets called.

2. Another thing we thought could help us was to use BLEAdvertising::setScanFilter. But we don't really understand the two flags scanRequestWhitelistOnly and connectWhitelistOnly. We thought having setScanFilter(false, true) will allow everyone to find our BLE device but only paired/bonded devices can connect to it. And with setScanFilter(false, false) everyone can find it and can connect to it.

3. We use the option from 2. but we stop() and start() with different setScanFilter configurations.

Another question regarding advertisement: Is advertisement mandatory in order for paired/bonded smartphones to connect to the BLE device or can advertisement be omitted and only enabled after the button was pressed?

*Additional note*: Maybe we are looking at it wrong, maybe this scenario is solved in a different way in the BLE specification and we are going in the wrong direction.

We know this is a lot to ask, so thanks in advance for any help :geek:

degill
Posts: 5
Joined: Mon Apr 29, 2019 11:17 am

Re: Activate BLE Bonding and security with Button and show special services

Postby degill » Tue May 07, 2019 2:42 pm

double post - but I can not delete it
Last edited by degill on Wed May 08, 2019 7:08 am, edited 2 times in total.

degill
Posts: 5
Joined: Mon Apr 29, 2019 11:17 am

Re: Activate BLE Bonding and security with Button and show special services

Postby degill » Tue May 07, 2019 3:06 pm

A little update from our progress.

Our current idea to get things working is the following: We initially start our esp32 with advertisement to be scannable by everyone but connectable only by whitelisted smartphones:

Code: Select all

server->getAdvertising()->setScanFilter(false,true);

BLESecurity *pSecurity = new BLESecurity();
pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_BOND);
pSecurity->setCapability(ESP_IO_CAP_NONE);
pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
After our button was pressed, we change this scan filter so that everyone can connect to it:

Code: Select all

server->getAdvertising()->setScanFilter(false,false);
After 30 seconds we change it back to the first filter.

We also add a custom GAP handler on our esp32 so that we get notified when a smartphone successfully paired with us after the button was pressed and everyone could connect to it. If there is such a smartphone, we add it to the whitelist:

Code: Select all

BLEDevice::setCustomGapHandler(my_gap_event_handler);
static void my_gap_event_handler(esp_gap_ble_cb_event_t  event, esp_ble_gap_cb_param_t* param) {
switch(event){
    case ESP_GAP_BLE_AUTH_CMPL_EVT:{
      BLEAddress address = BLEAddress(param->ble_security.auth_cmpl.bd_addr);
      BLEDevice::whiteListAdd(address);
      break;
   }   
}
This seems to work because after we added the smartphone to the whitelist our custom GAP handler gets notified with the event ESP_GAP_BLE_UPDATE_WHITELIST_COMPLETE_EVT ("When add or remove whitelist complete, the event comes")

After we reboot our esp32 our smartphone can successfully connect to it (filter: connect whitelist only, i.e. false & true). But after we disconnect with our smartphone we are not able to reconnect to our esp32. After another restart it works again for exactly one connect.

What are we missing here?
Last edited by degill on Wed May 08, 2019 7:34 am, edited 1 time in total.

chegewara
Posts: 2376
Joined: Wed Jun 14, 2017 9:00 pm

Re: Activate BLE Bonding and security with Button and show special services

Postby chegewara » Wed May 08, 2019 1:34 am

Hi,
there is/was issue with whitelisted devices connections/advertising in esp-idf and as far as i know it was not solved yet, but recently i saw that in master esp-idf add whitelisted devices function has been changed. This is good sign and maybe will fix that issue.

It is first time when i see that setting advertisement with filter to allow connect only whitelisted device works, even if it allows you to connect only one time after restart, so nicely done and thanks for update.

degill
Posts: 5
Joined: Mon Apr 29, 2019 11:17 am

Re: Activate BLE Bonding and security with Button and show special services

Postby degill » Wed May 08, 2019 7:34 pm

Hello chegewara and thank you for your reply! :)

I am using the CPP Utils library found here by nkolban: esp32-snippets.

I am interested in using the latest code from esp-idf, but I don't know how to combine the sources I can clone from their repository from here with the current sources from nkolban. I managed to build a .zip file from nkolbans sources and inlude them in the Arduino IDE. But how do I get to link them with the current sources from esp-idf?

Maybe this way we can stay up-to-date with any changes regarding our problems.

chegewara
Posts: 2376
Joined: Wed Jun 14, 2017 9:00 pm

Re: Activate BLE Bonding and security with Button and show special services

Postby chegewara » Thu May 09, 2019 6:17 pm

You can use this library like any other component.
Copy cpp_utils to somponents folder, add components.mk file (usually its empty file, but required), and thats it. Also you dont need all files from cpp_utils folder, some are for ble, some are just for other functions not related to ble.

Who is online

Users browsing this forum: Google [Bot] and 62 guests