Skip to content

ESP32 BLE Security #793

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
mpbejo opened this issue Jan 23, 2019 · 49 comments
Closed

ESP32 BLE Security #793

mpbejo opened this issue Jan 23, 2019 · 49 comments

Comments

@mpbejo
Copy link

mpbejo commented Jan 23, 2019

Hi everybody,
I trying to understand how BLE security works on ESP32 and I saw something strange for me.
I am using :
Arduino IDE 1.8.8
ESP32 1.0.0 Espressif Systems board library
ESP32 BLE Arduino 1.0.1 library by Neil Kolban
I downloaded:
BLE_server_passkey.ino

I tried to connect with two Android Smartphone:
First Vodafone Smart Ultra 6 (Android 6.0.1)
When I try to connect with nRF Connect App I have write the passkey as I expected, here the log:

[D][BLEDevice.cpp:104] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... Unknown
[D][BLEServer.cpp:153] handleGATTServerEvent(): >> handleGATTServerEvent: Unknown
[D][BLECharacteristic.cpp:203] handleGATTServerEvent(): >> handleGATTServerEvent: Unknown
[D][BLECharacteristic.cpp:459] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEServer.cpp:280] handleGATTServerEvent(): << handleGATTServerEvent
[I][BLEDevice.cpp:239] gapEventHandler(): ESP_GAP_BLE_PASSKEY_NOTIF_EVT
[I][BLEDevice.cpp:241] gapEventHandler(): passKey = 756464
[I][BLE_server_passkey.ino:23] onPassKeyNotify(): The passkey Notify number:756464
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 11]
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]
[D][BLEDevice.cpp:249] gapEventHandler(): ESP_GAP_BLE_KEY_EVT
[I][BLEDevice.cpp:251] gapEventHandler(): key type = ESP_LE_KEY_LENC
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 9]
[D][BLEDevice.cpp:249] gapEventHandler(): ESP_GAP_BLE_KEY_EVT
[I][BLEDevice.cpp:251] gapEventHandler(): key type = ESP_LE_KEY_PENC
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 9]
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]
[I][BLEDevice.cpp:255] gapEventHandler(): ESP_GAP_BLE_AUTH_CMPL_EVT
[I][BLE_server_passkey.ino:36] onAuthenticationComplete(): Starting BLE work!

Second HUAWEI GRA-L09 (HUAWEI P8) (Android 6.0)
When I try to connect with nRF Connect App I can connect without writing the passkey, here the log:
[D][BLEDevice.cpp:104] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... Unknown
[D][BLEServer.cpp:153] handleGATTServerEvent(): >> handleGATTServerEvent: Unknown
[D][BLECharacteristic.cpp:203] handleGATTServerEvent(): >> handleGATTServerEvent: Unknown
[D][BLECharacteristic.cpp:459] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEServer.cpp:280] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]
[I][BLEDevice.cpp:255] gapEventHandler(): ESP_GAP_BLE_AUTH_CMPL_EVT
[I][BLE_server_passkey.ino:36] onAuthenticationComplete(): Starting BLE work!

Any idea?
Best Regards
Marco

@mpbejo
Copy link
Author

mpbejo commented Jan 29, 2019

Hi chegewara, I think I found the solution.
In another forum I ask if is it possible on Arduino to set a static passkey (123456) as in ESP-IDF and You suggest me to use this sample:
https://github.com/espressif/esp-idf/blob/3c94b6e10a471223616564bfc9b9c88232e749e6/examples/bluetooth/gatt_security_server/main/example_ble_sec_gatts_demo.c#L555-L575

I tried to implement on Arduino BLE library all the missing things so I added in the file BLESecurity.h:
on public
void setPassKey(uint32_t passKey);
void setSpecifiedSecAuth(uint8_t auth_option);
void setOobSupport(uint8_t oob_support);
on private
uint32_t m_passKey;
uint8_t m_auth_option;
uint8_t m_oob_support;

In the file BLESecurity.cpp i added:
void BLESecurity::setPassKey(uint32_t passKey) {
m_passKey = passKey;
esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &m_passKey, sizeof(uint32_t));
} // setPasskey

void BLESecurity::setSpecifiedSecAuth(uint8_t auth_option) {
m_auth_option = auth_option;
esp_ble_gap_set_security_param(ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH, &m_auth_option, sizeof(uint8_t));
} // setSpecifiedSecAuth

void BLESecurity::setOobSupport(uint8_t oob_support) {
m_oob_support = oob_support;
esp_ble_gap_set_security_param(ESP_BLE_SM_OOB_SUPPORT, &m_oob_support, sizeof(uint8_t));
}// setOobSupport

And in the esp_gap_ble_api.h
I added:
ESP_BLE_SM_SET_STATIC_PASSKEY,
ESP_BLE_SM_CLEAR_STATIC_PASSKEY,
ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH,
ESP_BLE_SM_OOB_SUPPORT,
ESP_BLE_SM_MAX_PARAM,
on the
typedef enum {
ESP_BLE_SM_PASSKEY = 0,
ESP_BLE_SM_AUTHEN_REQ_MODE,
ESP_BLE_SM_IOCAP_MODE,
ESP_BLE_SM_SET_INIT_KEY,
ESP_BLE_SM_SET_RSP_KEY,
ESP_BLE_SM_MAX_KEY_SIZE,
} esp_ble_sm_param_t;

And always on esp_gap_ble_api.h

#define ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_DISABLE 0
#define ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_ENABLE 1

#define ESP_BLE_OOB_DISABLE 0
#define ESP_BLE_OOB_ENABLE 1

or should be better to update the old file with:
https://github.com/espressif/esp-idf/blob/44b97b7/components/bt/bluedroid/api/include/api/esp_gap_ble_api.h

I updated the BLE_server_passkey.ino:
uint8_t key_size = 16;
uint32_t passkey = 123456;
BLESecurity *pSecurity = new BLESecurity();
pSecurity->setPassKey(passkey);
pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_MITM_BOND);
pSecurity->setCapability(ESP_IO_CAP_NONE);
pSecurity->setKeySize(key_size);
pSecurity->setSpecifiedSecAuth(ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_DISABLE);
pSecurity->setOobSupport(ESP_BLE_OOB_DISABLE);
pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);
pSecurity->setRespEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);

The result is the static passkey is not working (when I try to connect with nRF the connection is done without passkey), but if I change
pSecurity->setCapability(ESP_IO_CAP_OUT);
now I have to write the random generated passkey on every smartphone that I try, also on IPhone XS (previously it connected without asking for the passkey)

So I think is solved the problem that I had about security connection using random passkey, now I have to understand what to do to use static passkey.
Any suggestion is really appreciated
Thank You
Best Regards
Marco

@chegewara
Copy link
Collaborator

Hi,
its not working because i forgot to mention that you need to change this line:
pSecurity->setCapability(ESP_IO_CAP_NONE);

It should be ESP_IO_CAP_IO if i remember.

@mpbejo
Copy link
Author

mpbejo commented Jan 29, 2019

Unfortunately ESP_IO_CAP_IO is not the solution

I tried and I have to input a random passkey to connect.

