Skip to content

BLE secure client/server not working as expected #7251

@sglvladi

Description

@sglvladi

Board

ESP32 LolinD32 Pro

Device Description

plain module

Hardware Configuration

Nothing connected

Version

v2.0.3

IDE Name

Arduino IDE

Operating System

Windows 10

Flash frequency

80MHz

PSRAM enabled

no

Upload speed

921600

Description

I am using the scripts for BLE security scripts found here to get an understanding of how the security callbacks are used.

My set-up is the following:

The sketches are pretty much the same as above, with some minor modifications to fix compilation errors:

  • I added #include "esp_log.h" for ESP_LOGI commands to work
  • I defined static const char* LOG_TAG = "XXXXXXXXX";

Both scripts use ESP_BLE_SEC_ENCRYPT Encryption Level, ESP_LE_AUTH_REQ_SC_ONLY Authentication Mode, and ESP_IO_CAP_IO capability.

Based on the above configuration, my understanding is that the onConfirmPIN() security callback should be triggered when pairing is initiated. I am basing my intuition off the fact that when I try to connect with the server on my phone using the nRFConnect App, I am being prompted to confirm a passcode. However, the client logs indicate that only the onSecurityRequest() callback is being triggered, and yet, the client is able to connect and read/write from/to the chosen characteristic.

Can someone shed some light on this? Is my understanding wrong and/or am I missing something?

Sketch

/**
   A BLE client example that is rich in capabilities.
*/

#include "BLEDevice.h"
//#include "BLEScan.h"
#include "esp_log.h"
static const char* LOG_TAG = "SampleClient";

// The remote service we wish to connect to.
static BLEUUID serviceUUID("4fafc201-1fb5-459e-8fcc-c5c9c331914b");
// The characteristic of the remote service we are interested in.
static BLEUUID    charUUID("beb5483e-36e1-4688-b7f5-ea07361b26a8");

static BLEAddress *pServerAddress;
static boolean doConnect = false;
static boolean connected = false;
static BLERemoteCharacteristic* pRemoteCharacteristic;

class MySecurity : public BLESecurityCallbacks {

    uint32_t onPassKeyRequest() {
      ESP_LOGI(LOG_TAG, "PassKeyRequest");
      return 123456;
    }
    void onPassKeyNotify(uint32_t pass_key) {
      ESP_LOGE(LOG_TAG, "The passkey Notify number:%d", pass_key);
    }
    bool onConfirmPIN(uint32_t pass_key) {
      ESP_LOGI(LOG_TAG, "The passkey YES/NO number:%d", pass_key);
      vTaskDelay(5000);
      return true;
    }
    bool onSecurityRequest() {
      ESP_LOGI(LOG_TAG, "Security Request");
      return true;
    }
    void onAuthenticationComplete(esp_ble_auth_cmpl_t auth_cmpl) {
      if (auth_cmpl.success) {
        ESP_LOGI(LOG_TAG, "remote BD_ADDR:");
        esp_log_buffer_hex(LOG_TAG, auth_cmpl.bd_addr, sizeof(auth_cmpl.bd_addr));
        ESP_LOGI(LOG_TAG, "address type = %d", auth_cmpl.addr_type);
      }
      ESP_LOGI(LOG_TAG, "pair status = %s", auth_cmpl.success ? "success" : "fail");
    }
};

static void notifyCallback(
  BLERemoteCharacteristic* pBLERemoteCharacteristic,
  uint8_t* pData,
  size_t length,
  bool isNotify) {
  Serial.print("Notify callback for characteristic ");
  Serial.print(pBLERemoteCharacteristic->getUUID().toString().c_str());
  Serial.print(" of data length ");
  Serial.println(length);
}

bool connectToServer(BLEAddress pAddress) {
  Serial.print("Forming a connection to ");
  Serial.println(pAddress.toString().c_str());

  BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT);
  BLEDevice::setSecurityCallbacks(new MySecurity());

  BLESecurity *pSecurity = new BLESecurity();
  pSecurity->setKeySize();
  pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_ONLY);
  pSecurity->setCapability(ESP_IO_CAP_IO);
  pSecurity->setRespEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
  BLEClient*  pClient  = BLEDevice::createClient();
  Serial.println(" - Created client");

  // Connect to the remove BLE Server.
  pClient->connect(pAddress);
  Serial.println(" - Connected to server");

  // Obtain a reference to the service we are after in the remote BLE server.
  BLERemoteService* pRemoteService = pClient->getService(serviceUUID);
  if (pRemoteService == nullptr) {
    Serial.print("Failed to find our service UUID: ");
    Serial.println(serviceUUID.toString().c_str());
    return false;
  }
  Serial.println(" - Found our service");


  // Obtain a reference to the characteristic in the service of the remote BLE server.
  pRemoteCharacteristic = pRemoteService->getCharacteristic(charUUID);
  if (pRemoteCharacteristic == nullptr) {
    Serial.print("Failed to find our characteristic UUID: ");
    Serial.println(charUUID.toString().c_str());
    return false;
  }
  Serial.println(" - Found our characteristic");

  // Read the value of the characteristic.
  std::string value = pRemoteCharacteristic->readValue();
  Serial.print("The characteristic value was: ");
  Serial.println(value.c_str());

  pRemoteCharacteristic->registerForNotify(notifyCallback);
  return true;
}
/**
   Scan for BLE servers and find the first one that advertises the service we are looking for.
*/
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
    /**
        Called for each advertising BLE server.
    */
    void onResult(BLEAdvertisedDevice advertisedDevice) {
      Serial.print("BLE Advertised Device found: ");
      Serial.println(advertisedDevice.toString().c_str());

      // We have found a device, let us now see if it contains the service we are looking for.
      if (advertisedDevice.getAddress().toString() == "30:ae:a4:19:21:22") {
        //    if (advertisedDevice.haveServiceUUID() && advertisedDevice.getServiceUUID().equals(serviceUUID)) {

        //
        Serial.print("Found our device!  address: ");
        advertisedDevice.getScan()->stop();

        pServerAddress = new BLEAddress(advertisedDevice.getAddress());
        doConnect = true;

      } // Found our server
    } // onResult
}; // MyAdvertisedDeviceCallbacks


