diff options
-rw-r--r-- | src/crypto/rand/rand_baremetal.go | 4 | ||||
-rw-r--r-- | src/machine/machine_nrf52840_rng.go | 60 |
2 files changed, 62 insertions, 2 deletions
diff --git a/src/crypto/rand/rand_baremetal.go b/src/crypto/rand/rand_baremetal.go index c7a205222..6f3370e96 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) || rp2040 -// +build stm32 sam,atsamd51 sam,atsame5x rp2040 +//go:build nrf52840 || stm32 || (sam && atsamd51) || (sam && atsame5x) || rp2040 +// +build nrf52840 stm32 sam,atsamd51 sam,atsame5x rp2040 package rand diff --git a/src/machine/machine_nrf52840_rng.go b/src/machine/machine_nrf52840_rng.go new file mode 100644 index 000000000..1d4eba040 --- /dev/null +++ b/src/machine/machine_nrf52840_rng.go @@ -0,0 +1,60 @@ +//go:build nrf52840 +// +build nrf52840 + +package machine + +import ( + "device/nrf" +) + +// Implementation based on Nordic Semiconductor's nRF52840 documentation version 1.7 found here: +// https://infocenter.nordicsemi.com/pdf/nRF52840_PS_v1.7.pdf + +// SetRNGBiasCorrection configures the RNG peripheral's bias correction mechanism. Note that when +// bias correction is enabled, the peripheral is slower to produce random values. +func SetRNGBiasCorrection(enabled bool) { + var val uint32 + if enabled { + val = nrf.RNG_CONFIG_DERCEN_Enabled + } + nrf.RNG.SetCONFIG_DERCEN(val) +} + +// RNGBiasCorrectionEnabled determines whether the RNG peripheral's bias correction mechanism is +// enabled or not. +func RNGBiasCorrectionEnabled() bool { + return nrf.RNG.GetCONFIG_DERCEN() == nrf.RNG_CONFIG_DERCEN_Enabled +} + +// StartRNG starts the RNG peripheral core. This is automatically called by GetRNG, but can be +// manually called for interacting with the RNG peripheral directly. +func StartRNG() { + nrf.RNG.SetTASKS_START(nrf.RNG_TASKS_START_TASKS_START_Trigger) +} + +// StopRNG stops the RNG peripheral core. This is not called automatically. It may make sense to +// manually disable RNG peripheral for power conservation. +func StopRNG() { + nrf.RNG.SetTASKS_STOP(nrf.RNG_TASKS_STOP_TASKS_STOP_Trigger) +} + +// GetRNG returns 32 bits of non-deterministic random data based on internal thermal noise. +// According to Nordic's documentation, the random output is suitable for cryptographic purposes. +func GetRNG() (ret uint32, err error) { + // There's no apparent way to check the status of the RNG peripheral's task, so simply start it + // to avoid deadlocking while waiting for output. + StartRNG() + + // The RNG returns one byte at a time, so stack up four bytes into a single uint32 for return. + for i := 0; i < 4; i++ { + // Wait for data to be ready. + for nrf.RNG.GetEVENTS_VALRDY() == nrf.RNG_EVENTS_VALRDY_EVENTS_VALRDY_NotGenerated { + } + // Append random byte to output. + ret = (ret << 8) ^ nrf.RNG.GetVALUE() + // Unset the EVENTS_VALRDY register to avoid reading the same random output twice. + nrf.RNG.SetEVENTS_VALRDY(nrf.RNG_EVENTS_VALRDY_EVENTS_VALRDY_NotGenerated) + } + + return ret, nil +} |