[D][BLEDevice.cpp:104] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... Unknown
[D][BLEServer.cpp:153] handleGATTServerEvent(): >> handleGATTServerEvent: Unknown
[D][BLECharacteristic.cpp:203] handleGATTServerEvent(): >> handleGATTServerEvent: Unknown
[D][BLECharacteristic.cpp:459] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEServer.cpp:280] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]
[I][BLEDevice.cpp:239] gapEventHandler(): ESP_GAP_BLE_PASSKEY_NOTIF_EVT
[I][BLEDevice.cpp:241] gapEventHandler(): passKey = 633097
[I][Test_Passkey.ino:25] onPassKeyNotify(): On passkey Notify number:633097
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 11]
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]
[D][BLEDevice.cpp:249] gapEventHandler(): ESP_GAP_BLE_KEY_EVT
[I][BLEDevice.cpp:251] gapEventHandler(): key type = ESP_LE_KEY_LENC
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 9]
[D][BLEDevice.cpp:249] gapEventHandler(): ESP_GAP_BLE_KEY_EVT
[I][BLEDevice.cpp:251] gapEventHandler(): key type = ESP_LE_KEY_LID
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 9]
[D][BLEDevice.cpp:249] gapEventHandler(): ESP_GAP_BLE_KEY_EVT
[I][BLEDevice.cpp:251] gapEventHandler(): key type = ESP_LE_KEY_PENC
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 9]
[D][BLEDevice.cpp:249] gapEventHandler(): ESP_GAP_BLE_KEY_EVT
[I][BLEDevice.cpp:251] gapEventHandler(): key type = ESP_LE_KEY_PID
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 9]
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]
[I][BLEDevice.cpp:255] gapEventHandler(): ESP_GAP_BLE_AUTH_CMPL_EVT
[I][Test_Passkey.ino:34] onAuthenticationComplete(): Starting BLE work!
[D][Test_Passkey.ino:38] onAuthenticationComplete(): size: 12
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 8]
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]
[D][BLEDevice.cpp:559] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]

@chegewara
Copy link
Collaborator

chegewara commented Jan 29, 2019

Try this:

pSecurity->setCapability(ESP_IO_CAP_OUT);
pSecurity->setKeySize(key_size);
pSecurity->setSpecifiedSecAuth(ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_ENABLE);

I know static passkey is working because i tested it months ago when it was added to esp-idf.

@mpbejo
Copy link
Author

mpbejo commented Jan 29, 2019

Tried same result.
I am sure that works on esp-idf, and I am sure that is my fault.
I hope it is not disturbing for you I attach my files if You can check it, if works could be useful for other people the static passkey
Thank You
Marco
Test_Passkey.zip

@chegewara
Copy link
Collaborator

chegewara commented Jan 30, 2019

Hi,
like i said, its not too hard. Its my log:

14:38:33.320 -> [E][BLECharacteristicMap.cpp:87] handleGATTServerEvent(): 42
14:38:33.320 -> [E][BLECharacteristicMap.cpp:87] handleGATTServerEvent(): 42
14:38:33.320 -> [I][BLEDevice.cpp:555] getAdvertising(): create advertising
14:38:33.320 -> Characteristic defined! Now you can read it in your phone!
14:38:45.052 -> [E][BLECharacteristicMap.cpp:87] handleGATTServerEvent(): 42
14:38:46.730 -> [I][BLEDevice.cpp:241] gapEventHandler(): ESP_GAP_BLE_PASSKEY_NOTIF_EVT
14:38:46.730 -> [I][BLEDevice.cpp:243] gapEventHandler(): passKey = 123456
14:38:46.730 -> [I][sketch_jan30b.ino:23] onPassKeyNotify(): The passkey Notify number:123456
14:38:54.915 -> [I][BLEDevice.cpp:253] gapEventHandler(): key type = ESP_LE_KEY_LENC
14:38:54.915 -> [I][BLEDevice.cpp:253] gapEventHandler(): key type = ESP_LE_KEY_PENC
14:38:54.915 -> [I][BLEDevice.cpp:253] gapEventHandler(): key type = ESP_LE_KEY_LID
14:38:55.009 -> [I][BLEDevice.cpp:253] gapEventHandler(): key type = ESP_LE_KEY_PID
14:38:55.009 -> [I][BLEDevice.cpp:257] gapEventHandler(): ESP_GAP_BLE_AUTH_CMPL_EVT
14:38:55.009 -> [I][sketch_jan30b.ino:36] onAuthenticationComplete(): Starting BLE work!

Replace this code:
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLETests/Arduino/security/BLE_server/BLE_server_numeric_confirmation/BLE_server_numeric_confirmation.ino#L63-L67
with this code:
https://github.com/espressif/esp-idf/blob/3c94b6e10a471223616564bfc9b9c88232e749e6/examples/bluetooth/gatt_security_server/main/example_ble_sec_gatts_demo.c#L555-L575

/*
    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"

class MySecurity : public BLESecurityCallbacks {

  uint32_t onPassKeyRequest(){
        ESP_LOGI(LOG_TAG, "PassKeyRequest");
    return 123456;
  }
  void onPassKeyNotify(uint32_t pass_key){
        ESP_LOGI(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, "SecurityRequest");
    return true;
  }

  void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl){
    ESP_LOGI(LOG_TAG, "Starting BLE work!");
  }
};

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

  BLEDevice::init("ESP32");
  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();
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE
                                       );

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

    esp_ble_auth_req_t auth_req = ESP_LE_AUTH_REQ_SC_MITM_BOND;     //bonding with peer device after authentication
    esp_ble_io_cap_t iocap = ESP_IO_CAP_OUT;           //set the IO capability to No output No input
    uint8_t key_size = 16;      //the key size should be 7~16 bytes
    uint8_t init_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
    uint8_t rsp_key = ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK;
    //set static passkey
    uint32_t passkey = 123456;
    uint8_t auth_option = ESP_BLE_ONLY_ACCEPT_SPECIFIED_AUTH_DISABLE;
    uint8_t oob_support = ESP_BLE_OOB_DISABLE;
    esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint32_t));
    esp_ble_gap_set_security_param(ESP_BLE_SM_AUTHEN_REQ_MODE, &auth_req, sizeof(uint8_t));
    esp_ble_gap_set_security_param(ESP_BLE_SM_IOCAP_MODE, &iocap, sizeof(uint8_t));
    esp_ble_gap_set_security_param(ESP_BLE_SM_MAX_KEY_SIZE, &key_size, sizeof(uint8_t));
    esp_ble_gap_set_security_param(ESP_BLE_SM_ONLY_ACCEPT_SPECIFIED_SEC_AUTH, &auth_option, sizeof(uint8_t));
//    esp_ble_gap_set_security_param(ESP_BLE_SM_OOB_SUPPORT, &oob_support, sizeof(uint8_t));
    /* If your BLE device act as a Slave, the init_key means you hope which types of key of the master should distribut to you,
    and the response key means which key you can distribut to the Master;
    If your BLE device act as a master, the response key means you hope which types of key of the slave should distribut to you,
    and the init key means which key you can distribut to the slave. */
    esp_ble_gap_set_security_param(ESP_BLE_SM_SET_INIT_KEY, &init_key, sizeof(uint8_t));
    esp_ble_gap_set_security_param(ESP_BLE_SM_SET_RSP_KEY, &rsp_key, sizeof(uint8_t));
  Serial.println("Characteristic defined! Now you can read it in your phone!");
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(2000);
}

I will try to add it to BLESecurity.

@chegewara
Copy link
Collaborator

chegewara commented Jan 30, 2019

This is minimal code required to connect with static PIN:

/*
    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"

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

  BLEDevice::init("ESP32");
  /*
   * Required in authentication process to provide displaying and/or input passkey or yes/no butttons confirmation
   */
  BLEServer *pServer = BLEDevice::createServer();
  BLEService *pService = pServer->createService(SERVICE_UUID);
  BLECharacteristic *pCharacteristic = pService->createCharacteristic(
                                         CHARACTERISTIC_UUID,
                                         BLECharacteristic::PROPERTY_READ |
                                         BLECharacteristic::PROPERTY_WRITE
                                       );
  pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
  pCharacteristic->setValue("Hello World says Neil");
  pService->start();
  BLEAdvertising *pAdvertising = pServer->getAdvertising();
  pAdvertising->start();

  BLESecurity *pSecurity = new BLESecurity();
  pSecurity->setStaticPIN(123456); 
  
  //set static passkey
  Serial.println("Characteristic defined! Now you can read it in your phone!");
}

void loop() {
  // put your main code here, to run repeatedly:
  delay(2000);
}

when you add this code to BLESecurity.cpp:

/**
 * Setup for static PIN connection
 */
void BLESecurity::setStaticPIN(uint32_t pin){
    uint32_t passkey = pin;
    esp_ble_gap_set_security_param(ESP_BLE_SM_SET_STATIC_PASSKEY, &passkey, sizeof(uint32_t));
    setCapability(ESP_IO_CAP_OUT);
}

PS im not sure that minimalist approach in this case is good

@mpbejo
Copy link
Author

mpbejo commented Jan 31, 2019

I found the problem.
It was the ESP32 1.0.0 Espressif Systems board library.
After upgraded to ESP32 1.0.1 I can use the static passkey.
I also tried my modified BLESecurity.cpp and BLESecurity.h with my Test_Passkey.ino and now work correctly.
ThankYou
Best Regards
Marco

@mpbejo
Copy link
Author

mpbejo commented Feb 1, 2019

After successfully connected with security one ESP32 and an Android smartphone I tried to connect using security two ESP32 I used for server:
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLETests/Arduino/security/BLE_server/BLE_server_passkey/BLE_server_passkey.ino

and for client:
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLETests/Arduino/security/BLE_client/BLE_client_passkey/BLE_client_passkey.ino
I only commented the line 38 esp_log_buffer_hex(LOG_TAG, auth_cmpl.bd_addr, sizeof(auth_cmpl.bd_addr)); for an error
and copy and pasted the serviceUUID and charUUID from the server to the client .
The result is the client never connect to the server as if never find the correct service and characteristics.
Here the client Log:

Starting Arduino BLE Client application...
[D][BLEScan.cpp:204] start(): >> start(duration=30)
[D][FreeRTOS.cpp:165] take(): Semaphore taking: name: ScanEnd (0x3ffdf018), owner: <N/A> for start
[D][FreeRTOS.cpp:174] take(): Semaphore taken: name: ScanEnd (0x3ffdf018), owner: start
[D][BLEScan.cpp:236] start(): << start()
[D][BLEAdvertisedDevice.cpp:424] setRSSI(): - setRSSI(): rssi: -75
[D][BLEAdvertisedDevice.cpp:253] parseAdvertisement(): Type: 0x01 (), length: 1, data: 1a
[D][BLEAdvertisedDevice.cpp:253] parseAdvertisement(): Type: 0xff (), length: 9, data: 4c001005031893a971
[D][BLEAdvertisedDevice.cpp:401] setManufacturerData(): - manufacturer data: 4c001005031893a971
BLE Advertised Device found: Name: , Address: 66:3d:a7:0e:ed:a7, manufacturer data: 4c001005031893a971
[D][BLEAdvertisedDevice.cpp:424] setRSSI(): - setRSSI(): rssi: -57
[D][BLEAdvertisedDevice.cpp:253] parseAdvertisement(): Type: 0x01 (), length: 1, data: 06
[D][BLEAdvertisedDevice.cpp:253] parseAdvertisement(): Type: 0x12 (), length: 4, data: 20004000
[D][BLEAdvertisedDevice.cpp:349] parseAdvertisement(): Unhandled type: adType: 18 - 0x12
[D][BLEAdvertisedDevice.cpp:253] parseAdvertisement(): Type: 0x01 (), length: 1, data: 06
[D][BLEAdvertisedDevice.cpp:253] parseAdvertisement(): Type: 0x09 (), length: 5, data: 4553503332
[D][BLEAdvertisedDevice.cpp:413] setName(): - setName(): name: ESP32
[D][BLEAdvertisedDevice.cpp:253] parseAdvertisement(): Type: 0x0a (), length: 1, data: 03
[D][BLEAdvertisedDevice.cpp:484] setTXPower(): - txPower: 3
[D][BLEAdvertisedDevice.cpp:253] parseAdvertisement(): Type: 0x12 (), length: 4, data: 20004000
[D][BLEAdvertisedDevice.cpp:349] parseAdvertisement(): Unhandled type: adType: 18 - 0x12
BLE Advertised Device found: Name: ESP32, Address: 24:0a:c4:9b:c4:be, txPower: 3
[D][BLEScan.cpp:106] handleGAPEvent(): Ignoring 24:0a:c4:9b:c4:be, already seen it.
[D][BLEScan.cpp:106] handleGAPEvent(): Ignoring 24:0a:c4:9b:c4:be, already seen it.
[D][BLEScan.cpp:106] handleGAPEvent(): Ignoring 24:0a:c4:9b:c4:be, already seen it.
[D][BLEScan.cpp:106] handleGAPEvent(): Ignoring 24:0a:c4:9b:c4:be, already seen it.
[D][BLEScan.cpp:106] handleGAPEvent(): Ignoring 24:0a:c4:9b:c4:be, already seen it.
[D][BLEScan.cpp:106] handleGAPEvent(): Ignoring 66:3d:a7:0e:ed:a7, already seen it.
[W][BLEScan.cpp:78] handleGAPEvent(): ESP_GAP_SEARCH_INQ_CMPL_EVT

Could You confirm the same result if You try? Or tell me what I am doing wrong?
Best regards
Marco

@mpbejo
Copy link
Author

mpbejo commented Feb 1, 2019

Yes there is. I copied and pasted all the code
And during scanning I see the ESP32 but the client does not connect

@chegewara
Copy link
Collaborator

@mpbejo
Copy link
Author

mpbejo commented Feb 5, 2019

Ok I understood what You mean.
Now the service is correctly advertised and the client connect, but after the connection ( no passkey requested ) the client restart with this error:
assertion "heap != NULL && "free() target pointer is outside heap areas"" failed: file "/Users/ficeto/Desktop/ESP32/ESP32/esp-idf-public/components/heap/heap_caps.c", line 268, function: heap_caps_free

I though that problem was the new security implementation, so I tried the standard client server samples but I have the same error.
I rolled back to the previous ESP32 Board Library 1.0.0 and the sample works!.
But with this version the static passkey does not work!

@chegewara
Copy link
Collaborator

@mpbejo
Copy link
Author

mpbejo commented Feb 6, 2019

I searched on the forum about the problem and I found:
espressif/arduino-esp32#2308
I solved "heap_caps_free" commenting the lines BLERemoteCharacteristic.cpp#L192-L194 as You suggested
then I had BLEclient readValue() crash
as #794
And I solved downloading from github: esp32-snippets/cpp_utils

Next I will continue to test how to connect two esp32 with security

@mpbejo
Copy link
Author

mpbejo commented Feb 7, 2019

In these days, I tried to connect to ESP32 using security one as server and one as client, my goal was that the server provide a passkey (random for now) and the client connect using this passkey like works with a smartphone
For this purpose I downloaded:
https://github.com/nkolban/esp32-snippets/tree/master/cpp_utils/tests/BLETests/Arduino/security/BLE_server/BLE_server_passkey
and
https://github.com/nkolban/esp32-snippets/tree/master/cpp_utils/tests/BLETests/Arduino/security/BLE_client/BLE_client_passkey
i set the same SERVICE_UUID and CHARACTERISTIC_UUID in both sketch and add on the server
pAdvertising->addServiceUUID(SERVICE_UUID); so the client can find the right service during scan.

To make the server provide a password I wrote:

BLESecurity *pSecurity = new BLESecurity();
pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_MITM_BOND);
pSecurity->setCapability(ESP_IO_CAP_OUT);
pSecurity->setInitEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);

When I try to connect with a smartphone i prompted to insert the passkey, if I write the wrong password I cannot read and write the characteristics.
this is the LOG of the server side:
D][BLEDevice.cpp:106] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_CONNECT_EVT
[D][BLEServer.cpp:154] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_CONNECT_EVT
[D][BLECharacteristic.cpp:203] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_CONNECT_EVT
[D][BLECharacteristic.cpp:466] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEServer.cpp:281] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]
[I][BLEDevice.cpp:241] gapEventHandler(): ESP_GAP_BLE_PASSKEY_NOTIF_EVT
[I][BLEDevice.cpp:243] gapEventHandler(): passKey = 420221
[I][BLE_Server_Passkey_base.ino:28] onPassKeyNotify(): On passkey Notify number:420221
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 11]
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]
[D][BLEDevice.cpp:251] gapEventHandler(): ESP_GAP_BLE_KEY_EVT
[I][BLEDevice.cpp:253] gapEventHandler(): key type = ESP_LE_KEY_LENC
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 9]
[D][BLEDevice.cpp:251] gapEventHandler(): ESP_GAP_BLE_KEY_EVT
[I][BLEDevice.cpp:253] gapEventHandler(): key type = ESP_LE_KEY_LID
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 9]
[D][BLEDevice.cpp:251] gapEventHandler(): ESP_GAP_BLE_KEY_EVT
[I][BLEDevice.cpp:253] gapEventHandler(): key type = ESP_LE_KEY_LCSRK
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 9]
[D][BLEDevice.cpp:251] gapEventHandler(): ESP_GAP_BLE_KEY_EVT
[I][BLEDevice.cpp:253] gapEventHandler(): key type = ESP_LE_KEY_PENC
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 9]
[D][BLEDevice.cpp:251] gapEventHandler(): ESP_GAP_BLE_KEY_EVT
[I][BLEDevice.cpp:253] gapEventHandler(): key type = ESP_LE_KEY_PID
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 9]
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]
[I][BLEDevice.cpp:257] gapEventHandler(): ESP_GAP_BLE_AUTH_CMPL_EVT
[I][BLE_Server_Passkey_base.ino:37] onAuthenticationComplete(): Starting BLE work!
[D][BLE_Server_Passkey_base.ino:41] onAuthenticationComplete(): size: 12
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 8]
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]

This is what I did with ESP32 client to connect to the server:

BLESecurity *pSecurity = new BLESecurity();
pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_MITM_BOND);
pSecurity->setCapability(ESP_IO_CAP_IN);
pSecurity->setRespEncryptionKey(ESP_BLE_ENC_KEY_MASK | ESP_BLE_ID_KEY_MASK);

I set ESP_IO_CAP_IN (I tried also ESP_IO_CAP_KBDISP) because on this side I have to write the passkey provided from the server.

here the LOG Server side:
[D][BLEDevice.cpp:106] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_CONNECT_EVT
[D][BLEServer.cpp:154] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_CONNECT_EVT
[D][BLECharacteristic.cpp:203] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_CONNECT_EVT
[D][BLECharacteristic.cpp:466] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEServer.cpp:281] handleGATTServerEvent(): << handleGATTServerEvent
[I][BLEDevice.cpp:241] gapEventHandler(): ESP_GAP_BLE_PASSKEY_NOTIF_EVT
[I][BLEDevice.cpp:243] gapEventHandler(): passKey = 693384
[I][BLE_Server_Passkey_base.ino:28] onPassKeyNotify(): On passkey Notify number:693384
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 11]
[I][BLEDevice.cpp:257] gapEventHandler(): ESP_GAP_BLE_AUTH_CMPL_EVT
[I][BLE_Server_Passkey_base.ino:37] onAuthenticationComplete(): Starting BLE work!
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 8]
[D][BLEDevice.cpp:106] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_MTU_EVT
[D][BLEServer.cpp:154] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_MTU_EVT
[D][BLECharacteristic.cpp:203] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_MTU_EVT
[D][BLECharacteristic.cpp:466] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEServer.cpp:281] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEDevice.cpp:106] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_READ_EVT
[D][BLEServer.cpp:154] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_READ_EVT
[D][BLECharacteristic.cpp:203] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_READ_EVT
[D][BLECharacteristic.cpp:368] handleGATTServerEvent(): mtu value: 516
[D][BLECharacteristic.cpp:370] handleGATTServerEvent(): Sending a response (esp_ble_gatts_send_response)
[D][BLECharacteristic.cpp:417] handleGATTServerEvent(): - Data: length=21, data=48656c6c6f20576f726c642073617973204e65696c, offset=0
[D][BLECharacteristic.cpp:466] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEServer.cpp:281] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEDevice.cpp:106] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_RESPONSE_EVT
[D][BLEServer.cpp:154] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_RESPONSE_EVT
[D][BLECharacteristic.cpp:203] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_RESPONSE_EVT
[D][BLECharacteristic.cpp:466] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEServer.cpp:281] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEDevice.cpp:106] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_WRITE_EVT
[D][BLEServer.cpp:154] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_WRITE_EVT
[D][BLECharacteristic.cpp:203] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_WRITE_EVT
[D][BLECharacteristic.cpp:639] setValue(): >> setValue: length=18, data=54696d652073696e636520626f6f743a2033, characteristic UUID=beb5483e-36e1-4688-b7f5-ea07361b26a8
[D][BLECharacteristic.cpp:646] setValue(): << setValue

as You can see when the client try to connect on the server side there is correctly an ESP_GAP_BLE_PASSKEY_NOTIF_EVT
and after ESP_GAP_BLE_AUTH_CMPL_EVT but I have not written the passkey on the client,
and above all the client start to write on the server characteristcs.

here the LOG Client side:
BLE Advertised Device found: Name: ESP32, Address: 24:0a:c4:9b:c4:be, serviceUUID: 4fafc201-1fb5-459e-8fcc-c5c9c331914b, txPower: 3
Found our device! address: [D][BLEScan.cpp:260] stop(): >> stop()
[D][BLEScan.cpp:272] stop(): << stop()
Forming a connection to 24:0a:c4:9b:c4:be
[D][BLEDevice.cpp:64] createClient(): >> createClient
[I][BLEDevice.cpp:594] addPeerDevice(): add conn_id: 0, GATT role: client
[D][FreeRTOS.cpp:164] take(): Semaphore taking: name: RegEvt (0x3ffdfdac), owner: <N/A> for connect
[D][FreeRTOS.cpp:173] take(): Semaphore taken: name: RegEvt (0x3ffdfdac), owner: connect
[D][BLEDevice.cpp:152] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_REG_EVT
[D][BLEClient.cpp:170] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_REG_EVT
[I][BLEClient.cpp:242] gattClientEventHandler(): register app id: 0, 0, gattc_if: 4
[D][BLEDevice.cpp:70] createClient(): << createClient
[D][BLEClient.cpp:121] connect(): >> connect(24:0a:c4:9b:c4:be)
[D][BLEClient.cpp:95] clearServices(): >> clearServices
[D][BLEClient.cpp:103] clearServices(): << clearServices
[D][FreeRTOS.cpp:164] take(): Semaphore taking: name: OpenEvt (0x3ffdfec8), owner: <N/A> for connect
[D][FreeRTOS.cpp:173] take(): Semaphore taken: name: OpenEvt (0x3ffdfec8), owner: connect
[D][BLEDevice.cpp:152] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_CONNECT_EVT
[D][BLEClient.cpp:170] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_CONNECT_EVT
[D][BLEDevice.cpp:578] updatePeerDevice(): update conn_id: 4, GATT role: client
[D][BLEDevice.cpp:152] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_OPEN_EVT
[D][BLEClient.cpp:170] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_OPEN_EVT
[D][BLEClient.cpp:140] connect(): << connect(), rc=1
[I][BLEDevice.cpp:226] gapEventHandler(): ESP_GAP_BLE_SEC_REQ_EVT
[I][BLE_Client_Passkey_base.ino:32] onSecurityRequest(): Security Request
[D][BLEClient.cpp:404] getService(): >> getService: uuid: 4fafc201-1fb5-459e-8fcc-c5c9c331914b
[D][BLEClient.cpp:440] getServices(): >> getServices
[D][BLEClient.cpp:95] clearServices(): >> clearServices
[D][BLEClient.cpp:103] clearServices(): << clearServices
[D][FreeRTOS.cpp:164] take(): Semaphore taking: name: SearchCmplEvt (0x3ffdff28), owner: <N/A> for getServices
[D][FreeRTOS.cpp:173] take(): Semaphore taken: name: SearchCmplEvt (0x3ffdff28), owner: getServices
[I][BLEDevice.cpp:212] gapEventHandler(): ESP_GAP_BLE_PASSKEY_REQ_EVT:
[I][BLEDevice.cpp:257] gapEventHandler(): ESP_GAP_BLE_AUTH_CMPL_EVT
[I][BLE_Client_Passkey_base.ino:41] onAuthenticationComplete(): pair status = fail
[D][BLEDevice.cpp:152] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_SEARCH_RES_EVT
[D][BLEClient.cpp:170] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_SEARCH_RES_EVT
[D][BLERemoteService.cpp:32] BLERemoteService(): >> BLERemoteService()
[D][BLERemoteService.cpp:40] BLERemoteService(): << BLERemoteService()
[D][BLEDevice.cpp:152] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_SEARCH_RES_EVT
[D][BLEClient.cpp:170] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_SEARCH_RES_EVT
[D][BLERemoteService.cpp:32] BLERemoteService(): >> BLERemoteService()
[D][BLERemoteService.cpp:40] BLERemoteService(): << BLERemoteService()
[D][BLEDevice.cpp:152] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_SEARCH_RES_EVT
[D][BLEClient.cpp:170] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_SEARCH_RES_EVT
[D][BLERemoteService.cpp:32] BLERemoteService(): >> BLERemoteService()
[D][BLERemoteService.cpp:40] BLERemoteService(): << BLERemoteService()
[D][BLEDevice.cpp:152] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_SEARCH_CMPL_EVT
[D][BLEClient.cpp:170] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_SEARCH_CMPL_EVT
[D][BLEClient.cpp:457] getServices(): << getServices
[D][BLEDevice.cpp:152] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_CFG_MTU_EVT
[D][BLEClient.cpp:417] getService(): << getService: found the service with uuid: 4fafc201-1fb5-459e-8fcc-c5c9c331914b
[D][BLEClient.cpp:170] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_CFG_MTU_EVT
[D][BLERemoteService.cpp:122] retrieveCharacteristics(): >> retrieveCharacteristics() for service: 4fafc201-1fb5-459e-8fcc-c5c9c331914b
[D][BLERemoteService.cpp:153] retrieveCharacteristics(): Found a characteristic: Handle: 42, UUID: beb5483e-36e1-4688-b7f5-ea07361b26a8
[D][BLERemoteCharacteristic.cpp:43] BLERemoteCharacteristic(): >> BLERemoteCharacteristic: handle: 42 0x42, uuid: beb5483e-36e1-4688-b7f5-ea07361b26a8
[D][BLERemoteCharacteristic.cpp:257] retrieveDescriptors(): >> retrieveDescriptors() for characteristic: beb5483e-36e1-4688-b7f5-ea07361b26a8
[D][BLERemoteCharacteristic.cpp:301] retrieveDescriptors(): << retrieveDescriptors(): Found 0 descriptors.
[D][BLERemoteCharacteristic.cpp:51] BLERemoteCharacteristic(): << BLERemoteCharacteristic
[D][BLERemoteService.cpp:169] retrieveCharacteristics(): << retrieveCharacteristics()

  • Found our characteristic
    [D][BLERemoteCharacteristic.cpp:405] readValue(): >> readValue(): uuid: beb5483e-36e1-4688-b7f5-ea07361b26a8, handle: 42 0x2a
    [D][FreeRTOS.cpp:164] take(): Semaphore taking: name: ReadCharEvt (0x3ffe0ddc), owner: <N/A> for readValue
    [D][FreeRTOS.cpp:173] take(): Semaphore taken: name: ReadCharEvt (0x3ffe0ddc), owner: readValue
    [D][BLEDevice.cpp:152] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_READ_CHAR_EVT
    [D][BLEClient.cpp:170] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_READ_CHAR_EVT
    [D][BLERemoteCharacteristic.cpp:433] readValue(): << readValue(): length: 21
    [D][BLERemoteCharacteristic.cpp:445] registerForNotify(): >> registerForNotify(): Characteristic: uuid: beb5483e-36e1-4688-b7f5-ea07361b26a8, handle: 42 0x2a, props: broadcast: 0, read: 1, write_nr: 0, write: 1, notify: 0, indicate: 0, auth: 0
    [D][FreeRTOS.cpp:164] take(): Semaphore taking: name: RegForNotifyEvt (0x3ffe1060), owner: <N/A> for registerForNotify
    [D][FreeRTOS.cpp:173] take(): Semaphore taken: name: RegForNotifyEvt (0x3ffe1060), owner: registerForNotify
    [D][BLERemoteCharacteristic.cpp:330] getDescriptor(): >> getDescriptor: uuid: 00002902-0000-1000-8000-00805f9b34fb
    [D][BLEDevice.cpp:152] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_REG_FOR_NOTIFY_EVT
    [D][BLERemoteCharacteristic.cpp:338] getDescriptor(): << getDescriptor: Not found
    [D][BLEClient.cpp:170] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_REG_FOR_NOTIFY_EVT
    [D][BLERemoteCharacteristic.cpp:487] registerForNotify(): << registerForNotify()
    Setting new characteristic value to "Time since boot: 3"
    [D][BLERemoteCharacteristic.cpp:554] writeValue(): >> writeValue(), length: 18
    [D][FreeRTOS.cpp:164] take(): Semaphore taking: name: WriteCharEvt (0x3ffe10c0), owner: <N/A> for writeValue
    [D][FreeRTOS.cpp:173] take(): Semaphore taken: name: WriteCharEvt (0x3ffe10c0), owner: writeValue
    [D][BLEDevice.cpp:152] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_WRITE_CHAR_EVT
    [D][BLEClient.cpp:170] gattClientEventHandler(): gattClientEventHandler [esp_gatt_if: 4] ... ESP_GATTC_WRITE_CHAR_EVT
    [D][BLERemoteCharacteristic.cpp:581] writeValue(): << writeValue

Here I can see that onAuthenticationComplete(): pair status = fail
but the client start anyway to write server characteristics

At this point I do not understand if I missing something or if there is a bug
Thank You
Best Regards
Marco

@chegewara
Copy link
Collaborator

chegewara commented Feb 7, 2019

Try to setup this for every characteristic and descriptor:
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLETests/Arduino/security/BLE_server/BLE_server_authorization/BLE_server_authorization.ino#L33

EDIT
pair status is fail, which means you wont be bonded/paired, but you still read/write attributes value because they are setup with read/write permission WITHOUT encrypted flag

@mpbejo
Copy link
Author

mpbejo commented Feb 7, 2019

Thank You for super fast answer
I added
pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
and now I cannot read and write if i am not correctly connect, this problem is solved.

What I do not understand is how the client can input the right passkey to connect correctly to the server?

@chegewara
Copy link
Collaborator

You have 30 seconds to get passskey from keyboard attached to esp32 client and pass it here as return value(int):
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLETests/Arduino/security/BLE_client/BLE_client_passkey/BLE_client_passkey.ino#L21

@mpbejo
Copy link
Author

mpbejo commented Feb 7, 2019

Well I see that, when a smartphone try to connect happens wath You say,
this is the server log when a smartphone try to connect:
[D][BLEDevice.cpp:106] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_CONNECT_EVT
[D][BLEServer.cpp:154] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_CONNECT_EVT
[D][BLECharacteristic.cpp:203] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_CONNECT_EVT
[D][BLECharacteristic.cpp:466] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEServer.cpp:281] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]
[I][BLEDevice.cpp:241] gapEventHandler(): ESP_GAP_BLE_PASSKEY_NOTIF_EVT
[I][BLEDevice.cpp:243] gapEventHandler(): passKey = 754928
[I][BLE_Server_Passkey_base.ino:28] onPassKeyNotify(): On passkey Notify number:754928
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 11]
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]
[D][BLEDevice.cpp:251] gapEventHandler(): ESP_GAP_BLE_KEY_EVT
[I][BLEDevice.cpp:253] gapEventHandler(): key type = ESP_LE_KEY_LENC

it stop on:

[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 20]

and only when I write the correct passkey i have:

[D][BLEDevice.cpp:251] gapEventHandler(): ESP_GAP_BLE_KEY_EVT

If I try with the ESP32 client there is no waiting time, this is the server log:

[D][BLEDevice.cpp:106] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_CONNECT_EVT
[D][BLEServer.cpp:154] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_CONNECT_EVT
[D][BLECharacteristic.cpp:203] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_CONNECT_EVT
[D][BLECharacteristic.cpp:466] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEServer.cpp:281] handleGATTServerEvent(): << handleGATTServerEvent
[I][BLEDevice.cpp:241] gapEventHandler(): ESP_GAP_BLE_PASSKEY_NOTIF_EVT
[I][BLEDevice.cpp:243] gapEventHandler(): passKey = 348297
[I][BLE_Server_Passkey_base.ino:28] onPassKeyNotify(): On passkey Notify number:348297
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 11]
[I][BLEDevice.cpp:257] gapEventHandler(): ESP_GAP_BLE_AUTH_CMPL_EVT
[I][BLE_Server_Passkey_base.ino:37] onAuthenticationComplete(): Starting BLE work!
[D][BLEDevice.cpp:557] getAdvertising(): get advertising
[D][BLEAdvertising.cpp:479] handleGAPEvent(): handleGAPEvent [event no: 8]
[D][BLEDevice.cpp:106] gattServerEventHandler(): gattServerEventHandler [esp_gatt_if: 4] ... ESP_GATTS_MTU_EVT
[D][BLEServer.cpp:154] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_MTU_EVT
[D][BLECharacteristic.cpp:203] handleGATTServerEvent(): >> handleGATTServerEvent: ESP_GATTS_MTU_EVT
[D][BLECharacteristic.cpp:466] handleGATTServerEvent(): << handleGATTServerEvent
[D][BLEServer.cpp:281] handleGATTServerEvent(): << handleGATTServerEvent

All this happen in one second.
Like the client don't wait the input but immediately sent the value in:
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLETests/Arduino/security/BLE_client/BLE_client_passkey/BLE_client_passkey.ino#L21

I tried to set a static key in the server 123456 and the client connect successfully.
So it is ok far a static passkey but not for a random passkey.

@chegewara
Copy link
Collaborator

Because in onPassKeyRequest you need some sort of logic that will wait your key to be input from keypad and then when you have correct passkey you can return it. There is some logic missing, because you have to handle keypad input. If i would do this i would use semaphore or queue to wait for input.

@mpbejo
Copy link
Author

mpbejo commented Feb 7, 2019

Ok sorry, I did not understand.
Now is clear.

@axa88
Copy link

axa88 commented Jul 9, 2019

good info here.
I think I have found one issue.

Try to setup this for every characteristic and descriptor:
https://github.com/nkolban/esp32-snippets/blob/master/cpp_utils/tests/BLETests/Arduino/security/BLE_server/BLE_server_authorization/BLE_server_authorization.ino#L33

EDIT
pair status is fail, which means you wont be bonded/paired, but you still read/write attributes value because they are setup with read/write permission WITHOUT encrypted flag

The problem is even when setting each characteristic with the read/write permission with encrypted flag:
pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);

A client can still request and receive notifications without ever being prompted for the key.

Please advise.

@chegewara
Copy link
Collaborator

The problem is even when setting each characteristic with the read/write permission with encrypted flag:
pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);

A client can still request and receive notifications without ever being prompted for the key.

Please advise.

Interesting. I can see 3 options here:

  • some issue with this library,
  • issue with esp-idf,
  • expected behavior consistent with bluetooth specs.

I didnt considered such case before and it requires tests/research or you could ask on esp-idf github issue tracker and get answer from someone smarter than me.

@axa88
Copy link

axa88 commented Jul 9, 2019

I didnt considered such case before and it requires tests/research or you could ask on esp-idf github issue tracker and get answer from someone smarter than me.

I see, appreciate the quick reply. To clarify, are issues related to this BLE library for Arduino welcome in the esp-idf issue tracker? Im unfamiliar with it, but I would imagine that it would not be welcome as it is an abstraction of esp idf.
Perhaps I will look through the espressif ESP32 Arduino forum.

Update:
It seems you might have inadvertently answered this question already.
https://esp32.com/viewtopic.php?f=13&t=9163

Apparently the Descriptor also needs to be protected with encryption flags. This makes sense because notify/indicate request by client is part of Descriptor function.

After adding this to Descriptor if the client requests to receive notifications, it must first provide the key.
Thanks

@suleatac
Copy link

Hello I am new on ESP32,
I am working with nrf52832 bluetooth modules . I prepared static passkey "123456" on nrf modules I can connect on nrf connect app after I write static passkey .Now I am trying to connect with ESP32 DEV Module .Is there any example Arduino code for ESP32 for pairing my nrf module with passkey? Can you advise me any example?

@Gcopper22
Copy link

