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

WIP: Security manager take 2 #286

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

blueluna
Copy link

@blueluna blueluna commented Feb 16, 2025

Security manager

Work in progress Bluetooth LE security manager for trouble-host.
Builds on the works of @HaoboGu and https://github.com/bjoernQ/bleps.

Starting this draft PR for working out integration into TrouBLE. Following details some of the current design choices

Current Implementation

Bluetooth LE Security Connection (LESC) with Just Works.

Inner cryptographic random generator

Chacha12 is used to provide a cryptographic random generator in the security manager. Seeded from the user.

HCI Event and Command handling

HCI event and command handling is done through a embassy_sync Channel.

Known limitations

Pairing Methods

Only LESC with Just Works/Numerical comparison is implemented. No support for BLE Legacy, LESC keypass entry or LESC out-of-band.

No privacy or signing support

Support for identity resolving keys (IRK) and Connection Signature Resolving Key (CSRK) has not been implemented.

Testing done

Tested ble_bas_peripheral_sec against nRF Connect on Android and iPad.
Tested ble_bas_central_sec against ble_bas_peripheral_sec.

Following hardware was used,

  • nRF52833 (micro:bit V2)
  • ESP32-C3 (ESP32-C3-DevKitM-1)
  • ESP32-C6 (ESP32-C6-DevKitM-1)
  • Serial-HCI using nrf52840-dongle

@blueluna blueluna changed the title Security manager WIP: Security manager take 2 Feb 16, 2025
Copy link
Member

