mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-05 03:27:48 +00:00
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:
@@ -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 {
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user