h2zero / NimBLE-Arduino

A fork of the NimBLE library structured for compilation with Arduino, for use with ESP32, nRF5x.
https://h2zero.github.io/NimBLE-Arduino/
Apache License 2.0
670 stars 138 forks source link

Write with no response does not work with encryption #615

Open Aizudev opened 7 months ago

Aizudev commented 7 months ago

Hi, thanks for your library!

I'm trying to send OTA firmware updates to ESP32. I'm following this example to test proof of concept.

This example creates a characteristic with property write with no response:

  // 4. Create BLE Characteristics inside the service(s)
  pTxCharacteristic = pService->createCharacteristic(CHARACTERISTIC_TX_UUID,
                      NIMBLE_PROPERTY:: NOTIFY);

  pOtaCharacteristic = pService->createCharacteristic(CHARACTERISTIC_OTA_UUID,
                       NIMBLE_PROPERTY:: WRITE_NR);

However, I wish to encrypt the transfer, so I added WRITE_ENC

  pOtaCharacteristic = pService->createCharacteristic(CHARACTERISTIC_OTA_UUID,
                       NIMBLE_PROPERTY:: WRITE_NR | NIMBLE_PROPERTY::WRITE_ENC);

With this, I expected a prompt to appear on my iOS running the example app, asking if I wish to pair the device. This happens when I have WRITE instead of WRITE_NR:

  pOtaCharacteristic = pService->createCharacteristic(CHARACTERISTIC_OTA_UUID,
                       NIMBLE_PROPERTY:: WRITE | NIMBLE_PROPERTY::WRITE_ENC);

However, no prompt appeared and the iOS app was unable to write the firmware to the ESP32.

Is WRITE_NR compatible with encryption? I tried modifying the iOS code to write with response instead, but it got stuck at 0.2%.

Thank you!

h2zero commented 6 months ago

I'm not sure why this would be happening, I will need to investigate.

Aizudev commented 6 months ago

Thank you, that would be much appreciated!

I tested it with your example code for the BLE server, and modified the setup to look like this:

  // 1. Create the BLE Device
  NimBLEDevice::init("My device");
  NimBLEDevice::setMTU(517);
 //NimBLEDevice::setSecurityAuth(BLE_SM_PAIR_AUTHREQ_BOND | BLE_SM_PAIR_AUTHREQ_MITM | BLE_SM_PAIR_AUTHREQ_SC);

  // 2. Create the BLE server
  pServer = NimBLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // 3. Create BLE Service
  pDataService = pServer->createService(SERVICE_DATA_UUID);
  pDataTxCharacteristic = pDataService->createCharacteristic(CHARACTERISTIC_DATA_TX_UUID,
                      NIMBLE_PROPERTY:: NOTIFY);
  pDataCharacteristic = pDataService->createCharacteristic(CHARACTERISTIC_DATA_UUID,
                       NIMBLE_PROPERTY:: WRITE_NR | NIMBLE_PROPERTY::WRITE_ENC);
  pDataCharacteristic->setCallbacks(new bleCallback());
  pDataService->start();

I then tried to send BLE data from the LightBlue app on iOS, with WRITE, the Pair prompt shows up but not WRITE_NR.

Aizudev commented 6 months ago

Fixed it by enforcing encryption on connect:

int b = NimBLEDevice::startSecurity(desc->conn_handle);

It works for now.

2 other issues that came up:

Enabling bonding disconnects automatically and does not attempt to reconnect. I had to go to iOS settings to forget the device to put it in a working state again.

  NimBLEDevice::setSecurityAuth(BLE_SM_PAIR_AUTHREQ_BOND |  /**BLE_SM_PAIR_AUTHREQ_MITM |*/ BLE_SM_PAIR_AUTHREQ_SC);

Also, I left the default max connections (3) as is, but it seems like only one device connect to it at one time.

h2zero commented 6 months ago

Thanks for this information, I will try this tomorrow and see if I can reproduce it.

Aizudev commented 5 months ago

hi @h2zero , any idea on what might be causing this or how to debug this?

  NimBLEDevice::setSecurityAuth(true, false true);

Setting this seems to enable bonding, but my iOS is unable to reconnect to the device unless I forget the bond and pair it again.

h2zero commented 5 months ago

Please try erasing the flash fully and try again to clear out any old bond info and try again.

Aizudev commented 5 months ago

Did all of that but didn't work.

I'm enforcing encryption on connect, and using iOS 17.2.1

h2zero commented 1 month ago

This may be resolved with https://github.com/h2zero/esp-nimble-cpp/pull/164