mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-06 03:53:42 +00:00
194438cdd6
Signed-off-by: deadprogram <ron@hybridgroup.com>
60 lines
1.7 KiB
Go
60 lines
1.7 KiB
Go
//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
|
|
}
|