Skip to content
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

Bonding doesn't work #11

Closed
schlaegerz opened this issue Apr 14, 2020 · 10 comments
Closed

Bonding doesn't work #11

schlaegerz opened this issue Apr 14, 2020 · 10 comments

Comments

@schlaegerz
Copy link

I have this to setup my security

 NimBLEDevice::setSecurityIOCap(BLE_HS_IO_DISPLAY_YESNO ); // set display output capability 
    NimBLEDevice::setSecurityAuth(true, true, true); // bonding, man in the middle protection, secure connection
 _service->createCharacteristic(FINGERPRINT_UUID, NIMBLE_PROPERTY::READ |
                                                            NIMBLE_PROPERTY::WRITE | 
                                                            NIMBLE_PROPERTY::WRITE_ENC);

And I am just wondering if I have the correct understanding of bonding. My thought was after my phone pairs with this it won't have to confirm the connection ever again, but every time I try to right that characteristic after I reboot the chip I get the pop up on my android device confirming that I want to connect.

Is it possible to just have it remain connected using the BLE_HS_IO_DISPLAY_YESNO or am I just confused about what should be happening.

@chegewara
Copy link

BLE_HS_IO_DISPLAY_YESNO is display + 2 buttons (YES and NO) to confirm pin.

Can you try nRF connect on android device? There is logging in app (debug log level) that may be useful, also it will show if device is bonded or not.

@h2zero
Copy link
Owner

h2zero commented Apr 14, 2020

I just tested with your code snippet in the NimBLE_Server example using nRF connect from my phone and it bonded as expected. However when I turned my phone off and on and rebooted the esp32 I can see an error:

rxed att command: read req; conn=0 handle=0x000c
looking up peer sec; peer_addr_type=1 peer_addr=0x36 0xee 0xd9 0x72 0x50 0x4a  
txed att command: error rsp; conn=0 req_op=10 handle=0x000c error_code=5

0x05 | BLE_ATT_ERR_INSUFFICIENT_AUTHEN | The attribute requires authentication before it can be read or written.

It seems NimBLE is storing the random public address from phones and using that as the store key instead of the IRK. This is something I need to bring up with the NimBLE team or set callback functions for the storage handling and implement it in the library.

No quick fix it seems sadly 😦.

@schlaegerz
Copy link
Author

Thanks for looking into it!

Not something that is essential for my project, but would be very nice.

@chegewara
Copy link

@h2zero This suppose to be handled by low level driver. I think it can be posted on esp-idf issue tracker.

@h2zero
Copy link
Owner

h2zero commented Apr 14, 2020

@chegewara I don't think this is a case for the esp-idf specifically as the callbacks I and idf are using are built-in NimBLE functions meant for demonstration use, so they may be incomplete. I'll see what more I can find.

@h2zero
Copy link
Owner

h2zero commented Apr 15, 2020

Quick update on this issue, there is some additional parameters that need to be set in the library for bonding with phones to work.

/**
 * @brief Set the keys we are willing to accept during pairing.
 * @param A bitmap indicating which keys to accept during pairing.
 * The bits are defined as follows:           
 ** 0x01: BLE_SM_PAIR_KEY_DIST_ENC  -  Accept the encryption key.
 ** 0x02: BLE_SM_PAIR_KEY_DIST_ID   -  Accept the ID key (IRK).
 ** 0x04: BLE_SM_PAIR_KEY_DIST_SIGN
 ** 0x08: BLE_SM_PAIR_KEY_DIST_LINK
 */
/*STATIC*/void NimBLEDevice::setSecurityRespKey(uint8_t init_key) {
    ble_hs_cfg.sm_their_key_dist = init_key;
} // setsSecurityRespKey

In your code (for now) you should add:
NimBLEDevice::setSecurityRespKey(BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID);

In the future I will make this the default setting, however it still does not recognize the client when reconnecting. I have tested this with IDF as well and it doesn't seem to work there either. So far I've narrowed it down to here, at this point it does not find the client key for some reason, either an error when created or searching.

If anyone is eager to deep dive into the NimBLE stack I'm open to PR's lol.

@chegewara
Copy link

Today i had to implement BLE code with old library and bonding connection. I found something that may be applicable here too. I had to add this line of code:

	pSecurity->setAuthenticationMode(ESP_LE_AUTH_REQ_SC_MITM_BOND);

@h2zero
Copy link
Owner

h2zero commented Apr 15, 2020

Thanks @chegewara, NimBLE does things a bit differently by just setting global variable flags for that function. Which is the purpose of the NimBLEDevice::setSecurityAuth(true, true, true); code above.

Good news is though I have found the error, it happens due to the host based privacy code that espressif implemented and requires calling ble_hs_pvcy_rpa_config(true); in the initialization.

This is only a partial fix though as with an iPad or iPhone I get an insufficient encryption error, Android seems to work with it but some versions may not.

I have instead modified the espressif code to work, needs more testing but if it works well I'll make a PR for IDF as well.

@h2zero
Copy link
Owner

h2zero commented Apr 16, 2020

Just pushed a fix for this, give it a try if you get a chance.
Also you don't need to add NimBLEDevice::setSecurityRespKey(BLE_SM_PAIR_KEY_DIST_ENC | BLE_SM_PAIR_KEY_DIST_ID); anymore, it's now the default setting.

@h2zero
Copy link
Owner

h2zero commented May 20, 2020

Closing this for now as it has been resolved in commit fd8b72b.

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

No branches or pull requests

3 participants