github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/src/crypto/rand/rand_windows.go (about)

     1  package rand
     2  
     3  import "errors"
     4  
     5  func init() {
     6  	Reader = &reader{}
     7  }
     8  
     9  type reader struct {
    10  }
    11  
    12  var errRandom = errors.New("failed to obtain random data from rand_s")
    13  
    14  func (r *reader) Read(b []byte) (n int, err error) {
    15  	if len(b) == 0 {
    16  		return
    17  	}
    18  
    19  	var randomByte uint32
    20  	for i := range b {
    21  		// Call rand_s every four bytes because it's a C int (always 32-bit in
    22  		// Windows).
    23  		if i%4 == 0 {
    24  			errCode := libc_rand_s(&randomByte)
    25  			if errCode != 0 {
    26  				// According to the documentation, it can return an error.
    27  				return n, errRandom
    28  			}
    29  		} else {
    30  			randomByte >>= 8
    31  		}
    32  		b[i] = byte(randomByte)
    33  	}
    34  
    35  	return len(b), nil
    36  }
    37  
    38  // Cryptographically secure random number generator.
    39  // https://docs.microsoft.com/en-us/cpp/c-runtime-library/reference/rand-s?view=msvc-170
    40  // errno_t rand_s(unsigned int* randomValue);
    41  //
    42  //export rand_s
    43  func libc_rand_s(randomValue *uint32) int32