diff options
-rw-r--r-- | src/crypto/rand/rand_baremetal.go | 4 | ||||
-rw-r--r-- | src/machine/machine_rp2040_rng.go | 38 |
2 files changed, 40 insertions, 2 deletions
diff --git a/src/crypto/rand/rand_baremetal.go b/src/crypto/rand/rand_baremetal.go index a0ebaf65a..c7a205222 100644 --- a/src/crypto/rand/rand_baremetal.go +++ b/src/crypto/rand/rand_baremetal.go @@ -1,5 +1,5 @@ -//go:build stm32 || (sam && atsamd51) || (sam && atsame5x) -// +build stm32 sam,atsamd51 sam,atsame5x +//go:build stm32 || (sam && atsamd51) || (sam && atsame5x) || rp2040 +// +build stm32 sam,atsamd51 sam,atsame5x rp2040 package rand diff --git a/src/machine/machine_rp2040_rng.go b/src/machine/machine_rp2040_rng.go new file mode 100644 index 000000000..246dadfa8 --- /dev/null +++ b/src/machine/machine_rp2040_rng.go @@ -0,0 +1,38 @@ +//go:build rp2040 +// +build rp2040 + +// Implementation based on code located here: +// https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/pico_lwip/random.c + +package machine + +import ( + "device/rp" +) + +const numberOfCycles = 32 + +// GetRNG returns 32 bits of semi-random data based on ring oscillator. +func GetRNG() (uint32, error) { + var val uint32 + for i := 0; i < 4; i++ { + val = (val << 8) | uint32(roscRandByte()) + } + return val, nil +} + +var randomByte uint8 + +func roscRandByte() uint8 { + var poly uint8 + for i := 0; i < numberOfCycles; i++ { + if randomByte&0x80 != 0 { + poly = 0x35 + } else { + poly = 0 + } + randomByte = ((randomByte << 1) | uint8(rp.ROSC.GetRANDOMBIT()) ^ poly) + // TODO: delay a little because the random bit is a little slow + } + return randomByte +} |