mirror of
https://github.com/tinygo-org/tinygo.git
synced 2026-08-10 05:53:39 +00:00
d3863f337d
The crypto/rand package is used for sensitive cryptographic operations. Do not use the rp2040 RNG for this purpose, because it's not strong enough for cryptography. I think it is _possible_ to make use of the RP2040 RNG to create cryptographically secure pseudo-random numbers, but it needs some entropy calculation and secure hashing (blake2s or so) to make them truly unpredictable.
43 lines
969 B
Go
43 lines
969 B
Go
//go:build rp2040
|
|
// +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
|
|
}
|