github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/machine/machine_rp2040_rng.go (about)

     1  //go:build rp2040
     2  
     3  // Implementation based on code located here:
     4  // https://github.com/raspberrypi/pico-sdk/blob/master/src/rp2_common/pico_lwip/random.c
     5  
     6  package machine
     7  
     8  import (
     9  	"device/rp"
    10  )
    11  
    12  const numberOfCycles = 32
    13  
    14  // GetRNG returns 32 bits of semi-random data based on ring oscillator.
    15  //
    16  // Unlike some other implementations of GetRNG, these random numbers are not
    17  // cryptographically secure and must not be used for cryptographic operations
    18  // (nonces, etc).
    19  func GetRNG() (uint32, error) {
    20  	var val uint32
    21  	for i := 0; i < 4; i++ {
    22  		val = (val << 8) | uint32(roscRandByte())
    23  	}
    24  	return val, nil
    25  }
    26  
    27  var randomByte uint8
    28  
    29  func roscRandByte() uint8 {
    30  	var poly uint8
    31  	for i := 0; i < numberOfCycles; i++ {
    32  		if randomByte&0x80 != 0 {
    33  			poly = 0x35
    34  		} else {
    35  			poly = 0
    36  		}
    37  		randomByte = ((randomByte << 1) | uint8(rp.ROSC.GetRANDOMBIT()) ^ poly)
    38  		// TODO: delay a little because the random bit is a little slow
    39  	}
    40  	return randomByte
    41  }