Description
On RP2040/RP2350, TinyGo always initializes the global math/rand RNG with a fixed seed.
This differs from Big Go, where since Go 1.20 the global RNG is seeded with randomness at startup.
Cause
The global math/rand RNG first tries to obtain randomness via n, ok := hardwareRand().
If hardwareRand() returns ok == true, the returned value n is used directly as the random source.
Otherwise, fastrand64() is used instead. (src/runtime/algorithm.go)
On RP2040/RP2350, however, hardwareRand() always returns 0, false. (src/runtime/rand_norng.go)
As a result, math/rand always falls back to fastrand64().
Since fastrand64() starts from a fixed initial state in this case,
the global RNG produces the same sequence on every run.
Proposed fix
RP2040/RP2350 provide a ROSC-based RNG via machine.GetRNG().
To avoid performance concerns, this RNG could be used only to provide initial entropy for fastrand64(),
rather than being used as the primary random source.
Notes
- The ROSC-based RNG is not cryptographically secure and should not be used for
crypto/rand.
- RP2350 includes a hardware TRNG, but using it is out of scope for this issue.
- RP2040 does not have a hardware TRNG; it may be worth discussing whether
machine.GetRNG() should be used as the source for crypto/rand on this target.
Description
On RP2040/RP2350, TinyGo always initializes the global
math/randRNG with a fixed seed.This differs from Big Go, where since Go 1.20 the global RNG is seeded with randomness at startup.
Cause
The global
math/randRNG first tries to obtain randomness vian, ok := hardwareRand().If
hardwareRand()returnsok == true, the returned valuenis used directly as the random source.Otherwise,
fastrand64()is used instead. (src/runtime/algorithm.go)On RP2040/RP2350, however,
hardwareRand()always returns0, false. (src/runtime/rand_norng.go)As a result,
math/randalways falls back tofastrand64().Since
fastrand64()starts from a fixed initial state in this case,the global RNG produces the same sequence on every run.
Proposed fix
RP2040/RP2350 provide a ROSC-based RNG via
machine.GetRNG().To avoid performance concerns, this RNG could be used only to provide initial entropy for
fastrand64(),rather than being used as the primary random source.
Notes
crypto/rand.machine.GetRNG()should be used as the source forcrypto/randon this target.