Adding Extra Protocomm Endpints to ble_prov example for BLE provosioning

RMandR
Posts: 75
Joined: Mon Oct 29, 2018 3:13 pm

Adding Extra Protocomm Endpints to ble_prov example for BLE provosioning

Postby RMandR » Fri Feb 22, 2019 12:10 am

I've following the example in the protocomm documentation https://docs.espressif.com/projects/esp ... ocomm.html and added two extra endpoints (0xFF54 and 0xFF55).

The additional data is unrelated to wifi config but can only be passed to the device while POP (proof of possession) is established.

Easy enough the endpoints are visible when you use something like gatttool:

Code: Select all

[Codebox=bash file=Untitled.bsh]sudo gatttool -i hci0 -b 3X:XX:XX:XX:XX:XX -m 48 --interactive
[3X:XX:XX:XX:XX:XX][LE]> connect
Attempting to connect to 3X:XX:XX:XX:XX:XX
Connection successful
[3X:XX:XX:XX:XX:XX][LE]> primary
attr handle: 0x0001, end grp handle: 0x0005 uuid: 00001801-0000-1000-8000-00805f9b34fb
attr handle: 0x0014, end grp handle: 0x001c uuid: 00001800-0000-1000-8000-00805f9b34fb
attr handle: 0x0028, end grp handle: 0xffff uuid: 0000ffff-0000-1000-8000-00805f9b34fb
[3X:XX:XX:XX:XX:XX][LE]> characteristics 0x0028 0xffff
handle: 0x0029, char properties: 0x0a, char value handle: 0x002a, uuid: 0000ff51-0000-1000-8000-00805f9b34fb
handle: 0x002b, char properties: 0x0a, char value handle: 0x002c, uuid: 0000ff52-0000-1000-8000-00805f9b34fb
handle: 0x002d, char properties: 0x0a, char value handle: 0x002e, uuid: 0000ff53-0000-1000-8000-00805f9b34fb
handle: 0x002f, char properties: 0x0a, char value handle: 0x0030, uuid: 0000ff54-0000-1000-8000-00805f9b34fb
handle: 0x0031, char properties: 0x0a, char value handle: 0x0032, uuid: 0000ff55-0000-1000-8000-00805f9b34fb
[3X:XX:XX:XX:XX:XX][LE]>
[/Codebox]
I tried modifying ble_prov.py (and ble_cli.py) to allow for additional endpoints and received "xyz" endpoint not found.

it turns out the added endpoints are not enumerated in ble_cli.py. Even a dump of the dbus object does not contain them:

Code: Select all

[Codebox=python file=ble_cli.py]    def _get_services_(self):
        bus = dbus.SystemBus()
        manager = dbus.Interface(bus.get_object("org.bluez", "/"), "org.freedesktop.DBus.ObjectManager")
        objects = manager.GetManagedObjects()
	print ("objects: " + str(objects) + " ")
[/Codebox]
However, ff51, ff52,ff53 are listed in the dump.

Is there step that I have missed?

ESP_Anurag
Posts: 19
Joined: Fri Aug 31, 2018 5:37 am

Re: Adding Extra Protocomm Endpints to ble_prov example for BLE provosioning

Postby ESP_Anurag » Fri Feb 22, 2019 6:28 am

It's actually due to BlueZ keeping the old device data in cache. To refresh the cache, find the cache folder corresponding to your ESP32 under "/var/lib/bluetooth/<MAC ID of your Bluetooth controller>/<MAC ID of ESP32>" and remove it. Another way is to disable caching from "/etc/bluetooth/main.conf". Please let us know if that fixes it for you.

RMandR
Posts: 75
Joined: Mon Oct 29, 2018 3:13 pm

Re: Adding Extra Protocomm Endpints to ble_prov example for BLE provosioning

Postby RMandR » Fri Feb 22, 2019 6:51 pm

Thanks Anurag! Yes, with cache refreshed, I got further along. Now I have a

Code: Select all

E (23472) WiFiProvConfig: Unable to unpack config data
E (23482) protocomm: Request handler for prov-config failed
E (23482) protocomm_ble: Invalid content received, killing connection
It maybe an issue of me not sending the right data to the esp for my added end point. This is what I added to ble_prov.py

Code: Select all

def send_extra_data(tp,sec, data):
    cmd = tobytes(data)
    msg = sec.encrypt_data(cmd).decode('latin-1')
    response = tp.send_data('prov-xyz', msg)
    return None
The data is a string. And this is what my handler looks like on the esp side (based on the docs):

Code: Select all

esp_err_t set_extra_data_handler(uint32_t session_id, const uint8_t *inbuf, ssize_t inlen, uint8_t **outbuf, ssize_t *outlen, void *priv_data)
{
      ESP_LOGI(TAG, "Extra data handler! size: %d", (int) inlen);

    /* Echo back the received data */
    *outlen = inlen;            /* Output data length updated */
    *outbuf = malloc(inlen);    /* This will be deallocated outside */
    memcpy(*outbuf, inbuf, inlen);

    /* print the buffer */
    for (int i = 0; i < inlen; i++)
        printf("%x ", ((char* ) priv_data)[i]);

    return ESP_OK;
}

