fix: correctly handle calls for GetRNG() when being made from nrf devices with SoftDevice enabled.

Signed-off-by: deadprogram <ron@hybridgroup.com>
This commit is contained in:
deadprogram
2025-01-12 13:56:46 +01:00
committed by Ron Evans
parent 217f677bbe
commit 194438cdd6
3 changed files with 70 additions and 2 deletions
+2 -2
View File
@@ -318,9 +318,9 @@ func (i2c *I2C) signalStop() error {
var rngStarted = false
// GetRNG returns 32 bits of non-deterministic random data based on internal thermal noise.
// 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) {
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.
if !rngStarted {
+9
View File
@@ -0,0 +1,9 @@
//go:build nrf && !softdevice
package machine
// 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) {
return getRNG()
}
+59
View File
@@ -0,0 +1,59 @@
//go:build nrf && softdevice
package machine
import (
"device/arm"
"device/nrf"
"errors"
)
// avoid a heap allocation in GetRNG.
var (
softdeviceEnabled uint8
bytesAvailable uint8
buf [4]uint8
errNoSoftDeviceSupport = errors.New("rng: softdevice not supported on this device")
errNotEnoughRandomData = errors.New("rng: not enough random data available")
)
// 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) {
// First check whether the SoftDevice is enabled.
// sd_rand_application_bytes_available_get cannot be called when the SoftDevice is not enabled.
arm.SVCall1(0x12, &softdeviceEnabled) // sd_softdevice_is_enabled
if softdeviceEnabled == 0 {
return getRNG()
}
// call into the SoftDevice to get random data bytes available
switch nrf.Device {
case "nrf51":
// sd_rand_application_bytes_available_get: SOC_SVC_BASE_NOT_AVAILABLE + 4
arm.SVCall1(0x2B+4, &bytesAvailable)
case "nrf52", "nrf52840", "nrf52833":
// sd_rand_application_bytes_available_get: SOC_SVC_BASE_NOT_AVAILABLE + 4
arm.SVCall1(0x2C+4, &bytesAvailable)
default:
return 0, errNoSoftDeviceSupport
}
if bytesAvailable < 4 {
return 0, errNotEnoughRandomData
}
switch nrf.Device {
case "nrf51":
// sd_rand_application_vector_get: SOC_SVC_BASE_NOT_AVAILABLE + 5
arm.SVCall2(0x2B+5, &buf, 4)
case "nrf52", "nrf52840", "nrf52833":
// sd_rand_application_vector_get: SOC_SVC_BASE_NOT_AVAILABLE + 5
arm.SVCall2(0x2C+5, &buf, 4)
}
return uint32(buf[0]) | uint32(buf[1])<<8 | uint32(buf[2])<<16 | uint32(buf[3])<<24, nil
}