1
2
3
4
5 package sysrand
6
7 import (
8 "internal/byteorder"
9 "internal/chacha8rand"
10 "io"
11 "os"
12 "sync"
13 )
14
15 const randomDevice = "/dev/random"
16
17
18
19
20
21 var (
22 mu sync.Mutex
23 seeded sync.Once
24 seedErr error
25 state chacha8rand.State
26 )
27
28 func read(b []byte) error {
29 seeded.Do(func() {
30 entropy, err := os.Open(randomDevice)
31 if err != nil {
32 seedErr = err
33 return
34 }
35 defer entropy.Close()
36 var seed [32]byte
37 _, err = io.ReadFull(entropy, seed[:])
38 if err != nil {
39 seedErr = err
40 return
41 }
42 state.Init(seed)
43 })
44 if seedErr != nil {
45 return seedErr
46 }
47
48 mu.Lock()
49 defer mu.Unlock()
50
51 for len(b) >= 8 {
52 if x, ok := state.Next(); ok {
53 byteorder.BEPutUint64(b, x)
54 b = b[8:]
55 } else {
56 state.Refill()
57 }
58 }
59 for len(b) > 0 {
60 if x, ok := state.Next(); ok {
61 var buf [8]byte
62 byteorder.BEPutUint64(buf[:], x)
63 n := copy(b, buf[:])
64 b = b[n:]
65 } else {
66 state.Refill()
67 }
68 }
69 state.Reseed()
70
71 return nil
72 }
73
View as plain text