void setup() {
  Serial.begin(115200);
  Serial.println("Starting Arduino BLE Client application...");
  BLEDevice::init("");

  // Retrieve a Scanner and set the callback we want to use to be informed when we
  // have detected a new device.  Specify that we want active scanning and start the
  // scan to run for 30 seconds.
  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true);
  pBLEScan->start(30);
} // End of setup.


// This is the Arduino main loop function.
void loop() {

  // If the flag "doConnect" is true then we have scanned for and found the desired
  // BLE Server with which we wish to connect.  Now we connect to it.  Once we are
  // connected we set the connected flag to be true.
  if (doConnect == true) {
    if (connectToServer(*pServerAddress)) {
      Serial.println("We are now connected to the BLE Server.");
      connected = true;
    } else {
      Serial.println("We have failed to connect to the server; there is nothin more we will do.");
    }
    doConnect = false;
  }

  // If we are connected to a peer BLE Server, update the characteristic each time we are reached
  // with the current time since boot.
  if (connected) {
    String newValue = "Time since boot: " + String(millis() / 1000);
    Serial.println("Setting new characteristic value to \"" + newValue + "\"");

    // Set the characteristic's value to be the array of bytes that is actually a string.
    pRemoteCharacteristic->writeValue(newValue.c_str(), newValue.length());
  }

  delay(1000); // Delay a second between loops.
} // End of loop

Debug Message

Starting Arduino BLE Client application...
BLE Advertised Device found: Name: , Address: 54:94:94:87:42:95, manufacturer data: e000017aca300f2a, serviceUUID: 0000fe9f-0000-1000-8000-00805f9b34fb
BLE Advertised Device found: Name: , Address: 49:09:09:55:a2:e9, manufacturer data: e000016fca904f0e, serviceUUID: 0000fe9f-0000-1000-8000-00805f9b34fb
BLE Advertised Device found: Name: , Address: 56:96:96:41:35:21, manufacturer data: e0000174ca57ad67, serviceUUID: 0000fe9f-0000-1000-8000-00805f9b34fb
BLE Advertised Device found: Name: F8B3C50D11EE33AAE9, Address: cd:4d:dd:ca:34:17, appearance: 0, manufacturer data: a705051001000000000000022200ca, serviceUUID: 0000fe07-0000-1000-8000-00805f9b34fb, txPower: 0
BLE Advertised Device found: Name: ESP32, Address: 30:ae:a4:19:21:22, txPower: 3
Found our device!  address: Forming a connection to 30:ae:a4:19:21:22
 - Created client
[   795][I][BLEDevice.cpp:622] addPeerDevice(): add conn_id: 0, GATT role: client
lld_pdu_get_tx_flush_nb HCI packet count mismatch (0, 1)
[   983][I][BLEDevice.cpp:222] gapEventHandler(): ESP_GAP_BLE_SEC_REQ_EVT
[   983][I][ESP32_BLE_CLIENT_SECURE.ino:35] onSecurityRequest(): Security Request
 - Connected to server
[  1384][I][BLEDevice.cpp:249] gapEventHandler(): key type = ESP_LE_KEY_LENC
[  1385][I][BLEDevice.cpp:249] gapEventHandler(): key type = ESP_LE_KEY_PENC
[  1387][I][BLEDevice.cpp:253] gapEventHandler(): ESP_GAP_BLE_AUTH_CMPL_EVT
[  1394][I][ESP32_BLE_CLIENT_SECURE.ino:40] onAuthenticationComplete(): remote BD_ADDR:
[  1401][I][ESP32_BLE_CLIENT_SECURE.ino:42] onAuthenticationComplete(): address type = 0
[  1409][I][ESP32_BLE_CLIENT_SECURE.ino:44] onAuthenticationComplete(): pair status = success
 - Found our service
[  1687][E][BLERemoteCharacteristic.cpp:287] retrieveDescriptors(): esp_ble_gattc_get_all_descr: Unknown
 - Found our characteristic
The characteristic value was: Hello World says Neil
We are now connected to the BLE Server.

Other Steps to Reproduce

No response

I have checked existing issues, online documentation and the Troubleshooting Guide

  • I confirm I have checked existing issues, online documentation and Troubleshooting guide.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions