BLE Security - Cannot Access Services after reconnect

streetec
Posts: 4
Joined: Thu Sep 24, 2020 12:50 pm

BLE Security - Cannot Access Services after reconnect

Postby streetec » Thu Sep 24, 2020 1:02 pm

Hello Everybody,
first of all thanks for reading my post and propably the intention to help me out :)

I am currently developing two devices with an ESP32 as controller. Both of them shall have bluetooth and wifi features. To use these features I am creating a C# Xamarin Application.

The ESP32 is running an BLE server and is providing two services, which shall be protected via a static passkey and only accessible for paired devices, which is working if I "freshly" pair the device to my phone. As soon as I disconnect / close the app, I cannot see the services after reconnecting any more.

BLE Setup:

Code: Select all

//
// begin
bool BLE::begin() {
   // Create the BLE Device
    BLEDevice::init("taco 1");
    BLEDevice::setEncryptionLevel(ESP_BLE_SEC_ENCRYPT);
    BLEDevice::setSecurityCallbacks(new SecurityCallback());
    BLEDevice::setMTU(256);

    // Create the BLE Server
    pServer = BLEDevice::createServer();
    pServer->setCallbacks(new ServerCallbacks(this));
  
    // Create the UART BLE Service
    pUARTService = pServer->createService(SERVICE_UART_UUID);

    // Create the UART BLE Characteristics
    pTxCharacteristic = pUARTService->createCharacteristic(
                                        CHARACTERISTIC_UUID_TX,
                                        BLECharacteristic::PROPERTY_NOTIFY
                                    );
                        
    pTxCharacteristic->addDescriptor(new BLE2902());
    pTxCharacteristic->setAccessPermissions(ESP_GATT_PERM_READ_ENC_MITM);

    pRxCharacteristic = pUARTService->createCharacteristic(
                                            CHARACTERISTIC_UUID_RX,
                                            BLECharacteristic::PROPERTY_WRITE
                                        );

    pRxCharacteristic->setCallbacks(new RxCallbacks());
    pRxCharacteristic->setAccessPermissions(ESP_GATT_PERM_WRITE_ENC_MITM);


    // Create the OTA BLE Service
    pOtaService = pServer->createService(SERVICE_OTA_UUI);

    // Create the OTA BLE Charateristic
    pOtaCharacteristic = pOtaService->createCharacteristic(
                                                CHARACTERISTIC_UUID_OTA,
                                                BLECharacteristic::PROPERTY_NOTIFY | BLECharacteristic::PROPERTY_WRITE_NR
                                            );
    pOtaCharacteristic->addDescriptor(new BLE2902());
    pOtaCharacteristic->setCallbacks(new otaCallback(this));
    pOtaCharacteristic->setAccessPermissions(ESP_GATT_PERM_WRITE_ENC_MITM);

    // Start the services
    pUARTService->start();
    pOtaService->start();

    // Start advertising
    pServer->getAdvertising()->addServiceUUID(SERVICE_OTA_UUI);
    pServer->getAdvertising()->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;                                      //key size between 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_ENABLE;
    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));

    return true;
}
BLE Callbacks:

Code: Select all

void otaCallback::onWrite(BLECharacteristic *pCharacteristic)
{
  Serial.println("otaCallback");
  std::string rxData = pCharacteristic->getValue();
  _p_ble->updater = new WiFiUpdater(rxData.c_str());

  pCharacteristic->notify();
}


void ServerCallbacks::onConnect(BLEServer* pServer, esp_ble_gatts_cb_param_t *param) {
  _p_ble->deviceConnected = true;
  esp_ble_set_encryption(param->connect.remote_bda, ESP_BLE_SEC_ENCRYPT);
  Serial.println("Connected");
};

void ServerCallbacks::onDisconnect(BLEServer* pServer) {
  _p_ble->deviceConnected = false;
  Serial.println("Disconnected");
}

uint32_t SecurityCallback::onPassKeyRequest() {
  Serial.println("onPassKeyRequest");
  return 123456;
}

void SecurityCallback::onPassKeyNotify(uint32_t pass_key) {
  Serial.printf("onPassKeyNotify %d\n", pass_key);
}

bool SecurityCallback::onConfirmPIN(uint32_t pass_key){
  Serial.printf("onConfirmPin %d\n", pass_key);
  vTaskDelay(5000);
  return true;
}

bool SecurityCallback::onSecurityRequest() {
  Serial.println("onSecurityRequest");
  return true;
}

void SecurityCallback::onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl) {
  Serial.print("onAuthenticationComplete success: " );
  Serial.println(cmpl.success);
}
Class Declarations:

Code: Select all

class BLE; // forward declaration

class ServerCallbacks: public BLEServerCallbacks {
    public:
      ServerCallbacks(BLE * ble) {
        _p_ble = ble;
      }
      BLE* _p_ble;

      void onConnect(BLEServer* pServer, esp_ble_gatts_cb_param_t *param);
      void onDisconnect(BLEServer* pServer);
};

class otaCallback: public BLECharacteristicCallbacks {
  public:
    otaCallback(BLE* ble) {
      _p_ble = ble;
    }
    BLE* _p_ble;

    void onWrite(BLECharacteristic *pCharacteristic);
};

class SecurityCallback : public BLESecurityCallbacks {
  public:
    uint32_t onPassKeyRequest();
    void onPassKeyNotify(uint32_t pass_key);
    bool onConfirmPIN(uint32_t pass_key);
    bool onSecurityRequest();
    void onAuthenticationComplete(esp_ble_auth_cmpl_t cmpl);
};

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

      if (rxValue.length() > 0) {
        Serial.print("Received Value: ");
        for (int i = 0; i < rxValue.length(); i++)
          Serial.print(rxValue[i]);
        Serial.println();

        // Toggle Compressor
       if (rxValue == msg_toggle_comp) {
          reqCompressor = reqCompressor ? 0 : 1;
        }

        // Toggle Compressor
        if (rxValue == msg_toggle_fan) {
          reqFan = reqFan ? 0 : 1;
        }
      }
    }
};

class BLE
{
  public:

    BLE(void);
    ~BLE(void);

    bool begin();

    bool deviceConnected;
    bool oldDeviceConnected;
    uint32_t ms_last_broadcast;
    const uint32_t interval_broadcast = 100;

    void loop();
    WiFiUpdater *updater = NULL;
  
  private:
    String local_name;

    BLEServer *pServer = NULL;

    BLEService *pOtaService = NULL;
    BLECharacteristic * pOtaCharacteristic = NULL;

    BLEService * pUARTService = NULL;
    BLECharacteristic * pTxCharacteristic = NULL;
    BLECharacteristic * pRxCharacteristic = NULL;

    
};
Finally C# Code:
  1.  public async Task<bool> CheckServiceAndCharateristics()
  2.         {
  3.             try
  4.             {
  5.                 if (this.BLEDevice == null || this.BLEDevice.State != Plugin.BLE.Abstractions.DeviceState.Connected)
  6.                     return false;
  7.  
  8.                 this.MTU = await BLEDevice.RequestMtuAsync(517);
  9.                 var uartService = await BLEDevice.GetServiceAsync(uuidServiceUart);
  10.                 if (uartService == null)
  11.                     return false;
  12.                 var otaService = await BLEDevice.GetServiceAsync(uuidServiceOta);
  13.                 if (otaService == null)
  14.                     return false;
  15.                 RxCharateristic = await uartService.GetCharacteristicAsync(uuidCharacteristicRx);
  16.                 TxCharateristic = await uartService.GetCharacteristicAsync(uuidCharacteristicTx);
  17.                 OtaCharateristic = await otaService.GetCharacteristicAsync(uuidCharacteristicOta);
  18.  
  19.                 if (RxCharateristic == null || TxCharateristic == null || OtaCharateristic == null)
  20.                     return false;
  21.  
  22.                 return true;
  23.             }
  24.             catch (Exception ex)
  25.             {
  26.                 return false;
  27.             }
  28.            
  29.         }
As I said, after the first connection after pairing, uart Service is null. If i "forget" the esp32 again and re-pair it, everything is working.

Who is online

Users browsing this forum: No registered users and 55 guests