aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/machine/machine_rp2040_rng.go
blob: 1706785d0fa160e5f7eff47c35fa0148b3560d67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
//go: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.
//
// Unlike some other implementations of GetRNG, these random numbers are not
// cryptographically secure and must not be used for cryptographic operations
// (nonces, etc).
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
}