ESP_Anurag
Posts: 19
Joined: Fri Aug 31, 2018 5:37 am

Re: Adding Extra Protocomm Endpints to ble_prov example for BLE provosioning

Postby ESP_Anurag » Fri Feb 22, 2019 8:13 pm

According to the error log:

Code: Select all

E (23482) protocomm: Request handler for prov-config failed
That means your data is for some reason arriving on the wrong endpoint "prov-config", which is at 0xFF52. Check if that's not the case

RMandR
Posts: 75
Joined: Mon Oct 29, 2018 3:13 pm

Re: Adding Extra Protocomm Endpints to ble_prov example for BLE provosioning

Postby RMandR » Mon Feb 25, 2019 9:47 pm

I had a chance to look a bit more into it.
It goes to the correct endpoint and my data gets passed fine to esp32 (see Hello, World).

However that somehow messes up the pipeline.


On Linux:

Code: Select all

==== Applying config to esp32 ====
++++ Client -> Device (ApplyConfig cmd) 050d ++++
++++ SetConfig status 0 ++++
==== Apply config sent successfully ====
==== Send Extra Endpoint Data ====
--- Encrypt Data: Hello, World ---
==== Sent Extra Endpoint successfully ====

==== Wi-Fi connection state  ====
++++ Client -> Device (Encrypted CmdGetStatus) ec3f ++++
Traceback (most recent call last):
  File "esp_prov.py", line 241, in <module>
    ret = get_wifi_config(obj_transport, obj_security)
  File "esp_prov.py", line 140, in get_wifi_config
    response = tp.send_data('prov-config', message)
  File "/home/user/esp/esp-idf/tools/esp_prov/transport/transport_ble.py", line 59, in send_data
    return self.cli.send_data(self.name_uuid_lookup[ep_name], data)
  File "/home/user/esp/esp-idf/tools/esp_prov/transport/ble_cli.py", line 166, in send_data
    return ''.join(chr(b) for b in path.ReadValue({}, dbus_interface='org.bluez.GattCharacteristic1'))
  File "/home/user/.local/lib/python2.7/site-packages/dbus/proxies.py", line 145, in __call__
    **keywords)
  File "/home/user/.local/lib/python2.7/site-packages/dbus/connection.py", line 651, in call_blocking
    message, timeout)
dbus.exceptions.DBusException: org.bluez.Error.Failed: Not connected

On The Esp32: You can see the "Hello, World" does get received. It also connects successfully to the AP and picks up an IP address.

But gets messed up after that.

Code: Select all

Hello, World 
I (23015) wifi: new:<6,0>, old:<1,0>, ap:<255,255>, sta:<6,0>, prof:1
I (24025) wifi: state: init -> auth (b0)
I (24035) wifi: state: auth -> assoc (0)
I (24035) wifi: state: assoc -> run (10)
I (24065) wifi: connected with SomeWifi, channel 6, bssid = 12:34:67:89:10:11
I (24075) wifi: pm start, type: 1

I (25015) event: sta ip: 172.22.1.163, mask: 255.255.255.0, gw: 172.22.1.1
I (25015) app_prov: STA Got IP
I (25015) app: got ip:172.22.1.163
E (27735) WiFiProvConfig: Unable to unpack config data
E (27735) protocomm: Request handler for prov-config failed
E (27735) protocomm_ble: Invalid content received, killing connection
I (55025) app_prov: Stopping provisioning
W (55025) BT_APPL: bta_dm_disable BTA_DISABLE_DELAY set to 200 ms
I (55295) app_prov: Provisioning stopped
Is there something I should clearing, freeing, or reseting to make it happy again?

ESP_Anurag
Posts: 19
Joined: Fri Aug 31, 2018 5:37 am

Re: Adding Extra Protocomm Endpints to ble_prov example for BLE provosioning

Postby ESP_Anurag » Tue Feb 26, 2019 11:28 am

You also need to decrypt the response data in the python script. That may seem unnecessary for your use case, but without that the encryption engine will not update the internal AES-CTR security counter on the client side (See https://docs.espressif.com/projects/esp ... ty-schemes).

So change your code as follows:

Code: Select all

def send_extra_data(tp,sec, data):
    cmd = tobytes(data)
    msg = sec.encrypt_data(cmd).decode('latin-1')
    response = tp.send_data('prov-xyz', msg)
    decrypt = sec.decrypt_data(tobytes(response))
    return None
What was happening in your case is that since the client side AES counter didn't get updated, the next encrypted packet (which is GetCmd in your case) is decrypted incorrectly on the device side (which has the latest counter). The counters need to be the same on both client and device side for the secure communication to work.

RMandR
Posts: 75
Joined: Mon Oct 29, 2018 3:13 pm

Re: Adding Extra Protocomm Endpints to ble_prov example for BLE provosioning

Postby RMandR » Tue Feb 26, 2019 2:07 pm

You also need to decrypt the response data in the python script

Thank Anurag! That was the issue.

Who is online

Users browsing this forum: sage1234 and 242 guests