Hello guys
I'm trying to use static pin for Esp32 bond connection..i use the example Test_passkey.zip with the modified Security.h and Security.cpp files. In version ESP32 1.0.1 is working,but in version ESP32 1.0.4 unfortunately is not working...

Is there any simply procedure to make it working even to the new version?

@chegewara
Copy link
Collaborator

@Gcopper22
Copy link

Gcopper22 commented Dec 7, 2020 via email

@chegewara
Copy link
Collaborator

Well, you have to replace BLESecurity.cpp and .h in arduino library with files from this repository. I dont know why it has not been done yet in arduino-esp32.

@Gcopper22
Copy link

Gcopper22 commented Dec 7, 2020 via email

@Gcopper22
Copy link

Gcopper22 commented Dec 7, 2020 via email

@chegewara
Copy link
Collaborator

There is 2 options:

  • force to pair with passkey on connect,
  • create characteristics and descriptors with property that requires authentication.

@Gcopper22
Copy link

Because i'm new with the ESP32 ,i don't know how to do it so i'll appreciate if you can help me,here is my sketch :

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

BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
std::string txValue;

#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID_RX "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

class MyServerCallbacks: public BLEServerCallbacks {
void onConnect(BLEServer* pServer) {
deviceConnected = true;
};

void onDisconnect(BLEServer* pServer) {
  deviceConnected = false;
}

};

class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();
char message[20];
for (int i = 0; i < rxValue.length(); i++) {
message[i]=rxValue[i];
}
}
};

class MySecurity : public BLESecurityCallbacks {

uint32_t onPassKeyRequest(){
ESP_LOGI(LOG_TAG, "PassKeyRequest");
return 123456;
}

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

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

void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl){
ESP_LOGI(LOG_TAG, "Starting BLE work!");
if(cmpl.success){
uint16_t length;
esp_ble_gap_get_whitelist_size(&length);
ESP_LOGD(LOG_TAG, "size: %d", length);
}
}
bool onConfirmPIN(uint32_t pass_key){
ESP_LOGI(LOG_TAG, "The passkey YES/NO number:%d", pass_key);
vTaskDelay(5000);
return false;
}
};

void setup() {

Serial.begin(115200);

// Create the BLE Device
BLEDevice::init("ESP32 UART Test"); // Give it a name

// Create the BLE Server
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());

// Create the BLE Service
BLEService *pService = pServer->createService(SERVICE_UUID);

// Create a BLE Characteristic
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);

pCharacteristic->addDescriptor(new BLE2902());

BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_RX,
BLECharacteristic::PROPERTY_WRITE
);

pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);

pCharacteristic->setCallbacks(new MyCallbacks());

pCharacteristic->setValue("Hello World says Neil");
// Start the service
pService->start();

// Start advertising
pServer->getAdvertising()->start();
Serial.println("Waiting a client connection to notify...");

BLESecurity *pSecurity = new BLESecurity();
pSecurity->setStaticPIN(123456);

}
void loop()
{
}

@chegewara
Copy link
Collaborator

pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);

Yes, that should be enough.

@Gcopper22
Copy link

Gcopper22 commented Dec 9, 2020

Unfortunately the problem exist using the above sketch.. The data transmission begin even without having bond the the esp32 with mobile phone..

So what will be the solution to force pair only with passkey on connect?

@chegewara
Copy link
Collaborator

Im pretty sure this should works. Maybe your smartphone is already bond with esp32? Did you erase all pairing data? I remember i did not erase data many times when ive been writing security class and i had headache because of that.

@Juicy-AUS
Copy link

Hiya legends, I've tried adding the
BLESecurity *pSecurity = new BLESecurity(); pSecurity->setStaticPIN(123456);
piece of code to my esp32 project and while it does require the password if i want to pair to it on my phone or tablet, im still able to connect to it and read and write to characteristics with an app, even when not paired.
I tried adding the
pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENCRYPTED | ESP_GATT_PERM_WRITE_ENCRYPTED);
code to each characteristic but i think, and i could be wrong, it just encrypts the data on that characteristic which i would need to decrypt on the other end (which isn't something i would like to do if i can avoid it).

Any advice?

@chegewara
Copy link
Collaborator

Hi,
you have 2 options:

  • to add access permisions to every characteristic and descriptor, just like you did it, or even easier, set it during char create
#define    ESP_GATT_PERM_READ                  (1 << 0)   /* bit 0 -  0x0001 */    /* relate to BTA_GATT_PERM_READ in bta/bta_gatt_api.h */
#define    ESP_GATT_PERM_READ_ENCRYPTED        (1 << 1)   /* bit 1 -  0x0002 */    /* relate to BTA_GATT_PERM_READ_ENCRYPTED in bta/bta_gatt_api.h */
#define    ESP_GATT_PERM_READ_ENC_MITM         (1 << 2)   /* bit 2 -  0x0004 */    /* relate to BTA_GATT_PERM_READ_ENC_MITM in bta/bta_gatt_api.h */
#define    ESP_GATT_PERM_WRITE                 (1 << 4)   /* bit 4 -  0x0010 */    /* relate to BTA_GATT_PERM_WRITE in bta/bta_gatt_api.h */
#define    ESP_GATT_PERM_WRITE_ENCRYPTED       (1 << 5)   /* bit 5 -  0x0020 */    /* relate to BTA_GATT_PERM_WRITE_ENCRYPTED in bta/bta_gatt_api.h */
#define    ESP_GATT_PERM_WRITE_ENC_MITM        (1 << 6)   /* bit 6 -  0x0040 */    /* relate to BTA_GATT_PERM_WRITE_ENC_MITM in bta/bta_gatt_api.h */
#define    ESP_GATT_PERM_WRITE_SIGNED          (1 << 7)   /* bit 7 -  0x0080 */    /* relate to BTA_GATT_PERM_WRITE_SIGNED in bta/bta_gatt_api.h */
#define    ESP_GATT_PERM_WRITE_SIGNED_MITM     (1 << 8)   /* bit 8 -  0x0100 */    /* relate to BTA_GATT_PERM_WRITE_SIGNED_MITM in bta/bta_gatt_api.h */
#define    ESP_GATT_PERM_READ_AUTHORIZATION    (1 << 9)   /* bit 9 -  0x0200 */
#define    ESP_GATT_PERM_WRITE_AUTHORIZATION   (1 << 10)  /* bit 10 - 0x0400 */
typedef uint16_t esp_gatt_perm_t;
  • to add BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT_MITM); after create server or init(), if i remember correctly

@Juicy-AUS
Copy link

So if I add either one, essentially it will prevent access to the characteristics unless passkey is entered?

@Juicy-AUS
Copy link

@chegewara you sir, are a legend! Added option 2 and work perfectly now.

@ParcoMolo
Copy link

ParcoMolo commented Jul 19, 2022

How to ensure/test AES128 bit encryption is enforced on Expressive BLE

Hi there, we have an esp32-Wroom that we are trying to set a BLE server up on.
we have added security to the BLE server as well as attempted a few variations of the server code as well.

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

BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
std::string txValue;

#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

class MyServerCallbacks: public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
  deviceConnected = true;

  // Logging
  ESP_LOGI(LOG_TAG, "Device Connected - Connection Status:%d", deviceConnected);
  Serial.println("Device Connected - Connection Status: ");
  Serial.println(deviceConnected);
  }; 

  void onDisconnect(BLEServer* pServer) {
  deviceConnected = false;

  // Logging
  ESP_LOGI(LOG_TAG, "Device disconnected - Connection Status:%d", deviceConnected);
  Serial.println("Device Disconnected - Connection Status: ");
  Serial.println(deviceConnected);
  }
};