@lulf lulf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot for your work on this! I made a first pass through it, and noted the following:

  • I'm wondering if it's more appropriate if security_manager is part of the connection_manager, rather than adding methods on connection_manager to convert between index and handle. It's a bad to hand out indexes to anything other than Connection instances, especially if it's used across await points, because then you may use an index to a connection that has been drop'ed, and even if it's safe now (I haven't really traced the code paths for that), it might lead to accidental bugs later.

  • From what I understand, the security manager packets work on top of l2cap, and could use the tx packet pool (https://github.com/embassy-rs/trouble/blob/main/host/src/host.rs#L70). Would it make sense to use that instead rather than having it's own?

  • For the examples you've added, are they tested and verified to work on real hardware?

Other than the above, I think it pretty much aligns nicely with the existing api and architecture.

@blueluna
Copy link
Author

Thanks for reviewing,

  1. Seems appropriate, I will try it out.
  2. Yes, it communicates upon l2cap. I will try to use that packet pool.
  3. I have tested on nrf52833 (microbit v2), esp32c6 (SparkFun Qwiic Pocket Development Board, ESP32-C6).

@alexmoon
Copy link

Would it be possible for the host to take an arbitrary CryptoRng impl? Some micros have hardware rngs that may be more efficient and/or more random. I don't know what the qualification criteria are for the random numbers used for secure pairing.

@blueluna
Copy link
Author

It probably would be possible, I did not find any good solution tough. When I started out I tried to sprinkle <RNG: RngCore + CryptoRng> all over the crate. My trait skills might not be good enough.

@lulf
Copy link
Member

lulf commented Feb 20, 2025

I personally think it's fine to not use the CryptoRng traits, it's has an unfortunate effect of creeping into the entire code base and making it a lot harder to make modifications. I learned this the hard way in lora-rs, and my preferred tradeoff from that experience would be to maybe use the CryptoRng trait when creating the stack only, as a way to produce a good seed for the 'internal' rng. Another point is that the hardware rngs are not always that fast, at least the nRF rng is pretty slow (if i remember correctly). And finally, if I understand correctly, it's only used in the pairing process, so it's not something on the critical path once pairing is done?

So at least in the first pass, I'm fine with not using the rng traits.

@blueluna
Copy link
Author

Providing a CryptoRng to generate a seed is a good idea. I will try that out.
Once the pairing is done the long term key is supplied to the HCI Controller which does the encryption and decryption of packages without any involvement from the security manager.

I tried to check if ChaCha12 is good enough as per the Bluetooth standard (Vol 2, Part H, Chapter 2). It needs to pass a test suite, and it seems like ChaCha12 passes the test suite dieharder. Might need some more investigation tough.

@alexmoon
Copy link

Yes, I agree that adding generic spam to everything is not worth it. It would only be useful if the generic "blast radius" could be contained to the security manager or related functions. Using CryptoRng to generate a seed is a good idea.

@blueluna blueluna force-pushed the security_manager_chacha branch from a2679a3 to a0f0d9d Compare February 22, 2025 08:18
@blueluna
Copy link
Author

blueluna commented Feb 22, 2025

Notes from using a CryptoRng to seed ChaCha12.

Serial-HCI, tests, ...

I provided rand::rngs::OsRng to Stack builder.

nRF-SDC

the nRF-SDC takes the random generator, which means I couldn't put it into the Stack builder. I seeded a ChaCha12 from the nRF random generator which I provided to the Stack builder.

Maybe there is a way to initiate in another order to be able to use the nRF random generator.

ESP32

I created a Trng which implemente CryptoRng. I could provide a cloned random generator to the Wi-Fi/Bluetooth driver and put the Trng in the Stackbuilder.

Raspberry Pi Pico W

Not very familiar with the RPI-pico's. I found a ring oscillator random bit generator, which doesn't seem to have cryptographic properties. I seeded a ChaCha12 from RoscRng which I provided to the Stack builder.
No testing done. I found a RP2040 W in my drawers, but I have yet to wired it up.

@blueluna blueluna force-pushed the security_manager_chacha branch from a0f0d9d to 12ae4d9 Compare February 22, 2025 08:51
Copy link
Member

@lulf lulf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is starting to look really good. I have one wish though, and that is the API for passing the rng seed. Rather than passing it to new(), I think it would be nicer expose a set_random_seed() or 'enable_rng()' on the Stack type (and propagate to BleHost internally), similar to the set_random_address(). This way it doesn't get in the way if you don't use the security manager.

If it's hard to do since it happens after creating the security manager, we should consider a StackBuilder or something that has that method.

@blueluna
Copy link
Author

This is how the random seed was configured earlier, I believe it will work. One nit is that the user might forget to add a seed and end up with a not so secure random generator, but this can be improved upon at a later date. I will try to implement the change.

I was able to wire up a Raspberry Pi W, the ble_bas_peripheral example works but when trying to run ble_bas_peripheral_sec, the Raspberry pi pico seems to fail to generate a DH Key. Needs investigating.

I also want to look into how to implement the pairing timeout, currently investigating if embassy_time::Ticker can be used.

@lure23
Copy link
Contributor

lure23 commented Feb 26, 2025

, I believe it will work. One nit is that the user might forget to add a seed and end up with a not so secure random generator [...]

What I'd like to see, as a developer, is a build warning if I'm building without proper seeds. Like esp-hal warns if debug mode is used (because it might be too slow that way); yet it allows me to do it.

In practise, it could be done like this:

  • if no features, and no seed given, panic when building the actual Stack (with a suitable error message).
  • use dev_no_rng or similar feature to override the behaviour. The feature should be named so that it's obvious it's about quick prototypes or the like.

An alternate way could be having different APIs based on the features. Some library had this, but I personally find it weird. It's confusing for documentation and what not. I'd recommend always sticking to one API per released version.

Just my 2c.

@blueluna blueluna force-pushed the security_manager_chacha branch 2 times, most recently from bff1355 to eee3170 Compare March 3, 2025 14:31
Use ChaCha12 in security manager.
Tested on ESP32-C6, nrf52833 and Serial HCI.
@blueluna blueluna force-pushed the security_manager_chacha branch from 5cd98e1 to bf8888d Compare March 6, 2025 22:43
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

Successfully merging this pull request may close these issues.

4 participants