Skip to content

Example applications without rand dependency#521

Open
finalyards wants to merge 1 commit intoembassy-rs:mainfrom
finalyards:pr-app-no-rand
Open

Example applications without rand dependency#521
finalyards wants to merge 1 commit intoembassy-rs:mainfrom
finalyards:pr-app-no-rand

Conversation

@finalyards
Copy link
Contributor

@finalyards finalyards commented Jan 9, 2026

Please consider this PR mostly as a cleanup / reorganization suggestion.

What it does

It removes the rand and rand_core dependencies fully from the examples/ side of the repo. The code used to create various random number generators that where then used - only - for seeding the actual RNG within trouble-host. This one-time effort feels clutter to the author of the PR - more importantly it created complexity in maintaining the #474 PR, which aims at bringing in rand 0.10 once it is released.

What's the beef?

We do want actual, hardware provided and platform specific, true random values, to get things going. Unfortunately, within the embedded Rust domain there is no standard for providing such (hardware dependent) values. I believe after the PR, the code reflects this better. There is no need to carry CryptoRng etc. traits around - with regard to nrf52 the old code actually used an initial RNG to generate a ChaCha18 (which is "crypto" grade), though that one was only used once, to seed in turn the real RNG within the library. I fail to see the point of that - it's likely just an accumulation of design choices and adhering to the compiler's requirements (it wants a CryptoRng; how can I provide one?). This is the kind of things the new "just give a seed" approach imho helps steer clear of.

Does it really simplify things?

It drops dependencies (rand, rand_core). It feels like it reduces the line count, but actually it's slightly longer:

31 files changed, 178 insertions(+), 119 deletions(-)

This is because of repetitive sections that create the seeds. [Edit: I can take those common things into a src/lib.rs but this breaks the nice approach that everything for an application is in a single file.] My gut feel is that the overall system becomes easier to reason about - and to maintain - due to randomness being locked fully within trouble-host, as an implementation detail.

Is there more?

Not really. The PR contains 2..3 places of unrelated (but useful) changes; I'm happy if I may bring them in at once.

If this gets approved, it makes the work on the real rand-update PR way easier...

@HaoboGu
Copy link
Collaborator

HaoboGu commented Jan 14, 2026

/test

@finalyards
Copy link
Contributor Author

finalyards commented Jan 20, 2026

I'd like to hear some feedback on this PR. Is it looking okay?

The real thing is what it says on the title: whether TrouBLE apps (with security) are expected to depend on rand|rand_core or whether that becomes an implementation detail of the library. I obviously am in favour of the latter. It just simplifies things.

Some news from elsewhere:

  • In discussions with esp-hal, it is explicit that they'd welcome a getrandom PR to their HAL.

    This is great. Ultimately, TrouBLE could use getrandom for also the embedded targets (as the PR now uses for desktop Linux). But there's no reason to wait for that. Such changes can be made, as further simplifications, in separate PRs, on a platform by platform basis.

I wonder...

image

...shouldn't those two tests be passing? Can I do anything about it?

Is there any reason not to merge this PR?

@HaoboGu
Copy link
Collaborator

HaoboGu commented Jan 21, 2026

My 2c: I like the idea of removing Rng generics and rand/rand_core in user's Cargo.toml, but the TrulyRandomBits looks confusing at the first glance. In the previous implementation, users need only to pass a rng generator and trouble-host does the others. But in this PR, users are responsible to generate the random seed. I don't know which one is better

@finalyards
Copy link
Contributor Author

finalyards commented Jan 21, 2026

My 2c: I like the idea of removing Rng generics and rand/rand_core in user's Cargo.toml, but the TrulyRandomBits looks confusing at the first glance. [...]

Thanks for the comment.

Yes, TrulyRandomBits is not my favourite, either. Most importantly, I don't like introducing a new "new-type" to the host library API, itself. And we don't really need to, either. We can:

  • keep the existing prototype:

        pub(crate) fn set_random_generator_seed(&self, random_seed: [u8; 32]) {
    

Note how it takes 256 bits. I tried to be clever about that, but it's also completely fine to keep the current API.

  • have TrulyRandomBits in the examples/apps side. This makes it less official, and kind of clearer that it's about your code, as applications. Not the library.

In some future, I would like to advance to using getrandom. This would then become a matter of changes solely in the examples/, and possibly eliminating the TrulyRandomBits as unnecessary.

Why I don't wish to directly go all-in with getrandom is that I anticipate some platforms might have a problem, implementing it. As the esp-hal case shows, a HAL either can provide such, or at least prepare their own random number generator so that implementation is possible.

Would the PR be more acceptible to you if TrulyRandomBits stays, but is moved out from the host API? Or is it something else about it?

@HaoboGu
Copy link
Collaborator

HaoboGu commented Jan 21, 2026

I just worry about the increased boilerplate code in user space:

-    let _trng_source = TrngSource::new(peripherals.RNG, peripherals.ADC1);
-    let mut trng = Trng::try_new().unwrap();    // Ok when there's a TrngSource accessible
+    let seed: TrulyRandomBits = {
+        let mut buf: [u8; 32];
+        let _ = TrngSource::new(peripherals.RNG, peripherals.ADC1);
+        Trng::try_new().unwrap().read(&mut buf);
+        TrulyRandomBits(buf)
+    };

What about just using the raw [u8; 32]? I'm not sure tho. Maybe lulf have better ideas.

@finalyards

This comment was marked as outdated.

@finalyards
Copy link
Contributor Author

Changed the underlying implementation to use getrandom instead of the application needing to provide a seed.

$ git diff --shortstat main...HEAD -- . ':!*.lock'
 39 files changed, 191 insertions(+), 147 deletions(-)

The host library itself uses ’getrandom’ for getting the seed for its encryption. This means simplification in the examples / apps side:

  • platforms with a ”getrandom” implementation simply omit anything about seeds in their code - host does it automatically
  • esp32 and nrf52 provide ”custom backend”, tying their TRNG’s to ”getrandom”. The ESP32 implementation is generic; the nrf52 one is a hack, but suitable for this context.
  • no .set_random_generator_seed method for apps to call

The point of the PR was to remove ’rand’ and ’rand_core’ dependencies from the examples/apps side, so that making the rand 0.6 -> 0.10 change (separate PR) becomes easier. I feel it also simplifies the application usage.

NOTE: Would someone please run ’_sec’ examples on nRF52. I have access to ESP32-C3, -C6 and nRF54 but not to that board - and nRF54 examples don’t contain ’_sec’ examples. This would check that the getrandom hack works.

$ cd examples/nrf52
$ cargo run --release --features nrf52833 --target thumbv7em-none-eabihf --bin ble_bas_peripheral_sec --features security

Asks:

dev-disable-csprng-seed-requirement

# For development. Disable security manager cryptographically secure pseudorandom number
# generator (CSPRNG) to require a cryptographically secure seed
dev-disable-csprng-seed-requirement = []

What is the use case of this dev-disable-csprng-seed-requirement feature? I kept it in place, but do the changes disturb it?

@finalyards

This comment was marked as resolved.

finalyards added a commit to finalyards/trouble.fork that referenced this pull request Feb 6, 2026
finalyards added a commit to finalyards/trouble.fork that referenced this pull request Feb 9, 2026
@finalyards
Copy link
Contributor Author

I've rebased the PR on latest origin/main, including the tester folder.

Since keeping up to date with an evolving main is a chore, I would like to hear your opinions on the getrandom approach. I personally am in favour of it, but it does come with some drawbacks. While it simplifies example creation (and can be simplified more, by moving getrandom implementations out of this repo), it does clash with current use of cargo batch in the ci.sh script.

I have edited the CI script accordingly. For open questions, please see todo in the PR - and the comments above, since 3 weeks ago. Thanks for guidance.

@lulf
Copy link
Member

lulf commented Mar 2, 2026

I'm sorry, but removing rand/rand_core in favor of this getrandom gets a thumbs down from me:

  • The CryptoRng trait from rand adds some constraints that you get cryptographically secure generators
  • Adding the getrandom.in feels very custom and non-ideomatic rust
  • I don't understand the initial motivation arguing that it's clutter.

@finalyards
Copy link
Contributor Author

finalyards commented Mar 2, 2026

I'm sorry, but removing rand/rand_core in favor of this getrandom gets a thumbs down from me:

  • The CryptoRng trait from rand adds some constraints that you get cryptographically secure generators
  • Adding the getrandom.in feels very custom and non-ideomatic rust
  • I don't understand the initial motivation arguing that it's clutter.

I'll go through these, one at a time:

1. getrandom provides cryptographically secure random values

They do:

It is assumed that the system always provides high-quality, cryptographically secure random data, ideally backed by hardware entropy sources.

This cannot, however, be enforced with a type, less they derive from rand_core - which there is some discussion that may be the case, for the next version.

For custom backends, this is obviously in the hands of the coder. I have used the same MCU specific, hardware-backed generators as current main does.

2. Using include!

Yeah. That's just one way to implement the custom backends - it's not a requirement by the getrandom use.

More conventional approaches are:

  • src/lib.rs that the necessary bins get. I played with this, don't remember exactly why I ended up using the include.

  • separate tool library, within the repo, e.g. getrandom-nrf52, getrandom-esp32

    If esp-hal starts supporting getrandom at some point, the custom code gets removed and one simply adds (e.g.) getrandom feature to the esp-hal dependency. There's currently no such work happening, but ESP32 are favourable of it and have prepared their TRNG with this in mind.

The reason I used include was likely just the wish to keep the examples as self-contained as possible. Perhaps I failed, there.

my arguing for "clutter"

  • I don't understand the initial motivation arguing that it's clutter.

Good point. I don't argue the dependencies as such are. My point was that passing the Rng + CryptoRng down the call chains was / felt like.

And this is perhaps the main point of the PR. If seeing the RNG being passed is genuinely providing value, then it deserves the attention. Now, however, the host library uses the provided generator one time, to pull 256 bits of entropy. That, in my opinion, can be an implementation detail, and "out of sight".

One more thing. I was new to this rand, rand_core - and getrandom - ecosystem, when somewhat bravely trying to make a small PR to update rand use to latest (0.8 at that time, I believe). Doing this has taught me loads, and I appreciate the division of concerns to the three repos (rand, rand_core, getrandom).

It's not obvious from "the tin", what their purposes are, though. What I want to emphasise is that they are all mainstream libraries in the Rust ecosystem - getrandom included. Bringing it in - for TrouBLE - would not mean adding some exotic third-party, rarely maintained repo, but an actively standing pillar of ... randomness ... in the Rust ecosystem.

Thanks for reading.

Let me know how to proceed.

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.

3 participants