class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();

//
Serial.println("Recieved: ");
Serial.println(rxValue.c_str());
//

char message[20];
for (int i = 0; i < rxValue.length(); i++) {
message[i]=rxValue[i];
}
}
};

class MySecurity : public BLESecurityCallbacks {

uint32_t onPassKeyRequest(){
ESP_LOGI(LOG_TAG, "PassKeyRequest");
return 123456;
}

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

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

void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl){
ESP_LOGI(LOG_TAG, "Starting BLE work!");
if(cmpl.success){
uint16_t length;
Serial.println("Auth Complete");
esp_ble_gap_get_whitelist_size(&length);
ESP_LOGD(LOG_TAG, "size: %d", length);
}
}
bool onConfirmPIN(uint32_t pass_key){
ESP_LOGI(LOG_TAG, "The passkey YES/NO number:%d", pass_key);
Serial.println("onConfirmPIN - pass_key:");
Serial.println(pass_key);
vTaskDelay(500);
return false;
}
};

void setup() {

Serial.begin(115200);

// Create the BLE Device
BLEDevice::init("Another controller");
BLESecurity *pSecurity = new BLESecurity();
pSecurity->setStaticPIN(123456);

// Create the BLE Server
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());

// Create the BLE Service
BLEService *pService = pServer->createService(SERVICE_UUID);

// Create a BLE Characteristic
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);

pCharacteristic->addDescriptor(new BLE2902());

BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_WRITE
);

pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENC_MITM | ESP_GATT_PERM_WRITE_ENC_MITM);

pCharacteristic->setCallbacks(new MyCallbacks());

pCharacteristic->setValue("Llamas controlls these gates");
// Start the service
pService->start();

// Start advertising
pServer->getAdvertising()->start();
Serial.println("Waiting for a client connection to notify...");



}
void loop()
{
}

We start up the esp32. and then use Wireshark to watch the communication between the phone and the ble server...
and when doing this we can see that the content we are sending to a characteristic is still in plain text and not encrypted.

Wireshark output:
image

image

are we doing something wrong? or how do we go about testing that encryption is indeed taking place when communicating to the BLE server

@chegewara
Copy link
Collaborator

2 posts above:
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT_MITM);

@ParcoMolo
Copy link

Thanks for the quick response @chegewara,

I've added the line as you mentioned, see code snippet below & screenshots:

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

BLECharacteristic *pCharacteristic;
bool deviceConnected = false;
std::string txValue;

#define SERVICE_UUID "6E400001-B5A3-F393-E0A9-E50E24DCCA9E" // UART service UUID
#define CHARACTERISTIC_UUID "6E400002-B5A3-F393-E0A9-E50E24DCCA9E"
#define CHARACTERISTIC_UUID_TX "6E400003-B5A3-F393-E0A9-E50E24DCCA9E"

class MyServerCallbacks: public BLEServerCallbacks {
  void onConnect(BLEServer* pServer) {
  deviceConnected = true;

  // Logging
  ESP_LOGI(LOG_TAG, "Device Connected - Connection Status:%d", deviceConnected);
  Serial.println("Device Connected - Connection Status: ");
  Serial.println(deviceConnected);
  }; 

  void onDisconnect(BLEServer* pServer) {
  deviceConnected = false;

  // Logging
  ESP_LOGI(LOG_TAG, "Device disconnected - Connection Status:%d", deviceConnected);
  Serial.println("Device Disconnected - Connection Status: ");
  Serial.println(deviceConnected);
  }
};

class MyCallbacks: public BLECharacteristicCallbacks {
void onWrite(BLECharacteristic *pCharacteristic) {
std::string rxValue = pCharacteristic->getValue();

//
Serial.println("Recieved: ");
Serial.println(rxValue.c_str());
//

char message[20];
for (int i = 0; i < rxValue.length(); i++) {
message[i]=rxValue[i];
}
}
};

class MySecurity : public BLESecurityCallbacks {

uint32_t onPassKeyRequest(){
ESP_LOGI(LOG_TAG, "PassKeyRequest");
return 123456;
}

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

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

void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl){
ESP_LOGI(LOG_TAG, "Starting BLE work!");
if(cmpl.success){
uint16_t length;
Serial.println("Auth Complete");
esp_ble_gap_get_whitelist_size(&length);
ESP_LOGD(LOG_TAG, "size: %d", length);
}
}
bool onConfirmPIN(uint32_t pass_key){
ESP_LOGI(LOG_TAG, "The passkey YES/NO number:%d", pass_key);
Serial.println("onConfirmPIN - pass_key:");
Serial.println(pass_key);
vTaskDelay(500);
return false;
}
};

void setup() {

Serial.begin(115200);

// Create the BLE Device
BLEDevice::init("Another controller"); // Give it a name
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT_MITM);  // The line you told me to add
BLESecurity *pSecurity = new BLESecurity();
pSecurity->setStaticPIN(123456);

// Create the BLE Server
BLEServer *pServer = BLEDevice::createServer();
pServer->setCallbacks(new MyServerCallbacks());

// Create the BLE Service
BLEService *pService = pServer->createService(SERVICE_UUID);


// Create a BLE Characteristic
pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID_TX,
BLECharacteristic::PROPERTY_NOTIFY
);

pCharacteristic->addDescriptor(new BLE2902());

BLECharacteristic *pCharacteristic = pService->createCharacteristic(
CHARACTERISTIC_UUID,
BLECharacteristic::PROPERTY_WRITE
);

pCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENC_MITM | ESP_GATT_PERM_WRITE_ENC_MITM);

pCharacteristic->setCallbacks(new MyCallbacks());

pCharacteristic->setValue("bla bla");
// Start the service
pService->start();

// Start advertising
pServer->getAdvertising()->start();
Serial.println("Waiting for a client connection to notify...");



}
void loop()
{
}

image

I also see the response from the server:
image

As you can see the "Sent Write Request" is still unencrypted, am I missing something?

Kind regards,

Marco

@chegewara
Copy link
Collaborator

You may have to play with other options too, like bonding.
The other option it is not working is the static pin, or some bug in the implementation of it.
I believe the clue is Initiator key and Responder key being none.

PS after checking the code i think i know the reason
please try to add this line of code you did in previous step, but after setStaticPin

@ParcoMolo
Copy link

I tried that and it's still not encrypted

image

I can remove the static pin func and change the IO capability toe OUT, but the problem is that our server doesn't have a display that can be used to compare the two codes, and we would ideally like to use static pins.

I agree with you regarding the Initiator key and Responder key being none, but I have no idea how to get it working:

The client cleary get the right info in the sense of what security params have been declared on the server
image

But the server responds with this:
image

Do you by any chance have a working example that I can use to compare with?

Thanks again for all your help.

@sonoqui
Copy link

sonoqui commented Mar 19, 2025

This is what finally worked for me trying to use the static pin.

BLESecurity *pSecurity = new BLESecurity();
pSecurity->setStaticPIN(888888); <--- It has to be set before the lines below as suggested by the setStaticPIN() definition comments
pSecurity->setAuthenticationMode(ESP_LE_AUTH_BOND | ESP_LE_AUTH_REQ_MITM);
pSecurity->setCapability(ESP_IO_CAP_OUT);
BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT);

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants