BLE Security - Cannot Access Services after reconnect
Posted: 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:
BLE Callbacks:
Class Declarations:
Finally C# Code:
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.
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;
}
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);
}
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;
};
- public async Task<bool> CheckServiceAndCharateristics()
- {
- try
- {
- if (this.BLEDevice == null || this.BLEDevice.State != Plugin.BLE.Abstractions.DeviceState.Connected)
- return false;
- this.MTU = await BLEDevice.RequestMtuAsync(517);
- var uartService = await BLEDevice.GetServiceAsync(uuidServiceUart);
- if (uartService == null)
- return false;
- var otaService = await BLEDevice.GetServiceAsync(uuidServiceOta);
- if (otaService == null)
- return false;
- RxCharateristic = await uartService.GetCharacteristicAsync(uuidCharacteristicRx);
- TxCharateristic = await uartService.GetCharacteristicAsync(uuidCharacteristicTx);
- OtaCharateristic = await otaService.GetCharacteristicAsync(uuidCharacteristicOta);
- if (RxCharateristic == null || TxCharateristic == null || OtaCharateristic == null)
- return false;
- return true;
- }
- catch (Exception ex)
- {
- return false;
- }
- }